summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--KEYS55
-rw-r--r--LICENSE2
-rw-r--r--NOTICE2
-rw-r--r--QPID_VERSION.txt2
-rw-r--r--README.txt14
-rwxr-xr-xbin/release.sh36
-rw-r--r--cpp/CMakeLists.txt1
-rw-r--r--cpp/INSTALL20
-rw-r--r--cpp/INSTALL-WINDOWS11
-rw-r--r--cpp/Makefile.am4
-rw-r--r--cpp/bindings/qmf/python/Makefile.am4
-rw-r--r--cpp/bindings/qmf/ruby/Makefile.am4
-rw-r--r--cpp/bindings/qmf/tests/test_base.rb3
-rw-r--r--cpp/bindings/qmf2/examples/cpp/Makefile.am5
-rw-r--r--cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp107
-rw-r--r--cpp/bindings/qmf2/python/Makefile.am4
-rw-r--r--cpp/bindings/qmf2/qmf2.i1
-rw-r--r--cpp/bindings/qmf2/ruby/Makefile.am4
-rw-r--r--cpp/bindings/qpid/CMakeLists.txt41
-rw-r--r--cpp/bindings/qpid/Makefile.am2
-rw-r--r--cpp/bindings/qpid/dotnet/configure-windows.ps1108
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs12
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs2
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb30
-rw-r--r--cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln6
-rw-r--r--cpp/bindings/qpid/dotnet/src/Address.cpp24
-rw-r--r--cpp/bindings/qpid/dotnet/src/Address.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Connection.cpp24
-rw-r--r--cpp/bindings/qpid/dotnet/src/Connection.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Duration.h12
-rw-r--r--cpp/bindings/qpid/dotnet/src/FailoverUpdates.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.cpp26
-rw-r--r--cpp/bindings/qpid/dotnet/src/Message.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Receiver.cpp25
-rw-r--r--cpp/bindings/qpid/dotnet/src/Receiver.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Sender.cpp25
-rw-r--r--cpp/bindings/qpid/dotnet/src/Sender.h1
-rw-r--r--cpp/bindings/qpid/dotnet/src/Session.cpp51
-rw-r--r--cpp/bindings/qpid/dotnet/src/Session.h3
-rw-r--r--cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs16
-rw-r--r--cpp/bindings/qpid/examples/perl/client.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/drain.pl12
-rw-r--r--cpp/bindings/qpid/examples/perl/hello_world.pl10
-rw-r--r--cpp/bindings/qpid/examples/perl/hello_xml.pl6
-rw-r--r--cpp/bindings/qpid/examples/perl/map_receiver.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/map_sender.pl8
-rw-r--r--cpp/bindings/qpid/examples/perl/server.pl6
-rw-r--r--cpp/bindings/qpid/examples/perl/spout.pl10
-rw-r--r--cpp/bindings/qpid/perl/CMakeLists.txt38
-rw-r--r--cpp/bindings/qpid/perl/Makefile.am22
-rw-r--r--cpp/bindings/qpid/perl/perl.i2
-rw-r--r--cpp/bindings/qpid/python/CMakeLists.txt45
-rw-r--r--cpp/bindings/qpid/python/Makefile.am6
-rw-r--r--cpp/bindings/qpid/python/python.i338
-rw-r--r--cpp/bindings/qpid/qpid.i3
-rw-r--r--cpp/bindings/qpid/ruby/.gitignore2
-rw-r--r--cpp/bindings/qpid/ruby/CMakeLists.txt63
-rw-r--r--cpp/bindings/qpid/ruby/LICENSE234
-rw-r--r--cpp/bindings/qpid/ruby/Makefile.am6
-rw-r--r--cpp/bindings/qpid/ruby/README.rdoc45
-rw-r--r--cpp/bindings/qpid/ruby/Rakefile130
-rw-r--r--cpp/bindings/qpid/ruby/TODO7
-rw-r--r--cpp/bindings/qpid/ruby/examples/client.rb50
-rw-r--r--cpp/bindings/qpid/ruby/examples/drain.rb111
-rw-r--r--cpp/bindings/qpid/ruby/examples/hello_world.rb49
-rw-r--r--cpp/bindings/qpid/ruby/examples/map_receiver.rb63
-rw-r--r--cpp/bindings/qpid/ruby/examples/map_sender.rb52
-rw-r--r--cpp/bindings/qpid/ruby/examples/server.rb51
-rw-r--r--cpp/bindings/qpid/ruby/examples/spout.rb126
-rw-r--r--cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb73
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid.rb29
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/address.rb125
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/connection.rb134
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/duration.rb63
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/encoding.rb56
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/errors.rb30
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/message.rb157
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/receiver.rb102
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/sender.rb82
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/session.rb186
-rw-r--r--cpp/bindings/qpid/ruby/lib/qpid/version.rb31
-rw-r--r--cpp/bindings/qpid/ruby/test/lib/setup.rb29
-rw-r--r--cpp/bindings/qpid/ruby/test/test_address.rb39
-rw-r--r--cpp/bindings/qpid/ruby/test/test_connection.rb257
-rw-r--r--cpp/bindings/qpid/ruby/test/test_encoding.rb146
-rw-r--r--cpp/bindings/qpid/ruby/test/test_message.rb353
-rw-r--r--cpp/bindings/qpid/ruby/test/test_receiver.rb238
-rw-r--r--cpp/bindings/qpid/ruby/test/test_sender.rb183
-rw-r--r--cpp/bindings/qpid/ruby/test/test_session.rb445
-rw-r--r--cpp/bindings/qpid/ruby/test/ts_bindings.rb30
-rw-r--r--cpp/bindings/swig_python_typemaps.i56
-rw-r--r--cpp/bindings/swig_ruby_typemaps.i2
-rw-r--r--cpp/bld-winsdk.ps13
-rw-r--r--cpp/configure.ac21
-rw-r--r--cpp/design_docs/hot-standby-design.txt239
-rw-r--r--cpp/design_docs/new-cluster-design.txt285
-rw-r--r--cpp/design_docs/new-cluster-plan.txt545
-rw-r--r--cpp/docs/api/developer.doxygen.in2
-rw-r--r--cpp/docs/api/doxygen_mainpage.h41
-rw-r--r--cpp/docs/api/footer.html2
-rw-r--r--cpp/docs/api/user.doxygen.in2
-rw-r--r--cpp/docs/man/Makefile.am23
-rw-r--r--cpp/docs/man/qpidd.1247
-rw-r--r--cpp/docs/man/qpidd.x2
-rw-r--r--cpp/etc/Makefile.am23
-rw-r--r--cpp/etc/qpidd.conf2
-rw-r--r--cpp/etc/sasl2/qpidd.conf5
-rw-r--r--cpp/examples/CMakeLists.txt13
-rw-r--r--cpp/examples/Makefile.am16
-rw-r--r--cpp/examples/README.verify (renamed from cpp/examples/old_api/README.verify)0
-rw-r--r--cpp/examples/direct/CMakeLists.txt (renamed from cpp/examples/old_api/direct/CMakeLists.txt)0
-rw-r--r--cpp/examples/direct/Makefile.am47
-rw-r--r--cpp/examples/direct/declare_queues.cpp (renamed from cpp/examples/old_api/direct/declare_queues.cpp)0
-rw-r--r--cpp/examples/direct/direct_declare_queues.vcproj (renamed from cpp/examples/old_api/direct/direct_declare_queues.vcproj)0
-rw-r--r--cpp/examples/direct/direct_direct_producer.vcproj (renamed from cpp/examples/old_api/direct/direct_direct_producer.vcproj)0
-rw-r--r--cpp/examples/direct/direct_listener.vcproj (renamed from cpp/examples/old_api/direct/direct_listener.vcproj)0
-rw-r--r--cpp/examples/direct/direct_producer.cpp (renamed from cpp/examples/old_api/direct/direct_producer.cpp)0
-rw-r--r--cpp/examples/direct/listener.cpp (renamed from cpp/examples/old_api/direct/listener.cpp)0
-rw-r--r--cpp/examples/direct/verify (renamed from cpp/examples/old_api/direct/verify)0
-rw-r--r--cpp/examples/direct/verify.in (renamed from cpp/examples/old_api/direct/verify.in)0
-rw-r--r--cpp/examples/examples.sln24
-rw-r--r--cpp/examples/failover/CMakeLists.txt (renamed from cpp/examples/old_api/failover/CMakeLists.txt)0
-rw-r--r--cpp/examples/failover/Makefile.am47
-rw-r--r--cpp/examples/failover/declare_queues.cpp (renamed from cpp/examples/old_api/failover/declare_queues.cpp)0
-rw-r--r--cpp/examples/failover/failover_declare_queues.vcproj (renamed from cpp/examples/old_api/failover/failover_declare_queues.vcproj)0
-rw-r--r--cpp/examples/failover/failover_replaying_sender.vcproj (renamed from cpp/examples/old_api/failover/failover_replaying_sender.vcproj)0
-rw-r--r--cpp/examples/failover/failover_resuming_receiver.vcproj (renamed from cpp/examples/old_api/failover/failover_resuming_receiver.vcproj)0
-rw-r--r--cpp/examples/failover/replaying_sender.cpp (renamed from cpp/examples/old_api/failover/replaying_sender.cpp)0
-rw-r--r--cpp/examples/failover/resuming_receiver.cpp (renamed from cpp/examples/old_api/failover/resuming_receiver.cpp)0
-rw-r--r--cpp/examples/fanout/CMakeLists.txt (renamed from cpp/examples/old_api/fanout/CMakeLists.txt)0
-rw-r--r--cpp/examples/fanout/Makefile.am42
-rw-r--r--cpp/examples/fanout/fanout_fanout_producer.vcproj (renamed from cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj)0
-rw-r--r--cpp/examples/fanout/fanout_listener.vcproj (renamed from cpp/examples/old_api/fanout/fanout_listener.vcproj)0
-rw-r--r--cpp/examples/fanout/fanout_producer.cpp (renamed from cpp/examples/old_api/fanout/fanout_producer.cpp)0
-rw-r--r--cpp/examples/fanout/listener.cpp (renamed from cpp/examples/old_api/fanout/listener.cpp)0
-rw-r--r--cpp/examples/fanout/verify (renamed from cpp/examples/old_api/fanout/verify)0
-rw-r--r--cpp/examples/fanout/verify.in (renamed from cpp/examples/old_api/fanout/verify.in)0
-rw-r--r--cpp/examples/messaging/drain.cpp4
-rw-r--r--cpp/examples/messaging/server.cpp4
-rw-r--r--cpp/examples/messaging/spout.cpp2
-rw-r--r--cpp/examples/old-examples.sln147
-rw-r--r--cpp/examples/old_api/CMakeLists.txt25
-rw-r--r--cpp/examples/old_api/Makefile.am48
-rw-r--r--cpp/examples/old_api/direct/Makefile.am47
-rw-r--r--cpp/examples/old_api/failover/Makefile.am47
-rw-r--r--cpp/examples/old_api/fanout/Makefile.am42
-rw-r--r--cpp/examples/old_api/old-examples.sln123
-rw-r--r--cpp/examples/old_api/pub-sub/Makefile.am43
-rw-r--r--cpp/examples/old_api/request-response/Makefile.am43
-rw-r--r--cpp/examples/old_api/tradedemo/Makefile.am46
-rwxr-xr-xcpp/examples/old_api/verify_all46
-rw-r--r--cpp/examples/old_api/xml-exchange/Makefile.am49
-rw-r--r--cpp/examples/pub-sub/CMakeLists.txt (renamed from cpp/examples/old_api/pub-sub/CMakeLists.txt)0
-rw-r--r--cpp/examples/pub-sub/Makefile.am43
-rw-r--r--cpp/examples/pub-sub/pub-sub_topic_listener.vcproj (renamed from cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj)0
-rw-r--r--cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj (renamed from cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj)0
-rw-r--r--cpp/examples/pub-sub/topic_listener.cpp (renamed from cpp/examples/old_api/pub-sub/topic_listener.cpp)0
-rw-r--r--cpp/examples/pub-sub/topic_publisher.cpp (renamed from cpp/examples/old_api/pub-sub/topic_publisher.cpp)0
-rw-r--r--cpp/examples/pub-sub/verify (renamed from cpp/examples/old_api/pub-sub/verify)0
-rw-r--r--cpp/examples/pub-sub/verify.in (renamed from cpp/examples/old_api/pub-sub/verify.in)0
-rw-r--r--cpp/examples/qmf-console/ping.cpp4
-rw-r--r--cpp/examples/qmf-console/printevents.cpp4
-rw-r--r--cpp/examples/request-response/CMakeLists.txt (renamed from cpp/examples/old_api/request-response/CMakeLists.txt)0
-rw-r--r--cpp/examples/request-response/Makefile.am43
-rw-r--r--cpp/examples/request-response/client.cpp (renamed from cpp/examples/old_api/request-response/client.cpp)0
-rw-r--r--cpp/examples/request-response/request-response_client.vcproj (renamed from cpp/examples/old_api/request-response/request-response_client.vcproj)0
-rw-r--r--cpp/examples/request-response/request-response_server.vcproj (renamed from cpp/examples/old_api/request-response/request-response_server.vcproj)0
-rw-r--r--cpp/examples/request-response/server.cpp (renamed from cpp/examples/old_api/request-response/server.cpp)0
-rw-r--r--cpp/examples/request-response/verify (renamed from cpp/examples/old_api/request-response/verify)0
-rw-r--r--cpp/examples/request-response/verify.in (renamed from cpp/examples/old_api/request-response/verify.in)0
-rw-r--r--cpp/examples/tradedemo/CMakeLists.txt (renamed from cpp/examples/old_api/tradedemo/CMakeLists.txt)0
-rw-r--r--cpp/examples/tradedemo/Makefile.am46
-rw-r--r--cpp/examples/tradedemo/declare_queues.cpp (renamed from cpp/examples/old_api/tradedemo/declare_queues.cpp)0
-rw-r--r--cpp/examples/tradedemo/topic_listener.cpp (renamed from cpp/examples/old_api/tradedemo/topic_listener.cpp)0
-rw-r--r--cpp/examples/tradedemo/topic_publisher.cpp (renamed from cpp/examples/old_api/tradedemo/topic_publisher.cpp)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_declare_queues.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_topic_listener.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj)0
-rw-r--r--cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj (renamed from cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj)0
-rwxr-xr-xcpp/examples/verify (renamed from cpp/examples/old_api/verify)0
-rwxr-xr-xcpp/examples/verify_all46
-rw-r--r--cpp/examples/xml-exchange/CMakeLists.txt (renamed from cpp/examples/old_api/xml-exchange/CMakeLists.txt)0
-rw-r--r--cpp/examples/xml-exchange/Makefile.am49
-rw-r--r--cpp/examples/xml-exchange/README.txt (renamed from cpp/examples/old_api/xml-exchange/README.txt)0
-rw-r--r--cpp/examples/xml-exchange/declare_queues.cpp (renamed from cpp/examples/old_api/xml-exchange/declare_queues.cpp)0
-rw-r--r--cpp/examples/xml-exchange/listener.cpp (renamed from cpp/examples/old_api/xml-exchange/listener.cpp)0
-rw-r--r--cpp/examples/xml-exchange/xml_producer.cpp (renamed from cpp/examples/old_api/xml-exchange/xml_producer.cpp)0
-rw-r--r--cpp/include/qmf/Agent.h2
-rw-r--r--cpp/include/qmf/AgentEvent.h2
-rw-r--r--cpp/include/qmf/AgentSession.h48
-rw-r--r--cpp/include/qmf/ConsoleEvent.h2
-rw-r--r--cpp/include/qmf/ConsoleSession.h55
-rw-r--r--cpp/include/qmf/Data.h2
-rw-r--r--cpp/include/qmf/DataAddr.h5
-rw-r--r--cpp/include/qmf/Handle.h10
-rw-r--r--cpp/include/qmf/ImportExport.h16
-rw-r--r--cpp/include/qmf/Query.h4
-rw-r--r--cpp/include/qmf/Schema.h2
-rw-r--r--cpp/include/qmf/SchemaId.h2
-rw-r--r--cpp/include/qmf/SchemaMethod.h2
-rw-r--r--cpp/include/qmf/SchemaProperty.h2
-rw-r--r--cpp/include/qmf/Subscription.h4
-rw-r--r--cpp/include/qmf/engine/QmfEngineImportExport.h9
-rw-r--r--cpp/include/qmf/exceptions.h8
-rw-r--r--cpp/include/qmf/posix/EventNotifier.h63
-rwxr-xr-xcpp/include/qpid/Address.h2
-rw-r--r--cpp/include/qpid/CommonImportExport.h14
-rw-r--r--cpp/include/qpid/Exception.h12
-rw-r--r--cpp/include/qpid/ImportExport.h71
-rw-r--r--cpp/include/qpid/Msg.h1
-rw-r--r--cpp/include/qpid/Options.h88
-rw-r--r--cpp/include/qpid/Url.h2
-rw-r--r--cpp/include/qpid/agent/ManagementAgent.h4
-rw-r--r--cpp/include/qpid/agent/QmfAgentImportExport.h16
-rw-r--r--cpp/include/qpid/amqp_0_10/Codecs.h20
-rw-r--r--cpp/include/qpid/client/ClientImportExport.h14
-rw-r--r--cpp/include/qpid/client/Completion.h2
-rw-r--r--cpp/include/qpid/client/Connection.h10
-rw-r--r--cpp/include/qpid/client/ConnectionSettings.h2
-rw-r--r--cpp/include/qpid/client/FailoverListener.h2
-rw-r--r--cpp/include/qpid/client/FailoverManager.h2
-rw-r--r--cpp/include/qpid/client/Future.h2
-rw-r--r--cpp/include/qpid/client/FutureResult.h2
-rw-r--r--cpp/include/qpid/client/Handle.h10
-rw-r--r--cpp/include/qpid/client/LocalQueue.h2
-rw-r--r--cpp/include/qpid/client/Message.h2
-rw-r--r--cpp/include/qpid/client/MessageListener.h2
-rw-r--r--cpp/include/qpid/client/MessageReplayTracker.h2
-rw-r--r--cpp/include/qpid/client/QueueOptions.h2
-rw-r--r--cpp/include/qpid/client/SessionBase_0_10.h2
-rw-r--r--cpp/include/qpid/client/Subscription.h8
-rw-r--r--cpp/include/qpid/client/SubscriptionManager.h2
-rw-r--r--cpp/include/qpid/console/Agent.h14
-rw-r--r--cpp/include/qpid/console/Broker.h16
-rw-r--r--cpp/include/qpid/console/ClassKey.h30
-rw-r--r--cpp/include/qpid/console/ConsoleImportExport.h14
-rw-r--r--cpp/include/qpid/console/ObjectId.h8
-rw-r--r--cpp/include/qpid/framing/Array.h26
-rw-r--r--cpp/include/qpid/framing/Buffer.h16
-rw-r--r--cpp/include/qpid/framing/FieldTable.h6
-rw-r--r--cpp/include/qpid/framing/FieldValue.h21
-rw-r--r--cpp/include/qpid/framing/List.h25
-rw-r--r--cpp/include/qpid/framing/ProtocolVersion.h12
-rw-r--r--cpp/include/qpid/framing/SequenceNumber.h2
-rw-r--r--cpp/include/qpid/framing/SequenceSet.h2
-rw-r--r--cpp/include/qpid/framing/StructHelper.h2
-rw-r--r--cpp/include/qpid/framing/Uuid.h10
-rw-r--r--cpp/include/qpid/log/Logger.h6
-rw-r--r--cpp/include/qpid/log/Options.h2
-rw-r--r--cpp/include/qpid/management/ManagementObject.h18
-rw-r--r--cpp/include/qpid/messaging/Address.h2
-rw-r--r--cpp/include/qpid/messaging/Connection.h30
-rw-r--r--cpp/include/qpid/messaging/Duration.h8
-rw-r--r--cpp/include/qpid/messaging/FailoverUpdates.h2
-rw-r--r--cpp/include/qpid/messaging/Handle.h10
-rw-r--r--cpp/include/qpid/messaging/ImportExport.h14
-rw-r--r--cpp/include/qpid/messaging/Message.h101
-rw-r--r--cpp/include/qpid/messaging/Receiver.h2
-rw-r--r--cpp/include/qpid/messaging/Sender.h2
-rw-r--r--cpp/include/qpid/messaging/Session.h51
-rw-r--r--cpp/include/qpid/messaging/exceptions.h98
-rw-r--r--cpp/include/qpid/sys/ExceptionHolder.h13
-rwxr-xr-xcpp/include/qpid/sys/IntegerTypes.h2
-rw-r--r--cpp/include/qpid/sys/Runnable.h2
-rw-r--r--cpp/include/qpid/sys/Thread.h6
-rw-r--r--cpp/include/qpid/sys/Time.h5
-rwxr-xr-xcpp/include/qpid/sys/windows/IntegerTypes.h6
-rw-r--r--cpp/include/qpid/types/Exception.h2
-rw-r--r--cpp/include/qpid/types/ImportExport.h14
-rw-r--r--cpp/include/qpid/types/Uuid.h2
-rw-r--r--cpp/include/qpid/types/Variant.h6
-rw-r--r--cpp/managementgen/Makefile.am12
-rwxr-xr-xcpp/managementgen/qmfgen/schema.py4
-rwxr-xr-xcpp/rubygen/0-10/specification.rb2
-rwxr-xr-xcpp/rubygen/MethodBodyDefaultVisitor.rb2
-rwxr-xr-xcpp/rubygen/amqpgen.rb6
-rwxr-xr-xcpp/rubygen/cppgen.rb3
-rwxr-xr-xcpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb2
-rwxr-xr-xcpp/rubygen/framing.0-10/OperationsInvoker.rb2
-rwxr-xr-xcpp/rubygen/framing.0-10/Proxy.rb4
-rwxr-xr-xcpp/rubygen/framing.0-10/Session.rb4
-rwxr-xr-xcpp/rubygen/framing.0-10/structs.rb2
-rw-r--r--cpp/src/CMakeLists.txt128
-rw-r--r--cpp/src/CMakeWinVersions.cmake12
-rw-r--r--cpp/src/Makefile.am55
-rw-r--r--cpp/src/acl.mk4
-rw-r--r--cpp/src/cluster.mk6
-rw-r--r--cpp/src/posix/QpiddBroker.cpp12
-rw-r--r--cpp/src/qmf.mk9
-rw-r--r--cpp/src/qmf/Agent.cpp29
-rw-r--r--cpp/src/qmf/AgentImpl.h1
-rw-r--r--cpp/src/qmf/AgentSession.cpp229
-rw-r--r--cpp/src/qmf/AgentSessionImpl.h175
-rw-r--r--cpp/src/qmf/ConsoleSession.cpp125
-rw-r--r--cpp/src/qmf/ConsoleSessionImpl.h22
-rw-r--r--cpp/src/qmf/DataAddr.cpp6
-rw-r--r--cpp/src/qmf/DataAddrImpl.h4
-rw-r--r--cpp/src/qmf/EventNotifierImpl.cpp56
-rw-r--r--cpp/src/qmf/EventNotifierImpl.h48
-rw-r--r--cpp/src/qmf/PosixEventNotifier.cpp65
-rw-r--r--cpp/src/qmf/PosixEventNotifierImpl.cpp112
-rw-r--r--cpp/src/qmf/PosixEventNotifierImpl.h61
-rw-r--r--cpp/src/qmf/PrivateImplRef.h2
-rw-r--r--cpp/src/qmf/engine/ResilientConnection.cpp6
-rw-r--r--cpp/src/qmf/engine/SchemaImpl.cpp11
-rw-r--r--cpp/src/qmf/engine/SchemaImpl.h7
-rw-r--r--cpp/src/qpid/Address.cpp8
-rw-r--r--cpp/src/qpid/BufferRef.h70
-rw-r--r--cpp/src/qpid/DisableExceptionLogging.h39
-rw-r--r--cpp/src/qpid/Exception.cpp16
-rw-r--r--cpp/src/qpid/Modules.cpp3
-rw-r--r--cpp/src/qpid/Options.cpp269
-rw-r--r--cpp/src/qpid/RefCounted.h6
-rw-r--r--cpp/src/qpid/RefCountedBuffer.cpp29
-rw-r--r--cpp/src/qpid/RefCountedBuffer.h61
-rw-r--r--cpp/src/qpid/Sasl.h4
-rw-r--r--cpp/src/qpid/SaslFactory.cpp28
-rw-r--r--cpp/src/qpid/Url.cpp23
-rw-r--r--cpp/src/qpid/acl/Acl.cpp5
-rw-r--r--cpp/src/qpid/acl/AclPlugin.cpp2
-rw-r--r--cpp/src/qpid/agent/ManagementAgentImpl.cpp361
-rw-r--r--cpp/src/qpid/agent/ManagementAgentImpl.h4
-rw-r--r--cpp/src/qpid/amqp_0_10/Codecs.cpp6
-rw-r--r--cpp/src/qpid/amqp_0_10/SessionHandler.cpp8
-rw-r--r--cpp/src/qpid/amqp_0_10/SessionHandler.h6
-rw-r--r--cpp/src/qpid/broker/AsyncCompletion.h201
-rw-r--r--cpp/src/qpid/broker/Bridge.cpp6
-rw-r--r--cpp/src/qpid/broker/Bridge.h2
-rw-r--r--cpp/src/qpid/broker/Broker.cpp566
-rw-r--r--cpp/src/qpid/broker/Broker.h107
-rw-r--r--cpp/src/qpid/broker/BrokerImportExport.h23
-rw-r--r--cpp/src/qpid/broker/Connection.cpp57
-rw-r--r--cpp/src/qpid/broker/Connection.h9
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.cpp78
-rw-r--r--cpp/src/qpid/broker/ConnectionHandler.h6
-rw-r--r--cpp/src/qpid/broker/ConnectionState.h9
-rw-r--r--cpp/src/qpid/broker/Consumer.h21
-rw-r--r--cpp/src/qpid/broker/Daemon.cpp5
-rw-r--r--cpp/src/qpid/broker/DeliverableMessage.h2
-rw-r--r--cpp/src/qpid/broker/DeliveryRecord.cpp28
-rw-r--r--cpp/src/qpid/broker/DeliveryRecord.h4
-rw-r--r--cpp/src/qpid/broker/DirectExchange.cpp14
-rw-r--r--cpp/src/qpid/broker/DtxAck.cpp4
-rw-r--r--cpp/src/qpid/broker/DtxAck.h35
-rw-r--r--cpp/src/qpid/broker/DtxBuffer.cpp22
-rw-r--r--cpp/src/qpid/broker/DtxBuffer.h53
-rw-r--r--cpp/src/qpid/broker/DtxManager.cpp40
-rw-r--r--cpp/src/qpid/broker/DtxManager.h26
-rw-r--r--cpp/src/qpid/broker/DtxTimeout.cpp2
-rw-r--r--cpp/src/qpid/broker/DtxTimeout.h10
-rw-r--r--cpp/src/qpid/broker/DtxWorkRecord.cpp40
-rw-r--r--cpp/src/qpid/broker/DtxWorkRecord.h14
-rw-r--r--cpp/src/qpid/broker/Exchange.cpp83
-rw-r--r--cpp/src/qpid/broker/Exchange.h48
-rw-r--r--cpp/src/qpid/broker/ExchangeRegistry.cpp11
-rw-r--r--cpp/src/qpid/broker/ExpiryPolicy.cpp10
-rw-r--r--cpp/src/qpid/broker/ExpiryPolicy.h14
-rw-r--r--cpp/src/qpid/broker/Fairshare.cpp76
-rw-r--r--cpp/src/qpid/broker/Fairshare.h6
-rw-r--r--cpp/src/qpid/broker/FanOutExchange.cpp11
-rw-r--r--cpp/src/qpid/broker/FifoDistributor.cpp58
-rw-r--r--cpp/src/qpid/broker/FifoDistributor.h58
-rw-r--r--cpp/src/qpid/broker/HeadersExchange.cpp20
-rw-r--r--cpp/src/qpid/broker/IncompleteMessageList.cpp85
-rw-r--r--cpp/src/qpid/broker/IncompleteMessageList.h58
-rw-r--r--cpp/src/qpid/broker/LegacyLVQ.cpp6
-rw-r--r--cpp/src/qpid/broker/Link.cpp65
-rw-r--r--cpp/src/qpid/broker/Link.h10
-rw-r--r--cpp/src/qpid/broker/LinkRegistry.cpp6
-rw-r--r--cpp/src/qpid/broker/Message.cpp172
-rw-r--r--cpp/src/qpid/broker/Message.h78
-rw-r--r--cpp/src/qpid/broker/MessageBuilder.h2
-rw-r--r--cpp/src/qpid/broker/MessageDistributor.h76
-rw-r--r--cpp/src/qpid/broker/MessageGroupManager.cpp411
-rw-r--r--cpp/src/qpid/broker/MessageGroupManager.h107
-rw-r--r--cpp/src/qpid/broker/Messages.h4
-rw-r--r--cpp/src/qpid/broker/NullMessageStore.cpp4
-rw-r--r--cpp/src/qpid/broker/NullMessageStore.h4
-rw-r--r--cpp/src/qpid/broker/PersistableMessage.cpp26
-rw-r--r--cpp/src/qpid/broker/PersistableMessage.h29
-rw-r--r--cpp/src/qpid/broker/Queue.cpp727
-rw-r--r--cpp/src/qpid/broker/Queue.h131
-rw-r--r--cpp/src/qpid/broker/QueueCleaner.cpp18
-rw-r--r--cpp/src/qpid/broker/QueueCleaner.h14
-rw-r--r--cpp/src/qpid/broker/QueueEvents.cpp4
-rw-r--r--cpp/src/qpid/broker/QueueFlowLimit.cpp410
-rw-r--r--cpp/src/qpid/broker/QueueFlowLimit.h132
-rw-r--r--cpp/src/qpid/broker/QueueListeners.cpp36
-rw-r--r--cpp/src/qpid/broker/QueueListeners.h4
-rw-r--r--cpp/src/qpid/broker/QueueObserver.h42
-rw-r--r--cpp/src/qpid/broker/QueuePolicy.cpp23
-rw-r--r--cpp/src/qpid/broker/QueuePolicy.h3
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.cpp20
-rw-r--r--cpp/src/qpid/broker/QueueRegistry.h7
-rw-r--r--cpp/src/qpid/broker/RateTracker.cpp51
-rw-r--r--cpp/src/qpid/broker/RateTracker.h57
-rw-r--r--cpp/src/qpid/broker/RecoveredDequeue.cpp1
-rw-r--r--cpp/src/qpid/broker/RecoveredEnqueue.cpp1
-rw-r--r--cpp/src/qpid/broker/RecoveryManagerImpl.cpp3
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.cpp66
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.h2
-rw-r--r--cpp/src/qpid/broker/SemanticState.cpp171
-rw-r--r--cpp/src/qpid/broker/SemanticState.h45
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.cpp292
-rw-r--r--cpp/src/qpid/broker/SessionAdapter.h1
-rw-r--r--cpp/src/qpid/broker/SessionContext.h1
-rw-r--r--cpp/src/qpid/broker/SessionHandler.cpp5
-rw-r--r--cpp/src/qpid/broker/SessionState.cpp245
-rw-r--r--cpp/src/qpid/broker/SessionState.h119
-rw-r--r--cpp/src/qpid/broker/StatefulQueueObserver.h63
-rw-r--r--cpp/src/qpid/broker/ThresholdAlerts.cpp68
-rw-r--r--cpp/src/qpid/broker/ThresholdAlerts.h7
-rw-r--r--cpp/src/qpid/broker/TopicExchange.cpp84
-rw-r--r--cpp/src/qpid/broker/TopicExchange.h29
-rw-r--r--cpp/src/qpid/broker/TxBuffer.cpp2
-rw-r--r--cpp/src/qpid/broker/TxPublish.cpp9
-rw-r--r--cpp/src/qpid/broker/TxPublish.h91
-rw-r--r--cpp/src/qpid/broker/windows/BrokerDefaults.cpp6
-rw-r--r--cpp/src/qpid/broker/windows/SaslAuthenticator.cpp32
-rw-r--r--cpp/src/qpid/broker/windows/SslProtocolFactory.cpp53
-rw-r--r--cpp/src/qpid/client/ConnectionHandler.cpp64
-rw-r--r--cpp/src/qpid/client/ConnectionImpl.cpp12
-rw-r--r--cpp/src/qpid/client/Connector.h2
-rw-r--r--cpp/src/qpid/client/RdmaConnector.cpp6
-rw-r--r--cpp/src/qpid/client/SessionImpl.cpp1
-rw-r--r--cpp/src/qpid/client/SslConnector.cpp6
-rw-r--r--cpp/src/qpid/client/TCPConnector.cpp6
-rw-r--r--cpp/src/qpid/client/TCPConnector.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp42
-rw-r--r--cpp/src/qpid/client/amqp0_10/AcceptTracker.h5
-rw-r--r--cpp/src/qpid/client/amqp0_10/AddressResolution.cpp60
-rw-r--r--cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp179
-rw-r--r--cpp/src/qpid/client/amqp0_10/ConnectionImpl.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp10
-rw-r--r--cpp/src/qpid/client/amqp0_10/IncomingMessages.h2
-rw-r--r--cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp4
-rw-r--r--cpp/src/qpid/client/amqp0_10/SenderImpl.cpp3
-rw-r--r--cpp/src/qpid/client/amqp0_10/SessionImpl.cpp56
-rw-r--r--cpp/src/qpid/client/amqp0_10/SessionImpl.h11
-rw-r--r--cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp79
-rw-r--r--cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h42
-rw-r--r--cpp/src/qpid/client/windows/SaslFactory.cpp16
-rw-r--r--cpp/src/qpid/client/windows/SslConnector.cpp4
-rw-r--r--cpp/src/qpid/cluster/Cluster.cpp169
-rw-r--r--cpp/src/qpid/cluster/Cluster.h56
-rw-r--r--cpp/src/qpid/cluster/ClusterMap.cpp5
-rw-r--r--cpp/src/qpid/cluster/ClusterPlugin.cpp1
-rw-r--r--cpp/src/qpid/cluster/ClusterSettings.h3
-rw-r--r--cpp/src/qpid/cluster/ClusterTimer.cpp4
-rw-r--r--cpp/src/qpid/cluster/Connection.cpp235
-rw-r--r--cpp/src/qpid/cluster/Connection.h55
-rw-r--r--cpp/src/qpid/cluster/Decoder.h2
-rw-r--r--cpp/src/qpid/cluster/ErrorCheck.h2
-rw-r--r--cpp/src/qpid/cluster/Event.cpp5
-rw-r--r--cpp/src/qpid/cluster/Event.h28
-rw-r--r--cpp/src/qpid/cluster/EventFrame.h6
-rw-r--r--cpp/src/qpid/cluster/ExpiryPolicy.cpp95
-rw-r--r--cpp/src/qpid/cluster/ExpiryPolicy.h42
-rw-r--r--cpp/src/qpid/cluster/FailoverExchange.cpp26
-rw-r--r--cpp/src/qpid/cluster/FailoverExchange.h10
-rw-r--r--cpp/src/qpid/cluster/Multicaster.cpp3
-rw-r--r--cpp/src/qpid/cluster/OutputInterceptor.cpp39
-rw-r--r--cpp/src/qpid/cluster/OutputInterceptor.h10
-rw-r--r--cpp/src/qpid/cluster/SecureConnectionFactory.cpp8
-rw-r--r--cpp/src/qpid/cluster/UpdateClient.cpp223
-rw-r--r--cpp/src/qpid/cluster/UpdateClient.h32
-rw-r--r--cpp/src/qpid/cluster/UpdateDataExchange.cpp10
-rw-r--r--cpp/src/qpid/cluster/UpdateDataExchange.h2
-rw-r--r--cpp/src/qpid/cluster/UpdateExchange.cpp27
-rw-r--r--cpp/src/qpid/cluster/UpdateReceiver.h14
-rw-r--r--cpp/src/qpid/cluster/types.h1
-rw-r--r--cpp/src/qpid/console/SessionManager.cpp3
-rw-r--r--cpp/src/qpid/framing/AMQBody.h2
-rw-r--r--cpp/src/qpid/framing/AMQContentBody.h12
-rw-r--r--cpp/src/qpid/framing/AMQFrame.cpp5
-rw-r--r--cpp/src/qpid/framing/AMQFrame.h7
-rw-r--r--cpp/src/qpid/framing/AMQHeaderBody.h14
-rw-r--r--cpp/src/qpid/framing/AMQHeartbeatBody.h2
-rw-r--r--cpp/src/qpid/framing/FieldTable.cpp6
-rw-r--r--cpp/src/qpid/framing/List.cpp6
-rw-r--r--cpp/src/qpid/framing/MethodBodyFactory.h1
-rw-r--r--cpp/src/qpid/framing/SendContent.h2
-rw-r--r--cpp/src/qpid/framing/TransferContent.h2
-rw-r--r--cpp/src/qpid/framing/Uuid.cpp4
-rw-r--r--cpp/src/qpid/log/Logger.cpp21
-rw-r--r--cpp/src/qpid/log/Options.cpp4
-rw-r--r--cpp/src/qpid/log/Statement.cpp5
-rw-r--r--cpp/src/qpid/log/posix/SinkOptions.cpp2
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.cpp4
-rw-r--r--cpp/src/qpid/log/windows/SinkOptions.h2
-rw-r--r--cpp/src/qpid/management/ManagementAgent.cpp228
-rw-r--r--cpp/src/qpid/management/ManagementAgent.h13
-rw-r--r--cpp/src/qpid/messaging/AddressParser.cpp5
-rw-r--r--cpp/src/qpid/messaging/Duration.cpp10
-rw-r--r--cpp/src/qpid/messaging/Message.cpp7
-rw-r--r--cpp/src/qpid/messaging/Session.cpp3
-rw-r--r--cpp/src/qpid/messaging/SessionImpl.h2
-rw-r--r--cpp/src/qpid/replication/ReplicatingEventListener.cpp7
-rw-r--r--cpp/src/qpid/replication/ReplicationExchange.cpp9
-rw-r--r--cpp/src/qpid/store/StorageProvider.h2
-rw-r--r--cpp/src/qpid/sys/AggregateOutput.h2
-rw-r--r--cpp/src/qpid/sys/AsynchIO.h4
-rw-r--r--cpp/src/qpid/sys/AsynchIOHandler.h2
-rw-r--r--cpp/src/qpid/sys/AtomicValue.h7
-rw-r--r--cpp/src/qpid/sys/AtomicValue_gcc.h11
-rw-r--r--cpp/src/qpid/sys/ClusterSafe.cpp12
-rw-r--r--cpp/src/qpid/sys/ClusterSafe.h21
-rw-r--r--cpp/src/qpid/sys/CopyOnWriteArray.h6
-rw-r--r--cpp/src/qpid/sys/PollableQueue.h21
-rw-r--r--cpp/src/qpid/sys/Poller.h2
-rw-r--r--cpp/src/qpid/sys/ProtocolFactory.h3
-rw-r--r--cpp/src/qpid/sys/RdmaIOPlugin.cpp24
-rw-r--r--cpp/src/qpid/sys/Socket.h32
-rw-r--r--cpp/src/qpid/sys/SocketAddress.h10
-rw-r--r--cpp/src/qpid/sys/SslPlugin.cpp11
-rw-r--r--cpp/src/qpid/sys/StateMonitor.h14
-rw-r--r--cpp/src/qpid/sys/TCPIOPlugin.cpp80
-rw-r--r--cpp/src/qpid/sys/Timer.cpp22
-rw-r--r--cpp/src/qpid/sys/Timer.h8
-rw-r--r--cpp/src/qpid/sys/TimerWarnings.cpp16
-rw-r--r--cpp/src/qpid/sys/alloca.h25
-rw-r--r--cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp3
-rw-r--r--cpp/src/qpid/sys/epoll/EpollPoller.cpp7
-rw-r--r--cpp/src/qpid/sys/posix/AsynchIO.cpp36
-rwxr-xr-xcpp/src/qpid/sys/posix/LockFile.cpp3
-rw-r--r--cpp/src/qpid/sys/posix/Socket.cpp171
-rw-r--r--cpp/src/qpid/sys/posix/SocketAddress.cpp80
-rw-r--r--cpp/src/qpid/sys/posix/Thread.cpp3
-rw-r--r--cpp/src/qpid/sys/posix/Time.cpp7
-rw-r--r--cpp/src/qpid/sys/rdma/RdmaIO.cpp14
-rw-r--r--cpp/src/qpid/sys/rdma/rdma_wrap.cpp15
-rw-r--r--cpp/src/qpid/sys/rdma/rdma_wrap.h10
-rw-r--r--cpp/src/qpid/sys/ssl/SslHandler.h2
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.cpp2
-rw-r--r--cpp/src/qpid/sys/ssl/SslIo.h2
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.cpp4
-rw-r--r--cpp/src/qpid/sys/ssl/SslSocket.h2
-rw-r--r--cpp/src/qpid/sys/windows/AsynchIO.cpp71
-rwxr-xr-xcpp/src/qpid/sys/windows/AsynchIoResult.h6
-rwxr-xr-xcpp/src/qpid/sys/windows/IocpPoller.cpp6
-rw-r--r--cpp/src/qpid/sys/windows/SCM.cpp332
-rw-r--r--cpp/src/qpid/sys/windows/SCM.h111
-rw-r--r--cpp/src/qpid/sys/windows/Shlib.cpp3
-rwxr-xr-x[-rw-r--r--]cpp/src/qpid/sys/windows/Socket.cpp188
-rw-r--r--cpp/src/qpid/sys/windows/SocketAddress.cpp120
-rw-r--r--cpp/src/qpid/sys/windows/SslAsynchIO.h3
-rwxr-xr-xcpp/src/qpid/sys/windows/StrError.cpp7
-rwxr-xr-xcpp/src/qpid/sys/windows/Thread.cpp285
-rw-r--r--cpp/src/qpid/sys/windows/Time.cpp36
-rw-r--r--cpp/src/qpid/sys/windows/mingw32_compat.h39
-rw-r--r--cpp/src/qpid/sys/windows/uuid.cpp6
-rw-r--r--cpp/src/qpid/types/Uuid.cpp19
-rw-r--r--cpp/src/qpid/types/Variant.cpp35
-rw-r--r--cpp/src/replication.mk6
-rw-r--r--cpp/src/ssl.mk6
-rw-r--r--cpp/src/tests/.valgrind.supp74
-rw-r--r--cpp/src/tests/Address.cpp11
-rw-r--r--cpp/src/tests/BrokerFixture.h32
-rw-r--r--cpp/src/tests/BrokerMgmtAgent.cpp3
-rw-r--r--cpp/src/tests/BrokerOptions.cpp79
-rw-r--r--cpp/src/tests/CMakeLists.txt18
-rw-r--r--cpp/src/tests/ClientSessionTest.cpp33
-rw-r--r--cpp/src/tests/ExchangeTest.cpp2
-rw-r--r--cpp/src/tests/ForkedBroker.cpp3
-rw-r--r--cpp/src/tests/IncompleteMessageList.cpp134
-rw-r--r--cpp/src/tests/Makefile.am47
-rw-r--r--cpp/src/tests/MessageReplayTracker.cpp4
-rw-r--r--cpp/src/tests/MessagingFixture.h117
-rw-r--r--cpp/src/tests/MessagingSessionTests.cpp228
-rw-r--r--cpp/src/tests/Qmf2.cpp104
-rw-r--r--cpp/src/tests/QueueEvents.cpp4
-rw-r--r--cpp/src/tests/QueueFlowLimitTest.cpp463
-rw-r--r--cpp/src/tests/QueuePolicyTest.cpp21
-rw-r--r--cpp/src/tests/QueueTest.cpp444
-rw-r--r--cpp/src/tests/ReplicationTest.cpp2
-rw-r--r--cpp/src/tests/SessionState.cpp8
-rw-r--r--cpp/src/tests/SocketProxy.h181
-rw-r--r--cpp/src/tests/TimerTest.cpp4
-rw-r--r--cpp/src/tests/TxPublishTest.cpp7
-rw-r--r--cpp/src/tests/Url.cpp26
-rw-r--r--cpp/src/tests/Variant.cpp58
-rw-r--r--cpp/src/tests/XmlClientSessionTest.cpp2
-rwxr-xr-xcpp/src/tests/acl.py219
-rwxr-xr-xcpp/src/tests/allhosts4
-rw-r--r--cpp/src/tests/brokertest.py312
-rwxr-xr-xcpp/src/tests/cli_tests.py24
-rw-r--r--cpp/src/tests/cluster_python_tests_failing.txt28
-rwxr-xr-xcpp/src/tests/cluster_test_logs.py16
-rwxr-xr-xcpp/src/tests/cluster_tests.py1033
-rw-r--r--cpp/src/tests/exception_test.cpp14
-rwxr-xr-xcpp/src/tests/federated_topic_test27
-rwxr-xr-xcpp/src/tests/federation.py398
-rwxr-xr-xcpp/src/tests/federation_sys.py1900
-rwxr-xr-xcpp/src/tests/ipv6_test150
-rw-r--r--cpp/src/tests/msg_group_test.cpp618
-rwxr-xr-xcpp/src/tests/python_tests2
-rwxr-xr-xcpp/src/tests/qpid-cluster-benchmark47
-rwxr-xr-xcpp/src/tests/qpid-cpp-benchmark71
-rwxr-xr-xcpp/src/tests/qpid-ctrl5
-rw-r--r--cpp/src/tests/qpid-perftest.cpp18
-rw-r--r--cpp/src/tests/qpid-receive.cpp9
-rw-r--r--cpp/src/tests/qpid-send.cpp104
-rw-r--r--cpp/src/tests/qrsh.cpp169
-rw-r--r--cpp/src/tests/qrsh_run.cpp321
-rw-r--r--cpp/src/tests/qrsh_server.cpp1068
-rwxr-xr-xcpp/src/tests/qrsh_utils/10_all30
-rwxr-xr-xcpp/src/tests/qrsh_utils/1_remote_run26
-rwxr-xr-xcpp/src/tests/qrsh_utils/2_forever26
-rwxr-xr-xcpp/src/tests/qrsh_utils/3_kill_it27
-rwxr-xr-xcpp/src/tests/qrsh_utils/4_wait_for_it26
-rwxr-xr-xcpp/src/tests/qrsh_utils/5_exited64
-rwxr-xr-xcpp/src/tests/qrsh_utils/6_get29
-rwxr-xr-xcpp/src/tests/qrsh_utils/7_get_output44
-rwxr-xr-xcpp/src/tests/qrsh_utils/8_any43
-rwxr-xr-xcpp/src/tests/qrsh_utils/9_alias38
-rw-r--r--cpp/src/tests/qrsh_utils/qrsh_example_command.cpp52
-rw-r--r--cpp/src/tests/qrsh_utils/qrsh_forever.cpp50
-rw-r--r--cpp/src/tests/qrsh_utils/qsh_doc.txt309
-rw-r--r--cpp/src/tests/queue_flow_limit_tests.py371
-rwxr-xr-xcpp/src/tests/replication_test2
-rwxr-xr-xcpp/src/tests/run_acl_tests2
-rwxr-xr-xcpp/src/tests/run_cli_tests5
-rwxr-xr-xcpp/src/tests/run_federation_sys_tests97
-rwxr-xr-xcpp/src/tests/run_federation_tests4
-rwxr-xr-xcpp/src/tests/run_header_test2
-rw-r--r--cpp/src/tests/run_long_federation_sys_tests24
-rwxr-xr-xcpp/src/tests/run_msg_group_tests66
-rwxr-xr-xcpp/src/tests/run_msg_group_tests_soak60
-rwxr-xr-xcpp/src/tests/run_queue_flow_limit_tests57
-rw-r--r--cpp/src/tests/run_store_tests.ps12
-rwxr-xr-xcpp/src/tests/run_test2
-rw-r--r--cpp/src/tests/sasl.mk16
-rwxr-xr-xcpp/src/tests/sasl_fed2
-rwxr-xr-xcpp/src/tests/sasl_fed_ex306
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_dynamic27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_dynamic_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_link27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_link_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_queue27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_queue_cluster28
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_route27
-rwxr-xr-xcpp/src/tests/sasl_fed_ex_route_cluster28
-rwxr-xr-xcpp/src/tests/sasl_no_dir218
-rwxr-xr-xcpp/src/tests/sasl_test_setup.sh1
-rw-r--r--cpp/src/tests/sender.cpp2
-rwxr-xr-xcpp/src/tests/ssl_test14
-rw-r--r--cpp/src/tests/windows/DisableWin32ErrorWindows.cpp4
-rw-r--r--cpp/src/windows/QpiddBroker.cpp16
-rw-r--r--cpp/src/windows/SCM.cpp332
-rw-r--r--cpp/src/windows/SCM.h109
-rw-r--r--cpp/src/windows/resources/template-resource.rc2
-rw-r--r--cpp/src/xml.mk2
-rw-r--r--cpp/xml/cluster.xml74
-rwxr-xr-xdoc/book/build-book.sh12
-rw-r--r--doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml2
-rw-r--r--doc/book/src/AMQP-Messaging-Broker-CPP.xml4
-rw-r--r--doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml10
-rw-r--r--doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml4
-rw-r--r--doc/book/src/Programming-In-Apache-Qpid.xml61
-rw-r--r--doc/book/src/Qpid-Java-FAQ.xml54
-rw-r--r--doc/book/src/Security.xml20
-rw-r--r--doc/book/src/System-Properties.xml70
-rw-r--r--doc/book/src/Using-message-groups.xml261
-rw-r--r--doc/book/src/producer-flow-control.xml351
-rw-r--r--doc/dev-readme/QPID-0.8-Component-README.odgbin0 -> 13700 bytes
-rw-r--r--doc/dev-readme/QPID-0.8-Component-README.pdfbin0 -> 40319 bytes
-rw-r--r--doc/dev-readme/QPID-Component-README.odgbin12661 -> 0 bytes
-rw-r--r--doc/dev-readme/QPID-Component-README.pdfbin38097 -> 0 bytes
-rw-r--r--doc/website/README.txt28
-rwxr-xr-xdoc/website/build.sh53
-rw-r--r--doc/website/content/.htaccess20
-rw-r--r--doc/website/content/acknowledgements.html39
-rw-r--r--doc/website/content/amqp.html71
-rw-r--r--doc/website/content/compatibility.html386
-rw-r--r--doc/website/content/documentation.html92
-rw-r--r--doc/website/content/download.cgi26
-rw-r--r--doc/website/content/download.html466
-rw-r--r--doc/website/content/getting_involved.html69
-rw-r--r--doc/website/content/getting_started.html85
-rw-r--r--doc/website/content/images/README.txt1
-rw-r--r--doc/website/content/images/jprofiler.pngbin0 -> 584 bytes
-rw-r--r--doc/website/content/images/structure101.jpgbin0 -> 3465 bytes
-rw-r--r--doc/website/content/index.html91
-rw-r--r--doc/website/content/mailing_lists.html82
-rw-r--r--doc/website/content/people.html98
-rw-r--r--doc/website/content/qpid_integrated_with.html40
-rw-r--r--doc/website/content/qpid_project_etiquette_guide.html104
-rw-r--r--doc/website/content/release_notes_0.8.html437
-rw-r--r--doc/website/content/source_repository.html74
-rw-r--r--doc/website/example/images/asf-logo.pngbin0 -> 4735 bytes
-rw-r--r--doc/website/example/images/asf_logo.gifbin0 -> 7279 bytes
-rw-r--r--doc/website/example/images/header.pngbin0 -> 22354 bytes
-rw-r--r--doc/website/example/images/main_body.pngbin0 -> 211 bytes
-rw-r--r--doc/website/example/images/main_bottom.pngbin0 -> 1719 bytes
-rw-r--r--doc/website/example/images/main_top.pngbin0 -> 295 bytes
-rw-r--r--doc/website/example/images/menu_body.pngbin0 -> 198 bytes
-rw-r--r--doc/website/example/images/menu_bottom.pngbin0 -> 264 bytes
-rw-r--r--doc/website/example/images/menu_top.pngbin0 -> 258 bytes
-rw-r--r--doc/website/example/images/qpid-logo-900x480.pngbin0 -> 39038 bytes
-rw-r--r--doc/website/example/images/qpid-logo.pngbin0 -> 5775 bytes
-rw-r--r--doc/website/example/index.html185
-rw-r--r--doc/website/example/style.css263
-rw-r--r--doc/website/template/images/asf-logo.pngbin0 -> 4735 bytes
-rw-r--r--doc/website/template/images/asf_logo.gifbin0 -> 7279 bytes
-rw-r--r--doc/website/template/images/header.pngbin0 -> 22576 bytes
-rw-r--r--doc/website/template/images/main_body.pngbin0 -> 211 bytes
-rw-r--r--doc/website/template/images/main_bottom.pngbin0 -> 1719 bytes
-rw-r--r--doc/website/template/images/main_top.pngbin0 -> 295 bytes
-rw-r--r--doc/website/template/images/menu_body.pngbin0 -> 198 bytes
-rw-r--r--doc/website/template/images/menu_bottom.pngbin0 -> 264 bytes
-rw-r--r--doc/website/template/images/menu_top.pngbin0 -> 258 bytes
-rw-r--r--doc/website/template/images/qpid-logo-900x480.pngbin0 -> 39038 bytes
-rw-r--r--doc/website/template/images/qpid-logo.pngbin0 -> 6600 bytes
-rw-r--r--doc/website/template/style.css276
-rw-r--r--doc/website/template/template.html126
-rwxr-xr-xdoc/website/tools/generate56
-rwxr-xr-xdoc/website/tools/wrap44
-rw-r--r--dotnet/LICENSE.txt757
-rw-r--r--dotnet/NOTICE.txt32
-rw-r--r--dotnet/Qpid.Buffer.Tests/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/Qpid.Buffer.Tests/Qpid.Buffer.Tests.csproj83
-rw-r--r--dotnet/Qpid.Buffer.Tests/SimpleByteBufferTests.cs333
-rw-r--r--dotnet/Qpid.Buffer.Tests/SlicedByteBufferTests.cs133
-rw-r--r--dotnet/Qpid.Buffer.Tests/default.build48
-rw-r--r--dotnet/Qpid.Buffer/BufferOverflowException.cs41
-rw-r--r--dotnet/Qpid.Buffer/BufferUnderflowException.cs42
-rw-r--r--dotnet/Qpid.Buffer/ByteBuffer.cs982
-rw-r--r--dotnet/Qpid.Buffer/ByteBufferHexDumper.cs79
-rw-r--r--dotnet/Qpid.Buffer/IByteBufferAllocator.cs50
-rw-r--r--dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/Qpid.Buffer/Qpid.Buffer.csproj77
-rw-r--r--dotnet/Qpid.Buffer/SimpleByteBuffer.cs120
-rw-r--r--dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs58
-rw-r--r--dotnet/Qpid.Buffer/SlicedByteBuffer.cs86
-rw-r--r--dotnet/Qpid.Buffer/default.build46
-rw-r--r--dotnet/Qpid.Client.Tests/App.config34
-rw-r--r--dotnet/Qpid.Client.Tests/BrokerDetails/BrokerDetailsTest.cs65
-rw-r--r--dotnet/Qpid.Client.Tests/Channel/ChannelMessageCreationTests.cs79
-rw-r--r--dotnet/Qpid.Client.Tests/Messages/MessageFactoryRegistryTests.cs114
-rw-r--r--dotnet/Qpid.Client.Tests/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj158
-rw-r--r--dotnet/Qpid.Client.Tests/Security/CallbackHandlerRegistryTests.cs66
-rw-r--r--dotnet/Qpid.Client.Tests/default.build64
-rw-r--r--dotnet/Qpid.Client.Tests/interop/TopicListener.cs211
-rw-r--r--dotnet/Qpid.Client.Tests/interop/TopicPublisher.cs208
-rw-r--r--dotnet/Qpid.Client.Tests/lib/nunit/nunit-licence.txt23
-rw-r--r--dotnet/Qpid.Client.Tests/lib/nunit/nunit.framework.dllbin0 -> 45056 bytes
-rw-r--r--dotnet/Qpid.Client.Tests/log4net.config68
-rw-r--r--dotnet/Qpid.Client.Tests/url/ConnectionUrlTest.cs446
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketProcessor.cs135
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketTransport.cs121
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/ByteChannel.cs63
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.csproj92
-rw-r--r--dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.mdp50
-rw-r--r--dotnet/Qpid.Client/Client/AMQAuthenticationException.cs39
-rw-r--r--dotnet/Qpid.Client/Client/AMQConnection.cs873
-rw-r--r--dotnet/Qpid.Client/Client/AMQConnectionException.cs38
-rw-r--r--dotnet/Qpid.Client/Client/AMQDestination.cs234
-rw-r--r--dotnet/Qpid.Client/Client/AMQNoConsumersException.cs45
-rw-r--r--dotnet/Qpid.Client/Client/AMQNoRouteException.cs46
-rw-r--r--dotnet/Qpid.Client/Client/AmqBrokerInfo.cs322
-rw-r--r--dotnet/Qpid.Client/Client/AmqChannel.cs1241
-rw-r--r--dotnet/Qpid.Client/Client/BasicMessageConsumer.cs485
-rw-r--r--dotnet/Qpid.Client/Client/BasicMessageProducer.cs405
-rw-r--r--dotnet/Qpid.Client/Client/Closeable.cs83
-rw-r--r--dotnet/Qpid.Client/Client/Configuration/AuthenticationConfigurationSectionHandler.cs84
-rw-r--r--dotnet/Qpid.Client/Client/ConnectionTuneParameters.cs83
-rw-r--r--dotnet/Qpid.Client/Client/Failover/FailoverException.cs42
-rw-r--r--dotnet/Qpid.Client/Client/Failover/FailoverHandler.cs175
-rw-r--r--dotnet/Qpid.Client/Client/Failover/FailoverState.cs31
-rw-r--r--dotnet/Qpid.Client/Client/Failover/FailoverSupport.cs55
-rw-r--r--dotnet/Qpid.Client/Client/Handler/BasicDeliverMethodHandler.cs42
-rw-r--r--dotnet/Qpid.Client/Client/Handler/BasicReturnMethodHandler.cs44
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ChannelCloseMethodHandler.cs68
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionCloseMethodHandler.cs68
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionCloseOkHandler.cs41
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionOpenOkMethodHandler.cs35
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionRedirectMethodHandler.cs68
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionSecureMethodHandler.cs60
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs144
-rw-r--r--dotnet/Qpid.Client/Client/Handler/ConnectionTuneMethodHandler.cs63
-rw-r--r--dotnet/Qpid.Client/Client/Handler/QueueDeleteOkMethodHandler.cs44
-rw-r--r--dotnet/Qpid.Client/Client/Handler/QueuePurgeOkMethodHandler.cs44
-rw-r--r--dotnet/Qpid.Client/Client/Message/AMQMessage.cs58
-rw-r--r--dotnet/Qpid.Client/Client/Message/AMQMessageFactory.cs73
-rw-r--r--dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs694
-rw-r--r--dotnet/Qpid.Client/Client/Message/IMessageFactory.cs52
-rw-r--r--dotnet/Qpid.Client/Client/Message/MessageFactoryRegistry.cs129
-rw-r--r--dotnet/Qpid.Client/Client/Message/QpidBytesMessage.cs353
-rw-r--r--dotnet/Qpid.Client/Client/Message/QpidBytesMessageFactory.cs75
-rw-r--r--dotnet/Qpid.Client/Client/Message/QpidHeaders.cs233
-rw-r--r--dotnet/Qpid.Client/Client/Message/QpidTextMessage.cs115
-rw-r--r--dotnet/Qpid.Client/Client/Message/QpidTextMessageFactory.cs40
-rw-r--r--dotnet/Qpid.Client/Client/Message/UnexpectedBodyReceivedException.cs57
-rw-r--r--dotnet/Qpid.Client/Client/Message/UnprocessedMessage.cs57
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/AMQMethodEvent.cs76
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs318
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/AMQProtocolSession.cs267
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs47
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/IConnectionCloser.cs27
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/IProtocolListener.cs36
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs110
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/Listener/IAMQMethodListener.cs46
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/Listener/SpecificMethodFrameListener.cs42
-rw-r--r--dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs107
-rw-r--r--dotnet/Qpid.Client/Client/QpidConnectionInfo.cs504
-rw-r--r--dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs129
-rw-r--r--dotnet/Qpid.Client/Client/Security/IAMQCallbackHandler.cs35
-rw-r--r--dotnet/Qpid.Client/Client/Security/UsernamePasswordCallbackHandler.cs56
-rw-r--r--dotnet/Qpid.Client/Client/SslOptions.cs81
-rw-r--r--dotnet/Qpid.Client/Client/State/AMQState.cs35
-rw-r--r--dotnet/Qpid.Client/Client/State/AMQStateChangedEvent.cs52
-rw-r--r--dotnet/Qpid.Client/Client/State/AMQStateManager.cs251
-rw-r--r--dotnet/Qpid.Client/Client/State/IAMQStateListener.cs29
-rw-r--r--dotnet/Qpid.Client/Client/State/IStateAwareMethodListener.cs31
-rw-r--r--dotnet/Qpid.Client/Client/State/IStateListener.cs33
-rw-r--r--dotnet/Qpid.Client/Client/State/IllegalStateTransitionException.cs74
-rw-r--r--dotnet/Qpid.Client/Client/State/StateWaiter.cs121
-rw-r--r--dotnet/Qpid.Client/Client/Transport/AMQProtocolProvider.cs47
-rw-r--r--dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs111
-rw-r--r--dotnet/Qpid.Client/Client/Transport/IByteChannel.cs71
-rw-r--r--dotnet/Qpid.Client/Client/Transport/IProtocolChannel.cs32
-rw-r--r--dotnet/Qpid.Client/Client/Transport/IProtocolWriter.cs29
-rw-r--r--dotnet/Qpid.Client/Client/Transport/IStreamFilter.cs38
-rw-r--r--dotnet/Qpid.Client/Client/Transport/ITransport.cs32
-rw-r--r--dotnet/Qpid.Client/Client/Transport/IoHandler.cs322
-rw-r--r--dotnet/Qpid.Client/Client/Transport/ProtocolDecoderOutput.cs60
-rw-r--r--dotnet/Qpid.Client/Client/Transport/SingleProtocolEncoderOutput.cs40
-rw-r--r--dotnet/Qpid.Client/Client/Transport/Socket/Blocking/BlockingSocketTransport.cs150
-rw-r--r--dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ByteChannel.cs92
-rw-r--r--dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ISocketConnector.cs34
-rw-r--r--dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SocketConnector.cs71
-rw-r--r--dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SslSocketConnector.cs107
-rw-r--r--dotnet/Qpid.Client/Client/Util/FlowControlQueue.cs98
-rw-r--r--dotnet/Qpid.Client/Properties/AssemblyInfo.cs52
-rw-r--r--dotnet/Qpid.Client/Qpid.Client.csproj102
-rw-r--r--dotnet/Qpid.Client/default.build52
-rw-r--r--dotnet/Qpid.Client/qms/BrokerInfo.cs55
-rw-r--r--dotnet/Qpid.Client/qms/ConnectionInfo.cs63
-rw-r--r--dotnet/Qpid.Client/qms/FailoverPolicy.cs315
-rw-r--r--dotnet/Qpid.Client/qms/UrlSyntaxException.cs134
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverMethod.cs78
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs255
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs147
-rw-r--r--dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs152
-rw-r--r--dotnet/Qpid.Codec/Demux/DemuxingProtocolCodecFactory.cs387
-rw-r--r--dotnet/Qpid.Codec/Demux/IMessageDecoder.cs56
-rw-r--r--dotnet/Qpid.Codec/Demux/IMessageDecoderFactory.cs32
-rw-r--r--dotnet/Qpid.Codec/Demux/IMessageEncoder.cs48
-rw-r--r--dotnet/Qpid.Codec/Demux/IMessageEncoderFactory.cs32
-rw-r--r--dotnet/Qpid.Codec/Demux/MessageDecoderResult.cs29
-rw-r--r--dotnet/Qpid.Codec/IProtocolCodecFactory.cs37
-rw-r--r--dotnet/Qpid.Codec/IProtocolDecoder.cs41
-rw-r--r--dotnet/Qpid.Codec/IProtocolDecoderOutput.cs35
-rw-r--r--dotnet/Qpid.Codec/IProtocolEncoder.cs41
-rw-r--r--dotnet/Qpid.Codec/IProtocolEncoderOutput.cs37
-rw-r--r--dotnet/Qpid.Codec/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/Qpid.Codec/ProtocolCodecException.cs49
-rw-r--r--dotnet/Qpid.Codec/ProtocolDecoderException.cs70
-rw-r--r--dotnet/Qpid.Codec/ProtocolEncoderException.cs49
-rw-r--r--dotnet/Qpid.Codec/Qpid.Codec.csproj82
-rw-r--r--dotnet/Qpid.Codec/Support/SimpleProtocolDecoderOutput.cs44
-rw-r--r--dotnet/Qpid.Codec/Support/SimpleProtocolEncoderOutput.cs43
-rw-r--r--dotnet/Qpid.Codec/default.build47
-rw-r--r--dotnet/Qpid.Common.Tests/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/Qpid.Common.Tests/Qpid.Common.Tests.csproj87
-rw-r--r--dotnet/Qpid.Common.Tests/Qpid/Collections/TestConsumerProducerQueue.cs85
-rw-r--r--dotnet/Qpid.Common.Tests/Qpid/Collections/TestLinkedHashtable.cs83
-rw-r--r--dotnet/Qpid.Common.Tests/Qpid/Framing/TestAMQType.cs270
-rw-r--r--dotnet/Qpid.Common.Tests/Qpid/Framing/TestEncodingUtils.cs60
-rw-r--r--dotnet/Qpid.Common.Tests/default.build52
-rw-r--r--dotnet/Qpid.Common/AMQChannelClosedException.cs40
-rw-r--r--dotnet/Qpid.Common/AMQConnectionClosedException.cs51
-rw-r--r--dotnet/Qpid.Common/AMQDisconnectedException.cs45
-rw-r--r--dotnet/Qpid.Common/AMQException.cs149
-rw-r--r--dotnet/Qpid.Common/AMQInvalidArgumentException.cs46
-rw-r--r--dotnet/Qpid.Common/AMQInvalidRoutingKeyException.cs46
-rw-r--r--dotnet/Qpid.Common/AMQUndeliveredException.cs59
-rw-r--r--dotnet/Qpid.Common/AssemblySettings.cs160
-rw-r--r--dotnet/Qpid.Common/Collections/BlockingQueue.cs95
-rw-r--r--dotnet/Qpid.Common/Collections/ConsumerProducerQueue.cs113
-rw-r--r--dotnet/Qpid.Common/Collections/LinkedBlockingQueue.cs384
-rw-r--r--dotnet/Qpid.Common/Collections/LinkedHashtable.cs327
-rw-r--r--dotnet/Qpid.Common/Collections/SynchronousQueue.cs375
-rw-r--r--dotnet/Qpid.Common/Framing/AMQDataBlockDecoder.cs155
-rw-r--r--dotnet/Qpid.Common/Framing/AMQDataBlockEncoder.cs65
-rw-r--r--dotnet/Qpid.Common/Framing/AMQFrame.cs107
-rw-r--r--dotnet/Qpid.Common/Framing/AMQFrameDecodingException.cs59
-rw-r--r--dotnet/Qpid.Common/Framing/AMQMethodBody.cs93
-rw-r--r--dotnet/Qpid.Common/Framing/AMQMethodBodyFactory.cs45
-rw-r--r--dotnet/Qpid.Common/Framing/AMQProtocolHeaderException.cs39
-rw-r--r--dotnet/Qpid.Common/Framing/AMQType.cs700
-rw-r--r--dotnet/Qpid.Common/Framing/AMQTypeMap.cs75
-rw-r--r--dotnet/Qpid.Common/Framing/AMQTypedValue.cs76
-rw-r--r--dotnet/Qpid.Common/Framing/BasicContentHeaderProperties.cs290
-rw-r--r--dotnet/Qpid.Common/Framing/CompositeAMQDataBlock.cs85
-rw-r--r--dotnet/Qpid.Common/Framing/ContentBody.cs100
-rw-r--r--dotnet/Qpid.Common/Framing/ContentBodyFactory.cs53
-rw-r--r--dotnet/Qpid.Common/Framing/ContentHeaderBody.cs118
-rw-r--r--dotnet/Qpid.Common/Framing/ContentHeaderBodyFactory.cs53
-rw-r--r--dotnet/Qpid.Common/Framing/ContentHeaderPropertiesFactory.cs63
-rw-r--r--dotnet/Qpid.Common/Framing/EncodingUtils.cs460
-rw-r--r--dotnet/Qpid.Common/Framing/FieldTable.cs633
-rw-r--r--dotnet/Qpid.Common/Framing/HeartbeatBody.cs64
-rw-r--r--dotnet/Qpid.Common/Framing/HeartbeatBodyFactory.cs32
-rw-r--r--dotnet/Qpid.Common/Framing/IBody.cs63
-rw-r--r--dotnet/Qpid.Common/Framing/IBodyFactory.cs38
-rw-r--r--dotnet/Qpid.Common/Framing/IContentHeaderProperties.cs65
-rw-r--r--dotnet/Qpid.Common/Framing/IDataBlock.cs47
-rw-r--r--dotnet/Qpid.Common/Framing/IEncodableAMQDataBlock.cs31
-rw-r--r--dotnet/Qpid.Common/Framing/ProtocolInitiation.cs158
-rw-r--r--dotnet/Qpid.Common/Properties/AssemblyInfo.cs52
-rw-r--r--dotnet/Qpid.Common/Protocol/AMQConstant.cs100
-rw-r--r--dotnet/Qpid.Common/Qpid.Common.csproj104
-rw-r--r--dotnet/Qpid.Common/amqp.xml3929
-rw-r--r--dotnet/Qpid.Common/build.xml95
-rw-r--r--dotnet/Qpid.Common/default.build49
-rw-r--r--dotnet/Qpid.Common/lib/log4net/log4net-licence.txt201
-rw-r--r--dotnet/Qpid.Common/lib/log4net/log4net.dllbin0 -> 266240 bytes
-rw-r--r--dotnet/Qpid.Common/lib/log4net/log4net.xml28676
-rw-r--r--dotnet/Qpid.Common/lib/saxon/saxon-licence.txt471
-rw-r--r--dotnet/Qpid.Common/lib/saxon/saxon8.jarbin0 -> 3118502 bytes
-rw-r--r--dotnet/Qpid.Common/lib/seclib-1.0.0/Org.Mentalis.Security.dllbin0 -> 184320 bytes
-rw-r--r--dotnet/Qpid.Common/lib/seclib-1.0.0/seclib-license.txt13
-rw-r--r--dotnet/Qpid.Common/resources/registry.template24
-rw-r--r--dotnet/Qpid.Common/stylesheets/csharp.xsl251
-rw-r--r--dotnet/Qpid.Common/stylesheets/framing.xsl65
-rw-r--r--dotnet/Qpid.Common/stylesheets/java.xsl230
-rw-r--r--dotnet/Qpid.Common/stylesheets/prepare1.xsl109
-rw-r--r--dotnet/Qpid.Common/stylesheets/prepare2.xsl68
-rw-r--r--dotnet/Qpid.Common/stylesheets/prepare3.xsl64
-rw-r--r--dotnet/Qpid.Common/stylesheets/readme.txt52
-rw-r--r--dotnet/Qpid.Common/stylesheets/registry.xsl33
-rw-r--r--dotnet/Qpid.Common/stylesheets/utils.xsl185
-rw-r--r--dotnet/Qpid.Integration.Tests/Properties/AssemblyInfo.cs53
-rwxr-xr-xdotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj124
-rw-r--r--dotnet/Qpid.Integration.Tests/README.txt3
-rw-r--r--dotnet/Qpid.Integration.Tests/default.build69
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Assertion.cs39
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Assertion.csx39
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/AssertionBase.csx65
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/BrokerLifecycleAware.csx67
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/CauseFailure.csx41
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/CauseFailureUserPrompt.csx63
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Circuit.cs102
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Circuit.csx103
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/CircuitEnd.csx86
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/CircuitEndBase.csx146
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/ExceptionMonitor.csx184
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.cs282
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.csx272
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/LocalCircuitFactory.csx301
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/MessageMonitor.csx102
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/MessagingTestConfigProperties.csx652
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/NotApplicableAssertion.csx111
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Publisher.cs65
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Publisher.csx72
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/README.txt3
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Receiver.cs80
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/Receiver.csx88
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/TestClientDetails.cs84
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/TestClientDetails.csx82
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/TestModel.cs657
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/TestUtils.csx188
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/alljava.csx7851
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchFailureException.csx45
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchThread.csx117
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchronizer.csx66
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/clocksynch/LocalClockSynchronizer.csx70
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/clocksynch/UDPClockSynchronizer.csx453
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClient.csx493
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientCircuitEnd.csx312
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientControlledTest.csx104
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalCircuitImpl.csx290
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalPublisherImpl.csx164
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalReceiverImpl.csx137
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/sequencers/BaseCircuitFactory.csx128
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.cs85
-rw-r--r--dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.csx99
-rw-r--r--dotnet/Qpid.Integration.Tests/interactive/FailoverTest.cs397
-rw-r--r--dotnet/Qpid.Integration.Tests/interactive/SendReceiveTest.cs181
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/InteropClientTestCase.cs87
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase1DummyRun.cs89
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase2BasicP2P.cs205
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase3BasicPubSub.cs244
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase4P2PMessageSize.cs244
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase5PubSubMessageSize.cs252
-rw-r--r--dotnet/Qpid.Integration.Tests/interop/TestClient.cs381
-rw-r--r--dotnet/Qpid.Integration.Tests/log4net.config69
-rw-r--r--dotnet/Qpid.Integration.Tests/old/ServiceProvidingClient.tmp150
-rw-r--r--dotnet/Qpid.Integration.Tests/old/ServiceRequestingClient.tmp182
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/BaseMessagingTestFixture.cs280
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/ChannelQueueTest.cs237
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/CommitRollbackTest.cs261
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/ConnectionTest.cs73
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/DurableSubscriptionTest.cs166
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/HeadersExchangeTest.cs282
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/MandatoryMessageTest.cs149
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/ProducerMultiConsumerTest.cs167
-rwxr-xr-xdotnet/Qpid.Integration.Tests/testcases/Qpid.Integration.Tests.csproj64
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/QueueBrowsingTest.cs121
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/SslConnectionTest.cs64
-rw-r--r--dotnet/Qpid.Integration.Tests/testcases/SustainedTest.cs109
-rw-r--r--dotnet/Qpid.Messaging/AcknowledgeMode.cs42
-rw-r--r--dotnet/Qpid.Messaging/ChannelLimitReachedException.cs60
-rw-r--r--dotnet/Qpid.Messaging/DeliveryMode.cs28
-rw-r--r--dotnet/Qpid.Messaging/ExchangeClassConstants.cs29
-rw-r--r--dotnet/Qpid.Messaging/ExchangeNameDefaults.cs42
-rw-r--r--dotnet/Qpid.Messaging/IBytesMessage.cs63
-rw-r--r--dotnet/Qpid.Messaging/IChannel.cs280
-rw-r--r--dotnet/Qpid.Messaging/ICloseable.cs38
-rw-r--r--dotnet/Qpid.Messaging/IConnection.cs55
-rw-r--r--dotnet/Qpid.Messaging/IConnectionFactory.cs28
-rw-r--r--dotnet/Qpid.Messaging/IConnectionListener.cs59
-rw-r--r--dotnet/Qpid.Messaging/IFieldTable.cs42
-rw-r--r--dotnet/Qpid.Messaging/IHeaders.cs67
-rw-r--r--dotnet/Qpid.Messaging/IMessage.cs97
-rw-r--r--dotnet/Qpid.Messaging/IMessageConsumer.cs79
-rw-r--r--dotnet/Qpid.Messaging/IMessagePublisher.cs92
-rw-r--r--dotnet/Qpid.Messaging/ITextMessage.cs27
-rw-r--r--dotnet/Qpid.Messaging/MessageConsumerBuilder.cs113
-rw-r--r--dotnet/Qpid.Messaging/MessageNotReadableException.cs39
-rw-r--r--dotnet/Qpid.Messaging/MessageNotWritableException.cs38
-rw-r--r--dotnet/Qpid.Messaging/MessagePublisherBuilder.cs91
-rw-r--r--dotnet/Qpid.Messaging/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/Qpid.Messaging/Qpid.Messaging.csproj115
-rw-r--r--dotnet/Qpid.Messaging/QpidException.cs43
-rw-r--r--dotnet/Qpid.Messaging/ResourceAllocationException.cs39
-rw-r--r--dotnet/Qpid.Messaging/default.build45
-rw-r--r--dotnet/Qpid.NET.FxCop16775
-rw-r--r--dotnet/Qpid.NET.sln116
-rw-r--r--dotnet/Qpid.Sasl.Tests/App.config33
-rw-r--r--dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs72
-rw-r--r--dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs90
-rw-r--r--dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs249
-rw-r--r--dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs71
-rw-r--r--dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs88
-rw-r--r--dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj86
-rw-r--r--dotnet/Qpid.Sasl.Tests/SaslTests.cs133
-rw-r--r--dotnet/Qpid.Sasl.Tests/TestClientFactory.cs75
-rw-r--r--dotnet/Qpid.Sasl.Tests/default.build52
-rw-r--r--dotnet/Qpid.Sasl/Callbacks.cs139
-rw-r--r--dotnet/Qpid.Sasl/Configuration/SaslConfiguration.cs90
-rw-r--r--dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs84
-rw-r--r--dotnet/Qpid.Sasl/DefaultClientFactory.cs99
-rw-r--r--dotnet/Qpid.Sasl/ISaslCallbackHandler.cs35
-rw-r--r--dotnet/Qpid.Sasl/ISaslClient.cs42
-rw-r--r--dotnet/Qpid.Sasl/ISaslClientFactory.cs40
-rw-r--r--dotnet/Qpid.Sasl/MD5HMAC.cs115
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs69
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs93
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs91
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs576
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/ExternalSaslClient.cs69
-rw-r--r--dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs81
-rw-r--r--dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/Qpid.Sasl/Qpid.Sasl.csproj73
-rw-r--r--dotnet/Qpid.Sasl/Sasl.cs115
-rw-r--r--dotnet/Qpid.Sasl/SaslClient.cs145
-rw-r--r--dotnet/Qpid.Sasl/SaslException.cs56
-rw-r--r--dotnet/Qpid.Sasl/SaslProperties.cs42
-rw-r--r--dotnet/Qpid.Sasl/default.build45
-rw-r--r--dotnet/README.txt68
-rw-r--r--dotnet/RELEASE_NOTES.txt11
-rw-r--r--dotnet/TestClient/Program.cs30
-rw-r--r--dotnet/TestClient/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/TestClient/TestClient.csproj115
-rw-r--r--dotnet/TestClient/default.build47
-rw-r--r--dotnet/TopicListener/Program.cs30
-rw-r--r--dotnet/TopicListener/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/TopicListener/TopicListener.csproj115
-rw-r--r--dotnet/TopicListener/default.build47
-rw-r--r--dotnet/TopicPublisher/Program.cs30
-rw-r--r--dotnet/TopicPublisher/Properties/AssemblyInfo.cs53
-rw-r--r--dotnet/TopicPublisher/TopicPublisher.csproj111
-rw-r--r--dotnet/TopicPublisher/default.build47
-rw-r--r--dotnet/build-framing.bat23
-rwxr-xr-xdotnet/build-mono21
-rw-r--r--dotnet/build-msbuild.bat22
-rwxr-xr-xdotnet/build-nant-release55
-rw-r--r--dotnet/build-nant.bat22
-rw-r--r--dotnet/client-010/App.config34
-rw-r--r--dotnet/client-010/LICENSE.txt757
-rw-r--r--dotnet/client-010/NOTICE.txt32
-rw-r--r--dotnet/client-010/README.txt69
-rw-r--r--dotnet/client-010/addins/ExcelAddIn/Excel.exe.config12
-rw-r--r--dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.cs290
-rw-r--r--dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.csproj89
-rw-r--r--dotnet/client-010/addins/ExcelAddIn/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/client-010/addins/ExcelAddInMessageProcessor/ExcelAddInMessageProcessor.csproj86
-rw-r--r--dotnet/client-010/addins/ExcelAddInMessageProcessor/Processor.cs44
-rw-r--r--dotnet/client-010/addins/ExcelAddInMessageProcessor/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/client-010/addins/ExcelAddInProducer/ExcelAddInProducer.csproj83
-rw-r--r--dotnet/client-010/addins/ExcelAddInProducer/Program.cs62
-rw-r--r--dotnet/client-010/addins/ExcelAddInProducer/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/addins/README.txt29
-rw-r--r--dotnet/client-010/client/Client.csproj242
-rw-r--r--dotnet/client-010/client/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/client-010/client/client.sln129
-rw-r--r--dotnet/client-010/client/client.suobin0 -> 572415 bytes
-rw-r--r--dotnet/client-010/client/client/Client.cs195
-rw-r--r--dotnet/client-010/client/client/ClientConnectionDelegate.cs128
-rw-r--r--dotnet/client-010/client/client/ClientInterface.cs59
-rw-r--r--dotnet/client-010/client/client/ClientSession.cs109
-rw-r--r--dotnet/client-010/client/client/ClientSessionDelegate.cs55
-rw-r--r--dotnet/client-010/client/client/ClosedListenerInterface.cs29
-rw-r--r--dotnet/client-010/client/client/ErrorCode.cs140
-rw-r--r--dotnet/client-010/client/client/IClient.cs82
-rw-r--r--dotnet/client-010/client/client/IClientSession.cs39
-rw-r--r--dotnet/client-010/client/client/IClosedListener.cs29
-rw-r--r--dotnet/client-010/client/client/IMessage.cs48
-rw-r--r--dotnet/client-010/client/client/IMessageListener.cs31
-rw-r--r--dotnet/client-010/client/client/Message.cs131
-rw-r--r--dotnet/client-010/client/default.build46
-rw-r--r--dotnet/client-010/client/transport/Binary.cs129
-rw-r--r--dotnet/client-010/client/transport/Binding.cs34
-rw-r--r--dotnet/client-010/client/transport/Channel.cs174
-rw-r--r--dotnet/client-010/client/transport/ChannelDelegate.cs41
-rw-r--r--dotnet/client-010/client/transport/ClientDelegate.cs35
-rw-r--r--dotnet/client-010/client/transport/Connection.cs168
-rw-r--r--dotnet/client-010/client/transport/ConnectionDelegate.cs108
-rw-r--r--dotnet/client-010/client/transport/Field.cs74
-rw-r--r--dotnet/client-010/client/transport/Future.cs38
-rw-r--r--dotnet/client-010/client/transport/Header.cs83
-rw-r--r--dotnet/client-010/client/transport/IBinding.cs34
-rw-r--r--dotnet/client-010/client/transport/IFuture.cs38
-rw-r--r--dotnet/client-010/client/transport/IProtocolDelegate.cs37
-rw-r--r--dotnet/client-010/client/transport/IProtocolEvent.cs42
-rw-r--r--dotnet/client-010/client/transport/IReceiver.cs38
-rw-r--r--dotnet/client-010/client/transport/ISender.cs32
-rw-r--r--dotnet/client-010/client/transport/ISession.cs73
-rw-r--r--dotnet/client-010/client/transport/Method.cs150
-rw-r--r--dotnet/client-010/client/transport/ProtocolDelegate.cs37
-rw-r--r--dotnet/client-010/client/transport/ProtocolError.cs85
-rw-r--r--dotnet/client-010/client/transport/ProtocolEvent.cs42
-rw-r--r--dotnet/client-010/client/transport/ProtocolHeader.cs124
-rw-r--r--dotnet/client-010/client/transport/Range.cs117
-rw-r--r--dotnet/client-010/client/transport/RangeSet.cs150
-rw-r--r--dotnet/client-010/client/transport/ReceivedPayload.cs43
-rw-r--r--dotnet/client-010/client/transport/Receiver.cs38
-rw-r--r--dotnet/client-010/client/transport/Sender.cs32
-rw-r--r--dotnet/client-010/client/transport/Session.cs522
-rw-r--r--dotnet/client-010/client/transport/SessionDelegate.cs126
-rw-r--r--dotnet/client-010/client/transport/Struct.cs121
-rw-r--r--dotnet/client-010/client/transport/codec/AbstractDecoder.cs399
-rw-r--r--dotnet/client-010/client/transport/codec/AbstractEncoder.cs590
-rw-r--r--dotnet/client-010/client/transport/codec/Decoder.cs72
-rw-r--r--dotnet/client-010/client/transport/codec/Encodable.cs37
-rw-r--r--dotnet/client-010/client/transport/codec/Encoder.cs70
-rw-r--r--dotnet/client-010/client/transport/codec/IDecoder.cs72
-rw-r--r--dotnet/client-010/client/transport/codec/IEncodable.cs37
-rw-r--r--dotnet/client-010/client/transport/codec/IEncoder.cs70
-rw-r--r--dotnet/client-010/client/transport/codec/MSDecoder.cs110
-rw-r--r--dotnet/client-010/client/transport/codec/MSEncoder.cs172
-rw-r--r--dotnet/client-010/client/transport/exception/ConnectionException.cs49
-rw-r--r--dotnet/client-010/client/transport/exception/ExceptionArgs.cs41
-rw-r--r--dotnet/client-010/client/transport/exception/ProtocolVersionException.cs59
-rw-r--r--dotnet/client-010/client/transport/exception/SessionClosedException.cs38
-rw-r--r--dotnet/client-010/client/transport/exception/SessionException.cs45
-rw-r--r--dotnet/client-010/client/transport/exception/TransportException.cs46
-rw-r--r--dotnet/client-010/client/transport/network/Assembler.cs254
-rw-r--r--dotnet/client-010/client/transport/network/Disassembler.cs222
-rw-r--r--dotnet/client-010/client/transport/network/Frame.cs143
-rw-r--r--dotnet/client-010/client/transport/network/IIoSender.cs28
-rw-r--r--dotnet/client-010/client/transport/network/INetworkDelegate.cs40
-rw-r--r--dotnet/client-010/client/transport/network/INetworkEvent.cs32
-rw-r--r--dotnet/client-010/client/transport/network/InputHandler.cs266
-rw-r--r--dotnet/client-010/client/transport/network/NetworkDelegate.cs40
-rw-r--r--dotnet/client-010/client/transport/network/NetworkEvent.cs32
-rw-r--r--dotnet/client-010/client/transport/network/io/IIoSender.cs28
-rw-r--r--dotnet/client-010/client/transport/network/io/IIoTransport.cs57
-rw-r--r--dotnet/client-010/client/transport/network/io/IoReceiver.cs185
-rw-r--r--dotnet/client-010/client/transport/network/io/IoSSLTransport.cs227
-rw-r--r--dotnet/client-010/client/transport/network/io/IoSender.cs137
-rw-r--r--dotnet/client-010/client/transport/network/io/IoTransport.cs141
-rw-r--r--dotnet/client-010/client/transport/util/ByteEncoder.cs218
-rw-r--r--dotnet/client-010/client/transport/util/CircularBuffer.cs132
-rw-r--r--dotnet/client-010/client/transport/util/Functions.cs41
-rw-r--r--dotnet/client-010/client/transport/util/Logger.cs114
-rw-r--r--dotnet/client-010/client/transport/util/ResultFuture.cs80
-rw-r--r--dotnet/client-010/client/transport/util/Serial.cs94
-rw-r--r--dotnet/client-010/client/transport/util/UUID.cs129
-rw-r--r--dotnet/client-010/default.build275
-rw-r--r--dotnet/client-010/demo/Demo.csproj110
-rw-r--r--dotnet/client-010/demo/Program.cs126
-rw-r--r--dotnet/client-010/demo/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/demo/Properties/Resources.Designer.cs84
-rw-r--r--dotnet/client-010/demo/Properties/Resources.resx137
-rw-r--r--dotnet/client-010/demo/Properties/Settings.Designer.cs47
-rw-r--r--dotnet/client-010/demo/Properties/Settings.settings27
-rw-r--r--dotnet/client-010/demo/default.build48
-rw-r--r--dotnet/client-010/examples/direct/example-direct-Listener/Listener.cs117
-rw-r--r--dotnet/client-010/examples/direct/example-direct-Listener/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/direct/example-direct-Listener/default.build48
-rw-r--r--dotnet/client-010/examples/direct/example-direct-Listener/example-direct-Listener.csproj85
-rw-r--r--dotnet/client-010/examples/direct/example-direct-producer/Producer.cs92
-rw-r--r--dotnet/client-010/examples/direct/example-direct-producer/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/direct/example-direct-producer/default.build48
-rw-r--r--dotnet/client-010/examples/direct/example-direct-producer/example-direct-producer.csproj85
-rw-r--r--dotnet/client-010/examples/direct/verify37
-rw-r--r--dotnet/client-010/examples/direct/verify.in14
-rw-r--r--dotnet/client-010/examples/direct/verify_cpp_dotnet29
-rw-r--r--dotnet/client-010/examples/direct/verify_cpp_dotnet.in14
-rw-r--r--dotnet/client-010/examples/direct/verify_dotnet_cpp29
-rw-r--r--dotnet/client-010/examples/direct/verify_dotnet_cpp.in15
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Listener/Listener.cs126
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Listener/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Listener/default.build48
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Listener/example-fanout-Listener.csproj85
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Producer/Producer.cs89
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Producer/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Producer/default.build48
-rw-r--r--dotnet/client-010/examples/fanout/example-fanout-Producer/example-fanout-Producer.csproj85
-rw-r--r--dotnet/client-010/examples/fanout/verify36
-rw-r--r--dotnet/client-010/examples/fanout/verify.in14
-rw-r--r--dotnet/client-010/examples/fanout/verify_cpp_dotnet30
-rw-r--r--dotnet/client-010/examples/fanout/verify_cpp_dotnet.in14
-rw-r--r--dotnet/client-010/examples/fanout/verify_dotnet_cpp31
-rw-r--r--dotnet/client-010/examples/fanout/verify_dotnet_cpp.in15
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Listener.cs143
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/default.build48
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/example-pub-sub-Listener.csproj85
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Publisher.cs98
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/default.build48
-rw-r--r--dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/example-pub-sub-Publisher.csproj85
-rw-r--r--dotnet/client-010/examples/pub-sub/verify36
-rw-r--r--dotnet/client-010/examples/pub-sub/verify.in95
-rw-r--r--dotnet/client-010/examples/pub-sub/verify_cpp_dotnet31
-rw-r--r--dotnet/client-010/examples/pub-sub/verify_cpp_dotnet.in55
-rw-r--r--dotnet/client-010/examples/pub-sub/verify_dotnet_cpp30
-rw-r--r--dotnet/client-010/examples/pub-sub/verify_dotnet_cpp.in99
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Client/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Client/RequestResponseClient.cs142
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Client/default.build48
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Client/example-request-response-Client.csproj85
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Server/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Server/Server.cs141
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Server/default.build48
-rw-r--r--dotnet/client-010/examples/request-response/example-request-response-Server/example-request-response-Server.csproj85
-rw-r--r--dotnet/client-010/examples/request-response/verify36
-rw-r--r--dotnet/client-010/examples/request-response/verify.in16
-rw-r--r--dotnet/client-010/examples/request-response/verify_cpp_dotnet31
-rw-r--r--dotnet/client-010/examples/request-response/verify_cpp_dotnet.in17
-rw-r--r--dotnet/client-010/examples/request-response/verify_dotnet_cpp31
-rw-r--r--dotnet/client-010/examples/request-response/verify_dotnet_cpp.in18
-rw-r--r--dotnet/client-010/gentool/Composite.tpl291
-rw-r--r--dotnet/client-010/gentool/Constant.tpl37
-rw-r--r--dotnet/client-010/gentool/Enum.tpl59
-rw-r--r--dotnet/client-010/gentool/IInvoker.tpl57
-rw-r--r--dotnet/client-010/gentool/Invoker.tpl67
-rw-r--r--dotnet/client-010/gentool/MethodDelegate.tpl35
-rw-r--r--dotnet/client-010/gentool/Option.tpl42
-rw-r--r--dotnet/client-010/gentool/StructFactory.tpl64
-rw-r--r--dotnet/client-010/gentool/Type.tpl103
-rw-r--r--dotnet/client-010/gentool/build.xml52
-rw-r--r--dotnet/client-010/gentool/codegen86
-rw-r--r--dotnet/client-010/gentool/dotnetgenutil.py271
-rw-r--r--dotnet/client-010/lib/log4net/log4net-licence.txt201
-rw-r--r--dotnet/client-010/lib/log4net/log4net.dllbin0 -> 266240 bytes
-rw-r--r--dotnet/client-010/lib/log4net/log4net.xml28676
-rw-r--r--dotnet/client-010/lib/nunit/nunit-licence.txt23
-rw-r--r--dotnet/client-010/lib/nunit/nunit.framework.dllbin0 -> 45056 bytes
-rw-r--r--dotnet/client-010/lib/plossum/C5-License.txt27
-rw-r--r--dotnet/client-010/lib/plossum/C5.dllbin0 -> 274432 bytes
-rw-r--r--dotnet/client-010/lib/plossum/Plossum CommandLine.dllbin0 -> 98304 bytes
-rw-r--r--dotnet/client-010/lib/plossum/license.txt28
-rw-r--r--dotnet/client-010/log.xml46
-rw-r--r--dotnet/client-010/management/console/AbstractConsole.cs45
-rw-r--r--dotnet/client-010/management/console/Agent.cs75
-rw-r--r--dotnet/client-010/management/console/Broker.cs351
-rw-r--r--dotnet/client-010/management/console/BrokerURL.cs71
-rw-r--r--dotnet/client-010/management/console/ClassKey.cs107
-rw-r--r--dotnet/client-010/management/console/Console.cs46
-rw-r--r--dotnet/client-010/management/console/MethodResult.cs67
-rw-r--r--dotnet/client-010/management/console/ObjectID.cs88
-rw-r--r--dotnet/client-010/management/console/QMFEvent.cs74
-rw-r--r--dotnet/client-010/management/console/QMFObject.cs294
-rw-r--r--dotnet/client-010/management/console/SchemaArgument.cs59
-rw-r--r--dotnet/client-010/management/console/SchemaClass.cs141
-rw-r--r--dotnet/client-010/management/console/SchemaMethod.cs66
-rw-r--r--dotnet/client-010/management/console/SchemaProperty.cs59
-rw-r--r--dotnet/client-010/management/console/SchemaStatistic.cs54
-rw-r--r--dotnet/client-010/management/console/SchemaVariable.cs84
-rw-r--r--dotnet/client-010/management/console/SequenceManager.cs62
-rw-r--r--dotnet/client-010/management/console/Session.cs796
-rw-r--r--dotnet/client-010/management/console/Util.cs150
-rw-r--r--dotnet/client-010/management/console/XMLUtil.cs127
-rw-r--r--dotnet/client-010/management/console/console.csproj101
-rw-r--r--dotnet/client-010/management/console/console.sln46
-rw-r--r--dotnet/client-010/management/console/default.build54
-rw-r--r--dotnet/client-010/perftest/PerfTest.cs715
-rw-r--r--dotnet/client-010/perftest/Properties/AssemblyInfo.cs54
-rw-r--r--dotnet/client-010/perftest/README.txt38
-rw-r--r--dotnet/client-010/perftest/default.build50
-rw-r--r--dotnet/client-010/perftest/perftest.csproj92
-rw-r--r--dotnet/client-010/test/Helpers/ConfigHelpers.cs65
-rw-r--r--dotnet/client-010/test/Properties/AssemblyInfo.cs56
-rw-r--r--dotnet/client-010/test/Qpid Test.dll.config31
-rw-r--r--dotnet/client-010/test/Test.csproj102
-rw-r--r--dotnet/client-010/test/default.build55
-rw-r--r--dotnet/client-010/test/interop/Admin.cs90
-rw-r--r--dotnet/client-010/test/interop/ApplicationHeaders.cs83
-rw-r--r--dotnet/client-010/test/interop/ConnectionTests.cs80
-rw-r--r--dotnet/client-010/test/interop/Message.cs180
-rw-r--r--dotnet/client-010/test/interop/TestCase.cs96
-rw-r--r--dotnet/client-010/test/transport/util/ByteEncoderTest.cs106
-rw-r--r--dotnet/client-010/test/transport/util/CircularBufferTest.cs89
-rw-r--r--dotnet/client-010/test/transport/util/ResultFutureTest.cs103
-rw-r--r--dotnet/client-010/test/transport/util/SerialTest.cs75
-rw-r--r--dotnet/client-010/test/transport/util/UUIDTest.cs64
-rw-r--r--dotnet/client-010/wcf/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/ConfigDemo.suobin0 -> 23552 bytes
-rw-r--r--dotnet/client-010/wcf/demo/Demo.suobin0 -> 33280 bytes
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Form1.Designer.cs185
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Form1.cs96
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Form1.resx143
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Program.cs41
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.Designer.cs92
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.resx137
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.Designer.cs51
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.settings27
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingClient/wcBookingClient.csproj123
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/Booking.cs62
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/IBooking.cs43
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/Order.cs45
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/Program.cs98
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/Receipt.cs46
-rw-r--r--dotnet/client-010/wcf/demo/wcfBookingServer/wcfBookingServer.csproj97
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/App.config56
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/HelloClient.cs36
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/IHelloService.cs33
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/Program.cs48
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloClient/wcfHelloClient.csproj85
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/App.config64
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/HelloService.cs34
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/IHelloService.cs32
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/Program.cs47
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/wcfHelloServer/wcfHelloServer.csproj87
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/IUpperCase.cs31
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/Program.cs113
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/Properties/AssemblyInfo.cs57
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/QpidBindingConfigurationElement.cs205
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/UpperCase.cs33
-rw-r--r--dotnet/client-010/wcf/demo/wcfRPC/wcfRPC.csproj93
-rw-r--r--dotnet/client-010/wcf/model/CommunicationOperation.cs31
-rw-r--r--dotnet/client-010/wcf/model/QpidBinding.cs185
-rw-r--r--dotnet/client-010/wcf/model/QpidChannelBase.cs167
-rw-r--r--dotnet/client-010/wcf/model/QpidChannelFactory.cs74
-rw-r--r--dotnet/client-010/wcf/model/QpidChannelListener.cs79
-rw-r--r--dotnet/client-010/wcf/model/QpidChannelListenerBase.cs111
-rw-r--r--dotnet/client-010/wcf/model/QpidInputChannel.cs218
-rw-r--r--dotnet/client-010/wcf/model/QpidInputChannelBase.cs101
-rw-r--r--dotnet/client-010/wcf/model/QpidOutputChannel.cs89
-rw-r--r--dotnet/client-010/wcf/model/QpidOutputChannelBase.cs77
-rw-r--r--dotnet/client-010/wcf/model/QpidTransportBindingElement.cs186
-rw-r--r--dotnet/client-010/wcf/model/QpidTransportElement.cs183
-rw-r--r--dotnet/client-010/wcf/wcf.csproj79
-rw-r--r--dotnet/client-010/wcf/wcf.sln70
-rw-r--r--dotnet/client-010/wcf/wcf.suobin0 -> 105984 bytes
-rw-r--r--dotnet/default.build252
-rwxr-xr-xextras/qmf/setup.py4
-rw-r--r--extras/qmf/src/py/qmf/console.py54
-rw-r--r--extras/qmf/src/py/qmf2/__init__.py (renamed from extras/qmf/src/py/qmf2-prototype/__init__.py)0
-rw-r--r--extras/qmf/src/py/qmf2/agent.py (renamed from extras/qmf/src/py/qmf2-prototype/agent.py)0
-rw-r--r--extras/qmf/src/py/qmf2/common.py (renamed from extras/qmf/src/py/qmf2-prototype/common.py)0
-rw-r--r--extras/qmf/src/py/qmf2/console.py (renamed from extras/qmf/src/py/qmf2-prototype/console.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/__init__.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/__init__.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/agent_discovery.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/agent_discovery.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/agent_test.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/agent_test.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/async_method.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/async_method.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/async_query.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/async_query.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/basic_method.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/basic_method.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/basic_query.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/basic_query.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/console_test.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/console_test.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/events.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/events.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/multi_response.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/multi_response.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/obj_gets.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/obj_gets.py)0
-rw-r--r--extras/qmf/src/py/qmf2/tests/subscriptions.py (renamed from extras/qmf/src/py/qmf2-prototype/tests/subscriptions.py)0
-rwxr-xr-xextras/sasl/bootstrap2
-rw-r--r--extras/sasl/configure.ac1
-rw-r--r--extras/sasl/python/Makefile.am3
-rw-r--r--extras/sasl/ruby/Makefile.am2
-rw-r--r--extras/sasl/src/Makefile.am1
-rw-r--r--gentools/build.xml2
-rwxr-xr-xjava/bdbstore/bin/backup.sh40
-rwxr-xr-xjava/bdbstore/bin/storeUpgrade.sh43
-rw-r--r--java/bdbstore/build.xml84
-rwxr-xr-xjava/bdbstore/etc/scripts/bdbbackuptest.sh44
-rwxr-xr-xjava/bdbstore/etc/scripts/bdbtest.sh43
-rw-r--r--java/bdbstore/src/main/java/BDBStoreUpgrade.log4j.xml52
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java59
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringTB.java48
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java344
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java2124
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgrade.java1125
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BindingKey.java62
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ContentTB.java52
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/DatabaseVisitor.java44
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ExchangeTB.java58
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java74
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/MessageContentKey.java42
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/QueueEntryKey.java49
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_4.java44
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_5.java44
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/ExchangeRecord.java53
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/QueueRecord.java66
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/testclient/BackupTestClient.java120
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple.java25
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTupleBindingFactory.java45
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple_4.java76
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_4.java47
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_5.java46
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTupleBindingFactory.java45
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_4.java162
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_5.java77
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTupleBindingFactory.java43
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java46
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple.java25
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTupleBindingFactory.java46
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_4.java72
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_5.java75
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/TupleBindingFactory.java35
-rw-r--r--java/bdbstore/src/resources/backup-log4j.xml65
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java88
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java470
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java232
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java540
-rw-r--r--java/bdbstore/src/test/resources/upgrade/bdbstore-to-upgrade/test-store/00000000.jdbbin1330321 -> 0 bytes
-rw-r--r--java/broker-plugins/access-control/MANIFEST.MF1
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java361
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java15
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java281
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java194
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java229
-rw-r--r--java/broker-plugins/experimental/info/build.xml9
-rw-r--r--java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java9
-rw-r--r--java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java8
-rw-r--r--java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java5
-rwxr-xr-xjava/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd2
-rw-r--r--java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java2
-rw-r--r--java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java148
-rw-r--r--java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java21
-rw-r--r--java/broker-plugins/simple-xml/MANIFEST.MF36
-rw-r--r--java/broker-plugins/simple-xml/build.xml29
-rwxr-xr-xjava/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java687
-rw-r--r--java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java427
-rw-r--r--java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java42
-rw-r--r--java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java57
-rw-r--r--java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java209
-rwxr-xr-xjava/broker/bin/qpid-server8
-rw-r--r--java/broker/bin/qpid-server.bat12
-rw-r--r--java/broker/build.xml4
-rw-r--r--java/broker/etc/access19
-rw-r--r--java/broker/etc/config.xml38
-rw-r--r--java/broker/etc/jmxremote.access23
-rw-r--r--java/broker/etc/passwdVhost19
-rw-r--r--java/broker/etc/qpid-server.conf.jpp3
-rw-r--r--java/broker/etc/virtualhosts.xml2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java76
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java70
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java100
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Broker.java441
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java170
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Main.java665
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java307
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java75
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java56
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java126
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java1
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java81
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java62
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java56
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java90
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java43
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java76
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java263
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java72
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java91
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties93
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java294
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java41
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java365
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java50
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java14
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java115
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java28
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java23
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java147
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java48
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java36
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java84
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java217
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java374
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java53
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java29
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java77
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java221
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java35
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java49
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java407
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java406
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java99
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java89
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java163
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java118
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java213
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java198
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java148
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java155
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java259
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java5
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java47
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java87
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java200
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java202
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/MainTest.java153
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/RunBrokerWithCommand.java132
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java830
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java47
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java29
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java16
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java44
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java18
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java202
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/plugins/MockPluginManager.java56
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java93
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java33
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java146
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java13
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java16
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java12
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java19
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTest.java247
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java756
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java53
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java358
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java269
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexServerTest.java228
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java86
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java49
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java122
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java118
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/stats/StatisticsCounterTest.java144
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java3
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java20
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java84
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java429
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockAction.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java11
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java11
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java11
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java59
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java67
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java271
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java214
-rw-r--r--java/broker/src/test/java/org/apache/qpid/util/MockChannel.java40
-rw-r--r--java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java2
-rw-r--r--java/build.deps103
-rw-r--r--java/build.overrides24
-rw-r--r--java/build.xml32
-rw-r--r--java/client-plugins/.gitignore0
-rw-r--r--java/client-plugins/README.txt21
-rw-r--r--java/client/README.txt2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/pubsub/ConnectionSetup.java4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/pubsub/Publisher.java2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/transport/ExistingSocketConnectorDemo.java171
-rwxr-xr-xjava/client/src/main/java/client.bnd2
-rw-r--r--java/client/src/main/java/org/apache/mina/transport/socket/nio/ExistingSocketConnector.java478
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQAnyDestination.java13
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java156
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnection.java178
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java158
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java75
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java280
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java19
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQDestination.java114
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java447
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java238
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java83
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java17
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java12
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTopic.java75
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java163
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java182
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java60
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java77
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java23
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/ChannelToSessionMap.java20
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java29
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/QpidConnectionMetaData.java9
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java87
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java61
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java35
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java46
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java178
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java61
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java28
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java13
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java67
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java124
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java760
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java103
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java19
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java169
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java3
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java31
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java71
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java8
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java217
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java8
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java129
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java161
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/QpidMessageProperties.java34
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/TypedBytesCodes.java46
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentReader.java674
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentWriter.java370
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java35
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java15
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java258
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java54
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java115
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java256
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties18
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties1
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java30
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java17
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClient.java52
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClientFactory.java52
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java16
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java18
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java168
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java90
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java351
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java63
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/url/URLParser.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java17
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java134
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java60
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java13
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java3
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java7
-rw-r--r--java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java21
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindConnectionFactory.java185
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindQueue.java213
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindTopic.java212
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/README.txt11
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/cluster/Client.java129
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/codec/BasicDeliverTest.java277
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/codec/Client.java133
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/codec/Server.java103
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java35
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/AbstractConfig.java69
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java29
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/Connector.java40
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/ConnectorConfig.java28
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java117
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/flow/ChannelFlowTest.java112
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargePublisher.java196
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargeSubscriber.java167
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/headers/Listener.java117
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/headers/MessageFactory.java175
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/headers/Publisher.java133
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Bind.java273
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Lookup.java196
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Unbind.java166
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/latency/LatencyTest.java153
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/mina/AcceptorTest.java102
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/mina/BlockingAcceptorTest.java93
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/mina/WriterTest.java271
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/multiconsumer/AMQTest.java269
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/pubsub1/TestPublisher.java176
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/pubsub1/TestSubscriber.java122
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/test/unit/client/connection/TestManyConnections.java95
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/PropertiesFileInitialContextFactoryTest.java153
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/example.properties38
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/topic/Config.java243
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/topic/Listener.java141
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/topic/MessageFactory.java155
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/topic/Publisher.java175
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Config.java110
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java45
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java45
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java127
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Start.java44
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java151
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java185
-rw-r--r--java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java125
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java765
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java36
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java5
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java23
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java312
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/security/CallbackHandlerRegistryTest.java185
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java99
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java78
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStreamTest.java86
-rw-r--r--java/client/src/test/java/org/apache/qpid/jms/FailoverPolicyTest.java338
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java9
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java2
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java99
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageUnitTest.java105
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java18
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java19
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java36
-rw-r--r--java/common.xml27
-rwxr-xr-xjava/common/bin/qpid-run13
-rwxr-xr-xjava/common/src/main/java/common.bnd2
-rw-r--r--java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java467
-rw-r--r--java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java227
-rw-r--r--java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java351
-rw-r--r--java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java48
-rw-r--r--java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java272
-rw-r--r--java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java197
-rw-r--r--java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java440
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java547
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java486
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java67
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java1026
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java240
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java488
-rw-r--r--java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java151
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQChannelException.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQConnectionException.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQException.java16
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyBroker.java208
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyClient.java108
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyExchange.java154
-rw-r--r--java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java17
-rw-r--r--java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java334
-rw-r--r--java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java66
-rw-r--r--java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java59
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQBody.java8
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java26
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java57
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java61
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java42
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java8
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java7
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java86
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java90
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java115
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQType.java81
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java13
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java374
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentBody.java59
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java58
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java12
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java7
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java50
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java229
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTable.java215
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java15
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java37
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java5
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java13
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java11
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/Job.java253
-rw-r--r--java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java9
-rw-r--r--java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java29
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java28
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java60
-rw-r--r--java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java216
-rw-r--r--java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java145
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Connection.java114
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java63
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java44
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java46
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java52
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java69
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Session.java184
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java16
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java78
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java1
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java31
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java49
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java18
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java35
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/Transport.java122
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java130
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java92
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java35
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java99
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java223
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java49
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java68
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java231
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java435
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java274
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java90
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java135
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java126
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java49
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java153
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java161
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java16
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java63
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java56
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java37
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/URLHelper.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/FileUtils.java25
-rw-r--r--java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java396
-rw-r--r--java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java157
-rw-r--r--java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java13
-rw-r--r--java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java32
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java214
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java11
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java30
-rw-r--r--java/common/src/test/java/org/apache/qpid/session/TestSession.java277
-rw-r--r--java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java84
-rw-r--r--java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java206
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java107
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/MockSender.java47
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java81
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java144
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java133
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java157
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java92
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java91
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java494
-rw-r--r--java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java82
-rw-r--r--java/common/src/test/java/org/apache/qpid/util/default.properties2
-rw-r--r--java/common/src/test/java/org/apache/qpid/util/mydefaults.properties2
-rw-r--r--java/common/templates/method/version/MethodBodyClass.vm10
-rw-r--r--java/common/templates/model/MethodRegistryClass.vm9
-rw-r--r--java/common/templates/model/version/MethodRegistryClass.vm95
-rw-r--r--java/ivy.xml39
-rw-r--r--java/ivysettings-nexus.xml30
-rw-r--r--java/lib/backport-util-concurrent-2.2.jarbin0 -> 326319 bytes
-rw-r--r--java/lib/bdbstore/README.txt14
-rw-r--r--java/lib/commons-pool-1.4.jarbin0 -> 87077 bytes
-rw-r--r--java/lib/core-3.1.1.jarbin0 -> 3566844 bytes
-rw-r--r--java/lib/geronimo-servlet_2.5_spec-1.2.jarbin0 -> 70593 bytes
-rw-r--r--java/lib/ivy/README.txt11
-rw-r--r--java/lib/javassist.jarbin0 -> 471005 bytes
-rw-r--r--java/lib/jline-0.9.94.jarbin0 -> 87325 bytes
-rw-r--r--java/lib/jsp-2.1.jarbin0 -> 1024681 bytes
-rw-r--r--java/lib/jsp-api-2.1.jarbin0 -> 134910 bytes
-rw-r--r--java/lib/junit-4.4.jarbin0 -> 161477 bytes
-rwxr-xr-xjava/lib/mina-core-1.0.1.jarbin0 -> 313338 bytes
-rwxr-xr-xjava/lib/mina-filter-ssl-1.0.1.jarbin0 -> 28950 bytes
-rw-r--r--java/lib/muse-core-2.2.0.jarbin0 -> 121976 bytes
-rw-r--r--java/lib/muse-platform-mini-2.2.0.jarbin0 -> 8227 bytes
-rw-r--r--java/lib/muse-util-2.2.0.jarbin0 -> 23215 bytes
-rw-r--r--java/lib/muse-util-qname-2.2.0.jarbin0 -> 4968 bytes
-rw-r--r--java/lib/muse-util-xml-2.2.0.jarbin0 -> 19082 bytes
-rw-r--r--java/lib/muse-wsa-soap-2.2.0.jarbin0 -> 25030 bytes
-rw-r--r--java/lib/muse-wsdm-muws-adv-api-2.2.0.jarbin0 -> 4145 bytes
-rw-r--r--java/lib/muse-wsdm-muws-adv-impl-2.2.0.jarbin0 -> 10366 bytes
-rw-r--r--java/lib/muse-wsdm-muws-api-2.2.0.jarbin0 -> 18492 bytes
-rw-r--r--java/lib/muse-wsdm-muws-impl-2.2.0.jarbin0 -> 57860 bytes
-rw-r--r--java/lib/muse-wsdm-wef-api-2.2.0.jarbin0 -> 9125 bytes
-rw-r--r--java/lib/muse-wsdm-wef-impl-2.2.0.jarbin0 -> 18049 bytes
-rw-r--r--java/lib/muse-wsn-api-2.2.0.jarbin0 -> 29692 bytes
-rw-r--r--java/lib/muse-wsn-impl-2.2.0.jarbin0 -> 80531 bytes
-rw-r--r--java/lib/muse-wsrf-api-2.2.0.jarbin0 -> 58684 bytes
-rw-r--r--java/lib/muse-wsrf-impl-2.2.0.jarbin0 -> 127656 bytes
-rw-r--r--java/lib/muse-wsrf-rmd-2.2.0.jarbin0 -> 5625 bytes
-rw-r--r--java/lib/muse-wsx-api-2.2.0.jarbin0 -> 4624 bytes
-rw-r--r--java/lib/muse-wsx-impl-2.2.0.jarbin0 -> 9349 bytes
-rw-r--r--java/lib/poms/backport-util-concurrent-2.2.xml22
-rw-r--r--java/lib/poms/mina-core-1.0.1.xml22
-rw-r--r--java/lib/poms/mina-filter-ssl-1.0.1.xml22
-rw-r--r--java/lib/start.jarbin0 -> 17125 bytes
-rw-r--r--java/lib/wsdl4j-1.6.1.jarbin0 -> 148522 bytes
-rw-r--r--java/lib/xercesImpl-2.8.1.jarbin0 -> 1212965 bytes
-rw-r--r--java/lib/xml-apis-1.3.03.jarbin0 -> 195119 bytes
-rw-r--r--java/management/agent/build.xml27
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/Agent.java706
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/AgentException.java45
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/EventSeverity.java27
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/ManagedEJB.java138
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObject.java52
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObjectBase.java72
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/ManagedPOJO.java90
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFAgent.java34
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFEvent.java42
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFHide.java39
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFObject.java42
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFProperty.java39
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFSeeAlso.java40
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFType.java42
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingContext.java213
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingException.java50
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingUtils.java137
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/ClassBinding.java601
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/EnumBinding.java108
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/ListBinding.java131
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/MapBinding.java95
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/MethodBinding.java91
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/ParameterBinding.java121
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/PropertyBinding.java131
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/QMFTypeBinding.java465
-rw-r--r--java/management/agent/src/main/java/org/apache/qpid/agent/binding/TypeBinding.java46
-rw-r--r--java/management/agent/src/test/java/org/apache/qpid/agent/Crumpet.java70
-rw-r--r--java/management/agent/src/test/java/org/apache/qpid/agent/Muppet.java113
-rw-r--r--java/management/agent/src/test/java/org/apache/qpid/agent/Pikelet.java52
-rw-r--r--java/management/agent/src/test/java/org/apache/qpid/agent/Puppet.java29
-rw-r--r--java/management/client/README.txt42
-rw-r--r--java/management/client/bin/qman-jmx.cmd78
-rw-r--r--java/management/client/bin/qman-jmx.sh76
-rw-r--r--java/management/client/bin/qman-wsdm-start.cmd88
-rw-r--r--java/management/client/bin/qman-wsdm-start.sh89
-rw-r--r--java/management/client/bin/qman-wsdm-stop.cmd37
-rw-r--r--java/management/client/bin/qman-wsdm-stop.sh38
-rw-r--r--java/management/client/build.xml213
-rw-r--r--java/management/client/console/brokers_management.jsp209
-rw-r--r--java/management/client/console/console.jsp122
-rw-r--r--java/management/client/console/error_page.jsp59
-rw-r--r--java/management/client/console/fragments/header.jsp36
-rw-r--r--java/management/client/console/fragments/menu.jsp31
-rw-r--r--java/management/client/console/images/asf-logo.pngbin0 -> 4735 bytes
-rw-r--r--java/management/client/console/images/menu.gifbin0 -> 1953 bytes
-rw-r--r--java/management/client/console/images/menuleft.gifbin0 -> 640 bytes
-rw-r--r--java/management/client/console/images/menuright.gifbin0 -> 1398 bytes
-rw-r--r--java/management/client/console/images/qpid-logo.pngbin0 -> 39056 bytes
-rw-r--r--java/management/client/console/images/style.css202
-rw-r--r--java/management/client/console/jmx_perspective.jsp157
-rw-r--r--java/management/client/console/logging_configuration.jsp241
-rw-r--r--java/management/client/console/resources_management.jsp105
-rw-r--r--java/management/client/console/tbd.jsp48
-rw-r--r--java/management/client/console/wsdm_operations_perspective.jsp174
-rw-r--r--java/management/client/console/wsdm_properties_perspective.jsp218
-rw-r--r--java/management/client/console/wsdm_rmd_perspective.jsp99
-rw-r--r--java/management/client/console/wsdm_wsdl_perspective.jsp99
-rw-r--r--java/management/client/doc/man/qman-jmx17
-rw-r--r--java/management/client/etc/jetty.xml47
-rw-r--r--java/management/client/etc/qman-config.xml68
-rw-r--r--java/management/client/etc/qman-config.xsd63
-rw-r--r--java/management/client/etc/qman.log4j29
-rw-r--r--java/management/client/src/example/ConnectWithBroker.out.ok81
-rw-r--r--java/management/client/src/example/GetMultipleResourceProperties.out.ok262
-rw-r--r--java/management/client/src/example/GetQManResourceMembers.out.ko54
-rw-r--r--java/management/client/src/example/GetQManResourceMembers.out.ok55
-rw-r--r--java/management/client/src/example/GetResourceMetadataDescriptor.out.ok188
-rw-r--r--java/management/client/src/example/GetResourcePropertyDocument.out.ok138
-rw-r--r--java/management/client/src/example/GetResourcePropertyRequest.out.ok588
-rw-r--r--java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources58
-rw-r--r--java/management/client/src/example/GetWsdlMetadata.out.ok1968
-rw-r--r--java/management/client/src/example/PauseAndResumeSubscription.out.ok133
-rw-r--r--java/management/client/src/example/README.txt69
-rw-r--r--java/management/client/src/example/SetResourcePropertiesRequest.out.ok2316
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java140
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java240
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java293
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java179
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java93
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java156
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java111
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java172
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java156
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java88
-rw-r--r--java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java306
-rw-r--r--java/management/client/src/main/java/muse.xml209
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/Messages.java175
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/Names.java216
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/Protocol.java52
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java53
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java280
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java136
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java42
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java485
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java51
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java240
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java64
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java249
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java54
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java53
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java43
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java53
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java109
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java54
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java114
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java52
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java57
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java51
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java39
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java41
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java57
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java157
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java68
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java106
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java314
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java234
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java217
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java33
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java33
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java239
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java38
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java76
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java410
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java35
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java123
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java105
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java833
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java41
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java184
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java493
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java41
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java86
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java454
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java147
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java286
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java295
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java34
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java51
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java105
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java169
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java45
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java101
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java46
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java183
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java249
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java152
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java50
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java412
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java361
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java41
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java42
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java31
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java147
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java168
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java189
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java161
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java68
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java89
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java79
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java109
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java100
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java204
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java117
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java158
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java189
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java114
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java91
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java191
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java185
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java139
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java140
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java130
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java95
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java48
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java76
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java41
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java44
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java68
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java86
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java82
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java219
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java549
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java557
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java104
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java99
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java57
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java135
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java196
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java93
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java140
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java460
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java58
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java79
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java70
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java61
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java72
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java57
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java105
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java68
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java86
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java118
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java57
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java762
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java83
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java75
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java85
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java134
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java202
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java72
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java149
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java34
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java49
-rw-r--r--java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java92
-rw-r--r--java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml23
-rw-r--r--java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml23
-rw-r--r--java/management/client/src/main/java/wsdl/QManAdapter.rmd27
-rw-r--r--java/management/client/src/main/java/wsdl/QManAdapter.wsdl694
-rw-r--r--java/management/client/src/main/java/wsdl/QManWsResource.rmd17
-rw-r--r--java/management/client/src/main/java/wsdl/QManWsResource.wsdl507
-rw-r--r--java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd181
-rw-r--r--java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd169
-rw-r--r--java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd84
-rw-r--r--java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl449
-rw-r--r--java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd577
-rw-r--r--java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd134
-rw-r--r--java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl54
-rw-r--r--java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd48
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl83
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd130
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd325
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl395
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd394
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl269
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd233
-rw-r--r--java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl206
-rw-r--r--java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd185
-rw-r--r--java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd114
-rw-r--r--java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd677
-rw-r--r--java/management/client/src/main/java/wsdl/WsResource.rmd14
-rw-r--r--java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl22
-rw-r--r--java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd46
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java67
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java181
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java163
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java79
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java59
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java44
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java96
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java55
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java187
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java408
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java293
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java147
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java171
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java53
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java269
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java159
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java127
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java59
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java241
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java140
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java143
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java72
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java125
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java105
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java134
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java169
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java580
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java118
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java219
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java61
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java156
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java335
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java204
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java81
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java110
-rw-r--r--java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml32
-rw-r--r--java/management/client/web.xml149
-rw-r--r--java/management/common/src/main/java/management-common.bnd2
-rw-r--r--java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java118
-rw-r--r--java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedConnection.java127
-rw-r--r--java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java121
-rw-r--r--java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/UserManagement.java98
-rw-r--r--java/management/console/build.xml27
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/AbstractConsole.java81
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/Agent.java116
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/Broker.java504
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/ClassKey.java146
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/Console.java51
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/ConsoleException.java48
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/EventSeverity.java37
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/MethodResult.java88
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/ObjectID.java93
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/QMFEvent.java108
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/QMFObject.java423
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaArgument.java65
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaClass.java251
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaMethod.java125
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaProperty.java81
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaStatistic.java88
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SchemaVariable.java185
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/SequenceManager.java57
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/Session.java980
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/Util.java184
-rw-r--r--java/management/console/src/main/java/org/apache/qpid/console/XMLUtil.java155
-rw-r--r--java/management/console/src/test/java/org/apache/qpid/console/ClassKeyTest.java39
-rw-r--r--java/management/eclipse-plugin/META-INF/MANIFEST.MF2
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java2
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java29
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java25
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java2
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/LegacySupportingUserManagement.java132
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java199
-rw-r--r--java/management/tools/qpid-cli/Guide.txt143
-rw-r--r--java/management/tools/qpid-cli/LICENSE225
-rw-r--r--java/management/tools/qpid-cli/NOTICE12
-rw-r--r--java/management/tools/qpid-cli/README.txt64
-rwxr-xr-xjava/management/tools/qpid-cli/bin/qpid-cli35
-rwxr-xr-xjava/management/tools/qpid-cli/bin/qpid-cli.bat28
-rw-r--r--java/management/tools/qpid-cli/build.xml31
-rw-r--r--java/management/tools/qpid-cli/report.property26
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/Command.java33
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/CommandExecutionEngine.java76
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/CommandLineInterpreter.java263
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/Connector.java49
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/ConnectorFactory.java50
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/ReportGenerator.java195
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/CommandImpl.java153
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commanddelete.java199
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandget.java211
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandhelp.java56
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandinfo.java206
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandlist.java232
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandmove.java259
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandset.java260
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandview.java255
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandviewcontent.java248
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/AllObjects.java38
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ConnectionObject.java46
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ExchangeObject.java45
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ObjectNames.java591
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/QueueObject.java67
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/UserManagementObject.java38
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/VirtualHostObject.java47
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOption.java104
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionConstants.java37
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionParser.java231
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfigProperty.java29
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfiguration.java182
-rw-r--r--java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXinfo.java53
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/AllTest.java41
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/ConnectionConstants.java30
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandExecutionEngine.java73
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandLineInterpreter.java80
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/TestConnector.java79
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/TestReportGenerator.java26
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommand.java79
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommanddelete.java79
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandinfo.java77
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandlist.java82
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandmove.java80
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandview.java78
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandviewcontent.java78
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestAllObject.java69
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestConnectionObject.java83
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestExchangeObject.java83
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestObjectNames.java26
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestQueueObject.java83
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestUserManagementObject.java74
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestVirtualHostObject.java84
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOption.java64
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOptionParser.java79
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfigProperty.java26
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfiguration.java64
-rw-r--r--java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXinfo.java30
-rw-r--r--java/maven-settings.xml2
-rw-r--r--java/module.xml140
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java3
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java14
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java207
-rw-r--r--java/resources/NOTICE7
-rw-r--r--java/systests/build.xml12
-rw-r--r--java/systests/etc/config-systests-ServerConfigurationTest-New.xml78
-rw-r--r--java/systests/etc/config-systests-ServerConfigurationTest-Old.xml92
-rw-r--r--java/systests/etc/config-systests-acl-settings.xml26
-rw-r--r--java/systests/etc/config-systests-acl.xml30
-rw-r--r--java/systests/etc/config-systests-aclv2.xml2
-rw-r--r--java/systests/etc/config-systests-bdb-settings.xml26
-rw-r--r--java/systests/etc/config-systests-bdb.xml30
-rw-r--r--java/systests/etc/config-systests-derby.xml2
-rw-r--r--java/systests/etc/config-systests-firewall-2.xml33
-rw-r--r--java/systests/etc/config-systests-firewall-3.xml35
-rw-r--r--java/systests/etc/config-systests-firewall.xml2
-rw-r--r--java/systests/etc/config-systests-settings.xml11
-rw-r--r--java/systests/etc/config-systests.xml2
-rw-r--r--java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml45
-rw-r--r--java/systests/etc/virtualhosts-systests-acl-settings.xml180
-rw-r--r--java/systests/etc/virtualhosts-systests-acl.xml29
-rw-r--r--java/systests/etc/virtualhosts-systests-aclv2.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests-bdb-settings.xml56
-rw-r--r--java/systests/etc/virtualhosts-systests-bdb.xml29
-rw-r--r--java/systests/etc/virtualhosts-systests-derby.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests-firewall.xml2
-rw-r--r--java/systests/etc/virtualhosts-systests.xml2
-rw-r--r--java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java125
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java13
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java82
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java949
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java26
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java159
-rw-r--r--java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java116
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java77
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java102
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java162
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java110
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java90
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java218
-rw-r--r--java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java128
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java15
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java123
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java15
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java55
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java22
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java19
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java247
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java13
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java18
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java611
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java644
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java32
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java542
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java56
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java96
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java95
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java70
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java136
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java154
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java82
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java9
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java15
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java231
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java57
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java22
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java1
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java105
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java26
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java41
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java101
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java25
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java26
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java280
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java7
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java41
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java45
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java51
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java403
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java14
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java182
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java162
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java74
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java308
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java246
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java26
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java22
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java50
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java111
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java507
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java58
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java104
-rw-r--r--java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java141
-rw-r--r--java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java25
-rw-r--r--java/test-profiles/08StandaloneExcludes39
-rwxr-xr-xjava/test-profiles/CPPExcludes35
-rw-r--r--java/test-profiles/CPPTransientExcludes3
-rw-r--r--java/test-profiles/Excludes10
-rwxr-xr-xjava/test-profiles/Java010Excludes55
-rw-r--r--java/test-profiles/JavaBDBExcludes22
-rw-r--r--java/test-profiles/JavaDerbyExcludes21
-rw-r--r--java/test-profiles/JavaExcludes47
-rw-r--r--java/test-profiles/JavaInVMExcludes43
-rw-r--r--java/test-profiles/JavaPre010Excludes56
-rw-r--r--java/test-profiles/JavaStandaloneExcludes55
-rw-r--r--java/test-profiles/JavaTransientExcludes4
-rwxr-xr-xjava/test-profiles/clean-dir25
-rw-r--r--java/test-profiles/cpp.async.testprofile2
-rw-r--r--java/test-profiles/cpp.ssl.excludes7
-rw-r--r--java/test-profiles/cpp.ssl.testprofile4
-rw-r--r--java/test-profiles/cpp.testprofile5
-rw-r--r--java/test-profiles/default.testprofile61
-rw-r--r--java/test-profiles/java-bdb-spawn.0-10.testprofile31
-rw-r--r--java/test-profiles/java-bdb-spawn.0-9-1.testprofile36
-rw-r--r--java/test-profiles/java-bdb.0-10.testprofile32
-rw-r--r--java/test-profiles/java-bdb.0-9-1.testprofile37
-rw-r--r--java/test-profiles/java-dby-spawn.0-10.testprofile29
-rw-r--r--java/test-profiles/java-dby-spawn.0-9-1.testprofile35
-rw-r--r--java/test-profiles/java-dby.0-10.testprofile30
-rw-r--r--java/test-profiles/java-dby.0-9-1.testprofile36
-rw-r--r--java/test-profiles/java-derby.0.10.testprofile29
-rw-r--r--java/test-profiles/java-derby.testprofile33
-rw-r--r--java/test-profiles/java-mms-spawn.0-10.testprofile29
-rw-r--r--java/test-profiles/java-mms-spawn.0-9-1.testprofile30
-rw-r--r--java/test-profiles/java-mms.0-10.testprofile27
-rw-r--r--java/test-profiles/java-mms.0-9-1.testprofile31
-rw-r--r--java/test-profiles/java.0.10.testprofile26
-rw-r--r--java/test-profiles/java.testprofile28
-rw-r--r--java/test-profiles/log4j-test.xml4
-rw-r--r--java/test-profiles/python_tests/Java010PythonExcludes22
-rw-r--r--java/test-profiles/test-provider.properties4
-rw-r--r--java/test-profiles/test_resources/ssl/certstore.jks (renamed from java/test-profiles/test_resources/ssl/java_client_truststore.jks)bin591 -> 591 bytes
-rw-r--r--java/test-profiles/test_resources/ssl/java_broker.crt15
-rw-r--r--java/test-profiles/test_resources/ssl/java_broker.req10
-rw-r--r--java/test-profiles/test_resources/ssl/java_broker_keystore.jksbin2475 -> 0 bytes
-rw-r--r--java/test-profiles/test_resources/ssl/keystore.jks (renamed from java/test-profiles/test_resources/ssl/java_client_keystore.jks)bin4296 -> 4296 bytes
-rw-r--r--java/test-profiles/testprofile.defaults59
-rwxr-xr-xjava/tools/bin/Profile-run-from-source71
-rwxr-xr-xjava/tools/bin/check-qpid-java-env38
-rw-r--r--java/tools/bin/controller132
-rwxr-xr-xjava/tools/bin/perf-report137
-rwxr-xr-xjava/tools/bin/perf_report.sh140
-rw-r--r--[-rwxr-xr-x]java/tools/bin/qpid-bench16
-rwxr-xr-xjava/tools/bin/qpid-python-testkit11
-rwxr-xr-xjava/tools/bin/run-pub28
-rwxr-xr-xjava/tools/bin/run-sub32
-rw-r--r--java/tools/bin/run_pub.sh24
-rw-r--r--java/tools/bin/run_sub.sh25
-rw-r--r--java/tools/bin/set-testkit-env.sh88
-rw-r--r--java/tools/bin/setenv.sh49
-rw-r--r--java/tools/bin/start-consumers119
-rw-r--r--java/tools/bin/start-producers136
-rw-r--r--java/tools/etc/perf-report.gnu42
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/Clock.java92
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java12
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java166
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java224
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java256
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java422
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/TestParams.java70
-rw-r--r--java/upload.xml90
-rw-r--r--packaging/windows/INSTALL_NOTES.html6
-rw-r--r--packaging/windows/installer.proj21
-rw-r--r--python/qpid/client.py2
-rw-r--r--python/qpid/codec010.py17
-rw-r--r--python/qpid/messaging/driver.py15
-rw-r--r--python/qpid/messaging/endpoints.py5
-rw-r--r--python/qpid/messaging/transports.py18
-rw-r--r--python/qpid/tests/messaging/endpoints.py25
-rw-r--r--python/qpid/util.py54
-rwxr-xr-xpython/setup.py2
-rwxr-xr-xruby/LICENSE.txt203
-rw-r--r--ruby/Makefile47
-rw-r--r--ruby/NOTICE.txt19
-rw-r--r--ruby/README.txt26
-rw-r--r--ruby/RELEASE_NOTES10
-rw-r--r--ruby/Rakefile116
-rwxr-xr-xruby/examples/hello-world.rb61
-rw-r--r--ruby/examples/qmf-libvirt.rb80
-rw-r--r--ruby/ext/sasl/extconf.rb28
-rw-r--r--ruby/ext/sasl/sasl.c472
-rw-r--r--ruby/lib/qpid.rb41
-rw-r--r--ruby/lib/qpid/assembler.rb148
-rw-r--r--ruby/lib/qpid/client.rb136
-rw-r--r--ruby/lib/qpid/codec.rb457
-rw-r--r--ruby/lib/qpid/codec08.rb265
-rw-r--r--ruby/lib/qpid/config.rb32
-rw-r--r--ruby/lib/qpid/connection.rb222
-rw-r--r--ruby/lib/qpid/connection08.rb252
-rw-r--r--ruby/lib/qpid/datatypes.rb353
-rw-r--r--ruby/lib/qpid/delegates.rb237
-rw-r--r--ruby/lib/qpid/fields.rb49
-rw-r--r--ruby/lib/qpid/framer.rb212
-rw-r--r--ruby/lib/qpid/invoker.rb65
-rw-r--r--ruby/lib/qpid/packer.rb33
-rw-r--r--ruby/lib/qpid/peer.rb289
-rw-r--r--ruby/lib/qpid/qmf.rb1957
-rw-r--r--ruby/lib/qpid/queue.rb101
-rw-r--r--ruby/lib/qpid/session.rb458
-rw-r--r--ruby/lib/qpid/spec.rb183
-rw-r--r--ruby/lib/qpid/spec010.rb485
-rw-r--r--ruby/lib/qpid/spec08.rb190
-rw-r--r--ruby/lib/qpid/specs/amqp.0-10-qpid-errata.xml6654
-rw-r--r--ruby/lib/qpid/specs/amqp.0-10.dtd246
-rw-r--r--ruby/lib/qpid/test.rb35
-rw-r--r--ruby/lib/qpid/traverse.rb64
-rw-r--r--ruby/lib/qpid/util.rb75
-rw-r--r--ruby/tests/assembler.rb78
-rw-r--r--ruby/tests/codec010.rb122
-rw-r--r--ruby/tests/connection.rb246
-rw-r--r--ruby/tests/datatypes.rb224
-rw-r--r--ruby/tests/framer.rb99
-rw-r--r--ruby/tests/qmf.rb248
-rw-r--r--ruby/tests/queue.rb80
-rw-r--r--ruby/tests/spec010.rb80
-rw-r--r--ruby/tests/util.rb72
-rw-r--r--ruby/tests_0-8/basic.rb69
-rw-r--r--ruby/tests_0-8/channel.rb48
-rw-r--r--specs/management-schema.xml46
-rwxr-xr-xtests/setup.py2
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/__init__.py1
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/alternate_exchange.py125
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/dtx.py102
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/exchange.py31
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/extensions.py58
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/management.py154
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/message.py165
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/msg_groups.py1077
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/priority.py20
-rw-r--r--tests/src/py/qpid_tests/broker_0_10/threshold.py15
-rwxr-xr-xtools/setup.py5
-rwxr-xr-xtools/src/py/qmf-tool148
-rwxr-xr-xtools/src/py/qpid-cluster9
-rwxr-xr-xtools/src/py/qpid-config145
-rwxr-xr-xtools/src/py/qpid-printevents28
-rwxr-xr-xtools/src/py/qpid-route62
-rwxr-xr-xtools/src/py/qpid-tool21
2641 files changed, 275422 insertions, 62850 deletions
diff --git a/KEYS b/KEYS
index 8fb029ba20..98e057984d 100644
--- a/KEYS
+++ b/KEYS
@@ -371,58 +371,3 @@ EAAKCRCFx21QqdfQx+2MAKDPilVZy0YNhW5fIvA/3Tz0/UvjgQCfUQuSqdXNgZaT
jvJP5xcF6/EBpys=
=Wc+j
-----END PGP PUBLIC KEY BLOCK-----
-pub 4096R/C6B459DB 2011-07-18
-uid Justin Ross (CODE SIGNING KEY) <jross@apache.org>
-sub 4096R/95BB2C1A 2011-07-18
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v2.0.17 (GNU/Linux)
-
-mQINBE4kjewBEADSfPSpx+dZqdopNR8h/QG6jFDL9stuTQkLN0y9VEo+PEX4wzR6
-npzxcjVZF0ZBGOZl6DT3/SgmOZtFtnH5nb3ebpFEaalktyC9K4rFad4QW3mez7+x
-Slsb6DEx0l6PFU9FM97RI7MLMfkkYuAsWqO1kDdLaY7XeFg0a05OA0d/i7qCl5fR
-rAmCKM80SDM23DToWWEVP3Pw8ZYl8KNjc2aTiov/2VdMRZgldJr4EpAkPWk88qGu
-s9otP5tKu+aQA/ub6myF295uBtdycvq2DkLUSStSPripADjBcsNswBfITr5inuuQ
-g4mIF8pzkRajud4ahZe8mi1hE4K2eyPc2a5Yj1gXM6MPsuNSieSiwlIfj3u+0dRX
-74PZzCbPPmmveVWXBFbHBPZs9BwDUBint+1QRk5b0xi3uV/YUuciHQPdjXBcFo8y
-fPeZv6vkPHlozXW+wnS7XZqz06fObFPGjpOsTXSiFzd/+9Ecav3tDY7z6UvzRqpN
-dU7x0SskEBaU3CS6Av2as5mJ4psaYspSk8goo71JrGZS8hZdALkn6Q6exb1BSEXL
-O06N6niNxEf97KAbKvdByfmGMCuombF7My/CwkD6tbhIFO+mGga0AHYkE/F9s3o+
-gWEk/Rfx0jgkiMZWaQqJUYM6XRkNiKjR/QYjbo3eIibCxX8PfKg2iG/tdQARAQAB
-tDFKdXN0aW4gUm9zcyAoQ09ERSBTSUdOSU5HIEtFWSkgPGpyb3NzQGFwYWNoZS5v
-cmc+iQI4BBMBAgAiBQJOJI3sAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK
-CRBkio5XxrRZ2xBpEACS45v7yMgqFzMEAdTb7uOZ6ibZSBD83Xhgraq0Deygt5aZ
-zglcegfHufVKC7jmGtWcKYrJ5zwPcclmAut4mc7akPUZYmeSKAcDPhysswvf4vm9
-lNxzwnT83S2bCALK67kj1M2K+U56hP49jCYWCYhoAIb2yRffO/x8EZDmN388Z3ki
-6wuD/bfhGKXig04njeWhdJz4asKifbORec4z8R2wIqiOfBy+ObZzQjtXq8CWb2VR
-cz0vVQGUCLdD3W2XKryxgzWoJlybCF2+XAx1GJ/zQ/6TDLm2P1kVX285/pcOVAUM
-Ca1IHf70z1SOjAI7KfH9ewgZoMJMqIauDxf2YNejntj9tyd5i4i1h1upeDD7mI79
-c1kBZfYDDJhqlbgPfSnBX46xEXY2Vh9hHmIeLzNpaMQhGgFVwLKQdNOjDN4WcaoV
-pKQf/ZZ6dzBkzTZni7j11DxIgCIu64qgzqlBI2xYmxNzkF/1hVVkHsrZ82TpFcKM
-ejmq3NKtQMvt9TeJwRe+NVdF19bpszk7FnxYWfiokP7SJcjBDnuXah8ScEk2Fa3D
-Q41Rpg3q6e3Gc7ehfhZsUNlstQ/zEVfg3Dj9lkkMm2Jx13S+bHobgXbNIG23Kv+N
-vfKqtoRKrJwujgdy0KgyeMUSTYKVxgjK9nbOZtNbFMn0rYTnKjdTt//DzZ5We7kC
-DQROJI3sARAA2wHTgOEYWLHhJPOzuM5nEnPTMTTSymo31dePqUEGM/5Gxcl+GXwK
-0RCvV4Hlaju7fR8SB2wbVqZDRACqynw7aSGxr327ebvCOKc/9d5R9aK2qRisoN9b
-wIq2IzboLDC8PKEZsFyOUcEirt0q8k05cC8S9nx5LG5ddeIcIyXwKUYLLgOeUgre
-Drzm2R+6N28C1AcXL7V8pDEfy5sd1tslMsV9khtF1hqxaW9nRKt/7qGsI+ALmwyz
-QwV54GPLs1LUJX7vlEbl3gUbmrgdCk1eYP/KloZJFMlwgB+EUoWFrboy+BAxUBwJ
-xk4y+Dqu9GLnNYo8MrTvL6QAFdoscAPFThZRndQ/MfOvCNz/0Yima7AKOPoQXDFB
-zhjR8lv8A12mmnegHpkV9P4isT6c5Tc5TPbCBqnOId2buLm2V7f3kgH5dPgPEO0z
-P3SPe39mJNSLWtrqpi89EQI+cD/JhyemgTNJOYqjLnnrsyaPXYClVR05nW3g7Bmh
-9UO/5L82Mi8LFZXFO23L/JRvpvh529f7fPpMv4KiJiU5Gc2LJ3/HAYDIp/4q3ETF
-TboPEAP7WW0BLVkl37LkhJ/uD7/COFlTolgsNqtIZtRr6m8/PeLPYXfOwKNSmhz2
-CqW7RSIiyqwdFtyfyR0RpDAYissaRpMgqU/6r49OsZIOLImkJI33M7sAEQEAAYkC
-HwQYAQIACQUCTiSN7AIbDAAKCRBkio5XxrRZ20o4EACnL2xNHpRZQm4L+qB/Lanz
-2GONIKqdFzRls/6WlqOS+/loylorF3hVo8aJe13bJtf8LIoBTViFUq8BCBEb1Q3S
-qmmlzfiMeTZtCK9WbfqC07iEe/KUNmxjA/ZR6sE9x8Pe+QI0mnXZBKHexLsjdpav
-hdwHi5EmAE8gEiY7PwbJmxq+JXxKWrhyPscn3TIQrs6F+0KMs61XVPsflN0Tfzvf
-7hJ8Zn7HGjGsa+g6XmiEoZMDWwZDQVZby+g95EE9iyAwT6tlNqNGgHS8QKL9zFo0
-cxCntJYMQhYHKsd744Tfq01i3EEFIUMqGc/md0Ra/E5bG563VfbvBOpDobiX1KX1
-wRIMo5StjjFVzZj7Zyj73ALSQ5mfSvzJqsXRYpoPdy6bHJj3nSBrswpjpl+WsVOR
-oe6o73mM3CB6r10YMITa+aEmSQGAFSwajpDAfqbSQRbIGq0K+hqyCMzZ7qqv2b0+
-U1N6jUaWBFLMNiti+jw6TRUcdQstagb6qYqpF5MQ+NU7ddxNgIiRByeoFR9vMIfT
-wFtVHi7IN8OM6rvshjc/rmOEiSPCULSvpI1vq14MfRAWfyeqkxrvuklbdMOeJwSP
-U6nOKyS2R4/y+0s1J85amn4YHTUhOHYRnQAEckX8DB0UtCP15FSmrN3aOBp7hbvm
-MxumwmEHVDFpDpKCCnJa9A==
-=Uryx
------END PGP PUBLIC KEY BLOCK-----
diff --git a/LICENSE b/LICENSE
index cd0c8d0a8b..5f84a6564b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,7 @@
Please see the individual LICENSE files for each language
cpp/LICENSE
+dotnet/LICENSE.txt
gentools/lib/LICENSE
java/resources/LICENSE
python/LICENSE.txt
+ruby/LICENSE.txt
diff --git a/NOTICE b/NOTICE
index 5691e0e1ac..ff65d299a9 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,6 +1,8 @@
Please see the individual NOTICE files for each language:
cpp/NOTICE
+dotnet/NOTICE.txt
gentools/lib/NOTICE
java/resources/NOTICE
python/NOTICE.txt
+ruby/NOTICE.txt
diff --git a/QPID_VERSION.txt b/QPID_VERSION.txt
index f3040840fd..b63ba696b7 100644
--- a/QPID_VERSION.txt
+++ b/QPID_VERSION.txt
@@ -1 +1 @@
-0.13
+0.9
diff --git a/README.txt b/README.txt
index ccd92c757b..00a56bdc3d 100644
--- a/README.txt
+++ b/README.txt
@@ -36,10 +36,22 @@ Python Client Libraries
./python
+Ruby Client Libraries
+
+ ./ruby
+
+.NET Client Libraries
+
+ ./dotnet
+
WCF Support
./wcf
+Messaging Client (implemented in Ruby):
+
+ ./ruby
+
Management Tools (implemented in Python):
./tools
@@ -54,4 +66,4 @@ Documentation:
Further information about the organization of Qpid source components may
-be found in ./doc/dev-readme/QPID-Component-README.pdf.
+be found in ./doc/dev-readme/QPID-0.8-Component-README.pdf.
diff --git a/bin/release.sh b/bin/release.sh
index 949cb57358..31c12e630c 100755
--- a/bin/release.sh
+++ b/bin/release.sh
@@ -41,8 +41,6 @@ usage()
echo "--ruby |-r : Generate the ruby artefacts"
echo "--python|-p : Generate the python artefacts"
echo "--wcf |-w : Generate the WCF artefacts"
- echo "--tools |-t : Generate the tools artefacts"
- echo "--qmf |-q : Generate the QMF artefacts"
echo "--source|-e : Generate the source artefact"
echo "--sign |-s : Sign generated artefacts"
echo "--upload|-u : Upload the artifacts directory to people.apache.org as qpid-\$VER"
@@ -76,11 +74,11 @@ for arg in $* ; do
;;
--all|-a)
CPP="CPP"
+ DOTNET="DOTNET"
JAVA="JAVA"
+ RUBY="RUBY"
PYTHON="PYTHON"
WCF="WCF"
- TOOLS="TOOLS"
- QMF="QMF"
SOURCE="SOURCE"
;;
--cpp|-c)
@@ -101,12 +99,6 @@ for arg in $* ; do
--wcf|-w)
WCF="WCF"
;;
- --tools|-t)
- TOOLS="TOOLS"
- ;;
- --qmf|-q)
- QMF="QMF"
- ;;
--source|-e)
SOURCE="SOURCE"
;;
@@ -226,8 +218,8 @@ if [ "JAVA" == "$JAVA" ] ; then
cp qpid-${VER}/java/management/eclipse-plugin/release/*.tar.gz qpid-${VER}/java/management/eclipse-plugin/release/*.zip artifacts/
# copy the Maven artifacts
- cp -a qpid-${VER}/java/client/release/maven artifacts/
- cp -a qpid-${VER}/java/common/release/maven artifacts/
+ cp qpid-${VER}/java/client/release/maven artifacts/
+ cp qpid-${VER}/java/common/release/maven artifacts/
fi
if [ "DOTNET" == "$DOTNET" ] ; then
@@ -247,26 +239,6 @@ if [ "DOTNET" == "$DOTNET" ] ; then
cp qpid-${VER}/dotnet/client-010/bin/mono-2.0/debug/*.zip artifacts/qpid-dotnet-0-10-${VER}.zip
fi
-if [ "TOOLS" = "$TOOLS" ] ; then
- pushd qpid-${VER}/tools
-
- python setup.py sdist
-
- popd
-
- cp qpid-${VER}/tools/dist/*.tar.gz artifacts/qpid-tools-${VER}.tar.gz
-fi
-
-if [ "QMF" = "$QMF" ]; then
- pushd qpid-${VER}/extras/qmf
-
- python setup.py sdist
-
- popd
-
- cp qpid-${VER}/extras/qmf/dist/*.tar.gz artifacts/qpid-qmf-${VER}.tar.gz
-fi
-
if [ "SIGN" == "$SIGN" ] ; then
pushd artifacts
sha1sum *.zip *.gz *.svnversion > SHA1SUM
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 17411e90a4..5c37ecfc97 100644
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -80,7 +80,6 @@ set(CPACK_PACKAGE_INSTALL_DIRECTORY "qpidc-${qpidc_version}")
add_subdirectory(managementgen)
add_subdirectory(etc)
add_subdirectory(src)
-add_subdirectory(bindings/qpid)
add_subdirectory(docs/api)
# add_subdirectory(docs/man)
add_subdirectory(examples)
diff --git a/cpp/INSTALL b/cpp/INSTALL
index dbd41c7cc1..6483d7de4e 100644
--- a/cpp/INSTALL
+++ b/cpp/INSTALL
@@ -47,9 +47,9 @@ Redhat Linux 3, will almost certainly require some packages to be upgraded.
====================
The following libraries and header files must be installed to build
a source distribution:
- * boost <http://www.boost.org> (1.35)(*)
- * libuuid <http://kernel.org/~kzak/util-linux/> (2.19)
- * pkgconfig <http://pkgconfig.freedesktop.org/wiki/> (0.21)
+ * boost <http://www.boost.org> (1.35)(*)
+ * e2fsprogs <http://e2fsprogs.sourceforge.net/> (1.39)
+ * pkgconfig <http://pkgconfig.freedesktop.org/wiki/> (0.21)
(*) earlier versions of boost e.g. 1.33 also work and there is a patch
to get 1.32 working in the svn tree though that is only recommended as
@@ -96,12 +96,12 @@ the following must also be installed:
* python-devel
* swig <http://www.swig.org> (1.3.35)
-UUID problems:
-In some earlier Linux releases (such as Fedora 11), the uuid/uuid.h
-file is located in the e2fsprogs-devel package instead of
-libuuid-devel. If you are using an older Linux release and run into a
-problem during configure in which uuid.h cannot be found, install the
-e2fsprogs-devel package.
+UUID problems:
+In some later Linux releases (such as Fedora 12), the uuid/uuid.h file has been
+moved from e2fsprogs-devel into libuuid-devel. If you are using a newer Linux
+release and run into a problem during configure in which uuid.h cannot be found,
+look for and install the libuuid-devel package.
+
2.2. How to Install
===================
@@ -112,7 +112,7 @@ e2fsprogs-devel package.
On linux most packages can be installed using your distribution's
package management tool. For example on Fedora:
- # yum install boost-devel libuuid-devel pkgconfig gcc-c++ make autoconf automake ruby libtool help2man doxygen graphviz
+ # yum install boost-devel e2fsprogs-devel pkgconfig gcc-c++ make autoconf automake ruby libtool help2man doxygen graphviz
The optional clustering packages changed name in Fedora 10. On Fedora 9 or earlier:
# yum install openais-devel cman-devel
diff --git a/cpp/INSTALL-WINDOWS b/cpp/INSTALL-WINDOWS
index 75fa69079e..964d644a7a 100644
--- a/cpp/INSTALL-WINDOWS
+++ b/cpp/INSTALL-WINDOWS
@@ -64,7 +64,7 @@ manually installed to non-standard locations. For example:
It is also necessary to set BOOST_ROOT to refer to the base of your Boost
installation. The Visual Studio projects refer to it. For example:
- # set BOOST_ROOT="C:\Program Files\boost\boost_1_35_0"
+ # set BOOST_ROOT=C:\Program Files\boost\boost_1_35_0
3. Building from a Source Distribution
@@ -75,7 +75,7 @@ Visual Studio solution file which is generated by CMake.
From a command prompt:
# cd qpid\cpp
- # cmake -i -G "Visual Studio 9 2008" .
+ # cmake -i
Output from CMake includes .h files in the include directory, .vcproj
files for executables and dlls, and the qpid-cpp.sln solution file.
@@ -120,12 +120,7 @@ files that are part of the build.
Configure again. Repeat until all the Cache Values are gray.
- Click the OK button to generate the project/make files.
-Open the qpid-cpp.sln solution located in the build directory, select Debug
-or Release, and build. You can build both Release and Debug from the same
-project.
-
-If you build all the projects you can then "Build" the RUN_TESTS project.
-This will run the test suite against the Qpid version just built.
+Now follow instruction for building from a source distribution in step (3).
5. Tests
diff --git a/cpp/Makefile.am b/cpp/Makefile.am
index 9f4b8e2082..01b8507454 100644
--- a/cpp/Makefile.am
+++ b/cpp/Makefile.am
@@ -33,7 +33,3 @@ SUBDIRS = managementgen etc src docs/api docs/man examples bindings/qmf bindings
# Update libtool, if needed.
libtool: $(LIBTOOL_DEPS)
$(SHELL) ./config.status --recheck
-
-check-long: all
- $(MAKE) -C src/tests check-long
- \ No newline at end of file
diff --git a/cpp/bindings/qmf/python/Makefile.am b/cpp/bindings/qmf/python/Makefile.am
index 8abad32959..421590f189 100644
--- a/cpp/bindings/qmf/python/Makefile.am
+++ b/cpp/bindings/qmf/python/Makefile.am
@@ -30,13 +30,11 @@ BUILT_SOURCES = $(generated_file_list)
SWIG_FLAGS = -w362,401
$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmfengine.i
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o qmfengine.cpp $(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 = $(PYTHON_LIB)
lib_LTLIBRARIES = _qmfengine.la
-qenginedir = $(pyexecdir)
-qengine_PYTHON = qmfengine.py qmf.py
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)"
#_qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".so"
diff --git a/cpp/bindings/qmf/ruby/Makefile.am b/cpp/bindings/qmf/ruby/Makefile.am
index de8c4d10d5..cfb3a33870 100644
--- a/cpp/bindings/qmf/ruby/Makefile.am
+++ b/cpp/bindings/qmf/ruby/Makefile.am
@@ -35,9 +35,9 @@ qmfengine.cpp: $(srcdir)/ruby.i $(srcdir)/../qmfengine.i
rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = qmfengine.la
-qmfengine_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfengine.la
-qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_qmfengine_la_SOURCES = qmfengine.cpp
CLEANFILES = qmfengine.cpp
diff --git a/cpp/bindings/qmf/tests/test_base.rb b/cpp/bindings/qmf/tests/test_base.rb
index 7d4609097c..3e4337a9c0 100644
--- a/cpp/bindings/qmf/tests/test_base.rb
+++ b/cpp/bindings/qmf/tests/test_base.rb
@@ -24,7 +24,6 @@ require 'socket'
class ConsoleTestBase < Qmf::ConsoleHandler
def initialize
- sleep(2)
@settings = Qmf::ConnectionSettings.new
@settings.host = ARGV[0] if ARGV.size > 0
@settings.port = ARGV[1].to_i if ARGV.size > 1
@@ -68,7 +67,7 @@ class ConsoleTestBase < Qmf::ConsoleHandler
def assert(condition, in_text=nil)
text = " (#{in_text})" if in_text
- raise "Assertion failed: #{condition} #{text}" unless condition
+ raise "Assertion failed: #{left} != #{right}#{text}" unless condition
end
def fail(text)
diff --git a/cpp/bindings/qmf2/examples/cpp/Makefile.am b/cpp/bindings/qmf2/examples/cpp/Makefile.am
index 062fbd0a85..84207d43c4 100644
--- a/cpp/bindings/qmf2/examples/cpp/Makefile.am
+++ b/cpp/bindings/qmf2/examples/cpp/Makefile.am
@@ -21,7 +21,7 @@ INCLUDE = -I$(top_srcdir)/include
AM_CPPFLAGS = $(INCLUDE)
-noinst_PROGRAMS=agent event_driven_list_agents list_agents print_events
+noinst_PROGRAMS=agent list_agents print_events
agent_SOURCES=agent.cpp
agent_LDADD=$(top_builddir)/src/libqmf2.la
@@ -29,8 +29,5 @@ agent_LDADD=$(top_builddir)/src/libqmf2.la
list_agents_SOURCES=list_agents.cpp
list_agents_LDADD=$(top_builddir)/src/libqmf2.la
-event_driven_list_agents_SOURCES=event_driven_list_agents.cpp
-event_driven_list_agents_LDADD=$(top_builddir)/src/libqmf2.la
-
print_events_SOURCES=print_events.cpp
print_events_LDADD=$(top_builddir)/src/libqmf2.la
diff --git a/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp b/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp
deleted file mode 100644
index c288aa6bdd..0000000000
--- a/cpp/bindings/qmf2/examples/cpp/event_driven_list_agents.cpp
+++ /dev/null
@@ -1,107 +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 <sys/select.h>
-#include <time.h>
-
-#include <qpid/messaging/Connection.h>
-#include <qpid/messaging/Duration.h>
-#include <qmf/Agent.h>
-#include <qmf/ConsoleEvent.h>
-#include <qmf/ConsoleSession.h>
-#include <qpid/types/Variant.h>
-#include "qmf/posix/EventNotifier.h"
-
-#include <string>
-#include <iostream>
-
-using namespace std;
-using namespace qmf;
-using qpid::types::Variant;
-using qpid::messaging::Duration;
-
-int main(int argc, char** argv)
-{
- string url("localhost");
- string connectionOptions;
- string sessionOptions;
-
- if (argc > 1)
- url = argv[1];
- if (argc > 2)
- connectionOptions = argv[2];
- if (argc > 3)
- sessionOptions = argv[3];
-
- qpid::messaging::Connection connection(url, connectionOptions);
- connection.open();
-
- ConsoleSession session(connection, sessionOptions);
- session.open();
- session.setAgentFilter("");
-
- posix::EventNotifier notifier(session);
-
- int fd(notifier.getHandle());
- time_t lastUpdate;
- bool ftl = false;
-
- time(&lastUpdate);
-
- while (true) {
- fd_set rfds;
- struct timeval tv;
- int nfds, retval;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- nfds = fd + 1;
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- retval = select(nfds, &rfds, NULL, NULL, &tv);
-
- if (retval > 0 && FD_ISSET(fd, &rfds)) {
- ConsoleEvent event;
- while (session.nextEvent(event, Duration::IMMEDIATE)) {
- string eventType = "";
- switch(event.getType()) {
- case CONSOLE_AGENT_ADD: eventType = "Added"; break;
- case CONSOLE_AGENT_DEL: eventType = "Deleted"; break;
- case CONSOLE_AGENT_RESTART: eventType = "Restarted"; break;
- case CONSOLE_AGENT_SCHEMA_UPDATE: eventType = "Schema Updated"; break;
- case CONSOLE_AGENT_SCHEMA_RESPONSE: eventType = "Schema Response"; break;
- case CONSOLE_EVENT: eventType = "Event"; break;
- case CONSOLE_QUERY_RESPONSE: eventType = "Query Response"; break;
- case CONSOLE_METHOD_RESPONSE: eventType = "Method Response"; break;
- case CONSOLE_EXCEPTION: eventType = "Exception"; break;
- case CONSOLE_SUBSCRIBE_ADD: eventType = "Subscription Added"; break;
- case CONSOLE_SUBSCRIBE_UPDATE: eventType = "Subscription Updated"; break;
- case CONSOLE_SUBSCRIBE_DEL: eventType = "Subscription Deleted" ; break;
- case CONSOLE_THREAD_FAILED: eventType = "Thread Failure"; break;
- default: eventType = "[UNDEFINED]";
- }
- cout << "Agent " << eventType << ": " << event.getAgent().getName() << endl;
- }
- } else {
- cout << "No message received within waiting period." << endl;
- }
- }
-}
-
diff --git a/cpp/bindings/qmf2/python/Makefile.am b/cpp/bindings/qmf2/python/Makefile.am
index 3dc04e832f..7adc62eddb 100644
--- a/cpp/bindings/qmf2/python/Makefile.am
+++ b/cpp/bindings/qmf2/python/Makefile.am
@@ -30,12 +30,12 @@ BUILT_SOURCES = $(generated_file_list)
SWIG_FLAGS = -w362,401
$(generated_file_list): $(srcdir)/python.i $(srcdir)/../qmf2.i $(srcdir)/../../swig_python_typemaps.i
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/python.i
+ swig -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqmf2.cpp $(srcdir)/python.i
pylibdir = $(PYTHON_LIB)
lib_LTLIBRARIES = _cqmf2.la
-cqpiddir = $(pyexecdir)
+cqpiddir = $(pythondir)
cqpid_PYTHON = qmf2.py cqmf2.py
_cqmf2_la_LDFLAGS = -avoid-version -module -shared
diff --git a/cpp/bindings/qmf2/qmf2.i b/cpp/bindings/qmf2/qmf2.i
index 0f573fe3e6..a09a95168f 100644
--- a/cpp/bindings/qmf2/qmf2.i
+++ b/cpp/bindings/qmf2/qmf2.i
@@ -37,7 +37,6 @@
%}
-%include <qpid/ImportExport.h>
%include <qpid/messaging/ImportExport.h>
%include <qpid/messaging/Duration.h>
diff --git a/cpp/bindings/qmf2/ruby/Makefile.am b/cpp/bindings/qmf2/ruby/Makefile.am
index 97bbc6f385..ae840f87c6 100644
--- a/cpp/bindings/qmf2/ruby/Makefile.am
+++ b/cpp/bindings/qmf2/ruby/Makefile.am
@@ -34,9 +34,9 @@ rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = cqmf2.la
dist_rubylib_DATA = qmf2.rb
-cqmf2_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+cqmf2_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
cqmf2_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqmf2 $(top_builddir)/src/libqmf2.la
-cqmf2_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+cqmf2_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_cqmf2_la_SOURCES = cqmf2.cpp
CLEANFILES = cqmf2.cpp
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 31bce5d1d5..ca9eda0c73 100644
--- a/cpp/bindings/qpid/Makefile.am
+++ b/cpp/bindings/qpid/Makefile.am
@@ -21,7 +21,7 @@ SUBDIRS = dotnet
if HAVE_SWIG
-EXTRA_DIST = CMakeLists.txt qpid.i
+EXTRA_DIST = qpid.i
if HAVE_RUBY_DEVEL
SUBDIRS += ruby
diff --git a/cpp/bindings/qpid/dotnet/configure-windows.ps1 b/cpp/bindings/qpid/dotnet/configure-windows.ps1
index 23fc742e07..34395911b9 100644
--- a/cpp/bindings/qpid/dotnet/configure-windows.ps1
+++ b/cpp/bindings/qpid/dotnet/configure-windows.ps1
@@ -24,32 +24,29 @@
# 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 32-bit and/or 64-bit development platforms.
#
# * User chooses in-source or out-of-source build directories.
#
# - 'In-source' builds happen when CMake is run from directory qpid\cpp.
-# Hundreds of CMake-generated output files are placed in qpid\cpp\src.
+# Hundreds of CMake-generated output files are placed in qpid\cpp\src.
# These files go right on top of files that are part of the source tree
# in qpid\cpp\src.
-# In-source builds support only one platform.
+# In-source builds support only one platform.
# Choose only a 32-bit or a 64-bit platform but not both.
#
# - Out-of-source builds happen when the user chooses another directory
# under qpid in which to run CMake. Out-of-source builds are required
-# in order to build both x86 and x64 targets using the same source tree.
+# in order to build both x86 and x64 targets using the same source tree.
# For each build platform (32-bit x86 or Win32, or 64-bit x64) the user
-# specifies a build directory and a specific version of Boost.
+# specifies a build directory and a specific version of Boost.
# Many platform/Boost-version directories may reside side by side.
#
# * User chooses to run CMake or not.
#
# - When a new build directory is created then the user is given the
-# option of running CMake in that directory. Running CMake is a
-# necessary step as CMake creates important source, solution, and
+# option of running CMake in that directory. Running CMake is a
+# necessary step as CMake creates important source, solution, and
# project files.
#
# - If a directory "looks like" is has already had CMake run in it
@@ -66,7 +63,7 @@
# 3. CMake 2.8 (or later) must be installed. The cmake\bin directory
# must be in the user's path.
# 4. Boost library specifications may or may not be in the user's path.
-# The script author recommeds not to have Boost in the path and only
+# The script author recommeds not to have Boost in the path and only
# allow the Boost path to be specified by generated command procedures.
# 5. Visual Studio build environment must be installed.
#
@@ -93,7 +90,7 @@
# In this example the build dirs are new. The script will prompt
# asking if CMake is to run in the build directories. User chooses Yes.
#
-# Now this script runs CMake twice, once each with the 32-bit and 64-bit
+# Now this script runs CMake twice, once each with the 32-bit and 64-bit
# generators.
# * This step creates qpid-cpp.sln and related project files.
# C:\svn\qpid\build32\qpid-cpp.sln
@@ -110,7 +107,7 @@
# C:\svn\qpid\build64\setenv-messaging-x64-64bit.bat
#
# Next the user compiles solution qpid\build32\qpid-cpp.sln.
-#
+#
# Using the generated scripts:
#
# Case 1. Run an executable in 32-bit mode.
@@ -145,11 +142,6 @@ $global:txtPath = '$env:PATH'
$global:txtQR = '$env:QPID_BUILD_ROOT'
$global:txtWH = 'Write-Host'
-#############################
-# Visual Studio version selection dialog items and choice
-#
-[array]$global:VsVersionCmakeChoiceList = "Visual Studio 10", "Visual Studio 9 2008"
-$global:cmakeGenerator = ''
#############################
# Select-Folder
@@ -176,7 +168,7 @@ function AskYesOrNo ($Question="No question?", $Title="No Title?")
[Windows.Forms.MessageBoxIcon]::Question)
$result = $dlg -eq [Windows.Forms.DialogResult]::Yes
-
+
$result
}
@@ -196,7 +188,7 @@ function SanityCheckBoostPath ($path=0)
$toTest = ('include', 'lib')
foreach ($pattern in $toTest) {
- $target = Join-Path $path $pattern
+ $target = Join-Path $path $pattern
if (!(Test-Path -path $target)) {
$result = $false
}
@@ -204,7 +196,7 @@ function SanityCheckBoostPath ($path=0)
} else {
$result = $false
}
-
+
if (! $result) {
Write-Host "The path ""$displayPath"" does not appear to be a Boost root path."
}
@@ -227,7 +219,7 @@ function SanityCheckBuildPath ($path=0)
$toTest = ('CMakeFiles', 'docs', 'etc', 'examples', 'include',
'managementgen', 'src')
foreach ($pattern in $toTest) {
- $target = Join-Path $path $pattern
+ $target = Join-Path $path $pattern
if (!(Test-Path -path $target)) {
$result = $false
}
@@ -321,7 +313,7 @@ function WriteDotnetBindingEnvSetupBat
$out = @("@ECHO OFF
REM
-REM Call this command procedure from a command prompt to set up a $vsPlatform ($nBits-bit)
+REM Call this command procedure from a command prompt to set up a $vsPlatform ($nBits-bit)
REM $slnName environment
REM
REM > call $outfileName
@@ -337,56 +329,6 @@ ECHO Environment set for $slnName $vsPlatform $nBits-bit development.
$out | Out-File "$buildRoot\$outfileName" -encoding ASCII
}
-#############################
-# Return the SelectedItem from the dropdown list and close the form.
-#
-function Return-DropDown {
- if ($DropDown.SelectedItem -ne $null) {
- $global:cmakeGenerator = $DropDown.SelectedItem.ToString()
- $Form.Close()
- Write-Host "Selected generator: $global:cmakeGenerator"
- }
-}
-
-#############################
-# Create the CMake generator form and launch it
-#
-function SelectCMakeGenerator {
-
- $Form = New-Object System.Windows.Forms.Form
-
- $Form.width = 350
- $Form.height = 150
- $Form.Text = ”Select CMake Generator”
-
- $DropDown = new-object System.Windows.Forms.ComboBox
- $DropDown.Location = new-object System.Drawing.Size(120,10)
- $DropDown.Size = new-object System.Drawing.Size(150,30)
-
- ForEach ($Item in $global:VsVersionCmakeChoiceList) {
- $DropDown.Items.Add($Item)
- }
- $DropDown.SelectedIndex = 0
-
- $Form.Controls.Add($DropDown)
-
- $DropDownLabel = new-object System.Windows.Forms.Label
- $DropDownLabel.Location = new-object System.Drawing.Size(10,10)
- $DropDownLabel.size = new-object System.Drawing.Size(100,20)
- $DropDownLabel.Text = "CMake generators"
- $Form.Controls.Add($DropDownLabel)
-
- $Button = new-object System.Windows.Forms.Button
- $Button.Location = new-object System.Drawing.Size(120,50)
- $Button.Size = new-object System.Drawing.Size(120,20)
- $Button.Text = "Select a generator"
- $Button.Add_Click({Return-DropDown})
- $form.Controls.Add($Button)
-
- $Form.Add_Shown({$Form.Activate()})
- $Form.ShowDialog()
-}
-
#############################
# Main
@@ -399,12 +341,6 @@ function SelectCMakeGenerator {
[string] $cppDir = Resolve-Path (Join-Path $curDir "..\..\..")
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
-[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
-
-#############################
-# User dialog to select a version of Visual Studio as CMake generator
-#
-SelectCMakeGenerator
#############################
# User dialog to get optional 32-bit boost and build paths
@@ -476,7 +412,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 "Visual Studio 9 2008" "-DCMAKE_INSTALL_PREFIX=install_x86" $cppDir
} else {
Write-Host "Skipped 32-bit CMake."
}
@@ -488,7 +424,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 "Visual Studio 9 2008 Win64" "-DCMAKE_INSTALL_PREFIX=install_x64" $cppDir
} else {
Write-Host "Skipped 64-bit CMake."
}
@@ -501,7 +437,7 @@ if ($make64) {
if ($defined32) {
Write-Host "Writing 32-bit scripts..."
-
+
###########
# Powershell script to launch org.apache.qpid.messaging.sln
#
@@ -512,8 +448,8 @@ if ($defined32) {
-vsPlatform "x86" `
-nBits "32" `
-outfileName "start-devenv-messaging-x86-32bit.ps1"
-
-
+
+
###########
# Batch script (that you doubleclick) to launch powershell script
# that launches org.apache.qpid.messaging.sln.
@@ -546,7 +482,7 @@ if ($defined32) {
if ($defined64) {
Write-Host "Writing 64-bit scripts..."
-
+
###########
# Powershell script to launch org.apache.qpid.messaging.sln
#
@@ -557,8 +493,8 @@ if ($defined64) {
-vsPlatform "x64" `
-nBits "64" `
-outfileName "start-devenv-messaging-x64-64bit.ps1"
-
-
+
+
###########
# Batch script (that you doubleclick) to launch powershell script
# that launches org.apache.qpid.messaging.sln.
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
index 6976be5d02..abe35cf053 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.direct.receiver/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.direct.receiver")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.direct.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
index 12368def8e..18502a0666 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.direct.sender/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.direct.sender")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.direct.sender")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
index 459130ec6c..a87f92ccdf 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.receiver/Properties/AssemblyInfo.cs
@@ -20,7 +20,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.callback.receiver")]
@@ -28,12 +28,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.callback.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -43,11 +43,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
index 2be4011f19..e633f76673 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.callback.sender/Properties/AssemblyInfo.cs
@@ -28,7 +28,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.callback.sender")]
-[assembly: AssemblyCopyright("Copyright 2010")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
index f11ce8c220..694d6b9ce1 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.receiver/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.receiver")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.receiver")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
index ee09057f18..ea29ac2417 100644
--- a/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/examples/csharp.map.sender/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("csharp.map.sender")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("csharp.map.sender")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb b/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
index 469d6ed5cf..d0727fe9fa 100644
--- a/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
+++ b/cpp/bindings/qpid/dotnet/examples/visualbasic.example.client/MyProject/AssemblyInfo.vb
@@ -6,9 +6,9 @@
' 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
@@ -21,34 +21,34 @@ Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
-' General Information about an assembly is controlled through the following
+' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
-<Assembly: AssemblyTitle("visualbasic.example.client")>
-<Assembly: AssemblyDescription("")>
-<Assembly: AssemblyCompany("")>
-<Assembly: AssemblyProduct("visualbasic.example.client")>
-<Assembly: AssemblyCopyright("Copyright 2011")>
-<Assembly: AssemblyTrademark("")>
+<Assembly: AssemblyTitle("visualbasic.example.client")>
+<Assembly: AssemblyDescription("")>
+<Assembly: AssemblyCompany("Microsoft")>
+<Assembly: AssemblyProduct("visualbasic.example.client")>
+<Assembly: AssemblyCopyright("Copyright © Microsoft 2010")>
+<Assembly: AssemblyTrademark("")>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
-<Assembly: Guid("ec9df8cf-c1d4-4938-9e72-93fb81d55700")>
+<Assembly: Guid("ec9df8cf-c1d4-4938-9e72-93fb81d55700")>
' Version information for an assembly consists of the following four values:
'
' Major Version
-' Minor Version
+' Minor Version
' Build Number
' Revision
'
-' You can specify all the values or you can default the Build and Revision Numbers
+' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
-' <Assembly: AssemblyVersion("1.0.*")>
+' <Assembly: AssemblyVersion("1.0.*")>
-<Assembly: AssemblyVersion("1.0.0.0")>
-<Assembly: AssemblyFileVersion("1.0.0.0")>
+<Assembly: AssemblyVersion("1.0.0.0")>
+<Assembly: AssemblyFileVersion("1.0.0.0")>
diff --git a/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln b/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
index edf8af4808..90e98a4bbe 100644
--- a/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
+++ b/cpp/bindings/qpid/dotnet/org.apache.qpid.messaging.sessionreceiver.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
-#
+#
# 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
@@ -8,9 +8,9 @@ Microsoft Visual Studio Solution File, Format Version 10.00
# 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
diff --git a/cpp/bindings/qpid/dotnet/src/Address.cpp b/cpp/bindings/qpid/dotnet/src/Address.cpp
index 79a8021d9a..b688d973ed 100644
--- a/cpp/bindings/qpid/dotnet/src/Address.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Address.cpp
@@ -141,7 +141,7 @@ namespace Messaging {
}
}
- // Copy constructor look-alike (C#)
+ // copy constructor
Address::Address(const Address ^ address)
{
System::Exception ^ newException = nullptr;
@@ -163,28 +163,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Address::Address(const Address % address)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- addressp = new ::qpid::messaging::Address(
- *(const_cast<Address %>(address).NativeAddress));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
// unmanaged clone
Address::Address(const ::qpid::messaging::Address & addrp)
{
diff --git a/cpp/bindings/qpid/dotnet/src/Address.h b/cpp/bindings/qpid/dotnet/src/Address.h
index 8bbc207d4e..e5a00d8f11 100644
--- a/cpp/bindings/qpid/dotnet/src/Address.h
+++ b/cpp/bindings/qpid/dotnet/src/Address.h
@@ -64,7 +64,6 @@ namespace Messaging {
// copy constructor
Address(const Address ^ address);
- Address(const Address % address);
// unmanaged clone
Address(const ::qpid::messaging::Address & addrp);
diff --git a/cpp/bindings/qpid/dotnet/src/Connection.cpp b/cpp/bindings/qpid/dotnet/src/Connection.cpp
index 12c0e29f74..69ace7db52 100644
--- a/cpp/bindings/qpid/dotnet/src/Connection.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Connection.cpp
@@ -114,7 +114,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Connection::Connection(const Connection ^ connection)
{
System::Exception ^ newException = nullptr;
@@ -136,28 +136,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Connection::Connection(const Connection % connection)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- connectionp = new ::qpid::messaging::Connection(
- *(const_cast<Connection %>(connection).NativeConnection));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
// Destructor
Connection::~Connection()
diff --git a/cpp/bindings/qpid/dotnet/src/Connection.h b/cpp/bindings/qpid/dotnet/src/Connection.h
index 0788f5d225..f9b62d4a08 100644
--- a/cpp/bindings/qpid/dotnet/src/Connection.h
+++ b/cpp/bindings/qpid/dotnet/src/Connection.h
@@ -56,7 +56,6 @@ namespace Messaging {
// copy constructor
Connection(const Connection ^ connection);
- Connection(const Connection % connection);
// unmanaged clone
// not defined
diff --git a/cpp/bindings/qpid/dotnet/src/Duration.h b/cpp/bindings/qpid/dotnet/src/Duration.h
index d4239fae88..213c338a59 100644
--- a/cpp/bindings/qpid/dotnet/src/Duration.h
+++ b/cpp/bindings/qpid/dotnet/src/Duration.h
@@ -81,17 +81,7 @@ namespace Messaging {
Duration ^ result = gcnew Duration(multiplier * dur->Milliseconds);
return result;
}
-
- static bool operator == (Duration ^ a, Duration ^ b)
- {
- return a->Milliseconds == b->Milliseconds;
- }
-
- static bool operator != (Duration ^ a, Duration ^ b)
- {
- return a->Milliseconds != b->Milliseconds;
- }
-};
+ };
public ref class DurationConstants sealed
{
diff --git a/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h b/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
index d82e276fc8..1dd92b8688 100644
--- a/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
+++ b/cpp/bindings/qpid/dotnet/src/FailoverUpdates.h
@@ -54,7 +54,6 @@ namespace Messaging {
// copy constructor
FailoverUpdates(const FailoverUpdates ^ failoverUpdates) {}
- FailoverUpdates(const FailoverUpdates % failoverUpdates) {}
// assignment operator
FailoverUpdates % operator=(const FailoverUpdates % rhs)
diff --git a/cpp/bindings/qpid/dotnet/src/Message.cpp b/cpp/bindings/qpid/dotnet/src/Message.cpp
index e5dbf845b3..fe7825134d 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Message.cpp
@@ -235,7 +235,7 @@ namespace Messaging {
}
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Message::Message(const Message ^ message)
{
System::Exception ^ newException = nullptr;
@@ -257,29 +257,7 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Message::Message(const Message % message)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- messagep = new ::qpid::messaging::Message(
- *(const_cast<Message %>(message).NativeMessage));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
- // Property
+ // Property
void Message::SetProperty(System::String ^ name, System::Object ^ value)
{
System::Exception ^ newException = nullptr;
diff --git a/cpp/bindings/qpid/dotnet/src/Message.h b/cpp/bindings/qpid/dotnet/src/Message.h
index ac7f285fe5..b92cc4200b 100644
--- a/cpp/bindings/qpid/dotnet/src/Message.h
+++ b/cpp/bindings/qpid/dotnet/src/Message.h
@@ -71,7 +71,6 @@ namespace Messaging {
// Copy constructor
Message(const Message ^ message);
- Message(const Message % message);
// unmanaged clone
Message(const ::qpid::messaging::Message & msgp);
diff --git a/cpp/bindings/qpid/dotnet/src/Receiver.cpp b/cpp/bindings/qpid/dotnet/src/Receiver.cpp
index 8aa77effbd..3c0d79b393 100644
--- a/cpp/bindings/qpid/dotnet/src/Receiver.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Receiver.cpp
@@ -89,7 +89,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Receiver::Receiver(const Receiver ^ receiver) :
parentSession(receiver->parentSession)
{
@@ -112,29 +112,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Receiver::Receiver(const Receiver % receiver) :
- parentSession(receiver.parentSession)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- receiverp = new ::qpid::messaging::Receiver(
- *(const_cast<Receiver %>(receiver).NativeReceiver));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
//
// Get(message)
diff --git a/cpp/bindings/qpid/dotnet/src/Receiver.h b/cpp/bindings/qpid/dotnet/src/Receiver.h
index 8ddcc9ac01..e9912a61dd 100644
--- a/cpp/bindings/qpid/dotnet/src/Receiver.h
+++ b/cpp/bindings/qpid/dotnet/src/Receiver.h
@@ -65,7 +65,6 @@ namespace Messaging {
// copy constructor
Receiver(const Receiver ^ receiver);
- Receiver(const Receiver % receiver);
// unmanaged clone
// undefined
diff --git a/cpp/bindings/qpid/dotnet/src/Sender.cpp b/cpp/bindings/qpid/dotnet/src/Sender.cpp
index 3225f1a6e1..584075ef5f 100644
--- a/cpp/bindings/qpid/dotnet/src/Sender.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Sender.cpp
@@ -84,7 +84,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Sender::Sender(const Sender ^ sender)
: parentSession(sender->parentSession)
{
@@ -107,29 +107,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Sender::Sender(const Sender % sender)
- : parentSession(sender.parentSession)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- senderp = new ::qpid::messaging::Sender(
- *(const_cast<Sender %>(sender).NativeSender));
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
//
// Send(msg)
diff --git a/cpp/bindings/qpid/dotnet/src/Sender.h b/cpp/bindings/qpid/dotnet/src/Sender.h
index 4054e87316..0e90a9f4a4 100644
--- a/cpp/bindings/qpid/dotnet/src/Sender.h
+++ b/cpp/bindings/qpid/dotnet/src/Sender.h
@@ -62,7 +62,6 @@ namespace Messaging {
// copy constructor
Sender(const Sender ^ sender);
- Sender(const Sender % sender);
~Sender();
!Sender();
diff --git a/cpp/bindings/qpid/dotnet/src/Session.cpp b/cpp/bindings/qpid/dotnet/src/Session.cpp
index 0e918769a3..880331c588 100644
--- a/cpp/bindings/qpid/dotnet/src/Session.cpp
+++ b/cpp/bindings/qpid/dotnet/src/Session.cpp
@@ -89,7 +89,7 @@ namespace Messaging {
}
- // Copy constructor look-alike (C#)
+ // Copy constructor
Session::Session(const Session ^ session)
: parentConnectionp(session->parentConnectionp)
{
@@ -113,30 +113,6 @@ namespace Messaging {
}
}
- // Copy constructor implicitly dereferenced (C++)
- Session::Session(const Session % session)
- : parentConnectionp(session.parentConnectionp)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- sessionp = new ::qpid::messaging::Session(
- *(const_cast<Session %>(session).NativeSession));
-
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
void Session::Close()
{
@@ -248,31 +224,6 @@ namespace Messaging {
}
}
- void Session::AcknowledgeUpTo(Message ^ message)
- {
- AcknowledgeUpTo(message, false);
- }
-
- void Session::AcknowledgeUpTo(Message ^ message, bool sync)
- {
- System::Exception ^ newException = nullptr;
-
- try
- {
- sessionp->acknowledgeUpTo(*(message->NativeMessage), sync);
- }
- catch (const ::qpid::types::Exception & error)
- {
- String ^ errmsg = gcnew String(error.what());
- newException = gcnew QpidException(errmsg);
- }
-
- if (newException != nullptr)
- {
- throw newException;
- }
- }
-
void Session::Reject(Message ^ message)
{
System::Exception ^ newException = nullptr;
diff --git a/cpp/bindings/qpid/dotnet/src/Session.h b/cpp/bindings/qpid/dotnet/src/Session.h
index 4b98a37f18..7eaad8a0a5 100644
--- a/cpp/bindings/qpid/dotnet/src/Session.h
+++ b/cpp/bindings/qpid/dotnet/src/Session.h
@@ -69,7 +69,6 @@ namespace Messaging {
// copy constructor
Session(const Session ^ session);
- Session(const Session % session);
~Session();
!Session();
@@ -104,8 +103,6 @@ namespace Messaging {
void Acknowledge(bool sync);
void Acknowledge(Message ^ message);
void Acknowledge(Message ^ message, bool sync);
- void AcknowledgeUpTo(Message ^ message);
- void AcknowledgeUpTo(Message ^ message, bool sync);
void Reject(Message ^);
void Release(Message ^);
void Sync();
diff --git a/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs b/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
index 81a89ce393..cf50e88200 100644
--- a/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
+++ b/cpp/bindings/qpid/dotnet/test/messaging.test/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,7 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
+// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("messaging.test")]
@@ -31,12 +31,12 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("messaging.test")]
-[assembly: AssemblyCopyright("Copyright 2011")]
+[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
@@ -46,11 +46,11 @@ using System.Runtime.InteropServices;
// Version information for an assembly consists of the following four values:
//
// Major Version
-// Minor Version
+// Minor Version
// Build Number
// Revision
//
-// You can specify all the values or you can default the Build and Revision Numbers
+// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/cpp/bindings/qpid/examples/perl/client.pl b/cpp/bindings/qpid/examples/perl/client.pl
index 19d9d3f14f..93eec88e07 100644
--- a/cpp/bindings/qpid/examples/perl/client.pl
+++ b/cpp/bindings/qpid/examples/perl/client.pl
@@ -20,13 +20,13 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
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);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -35,7 +35,7 @@ my $session = $connection->createSession();
my $sender = $session->createSender("service_queue");
#create temp queue & receiver...
-my $responseQueue = new cqpid_perl::Address("#response-queue; {create:always, delete:always}");
+my $responseQueue = new cqpid::Address("#response-queue; {create:always, delete:always}");
my $receiver = $session->createReceiver($responseQueue);
#Now send some messages...
@@ -47,7 +47,7 @@ my @s = (
"And the mome raths outgrabe."
);
-my $request = new cqpid_perl::Message();
+my $request = new cqpid::Message();
$request->setReplyTo($responseQueue);
for (my $i=0; $i<4; $i++) {
$request->setContent($s[$i]);
diff --git a/cpp/bindings/qpid/examples/perl/drain.pl b/cpp/bindings/qpid/examples/perl/drain.pl
index 60ac0c50ed..8010b7c95b 100644
--- a/cpp/bindings/qpid/examples/perl/drain.pl
+++ b/cpp/bindings/qpid/examples/perl/drain.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
use Getopt::Long;
my $url = "127.0.0.1";
@@ -47,11 +47,11 @@ if ($#ARGV ge 0) {
}
sub getTimeout {
- return ($forever) ? $cqpid_perl::Duration::FOREVER : new cqpid_perl::Duration($timeout*1000);
+ return ($forever) ? $cqpid::Duration::FOREVER : new cqpid::Duration($timeout*1000);
}
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -59,13 +59,13 @@ eval {
my $receiver = $session->createReceiver($address);
my $timeout = getTimeout();
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $i = 0;
while($receiver->fetch($message, $timeout)) {
print "Message(properties=" . $message->getProperties() . ",content='";
if ($message->getContentType() eq "amqp/map") {
- my $content = cqpid_perl::decodeMap($message);
+ my $content = cqpid::decodeMap($message);
map{ print "\n$_ => $content->{$_}"; } keys %{$content};
}
else {
@@ -77,7 +77,7 @@ eval {
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.");
+ my $response = new cqpid::Message("received by the server.");
$sender->send($response);
}
$session->acknowledge();
diff --git a/cpp/bindings/qpid/examples/perl/hello_world.pl b/cpp/bindings/qpid/examples/perl/hello_world.pl
index a96b98a002..cf2f05f8b7 100644
--- a/cpp/bindings/qpid/examples/perl/hello_world.pl
+++ b/cpp/bindings/qpid/examples/perl/hello_world.pl
@@ -21,13 +21,13 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
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);
+my $connection = new cqpid::Connection($broker, $connectionOptions);
eval {
$connection->open();
@@ -36,12 +36,12 @@ eval {
my $receiver = $session->createReceiver($address);
my $sender = $session->createSender($address);
- $sender->send(new cqpid_perl::Message("Hello world!"));
+ $sender->send(new cqpid::Message("Hello world!"));
- #my $duration = new cqpid_perl::Duration(1000);
+ #my $duration = new cqpid::Duration(1000);
#print ">>>" . $duration->getMilliseconds() . "\n";
- my $message = $receiver->fetch($cqpid_perl::Duration::SECOND);
+ my $message = $receiver->fetch($cqpid::Duration::SECOND);
#$message->setDurable(1);
#print "Durable: " . $message->getDurable() . "\n";
diff --git a/cpp/bindings/qpid/examples/perl/hello_xml.pl b/cpp/bindings/qpid/examples/perl/hello_xml.pl
index cebf2ceee6..c48a5225c2 100644
--- a/cpp/bindings/qpid/examples/perl/hello_xml.pl
+++ b/cpp/bindings/qpid/examples/perl/hello_xml.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
my $broker = ( @ARGV > 0 ) ? $ARGV[0] : "localhost:5672";
my $connectionOptions = ( @ARGV > 1 ) ? $ARGV[1] : "";
@@ -44,7 +44,7 @@ x-bindings: [{ exchange: xml-exchange, key: weather, arguments: { xquery:" $quer
END
-my $connection = new cqpid_perl::Connection($broker, $connectionOptions);
+my $connection = new cqpid::Connection($broker, $connectionOptions);
eval {
$connection->open();
@@ -52,7 +52,7 @@ eval {
my $receiver = $session->createReceiver($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $content = <<END;
<weather>
diff --git a/cpp/bindings/qpid/examples/perl/map_receiver.pl b/cpp/bindings/qpid/examples/perl/map_receiver.pl
index 2e2611e38f..e3e8a201dd 100644
--- a/cpp/bindings/qpid/examples/perl/map_receiver.pl
+++ b/cpp/bindings/qpid/examples/perl/map_receiver.pl
@@ -21,21 +21,21 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
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);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
my $session = $connection->createSession();
my $receiver = $session->createReceiver($address);
- my $content = cqpid_perl::decodeMap($receiver->fetch());
- #my $content = cqpid_perl::decodeList($receiver->fetch());
+ my $content = cqpid::decodeMap($receiver->fetch());
+ #my $content = cqpid::decodeList($receiver->fetch());
print Dumper($content);
diff --git a/cpp/bindings/qpid/examples/perl/map_sender.pl b/cpp/bindings/qpid/examples/perl/map_sender.pl
index 4107cd48b9..095acce0ab 100644
--- a/cpp/bindings/qpid/examples/perl/map_sender.pl
+++ b/cpp/bindings/qpid/examples/perl/map_sender.pl
@@ -21,13 +21,13 @@ use strict;
use warnings;
use Data::Dumper;
-use cqpid_perl;
+use cqpid;
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);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -35,13 +35,13 @@ eval {
my $session = $connection->createSession();
my $sender = $session->createSender($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
my $content = { id => 987654321,
name => "Widget",
percent => sprintf("%.2f", 0.99),
colours => [ qw (red green white) ],
};
- cqpid_perl::encode($content, $message);
+ cqpid::encode($content, $message);
$sender->send($message, 1);
$connection->close();
diff --git a/cpp/bindings/qpid/examples/perl/server.pl b/cpp/bindings/qpid/examples/perl/server.pl
index b14da565b9..0c64f15c66 100644
--- a/cpp/bindings/qpid/examples/perl/server.pl
+++ b/cpp/bindings/qpid/examples/perl/server.pl
@@ -20,13 +20,13 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
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);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
@@ -41,7 +41,7 @@ eval {
my $sender = $session->createSender($address);
my $s = $request->getContent();
$s = uc($s);
- my $response = new cqpid_perl::Message($s);
+ my $response = new cqpid::Message($s);
$sender->send($response);
print "Processed request: " . $request->getContent() . " -> " . $response->getContent() . "\n";
$session->acknowledge();
diff --git a/cpp/bindings/qpid/examples/perl/spout.pl b/cpp/bindings/qpid/examples/perl/spout.pl
index 7365e732bf..50773a4fe2 100644
--- a/cpp/bindings/qpid/examples/perl/spout.pl
+++ b/cpp/bindings/qpid/examples/perl/spout.pl
@@ -20,7 +20,7 @@
use strict;
use warnings;
-use cqpid_perl;
+use cqpid;
use Getopt::Long;
use Time::Local;
@@ -77,19 +77,19 @@ sub setProperties {
}
}
-my $connection = new cqpid_perl::Connection($url, $connectionOptions);
+my $connection = new cqpid::Connection($url, $connectionOptions);
eval {
$connection->open();
my $session = $connection->createSession();
my $sender = $session->createSender($address);
- my $message = new cqpid_perl::Message();
+ my $message = new cqpid::Message();
setProperties($message) if (@properties);
if (@entries) {
my $content = {};
setEntries($content);
- cqpid_perl::encode($content, $message);
+ cqpid::encode($content, $message);
}
elsif ($content) {
$message->setContent($content);
@@ -98,7 +98,7 @@ eval {
my $receiver;
if ($replyto) {
- my $responseQueue = new cqpid_perl::Address($replyto);
+ my $responseQueue = new cqpid::Address($replyto);
$receiver = $session->createReceiver($responseQueue);
$message->setReplyTo($responseQueue);
}
diff --git a/cpp/bindings/qpid/perl/CMakeLists.txt b/cpp/bindings/qpid/perl/CMakeLists.txt
deleted file mode 100644
index 6edaf284b1..0000000000
--- a/cpp/bindings/qpid/perl/CMakeLists.txt
+++ /dev/null
@@ -1,38 +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.
-#
-
-##------------------------------------------------------
-## 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")
-
-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")
-
-##----------------------------------
-## Install the complete Perl binding
-##----------------------------------
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid_perl.so
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid_perl.pm
- DESTINATION ${PERL_VENDORARCH}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
diff --git a/cpp/bindings/qpid/perl/Makefile.am b/cpp/bindings/qpid/perl/Makefile.am
index da082896e8..982d493ba0 100644
--- a/cpp/bindings/qpid/perl/Makefile.am
+++ b/cpp/bindings/qpid/perl/Makefile.am
@@ -21,22 +21,22 @@ if HAVE_PERL_DEVEL
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src -I$(PERL_INC)
-EXTRA_DIST = CMakeLists.txt perl.i
-BUILT_SOURCES = cqpid_perl.cpp
+EXTRA_DIST = perl.i
+BUILT_SOURCES = cqpid.cpp
SWIG_FLAGS = -w362,401
-cqpid_perl.cpp: $(srcdir)/perl.i $(srcdir)/../qpid.i $(srcdir)/../../swig_perl_typemaps.i
- $(SWIG) -perl -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqpid_perl.cpp $(srcdir)/perl.i
+cqpid.cpp: $(srcdir)/perl.i $(srcdir)/../qpid.i $(srcdir)/../../swig_perl_typemaps.i
+ $(SWIG) -perl -c++ $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I/usr/include -o cqpid.cpp $(srcdir)/perl.i
-lib_LTLIBRARIES = libcqpid_perl.la
-cqpid_perl_PERL = cqpid_perl.pm
+lib_LTLIBRARIES = cqpid.la
+cqpid_PERL = cqpid.pm
-libcqpid_perl_la_LDFLAGS = -avoid-version -shared
-libcqpid_perl_la_LIBADD = -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
+cqpid_la_LDFLAGS = -avoid-version -module -shared
+cqpid_la_LIBADD = -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
$(top_builddir)/src/libqpidmessaging.la $(top_builddir)/src/libqpidtypes.la
-libcqpid_perl_la_CXXFLAGS = $(INCLUDES) -fno-strict-aliasing
-nodist_libcqpid_perl_la_SOURCES = cqpid_perl.cpp
+cqpid_la_CXXFLAGS = $(INCLUDES)
+nodist_cqpid_la_SOURCES = cqpid.cpp
-CLEANFILES = cqpid_perl.cpp cqpid_perl.pm
+CLEANFILES = cqpid.cpp cqpid.pm
endif # HAVE_PERL_DEVEL
diff --git a/cpp/bindings/qpid/perl/perl.i b/cpp/bindings/qpid/perl/perl.i
index 38ac91761f..b7ae0568b6 100644
--- a/cpp/bindings/qpid/perl/perl.i
+++ b/cpp/bindings/qpid/perl/perl.i
@@ -17,7 +17,7 @@
* under the License.
*/
-%module cqpid_perl
+%module cqpid
%include "std_string.i"
%include "../../swig_perl_typemaps.i"
diff --git a/cpp/bindings/qpid/python/CMakeLists.txt b/cpp/bindings/qpid/python/CMakeLists.txt
deleted file mode 100644
index 5e4649cd7c..0000000000
--- a/cpp/bindings/qpid/python/CMakeLists.txt
+++ /dev/null
@@ -1,45 +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.
-#
-
-##------------------------------------------------------
-## 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")
-
-swig_add_module(cqpid python ${CMAKE_CURRENT_SOURCE_DIR}/python.i)
-swig_link_libraries(cqpid 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")
-
-##------------------------------------
-## 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
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cqpid.py
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyc
- ${CMAKE_CURRENT_BINARY_DIR}/cqpid.pyo
- ${CMAKE_CURRENT_BINARY_DIR}/_cqpid.so
- DESTINATION ${PYTHON_SITE_PACKAGES}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
diff --git a/cpp/bindings/qpid/python/Makefile.am b/cpp/bindings/qpid/python/Makefile.am
index dd25f34829..7fa4106be0 100644
--- a/cpp/bindings/qpid/python/Makefile.am
+++ b/cpp/bindings/qpid/python/Makefile.am
@@ -25,17 +25,17 @@ generated_file_list = \
cqpid.cpp \
cqpid.py
-EXTRA_DIST = CMakeLists.txt python.i
+EXTRA_DIST = 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
- $(SWIG) -c++ -python $(SWIG_FLAGS) $(INCLUDES) $(QPID_CXXFLAGS) -I$(top_srcdir)/src/qmf -I/usr/include -o cqpid.cpp $(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 = $(PYTHON_LIB)
lib_LTLIBRARIES = _cqpid.la
-cqpiddir = $(pyexecdir)
+cqpiddir = $(pythondir)
cqpid_PYTHON = cqpid.py
_cqpid_la_LDFLAGS = -avoid-version -module -shared
diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i
index 9d45bf54ee..bf61cb10b7 100644
--- a/cpp/bindings/qpid/python/python.i
+++ b/cpp/bindings/qpid/python/python.i
@@ -21,357 +21,21 @@
%include "std_string.i"
%include "../../swig_python_typemaps.i"
-/* Needed for get/setPriority methods. Surprising SWIG 1.3.40 doesn't
- * convert uint8_t by default. */
-%apply unsigned char { uint8_t };
-
-
-/*
- * Exceptions
- *
- * The convention below is that exceptions in _cqpid.so have the same
- * names as in the C++ library. They get renamed to their Python
- * equivalents when brought into the Python wrapping
- */
-%{
-static PyObject* pNoMessageAvailable;
-static PyObject* pTargetCapacityExceeded;
-static PyObject* pNotFound;
-static PyObject* pTransportFailure;
-%}
-
-%init %{
- pNoMessageAvailable = PyErr_NewException(
- "_cqpid.NoMessageAvailable", NULL, NULL);
- Py_INCREF(pNoMessageAvailable);
- PyModule_AddObject(m, "NoMessageAvailable", pNoMessageAvailable);
-
- pTargetCapacityExceeded = PyErr_NewException(
- "_cqpid.TargetCapacityExceeded", NULL, NULL);
- Py_INCREF(pTargetCapacityExceeded);
- PyModule_AddObject(m, "TargetCapacityExceeded", pTargetCapacityExceeded);
-
- pNotFound = PyErr_NewException(
- "_cqpid.NotFound", NULL, NULL);
- Py_INCREF(pNotFound);
- PyModule_AddObject(m, "NotFound", pNotFound);
-
- pTransportFailure = PyErr_NewException(
- "_cqpid.TransportFailure", NULL, NULL);
- Py_INCREF(pTransportFailure);
- PyModule_AddObject(m, "TransportFailure", pTransportFailure);
-%}
-
-%pythoncode %{
- Empty = _cqpid.NoMessageAvailable
- TargetCapacityExceeded = _cqpid.TargetCapacityExceeded
- NotFound = _cqpid.NotFound
- ConnectError = _cqpid.TransportFailure
-%}
-
/* Define the general-purpose exception handling */
%exception {
- PyObject * pExceptionType = NULL;
std::string error;
Py_BEGIN_ALLOW_THREADS;
try {
$action
- } catch (qpid::messaging::NoMessageAvailable & ex) {
- pExceptionType = pNoMessageAvailable;
- error = ex.what();
- } catch (qpid::messaging::TargetCapacityExceeded & ex) {
- pExceptionType = pTargetCapacityExceeded;
- error = ex.what();
- } catch (qpid::messaging::NotFound & ex) {
- pExceptionType = pNotFound;
- error = ex.what();
- } catch (qpid::messaging::TransportFailure & ex) {
- pExceptionType = pTransportFailure;
- error = ex.what();
} catch (qpid::types::Exception& ex) {
- pExceptionType = PyExc_RuntimeError;
error = ex.what();
}
Py_END_ALLOW_THREADS;
if (!error.empty()) {
- PyErr_SetString(pExceptionType, error.c_str());
+ PyErr_SetString(PyExc_RuntimeError, error.c_str());
return NULL;
}
}
-
-/* This only renames the non-const version (I believe). Then again, I
- * don't even know why there is a non-const version of the method. */
-%rename(opened) qpid::messaging::Connection::isOpen();
-%rename(receiver) qpid::messaging::Session::createReceiver;
-%rename(sender) qpid::messaging::Session::createSender;
-%rename(_acknowledge_all) qpid::messaging::Session::acknowledge(bool);
-%rename(_acknowledge_msg) qpid::messaging::Session::acknowledge(
- Message &, bool);
-
-%rename(_fetch) qpid::messaging::Receiver::fetch;
-%rename(unsettled) qpid::messaging::Receiver::getUnsettled;
-%rename(available) qpid::messaging::Receiver::getAvailable;
-
-%rename(unsettled) qpid::messaging::Sender::getUnsettled;
-%rename(available) qpid::messaging::Sender::getAvailable;
-%rename(_send) qpid::messaging::Sender::send;
-
-%rename(_getReplyTo) qpid::messaging::Message::getReplyTo;
-%rename(_setReplyTo) qpid::messaging::Message::setReplyTo;
-%rename(_getTtl) qpid::messaging::Message::getTtl;
-%rename(_setTtl) qpid::messaging::Message::setTtl;
-
-
%include "../qpid.i"
-%extend qpid::messaging::Connection {
- %pythoncode %{
- # Handle the different options by converting underscores to hyphens.
- # Also, the sasl_mechanisms option in Python has no direct
- # equivalent in C++, so we will translate them to sasl_mechanism
- # when possible.
- def __init__(self, url=None, **options):
- args = [url] if url else []
- if options :
- if "sasl_mechanisms" in options :
- if ' ' in options.get("sasl_mechanisms",'') :
- raise Exception(
- "C++ Connection objects are unable to handle "
- "multiple sasl-mechanisms")
- options["sasl_mechanism"] = options.pop("sasl_mechanisms")
- args.append(options)
- this = _cqpid.new_Connection(*args)
- try: self.this.append(this)
- except: self.this = this
- %}
-
- /* Return a pre-existing session with the given name, if one
- * exists, otherwise return a new one. (Note that if a
- * pre-existing session exists, the transactional argument is
- * ignored, and the returned session might not satisfy the desired
- * setting. */
- qpid::messaging::Session _session(const std::string & name,
- bool transactional) {
- if (!name.empty()) {
- try {
- return self->getSession(name);
- }
- catch (const qpid::messaging::KeyError &) {
- }
- }
- if (transactional) {
- return self->createTransactionalSession(name);
- }
- else {
- return self->createSession(name);
- }
- }
-
- %pythoncode %{
- def session(self, name=None, transactional=False) :
- if name is None :
- name = ''
- return self._session(name, transactional)
- %}
-
- %pythoncode %{
- @staticmethod
- def establish(url=None, **options) :
- conn = Connection(url, **options)
- conn.open()
- return conn
- %}
-}
-
-%extend qpid::messaging::Session {
- %pythoncode %{
- def acknowledge(self, message=None, disposition=None, sync=True) :
- if disposition :
- raise Exception("SWIG does not support dispositions yet. Use "
- "Session.reject and Session.release instead")
- if message :
- self._acknowledge_msg(message, sync)
- else :
- self._acknowledge_all(sync)
-
- __swig_getmethods__["connection"] = getConnection
- if _newclass: connection = _swig_property(getConnection)
- %}
-}
-
-
-%extend qpid::messaging::Receiver {
- %pythoncode %{
- __swig_getmethods__["capacity"] = getCapacity
- __swig_setmethods__["capacity"] = setCapacity
- if _newclass: capacity = _swig_property(getCapacity, setCapacity)
-
- __swig_getmethods__["session"] = getSession
- if _newclass: session = _swig_property(getSession)
- %}
-
- %pythoncode %{
- def fetch(self, timeout=None) :
- if timeout is None :
- return self._fetch()
- else :
- # Python API uses timeouts in seconds,
- # but C++ API uses milliseconds
- return self._fetch(Duration(int(1000*timeout)))
- %}
-}
-
-%extend qpid::messaging::Sender {
- %pythoncode %{
- def send(self, object, sync=True) :
- if isinstance(object, Message):
- message = object
- else:
- message = Message(object)
- return self._send(message, sync)
-
- __swig_getmethods__["capacity"] = getCapacity
- __swig_setmethods__["capacity"] = setCapacity
- if _newclass: capacity = _swig_property(getCapacity, setCapacity)
-
- __swig_getmethods__["session"] = getSession
- if _newclass: session = _swig_property(getSession)
- %}
-}
-
-
-%extend qpid::messaging::Message {
- %pythoncode %{
- # UNSPECIFIED was module level before, but I do not
- # know how to insert python code at the top of the module.
- # (A bare "%pythoncode" inserts at the end.
- UNSPECIFIED=object()
- def __init__(self, content=None, content_type=UNSPECIFIED, id=None,
- subject=None, user_id=None, reply_to=None,
- correlation_id=None, durable=None, priority=None,
- ttl=None, properties=None):
- this = _cqpid.new_Message('')
- try: self.this.append(this)
- except: self.this = this
- if content :
- self.content = content
- if content_type != UNSPECIFIED :
- self.content_type = content_type
- if id is not None :
- self.id = id
- if subject is not None :
- self.subject = subject
- if user_id is not None :
- self.user_id = user_id
- if reply_to is not None :
- self.reply_to = reply_to
- if correlation_id is not None :
- self.correlation_id = correlation_id
- if durable is not None :
- self.durable = durable
- if priority is not None :
- self.priority = priority
- if ttl is not None :
- self.ttl = ttl
- if properties is not None :
- # Can't set properties via (inst).getProperties, because
- # the typemaps make a copy of the underlying properties.
- # Instead, set via setProperty for the time-being
- for k, v in properties.iteritems() :
- self.setProperty(k, v)
-
- def _get_content(self) :
- if self.content_type == "amqp/list" :
- return decodeList(self)
- if self.content_type == "amqp/map" :
- return decodeMap(self)
- return self.getContent()
- def _set_content(self, content) :
- if isinstance(content, basestring) :
- self.setContent(content)
- elif isinstance(content, list) or isinstance(content, dict) :
- encode(content, self)
- else :
- # Not a type we can handle. Try setting it anyway,
- # although this will probably lead to a swig error
- self.setContent(content)
- __swig_getmethods__["content"] = _get_content
- __swig_setmethods__["content"] = _set_content
- if _newclass: content = _swig_property(_get_content, _set_content)
-
- __swig_getmethods__["content_type"] = getContentType
- __swig_setmethods__["content_type"] = setContentType
- if _newclass: content_type = _swig_property(getContentType,
- setContentType)
-
- __swig_getmethods__["id"] = getMessageId
- __swig_setmethods__["id"] = setMessageId
- if _newclass: id = _swig_property(getMessageId, setMessageId)
-
- __swig_getmethods__["subject"] = getSubject
- __swig_setmethods__["subject"] = setSubject
- if _newclass: subject = _swig_property(getSubject, setSubject)
-
- __swig_getmethods__["priority"] = getPriority
- __swig_setmethods__["priority"] = setPriority
- if _newclass: priority = _swig_property(getPriority, setPriority)
-
- def getTtl(self) :
- return self._getTtl().getMilliseconds()/1000.0
- def setTtl(self, duration) :
- self._setTtl(Duration(int(1000*duration)))
- __swig_getmethods__["ttl"] = getTtl
- __swig_setmethods__["ttl"] = setTtl
- if _newclass: ttl = _swig_property(getTtl, setTtl)
-
- __swig_getmethods__["user_id"] = getUserId
- __swig_setmethods__["user_id"] = setUserId
- if _newclass: user_id = _swig_property(getUserId, setUserId)
-
- __swig_getmethods__["correlation_id"] = getCorrelationId
- __swig_setmethods__["correlation_id"] = setCorrelationId
- if _newclass: correlation_id = _swig_property(getCorrelationId,
- setCorrelationId)
-
- __swig_getmethods__["redelivered"] = getRedelivered
- __swig_setmethods__["redelivered"] = setRedelivered
- if _newclass: redelivered = _swig_property(getRedelivered,
- setRedelivered)
-
- __swig_getmethods__["durable"] = getDurable
- __swig_setmethods__["durable"] = setDurable
- if _newclass: durable = _swig_property(getDurable, setDurable)
-
- __swig_getmethods__["properties"] = getProperties
- if _newclass: properties = _swig_property(getProperties)
-
- def getReplyTo(self) :
- return self._getReplyTo().str()
- def setReplyTo(self, address_str) :
- self._setReplyTo(Address(address_str))
- __swig_getmethods__["reply_to"] = getReplyTo
- __swig_setmethods__["reply_to"] = setReplyTo
- if _newclass: reply_to = _swig_property(getReplyTo, setReplyTo)
-
- def __repr__(self):
- args = []
- for name in ["id", "subject", "user_id", "reply_to",
- "correlation_id", "priority", "ttl",
- "durable", "redelivered", "properties",
- "content_type"] :
- value = getattr(self, name)
- if value : args.append("%s=%r" % (name, value))
- if self.content is not None:
- if args:
- args.append("content=%r" % self.content)
- else:
- args.append(repr(self.content))
- return "Message(%s)" % ", ".join(args)
- %}
-}
-
-%pythoncode %{
-# Bring into module scope
-UNSPECIFIED = Message.UNSPECIFIED
-%}
diff --git a/cpp/bindings/qpid/qpid.i b/cpp/bindings/qpid/qpid.i
index 352bafa3c8..e60ce1ce7c 100644
--- a/cpp/bindings/qpid/qpid.i
+++ b/cpp/bindings/qpid/qpid.i
@@ -27,7 +27,6 @@
#include <qpid/messaging/Sender.h>
#include <qpid/messaging/Message.h>
#include <qpid/messaging/Duration.h>
-#include <qpid/messaging/FailoverUpdates.h>
//
// Wrapper functions for map-decode and list-decode. This allows us to avoid
@@ -49,7 +48,6 @@ qpid::types::Variant::List& decodeList(const qpid::messaging::Message& msg) {
%}
-%include <qpid/ImportExport.h>
%include <qpid/messaging/ImportExport.h>
%include <qpid/messaging/Address.h>
%include <qpid/messaging/Duration.h>
@@ -58,7 +56,6 @@ qpid::types::Variant::List& decodeList(const qpid::messaging::Message& msg) {
%include <qpid/messaging/Sender.h>
%include <qpid/messaging/Session.h>
%include <qpid/messaging/Connection.h>
-%include <qpid/messaging/FailoverUpdates.h>
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/.gitignore b/cpp/bindings/qpid/ruby/.gitignore
deleted file mode 100644
index ab78513491..0000000000
--- a/cpp/bindings/qpid/ruby/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-pkg
-html
diff --git a/cpp/bindings/qpid/ruby/CMakeLists.txt b/cpp/bindings/qpid/ruby/CMakeLists.txt
deleted file mode 100644
index 25258cfc6a..0000000000
--- a/cpp/bindings/qpid/ruby/CMakeLists.txt
+++ /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.
-#
-
-##--------------------------------------------------
-## Properties used for generating the Ruby bindings.
-##--------------------------------------------------
-set(GEM_BINDINGS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/cqpid)
-set(GEM_BINDINGS_SOURCE_FILE ${GEM_BINDINGS_SOURCE_DIR}/cqpid.cpp)
-set(GEM_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
-set(GEM_OUTPUT_FILE ${GEM_OUTPUT_PATH}/pkg/qpid-${qpidc_version}.0.gem)
-
-
-##------------------------------------------------------
-## Use Swig to generate a literal binding to the C++ API
-##------------------------------------------------------
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES CPLUSPLUS ON)
-set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/ruby.i PROPERTIES SWIG_FLAGS "-I${qpid-cpp_SOURCE_DIR}/include")
-
-swig_add_module(cqpid ruby ${CMAKE_CURRENT_SOURCE_DIR}/ruby.i)
-swig_link_libraries(cqpid qpidmessaging qpidtypes qmf2 ${RUBY_LIBRARY})
-
-set_source_files_properties(${swig_generated_file_fullname} PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -I${RUBY_INCLUDE_DIR} -I${qpid-cpp_SOURCE_DIR}/include")
-
-##----------------------------------
-## Install the complete Ruby binding
-##----------------------------------
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcqpid.so
- RENAME cqpid.so
- DESTINATION ${RUBY_SITEARCH_DIR}
- COMPONENT ${QPID_COMPONENT_CLIENT}
- )
-
-add_custom_command(OUTPUT ${GEM_BINDINGS_SOURCE_FILE}
- COMMAND cp ${swig_generated_file_fullname} ${GEM_BINDINGS_SOURCE_FILE}
- DEPENDS ${swig_generated_file_fullname}
- )
-
-add_custom_command(OUTPUT ${GEM_OUTPUT_FILE}
- COMMAND OUTPUT_DIR=${GEM_OUTPUT_PATH} rake clean clobber package
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS ${swig_generated_file_fullname} ${GEM_BINDINGS_SOURCE_FILE}
- )
-
-add_custom_target(gemfile
- DEPENDS ${GEM_OUTPUT_FILE}
- )
-
diff --git a/cpp/bindings/qpid/ruby/LICENSE b/cpp/bindings/qpid/ruby/LICENSE
deleted file mode 100644
index cff2a5e25d..0000000000
--- a/cpp/bindings/qpid/ruby/LICENSE
+++ /dev/null
@@ -1,234 +0,0 @@
-=========================================================================
-== 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.
-
-=========================================================================
-== Boost License ==
-=========================================================================
-
-Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
diff --git a/cpp/bindings/qpid/ruby/Makefile.am b/cpp/bindings/qpid/ruby/Makefile.am
index a2a5dd76bd..67a3615362 100644
--- a/cpp/bindings/qpid/ruby/Makefile.am
+++ b/cpp/bindings/qpid/ruby/Makefile.am
@@ -21,7 +21,7 @@ if HAVE_RUBY_DEVEL
INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src -I$(top_builddir)/src
-EXTRA_DIST = CMakeLists.txt ruby.i
+EXTRA_DIST = ruby.i
BUILT_SOURCES = cqpid.cpp
SWIG_FLAGS = -w362,401
@@ -33,10 +33,10 @@ cqpid.cpp: $(srcdir)/ruby.i $(srcdir)/../qpid.i $(srcdir)/../../swig_ruby_typema
rubylibarchdir = $(RUBY_LIB_ARCH)
rubylibarch_LTLIBRARIES = cqpid.la
-cqpid_la_LDFLAGS = -avoid-version -module -shared -shrext ".$(RUBY_DLEXT)"
+cqpid_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)"
cqpid_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidmessaging -lqpidtypes \
$(top_builddir)/src/libqpidmessaging.la $(top_builddir)/src/libqpidtypes.la
-cqpid_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+cqpid_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_cqpid_la_SOURCES = cqpid.cpp
CLEANFILES = cqpid.cpp
diff --git a/cpp/bindings/qpid/ruby/README.rdoc b/cpp/bindings/qpid/ruby/README.rdoc
deleted file mode 100644
index 0ae7e5cbed..0000000000
--- a/cpp/bindings/qpid/ruby/README.rdoc
+++ /dev/null
@@ -1,45 +0,0 @@
-= Qpid - Open Source AMQP Messaging
-
-Qpid is an cross-platform enterprise messaging system.
-
-Version :: 0.10.0.alpha.0
-
-= Links
-
-Documents :: http://qpid.apache.org/
-
-= Installation
-
-You can install Qpid with the following command.
-
- $ gem install qpid
-
-== Building The Native Code
-
-The Qpid gem requires that you have available the Qpid libraries and
-development header files. To install them, please see:
-
-http://cwiki.apache.org/qpid/developer-pages.html
-
-If you are building the gem within the Qpid development environment
-itself, you can specify the location of the Qpid headers and
-libraries with:
-
-$ ruby extconfig.rb --with-qpid-lib=[path to libqpidclient.so, etc.]
-$ make
-
-== Examples
-
-Take a look at the integration tests for examples on how to leverage
-the messaging capabilities of Qpid in your Ruby applications.
-
-== 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.
-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 07cfff9844..0000000000
--- a/cpp/bindings/qpid/ruby/Rakefile
+++ /dev/null
@@ -1,130 +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"
-
-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:all"
-
-#---------------
-# Testing tasks.
-#---------------
-
-desc "Run all tests (alias for test:all)."
-task :test => :"test:all"
-
-namespace :test do
- desc "Run all tests (default)."
- task :all => [:units, :integrations]
-
- desc "Run unit tests."
- Rake::TestTask.new(:units) do |t|
- t.libs << "."
- t.pattern = "test/test*.rb"
- t.verbose = true
- end
-
- desc "Run integration tests."
- Rake::TestTask.new(:integrations) do |t|
- t.libs << "."
- t.pattern = "test/integration/*.rb"
- t.verbose = true
- 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/**/*"]
-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
deleted file mode 100644
index 454aac9200..0000000000
--- a/cpp/bindings/qpid/ruby/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO Items
------------------------------------------------------------------------------
-
-Version 0.11.0:
- * Deliver the Ruby bindings as a gem.
- * Rework the blocking tasks to not bring the main thread to a halt.
-
diff --git a/cpp/bindings/qpid/ruby/examples/client.rb b/cpp/bindings/qpid/ruby/examples/client.rb
deleted file mode 100644
index f42f25cfc9..0000000000
--- a/cpp/bindings/qpid/ruby/examples/client.rb
+++ /dev/null
@@ -1,50 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-if __FILE__ == $0
- broker = ARGV[1] || "amqp:tcp:localhost:5672"
- options = ARGV[2] || ""
-
- connection = Qpid::Messaging::Connection.new broker, options
- connection.open
- session = connection.create_session
- sender = session.create_sender "service_queue"
- response_queue = Qpid::Messaging::Address.new("#response-queue", "",
- :create => :always,
- :delete => :always)
- receiver = session.create_receiver response_queue
-
- ["Twas brillig, and the slithy toves",
- "Did gire and gymble in the wabe.",
- "All mimsy were the borogroves,",
- "And the mome raths outgrabe."].each do |line|
- request = Qpid::Messaging::Message.new :content => line
- request.reply_to = response_queue
- sender.send request
- response = receiver.fetch
- puts "#{request.content} -> #{response.content}"
- end
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/drain.rb b/cpp/bindings/qpid/ruby/examples/drain.rb
deleted file mode 100644
index a6cf35e189..0000000000
--- a/cpp/bindings/qpid/ruby/examples/drain.rb
+++ /dev/null
@@ -1,111 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-require 'optparse'
-
-options = {
- :broker => "localhost",
- :timeout => Qpid::Messaging::Duration::IMMEDIATE,
- :count => 1,
- :forever => false,
- :connection_options => ""
-}
-
-opts = OptionParser.new do |opts|
- opts.banner = "Usage: drain.rb [OPTIONS] ADDRESS"
-
- opts.separator ""
- opts.separator "Drains messages from the specified address"
- opts.separator ""
-
- opts.on("-h", "--help",
- "show this message") do
- puts opts
- exit
- end
-
- opts.on("-b", "--broker VALUE",
- "url of broker to connect to") do |broker|
- options[:broker] = broker
- end
-
- opts.on("-t", "--timeout VALUE", Integer,
- "timeout in seconds to wait before exiting") do |timeout|
- options[:timeout] = Qpid::Messaging::Duration.new timeout * 1000
- end
-
- opts.on("-f", "--forever",
- "ignore timeout and wait forever") do
- options[:forever] = true
- end
-
- opts.on("--connection-options VALUE",
- "connection options string in the form {name1:value,name2:value2}") do |conopts|
- options[:connection_options] = conopts
- end
-
- opts.on("-c", "--count VALUE", Integer,
- "number of messages to read before exiting") do |count|
- options[:count] = count
- end
-end
-
-opts.parse!(ARGV)
-
-options[:address] = ARGV[0] || ""
-
-connection = Qpid::Messaging::Connection.new options[:broker], options[:connection_options]
-connection.open
-
-def render_map map
- print "{"
- map.keys.sort.each_with_index {|key,index| print "#{index > 0 ? ', ' : ''}#{key}:#{map[key]}"}
- print "}"
-end
-
-begin
- session = connection.create_session
- receiver = session.create_receiver options[:address]
- done = false
- count = 0
- options[:timeout] = Qpid::Messaging::Duration::FOREVER if options[:forever]
-
- while !done && (count < options[:count])
- message = receiver.fetch(options[:timeout])
- print "Message(properties="
- render_map message.properties
- print ", content="
- if message.content_type == "amqp/map"
- print "'#{render_map message.content}')"
- else
- print "'#{message.content}'"
- end
- print ")\n"
- session.acknowledge message
- count += 1
- end
-rescue Exception => error
- puts "Exception: #{error.to_s}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/hello_world.rb b/cpp/bindings/qpid/ruby/examples/hello_world.rb
deleted file mode 100644
index 703febeba1..0000000000
--- a/cpp/bindings/qpid/ruby/examples/hello_world.rb
+++ /dev/null
@@ -1,49 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-# This is your classic Hello World application, written in
-# Ruby, that uses Qpid. It demonstrates how to send and
-# also receive messages.
-#
-if __FILE__ == $0
- broker = ARGV[0] || "localhost:5672"
- address = ARGV[1] || "amq.topic"
- options = ARGV[2] || ""
-
- connection = Qpid::Messaging::Connection.new broker
- connection.open
- session = connection.create_session
- receiver = session.create_receiver address
- sender = session.create_sender address
-
- # Send a simple message
- sender.send Qpid::Messaging::Message.new :content => "Hello world!"
-
- # Now receive the message
- message = receiver.fetch Qpid::Messaging::Duration::SECOND
- puts "#{message.content}"
- session.acknowledge
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/map_receiver.rb b/cpp/bindings/qpid/ruby/examples/map_receiver.rb
deleted file mode 100644
index 805943a0a4..0000000000
--- a/cpp/bindings/qpid/ruby/examples/map_receiver.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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672"
-address = ARGV[1] || "message_queue; {create: always}"
-options = ARGV[2] || ""
-
-connection = Qpid::Messaging::Connection.new broker, options
-connection.open
-
-def display_value value
- case value
- when Array
- result = ""
- value.each_with_index {|element, index| result += "#{', ' if index > 0}#{element}"}
- return "[#{result}]"
- end
-
- value.to_s
-end
-
-begin
- session = connection.create_session
- receiver = session.create_receiver address
-
- message = receiver.fetch
- content = message.content
-
- print "content-type:#{message.content_type}"
- print "{"
- content.keys.sort.each_with_index do |key, index|
- print "#{', ' if index > 0}#{key}:#{display_value content[key]}"
- end
- print "}\n"
-
- session.acknowledge
-
-rescue Exception => error
- puts "Exception: #{error.message}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/map_sender.rb b/cpp/bindings/qpid/ruby/examples/map_sender.rb
deleted file mode 100644
index fa0c6e4562..0000000000
--- a/cpp/bindings/qpid/ruby/examples/map_sender.rb
+++ /dev/null
@@ -1,52 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-broker = ARGV[0] || "amqp:tcp:127.0.0.1:5672"
-address = ARGV[1] || "message_queue; {create: always}"
-options = ARGV[2] || []
-
-connection = Qpid::Messaging::Connection.new broker, options
-connection.open
-
-begin
- session = connection.create_session
- sender = session.create_sender address
- message = Qpid::Messaging::Message.new
-
- content = {
- :id => 987654321,
- :name => "Widget",
- :percent => 0.99,
- :colors => ["red", "green", "blue"]
- }
-
- message.content = content
-
- sender.send message
-
-rescue Exception => error
- puts "Exception: #{error.message}"
-end
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/examples/server.rb b/cpp/bindings/qpid/ruby/examples/server.rb
deleted file mode 100644
index ead9d58472..0000000000
--- a/cpp/bindings/qpid/ruby/examples/server.rb
+++ /dev/null
@@ -1,51 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-if __FILE__ == $0
- broker = ARGV[0] || "amqp:tcp:localhost:5672"
- options = ARGV[1] || ""
-
- connection = Qpid::Messaging::Connection.new broker, options
- connection.open
- session = connection.create_session
- receiver = session.create_receiver "service_queue; {create:always}"
-
- loop do
- request = receiver.fetch
- address = request.reply_to
-
- if !address.nil?
- sender = session.create_sender address
- response = Qpid::Messaging::Message.new :content => request.content.upcase
- sender.send response
- puts "Processed request: #{request.content} -> #{response.content}"
- session.acknowledge
- else
- puts "Error: no reply address specified for request: #{request.content}"
- session.reject request
- end
- end
-
- connection.close
-end
-
diff --git a/cpp/bindings/qpid/ruby/examples/spout.rb b/cpp/bindings/qpid/ruby/examples/spout.rb
deleted file mode 100644
index c012e31f9d..0000000000
--- a/cpp/bindings/qpid/ruby/examples/spout.rb
+++ /dev/null
@@ -1,126 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-require 'optparse'
-
-options = {
- :broker => "127.0.0.1",
- :address => "",
- :timeout => 0,
- :count => 1,
- :properties => {},
- :content => nil,
- :mapped => {}
-}
-
-opts = OptionParser.new do |opts|
- opts.banner = "Usage: spout.rb [OPTIONS] ADDRESS"
-
- opts.on("-h", "--help",
- "show this message") do |help|
- puts opts
- exit
- end
-
- opts.on("-b","--broker VALUE",
- "url of broker to connect to ") do |broker|
- options[:broker] = broker
- end
-
- opts.on("-t", "--timeout VALUE", Integer,
- "exit after the specified time") do |timeout|
- options[:timeout] = Qpid::Messaging::Duration.new timeout * 1000
- end
-
- opts.on("-c", "--count VALUE", Integer,
- "stop after count messages have been sent, zero disables") do |count|
- options[:count] = count
- end
-
- opts.on("-i", "--id VALUE",
- "use the supplied id instead of generating one") do |id|
- options[:id] = id
- end
-
- opts.on("--reply-to VALUE",
- "specify reply-to address") do |replyto|
- options[:replyto] = replyto
- end
-
- opts.on("-P", "--property VALUE",
- "specify message property") do |property|
- name = property.split(/=/)[0]
- value = property.split(/=/)[1]
- options[:properties][name] = value
- end
-
- opts.on("-M", "--map VALUE",
- "specify entry for map content") do |mapped|
- name = mapped.split(/=/)[0]
- value = mapped.split(/=/)[1]
- options[:mapped][name] = value
- end
-
- opts.on("--content VALUE",
- "specify textual content") do |content|
- options[:content] = content
- end
-
- opts.on(nil, "--connection-options VALUE",
- "connection options string in the form {name1:value1, name2:value2}") do |conopts|
- options[:connection_options] = conopts
- end
-end
-
-begin
- opts.parse!(ARGV)
-rescue => error
- opts.parse(["-h"])
-end
-
-# now get the non-arg options
-options[:address] = ARGV[0] unless ARGV[0].nil?
-
-connection = Qpid::Messaging::Connection.new options[:broker], options[:connection_options]
-connection.open
-session = connection.create_session
-sender = session.create_sender options[:address]
-message = Qpid::Messaging::Message.new
-
-options[:properties].each_key {|key| message.properties[key] = options[:properties][key]}
-
-(1..options[:count]).each do |count|
- if !options[:mapped].keys.empty?
- message.content = options[:mapped]
- elsif options[:content]
- message.content = options[:content]
- end
- message.content = options[:content] unless options[:content].nil?
- message.properties["spout-id"] = "#{count}"
- message.reply_to = options[:replyto] unless options[:replyto].nil? || options[:replyto].empty?
- sender.send message
-end
-
-# session.sync
-
-connection.close
-
diff --git a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb b/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb
deleted file mode 100644
index 90292d4bec..0000000000
--- a/cpp/bindings/qpid/ruby/ext/cqpid/extconf.rb
+++ /dev/null
@@ -1,73 +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.
-#
-
-# To create the Makefile then you need to specify the location
-# of the Qpid shared libraries using the commandline:
-#
-# $ ruby extconf.rb --with-qpid-lib=[path to libraries]
-#
-
-require 'mkmf'
-
-# Setup the build environment.
-$CFLAGS = "-fPIC -fno-inline -x c++"
-
-REQUIRED_LIBRARIES = [
- 'qpidclient',
- 'qpidcommon',
- 'qpidmessaging',
- 'qpidtypes'
- ]
-
-REQUIRED_HEADERS = [
- 'qpid/messaging/Address.h',
- 'qpid/messaging/Connection.h',
- 'qpid/messaging/Duration.h',
- 'qpid/messaging/exceptions.h',
- 'qpid/messaging/FailoverUpdates.h',
- 'qpid/messaging/Handle.h',
- 'qpid/messaging/ImportExport.h',
- 'qpid/messaging/Message.h',
- 'qpid/messaging/Receiver.h',
- 'qpid/messaging/Sender.h',
- 'qpid/messaging/Session.h'
- ]
-
-dir_config('qpid')
-
-def abort_build filetype, filename
- abort "Missing required #{filetype}: #{filename}"
-end
-
-def require_library lib
- abort_build "library", lib unless have_library lib
-end
-
-def require_header header
- abort_build "header", header unless have_header header
-end
-
-have_library('stdc++')
-
-REQUIRED_LIBRARIES.each {|library| require_library library}
-
-REQUIRED_HEADERS.each {|header| require_header header}
-
-create_makefile('cqpid')
-
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 73b61bb1c7..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/address.rb
+++ /dev/null
@@ -1,125 +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:
- #
- # <address> [ / <subject> ] ; [ { <key> : <value> , ... } ]
- #
- # 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
-
- 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.
- def name; @address_impl.getName; end
-
- # Sets the name.
- def name=(name); @address_impl.setName name; end
-
- # Returns the subject.
- def subject; @address_impl.getSubject; end
-
- # Sets the subject.
- def subject=(subject); @address_impl.setSubject(subject); end
-
- # Returns the type.
- #---
- # We cannot use "type" since that clashes with the Ruby object.type
- # identifier.
- def _type; @address_impl.getType; end
-
- # Sets the type.
- #
- # 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.
- def _type=(_type); @address_impl.setType(_type); end
-
- # Returns the options.
- def options; @address_impl.getOptions; end
-
- # Sets the options for the address.
- # Any symbols are converted to strings.
- def options=(options); @address_impl.setOptions(convert_options(options)); end
-
- def to_s; @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 5c56c1f5d0..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/connection.rb
+++ /dev/null
@@ -1,134 +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
-
- # Connection allows for establishing connections to a remote endpoint.
- class Connection
-
- # The following general options are supported (as strings or symbols):
- #
- # username::
- # password::
- # heartbeat::
- # tcp_nodelay::
- # sasl_mechanism::
- # sasl_service::
- # sasl_min_ssf::
- # sasl_max_ssf::
- # transport::
- #
- # The following options specifically control reconnection behavior:
- #
- # reconnect:: *true* or *false*; 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 reconnecting
- # reconnect_interval_max:: number of seconds to wait before additional reconnect attempts
- # reconnect_interval:: shorthand for setting box min and max values
- # reconnect_urls:: a list of alternate URLs to use for reconnection attempts
- def initialize(url, options = {}, connection_impl = nil)
- @url = url
- @connection_impl = connection_impl
- @options = options
- end
-
- def connection_impl # :nodoc:
- @connection_impl
- end
-
- # Opens the connection.
- def open
- @connection_impl = Cqpid::Connection.new(@url, convert_options)
- @connection_impl.open
- end
-
- # Reports whether the connection is open.
- def open?; false || (@connection_impl.isOpen if @connection_impl); end
-
- # Closes the connection.
- def close; @connection_impl.close if open?; end
-
- # Creates a new session.
- #
- # If :transactional => true then a transactional session is created.
- # Otherwise a standard session is created.
- 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(session)
- else
- raise RuntimeError.new "No connection available."
- end
- end
-
- # Returns a session for the specified session name.
- def session name
- session_impl = @connection_impl.getSession name
- Qpid::Messaging::Session.new session_impl if session_impl
- end
-
- # Returns the username used to authenticate with the connection.
- def authenticated_username; @connection_impl.getAuthenticatedUsername if open?; end
-
- # inherited from Handle
-
- # Returns whether the underlying handle is valid; i.e., not null.
- def valid?
- @connection_impl.isValid
- end
-
- # Returns whether the underlying handle is null.
- def null?
- @connection_impl.isNull
- end
-
- # Swaps the underlying connection handle.
- def swap connection
- @connection_impl.swap connection.connection_impl
- end
-
- private
-
- def convert_options
- result = {}
- # map only those options defined in the C++ layer
- # TODO when new options are added, this needs to be updated.
- 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 c1f44e9281..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/duration.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 '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
- # :IMMEDIATE :: an alias for 0
- # :SECOND :: 1,000ms
- # :MINUTE :: 60,000ms
- class Duration
-
- def initialize duration # :nodoc:
- @duration_impl = Cqpid::Duration.new duration
- end
-
- def duration_impl # :nodoc:
- @duration_impl
- 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 c8b843b597..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/encoding.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 '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
- 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 7a16d08d84..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/errors.rb
+++ /dev/null
@@ -1,30 +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
-
- 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 9b1b68c7c3..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/message.rb
+++ /dev/null
@@ -1,157 +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
-
- # Message represents a message.
- class Message
-
- def initialize(args = {}, message_impl = nil)
- @message_impl = message_impl
- @message_impl = Cqpid::Message.new if @message_impl.nil?
- @message_impl.setContent args[:content].to_s if args[:content]
- @content = nil
- end
-
- def message_impl # :nodoc:
- @message_impl
- end
-
- # Assigns the reply to address.
- # The address must be an instance of Address.
- def reply_to=(address); @message_impl.setReplyTo address.address_impl; end
-
- # Returns the reply to address for the message as an instance of +Address+.
- 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.
- def subject=(subject); @message_impl.setSubject subject; end
-
- # Returns the subject.
- def subject; @message_impl.getSubject; end
-
- # Sets the content type.
- def content_type=(content_type); @message_impl.setContentType content_type; end
-
- # Returns the content type.
- def content_type; @message_impl.getContentType; end
-
- # Sets the message id.
- 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.
- def user_id=(user_id); @message_impl.setUserId user_id; end
-
- # Returns the user id.
- def user_id; @message_impl.getUserId; end
-
- # Sets the correlation id.
- def correlation_id=(correlation_id); @message_impl.setCorrelationId correlation_id; end
-
- # Returns the correlation id.
- def correlation_id; @message_impl.getCorrelationId; end
-
- # Sets the priority.
- def priority=(priority); @message_impl.setPriority priority; end
-
- # Returns the priority.
- def priority; @message_impl.getPriority; end
-
- # Sets the time-to-live in milliseconds.
- def ttl=(duration); @message_impl.setTtl duration; end
-
- # Returns the time-to-live in milliseconds.
- def ttl; @message_impl.getTtl; end
-
- # Sets the durability.
- def durable=(durable); @message_impl.setDurable durable; end
-
- # Returns the durability.
- def durable; @message_impl.getDurable; end
-
- # Allows marking the message as redelivered.
- def redelivered=(redelivered); @message_impl.setRedelivered redelivered; end
-
- # Returns if the message was redelivered.
- def redelivered; @message_impl.getRedelivered; end
-
- # Returns all named properties.
- # *NOTE:* It is recommended to use the +foo[key]+ method for
- # retrieving properties.
- def properties; @message_impl.getProperties; end
-
- # Returns the value for the named property.
- def [](key); self.properties[key.to_s]; end
-
- # Assigns a value to the named property.
- def []=(key, value); @message_impl.setProperty(key.to_s, value.to_s); end
-
- # Sets the content.
- def content=(content)
- content_type = nil
- @content = 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.
- 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 d498aa922b..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/receiver.rb
+++ /dev/null
@@ -1,102 +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 defines a type for receiving messages.
- class Receiver
-
- def initialize(receiver_impl) # :nodoc:
- @receiver_impl = receiver_impl
- end
-
- def receiver_impl # :nodoc:
- @receiver_impl
- end
-
- # Retrieves a message from the receiver's local queue, or waits
- # for up to the duration specified for one to become available.
- 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.
- 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 for a receiver determines the number of messages that
- # can be held in the receiver before being fetched.
- def capacity=(capacity); @receiver_impl.setCapacity capacity; end
-
- # Returns the capacity.
- def capacity; @receiver_impl.getCapacity; end
-
- # Returns the number of available messages waiting to be fetched.
- 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
-
- # Cancels the reciever.
- def close; @receiver_impl.close; end
-
- # Returns whether the receiver is closed.
- def closed?; @receiver_impl.isClosed; end
-
- # Returns the name of the receiver
- def name; @receiver_impl.getName; end
-
- # Returns the Session for this receiver.
- def session; Qpid::Messaging::Session.new(@receiver_impl.getSession); end
-
- # Returns whether the underlying handle is valid.
- def valid?; @receiver_impl.isValid; end
-
- # Returns whether the underlying handle is null.
- def null?; @receiver_impl.isNull; end
-
- def swap receiver
- @receiver_impl.swap receiver.receiver_impl
- end
-
- private
-
- def create_message_wrapper message_impl
- Qpid::Messaging::Message.new({}, 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 5d59c20d7e..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/sender.rb
+++ /dev/null
@@ -1,82 +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 defines a type for sending messages.
- class Sender
-
- def initialize(sender_impl) # :nodoc:
- @sender_impl = sender_impl
- end
-
- def sender_impl # :nodoc:
- @sender_impl
- end
-
- # Sends a message.
- def send(message, args = {})
- block = args[:block] || false
- @sender_impl.send message.message_impl, block
- end
-
- # Closes the sender.
- def close; @sender_impl.close; end
-
- # Returns the name for the sender.
- def name; @sender_impl.getName; end
-
- # Sets the capacity for the sender, which is the number of outgoing
- # messages that can be held pending confirmation or receipt by
- # the broker.
- 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 capacity for sending messages.
- def available
- @sender_impl.getAvailable
- end
-
- # Returns the Session for this sender.
- def session; Qpid::Messaging::Session.new @sender_impl.getSession; end
-
- # Returns if the underlying sender is valid.
- def valid?; @sender_impl.isValid; end
-
- # Returns if the underlying sender is null.
- def null?; @sender_impl.isNull; end
-
- def swap sender
- @sender_impl.swap sender.sender_impl
- 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 543c26cc70..0000000000
--- a/cpp/bindings/qpid/ruby/lib/qpid/session.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/errors'
-
-module Qpid
-
- module Messaging
-
- # A Session represents a distinct conversation between end points.
- class Session
-
- def initialize(session) # :nodoc:
- @session_impl = session
- end
-
- def session_impl # :nodoc:
- @session_impl
- end
-
- # Returns the +Connection+ for the +Session+.
- def connection
- connection_impl = @session_impl.getConnection
- Qpid::Messaging::Connection.new "", {}, connection_impl
- end
-
- # Creates a new endpoint for sending messages.
- def create_sender(address)
- _address = address
-
- if address.class == Qpid::Messaging::Address
- _address = address.address_impl
- end
-
- Qpid::Messaging::Sender.new(@session_impl.createSender(_address))
- end
-
- # Retrieves the +Sender+ with the specified name.
- def sender(name)
- result = nil
-
- begin
- sender_impl = @session_impl.getSender name
- result = Sender.for_impl sender_impl
- rescue
- # treat any error as a key error
- end
-
- raise Qpid::Messaging::KeyError, "No such sender: #{name}" if result.nil?
- result
- end
-
- # Retrieves the +Receiver+ with the specified name.
- def receiver(name)
- result = nil
-
- begin
- receiver_impl = @session_impl.getReceiver name
- result = Receiver.for_impl receiver_impl
- rescue
- # treat any error as a key error
- end
-
- raise Qpid::Messaging::KeyError, "No such receiver: #{name}" if result.nil?
- result
- end
-
- # Creates a new endpoint for receiving messages.
- def create_receiver(address)
- result = nil
-
- if address.class == Qpid::Messaging::Address
- address_impl = address.address_impl
- result = Qpid::Messaging::Receiver.new(@session_impl.createReceiver(address_impl))
- else
- result = Qpid::Messaging::Receiver.new(@session_impl.createReceiver(address))
- end
-
- return result
- end
-
- # Closes the Session and all associated Senders and Receivers.
- # All Sessions are closed when the associated 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.
- #
- # If a message is submitted (:message => something_message) then only
- # that message is acknowledged. Otherwise all messsages are acknowledged.
- #
- # If :sync => true then the call will block until the server completes
- # processing the acknowledgements.
- # If :sync => true then the call will block until processed by the server (def. false)
- 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.
- #
- # If :block => true then the call will block until the server acknowledges.
- #
- # If :block => false (default) then the call will complete and the server
- # will send notification on completion.
- def sync(args = {})
- block = args[:block] || false
- @session_impl.sync block
- end
-
- # Returns the total number of receivable messages, and messages already received,
- # by Receivers 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.
- def next_receiver(timeout = Qpid::Messaging::Duration::FOREVER)
- receiver_impl = @session_impl.nextReceiver(timeout.duration_impl)
- Qpid::Messaging::Receiver.new receiver_impl
- end
-
- # Returns whether there are errors on this session.
- def error?; @session_impl.hasError; end
-
- def check_error; @session_impl.checkError; end
-
- # Returns if the underlying session is valid.
- def valid?; @session_impl.isValid; end
-
- # Returns if the underlying session is null.
- def null?; @session_impl.isNull; end
-
- def swap session
- @session_impl.swap session.session_impl
- 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 f387ba98dc..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 = 13,
- BUILD = 0]
- end
-
- VERSION = Version::NUMBERS.join('.')
-
-end
diff --git a/cpp/bindings/qpid/ruby/test/lib/setup.rb b/cpp/bindings/qpid/ruby/test/lib/setup.rb
deleted file mode 100644
index c4901ed907..0000000000
--- a/cpp/bindings/qpid/ruby/test/lib/setup.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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'qpid'
-
-def create_session url, session_name
- conn = Qpid::Messaging::Connection.new url
- conn.open
- conn.create_session session_name
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_address.rb b/cpp/bindings/qpid/ruby/test/test_address.rb
deleted file mode 100644
index f54e93aa3d..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_address.rb
+++ /dev/null
@@ -1,39 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/address'
-
-class TestAddress < Test::Unit::TestCase
-
- def test_constructor
- result = Qpid::Messaging::Address.new "name", "subject", {:foo => :bar}, "type"
-
- assert_equal "name", result.name
- assert_equal "subject", result.subject
- assert_equal "type", result._type
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_connection.rb b/cpp/bindings/qpid/ruby/test/test_connection.rb
deleted file mode 100644
index 648fb0588a..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_connection.rb
+++ /dev/null
@@ -1,257 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/connection'
-
-class TestConnection < Test::Unit::TestCase
-
- def setup
- @connection_impl = flexmock("connection_impl")
- @other_connection = flexmock("other_connection")
- @other_connection_impl = flexmock("other_connection_impl")
- @cqpid_connection = flexmock(Cqpid::Connection)
-
- @session = flexmock("session")
- @session_name = "test-session"
-
- @url = "localhost"
- @options = {}
-
- @connection = Qpid::Messaging::Connection.new(@url, @options, @connection_impl)
- end
-
- def test_create_with_username_and_password
- @cqpid_connection.
- should_receive(:new).
- once.with("localhost",
- {"username" => "username",
- "password" => "password"}).
- and_return(@connection_impl)
- @connection_impl.
- should_receive(:open).
- once
-
- result = Qpid::Messaging::Connection.new("localhost",
- :username => "username",
- :password => "password")
- result.open
-
- assert_same @connection_impl, result.connection_impl
- end
-
- def test_create_with_hostname
- result = Qpid::Messaging::Connection.new("localhost")
-
- assert_not_nil result
- end
-
- def test_open
- @cqpid_connection.
- should_receive(:new).
- once.
- with(@url, {}).
- and_return(@connection_impl)
- @connection_impl.
- should_receive(:open).
- once
-
- @connection.open
-
- assert_same @connection_impl, @connection.connection_impl
- end
-
- def test_check_open_when_open
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true)
-
- assert @connection.open?
- end
-
- def test_check_open_before_connection
- result = Qpid::Messaging::Connection.new("hostname")
-
- assert !result.open?
- end
-
- def test_check_open_when_closed
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- assert !@connection.open?
- end
-
- def test_close_an_unopened_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- @connection.close
- end
-
- def test_close
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:close).
- once
-
- @connection.close
- end
-
- def test_create_session_without_name
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createSession).
- once.
- with("").
- and_return(@session)
-
- result = @connection.create_session
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_create_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createSession).
- once.
- with(@session_name).
- and_return(@session)
-
- result = @connection.create_session :name => @session_name
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_create_session_raises_exception_when_closed
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- assert_raise(RuntimeError) {@connection.create_session @session_name}
- end
-
- def test_create_transactional_session
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:createTransactionalSession).
- once.
- with("").
- and_return(@session)
-
- result = @connection.create_session :transactional => true
-
- assert_not_nil result
- assert_same @session, result.session_impl
- end
-
- def test_authenticated_username_when_not_connected
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(false)
-
- result = @connection.authenticated_username
-
- assert_nil result
- end
-
- def test_authenticated_username
- @connection_impl.
- should_receive(:isOpen).
- once.
- and_return(true).
- should_receive(:getAuthenticatedUsername).
- once.
- and_return("farkle")
-
- result = @connection.authenticated_username
-
- assert_equal "farkle", result
- end
-
- def test_get_session_with_invalid_name
- @connection_impl.
- should_receive(:getSession).
- once.
- with(@session_name).
- and_return(nil)
-
- result = @connection.session @session_name
-
- assert_nil result
- end
-
- # APIs inherited from Handle
-
- def test_is_valid
- @connection_impl.
- should_receive(:isValid).
- once.
- and_return(true)
-
- assert @connection.valid?
- end
-
- def test_is_null
- @connection_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@connection.null?
- end
-
- def test_swap
- @other_connection.
- should_receive(:connection_impl).
- once.
- and_return(@other_connection_impl)
- @connection_impl.
- should_receive(:swap).
- once.
- with(@other_connection_impl)
-
- @connection.swap @other_connection
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_encoding.rb b/cpp/bindings/qpid/ruby/test/test_encoding.rb
deleted file mode 100644
index 060975a1d5..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_encoding.rb
+++ /dev/null
@@ -1,146 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'cqpid'
-require 'qpid/encoding'
-
-class TestEncoding < Test::Unit::TestCase
-
- def setup
- @cqpid = flexmock(Cqpid)
-
- @message = flexmock("message")
- @message_impl = flexmock("message_impl")
-
- @encoded = {"foo" => "bar"}
- end
-
- def test_encode_map_with_symbols
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({:foo => :bar}, @message)
-
- assert_same @encoded, result
- end
-
- def test_encode_list_with_symbols
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with(["foo", "bar"], @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode([:foo, :bar], @message)
-
- assert_same @encoded, result
- end
-
- def test_encode_with_content_type
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({:foo => :bar}, @message)
-
- assert_same @encoded, result
- end
-
- def test_encode
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:encode).
- once.
- with({"foo" => "bar"}, @message_impl).
- and_return(@encoded)
-
- result = Qpid::Messaging.encode({"foo" => "bar"}, @message)
-
- assert_same @encoded, result
- end
-
- def test_decode_for_map
- decoded = {"foo" => "bar"}
- @message.
- should_receive(:content_type).
- once.
- and_return("amqp/map")
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:decodeMap).
- once.
- with(@message_impl).
- and_return(decoded)
-
- result = Qpid::Messaging.decode(@message)
-
- assert_same decoded, result
- end
-
- def test_decode_for_list
- decoded = ["foo", "bar"]
- @message.
- should_receive(:content_type).
- once.
- and_return("amqp/list")
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @cqpid.
- should_receive(:decodeList).
- once.
- with(@message_impl).
- and_return(decoded)
-
- result = Qpid::Messaging.decode(@message)
-
- assert_same decoded, result
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_message.rb b/cpp/bindings/qpid/ruby/test/test_message.rb
deleted file mode 100644
index 3fc705bf7e..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_message.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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid'
-
-class TestMessage < Test::Unit::TestCase
-
- def setup
- @address = flexmock("address")
- @address_impl = flexmock("address_impl")
-
- @messaging = flexmock(Qpid::Messaging)
- @message_impl = flexmock("message")
- @message = Qpid::Messaging::Message.new({}, @message_impl)
- end
-
- def test_message_impl
- assert_same @message_impl, @message.message_impl
- end
-
- def test_set_reply_to
- @address.
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @message_impl.
- should_receive(:setReplyTo).
- once.
- with(@address_impl)
-
- @message.reply_to = @address
- end
-
- def test_get_reply_to
- @message_impl.
- should_receive(:getReplyTo).
- once.
- and_return(@address_impl)
-
- result = @message.reply_to
-
- assert_not_nil result
- assert_same @address_impl, result.address_impl
- end
-
- def test_set_subject
- @message_impl.
- should_receive(:setSubject).
- once.
- with("New Subject")
-
- @message.subject = "New Subject"
- end
-
- def test_get_subject
- @message_impl.
- should_receive(:getSubject).
- once.
- and_return("Old Subject")
-
- assert_equal "Old Subject", @message.subject
- end
-
- def test_set_content_type
- @message_impl.
- should_receive(:setContentType).
- once.
- and_return("amqp/map")
-
- @message.content_type = "amqp/map"
- end
-
- def test_get_content_type
- @message_impl.
- should_receive(:getContentType).
- once.
- and_return("amqp/list")
-
- assert_equal "amqp/list", @message.content_type
- end
-
- def test_set_message_id
- @message_impl.
- should_receive(:setMessageId).
- once.
- with("717")
-
- @message.message_id = "717"
- end
-
- def test_get_message_id
- @message_impl.
- should_receive(:getMessageId).
- once.
- and_return("1965")
-
- assert_equal "1965", @message.message_id
- end
-
- def test_set_user_id
- @message_impl.
- should_receive(:setUserId).
- once.
- with("129")
-
- @message.user_id = "129"
- end
-
- def test_get_user_id
- @message_impl.
- should_receive(:getUserId).
- once.
- and_return("1971")
-
- assert_equal "1971", @message.user_id
- end
-
- def test_set_correlation_id
- @message_impl.
- should_receive(:setCorrelationId).
- once.
- with("320")
-
- @message.correlation_id = "320"
- end
-
- def test_get_correlation_id
- @message_impl.
- should_receive(:getCorrelationId).
- once.
- and_return("1996")
-
- assert_equal "1996", @message.correlation_id
- end
-
- def test_set_priority
- @message_impl.
- should_receive(:setPriority).
- once.
- with(9)
-
- @message.priority = 9
- end
-
- def test_get_priority
- @message_impl.
- should_receive(:getPriority).
- once.
- and_return(21)
-
- assert_equal 21, @message.priority
- end
-
- def test_set_ttl
- @message_impl.
- should_receive(:setTtl).
- once.
- with(Qpid::Messaging::Duration::FOREVER)
-
- @message.ttl = Qpid::Messaging::Duration::FOREVER
- end
-
- def test_get_ttl
- @message_impl.
- should_receive(:getTtl).
- once.
- and_return(Qpid::Messaging::Duration::SECOND)
-
- assert_equal Qpid::Messaging::Duration::SECOND, @message.ttl
- end
-
- def test_set_durable
- @message_impl.
- should_receive(:setDurable).
- once.
- with(true)
-
- @message.durable = true
- end
-
- def test_set_not_durable
- @message_impl.
- should_receive(:setDurable).
- once.
- with(false)
-
- @message.durable = false
- end
-
- def test_get_durable
- @message_impl.
- should_receive(:getDurable).
- once.
- and_return(true)
-
- assert @message.durable
- end
-
- def test_set_redelivered
- @message_impl.
- should_receive(:setRedelivered).
- once.
- with(true)
-
- @message.redelivered = true
- end
-
- def test_set_not_redelivered
- @message_impl.
- should_receive(:setRedelivered).
- once.
- with(false)
-
- @message.redelivered = false
- end
-
- def test_get_redelivered
- @message_impl.
- should_receive(:getRedelivered).
- once.
- and_return(false)
-
- assert !@message.redelivered
- end
-
- def test_get_properties
- properties = {"foo" => "bar"}
- @message_impl.
- should_receive(:getProperties).
- once.
- and_return(properties)
-
- result = @message.properties
-
- assert_equal properties, result
- end
-
- def test_get_property
- @message_impl.
- should_receive(:getProperties).
- once.
- and_return({"foo" => "bar"})
-
- result = @message["foo"]
-
- assert_equal "bar", result
- end
-
- def test_set_property
- @message_impl.
- should_receive(:setProperty).
- once.
- with("foo", "bar")
-
- @message["foo"] = "bar"
- end
-
- def test_set_content
- @message_impl.
- should_receive(:setContent).
- once.
- with("foo")
-
- @message.content = "foo"
- assert_equal "foo", @message.content
- end
-
- def test_set_content_with_array
- content = ["one", "two", "three"]
-
- @messaging.
- should_receive(:encode).
- once.
- with(content, @message, "amqp/list")
-
- @message.content = content
- assert_same content, @message.content
- end
-
- def test_set_content_with_map
- content = {:foo => "bar", :dog => "cat"}
-
- @messaging.
- should_receive(:encode).
- once.
- with(content, @message, "amqp/map")
-
- @message.content = content
- assert_same content, @message.content
- end
-
- def test_get_content
- @message_impl.
- should_receive(:getContent).
- and_return("foo")
- @message_impl.
- should_receive(:getContentType).
- and_return(String)
-
- assert_equal "foo", @message.content
- end
-
- def test_get_content_with_array
- decoded = ["foo", "bar"]
-
- @message_impl.
- should_receive(:getContent).
- and_return("[foo,bar]")
- @message_impl.
- should_receive(:getContentType).
- and_return("amqp/list")
- @messaging.
- should_receive(:decode).
- once.
- with(@message, "amqp/list").
- and_return(decoded)
-
- result = @message.content
- assert_same decoded, result
- end
-
- def test_get_content_size
- @message_impl.
- should_receive(:getContentSize).
- once.
- and_return(68)
-
- assert_equal 68, @message.content_size
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_receiver.rb b/cpp/bindings/qpid/ruby/test/test_receiver.rb
deleted file mode 100644
index 61a4db17f2..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_receiver.rb
+++ /dev/null
@@ -1,238 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/receiver'
-
-class TestReceiver < Test::Unit::TestCase
-
- def setup
- @session_impl = flexmock("session")
-
- @Message_class = flexmock(Qpid::Messaging::Message)
- @Messaging_module = flexmock(Qpid::Messaging)
- @message_impl = flexmock("message_impl")
- @message = flexmock("message")
-
- @receiver_impl = flexmock("receiver")
- @other_receiver = flexmock("other_receiver")
- @other_receiver_impl = flexmock("other_receiver_impl")
- @receiver = Qpid::Messaging::Receiver.new @receiver_impl
- end
-
- def test_receiver_impl
- assert_same @receiver_impl, @receiver.receiver_impl
- end
-
- def test_get
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.get
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_get_with_duration
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.get Qpid::Messaging::Duration::MINUTE
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_get_with_no_message_received
- @receiver_impl.
- should_receive(:get).
- once.
- with_any_args.
- and_return(nil)
-
- result = @receiver.get Qpid::Messaging::Duration::SECOND
-
- assert_nil result
- end
-
- def test_fetch
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.fetch
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_fetch_with_duration
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(@message_impl)
-
- result = @receiver.fetch Qpid::Messaging::Duration::MINUTE
-
- assert_not_nil result
- assert_same @message_impl, result.message_impl
- end
-
- def test_fetch_with_no_message_received
- @receiver_impl.
- should_receive(:fetch).
- once.
- with_any_args.
- and_return(nil)
-
- result = @receiver.fetch Qpid::Messaging::Duration::SECOND
-
- assert_nil result
- end
-
- def test_set_capacity
- @receiver_impl.
- should_receive(:setCapacity).
- once.
- with(15)
-
- @receiver.capacity = 15
- end
-
- def test_get_capacity
- @receiver_impl.
- should_receive(:getCapacity).
- once.
- and_return(17)
-
- assert_equal 17, @receiver.capacity
- end
-
- def test_get_available
- @receiver_impl.
- should_receive(:getAvailable).
- once.
- and_return(2)
-
- assert_equal 2, @receiver.available
- end
-
- def test_get_unsettled
- @receiver_impl.
- should_receive(:getUnsettled).
- once.
- and_return(12)
-
- assert_equal 12, @receiver.unsettled
- end
-
- def test_close
- @receiver_impl.
- should_receive(:close).
- once
-
- @receiver.close
- end
-
- def test_closed_when_open
- @receiver_impl.
- should_receive(:isClosed).
- once.
- and_return(false)
-
- assert !@receiver.closed?
- end
-
- def test_closed
- @receiver_impl.
- should_receive(:isClosed).
- once.
- and_return(true)
-
- assert @receiver.closed?
- end
-
- def test_get_name
- @receiver_impl.
- should_receive(:getName).
- once.
- and_return("my-queue")
-
- assert_equal "my-queue", @receiver.name
- end
-
- def test_get_session
- @receiver_impl.
- should_receive(:getSession).
- once.
- and_return(@session_impl)
-
- result = @receiver.session
-
- assert_not_nil result
- assert_same @session_impl, result.session_impl
- end
-
- def test_is_valid
- @receiver_impl.
- should_receive(:isValid).
- once.
- and_return(false)
-
- assert !@receiver.valid?
- end
-
- def test_is_null
- @receiver_impl.
- should_receive(:isNull).
- once.
- and_return(true)
-
- assert @receiver.null?
- end
-
- def test_swap
- @other_receiver.
- should_receive(:receiver_impl).
- once.
- and_return(@other_receiver_impl)
- @receiver_impl.
- should_receive(:swap).
- once.
- with(@other_receiver_impl)
-
- @receiver.swap @other_receiver
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_sender.rb b/cpp/bindings/qpid/ruby/test/test_sender.rb
deleted file mode 100644
index 64348b9f72..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_sender.rb
+++ /dev/null
@@ -1,183 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/sender'
-
-class TestSender < Test::Unit::TestCase
-
- def setup
- @messaging = flexmock(Qpid::Messaging)
- @message = flexmock("message")
-
- @session_impl = flexmock("session_impl")
-
- @sender_impl = flexmock("sender_impl")
- @other_sender_impl = flexmock("other_sender_impl")
- @sender = Qpid::Messaging::Sender.new @sender_impl
- @other_sender = flexmock("other_sender")
- end
-
- def test_send
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, false)
-
- @sender.send @message
- end
-
- def test_send_and_dont_block
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, false)
-
- @sender.send @message, :block => false
- end
-
- def test_send_and_block
- message_impl = "message_impl"
- content = {:foo => :bar}
- @message.
- should_receive(:message_impl).
- once.
- and_return(message_impl)
- @sender_impl.
- should_receive(:send).
- once.
- with(message_impl, true)
-
- @sender.send @message, :block => true
- end
-
- def test_close
- @sender_impl.
- should_receive(:close).
- once
-
- @sender.close
- end
-
- def test_set_capacity
- @sender_impl.
- should_receive(:setCapacity).
- once.
- with(17)
-
- @sender.capacity = 17
- end
-
- def test_get_capacity
- @sender_impl.
- should_receive(:getCapacity).
- once.
- and_return(12)
-
- assert_equal 12, @sender.capacity
- end
-
- def test_unsettled
- @sender_impl.
- should_receive(:getUnsettled).
- once.
- and_return(5)
-
- assert_equal 5, @sender.unsettled
- end
-
- def test_available
- @sender_impl.
- should_receive(:getAvailable).
- once.
- and_return(15)
-
- assert_equal 15, @sender.available
- end
-
- def test_name
- @sender_impl.
- should_receive(:getName).
- once.
- and_return("myname")
-
- assert_equal "myname", @sender.name
- end
-
- def test_session
- @sender_impl.
- should_receive(:getSession).
- once.
- and_return(@session_impl)
-
- result = @sender.session
-
- assert_not_nil result
- assert_same @session_impl, result.session_impl
- end
-
- def test_is_valid
- @sender_impl.
- should_receive(:isValid).
- once.
- and_return(true)
-
- assert @sender.valid?
- end
-
- def test_is_null
- @sender_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@sender.null?
- end
-
- def test_swap
- @other_sender.
- should_receive(:sender_impl).
- once.
- and_return(@other_sender_impl)
- @sender_impl.
- should_receive(:swap).
- once.
- with(@other_sender_impl)
-
- @sender.swap @other_sender
- end
-
-end
-
diff --git a/cpp/bindings/qpid/ruby/test/test_session.rb b/cpp/bindings/qpid/ruby/test/test_session.rb
deleted file mode 100644
index 20f055967b..0000000000
--- a/cpp/bindings/qpid/ruby/test/test_session.rb
+++ /dev/null
@@ -1,445 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'flexmock/test_unit'
-
-require 'qpid/errors'
-require 'qpid/duration'
-require 'qpid/session'
-
-class TestSession < Test::Unit::TestCase
-
- def setup
- @session_impl = flexmock("session_impl")
- @other_session = flexmock("other_session")
- @other_session_impl = flexmock("other_session_impl")
- @sender = flexmock("sender")
-
- @Connection_class = flexmock(Qpid::Messaging::Connection)
- @connection_impl = flexmock("connection_impl")
- @connection = flexmock("connection")
-
- @Receiver_class = flexmock(Qpid::Messaging::Receiver)
- @receiver = flexmock("receiver")
- @receiver_impl = flexmock("receiver_impl")
-
- @address = flexmock("address")
- @address_impl = flexmock("address_impl")
-
- @Sender_class = flexmock(Qpid::Messaging::Sender)
- @sender = flexmock("sender")
- @sender_impl = flexmock("sender_impl")
-
- @message = flexmock("message")
- @message_impl = flexmock("message_impl")
-
- @duration = flexmock("duration")
- @duration_impl = flexmock("duration_impl")
-
- @session = Qpid::Messaging::Session.new(@session_impl)
- end
-
- def test_create_sender_with_Address
- @address.
- should_receive(:class).
- once.
- and_return(Qpid::Messaging::Address).
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @session_impl.
- should_receive(:createSender).
- once.
- with(@address_impl).
- and_return(@sender_impl)
-
- result = @session.create_sender @address
-
- assert_not_nil result
- end
-
- def test_create_sender
- @session_impl.
- should_receive(:createSender).
- once.
- with_any_args.
- and_return(@sender_impl)
-
- result = @session.create_sender("my-queue")
-
- assert_not_nil result
- end
-
- def test_create_sender_with_address_string
- @session_impl.
- should_receive(:createSender).
- once.
- with("my-queue;{create:always}").
- and_return(@sender_impl)
-
- result = @session.create_sender "my-queue;{create:always}"
-
- assert_same @sender_impl, result.sender_impl
- end
-
- def test_create_receiver
- @address.
- should_receive(:class).
- once.
- and_return(Qpid::Messaging::Address).
- should_receive(:address_impl).
- once.
- and_return(@address_impl)
- @session_impl.
- should_receive(:createReceiver).
- once.
- with(@address_impl).
- and_return(@receiver_impl)
-
- result = @session.create_receiver(@address)
-
- assert_equal @receiver_impl, result.receiver_impl
- end
-
- def test_create_receiver_with_address_string
- @session_impl.
- should_receive(:createReceiver).
- once.
- with("my-queue").
- and_return(@receiver_impl)
-
- result = @session.create_receiver("my-queue")
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_close
- @session_impl.
- should_receive(:close).
- once
-
- @session.close
- end
-
- def test_commit
- @session_impl.
- should_receive(:commit).
- once
-
- @session.commit
- end
-
- def test_rollback
- @session_impl.
- should_receive(:rollback).
- once
-
- @session.rollback
- end
-
- def test_acknowledge_with_no_args
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(false)
-
- @session.acknowledge
- end
-
- def test_acknowledge_and_sync
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(true)
-
- @session.acknowledge :sync => true
- end
-
- def test_acknowledge_and_dont_sync
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(false)
-
- @session.acknowledge :sync => false
- end
-
- def test_acknowledge_message_without_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, false)
-
- @session.acknowledge :message => @message
- end
-
- def test_acknowledge_message_and_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, true)
-
- @session.acknowledge :message => @message, :sync => true
- end
-
- def test_acknowledge_message_and_dont_sync
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:acknowledge).
- once.
- with(@message_impl, false)
-
- @session.acknowledge :message => @message, :sync => false
- end
-
- def test_reject_message
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:reject).
- once.
- with(@message_impl)
-
- @session.reject @message
- end
-
- def test_release_message
- @message.
- should_receive(:message_impl).
- once.
- and_return(@message_impl)
- @session_impl.
- should_receive(:release).
- once.
- with(@message_impl)
-
- @session.release @message
- end
-
- def test_sync_without_block
- @session_impl.
- should_receive(:sync).
- once
-
- @session.sync
- end
-
- def test_sync_and_block
- @session_impl.
- should_receive(:sync).
- once.
- with(true)
-
- @session.sync :block => true
- end
-
- def test_sync_and_dont_block
- @session_impl.
- should_receive(:sync).
- once.
- with(false)
-
- @session.sync :block => false
- end
-
- def test_receivable
- @session_impl.
- should_receive(:getReceivable).
- once.
- and_return(5)
-
- assert_equal 5, @session.receivable
- end
-
- def test_unsettled_acks
- @session_impl.
- should_receive(:getUnsettledAcks).
- once.
- and_return(17)
-
- assert_equal 17, @session.unsettled_acks
- end
-
- def test_next_receiver_with_no_duration
- @session_impl.
- should_receive(:nextReceiver).
- once.
- with(Qpid::Messaging::Duration::FOREVER.duration_impl).
- and_return(@receiver_impl)
-
- result = @session.next_receiver
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_next_receiver_with_duration
- @duration.
- should_receive(:duration_impl).
- once.
- and_return(@duration_impl)
- @session_impl.
- should_receive(:nextReceiver).
- once.
- with(@duration_impl).
- and_return(@receiver_impl)
-
- result = @session.next_receiver @duration
-
- assert_same @receiver_impl, result.receiver_impl
- end
-
- def test_sender
- @session_impl.
- should_receive(:getSender).
- once.
- with("farkle").
- and_return(@sender_impl)
- @Sender_class.
- should_receive(:for_impl).
- once.
- with(@sender_impl).
- and_return(@sender)
-
- result = @session.sender "farkle"
-
- assert_same @sender, result
- end
-
- def test_sender_with_invalid_name
- @session_impl.
- should_receive(:getSender).
- once.
- with("farkle").
- and_throw(RuntimeError)
-
- assert_raise(Qpid::Messaging::KeyError) {@session.sender "farkle"}
- end
-
- def test_receiver
- @session_impl.
- should_receive(:getReceiver).
- once.
- with("farkle").
- and_return(@receiver_impl)
- @Receiver_class.
- should_receive(:for_impl).
- once.
- with(@receiver_impl).
- and_return(@receiver)
-
- result = @session.receiver "farkle"
-
- assert_same @receiver, result
- end
-
- def test_receiver_with_invalid_name
- @session_impl.
- should_receive(:getReceiver).
- once.
- with("farkle").
- and_throw(RuntimeError)
-
- assert_raise(Qpid::Messaging::KeyError) {@session.receiver "farkle"}
- end
-
- def test_connection
- @session_impl.
- should_receive(:getConnection).
- once.
- and_return(@connection_impl)
-
- result = @session.connection
-
- assert_same @connection_impl, result.connection_impl
- end
-
- def test_error_with_none
- @session_impl.
- should_receive(:hasError).
- once.
- and_return(false)
-
- assert !@session.error?
- end
-
- def test_error
- @session_impl.
- should_receive(:hasError).
- once.
- and_return(true)
-
- assert @session.error?
- end
-
- def test_check_error
- @session_impl.
- should_receive(:checkError).
- once
-
- @session.check_error
- end
-
- def test_is_valid
- @session_impl.
- should_receive(:isValid).
- once.
- and_return(false)
-
- assert !@session.valid?
- end
-
- def test_is_null
- @session_impl.
- should_receive(:isNull).
- once.
- and_return(false)
-
- assert !@session.null?
- end
-
- def test_swap
- @other_session.
- should_receive(:session_impl).
- once.
- and_return(@other_session_impl)
- @session_impl.
- should_receive(:swap).
- once.
- with(@other_session_impl)
-
- @session.swap @other_session
- end
-
-end
diff --git a/cpp/bindings/qpid/ruby/test/ts_bindings.rb b/cpp/bindings/qpid/ruby/test/ts_bindings.rb
deleted file mode 100644
index 7aa410c8f8..0000000000
--- a/cpp/bindings/qpid/ruby/test/ts_bindings.rb
+++ /dev/null
@@ -1,30 +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.
-#
-
-$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
-
-require 'test/unit'
-require 'test_encoding'
-require 'test_address'
-require 'test_message'
-require 'test_sender'
-require 'test_receiver'
-require 'test_session'
-require 'test_connection'
-
diff --git a/cpp/bindings/swig_python_typemaps.i b/cpp/bindings/swig_python_typemaps.i
index 18bfd48f72..b69784a6de 100644
--- a/cpp/bindings/swig_python_typemaps.i
+++ b/cpp/bindings/swig_python_typemaps.i
@@ -17,25 +17,6 @@
* 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 %{
- pUuidModule = PyImport_ImportModule("uuid");
-
- /* 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)
@@ -47,7 +28,6 @@ typedef int Py_ssize_t;
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*);
@@ -124,9 +104,6 @@ typedef int Py_ssize_t;
break;
}
case qpid::types::VAR_UUID : {
- qpid::types::Uuid uuid = v->asUuid();
- result = UuidToPy(&uuid);
- break;
}
}
} catch (qpid::types::Exception& ex) {
@@ -166,30 +143,6 @@ typedef int Py_ssize_t;
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);
@@ -351,15 +304,6 @@ typedef int Py_ssize_t;
Py_INCREF($result);
}
-/*
- * UUID type: C++ --> Python
- */
-%typemap(out) qpid::types::UUID & {
- $result = UuidToPy($1);
- if ($result)
- Py_INCREF($result);
-}
-
/*
* Variant types: Ruby --> C++
diff --git a/cpp/bindings/swig_ruby_typemaps.i b/cpp/bindings/swig_ruby_typemaps.i
index 326d607c8d..79e679663d 100644
--- a/cpp/bindings/swig_ruby_typemaps.i
+++ b/cpp/bindings/swig_ruby_typemaps.i
@@ -49,7 +49,7 @@
}
VALUE VariantToRb(const qpid::types::Variant* v) {
- VALUE result = Qnil;
+ VALUE result;
try {
switch (v->getType()) {
case qpid::types::VAR_VOID: {
diff --git a/cpp/bld-winsdk.ps1 b/cpp/bld-winsdk.ps1
index bea46da28f..8f0a5886dc 100644
--- a/cpp/bld-winsdk.ps1
+++ b/cpp/bld-winsdk.ps1
@@ -186,6 +186,9 @@ function BuildAPlatform
'examples/qmf-console',
'examples/request-response',
'examples/tradedemo',
+ 'examples/old-examples.sln',
+ 'examples/README.*',
+ 'examples/verify*',
'include',
'plugins')
diff --git a/cpp/configure.ac b/cpp/configure.ac
index 092694d56b..ea1a1b49ea 100644
--- a/cpp/configure.ac
+++ b/cpp/configure.ac
@@ -68,10 +68,8 @@ if test x$GXX = xyes; then
# The following warnings are deliberately omitted, they warn on valid code.
# -Wunreachable-code -Wpadded -Winline
# -Wshadow - warns about boost headers.
- # Can't test for -Werror as whether it fails or not depends on what's in
- # CFLAGS/CXXFLAGS. In any case it's been in gcc for a long time (since 2.95 at least)
if test "${enableval}" = yes; then
- COMPILER_FLAGS="-Werror"
+ gl_COMPILER_FLAGS(-Werror)
gl_COMPILER_FLAGS(-pedantic)
gl_COMPILER_FLAGS(-Wall)
gl_COMPILER_FLAGS(-Wextra)
@@ -523,19 +521,18 @@ AM_PATH_PYTHON()
builddir_lib_suffix="/.libs"
AC_SUBST([builddir_lib_suffix])
-# Files to generate
+# Files to generate
AC_CONFIG_FILES([
Makefile
examples/Makefile
- examples/old_api/Makefile
- examples/old_api/direct/Makefile
- examples/old_api/fanout/Makefile
- examples/old_api/pub-sub/Makefile
- examples/old_api/request-response/Makefile
- examples/old_api/failover/Makefile
- examples/old_api/xml-exchange/Makefile
+ examples/direct/Makefile
+ examples/fanout/Makefile
+ examples/pub-sub/Makefile
+ examples/request-response/Makefile
+ examples/failover/Makefile
+ examples/xml-exchange/Makefile
examples/qmf-console/Makefile
- examples/old_api/tradedemo/Makefile
+ examples/tradedemo/Makefile
examples/messaging/Makefile
bindings/qpid/Makefile
bindings/qpid/ruby/Makefile
diff --git a/cpp/design_docs/hot-standby-design.txt b/cpp/design_docs/hot-standby-design.txt
deleted file mode 100644
index 99a5dc0199..0000000000
--- a/cpp/design_docs/hot-standby-design.txt
+++ /dev/null
@@ -1,239 +0,0 @@
--*-org-*-
-# 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.
-
-* Another new design for Qpid clustering.
-
-For background see [[./new-cluster-design.txt]] which describes the issues
-with the old design and a new active-active design that could replace it.
-
-This document describes an alternative hot-standby approach.
-
-** Delivery guarantee
-
-We guarantee N-way redundant, at least once delivey. Once a message
-from a client has been acknowledged by the broker, it will be
-delivered even if N-1 brokers subsequently fail. There may be
-duplicates in the event of a failure. We don't make duplicates
-during normal operation (i.e when no brokers have failed)
-
-This is the same guarantee as the old cluster and the alternative
-active-active design.
-
-** Active-active vs. hot standby (aka primary-backup)
-
-An active-active cluster allows clients to connect to any broker in
-the cluster. If a broker fails, clients can fail-over to any other
-live broker.
-
-A hot-standby cluster has only one active broker at a time (the
-"primary") and one or more brokers on standby (the "backups"). Clients
-are only served by the leader, clients that connect to a backup are
-redirected to the leader. The backpus are kept up-to-date in real time
-by the primary, if the primary fails a backup is elected to be the new
-primary.
-
-Aside: A cold-standby cluster is possible using a standalone broker,
-CMAN and shared storage. In this scenario only one broker runs at a
-time writing to a shared store. If it fails, another broker is started
-(by CMAN) and recovers from the store. This bears investigation but
-the store recovery time is probably too long for failover.
-
-** Why hot standby?
-
-Active-active has some advantages:
-- Finding a broker on startup or failover is simple, just pick any live broker.
-- All brokers are always running in active mode, there's no
-- Distributing clients across brokers gives better performance, but see [1].
-- A broker failure affects only clients connected to that broker.
-
-The main problem with active-active is co-ordinating consumers of the
-same queue on multiple brokers such that there are no duplicates in
-normal operation. There are 2 approaches:
-
-Predictive: each broker predicts which messages others will take. This
-the main weakness of the old design so not appealing.
-
-Locking: brokers "lock" a queue in order to take messages. This is
-complex to implement, its not straighforward to determine the most
-performant strategie for passing the lock.
-
-Hot-standby removes this problem. Only the primary can modify queues
-so it just has to tell the backups what it is doing, there's no
-locking.
-
-The primary can enqueue messages and replicate asynchronously -
-exactly like the store does, but it "writes" to the replicas over the
-network rather than writing to disk.
-
-** Failover in a hot-standby cluster.
-
-Hot-standby has some potential performance issues around failover:
-
-- Failover "spike": when the primary fails every client will fail over
- at the same time, putting strain on the system.
-
-- Until a new primary is elected, cluster cannot serve any clients or
- redirect clients to the primary.
-
-We want to minimize the number of re-connect attempts that clients
-have to make. The cluster can use a well-known algorithm to choose the
-new primary (e.g. round robin on a known sequence of brokers) so that
-clients can guess the new primary correctly in most cases.
-
-Even if clients do guess correctly it may be that the new primary is
-not yet aware of the death of the old primary, which is may to cause
-multiple failed connect attempts before clients eventually get
-connected. We will need to prototype to see how much this happens in
-reality and how we can best get clients redirected.
-
-** Threading and performance.
-
-The primary-backup cluster operates analogously to the way the disk store does now:
-- use the same MessageStore interface as the store to interact with the broker
-- use the same asynchronous-completion model for replicating messages.
-- use the same recovery interfaces (?) for new backups joining.
-
-Re-using the well-established store design gives credibility to the new cluster design.
-
-The single CPG dispatch thread was a severe performance bottleneck for the old cluster.
-
-The primary has the same threading model as a a standalone broker with
-a store, which we know that this performs well.
-
-If we use CPG for replication of messages, the backups will receive
-messages in the CPG dispatch thread. To get more concurency, the CPG
-thread can dump work onto internal PollableQueues to be processed in
-parallel.
-
-Messages from the same broker queue need to go onto the same
-PollableQueue. There could be a separate PollableQueue for each broker
-queue. If that's too resource intensive we can use a fixed set of
-PollableQueues and assign broker queues to PollableQueues via hashing
-or round robin.
-
-Another possible optimization is to use multiple CPG queues: one per
-queue or a hashed set, to get more concurrency in the CPG layer. The
-old cluster is not able to keep CPG busy.
-
-TODO: Transactions pose a challenge with these concurrent models: how
-to co-ordinate multiple messages being added (commit a publish or roll
-back an accept) to multiple queues so that all replicas end up with
-the same message sequence while respecting atomicity.
-
-** Use of CPG
-
-CPG provides several benefits in the old cluster:
-- tracking membership (essential for determining the primary)
-- handling "spit brain" (integrates with partition support from CMAN)
-- reliable multicast protocol to distribute messages.
-
-I believe we still need CPG for membership and split brain. We could
-experiment with sending the bulk traffic over AMQP conections.
-
-** Flow control
-
-Need to ensure that
-1) In-memory internal queues used by the cluster don't overflow.
-2) The backups don't fall too far behind on processing CPG messages
-
-** Recovery
-When a new backup joins an active cluster it must get a snapshot
-from one of the other backups, or the primary if there are none. In
-store terms this is "recovery" (old cluster called it an "update)
-
-Compared to old cluster we only replidate well defined data set of the store.
-This is the crucial sore spot of old cluster.
-
-We can also replicated it more efficiently by recovering queues in
-reverse (LIFO) order. That means as clients actively consume messages
-from the front of the queue, they are redeucing the work we have to do
-in recovering from the back. (NOTE: this may not be compatible with
-using the same recovery interfaces as the store.)
-
-** Selective replication
-In this model it's easy to support selective replication of individual queues via
-configuration.
-- Explicit exchange/queue declare argument and message boolean: x-qpid-replicate.
- Treated analogously to persistent/durable properties for the store.
-- if not explicitly marked, provide a choice of default
- - default is replicate (replicated message on replicated queue)
- - default is don't replicate
- - default is replicate persistent/durable messages.
-
-** Inconsistent errors
-
-The new design eliminates most sources of inconsistent errors in the
-old design (connections, sessions, security, management etc.) and
-eliminates the need to stall the whole cluster till an error is
-resolved. We still have to handle inconsistent store errors when store
-and cluster are used together.
-
-We also have to include error handling in the async completion loop to
-guarantee N-way at least once: we should only report success to the
-client when we know the message was replicated and stored on all N-1
-backups.
-
-TODO: We have a lot more options than the old cluster, need to figure
-out the best approach, or possibly allow mutliple approaches. Need to
-go thru the various failure cases. We may be able to do recovery on a
-per-queue basis rather than restarting an entire node.
-
-** New members joining
-
-We should be able to catch up much faster than the the old design. A
-new backup can catch up ("recover") the current cluster state on a
-per-queue basis.
-- queues can be updated in parallel
-- "live" updates avoid the the "endless chase"
-
-During a "live" update several things are happening on a queue:
-- clients are publishing messages to the back of the queue, replicated to the backup
-- clients are consuming messages from the front of the queue, replicated to the backup.
-- the primary is sending pre-existing messages to the new backup.
-
-The primary sends pre-existing messages in LIFO order - starting from
-the back of the queue, at the same time clients are consuming from the front.
-The active consumers actually reduce the amount of work to be done, as there's
-no need to replicate messages that are no longer on the queue.
-
-* Steps to get there
-
-** Baseline replication
-Validate the overall design get initial notion of performance. Just
-message+wiring replication, no update/recovery for new members joining,
-single CPG dispatch thread on backups, no failover, no transactions.
-
-** Failover
-Electing primary, backups redirect to primary. Measure failover time
-for large # clients. Strategies to minimise number of retries after a
-failure.
-
-** Flow Control
-Keep internal queues from over-flowing. Similar to internal flow control in old cluster.
-Needed for realistic performance/stress tests
-
-** Concurrency
-Experiment with multiple threads on backups, multiple CPG groups.
-
-** Recovery/new member joining
-Initial status handshake for new member. Recovering queues from the back.
-
-** Transactions
-TODO: How to implement transactions with concurrency. Worst solution:
-a global --cluster-use-transactions flag that forces single thread
-mode. Need to find a better solution.
diff --git a/cpp/design_docs/new-cluster-design.txt b/cpp/design_docs/new-cluster-design.txt
index a162ea68ec..7adb46fee3 100644
--- a/cpp/design_docs/new-cluster-design.txt
+++ b/cpp/design_docs/new-cluster-design.txt
@@ -17,6 +17,7 @@
# under the License.
* A new design for Qpid clustering.
+
** Issues with current design.
The cluster is based on virtual synchrony: each broker multicasts
@@ -94,9 +95,8 @@ Use a moving queue ownership protocol to agree order of dequeues.
No longer relies on identical state and lock-step behavior to cause
identical dequeues on each broker.
-Use multiple CPG groups to process different queues in parallel. Use a
-fixed set of groups and hash queue names to choose the group for each
-queue.
+Each queue has an associated thread-context. Events for a queue are executed
+in that queues context, in parallel with events for other queues.
*** Requirements
@@ -149,7 +149,7 @@ a release-queue event, allowing another interested broker to take
ownership.
*** Asynchronous completion of accept
-
+### HERE
In acknowledged mode a message is not forgotten until it is accepted,
to allow for requeue on rejection or crash. The accept should not be
completed till the message has been forgotten.
@@ -162,32 +162,19 @@ On receiving an accept the broker:
NOTE: The message store does not currently implement asynchronous
completions of accept, this is a bug.
-*** Multiple CPG groups.
-
-The old cluster was bottlenecked by processing everything in a single
-CPG deliver thread.
-
-The new cluster uses a set of CPG groups, one per core. Queue names
-are hashed to give group indexes, so statistically queues are likely
-to be spread over the set of groups.
-
-Operations on a given queue always use the same group, so we have
-order within each queue, but operations on different queues can use
-different groups giving greater throughput sending to CPG and multiple
-handler threads to process CPG messages.
-
** Inconsistent errors.
-An inconsistent error means that after multicasting an enqueue, accept
-or dequeue, some brokers succeed in processing it and others fail.
+The new design eliminates most sources of inconsistent errors
+(connections, sessions, security, management etc.) The only points
+where inconsistent errors can occur are at enqueue and dequeue (most
+likely store-related errors.)
-The new design eliminates most sources of inconsistent errors in the
-old broker: connections, sessions, security, management etc. Only
-store journal errors remain.
+The new design can use the exisiting error-handling protocol with one
+major improvement: since brokers are no longer required to maintain
+identical state they do not have to stall processing while an error is
+being resolved.
-The new inconsistent error protocol is similar to the old one with one
-major improvement: brokers do not have to stall processing while an
-error is being resolved.
+#TODO: The only source of dequeue errors is probably an unrecoverable journal failure.
** Updating new members
@@ -206,44 +193,60 @@ catch up (which is not guaranteed to happen in a bounded time.)
With the new cluster design only exchanges, queues, bindings and
messages need to be replicated.
-We update individual objects (queues and exchanges) independently.
-- create queues first, then update all queues and exchanges in parallel.
-- multiple updater threads, per queue/exchange.
+Update of wiring (exchanges, queues, bindings) is the same as current
+design.
+
+Update of messages is different:
+- per-queue rather than per-broker, separate queues can be updated in parallel.
+- updates queues in reverse order to eliminate unbounded catch-up
+- does not require updater & updatee to stall during update.
-Queue updater:
-- marks the queue position at the sync point
-- sends messages starting from the sync point working towards the head of the queue.
-- send "done" message.
+Replication events, multicast to cluster:
+- enqueue(q,m): message m pushed on back of queue q .
+- acquire(q,m): mark m acquired
+- dequeue(q,m): forget m.
+Messages sent on update connection:
+- update_front(q,m): during update, receiver pushes m to *front* of q
+- update_done(q): during update, update of q is complete.
-Queue updatee:
-- enqueues received from CPG: add to back of queue as normal.
-- dequeues received from CPG: apply if found, else save to check at end of update.
-- messages from updater: add to the *front* of the queue.
-- update complete: apply any saved dequeues.
+Updater:
+- when updatee joins set iterator i = q.end()
+- while i != q.begin(): --i; send update_front(q,*i) to updatee
+- send update_done(q) to updatee
-Exchange updater:
-- updater: send snapshot of exchange as it was at the sync point.
+Updatee:
+- q initially in locked state, can't dequeue locally.
+- start processing replication events for q immediately (enqueue, dequeue, acquire etc.)
+- receive update_front(q,m): q.push_front(m)
+- receive update_done(q): q can be unlocked for local dequeing.
-Exchange updatee:
-- queue exchange operations after the sync point.
-- when snapshot is received: apply saved operations.
+Benefits:
+- Stall only for wiring update: updater & updatee can process multicast messages while messages are updated.
+- No unbounded catch-up: update consists of at most N update_front() messages where N=q.size() at start of update.
+- During update consumers actually help by removing messages before they need to be updated.
+- Needs no separate "work to do" queue, only the broker queues themselves.
-Note:
-- Updater is active throughout, no stalling.
-- Consuming clients actually reduce the size of the update.
-- Updatee stalls clients until the update completes.
- (Note: May be possible to avoid updatee stall as well, needs thought)
+# TODO how can we recover from updater crashing before update complete?
+# Clear queues that are not updated & send request for udpates on those queues?
-** Internal cluster interface
+# TODO updatee may receive a dequeue for a message it has not yet seen, needs
+# to hold on to that so it can drop the message when it is seen.
+# Similar problem exists for wiring?
-The new cluster interface is similar to the MessageStore interface, but
-provides more detail (message positions) and some additional call
-points (e.g. acquire)
+** Cluster API
+
+The new cluster API is similar to the MessageStore interface.
+(Initially I thought it would be an extension of the MessageStore interface,
+but as the design develops it seems better to make it a separate interface.)
The cluster interface captures these events:
- wiring changes: queue/exchange declare/bind
- message enqueued/acquired/released/rejected/dequeued.
-- transactional events.
+
+The cluster will require some extensions to the Queue:
+- Queues can be "locked", locked queues are ignored by IO-driven output.
+- Cluster must be able to apply queue events from the cluster to a queue.
+ These appear to fit into existing queue operations.
** Maintainability
@@ -270,48 +273,106 @@ A number of specific ways the code will be simplified:
** Performance
-The standalone broker processes _connections_ concurrently, so CPU
-usage increases as you add more connections.
-
-The new cluster processes _queues_ concurrently, so CPU usage increases as you
-add more queues.
-
-In both cases, CPU usage peaks when the number of "units of
- concurrency" (connections or queues) goes above the number of cores.
-
-When all consumers on a queue are connected to the same broker the new
-cluster uses the same messagea allocation threading/logic as a
-standalone broker, with a little extra asynchronous book-keeping.
-
-If a queue has multiple consumers connected to multiple brokers, the
-new cluster time-shares the queue which is less efficient than having
-all consumers on a queue connected to the same broker.
+The only way to verify the relative performance of the new design is
+to prototype & profile. The following points suggest the new design
+may scale/perform better:
+
+Some work moved from virtual synchrony thread to connection threads:
+- All connection/session logic moves to connection thread.
+- Exchange routing logic moves to connection thread.
+- On local broker dequeueing is done in connection thread
+- Local broker dequeue is IO driven as for a standalone broker.
+
+For queues with all consumers on a single node dequeue is all
+IO-driven in connection thread. Pay for time-sharing only if queue has
+consumers on multiple brokers.
+
+Doing work for different queues in parallel scales on multi-core boxes when
+there are multiple queues.
+
+One difference works against performance, thre is an extra
+encode/decode. The old design multicasts raw client data and decodes
+it in the virtual synchrony thread. The new design would decode
+messages in the connection thread, re-encode them for multicast, and
+decode (on non-local brokers) in the virtual synchrony thread. There
+is extra work here, but only in the *connection* thread: on a
+multi-core machine this happens in parallel for every connection, so
+it probably is not a bottleneck. There may be scope to optimize
+decode/re-encode by re-using some of the original encoded data, this
+could also benefit the stand-alone broker.
+
+** Asynchronous queue replication
+
+The existing "asynchronous queue replication" feature maintains a
+passive backup passive backup of queues on a remote broker over a TCP
+connection.
+
+The new cluster replication protocol could be re-used to implement
+asynchronous queue replication: its just a special case where the
+active broker is always the queue owner and the enqueue/dequeue
+messages are sent over a TCP connection rather than multicast.
+
+The new update update mechanism could also work with 'asynchronous
+queue replication', allowing such replication (over a TCP connection
+on a WAN say) to be initiated after the queue had already been created
+and been in use (one of the key missing features).
+
+** Increasing Concurrency and load sharing
+
+The current cluster is bottlenecked by processing everything in the
+CPG deliver thread. By removing the need for identical operation on
+each broker, we open up the possiblility of greater concurrency.
+
+Handling multicast enqueue, acquire, accpet, release etc: concurrency
+per queue. Operatons on different queues can be done in different
+threads.
+
+The new design does not force each broker to do all the work in the
+CPG thread so spreading load across cluster members should give some
+scale-up.
+
+** Misc outstanding issues & notes
+
+Replicating wiring
+- Need async completion of wiring commands?
+- qpid.sequence_counter: need extra work to support in new design, do we care?
+
+Cluster+persistence:
+- finish async completion: dequeue completion for store & cluster
+- cluster restart from store: clean stores *not* identical, pick 1, all others update.
+- need to generate cluster ids for messages recovered from store.
+
+Live updates: we don't need to stall brokers during an update!
+- update on queue-by-queue basis.
+- updatee locks queues during update, no dequeue.
+- update in reverse: don't update messages dequeued during update.
+- updatee adds update messages at front (as normal), replicated messages at back.
+- updater starts from back, sends "update done" when it hits front of queue.
+
+Flow control: need to throttle multicasting
+1. bound the number of outstanding multicasts.
+2. ensure the entire cluster keeps up, no unbounded "lag"
+The existing design uses read-credit to solve 1., and does not solve 2.
+New design should stop reading on all connections while flow control
+condition exists?
+
+Can federation also be unified, at least in configuration?
+
+Consider queues (and exchanges?) as having "reliability" attributes:
+- persistent: is the message stored on disk.
+- backed-up (to another broker): active/passive async replication.
+- replicated (to a cluster): active/active multicast replication to cluster.
+- federated: federation link to a queue/exchange on another broker.
+
+"Reliability" seems right for the first 3 but not for federation, is
+there a better term?
+
+Clustering and scalability: new design may give us the flexibility to
+address scalability as part of cluster design. Think about
+relationship to federation and "fragmented queues" idea.
+
+* Design debates/descisions
-** Flow control
-New design does not queue up CPG delivered messages, they are
-processed immediately in the CPG deliver thread. This means that CPG's
-flow control is sufficient for qpid.
-
-** Live upgrades
-
-Live upgrades refers to the ability to upgrade a cluster while it is
-running, with no downtime. Each brokers in the cluster is shut down,
-and then re-started with a new version of the broker code.
-
-To achieve this
-- Cluster protocl XML file has a new element <version number=N> attached
- to each method. This is the version at which the method was added.
-- New versions can only add methods, existing methods cannot be changed.
-- The cluster handshake for new members includes the protocol version
- at each member.
-- The cluster's version is the lowest version among its members.
-- A newer broker can join and older cluster. When it does, it must restrict
- itself to speaking the older version protocol.
-- When the cluster version increases (because the lowest version member has left)
- the remaining members may move up to the new version.
-
-
-* Design debates
** Active/active vs. active passive
An active-active cluster can be used in an active-passive mode. In
@@ -324,7 +385,7 @@ An active/passive implementation allows some simplifications over active/active:
- can do immediate local enqueue and still guarantee order.
Active/passive introduces a few extra requirements:
-- Exactly one broker has to take over if primary fails.
+- Exactly one broker hast to take over if primary fails.
- Passive members must refuse client connections.
- On failover, clients must re-try all known addresses till they find the active member.
@@ -332,17 +393,43 @@ Active/active benefits:
- A broker failure only affects the subset of clients connected to that broker.
- Clients can switch to any other broker on failover
- Backup brokers are immediately available on failover.
-- As long as a client can connect to any broker in the cluster, it can be served.
+- Some load sharing: reading from client + multicast only done on direct node.
+
+Active/active drawbacks:
+- Co-ordinating message acquisition may impact performance (not tested)
+- Code may be more complex that active/passive.
Active/passive benefits:
-- Don't need to replicate message allocation, can feed consumers at top speed.
+- Don't need message allocation strategy, can feed consumers at top speed.
+- Code may be simpler than active/active.
Active/passive drawbacks:
- All clients on one node so a failure affects every client in the system.
- After a failure there is a "reconnect storm" as every client reconnects to the new active node.
- After a failure there is a period where no broker is active, until the other brokers realize the primary is gone and agree on the new primary.
- Clients must find the single active node, may involve multiple connect attempts.
-- No service if a partition separates a client from the active broker,
- even if the client can see other brokers.
+** Total ordering.
+
+Initial thinking: allow message ordering to differ between brokers.
+New thinking: use CPG total ordering, get identical ordering on all brokers.
+- Allowing variation in order introduces too much chance of unexpected behavior.
+- Usign total order allows other optimizations, see Message Identifiers below.
+
+** Message identifiers.
+
+Initial thinking: message ID = CPG node id + 64 bit sequence number.
+This involves a lot of mapping between cluster IDs and broker messsages.
+
+New thinking: message ID = queue name + queue position.
+- Removes most of the mapping and memory management for cluster code.
+- Requires total ordering of messages (see above)
+
+** Message rejection
+
+Initial thinking: add special reject/rejected points to cluster interface so
+rejected messages could be re-queued without multicast.
+New thinking: treat re-queueing after reject as entirely new message.
+- Simplifies cluster interface & implementation
+- Not on the critical path.
diff --git a/cpp/design_docs/new-cluster-plan.txt b/cpp/design_docs/new-cluster-plan.txt
index 32e3f710e7..781876e55a 100644
--- a/cpp/design_docs/new-cluster-plan.txt
+++ b/cpp/design_docs/new-cluster-plan.txt
@@ -17,150 +17,376 @@
# specific language governing permissions and limitations
# under the License.
-* Status of impementation
-Meaning of priorities:
-[#A] Essential for basic functioning.
-[#B] Required for first release.
-[#C] Can be addressed in a later release.
+Notes on new cluster implementation. See also: new-cluster-design.txt
-The existig prototype is bare bones to do performance benchmarks:
-- Implements publish and consumer locking protocol.
-- Defered delivery and asynchronous completion of message.
-- Optimize the case all consumers are on the same node.
-- No new member updates, no failover updates, no transactions, no persistence etc.
+* Implementation plan.
-Prototype code is on branch qpid-2920-active, in cpp/src/qpid/cluster/exp/
+Co-existence with old cluster code and tests:
+- Separate plugin cluster2, options --cluster2-*. Eventually renamed to replace cluster.
+- Double up tests with old version/new version as the new code develops.
-** Similarities to existing cluster.
+Minimal POC for message delivery & perf test.
+- no wiring replication, no updates, no failover, no persistence, no async completion.
+- just implement publish and acquire/dequeue locking protocol.
+- optimize the special case where all consumers are on the same node.
+- measure performance: compare active-passive and active-active modes of use.
-/Active-active/: the new cluster can be a drop-in replacement for the
-old, existing tests & customer deployment configurations are still
-valid.
+Full implementation of transient cluster
+- Update (based on existing update), async completion etc.
+- Passing all existing transient cluster tests.
-/Virtual synchrony/: Uses corosync to co-ordinate activity of members.
+Persistent cluster
+- Make sure async completion works correctly.
+- InitialStatus protoocl etc. to support persistent start-up (existing code)
+- cluster restart from store: stores not identical. Load one, update the rest.
+ - assign cluster ID's to messages recovered from store, don't replicate.
-/XML controls/: Uses XML to define the primitives multicast to the
-cluster.
+Improved update protocol
+- per-queue, less stalling, bounded catch-up.
-** Differences with existing cluster.
+* Task list
-/Report rather than predict consumption/: brokers explicitly tell each
-other which messages have been acquired or dequeued. This removes the
-major cause of bugs in the existing cluster.
+** TODO [#A] Minimal POC: publish/acquire/dequeue protocol.
-/Queue consumer locking/: to avoid duplicates only one broker can acquire or
-dequeue messages at a time - while has the consume-lock on the
-queue. If multiple brokers are consuming from the same queue the lock
-is passed around to time-share access to the queue.
+NOTE: as implementation questions arise, take the easiest option and make
+a note for later optimization/improvement.
-/Per-queue concurrency/: uses a fixed-size set of CPG groups (reflecting
-the concurrency of the host) to allow concurrent processing on
-different queues. Queues are hashed onto the groups.
+*** Tests
+- python test: 4 senders, numbered messages, 4 receivers, verify message set.
+- acquire then release messages: verify can be dequeued on any member
+- acquire then kill broker: verify can be dequeued other members.
+- acquire then reject: verify goes on alt-exchange once only.
-* Completed tasks
-** DONE [#A] Minimal POC: publish/acquire/dequeue protocol.
- CLOSED: [2011-10-05 Wed 16:03]
+*** DONE broker::Cluster interface and call points.
-Defines broker::Cluster interface and call points.
-Initial interface commite
+Initial interface commited.
-Main classes
-Core: central object holding cluster classes together (replaces cluster::Cluster)
-BrokerContext: implements broker::Cluster interface.
-QueueContext: Attached to a broker::Queue, holds cluster status.
-MessageHolder:holds local messages while they are being enqueued.
+*** Main classes
-Implements multiple CPG groups for better concurrency.
+BrokerHandler:
+- implements broker::Cluster intercept points.
+- sends mcast events to inform cluster of local actions.
+- thread safe, called in connection threads.
-** DONE [#A] Large message replication.
- CLOSED: [2011-10-05 Wed 17:22]
-Multicast using fixed-size (64k) buffers, allow fragmetation of messages across buffers (frame by frame)
+LocalMessageMap:
+- Holds local messages while they are being enqueued.
+- thread safe: called by both BrokerHandler and MessageHandler
+
+MessageHandler:
+- handles delivered mcast messages related to messages.
+- initiates local actions in response to mcast events.
+- thread unsafe, only called in deliver thread.
+- maintains view of cluster state regarding messages.
-* Open questions
+QueueOwnerHandler:
+- handles delivered mcast messages related to queue consumer ownership.
+- thread safe, called in deliver, connection and timer threads.
+- maintains view of cluster state regarding queue ownership.
+
+cluster::Core: class to hold new cluster together (replaces cluster::Cluster)
+- thread safe: manage state used by both MessageHandler and BrokerHandler
+
+The following code sketch illustrates only the "happy path" error handling
+is omitted.
+
+*** BrokerHandler
+Types:
+- struct QueuedMessage { Message msg; QueueName q; SequenceNumber position; }
+- struct
+
+NOTE:
+- Messages on queues are identified by a queue name + a position.
+- Messages being routed are identified by a sequence number.
+
+Members:
+- thread_local bool noReplicate // suppress replication.
+- thread_local bool isRouting // suppress operations while routing
+- Message localMessage[SequenceNumber] // local messages being routed.
+- thread_local SequenceNumber routingSequence
+
+NOTE: localMessage is also modified by MessageHandler.
+
+broker::Cluster intercept functions:
+
+routing(msg)
+ if noReplicate: return
+ # Supress everything except enqueues while we are routing.
+ # We don't want to replicate acquires & dequeues caused by an enqueu,
+ # e.g. removal of messages from ring/LV queues.
+ isRouting = true
+
+enqueue(qmsg):
+ if noReplicate: return
+ if routingSequence == 0 # thread local
+ routingSequence = nextRoutingSequence()
+ mcast create(encode(qmsg.msg),routingSeq)
+ mcast enqueue(qmsg.q,routingSeq)
+
+routed(msg):
+ if noReplicate: return
+ isRouting = false
+
+acquire(qmsg):
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ if msg.id: mcast acquire(qmsg)
+
+release(QueuedMessage)
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ mcast release(qmsg)
+
+accept(QueuedMessage):
+ if noReplicate: return
+ if isRouting: return # Ignore while we are routing a message.
+ mcast accept(qmsg)
+
+reject(QueuedMessage):
+ isRejecting = true
+ mcast reject(qmsg)
+
+# FIXME no longer needed?
+drop(QueuedMessage)
+ cleanup(qmsg)
+
+*** MessageHandler and mcast messages
+Types:
+- struct QueueEntry { QueuedMessage qmsg; NodeId acquired; }
+- struct QueueKey { MessageId id; QueueName q; }
+- typedef map<QueueKey, QueueEntry> Queue
+- struct Node { Message routing[SequenceNumber]; list<QueueKey> acquired; }
+
+Members:
+- QueueEntry enqueued[QueueKey]
+- Node node[NodeId]
+
+Mcast messages in Message class:
+
+create(msg,seq)
+ if sender != self: node[sender].routing[seq] = decode(msg)
+
+enqueue(q,seq):
+ id = (sender,seq)
+ if sender == self:
+ enqueued[id,q] = (localMessage[seq], acquired=None)
+ else:
+ msg = sender.routing[seq]
+ enqueued[id,q] = (qmsg, acquired=None)
+ with noReplicate=true: qmsg = broker.getQueue(q).push(msg)
+
+routed(seq):
+ if sender == self: localMessage.erase(msg.id.seq)
+ else: sender.routing.erase(seq)
+
+acquire(id,q):
+ enqueued[id,q].acquired = sender
+ node[sender].acquired.push_back((id,q))
+ if sender != self:
+ with noReplicate=true: broker.getQueue(q).acquire(enqueued[id,q])
+
+release(id,q)
+ enqueued[id,q].acquired = None
+ node[sender].acquired.erase((id,q))
+ if sender != self
+ with noReplicate=true: broker.getQueue(q).requeue(enqueued[id,q])
+
+reject(id,q):
+ sender.routing[id] = enqueued[id,q] # prepare for re-queueing
+
+rejected(id,q)
+ sender.routing.erase[id]
+
+dequeue(id,q)
+ entry = enqueued[id,q]
+ enqueued.erase[id,q]
+ node[entry.acquired].acquired.erase(id,q)
+ if sender != self:
+ with noReplicate=true: broker.getQueue(q).dequeue(entry.qmsg)
+
+member m leaves cluster:
+ for key in node[m].acquired:
+ release(key.id, key.q)
+ node.erase(m)
+
+*** Queue consumer locking
+
+When a queue is locked it does not deliver messages to its consumers.
+
+New broker::Queue functions:
+- stopConsumers(): set consumersStopped flag, wait for currently busy consumers to exit.
+- startConsumers(): reset consumersStopped flag
+
+Implementation sketch, locking omitted:
+
+void Queue::stopConsumers() {
+ consumersStopped = true;
+ while (consumersBusy) consumersBusyMonitor.wait();
+}
+
+void Queue::startConsumers() {
+ consumersStopped = false;
+ listeners.notify();
+}
+
+bool Queue::dispatch(consumer) {
+ if (consumersStopped) return false;
+ ++consumersBusy;
+ do_regular_dispatch_body()
+ if (--consumersBusy == 0) consumersBusyMonitor.notify();
+}
+
+*** QueueOwnerHandler
+
+Invariants:
+- Each queue is owned by at most one node at any time.
+- Each node is interested in a set of queues at any given time.
+- A queue is un-owned if no node is interested.
+
+The queue owner releases the queue when
+- it loses interest i.e. queue has no consumers with credit.
+- a configured time delay expires and there are other interested nodes.
+
+The owner mcasts release(q). On delivery the new queue owner is the
+next node in node-id order (treating nodes as a circular list)
+starting from the old owner that is interested in the queue.
+
+Queue consumers initially are stopped, only started when we get
+ownership from the cluster.
+
+Thread safety: called by deliver, connection and timer threads, needs locking.
+
+Thread safe object per queue holding queue ownership status.
+Called by deliver, connection and timer threads.
+
+class QueueOwnership {
+ bool owned;
+ Timer timer;
+ BrokerQueue q;
+
+ drop(): # locked
+ if owned:
+ owned = false
+ q.stopConsumers()
+ mcast release(q.name, false)
+ timer.stop()
+
+ take(): # locked
+ if not owned:
+ owned = true
+ q.startConsumers()
+ timer.start(timeout)
+
+ timer.fire(): drop()
+}
+
+Data Members, only modified/examined in deliver thread:
+- typedef set<NodeId> ConsumerSet
+- map<QueueName, ConsumerSet> consumers
+- map<QueueName, NodeId> owner
-** TODO [#A] Queue sequence numbers vs. independant message IDs.
- SCHEDULED: <2011-10-07 Fri>
+Thread safe data members, accessed in connection threads (via BrokerHandler):
+- map<QueueName, QueueOwnership> ownership
-Current prototype uses queue sequence numbers to identify
-message. This is tricky for updating new members as the sequence
-numbers are only known on delivery.
+Multicast messages in QueueOwner class:
-Independent message IDs that can be generated and sent with the message simplify
-this and potentially allow performance benefits by relaxing total ordering.
-However they imply additional map lookups that might hurt performance.
+consume(q):
+ if sender==self and consumers[q].empty(): ownership[q].take()
+ consumers[q].insert(sender)
-- [ ] Prototype independent message IDs, check performance.
+release(q):
+ asssert(owner[q] == sender and owner[q] in consumers[q])
+ owner[q] = circular search from sender in consumers[q]
+ if owner==self: ownership[q].take()
-* Outstanding Tasks
-** TODO [#A] Defer and async completion of wiring commands.
+cancel(q):
+ assert(queue[q].owner != sender) # sender must release() before cancel()
+ consumers[q].erase(sender)
-Testing requirement: Many tests assume wiring changes are visible
-across the cluster once the commad completes.
+member-leaves:
+ for q in queue: if owner[q] = left: left.release(q)
-Name clashes: need to avoid race if same name queue/exchange declared
-on 2 brokers simultaneously
+Need 2 more intercept points in broker::Cluster:
-** TODO [#A] Passing all existing cluster tests.
+consume(q,consumer,consumerCount) - Queue::consume()
+ if consumerCount == 1: mcast consume(q)
-The new cluster should be a drop-in replacement for the old, so it
-should be able to pass all the existing tests.
+cancel(q,consumer,consumerCount) - Queue::cancel()
+ if consumerCount == 0:
+ ownership[q].drop()
+ mcast cancel(q)
-** TODO [#A] Update to new members joining.
+#TODO: lifecycle, updating cluster data structures when queues are destroyed
+
+*** Increasing concurrency
+The major performance limitation of the old cluster is that it does
+everything in the single CPG deliver thread context.
+
+We can get additional concurrency by creating a thread context _per queue_
+for queue operations: enqueue, acquire, accept etc.
+
+We associate a PollableQueue of queue operations with each AMQP queue.
+The CPG deliver thread would
+- build messages and associate with cluster IDs.
+- push queue ops to the appropriate PollableQueue to be dispatched the queues thread.
+
+Serializing operations on the same queue avoids contention, but takes advantage
+of the independence of operations on separate queues.
-Need to resolve [[Queue sequence numbers vs. independant message IDs]] first.
-- implicit sequence numbers are more tricky to replicate to new member.
+*** Re-use of existing cluster code
+- re-use Event
+- re-use Multicaster
+- re-use same PollableQueueSetup (may experiment later)
+- new Core class to replace Cluster.
+- keep design modular, keep threading rules clear.
-Update individual objects (queues and exchanges) independently.
-- create queues first, then update all queues and exchanges in parallel.
-- multiple updater threads, per queue/exchange.
-- updater sends messages to special exchange(s) (not using extended AMQP controls)
+** TODO [#B] Large message replication.
+Multicast should encode messages in fixed size buffers (64k)?
+Can't assume we can send message in one chunk.
+For 0-10 can use channel numbers & send whole frames packed into larger buffer.
+** TODO [#B] Transaction support.
+Extend broker::Cluster interface to capture transaction context and completion.
+Sequence number to generate per-node tx IDs.
+Replicate transaction completion.
+** TODO [#B] Batch CPG multicast messages
+The new cluster design involves a lot of small multicast messages,
+they need to be batched into larger CPG messages for efficiency.
+** TODO [#B] Genuine async completion
+Replace current synchronous waiting implementation with genuine async completion.
-Queue updater:
-- marks the queue position at the sync point
-- sends messages starting from the sync point working towards the head of the queue.
-- send "done" message.
-Note: updater remains active throughout, consuming clients actually reduce the
-size of the update.
+Test: enhance test_store.cpp to defer enqueueComplete till special message received.
-Queue updatee:
-- enqueues received from CPG: add to back of queue as normal.
-- dequeues received from CPG: apply if found, else save to check at end of update.
-- messages from updater: add to the *front* of the queue.
-- update complete: apply any saved dequeues.
+Async callback uses *requestIOProcessing* to queue action on IO thread.
-Exchange updater:
-- updater: send snapshot of exchange as it was at the sync point.
+** TODO [#B] Async completion of accept when dequeue completes.
+Interface is already there on broker::Message, just need to ensure
+that store and cluster implementations call it appropriately.
-Exchange updatee:
-- queue exchange operations after the sync point.
-- when snapshot is received: apply saved operations.
+** TODO [#B] Replicate wiring.
+From messageStore create/destroy/bind, replicate encoded declare/destroy/bind command.
-Updater remains active throughout.
-Updatee stalls clients until the update completes.
+** TODO [#B] New members joining - first pass
-Updating queue/exchange/binding objects is via the same encode/decode
-that is used by the store. Updatee to use recovery interfaces to
-recover?
+Re-use update code from old cluster but don't replicate sessions &
+connections.
-** TODO [#A] Failover updates to client.
-Implement the amq.failover exchange to notify clients of membership.
+Need to extend it to send cluster IDs with messages.
-** TODO [#B] Initial status protocol.
-Handshake to give status of each broker member to new members joining.
-Status includes
-- persistent store state (clean, dirty)
-- cluster protocol version.
+Need to replicate the queue ownership data as part of the update.
-** TODO [#B] Persistent cluster support.
-Initial status protoocl to support persistent start-up (see existing code)
+** TODO [#B] Persistence support.
+InitialStatus protoocl etc. to support persistent start-up (existing code)
Only one broker recovers from store, update to others.
Assign cluster IDs to messages recovered from store, don't replicate. See Queue::recover.
-** TODO [#B] Management support
-Replicate management methods that modify queues - e.g. move, purge.
+** TODO [#B] Handle other ways that messages can leave a queue.
+
+Other ways (other than via a consumer) that messages are take off a queue.
+
+NOTE: Not controlled by queue lock, how to make them consistent?
+
Target broker may not have all messages on other brokers for purge/destroy.
- Queue::move() - need to wait for lock? Replicate?
- Queue::get() - ???
@@ -169,38 +395,66 @@ Target broker may not have all messages on other brokers for purge/destroy.
Need to add callpoints & mcast messages to replicate these?
-** TODO [#B] TX transaction support.
-Extend broker::Cluster interface to capture transaction context and completion.
-Running brokers exchange TX information.
-New broker update includes TX information.
-
- // FIXME aconway 2010-10-18: As things stand the cluster is not
- // compatible with transactions
- // - enqueues occur after routing is complete
- // - no call to Cluster::enqueue, should be in Queue::process?
- // - no transaction context associated with messages in the Cluster interface.
- // - no call to Cluster::accept in Queue::dequeueCommitted
-
-** TODO [#B] DTX transaction support.
-Extend broker::Cluster interface to capture transaction context and completion.
-Running brokers exchange DTX information.
-New broker update includes DTX information.
-
-** TODO [#B] Async completion of accept.
-When this is fixed in the standalone broker, it should be fixed for cluster.
-
-** TODO [#B] Network partitions and quorum.
-Re-use existing implementation.
+** TODO [#B] Flow control for internal queues.
+
+Need to bound the size of internal queues: delivery and multicast.
+- stop polling for read on client connections when we reach a bound.
+- restart polling when we get back under it.
+
+That will stop local multicasting, we still have to deal with remote
+multicasting (note existing cluster does not do this.) Something like:
+- when over bounds multicast a flow-control event.
+- on delivery of flow-control all members stop polling to read client connections
+- when back under bounds send flow-control-end, all members resume
+- if flow-controling member dies others resume
+
+** TODO [#B] Integration with transactions.
+Do we want to replicate during transaction & replicate commit/rollback
+or replicate only on commit?
+No integration with DTX transactions.
+** TODO [#B] Make new cluster work with replication exchange.
+Possibly re-use some common logic. Replication exchange is like clustering
+except over TCP.
+** TODO [#B] Better concurrency, scalabiility on multi-cores.
+Introduce PollableQueue of operations per broker queue. Queue up mcast
+operations (enqueue, acquire, accept etc.) to be handled concurrently
+on different queue. Performance testing to verify improved scalability.
+** TODO [#C] Async completion for declare, bind, destroy queues and exchanges.
+Cluster needs to complete these asynchronously to guarantee resources
+exist across the cluster when the command completes.
** TODO [#C] Allow non-replicated exchanges, queues.
-Set qpid.replicate=false in declare arguments, set flag on Exchange, Queue objects.
+Set qpid.replicated=false in declare arguments, set flag on Exchange, Queue objects.
- save replicated status to store.
- support in management tools.
+Replicated exchange: replicate binds to replicated queues.
Replicated queue: replicate all messages.
-Replicated exchange: replicate bindings to replicated queues only.
-Configurable default? Defaults to true.
+** TODO [#C] New members joining - improved.
+
+Replicate wiring like old cluster, stall for wiring but not for
+messages. Update messages on a per-queue basis from back to front.
+
+Updater:
+- stall & push wiring: declare exchanges, queues, bindings.
+- start update iterator thread on each queue.
+- unstall and process normally while iterator threads run.
+
+Update iterator thread:
+- starts at back of updater queue, message m.
+- send update_front(q,m) to updatee and advance towards front
+- at front: send update_done(q)
+
+Updatee:
+- stall, receive wiring, lock all queues, mark queues "updating", unstall
+- update_front(q,m): push m to *front* of q
+- update_done(q): mark queue "ready"
+
+Updatee cannot take the queue consume lock for a queue that is updating.
+Updatee *can* push messages onto a queue that is updating.
+
+TODO: Is there any way to eliminate the stall for wiring?
** TODO [#C] Refactoring of common concerns.
@@ -215,40 +469,9 @@ Look for ways to capitalize on the similarity & simplify the code.
In particular QueuedEvents (async replication) strongly resembles
cluster replication, but over TCP rather than multicast.
-
+** TODO [#C] Concurrency for enqueue events.
+All enqueue events are being processed in the CPG deliver thread context which
+serializes all the work. We only need ordering on a per queue basis, can we
+enqueue in parallel on different queues and will that improve performance?
** TODO [#C] Handling immediate messages in a cluster
Include remote consumers in descision to deliver an immediate message?
-** TODO [#C] Remove old cluster hacks and workarounds
-The old cluster has workarounds in the broker code that can be removed.
-- [ ] drop code to replicate management model.
-- [ ] drop timer workarounds for TTL, management, heartbeats.
-- [ ] drop "cluster-safe assertions" in broker code.
-- [ ] drop connections, sessions, management from cluster update.
-- [ ] drop security workarounds: cluster code now operates after message decoding.
-- [ ] drop connection tracking in cluster code.
-- [ ] simper inconsistent-error handling code, no need to stall.
-** TODO [#C] Support for live upgrades.
-
-Allow brokers in a running cluster to be replaced one-by-one with a new version.
-
-The old cluster protocol was unstable because any changes in broker
-state caused changes to the cluster protocol.The new design should be
-much more stable.
-
-Points to implement:
-- Brokers should ignore unknown controls (with a warning) rather than an error.
-- Limit logging frequency for unknown control warnings.
-- Add a version number at front of every CPG message. Determines how the
- rest of the message is decoded. (allows for entirely new encodings e.g. AMQP 1.0)
-- Protocol version XML element in cluster.xml, on each control.
-- Initial status protocol to include protocol version number.
-
-** TODO [#C] Support for AMQP 1.0.
-
-* Testing
-** TODO [#A] Pass all existing cluster tests.
-Requires [[Defer and async completion of wiring commands.]]
-** TODO [#A] New cluster tests.
-Stress tests & performance benchmarks focused on changes in new cluster:
-- concurrency by queues rather than connections.
-- different handling shared queues when consuemrs are on different brokers.
diff --git a/cpp/docs/api/developer.doxygen.in b/cpp/docs/api/developer.doxygen.in
index 1e1fddab80..fd3a9ac621 100644
--- a/cpp/docs/api/developer.doxygen.in
+++ b/cpp/docs/api/developer.doxygen.in
@@ -1029,7 +1029,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN= QMFE_EXTERN=
+PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/cpp/docs/api/doxygen_mainpage.h b/cpp/docs/api/doxygen_mainpage.h
index 9acae52da4..cb36d7edb0 100644
--- a/cpp/docs/api/doxygen_mainpage.h
+++ b/cpp/docs/api/doxygen_mainpage.h
@@ -266,46 +266,7 @@
* else
* session.rollback();
* </pre>
- *
- * <h3>Exceptions</h3>
- *
- * All exceptions for the messaging API have MessagingException as
- * their base class.
-
- * A common class of exception are those related to processing
- * addresses used to create senders and/or receivers. These all have
- * AddressError as their base class.
- *
- * Where there is a syntax error in the address itself, a
- * MalformedAddress will be thrown. Where the address is valid, but
- * there is an error in interpreting (i.e. resolving) it, a
- * ResolutionError - or a sub-class of it - will be thrown. If the
- * address has assertions enabled for a given context and the asserted
- * node properties are not in fact correct then AssertionFailed will
- * be thrown. If the node is not found, NotFound will be thrown.
- *
- * The loss of the underlying connection (e.g. the TCP connection)
- * results in TransportFailure being thrown. If automatic reconnect is
- * enabled, this will be caught be the library which will then try to
- * reconnect. If reconnection - as configured by the connection
- * options - fails, then TransportFailure will be thrown. This can
- * occur on any call to the messaging API.
- *
- * Sending a message may also result in an exception
- * (e.g. TargetCapacityExceeded if a queue to which the message is
- * delivered cannot enqueue it due to lack of capacity). For
- * asynchronous send the exception may not be thrown on the send
- * invocation that actually triggers it, but on a subsequent method
- * call on the API.
- *
- * Certain exceptions may render the session invalid; once these
- * occur, subsequent calls on the session will throw the same class of
- * exception. This is not an intrinsic property of the class of
- * exception, but is a result of the current mapping of the API to the
- * underlying AMQP 0-10 protocol. You can test whether the session is
- * valid at any time using the hasError() and/or checkError() methods
- * on Session.
- *
+ *
* <h3>Logging</h3>
*
* The Qpidd broker and C++ clients can both use environment variables to
diff --git a/cpp/docs/api/footer.html b/cpp/docs/api/footer.html
index 5a31e81821..883410ce25 100644
--- a/cpp/docs/api/footer.html
+++ b/cpp/docs/api/footer.html
@@ -25,7 +25,7 @@ Qpid C++ API Reference</small></address>
<address style="text-align: right;">
<small>
-Generated on $date for $projectname by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion</small>
+Generated on $datetime for $projectname by&nbsp;<a href="http://www.doxygen.org/index.html"><img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> $doxygenversion</small>
</address>
</body>
</html>
diff --git a/cpp/docs/api/user.doxygen.in b/cpp/docs/api/user.doxygen.in
index ec0fd1361c..2728df47e4 100644
--- a/cpp/docs/api/user.doxygen.in
+++ b/cpp/docs/api/user.doxygen.in
@@ -1021,7 +1021,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN= QMFE_EXTERN=
+PREDEFINED = QPID_CLIENT_EXTERN= QPID_COMMON_EXTERN= QPID_CONSOLE_EXTERN= QPID_BROKER_EXTERN= QPID_MESSAGING_EXTERN= QMF_EXTERN=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/cpp/docs/man/Makefile.am b/cpp/docs/man/Makefile.am
index b821568f81..14295f73bf 100644
--- a/cpp/docs/man/Makefile.am
+++ b/cpp/docs/man/Makefile.am
@@ -16,29 +16,10 @@
# specific language governing permissions and limitations
# under the License.
#
-
-# Generate makefile from qpidd --help
-#
-# Note: qiddd.1 is normally a _checked in_ pre-generated file, so that
-# make dist does not have to build the entire source just for the man page.
-#
-# To update the checked-in file (e.g. for a new release) do the following:
-#
-# - start with a completely clean checkout.
-# - make sure there are no modules installed in your configured prefix,
-# we don't want to pick up configuration from optional modules
-# - do bootstrap; configure
-# - in build-dir: cd src; make # build the broker
-# - in source-dir: cd docs/man; rm qpidd.1 # remove checked-in man page.
-# - in build-dir: cd docs/man; make # make new man page
-# - edit qpidd.1 to remove all default values referring to file/directory locations.
-# these values will differ between builds depending on configuration.
-# - if source-dir != build-dir: copy qpidd.1 from build-dir/docs/man to source-dir/docs/man
-
dist_man_MANS = qpidd.1
-man_aux = $(dist_man_MANS:.1=.x)
-EXTRA_DIST = $(man_aux) generate_manpage groffify_options.sed groffify_template.sed
+man_aux = $(dist_man_MANS:.1=.x)
+EXTRA_DIST = $(man_aux) generate_manpage groffify_options.sed groffify_template.sed
DISTCLEANFILES = $(dist_man_MANS)
CLEANFILES=qpidd.1
diff --git a/cpp/docs/man/qpidd.1 b/cpp/docs/man/qpidd.1
deleted file mode 100644
index d2cff454cf..0000000000
--- a/cpp/docs/man/qpidd.1
+++ /dev/null
@@ -1,247 +0,0 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.38.2.
-.TH QPIDD "1" "March 2011" "qpidd (qpidc) version 0.11" "User Commands"
-.SH NAME
-
-qpidd \- the Qpid AMQP Message Broker Daemon
-.SH SYNOPSIS
-
-qpidd [-p port] [--config config_file] [--data-dir directory]
-.SH DESCRIPTION
-
-An AMQP message broker daemon that stores, routes and forwards
-messages using the Advanced Message Queueing Protocol (AMQP).
-.SH OPTIONS
-
-The options below are built-in to qpidd. Installing add-on modules provides additional options. To see the full set of options available type "qpidd --help"
-
-Options may be specified via command line, environment variable or configuration file. See FILES and ENVIRONMENT below for details.
-.PP
-
-.TP
-\fB\-h\fR [ \fB\-\-help\fR ]
-Displays the help message
-.TP
-\fB\-v\fR [ \fB\-\-version\fR ]
-Displays version information
-.TP
-\fB\-\-config\fR FILE
-Reads configuration from FILE
-.SS "Module options:"
-.TP
-\fB\-\-module\-dir\fR DIR
-Load all shareable modules in this
-directory
-.TP
-\fB\-\-load\-module\fR FILE
-Specifies additional module(s) to be
-loaded
-.TP
-\fB\-\-no\-module\-dir\fR
-Don't load modules from module
-directory
-.SS "Broker Options:"
-.TP
-\fB\-\-data\-dir\fR DIR
-Directory to contain persistent data
-generated by the broker
-.TP
-\fB\-\-no\-data\-dir\fR
-Don't use a data directory. No
-persistent configuration will be loaded
-or stored
-.TP
-\fB\-p\fR [ \fB\-\-port\fR ] PORT (5672)
-Tells the broker to listen on PORT
-.TP
-\fB\-\-worker\-threads\fR N (3)
-Sets the broker thread pool size
-.TP
-\fB\-\-max\-connections\fR N (500)
-Sets the maximum allowed connections
-.TP
-\fB\-\-connection\-backlog\fR N (10)
-Sets the connection backlog limit for
-the server socket
-.TP
-\fB\-m\fR [ \fB\-\-mgmt\-enable\fR ] yes|no (1)
-Enable Management
-.TP
-\fB\-\-mgmt\-qmf2\fR yes|no (1)
-Enable broadcast of management
-information over QMF v2
-.TP
-\fB\-\-mgmt\-qmf1\fR yes|no (1)
-Enable broadcast of management
-information over QMF v1
-.TP
-\fB\-\-mgmt\-pub\-interval\fR SECONDS (10)
-Management Publish Interval
-.TP
-\fB\-\-queue\-purge\-interval\fR SECONDS (600)
-Interval between attempts to purge any
-expired messages from queues
-.TP
-\fB\-\-auth\fR yes|no (1)
-Enable authentication, if disabled all
-incoming connections will be trusted
-.TP
-\fB\-\-realm\fR REALM (QPID)
-Use the given realm when performing
-authentication
-.TP
-\fB\-\-default\-queue\-limit\fR BYTES (104857600)
-Default maximum size for queues (in
-bytes)
-.TP
-\fB\-\-tcp\-nodelay\fR
-Set TCP_NODELAY on TCP connections
-.TP
-\fB\-\-require\-encryption\fR
-Only accept connections that are
-encrypted
-.TP
-\fB\-\-known\-hosts\-url\fR URL or 'none'
-URL to send as 'known\-hosts' to clients
-('none' implies empty list)
-.TP
-\fB\-\-sasl\-config\fR DIR
-gets sasl config info from nonstandard
-location
-.TP
-\fB\-\-max\-session\-rate\fR MESSAGES/S (0)
-Sets the maximum message rate per
-session (0=unlimited)
-.TP
-\fB\-\-async\-queue\-events\fR yes|no (0)
-Set Queue Events async, used for
-services like replication
-.TP
-\fB\-\-default\-flow\-stop\-threshold\fR PERCENT (80)
-Percent of queue's maximum capacity at
-which flow control is activated.
-.TP
-\fB\-\-default\-flow\-resume\-threshold\fR PERCENT (70)
-Percent of queue's maximum capacity at
-which flow control is de\-activated.
-.TP
-\fB\-\-default\-event\-threshold\-ratio\fR %age of limit (80)
-The ratio of any specified queue limit
-at which an event will be raised
-.SS "Logging options:"
-.TP
-\fB\-t\fR [ \fB\-\-trace\fR ]
-Enables all logging
-.TP
-\fB\-\-log\-enable\fR RULE (notice+)
-Enables logging for selected levels and
-components. RULE is in the form
-\&'LEVEL[+][:PATTERN]' Levels are one of:
-.IP
-trace debug info notice warning error
-.IP
-critical
-For example:
-\&'\-\-log\-enable warning+' logs all
-warning, error and critical messages.
-\&'\-\-log\-enable debug:framing' logs debug
-messages from the framing namespace.
-This option can be used multiple times
-.TP
-\fB\-\-log\-time\fR yes|no (1)
-Include time in log messages
-.TP
-\fB\-\-log\-level\fR yes|no (1)
-Include severity level in log messages
-.TP
-\fB\-\-log\-source\fR yes|no (0)
-Include source file:line in log
-messages
-.TP
-\fB\-\-log\-thread\fR yes|no (0)
-Include thread ID in log messages
-.TP
-\fB\-\-log\-function\fR yes|no (0)
-Include function signature in log
-messages
-.TP
-\fB\-\-log\-prefix\fR STRING
-Prefix to append to all log messages
-.SS "Logging sink options:"
-.TP
-\fB\-\-log\-to\-stderr\fR yes|no (1)
-Send logging output to stderr
-.TP
-\fB\-\-log\-to\-stdout\fR yes|no (0)
-Send logging output to stdout
-.TP
-\fB\-\-log\-to\-file\fR FILE
-Send log output to FILE.
-.TP
-\fB\-\-log\-to\-syslog\fR yes|no (0)
-Send logging output to syslog;
-customize using \fB\-\-syslog\-name\fR and
-\fB\-\-syslog\-facility\fR
-.TP
-\fB\-\-syslog\-name\fR NAME (lt\-qpidd)
-Name to use in syslog messages
-.TP
-\fB\-\-syslog\-facility\fR LOG_XXX (LOG_DAEMON)
-Facility to use in syslog messages
-.SS "Daemon options:"
-.TP
-\fB\-d\fR [ \fB\-\-daemon\fR ]
-Run as a daemon. Logs to syslog by
-default in this mode.
-.TP
-\fB\-\-transport\fR TRANSPORT (tcp)
-The transport for which to return the
-port
-.TP
-\fB\-\-pid\-dir\fR DIR
-Directory where port\-specific PID file
-is stored
-.TP
-\fB\-w\fR [ \fB\-\-wait\fR ] SECONDS (600)
-Sets the maximum wait time to
-initialize the daemon. If the daemon
-fails to initialize, prints an error
-and returns 1
-.TP
-\fB\-c\fR [ \fB\-\-check\fR ]
-Prints the daemon's process ID to
-stdout and returns 0 if the daemon is
-running, otherwise returns 1
-.TP
-\fB\-q\fR [ \fB\-\-quit\fR ]
-Tells the daemon to shut down
-.SH ENVIRONMENT
-.I QPID_<option>
-.RS
-There is an environment variable for each option.
-.RE
-
-The environment variable is the option name in uppercase, prefixed with QPID_ and '.' or '-' are replaced with '_'. Environment settings are over-ridden by command line settings. For example:
-
- export QPID_PORT=6000
- export QPID_MAX_CONNECTIONS=10
- export QPID_LOG_TO_FILE=/tmp/qpidd.log
-.SH FILES
-.I /etc/qpidd.conf
-.RS
-Default configuration file.
-.RE
-
-Configuration file settings are over-ridden by command line or environment variable settings. '--config <file>' or 'export QPID_CONFIG=<file>' specifies an alternate file.
-
-Each line is a name=value pair. Blank lines and lines beginning with # are ignored. For example:
-
- # My qpidd configuration file.
- port=6000
- max-connections=10
- log-to-file=/tmp/qpidd.log
-.SH AUTHOR
-
-The Apache Qpid Project, dev@qpid.apache.org
-.SH "REPORTING BUGS"
-
-Please report bugs to users@qpid.apache.org
diff --git a/cpp/docs/man/qpidd.x b/cpp/docs/man/qpidd.x
index 0ccf3b562a..af5d9628ee 100644
--- a/cpp/docs/man/qpidd.x
+++ b/cpp/docs/man/qpidd.x
@@ -13,8 +13,6 @@ messages using the Advanced Message Queueing Protocol (AMQP).
[OPTIONS]
-The options below are built-in to qpidd. Installing add-on modules provides additional options. To see the full set of options available type "qpidd --help"
-
Options may be specified via command line, environment variable or configuration file. See FILES and ENVIRONMENT below for details.
[FILES]
diff --git a/cpp/etc/Makefile.am b/cpp/etc/Makefile.am
index 1e4db561a7..c91dbcbbad 100644
--- a/cpp/etc/Makefile.am
+++ b/cpp/etc/Makefile.am
@@ -30,7 +30,30 @@ nobase_sysconf_DATA = \
qpidd.conf
if HAVE_SASL
+SASL_DB = qpidd.sasldb
+
nobase_sysconf_DATA += \
$(SASL_CONF)
+sasldbdir = $(localstatedir)/lib/qpidd
+sasldb_DATA = $(SASL_DB)
+
+# Setup the default sasldb file with a single user, guest, with an
+# obvious password. This user and password are the default for many
+# clients.
+#
+# The realm specified by -u is very important, and QPID is the default
+# for the broker so we use it here. The realm is important because it
+# defaults to the local hostname of the machine running the
+# broker. This may not seem to bad at first glance, but it means that
+# the sasldb has to be tailored to each machine that would be running
+# a broker, and if the machine ever changed its name the
+# authentication would stop working until the sasldb was updated. For
+# these reasons we always want the broker to specify a realm where its
+# users live, and we want the users to exist in that realm as well.
+$(SASL_DB):
+ echo guest | $(SASL_PASSWD) -c -p -f $(SASL_DB) -u QPID guest
+
+CLEANFILES=$(SASL_DB)
+
endif
diff --git a/cpp/etc/qpidd.conf b/cpp/etc/qpidd.conf
index bfe4e38bbd..8082660f6f 100644
--- a/cpp/etc/qpidd.conf
+++ b/cpp/etc/qpidd.conf
@@ -21,4 +21,4 @@
#
# (Note: no spaces on either side of '='). Using default settings:
# "qpidd --help" or "man qpidd" for more details.
-cluster-mechanism=DIGEST-MD5 ANONYMOUS
+cluster-mechanism=ANONYMOUS
diff --git a/cpp/etc/sasl2/qpidd.conf b/cpp/etc/sasl2/qpidd.conf
index d766cb8ef8..3197d7792a 100644
--- a/cpp/etc/sasl2/qpidd.conf
+++ b/cpp/etc/sasl2/qpidd.conf
@@ -17,8 +17,8 @@
# under the License.
#
#
-# This configuation allows for either SASL ANONYMOUS or DIGEST-MD5
-# authentication. The DIGEST-MD5 authentication is done on a
+# This configuation allows for either SASL PLAIN or ANONYMOUS
+# authentication. The PLAIN authentication is done on a
# username+password, which is stored in the sasldb_path
# file. Usernames and passwords can be added to the file using the
# command:
@@ -39,7 +39,6 @@
pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: /var/lib/qpidd/qpidd.sasldb
-mech_list: DIGEST-MD5 ANONYMOUS
#following line stops spurious 'sql_select option missing' errors when
#cyrus-sql-sasl plugin is installed
diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index 1b28cfd031..da8e39e944 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -77,14 +77,25 @@ macro(add_example subdir example)
endmacro(add_example)
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/README.txt
+ ${CMAKE_CURRENT_SOURCE_DIR}/README.verify
+ ${CMAKE_CURRENT_SOURCE_DIR}/verify
+ ${CMAKE_CURRENT_SOURCE_DIR}/verify_all
DESTINATION ${QPID_INSTALL_EXAMPLESDIR}
COMPONENT ${QPID_COMPONENT_EXAMPLES})
if (MSVC)
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/examples.sln
+ ${CMAKE_CURRENT_SOURCE_DIR}/old-examples.sln
DESTINATION ${QPID_INSTALL_EXAMPLESDIR}
COMPONENT ${QPID_COMPONENT_EXAMPLES})
endif (MSVC)
+add_subdirectory(direct)
+add_subdirectory(failover)
+add_subdirectory(fanout)
+add_subdirectory(pub-sub)
+#add_subdirectory(qmf-agent)
add_subdirectory(qmf-console)
+add_subdirectory(request-response)
+add_subdirectory(tradedemo)
+add_subdirectory(xml-exchange)
add_subdirectory(messaging)
-add_subdirectory(old_api)
diff --git a/cpp/examples/Makefile.am b/cpp/examples/Makefile.am
index 6b2bb73587..c6cc308d98 100644
--- a/cpp/examples/Makefile.am
+++ b/cpp/examples/Makefile.am
@@ -16,7 +16,15 @@
# specific language governing permissions and limitations
# under the License.
#
-SUBDIRS = qmf-console messaging old_api
+SUBDIRS = direct fanout pub-sub request-response failover qmf-console tradedemo messaging
+if HAVE_XML
+ SUBDIRS += xml-exchange
+ broker_args = "--no-module-dir --data-dir \"\" --auth no --load-module $(top_builddir)/src/.libs/xml.so"
+endif
+if !HAVE_XML
+ exclude_examples_regexp="xml" # Exclude XML examples.
+ broker_args = "--no-module-dir --data-dir \"\" --auth no"
+endif
MAKEDIST=.libs/Makefile
@@ -29,9 +37,13 @@ $(MAKEDIST): Makefile
examplesdir=$(pkgdatadir)/examples
dist_examples_DATA = README.txt $(MAKEDIST)
-EXTRA_DIST = examples.sln CMakeLists.txt
+EXTRA_DIST = README.verify verify verify_all examples.sln CMakeLists.txt
# For older versions of automake
abs_top_srcdir = @abs_top_srcdir@
abs_top_builddir = @abs_top_builddir@
+# Verify the examples in the buid tree.
+check-local:
+ $(srcdir)/verify_all $(abs_top_srcdir)/.. $(abs_top_builddir) $(broker_args) $(exclude_examples_regexp)
+
diff --git a/cpp/examples/old_api/README.verify b/cpp/examples/README.verify
index e1370764c9..e1370764c9 100644
--- a/cpp/examples/old_api/README.verify
+++ b/cpp/examples/README.verify
diff --git a/cpp/examples/old_api/direct/CMakeLists.txt b/cpp/examples/direct/CMakeLists.txt
index 2ec1b2b813..2ec1b2b813 100644
--- a/cpp/examples/old_api/direct/CMakeLists.txt
+++ b/cpp/examples/direct/CMakeLists.txt
diff --git a/cpp/examples/direct/Makefile.am b/cpp/examples/direct/Makefile.am
new file mode 100644
index 0000000000..b07db2cfd6
--- /dev/null
+++ b/cpp/examples/direct/Makefile.am
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+examplesdir=$(pkgdatadir)/examples/direct
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=direct_producer listener declare_queues
+direct_producer_SOURCES=direct_producer.cpp
+direct_producer_LDADD=$(CLIENT_LIB)
+
+listener_SOURCES=listener.cpp
+listener_LDADD=$(CLIENT_LIB)
+
+declare_queues_SOURCES=declare_queues.cpp
+declare_queues_LDADD=$(CLIENT_LIB)
+
+examples_DATA= \
+ direct_producer.cpp \
+ listener.cpp \
+ declare_queues.cpp \
+ $(MAKEDIST)
+
+EXTRA_DIST= \
+ $(examples_DATA) \
+ CMakeLists.txt \
+ verify \
+ verify.in \
+ direct_declare_queues.vcproj \
+ direct_direct_producer.vcproj \
+ direct_listener.vcproj
diff --git a/cpp/examples/old_api/direct/declare_queues.cpp b/cpp/examples/direct/declare_queues.cpp
index 9a51d1982b..9a51d1982b 100644
--- a/cpp/examples/old_api/direct/declare_queues.cpp
+++ b/cpp/examples/direct/declare_queues.cpp
diff --git a/cpp/examples/old_api/direct/direct_declare_queues.vcproj b/cpp/examples/direct/direct_declare_queues.vcproj
index 083474b9ef..083474b9ef 100644
--- a/cpp/examples/old_api/direct/direct_declare_queues.vcproj
+++ b/cpp/examples/direct/direct_declare_queues.vcproj
diff --git a/cpp/examples/old_api/direct/direct_direct_producer.vcproj b/cpp/examples/direct/direct_direct_producer.vcproj
index f091fbf291..f091fbf291 100644
--- a/cpp/examples/old_api/direct/direct_direct_producer.vcproj
+++ b/cpp/examples/direct/direct_direct_producer.vcproj
diff --git a/cpp/examples/old_api/direct/direct_listener.vcproj b/cpp/examples/direct/direct_listener.vcproj
index dce1d3ec28..dce1d3ec28 100644
--- a/cpp/examples/old_api/direct/direct_listener.vcproj
+++ b/cpp/examples/direct/direct_listener.vcproj
diff --git a/cpp/examples/old_api/direct/direct_producer.cpp b/cpp/examples/direct/direct_producer.cpp
index ecc9675189..ecc9675189 100644
--- a/cpp/examples/old_api/direct/direct_producer.cpp
+++ b/cpp/examples/direct/direct_producer.cpp
diff --git a/cpp/examples/old_api/direct/listener.cpp b/cpp/examples/direct/listener.cpp
index 38bf24ec41..38bf24ec41 100644
--- a/cpp/examples/old_api/direct/listener.cpp
+++ b/cpp/examples/direct/listener.cpp
diff --git a/cpp/examples/old_api/direct/verify b/cpp/examples/direct/verify
index f598bacc1f..f598bacc1f 100644
--- a/cpp/examples/old_api/direct/verify
+++ b/cpp/examples/direct/verify
diff --git a/cpp/examples/old_api/direct/verify.in b/cpp/examples/direct/verify.in
index d1e95f1151..d1e95f1151 100644
--- a/cpp/examples/old_api/direct/verify.in
+++ b/cpp/examples/direct/verify.in
diff --git a/cpp/examples/examples.sln b/cpp/examples/examples.sln
index 6f96105d97..8511fe3cce 100644
--- a/cpp/examples/examples.sln
+++ b/cpp/examples/examples.sln
@@ -32,14 +32,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "messaging_drain", "messagin
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "messaging_spout", "messaging\messaging_spout.vcproj", "{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_console", "qmf-console\qmf-console_console.vcproj", "{490473E1-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_ping", "qmf-console\qmf-console_ping.vcproj", "{C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_printevents", "qmf-console\qmf-console_printevents.vcproj", "{72C74624-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_queuestats", "qmf-console\qmf-console_queuestats.vcproj", "{B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -96,22 +88,6 @@ Global
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|Win32.Build.0 = Release|Win32
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|x64.ActiveCfg = Release|x64
{D3115AC9-91C4-4D79-BCAC-DE837C70F1EA}.Release|x64.Build.0 = Release|x64
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.ActiveCfg = Debug|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.Build.0 = Debug|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.ActiveCfg = Release|Win32
- {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.Build.0 = Release|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
- {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/cpp/examples/old_api/failover/CMakeLists.txt b/cpp/examples/failover/CMakeLists.txt
index 05db8fad51..05db8fad51 100644
--- a/cpp/examples/old_api/failover/CMakeLists.txt
+++ b/cpp/examples/failover/CMakeLists.txt
diff --git a/cpp/examples/failover/Makefile.am b/cpp/examples/failover/Makefile.am
new file mode 100644
index 0000000000..48846fdf79
--- /dev/null
+++ b/cpp/examples/failover/Makefile.am
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+examplesdir=$(pkgdatadir)/examples/failover
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=declare_queues resuming_receiver replaying_sender
+
+declare_queues_SOURCES=declare_queues.cpp
+declare_queues_LDADD=$(CLIENT_LIB)
+
+resuming_receiver_SOURCES=resuming_receiver.cpp
+resuming_receiver_LDADD=$(CLIENT_LIB)
+
+replaying_sender_SOURCES=replaying_sender.cpp
+replaying_sender_LDADD=$(CLIENT_LIB)
+
+examples_DATA= \
+ declare_queues.cpp \
+ resuming_receiver.cpp \
+ replaying_sender.cpp \
+ $(MAKEDIST)
+
+# FIXME aconway 2008-10-10: add verify scripts.
+
+EXTRA_DIST= \
+ CMakeLists.txt \
+ failover_declare_queues.vcproj \
+ failover_replaying_sender.vcproj \
+ failover_resuming_receiver.vcproj
diff --git a/cpp/examples/old_api/failover/declare_queues.cpp b/cpp/examples/failover/declare_queues.cpp
index a677870c53..a677870c53 100644
--- a/cpp/examples/old_api/failover/declare_queues.cpp
+++ b/cpp/examples/failover/declare_queues.cpp
diff --git a/cpp/examples/old_api/failover/failover_declare_queues.vcproj b/cpp/examples/failover/failover_declare_queues.vcproj
index c87c72affd..c87c72affd 100644
--- a/cpp/examples/old_api/failover/failover_declare_queues.vcproj
+++ b/cpp/examples/failover/failover_declare_queues.vcproj
diff --git a/cpp/examples/old_api/failover/failover_replaying_sender.vcproj b/cpp/examples/failover/failover_replaying_sender.vcproj
index 6d22fa6770..6d22fa6770 100644
--- a/cpp/examples/old_api/failover/failover_replaying_sender.vcproj
+++ b/cpp/examples/failover/failover_replaying_sender.vcproj
diff --git a/cpp/examples/old_api/failover/failover_resuming_receiver.vcproj b/cpp/examples/failover/failover_resuming_receiver.vcproj
index ba5061e248..ba5061e248 100644
--- a/cpp/examples/old_api/failover/failover_resuming_receiver.vcproj
+++ b/cpp/examples/failover/failover_resuming_receiver.vcproj
diff --git a/cpp/examples/old_api/failover/replaying_sender.cpp b/cpp/examples/failover/replaying_sender.cpp
index 22a7e1ebd3..22a7e1ebd3 100644
--- a/cpp/examples/old_api/failover/replaying_sender.cpp
+++ b/cpp/examples/failover/replaying_sender.cpp
diff --git a/cpp/examples/old_api/failover/resuming_receiver.cpp b/cpp/examples/failover/resuming_receiver.cpp
index d1886ce861..d1886ce861 100644
--- a/cpp/examples/old_api/failover/resuming_receiver.cpp
+++ b/cpp/examples/failover/resuming_receiver.cpp
diff --git a/cpp/examples/old_api/fanout/CMakeLists.txt b/cpp/examples/fanout/CMakeLists.txt
index 3f89d67650..3f89d67650 100644
--- a/cpp/examples/old_api/fanout/CMakeLists.txt
+++ b/cpp/examples/fanout/CMakeLists.txt
diff --git a/cpp/examples/fanout/Makefile.am b/cpp/examples/fanout/Makefile.am
new file mode 100644
index 0000000000..6e2e821eae
--- /dev/null
+++ b/cpp/examples/fanout/Makefile.am
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+examplesdir=$(pkgdatadir)/examples/fanout
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=fanout_producer listener
+fanout_producer_SOURCES=fanout_producer.cpp
+fanout_producer_LDADD=$(CLIENT_LIB)
+
+listener_SOURCES=listener.cpp
+listener_LDADD=$(CLIENT_LIB)
+
+examples_DATA= \
+ fanout_producer.cpp \
+ listener.cpp \
+ $(MAKEDIST)
+
+EXTRA_DIST= \
+ $(examples_DATA) \
+ CMakeLists.txt \
+ verify \
+ verify.in \
+ fanout_fanout_producer.vcproj \
+ fanout_listener.vcproj
diff --git a/cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj b/cpp/examples/fanout/fanout_fanout_producer.vcproj
index daff5f3cf0..daff5f3cf0 100644
--- a/cpp/examples/old_api/fanout/fanout_fanout_producer.vcproj
+++ b/cpp/examples/fanout/fanout_fanout_producer.vcproj
diff --git a/cpp/examples/old_api/fanout/fanout_listener.vcproj b/cpp/examples/fanout/fanout_listener.vcproj
index f0e91b7dc6..f0e91b7dc6 100644
--- a/cpp/examples/old_api/fanout/fanout_listener.vcproj
+++ b/cpp/examples/fanout/fanout_listener.vcproj
diff --git a/cpp/examples/old_api/fanout/fanout_producer.cpp b/cpp/examples/fanout/fanout_producer.cpp
index decd4d314d..decd4d314d 100644
--- a/cpp/examples/old_api/fanout/fanout_producer.cpp
+++ b/cpp/examples/fanout/fanout_producer.cpp
diff --git a/cpp/examples/old_api/fanout/listener.cpp b/cpp/examples/fanout/listener.cpp
index cd3071c29a..cd3071c29a 100644
--- a/cpp/examples/old_api/fanout/listener.cpp
+++ b/cpp/examples/fanout/listener.cpp
diff --git a/cpp/examples/old_api/fanout/verify b/cpp/examples/fanout/verify
index 2eaadff56b..2eaadff56b 100644
--- a/cpp/examples/old_api/fanout/verify
+++ b/cpp/examples/fanout/verify
diff --git a/cpp/examples/old_api/fanout/verify.in b/cpp/examples/fanout/verify.in
index 8f8612ce67..8f8612ce67 100644
--- a/cpp/examples/old_api/fanout/verify.in
+++ b/cpp/examples/fanout/verify.in
diff --git a/cpp/examples/messaging/drain.cpp b/cpp/examples/messaging/drain.cpp
index 563e5e5060..5c938e9742 100644
--- a/cpp/examples/messaging/drain.cpp
+++ b/cpp/examples/messaging/drain.cpp
@@ -45,12 +45,12 @@ struct Options : OptionParser
url("127.0.0.1"),
timeout(0),
forever(false),
- count(0)
+ count(1)
{
add("broker,b", url, "url of broker to connect to");
add("timeout,t", timeout, "timeout in seconds to wait before exiting");
add("forever,f", forever, "ignore timeout and wait forever");
- add("connection-options", connectionOptions, "connection options string in the form {name1:value1, name2:value2}");
+ add("connection-options", connectionOptions, "connection options string in the form {name1=value1, name2=value2}");
add("count,c", count, "number of messages to read before exiting");
}
diff --git a/cpp/examples/messaging/server.cpp b/cpp/examples/messaging/server.cpp
index aa271d91f9..ab72694c61 100644
--- a/cpp/examples/messaging/server.cpp
+++ b/cpp/examples/messaging/server.cpp
@@ -39,8 +39,8 @@ using std::string;
int main(int argc, char** argv) {
const char* url = argc>1 ? argv[1] : "amqp:tcp:127.0.0.1:5672";
- std::string connectionOptions = argc > 2 ? argv[2] : "";
-
+ std::string connectionOptions = argc > 3 ? argv[3] : "";
+
Connection connection(url, connectionOptions);
try {
connection.open();
diff --git a/cpp/examples/messaging/spout.cpp b/cpp/examples/messaging/spout.cpp
index cd11a7ad81..57b955c1de 100644
--- a/cpp/examples/messaging/spout.cpp
+++ b/cpp/examples/messaging/spout.cpp
@@ -65,7 +65,7 @@ struct Options : OptionParser
add("property,P", properties, "specify message property");
add("map,M", entries, "specify entry for map content");
add("content", content, "specify textual content");
- add("connection-options", connectionOptions, "connection options string in the form {name1:value1, name2:value2}");
+ add("connection-options", connectionOptions, "connection options string in the form {name1=value1, name2=value2}");
}
static bool nameval(const std::string& in, std::string& name, std::string& value)
diff --git a/cpp/examples/old-examples.sln b/cpp/examples/old-examples.sln
new file mode 100644
index 0000000000..7f2fa3e8b0
--- /dev/null
+++ b/cpp/examples/old-examples.sln
@@ -0,0 +1,147 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+#
+#
+# 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
+#
+#
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_declare_queues", "direct\direct_declare_queues.vcproj", "{18165D4D-FECA-1BAD-4346-8C4DF2536AA5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_direct_producer", "direct\direct_direct_producer.vcproj", "{9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_listener", "direct\direct_listener.vcproj", "{95CE1459-FECA-1BAD-4346-8C4DF2536AA5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_declare_queues", "failover\failover_declare_queues.vcproj", "{7817898E-FECA-1BAD-8026-8D997AD361D0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_replaying_sender", "failover\failover_replaying_sender.vcproj", "{085D6A66-FECA-1BAD-8026-8D997AD361D0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_resuming_receiver", "failover\failover_resuming_receiver.vcproj", "{B0DAF702-FECA-1BAD-8026-8D997AD361D0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fanout_fanout_producer", "fanout\fanout_fanout_producer.vcproj", "{972AB76B-FECA-1BAD-8826-8C64F27AA1C5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fanout_listener", "fanout\fanout_listener.vcproj", "{95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_listener", "pub-sub\pub-sub_topic_listener.vcproj", "{A415E66A-FECA-1BAD-A430-FD5330E23A2D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_publisher", "pub-sub\pub-sub_topic_publisher.vcproj", "{05158653-FECA-1BAD-A430-FD5330E23A2D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_console", "qmf-console\qmf-console_console.vcproj", "{490473E1-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_ping", "qmf-console\qmf-console_ping.vcproj", "{C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_printevents", "qmf-console\qmf-console_printevents.vcproj", "{72C74624-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qmf_console_queuestats", "qmf-console\qmf-console_queuestats.vcproj", "{B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_client", "request-response\request-response_client.vcproj", "{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_server", "request-response\request-response_server.vcproj", "{46817425-FECA-1BAD-BD3A-8A467D0C5CCC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_declare_queues", "tradedemo\tradedemo_declare_queues.vcproj", "{9057502D-FECA-1BAD-23CE-CD4095BD3C8B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_topic_listener", "tradedemo\tradedemo_topic_listener.vcproj", "{5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_topic_publisher", "tradedemo\tradedemo_topic_publisher.vcproj", "{E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
+ {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
+ {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
+ {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
+ {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
+ {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
+ {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
+ {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
+ {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
+ {7817898E-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7817898E-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
+ {7817898E-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
+ {7817898E-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
+ {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
+ {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
+ {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
+ {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
+ {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
+ {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
+ {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.Build.0 = Debug|Win32
+ {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.ActiveCfg = Release|Win32
+ {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.Build.0 = Release|Win32
+ {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.Build.0 = Debug|Win32
+ {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.ActiveCfg = Release|Win32
+ {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.Build.0 = Release|Win32
+ {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.Build.0 = Debug|Win32
+ {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.ActiveCfg = Release|Win32
+ {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.Build.0 = Release|Win32
+ {05158653-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {05158653-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.Build.0 = Debug|Win32
+ {05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.ActiveCfg = Release|Win32
+ {05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.Build.0 = Release|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {490473E1-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Debug|Win32.Build.0 = Debug|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.ActiveCfg = Release|Win32
+ {C1FFDE95-3442-49AE-9985-7EEE3D45B4A3}.Release|Win32.Build.0 = Release|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {72C74624-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Debug|Win32.Build.0 = Debug|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.ActiveCfg = Release|Win32
+ {B21825EA-FECA-1BAD-2E13-3FFA2B8669C3}.Release|Win32.Build.0 = Release|Win32
+ {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.Build.0 = Debug|Win32
+ {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.ActiveCfg = Release|Win32
+ {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.Build.0 = Release|Win32
+ {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.Build.0 = Debug|Win32
+ {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.ActiveCfg = Release|Win32
+ {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.Build.0 = Release|Win32
+ {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
+ {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
+ {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
+ {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
+ {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
+ {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
+ {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
+ {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
+ {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/cpp/examples/old_api/CMakeLists.txt b/cpp/examples/old_api/CMakeLists.txt
deleted file mode 100644
index 701f9be860..0000000000
--- a/cpp/examples/old_api/CMakeLists.txt
+++ /dev/null
@@ -1,25 +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.
-#
-add_subdirectory(direct)
-add_subdirectory(failover)
-add_subdirectory(fanout)
-add_subdirectory(pub-sub)
-add_subdirectory(request-response)
-add_subdirectory(tradedemo)
-add_subdirectory(xml-exchange)
diff --git a/cpp/examples/old_api/Makefile.am b/cpp/examples/old_api/Makefile.am
deleted file mode 100644
index 04216ffa97..0000000000
--- a/cpp/examples/old_api/Makefile.am
+++ /dev/null
@@ -1,48 +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.
-#
-SUBDIRS = direct pub-sub fanout request-response failover tradedemo
-if HAVE_XML
- SUBDIRS += xml-exchange
- broker_args = "--no-module-dir --data-dir \"\" --auth no --load-module $(top_builddir)/src/.libs/xml.so"
-endif
-if !HAVE_XML
- exclude_examples_regexp="xml" # Exclude XML examples.
- broker_args = "--no-module-dir --data-dir \"\" --auth no"
-endif
-
-MAKEDIST=.libs/Makefile
-
-$(MAKEDIST): Makefile
- mkdir -p .libs
- @(echo 'all clean:' ; \
- echo ' for d in $(SUBDIRS) ; do $$(MAKE) -C $$$$d $$@ ; done' ; \
- ) > $(MAKEDIST)
-
-examplesdir=$(pkgdatadir)/examples/old_api
-dist_examples_DATA = $(MAKEDIST)
-EXTRA_DIST = README.verify verify verify_all CMakeLists.txt
-
-# For older versions of automake
-abs_top_srcdir = @abs_top_srcdir@
-abs_top_builddir = @abs_top_builddir@
-
-# Verify the examples in the buid tree.
-check-local:
- $(srcdir)/verify_all $(abs_top_srcdir)/.. $(abs_top_builddir) $(broker_args) $(exclude_examples_regexp)
-
diff --git a/cpp/examples/old_api/direct/Makefile.am b/cpp/examples/old_api/direct/Makefile.am
deleted file mode 100644
index 24f783fcc7..0000000000
--- a/cpp/examples/old_api/direct/Makefile.am
+++ /dev/null
@@ -1,47 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/direct
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=direct_producer listener declare_queues
-direct_producer_SOURCES=direct_producer.cpp
-direct_producer_LDADD=$(CLIENT_LIB)
-
-listener_SOURCES=listener.cpp
-listener_LDADD=$(CLIENT_LIB)
-
-declare_queues_SOURCES=declare_queues.cpp
-declare_queues_LDADD=$(CLIENT_LIB)
-
-examples_DATA= \
- direct_producer.cpp \
- listener.cpp \
- declare_queues.cpp \
- $(MAKEDIST)
-
-EXTRA_DIST= \
- $(examples_DATA) \
- CMakeLists.txt \
- verify \
- verify.in \
- direct_declare_queues.vcproj \
- direct_direct_producer.vcproj \
- direct_listener.vcproj
diff --git a/cpp/examples/old_api/failover/Makefile.am b/cpp/examples/old_api/failover/Makefile.am
deleted file mode 100644
index 8b1da80f2c..0000000000
--- a/cpp/examples/old_api/failover/Makefile.am
+++ /dev/null
@@ -1,47 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/failover
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=declare_queues resuming_receiver replaying_sender
-
-declare_queues_SOURCES=declare_queues.cpp
-declare_queues_LDADD=$(CLIENT_LIB)
-
-resuming_receiver_SOURCES=resuming_receiver.cpp
-resuming_receiver_LDADD=$(CLIENT_LIB)
-
-replaying_sender_SOURCES=replaying_sender.cpp
-replaying_sender_LDADD=$(CLIENT_LIB)
-
-examples_DATA= \
- declare_queues.cpp \
- resuming_receiver.cpp \
- replaying_sender.cpp \
- $(MAKEDIST)
-
-# FIXME aconway 2008-10-10: add verify scripts.
-
-EXTRA_DIST= \
- CMakeLists.txt \
- failover_declare_queues.vcproj \
- failover_replaying_sender.vcproj \
- failover_resuming_receiver.vcproj
diff --git a/cpp/examples/old_api/fanout/Makefile.am b/cpp/examples/old_api/fanout/Makefile.am
deleted file mode 100644
index 3ab43b0279..0000000000
--- a/cpp/examples/old_api/fanout/Makefile.am
+++ /dev/null
@@ -1,42 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/fanout
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=fanout_producer listener
-fanout_producer_SOURCES=fanout_producer.cpp
-fanout_producer_LDADD=$(CLIENT_LIB)
-
-listener_SOURCES=listener.cpp
-listener_LDADD=$(CLIENT_LIB)
-
-examples_DATA= \
- fanout_producer.cpp \
- listener.cpp \
- $(MAKEDIST)
-
-EXTRA_DIST= \
- $(examples_DATA) \
- CMakeLists.txt \
- verify \
- verify.in \
- fanout_fanout_producer.vcproj \
- fanout_listener.vcproj
diff --git a/cpp/examples/old_api/old-examples.sln b/cpp/examples/old_api/old-examples.sln
deleted file mode 100644
index e6ec9a0d66..0000000000
--- a/cpp/examples/old_api/old-examples.sln
+++ /dev/null
@@ -1,123 +0,0 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-#
-#
-# 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
-#
-#
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_declare_queues", "direct\direct_declare_queues.vcproj", "{18165D4D-FECA-1BAD-4346-8C4DF2536AA5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_direct_producer", "direct\direct_direct_producer.vcproj", "{9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "direct_listener", "direct\direct_listener.vcproj", "{95CE1459-FECA-1BAD-4346-8C4DF2536AA5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_declare_queues", "failover\failover_declare_queues.vcproj", "{7817898E-FECA-1BAD-8026-8D997AD361D0}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_replaying_sender", "failover\failover_replaying_sender.vcproj", "{085D6A66-FECA-1BAD-8026-8D997AD361D0}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "failover_resuming_receiver", "failover\failover_resuming_receiver.vcproj", "{B0DAF702-FECA-1BAD-8026-8D997AD361D0}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fanout_fanout_producer", "fanout\fanout_fanout_producer.vcproj", "{972AB76B-FECA-1BAD-8826-8C64F27AA1C5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fanout_listener", "fanout\fanout_listener.vcproj", "{95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_listener", "pub-sub\pub-sub_topic_listener.vcproj", "{A415E66A-FECA-1BAD-A430-FD5330E23A2D}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pub_sub_topic_publisher", "pub-sub\pub-sub_topic_publisher.vcproj", "{05158653-FECA-1BAD-A430-FD5330E23A2D}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_client", "request-response\request-response_client.vcproj", "{2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "request_response_server", "request-response\request-response_server.vcproj", "{46817425-FECA-1BAD-BD3A-8A467D0C5CCC}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_declare_queues", "tradedemo\tradedemo_declare_queues.vcproj", "{9057502D-FECA-1BAD-23CE-CD4095BD3C8B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_topic_listener", "tradedemo\tradedemo_topic_listener.vcproj", "{5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tradedemo_topic_publisher", "tradedemo\tradedemo_topic_publisher.vcproj", "{E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
- {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
- {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
- {18165D4D-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
- {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
- {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
- {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
- {9701E0BD-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
- {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.ActiveCfg = Debug|Win32
- {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Debug|Win32.Build.0 = Debug|Win32
- {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.ActiveCfg = Release|Win32
- {95CE1459-FECA-1BAD-4346-8C4DF2536AA5}.Release|Win32.Build.0 = Release|Win32
- {7817898E-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
- {7817898E-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
- {7817898E-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
- {7817898E-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
- {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
- {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
- {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
- {085D6A66-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
- {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.ActiveCfg = Debug|Win32
- {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Debug|Win32.Build.0 = Debug|Win32
- {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.ActiveCfg = Release|Win32
- {B0DAF702-FECA-1BAD-8026-8D997AD361D0}.Release|Win32.Build.0 = Release|Win32
- {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.ActiveCfg = Debug|Win32
- {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.Build.0 = Debug|Win32
- {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.ActiveCfg = Release|Win32
- {972AB76B-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.Build.0 = Release|Win32
- {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.ActiveCfg = Debug|Win32
- {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Debug|Win32.Build.0 = Debug|Win32
- {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.ActiveCfg = Release|Win32
- {95E7DF39-FECA-1BAD-8826-8C64F27AA1C5}.Release|Win32.Build.0 = Release|Win32
- {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.ActiveCfg = Debug|Win32
- {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.Build.0 = Debug|Win32
- {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.ActiveCfg = Release|Win32
- {A415E66A-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.Build.0 = Release|Win32
- {05158653-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.ActiveCfg = Debug|Win32
- {05158653-FECA-1BAD-A430-FD5330E23A2D}.Debug|Win32.Build.0 = Debug|Win32
- {05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.ActiveCfg = Release|Win32
- {05158653-FECA-1BAD-A430-FD5330E23A2D}.Release|Win32.Build.0 = Release|Win32
- {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.ActiveCfg = Debug|Win32
- {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.Build.0 = Debug|Win32
- {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.ActiveCfg = Release|Win32
- {2691FE1E-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.Build.0 = Release|Win32
- {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.ActiveCfg = Debug|Win32
- {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Debug|Win32.Build.0 = Debug|Win32
- {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.ActiveCfg = Release|Win32
- {46817425-FECA-1BAD-BD3A-8A467D0C5CCC}.Release|Win32.Build.0 = Release|Win32
- {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
- {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
- {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
- {9057502D-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
- {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
- {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
- {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
- {5A25F2CD-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
- {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.ActiveCfg = Debug|Win32
- {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Debug|Win32.Build.0 = Debug|Win32
- {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.ActiveCfg = Release|Win32
- {E614CC2C-FECA-1BAD-23CE-CD4095BD3C8B}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/cpp/examples/old_api/pub-sub/Makefile.am b/cpp/examples/old_api/pub-sub/Makefile.am
deleted file mode 100644
index 8f42ee0211..0000000000
--- a/cpp/examples/old_api/pub-sub/Makefile.am
+++ /dev/null
@@ -1,43 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/pub-sub
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=topic_listener topic_publisher
-
-topic_listener_SOURCES=topic_listener.cpp
-topic_listener_LDADD=$(CLIENT_LIB)
-
-topic_publisher_SOURCES=topic_publisher.cpp
-topic_publisher_LDADD=$(CLIENT_LIB)
-
-examples_DATA= \
- topic_listener.cpp \
- topic_publisher.cpp \
- $(MAKEDIST)
-
-EXTRA_DIST= \
- $(examples_DATA) \
- CMakeLists.txt \
- verify \
- verify.in \
- pub-sub_topic_listener.vcproj \
- pub-sub_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/request-response/Makefile.am b/cpp/examples/old_api/request-response/Makefile.am
deleted file mode 100644
index f48762da51..0000000000
--- a/cpp/examples/old_api/request-response/Makefile.am
+++ /dev/null
@@ -1,43 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/request-response
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=client server
-
-client_SOURCES=client.cpp
-client_LDADD=$(CLIENT_LIB)
-
-server_SOURCES=server.cpp
-server_LDADD=$(CLIENT_LIB)
-
-examples_DATA= \
- server.cpp \
- client.cpp \
- $(MAKEDIST)
-
-EXTRA_DIST= \
- $(examples_DATA) \
- CMakeLists.txt \
- verify \
- verify.in \
- request-response_client.vcproj \
- request-response_server.vcproj
diff --git a/cpp/examples/old_api/tradedemo/Makefile.am b/cpp/examples/old_api/tradedemo/Makefile.am
deleted file mode 100644
index 445b15b367..0000000000
--- a/cpp/examples/old_api/tradedemo/Makefile.am
+++ /dev/null
@@ -1,46 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/tradedemo
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=topic_listener topic_publisher declare_queues
-
-topic_listener_SOURCES=topic_listener.cpp
-topic_listener_LDADD=$(CLIENT_LIB)
-
-topic_publisher_SOURCES=topic_publisher.cpp
-topic_publisher_LDADD=$(CLIENT_LIB)
-
-declare_queues_SOURCES=declare_queues.cpp
-declare_queues_LDADD=$(CLIENT_LIB)
-
-
-examples_DATA= \
- topic_listener.cpp \
- topic_publisher.cpp \
- declare_queues.cpp \
- $(MAKEDIST)
-
-EXTRA_DIST= \
- CMakeLists.txt \
- tradedemo_declare_queues.vcproj \
- tradedemo_topic_listener.vcproj \
- tradedemo_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/verify_all b/cpp/examples/old_api/verify_all
deleted file mode 100755
index fbe51377b6..0000000000
--- a/cpp/examples/old_api/verify_all
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Verify all examples
-
-verify=`dirname $0`/verify
-topsrcdir=$1
-topbuilddir=$2
-qpidd=$topbuilddir/src/qpidd
-broker_args=$3
-exclude_regexp=$4
-
-trap "$qpidd -q" exit
-QPID_PORT=`$qpidd -dp0 $broker_args` || { echo "Can't run qpidd" ; exit 1; }
-export QPID_PORT
-
-find="find $topsrcdir/cpp/examples/old_api"
-find="$find -mindepth 2 -name verify"
-all_examples=`$find`
-
-if test -z "$exclude_regexp"; then
- run_examples=$all_examples
-else
- for f in $all_examples; do
- { echo $f | grep $exclude_regexp > /dev/null ; } || run_examples="$run_examples $f"
- done
-fi
-$verify $topsrcdir $topbuilddir $run_examples
diff --git a/cpp/examples/old_api/xml-exchange/Makefile.am b/cpp/examples/old_api/xml-exchange/Makefile.am
deleted file mode 100644
index 3e1082cdb2..0000000000
--- a/cpp/examples/old_api/xml-exchange/Makefile.am
+++ /dev/null
@@ -1,49 +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.
-#
-examplesdir=$(pkgdatadir)/examples/old_api/xml-exchange
-
-MAKELDFLAGS=$(CLIENTFLAGS)
-include $(top_srcdir)/examples/makedist.mk
-
-noinst_PROGRAMS=declare_queues xml_producer listener
-
-declare_queues_SOURCES=declare_queues.cpp
-declare_queues_LDADD=$(CLIENT_LIB)
-
-xml_producer_SOURCES=xml_producer.cpp
-xml_producer_LDADD=$(CLIENT_LIB)
-
-listener_SOURCES=listener.cpp
-listener_LDADD=$(CLIENT_LIB)
-
-EXTRA_DIST= \
- README.txt \
- CMakeLists.txt
-
-examples_DATA= \
- $(EXTRA_DIST) \
- declare_queues.cpp \
- listener.cpp \
- xml_producer.cpp \
- $(MAKEDIST)
-
-
-
-
-
diff --git a/cpp/examples/old_api/pub-sub/CMakeLists.txt b/cpp/examples/pub-sub/CMakeLists.txt
index 961de06d5a..961de06d5a 100644
--- a/cpp/examples/old_api/pub-sub/CMakeLists.txt
+++ b/cpp/examples/pub-sub/CMakeLists.txt
diff --git a/cpp/examples/pub-sub/Makefile.am b/cpp/examples/pub-sub/Makefile.am
new file mode 100644
index 0000000000..62658ebe94
--- /dev/null
+++ b/cpp/examples/pub-sub/Makefile.am
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+examplesdir=$(pkgdatadir)/examples/pub-sub
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=topic_listener topic_publisher
+
+topic_listener_SOURCES=topic_listener.cpp
+topic_listener_LDADD=$(CLIENT_LIB)
+
+topic_publisher_SOURCES=topic_publisher.cpp
+topic_publisher_LDADD=$(CLIENT_LIB)
+
+examples_DATA= \
+ topic_listener.cpp \
+ topic_publisher.cpp \
+ $(MAKEDIST)
+
+EXTRA_DIST= \
+ $(examples_DATA) \
+ CMakeLists.txt \
+ verify \
+ verify.in \
+ pub-sub_topic_listener.vcproj \
+ pub-sub_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj b/cpp/examples/pub-sub/pub-sub_topic_listener.vcproj
index aa0b3bcaa3..aa0b3bcaa3 100644
--- a/cpp/examples/old_api/pub-sub/pub-sub_topic_listener.vcproj
+++ b/cpp/examples/pub-sub/pub-sub_topic_listener.vcproj
diff --git a/cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj b/cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj
index 76e51df4df..76e51df4df 100644
--- a/cpp/examples/old_api/pub-sub/pub-sub_topic_publisher.vcproj
+++ b/cpp/examples/pub-sub/pub-sub_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/pub-sub/topic_listener.cpp b/cpp/examples/pub-sub/topic_listener.cpp
index d38a806303..d38a806303 100644
--- a/cpp/examples/old_api/pub-sub/topic_listener.cpp
+++ b/cpp/examples/pub-sub/topic_listener.cpp
diff --git a/cpp/examples/old_api/pub-sub/topic_publisher.cpp b/cpp/examples/pub-sub/topic_publisher.cpp
index aed5f8f033..aed5f8f033 100644
--- a/cpp/examples/old_api/pub-sub/topic_publisher.cpp
+++ b/cpp/examples/pub-sub/topic_publisher.cpp
diff --git a/cpp/examples/old_api/pub-sub/verify b/cpp/examples/pub-sub/verify
index 528d2f401e..528d2f401e 100644
--- a/cpp/examples/old_api/pub-sub/verify
+++ b/cpp/examples/pub-sub/verify
diff --git a/cpp/examples/old_api/pub-sub/verify.in b/cpp/examples/pub-sub/verify.in
index 6413c5c788..6413c5c788 100644
--- a/cpp/examples/old_api/pub-sub/verify.in
+++ b/cpp/examples/pub-sub/verify.in
diff --git a/cpp/examples/qmf-console/ping.cpp b/cpp/examples/qmf-console/ping.cpp
index e6d6d138d5..fe537d48d2 100644
--- a/cpp/examples/qmf-console/ping.cpp
+++ b/cpp/examples/qmf-console/ping.cpp
@@ -31,7 +31,9 @@ using namespace qpid::console;
int main_int(int /*argc*/, char** /*argv*/)
{
//
- // Declare connection settings for the messaging broker.
+ // Declare connection settings for the messaging broker. The settings default to
+ // localhost:5672 with user guest (password guest). Refer to the header file
+ // <qpid/client/ConnectionSettings.h> for full details.
//
qpid::client::ConnectionSettings connSettings;
diff --git a/cpp/examples/qmf-console/printevents.cpp b/cpp/examples/qmf-console/printevents.cpp
index ac3e449a2c..3a0a2ab68b 100644
--- a/cpp/examples/qmf-console/printevents.cpp
+++ b/cpp/examples/qmf-console/printevents.cpp
@@ -64,7 +64,9 @@ struct Main {
Listener listener;
//
- // Declare connection settings for the messaging broker.
+ // Declare connection settings for the messaging broker. The settings default to
+ // localhost:5672 with user guest (password guest). Refer to the header file
+ // <qpid/client/ConnectionSettings.h> for full details.
//
qpid::client::ConnectionSettings connSettings;
diff --git a/cpp/examples/old_api/request-response/CMakeLists.txt b/cpp/examples/request-response/CMakeLists.txt
index 873a0cfa86..873a0cfa86 100644
--- a/cpp/examples/old_api/request-response/CMakeLists.txt
+++ b/cpp/examples/request-response/CMakeLists.txt
diff --git a/cpp/examples/request-response/Makefile.am b/cpp/examples/request-response/Makefile.am
new file mode 100644
index 0000000000..48b3d989f0
--- /dev/null
+++ b/cpp/examples/request-response/Makefile.am
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+examplesdir=$(pkgdatadir)/examples/request-response
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=client server
+
+client_SOURCES=client.cpp
+client_LDADD=$(CLIENT_LIB)
+
+server_SOURCES=server.cpp
+server_LDADD=$(CLIENT_LIB)
+
+examples_DATA= \
+ server.cpp \
+ client.cpp \
+ $(MAKEDIST)
+
+EXTRA_DIST= \
+ $(examples_DATA) \
+ CMakeLists.txt \
+ verify \
+ verify.in \
+ request-response_client.vcproj \
+ request-response_server.vcproj
diff --git a/cpp/examples/old_api/request-response/client.cpp b/cpp/examples/request-response/client.cpp
index 679d1c5fc2..679d1c5fc2 100644
--- a/cpp/examples/old_api/request-response/client.cpp
+++ b/cpp/examples/request-response/client.cpp
diff --git a/cpp/examples/old_api/request-response/request-response_client.vcproj b/cpp/examples/request-response/request-response_client.vcproj
index 5f9eadde36..5f9eadde36 100644
--- a/cpp/examples/old_api/request-response/request-response_client.vcproj
+++ b/cpp/examples/request-response/request-response_client.vcproj
diff --git a/cpp/examples/old_api/request-response/request-response_server.vcproj b/cpp/examples/request-response/request-response_server.vcproj
index 54352b9f46..54352b9f46 100644
--- a/cpp/examples/old_api/request-response/request-response_server.vcproj
+++ b/cpp/examples/request-response/request-response_server.vcproj
diff --git a/cpp/examples/old_api/request-response/server.cpp b/cpp/examples/request-response/server.cpp
index 65a4717b35..65a4717b35 100644
--- a/cpp/examples/old_api/request-response/server.cpp
+++ b/cpp/examples/request-response/server.cpp
diff --git a/cpp/examples/old_api/request-response/verify b/cpp/examples/request-response/verify
index dee82413e7..dee82413e7 100644
--- a/cpp/examples/old_api/request-response/verify
+++ b/cpp/examples/request-response/verify
diff --git a/cpp/examples/old_api/request-response/verify.in b/cpp/examples/request-response/verify.in
index 7925dc5671..7925dc5671 100644
--- a/cpp/examples/old_api/request-response/verify.in
+++ b/cpp/examples/request-response/verify.in
diff --git a/cpp/examples/old_api/tradedemo/CMakeLists.txt b/cpp/examples/tradedemo/CMakeLists.txt
index e61fc1467d..e61fc1467d 100644
--- a/cpp/examples/old_api/tradedemo/CMakeLists.txt
+++ b/cpp/examples/tradedemo/CMakeLists.txt
diff --git a/cpp/examples/tradedemo/Makefile.am b/cpp/examples/tradedemo/Makefile.am
new file mode 100644
index 0000000000..f4d8686d05
--- /dev/null
+++ b/cpp/examples/tradedemo/Makefile.am
@@ -0,0 +1,46 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+examplesdir=$(pkgdatadir)/examples/tradedemo
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=topic_listener topic_publisher declare_queues
+
+topic_listener_SOURCES=topic_listener.cpp
+topic_listener_LDADD=$(CLIENT_LIB)
+
+topic_publisher_SOURCES=topic_publisher.cpp
+topic_publisher_LDADD=$(CLIENT_LIB)
+
+declare_queues_SOURCES=declare_queues.cpp
+declare_queues_LDADD=$(CLIENT_LIB)
+
+
+examples_DATA= \
+ topic_listener.cpp \
+ topic_publisher.cpp \
+ declare_queues.cpp \
+ $(MAKEDIST)
+
+EXTRA_DIST= \
+ CMakeLists.txt \
+ tradedemo_declare_queues.vcproj \
+ tradedemo_topic_listener.vcproj \
+ tradedemo_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/tradedemo/declare_queues.cpp b/cpp/examples/tradedemo/declare_queues.cpp
index b1f2cc3510..b1f2cc3510 100644
--- a/cpp/examples/old_api/tradedemo/declare_queues.cpp
+++ b/cpp/examples/tradedemo/declare_queues.cpp
diff --git a/cpp/examples/old_api/tradedemo/topic_listener.cpp b/cpp/examples/tradedemo/topic_listener.cpp
index c488e7fb69..c488e7fb69 100644
--- a/cpp/examples/old_api/tradedemo/topic_listener.cpp
+++ b/cpp/examples/tradedemo/topic_listener.cpp
diff --git a/cpp/examples/old_api/tradedemo/topic_publisher.cpp b/cpp/examples/tradedemo/topic_publisher.cpp
index e22c185bc7..e22c185bc7 100644
--- a/cpp/examples/old_api/tradedemo/topic_publisher.cpp
+++ b/cpp/examples/tradedemo/topic_publisher.cpp
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj b/cpp/examples/tradedemo/tradedemo_declare_queues.vcproj
index 34b5cb3b2b..34b5cb3b2b 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_declare_queues.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_declare_queues.vcproj
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj b/cpp/examples/tradedemo/tradedemo_topic_listener.vcproj
index 965be2e88b..965be2e88b 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_topic_listener.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_topic_listener.vcproj
diff --git a/cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj b/cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj
index 77fd511e15..77fd511e15 100644
--- a/cpp/examples/old_api/tradedemo/tradedemo_topic_publisher.vcproj
+++ b/cpp/examples/tradedemo/tradedemo_topic_publisher.vcproj
diff --git a/cpp/examples/old_api/verify b/cpp/examples/verify
index 9a1ed078d6..9a1ed078d6 100755
--- a/cpp/examples/old_api/verify
+++ b/cpp/examples/verify
diff --git a/cpp/examples/verify_all b/cpp/examples/verify_all
new file mode 100755
index 0000000000..cb4c5283fa
--- /dev/null
+++ b/cpp/examples/verify_all
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Verify all examples
+
+verify=`dirname $0`/verify
+topsrcdir=$1
+topbuilddir=$2
+qpidd=$topbuilddir/src/qpidd
+broker_args=$3
+exclude_regexp=$4
+
+trap "$qpidd -q" exit
+QPID_PORT=`$qpidd -dp0 $broker_args` || { echo "Can't run qpidd" ; exit 1; }
+export QPID_PORT
+
+find="find $topsrcdir/cpp/examples"
+find="$find -mindepth 2 -name verify"
+all_examples=`$find`
+
+if test -z "$exclude_regexp"; then
+ run_examples=$all_examples
+else
+ for f in $all_examples; do
+ { echo $f | grep $exclude_regexp > /dev/null ; } || run_examples="$run_examples $f"
+ done
+fi
+$verify $topsrcdir $topbuilddir $run_examples
diff --git a/cpp/examples/old_api/xml-exchange/CMakeLists.txt b/cpp/examples/xml-exchange/CMakeLists.txt
index 3fea47a208..3fea47a208 100644
--- a/cpp/examples/old_api/xml-exchange/CMakeLists.txt
+++ b/cpp/examples/xml-exchange/CMakeLists.txt
diff --git a/cpp/examples/xml-exchange/Makefile.am b/cpp/examples/xml-exchange/Makefile.am
new file mode 100644
index 0000000000..9001e3fa61
--- /dev/null
+++ b/cpp/examples/xml-exchange/Makefile.am
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+examplesdir=$(pkgdatadir)/examples/xml-exchange
+
+MAKELDFLAGS=$(CLIENTFLAGS)
+include $(top_srcdir)/examples/makedist.mk
+
+noinst_PROGRAMS=declare_queues xml_producer listener
+
+declare_queues_SOURCES=declare_queues.cpp
+declare_queues_LDADD=$(CLIENT_LIB)
+
+xml_producer_SOURCES=xml_producer.cpp
+xml_producer_LDADD=$(CLIENT_LIB)
+
+listener_SOURCES=listener.cpp
+listener_LDADD=$(CLIENT_LIB)
+
+EXTRA_DIST= \
+ README.txt \
+ CMakeLists.txt
+
+examples_DATA= \
+ $(EXTRA_DIST) \
+ declare_queues.cpp \
+ listener.cpp \
+ xml_producer.cpp \
+ $(MAKEDIST)
+
+
+
+
+
diff --git a/cpp/examples/old_api/xml-exchange/README.txt b/cpp/examples/xml-exchange/README.txt
index 85caebe352..85caebe352 100644
--- a/cpp/examples/old_api/xml-exchange/README.txt
+++ b/cpp/examples/xml-exchange/README.txt
diff --git a/cpp/examples/old_api/xml-exchange/declare_queues.cpp b/cpp/examples/xml-exchange/declare_queues.cpp
index ad08642019..ad08642019 100644
--- a/cpp/examples/old_api/xml-exchange/declare_queues.cpp
+++ b/cpp/examples/xml-exchange/declare_queues.cpp
diff --git a/cpp/examples/old_api/xml-exchange/listener.cpp b/cpp/examples/xml-exchange/listener.cpp
index 11bcb9f669..11bcb9f669 100644
--- a/cpp/examples/old_api/xml-exchange/listener.cpp
+++ b/cpp/examples/xml-exchange/listener.cpp
diff --git a/cpp/examples/old_api/xml-exchange/xml_producer.cpp b/cpp/examples/xml-exchange/xml_producer.cpp
index af1a7e60c7..af1a7e60c7 100644
--- a/cpp/examples/old_api/xml-exchange/xml_producer.cpp
+++ b/cpp/examples/xml-exchange/xml_producer.cpp
diff --git a/cpp/include/qmf/Agent.h b/cpp/include/qmf/Agent.h
index 94083be4f3..8c0f48b8b1 100644
--- a/cpp/include/qmf/Agent.h
+++ b/cpp/include/qmf/Agent.h
@@ -42,7 +42,7 @@ namespace qmf {
class SchemaId;
class Schema;
- class QMF_CLASS_EXTERN Agent : public qmf::Handle<AgentImpl> {
+ class Agent : public qmf::Handle<AgentImpl> {
public:
QMF_EXTERN Agent(AgentImpl* impl = 0);
QMF_EXTERN Agent(const Agent&);
diff --git a/cpp/include/qmf/AgentEvent.h b/cpp/include/qmf/AgentEvent.h
index 0f93a9bb0a..59a41c3267 100644
--- a/cpp/include/qmf/AgentEvent.h
+++ b/cpp/include/qmf/AgentEvent.h
@@ -46,7 +46,7 @@ namespace qmf {
AGENT_THREAD_FAILED = 8
};
- class QMF_CLASS_EXTERN AgentEvent : public qmf::Handle<AgentEventImpl> {
+ class AgentEvent : public qmf::Handle<AgentEventImpl> {
public:
QMF_EXTERN AgentEvent(AgentEventImpl* impl = 0);
QMF_EXTERN AgentEvent(const AgentEvent&);
diff --git a/cpp/include/qmf/AgentSession.h b/cpp/include/qmf/AgentSession.h
index 589d364bcc..9e29d6b54b 100644
--- a/cpp/include/qmf/AgentSession.h
+++ b/cpp/include/qmf/AgentSession.h
@@ -40,7 +40,7 @@ namespace qmf {
class Data;
class DataAddr;
- class QMF_CLASS_EXTERN AgentSession : public qmf::Handle<AgentSessionImpl> {
+ class AgentSession : public qmf::Handle<AgentSessionImpl> {
public:
QMF_EXTERN AgentSession(AgentSessionImpl* impl = 0);
QMF_EXTERN AgentSession(const AgentSession&);
@@ -71,20 +71,15 @@ namespace qmf {
* If False: Listen only on the routable direct address
* strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network
* - If False: Operate more flexibly with regard to use of messaging facilities [default]
- * max-thread-wait-time:N - Time (in seconds) the session thread will wait for messages from the network between
- * periodic background processing passes. [default: 5]
- * Must not be greater than 'interval'. Larger numbers will cause fewer wake-ups but will
- * increase the time it takes to shut down the process. This setting will not affect the
- * agent's response time for queries or method invocation.
*/
- QMF_EXTERN AgentSession(qpid::messaging::Connection& conn, const std::string& options="");
+ QMF_EXTERN AgentSession(qpid::messaging::Connection&, const std::string& options="");
/**
* setDomain - Change the QMF domain that this agent will operate in. If this is not called,
* the domain will be "default". Agents in a domain can be seen only by consoles in the same domain.
* This must be called prior to opening the agent session.
*/
- QMF_EXTERN void setDomain(const std::string& domain);
+ QMF_EXTERN void setDomain(const std::string&);
/**
* Set identifying attributes of this agent.
@@ -93,16 +88,16 @@ namespace qmf {
* setInstance - Set the unique instance name (if not set, a UUID will be assigned)
* These must be called prior to opening the agent session.
*/
- QMF_EXTERN void setVendor(const std::string& vendor);
- QMF_EXTERN void setProduct(const std::string& product);
- QMF_EXTERN void setInstance(const std::string& instance);
+ QMF_EXTERN void setVendor(const std::string&);
+ QMF_EXTERN void setProduct(const std::string&);
+ QMF_EXTERN void setInstance(const std::string&);
/**
* setAttribute - Set an arbitrary attribute for this agent. The attributes are not used
* to uniquely identify the agent but can be used as a search criteria when looking for agents.
* This must be called prior to opening the agent session.
*/
- QMF_EXTERN void setAttribute(const std::string& key, const qpid::types::Variant& value);
+ QMF_EXTERN void setAttribute(const std::string&, const qpid::types::Variant&);
/**
* Get the identifying name of the agent.
@@ -124,19 +119,13 @@ namespace qmf {
* Get the next event from the agent session. Events represent actions that must be acted upon by the
* agent application. This method blocks for up to the timeout if there are no events to be handled.
* This method will typically be the focus of the agent application's main execution loop.
- * If the timeout is set to Duration::IMMEDIATE, the call will not block.
*/
- QMF_EXTERN bool nextEvent(AgentEvent& outEvent, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
-
- /**
- * Return the number of events pending for nextEvent. This method will never block.
- */
- QMF_EXTERN int pendingEvents() const;
+ QMF_EXTERN bool nextEvent(AgentEvent&, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
/**
* Register a schema to be exposed by this agent.
*/
- QMF_EXTERN void registerSchema(Schema& schema);
+ QMF_EXTERN void registerSchema(Schema&);
/**
* Add data to be managed internally by the agent. If the option external:True is selected, this call
@@ -149,12 +138,12 @@ namespace qmf {
* across different sessions. If persistent, it is the agent application's
* responsibility to ensure the name is the same each time it is added.
*/
- QMF_EXTERN DataAddr addData(Data& data, const std::string& name="", bool persistent=false);
+ QMF_EXTERN DataAddr addData(Data&, const std::string& name="", bool persistent=false);
/**
* Delete data from internal agent management.
*/
- QMF_EXTERN void delData(const DataAddr& dataAddr);
+ QMF_EXTERN void delData(const DataAddr&);
/**
* The following methods are used to respond to events received in nextEvent.
@@ -166,13 +155,13 @@ namespace qmf {
* complete - Indicate that the response to a query is complete (external:True only)
* methodSuccess - Indicate the successful completion of a method call.
*/
- QMF_EXTERN void authAccept(AgentEvent& event);
- QMF_EXTERN void authReject(AgentEvent& event, const std::string& diag="");
- QMF_EXTERN void raiseException(AgentEvent& event, const std::string& errorText);
- QMF_EXTERN void raiseException(AgentEvent& event, const Data& errorData);
- QMF_EXTERN void response(AgentEvent& event, const Data& responseData);
- QMF_EXTERN void complete(AgentEvent& event);
- QMF_EXTERN void methodSuccess(AgentEvent& event);
+ QMF_EXTERN void authAccept(AgentEvent&);
+ QMF_EXTERN void authReject(AgentEvent&, const std::string& diag="");
+ QMF_EXTERN void raiseException(AgentEvent&, const std::string&);
+ QMF_EXTERN void raiseException(AgentEvent&, const Data&);
+ QMF_EXTERN void response(AgentEvent&, const Data&);
+ QMF_EXTERN void complete(AgentEvent&);
+ QMF_EXTERN void methodSuccess(AgentEvent&);
/**
* Raise an event to be sent into the QMF network.
@@ -188,7 +177,6 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<AgentSession>;
- friend struct AgentSessionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/ConsoleEvent.h b/cpp/include/qmf/ConsoleEvent.h
index 94600f9357..b836b629af 100644
--- a/cpp/include/qmf/ConsoleEvent.h
+++ b/cpp/include/qmf/ConsoleEvent.h
@@ -57,7 +57,7 @@ namespace qmf {
AGENT_DEL_FILTER = 2
};
- class QMF_CLASS_EXTERN ConsoleEvent : public qmf::Handle<ConsoleEventImpl> {
+ class ConsoleEvent : public qmf::Handle<ConsoleEventImpl> {
public:
QMF_EXTERN ConsoleEvent(ConsoleEventImpl* impl = 0);
QMF_EXTERN ConsoleEvent(const ConsoleEvent&);
diff --git a/cpp/include/qmf/ConsoleSession.h b/cpp/include/qmf/ConsoleSession.h
index 022485cfa7..0c73e7a6db 100644
--- a/cpp/include/qmf/ConsoleSession.h
+++ b/cpp/include/qmf/ConsoleSession.h
@@ -38,7 +38,7 @@ namespace qmf {
class ConsoleSessionImpl;
class ConsoleEvent;
- class QMF_CLASS_EXTERN ConsoleSession : public qmf::Handle<ConsoleSessionImpl> {
+ class ConsoleSession : public qmf::Handle<ConsoleSessionImpl> {
public:
QMF_EXTERN ConsoleSession(ConsoleSessionImpl* impl = 0);
QMF_EXTERN ConsoleSession(const ConsoleSession&);
@@ -61,53 +61,15 @@ namespace qmf {
* If False: Listen only on the routable direct address
* strict-security:{True,False} - If True: Cooperate with the broker to enforce strict access control to the network
* - If False: Operate more flexibly with regard to use of messaging facilities [default]
- * max-thread-wait-time:N - Time (in seconds) the session thread will wait for messages from the network between
- * periodic background processing passes.
- * Must not be greater than 60. Larger numbers will cause fewer wake-ups but will
- * increase the time it takes to shut down the process. [default: 5]
- */
- QMF_EXTERN ConsoleSession(qpid::messaging::Connection& conn, const std::string& options="");
-
- /**
- * setDomain - Change the QMF domain that this console will operate in. If this is not called,
- * the domain will be "default". Agents in a domain can be seen only by consoles in the same domain.
- * This must be called prior to opening the console session.
- */
- QMF_EXTERN void setDomain(const std::string& domain);
- QMF_EXTERN void setAgentFilter(const std::string& filter);
-
- /**
- * Open the console session. After opening the session, the domain cannot be changed.
*/
+ QMF_EXTERN ConsoleSession(qpid::messaging::Connection&, const std::string& options="");
+ QMF_EXTERN void setDomain(const std::string&);
+ QMF_EXTERN void setAgentFilter(const std::string&);
QMF_EXTERN void open();
-
- /**
- * Close the session. Once closed, the session no longer communicates on the messaging network.
- */
QMF_EXTERN void close();
-
- /**
- * Get the next event from the console session. Events represent actions that must be acted upon by the
- * console application. This method blocks for up to the timeout if there are no events to be handled.
- * This method will typically be the focus of the console application's main execution loop.
- * If the timeout is set to Duration::IMMEDIATE, the call will not block.
- */
- QMF_EXTERN bool nextEvent(ConsoleEvent& outEvent, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
-
- /**
- * Return the number of events pending for nextEvent. This method will never block.
- */
- QMF_EXTERN int pendingEvents() const;
-
- /**
- * getAgentCount, getAgent - Retrieve the set of agents that match the console session's agent filter.
- */
+ QMF_EXTERN bool nextEvent(ConsoleEvent&, qpid::messaging::Duration timeout=qpid::messaging::Duration::FOREVER);
QMF_EXTERN uint32_t getAgentCount() const;
- QMF_EXTERN Agent getAgent(uint32_t agentIndex) const;
-
- /**
- * Get the agent for the connected broker (i.e. the agent embedded in the broker to which we have a connection).
- */
+ QMF_EXTERN Agent getAgent(uint32_t) const;
QMF_EXTERN Agent getConnectedBrokerAgent() const;
/**
@@ -117,13 +79,12 @@ namespace qmf {
* will involve all known agents. If agentFilter is non-empty, it will be applied only to the set of known
* agents. A subscription cannot be created that involves an agent not known by the session.
*/
- QMF_EXTERN Subscription subscribe(const Query& query, const std::string& agentFilter = "", const std::string& options = "");
- QMF_EXTERN Subscription subscribe(const std::string& query, const std::string& agentFilter = "", const std::string& options = "");
+ QMF_EXTERN Subscription subscribe(const Query&, const std::string& agentFilter = "", const std::string& options = "");
+ QMF_EXTERN Subscription subscribe(const std::string&, const std::string& agentFilter = "", const std::string& options = "");
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<ConsoleSession>;
- friend struct ConsoleSessionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/Data.h b/cpp/include/qmf/Data.h
index 487a02fe95..82f1569a0b 100644
--- a/cpp/include/qmf/Data.h
+++ b/cpp/include/qmf/Data.h
@@ -39,7 +39,7 @@ namespace qmf {
class DataAddr;
class Agent;
- class QMF_CLASS_EXTERN Data : public qmf::Handle<DataImpl> {
+ class Data : public qmf::Handle<DataImpl> {
public:
QMF_EXTERN Data(DataImpl* impl = 0);
QMF_EXTERN Data(const Data&);
diff --git a/cpp/include/qmf/DataAddr.h b/cpp/include/qmf/DataAddr.h
index 20c469081e..72de0c986a 100644
--- a/cpp/include/qmf/DataAddr.h
+++ b/cpp/include/qmf/DataAddr.h
@@ -34,7 +34,7 @@ namespace qmf {
class DataAddrImpl;
- class QMF_CLASS_EXTERN DataAddr : public qmf::Handle<DataAddrImpl> {
+ class DataAddr : public qmf::Handle<DataAddrImpl> {
public:
QMF_EXTERN DataAddr(DataAddrImpl* impl = 0);
QMF_EXTERN DataAddr(const DataAddr&);
@@ -51,9 +51,6 @@ namespace qmf {
QMF_EXTERN uint32_t getAgentEpoch() const;
QMF_EXTERN qpid::types::Variant::Map asMap() const;
- QMF_EXTERN bool operator==(const DataAddr&) const;
- QMF_EXTERN bool operator<(const DataAddr&) const;
-
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<DataAddr>;
diff --git a/cpp/include/qmf/Handle.h b/cpp/include/qmf/Handle.h
index 50971ea626..510e2993aa 100644
--- a/cpp/include/qmf/Handle.h
+++ b/cpp/include/qmf/Handle.h
@@ -39,22 +39,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QMF_INLINE_EXTERN bool isValid() const { return impl; }
+ QMF_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QMF_INLINE_EXTERN bool isNull() const { return !impl; }
+ QMF_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QMF_INLINE_EXTERN operator bool() const { return impl; }
+ QMF_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QMF_INLINE_EXTERN bool operator !() const { return !impl; }
+ QMF_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QMF_INLINE_EXTERN Handle() :impl() {}
+ QMF_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QMF_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qmf/ImportExport.h b/cpp/include/qmf/ImportExport.h
index 7405c15259..f5e1d9127c 100644
--- a/cpp/include/qmf/ImportExport.h
+++ b/cpp/include/qmf/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
-#if defined(QMF_EXPORT) || defined (qmf2_EXPORTS)
-# define QMF_EXTERN QPID_EXPORT
-# define QMF_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QMF_INLINE_EXTERN QPID_INLINE_EXPORT
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+# if defined(QMF_EXPORT) || defined (qmfcommon_EXPORTS)
+# define QMF_EXTERN __declspec(dllexport)
+# else
+# define QMF_EXTERN __declspec(dllimport)
+# endif
#else
-# define QMF_EXTERN QPID_IMPORT
-# define QMF_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QMF_INLINE_EXTERN QPID_INLINE_IMPORT
+# define QMF_EXTERN
#endif
#endif
diff --git a/cpp/include/qmf/Query.h b/cpp/include/qmf/Query.h
index c1264f8901..fec4660bd7 100644
--- a/cpp/include/qmf/Query.h
+++ b/cpp/include/qmf/Query.h
@@ -43,7 +43,7 @@ namespace qmf {
QUERY_SCHEMA_ID = 4
};
- class QMF_CLASS_EXTERN Query : public qmf::Handle<QueryImpl> {
+ class Query : public qmf::Handle<QueryImpl> {
public:
QMF_EXTERN Query(QueryImpl* impl = 0);
QMF_EXTERN Query(const Query&);
@@ -65,7 +65,7 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<Query>;
- friend struct QueryImplAccess;
+ friend class QueryImplAccess;
#endif
};
diff --git a/cpp/include/qmf/Schema.h b/cpp/include/qmf/Schema.h
index 6cfd2e2a56..cf316138c1 100644
--- a/cpp/include/qmf/Schema.h
+++ b/cpp/include/qmf/Schema.h
@@ -38,7 +38,7 @@ namespace qmf {
class SchemaProperty;
class SchemaMethod;
- class QMF_CLASS_EXTERN Schema : public qmf::Handle<SchemaImpl> {
+ class Schema : public qmf::Handle<SchemaImpl> {
public:
QMF_EXTERN Schema(SchemaImpl* impl = 0);
QMF_EXTERN Schema(const Schema&);
diff --git a/cpp/include/qmf/SchemaId.h b/cpp/include/qmf/SchemaId.h
index 2dafc1c091..13fb1cb902 100644
--- a/cpp/include/qmf/SchemaId.h
+++ b/cpp/include/qmf/SchemaId.h
@@ -35,7 +35,7 @@ namespace qmf {
class SchemaIdImpl;
- class QMF_CLASS_EXTERN SchemaId : public qmf::Handle<SchemaIdImpl> {
+ class SchemaId : public qmf::Handle<SchemaIdImpl> {
public:
QMF_EXTERN SchemaId(SchemaIdImpl* impl = 0);
QMF_EXTERN SchemaId(const SchemaId&);
diff --git a/cpp/include/qmf/SchemaMethod.h b/cpp/include/qmf/SchemaMethod.h
index b5944dc29e..47302b62b9 100644
--- a/cpp/include/qmf/SchemaMethod.h
+++ b/cpp/include/qmf/SchemaMethod.h
@@ -36,7 +36,7 @@ namespace qmf {
class SchemaMethodImpl;
class SchemaProperty;
- class QMF_CLASS_EXTERN SchemaMethod : public qmf::Handle<SchemaMethodImpl> {
+ class SchemaMethod : public qmf::Handle<SchemaMethodImpl> {
public:
QMF_EXTERN SchemaMethod(SchemaMethodImpl* impl = 0);
QMF_EXTERN SchemaMethod(const SchemaMethod&);
diff --git a/cpp/include/qmf/SchemaProperty.h b/cpp/include/qmf/SchemaProperty.h
index bbb603fa50..a3a328b60b 100644
--- a/cpp/include/qmf/SchemaProperty.h
+++ b/cpp/include/qmf/SchemaProperty.h
@@ -36,7 +36,7 @@ namespace qmf {
class SchemaPropertyImpl;
- class QMF_CLASS_EXTERN SchemaProperty : public Handle<SchemaPropertyImpl> {
+ class SchemaProperty : public Handle<SchemaPropertyImpl> {
public:
QMF_EXTERN SchemaProperty(SchemaPropertyImpl* impl = 0);
QMF_EXTERN SchemaProperty(const SchemaProperty&);
diff --git a/cpp/include/qmf/Subscription.h b/cpp/include/qmf/Subscription.h
index 398a45b922..4e60eb984e 100644
--- a/cpp/include/qmf/Subscription.h
+++ b/cpp/include/qmf/Subscription.h
@@ -35,7 +35,7 @@ namespace qmf {
class SubscriptionImpl;
class Data;
- class QMF_CLASS_EXTERN Subscription : public qmf::Handle<SubscriptionImpl> {
+ class Subscription : public qmf::Handle<SubscriptionImpl> {
public:
QMF_EXTERN Subscription(SubscriptionImpl* impl = 0);
QMF_EXTERN Subscription(const Subscription&);
@@ -73,7 +73,7 @@ namespace qmf {
#ifndef SWIG
private:
friend class qmf::PrivateImplRef<Subscription>;
- friend struct SubscriptionImplAccess;
+ friend class SubscriptionImplAccess;
#endif
};
diff --git a/cpp/include/qmf/engine/QmfEngineImportExport.h b/cpp/include/qmf/engine/QmfEngineImportExport.h
index cf8fffdb17..373617e046 100644
--- a/cpp/include/qmf/engine/QmfEngineImportExport.h
+++ b/cpp/include/qmf/engine/QmfEngineImportExport.h
@@ -26,17 +26,8 @@
# else
# define QMFE_EXTERN __declspec(dllimport)
# endif
-# ifdef _MSC_VER
-# define QMFE_CLASS_EXTERN
-# define QMFE_INLINE_EXTERN QMFE_EXTERN
-# else
-# define QMFE_CLASS_EXTERN QMFE_EXTERN
-# define QMFE_INLINE_EXTERN
-# endif
#else
# define QMFE_EXTERN
-# define QMFE_CLASS_EXTERN
-# define QMFE_INLINE_EXTERN
#endif
#endif
diff --git a/cpp/include/qmf/exceptions.h b/cpp/include/qmf/exceptions.h
index c7ffa68ce2..7959499d63 100644
--- a/cpp/include/qmf/exceptions.h
+++ b/cpp/include/qmf/exceptions.h
@@ -31,24 +31,24 @@ namespace qmf {
/** \ingroup qmf
*/
- struct QMF_CLASS_EXTERN QmfException : public qpid::types::Exception {
+ struct QmfException : public qpid::types::Exception {
QMF_EXTERN QmfException(const std::string& msg);
QMF_EXTERN virtual ~QmfException() throw();
qpid::types::Variant::Map detail;
};
- struct QMF_CLASS_EXTERN KeyNotFound : public QmfException {
+ struct KeyNotFound : public QmfException {
QMF_EXTERN KeyNotFound(const std::string& msg);
QMF_EXTERN virtual ~KeyNotFound() throw();
};
- struct QMF_CLASS_EXTERN IndexOutOfRange : public QmfException {
+ struct IndexOutOfRange : public QmfException {
QMF_EXTERN IndexOutOfRange();
QMF_EXTERN virtual ~IndexOutOfRange() throw();
};
- struct QMF_CLASS_EXTERN OperationTimedOut : public QmfException {
+ struct OperationTimedOut : public QmfException {
QMF_EXTERN OperationTimedOut();
QMF_EXTERN virtual ~OperationTimedOut() throw();
};
diff --git a/cpp/include/qmf/posix/EventNotifier.h b/cpp/include/qmf/posix/EventNotifier.h
deleted file mode 100644
index ebc1cb5364..0000000000
--- a/cpp/include/qmf/posix/EventNotifier.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __QMF_POSIX_EVENT_NOTIFIER_H
-#define __QMF_POSIX_EVENT_NOTIFIER_H
-
-/*
- * 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/ImportExport.h>
-#include "qmf/Handle.h"
-#include "qmf/AgentSession.h"
-#include "qmf/ConsoleSession.h"
-
-namespace qmf {
-
- class PosixEventNotifierImpl;
- class PosixEventNotifierImplAccess;
-
-namespace posix {
-
-#ifndef SWIG
- template <class> class PrivateImplRef;
-#endif
-
- class QMF_CLASS_EXTERN EventNotifier : public qmf::Handle<qmf::PosixEventNotifierImpl> {
- public:
- QMF_EXTERN EventNotifier(PosixEventNotifierImpl* impl = 0);
- QMF_EXTERN EventNotifier(::qmf::AgentSession& agentSession);
- QMF_EXTERN EventNotifier(::qmf::ConsoleSession& consoleSession);
- QMF_EXTERN EventNotifier(const EventNotifier& that);
-
- QMF_EXTERN ~EventNotifier();
-
- QMF_EXTERN EventNotifier& operator=(const EventNotifier& that);
-
- QMF_EXTERN int getHandle() const;
-
-#ifndef SWIG
- private:
- friend class qmf::PrivateImplRef<EventNotifier>;
- friend struct qmf::PosixEventNotifierImplAccess;
-#endif
-
- };
-
-}}
-
-#endif
-
diff --git a/cpp/include/qpid/Address.h b/cpp/include/qpid/Address.h
index f5b19d0532..57c9139f87 100755
--- a/cpp/include/qpid/Address.h
+++ b/cpp/include/qpid/Address.h
@@ -36,7 +36,7 @@ public:
static const std::string TCP; // Default TCP protocol tag.
static const uint16_t AMQP_PORT=5672; // Default AMQP port.
- QPID_COMMON_INLINE_EXTERN explicit Address(
+ QPID_COMMON_EXTERN explicit Address(
const std::string& protocol_=std::string(),
const std::string& host_=std::string(),
uint16_t port_=0
diff --git a/cpp/include/qpid/CommonImportExport.h b/cpp/include/qpid/CommonImportExport.h
index dd2b900b73..02c06ed7af 100644
--- a/cpp/include/qpid/CommonImportExport.h
+++ b/cpp/include/qpid/CommonImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(COMMON_EXPORT) || defined (qpidcommon_EXPORTS)
-# define QPID_COMMON_EXTERN QPID_EXPORT
-# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_COMMON_EXTERN __declspec(dllexport)
+#else
+#define QPID_COMMON_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_COMMON_EXTERN QPID_IMPORT
-# define QPID_COMMON_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_COMMON_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_COMMON_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/Exception.h b/cpp/include/qpid/Exception.h
index cbd175214d..fa7111160c 100644
--- a/cpp/include/qpid/Exception.h
+++ b/cpp/include/qpid/Exception.h
@@ -36,7 +36,7 @@ namespace qpid
/**
* Base class for Qpid runtime exceptions.
*/
-class QPID_COMMON_CLASS_EXTERN Exception : public std::exception
+class Exception : public std::exception
{
public:
QPID_COMMON_EXTERN explicit Exception(const std::string& message=std::string()) throw();
@@ -51,30 +51,30 @@ class QPID_COMMON_CLASS_EXTERN Exception : public std::exception
};
/** Exception that includes an errno message. */
-struct QPID_COMMON_CLASS_EXTERN ErrnoException : public Exception {
+struct ErrnoException : public Exception {
ErrnoException(const std::string& msg, int err) : Exception(msg+": "+qpid::sys::strError(err)) {}
ErrnoException(const std::string& msg) : Exception(msg+": "+qpid::sys::strError(errno)) {}
};
-struct QPID_COMMON_CLASS_EXTERN SessionException : public Exception {
+struct SessionException : public Exception {
const framing::execution::ErrorCode code;
SessionException(framing::execution::ErrorCode code_, const std::string& message)
: Exception(message), code(code_) {}
};
-struct QPID_COMMON_CLASS_EXTERN ChannelException : public Exception {
+struct ChannelException : public Exception {
const framing::session::DetachCode code;
ChannelException(framing::session::DetachCode _code, const std::string& message)
: Exception(message), code(_code) {}
};
-struct QPID_COMMON_CLASS_EXTERN ConnectionException : public Exception {
+struct ConnectionException : public Exception {
const framing::connection::CloseCode code;
ConnectionException(framing::connection::CloseCode _code, const std::string& message)
: Exception(message), code(_code) {}
};
-struct QPID_COMMON_CLASS_EXTERN ClosedException : public Exception {
+struct ClosedException : public Exception {
QPID_COMMON_EXTERN ClosedException(const std::string& msg=std::string());
QPID_COMMON_EXTERN std::string getPrefix() const;
};
diff --git a/cpp/include/qpid/ImportExport.h b/cpp/include/qpid/ImportExport.h
deleted file mode 100644
index e62399faf7..0000000000
--- a/cpp/include/qpid/ImportExport.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef QPID_IMPORTEXPORT_H
-#define QPID_IMPORTEXPORT_H
-
-/*
- * 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.
- */
-
-//
-// This header file defines the following macros for the control of library/DLL
-// import and export:
-//
-// QPID_EXPORT - Export declaration for Methods
-// QPID_CLASS_EXPORT - Export declaration for Classes
-// QPID_INLINE_EXPORT - Export declaration for Inline methods
-//
-// QPID_IMPORT - Import declaration for Methods
-// QPID_CLASS_IMPORT - Import declaration for Classes
-// QPID_INLINE_IMPORT - Import declaration for Inline methods
-//
-
-#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
- //
- // Import and Export definitions for Windows:
- //
-# define QPID_EXPORT __declspec(dllexport)
-# define QPID_IMPORT __declspec(dllimport)
-# ifdef _MSC_VER
- //
- // Specific to the Microsoft compiler:
- //
-# define QPID_CLASS_EXPORT
-# define QPID_CLASS_IMPORT
-# define QPID_INLINE_EXPORT QPID_EXPORT
-# define QPID_INLINE_IMPORT QPID_IMPORT
-# else
- //
- // Specific to non-Microsoft compilers (mingw32):
- //
-# define QPID_CLASS_EXPORT QPID_EXPORT
-# define QPID_CLASS_IMPORT QPID_IMPORT
-# define QPID_INLINE_EXPORT
-# define QPID_INLINE_IMPORT
-# endif
-#else
- //
- // Non-Windows (Linux, etc.) definitions:
- //
-# define QPID_EXPORT
-# define QPID_IMPORT
-# define QPID_CLASS_EXPORT
-# define QPID_CLASS_IMPORT
-# define QPID_INLINE_EXPORT
-# define QPID_INLINE_IMPORT
-#endif
-
-#endif /*!QPID_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/Msg.h b/cpp/include/qpid/Msg.h
index 5f0b11bc60..e1837c29e5 100644
--- a/cpp/include/qpid/Msg.h
+++ b/cpp/include/qpid/Msg.h
@@ -24,7 +24,6 @@
#include <sstream>
#include <iostream>
-#include "qpid/types/ImportExport.h"
namespace qpid {
diff --git a/cpp/include/qpid/Options.h b/cpp/include/qpid/Options.h
index 63d91c2d72..078a6b4d95 100644
--- a/cpp/include/qpid/Options.h
+++ b/cpp/include/qpid/Options.h
@@ -133,6 +133,77 @@ inline po::value_semantic* optValue(bool& value) { return po::bool_switch(&value
+/*
+ * ---------------------------------------------
+ * Explanation for Boost 103200 conditional code
+ * ---------------------------------------------
+ *
+ * This boost version has an implementation of the program_options library
+ * that has no provision for allowing unregistered options to pass by.
+ *
+ * But that means that, if you have a program that loads optional modules
+ * after start-up, and those modules each have their own set of options,
+ * then if you parse the command line too soon, you will get spurious
+ * reports of unrecognized options -- and the program will exit!
+ *
+ * And we must process the command-line before module-loading, because we
+ * need to look at the "bootstrap" options.
+ *
+ * This conditional code:
+ *
+ * 1. implements it's own functor class, derived from the Boost
+ * "options_description_easy_init" class. This functor is used
+ * to process added options and do the functor chaining, so that
+ * I can snoop on the arguments before doing an explicit call
+ * to its parent.
+ *
+ * 2. It implements two static vectors, one to hold long names, and
+ * one for short names, so that options declared by modules are
+ * not forgotten when their options_description goes out of scope.
+ *
+ * I will be thrilled to personally delete this code if we ever decide
+ * that qpid doesn't really need to support this antique version of Boost.
+ *
+ */
+
+#if ( BOOST_VERSION == 103200 )
+struct Options;
+
+
+struct
+options_description_less_easy_init
+ : public po::options_description_easy_init
+{
+ options_description_less_easy_init ( Options * my_owner,
+ po::options_description * my_parents_owner
+ )
+ : po::options_description_easy_init(my_parents_owner)
+ {
+ owner = my_owner;
+ }
+
+
+ options_description_less_easy_init&
+ operator()(char const * name,
+ char const * description);
+
+
+ options_description_less_easy_init&
+ operator()(char const * name,
+ const po::value_semantic* s);
+
+
+ options_description_less_easy_init&
+ operator()(const char* name,
+ const po::value_semantic* s,
+ const char* description);
+
+
+ Options * owner;
+};
+#endif
+
+
struct Options : public po::options_description {
struct Exception : public qpid::Exception {
@@ -151,9 +222,26 @@ struct Options : public po::options_description {
bool allowUnknown = false);
+ #if ( BOOST_VERSION == 103200 )
+ options_description_less_easy_init m_less_easy;
+
+ options_description_less_easy_init addOptions() {
+ return m_less_easy;
+ }
+
+ bool
+ is_registered_option ( std::string s );
+
+ void
+ register_names ( std::string s );
+
+ static std::vector<std::string> long_names;
+ static std::vector<std::string> short_names;
+ #else
boost::program_options::options_description_easy_init addOptions() {
return add_options();
}
+ #endif
};
diff --git a/cpp/include/qpid/Url.h b/cpp/include/qpid/Url.h
index 915b08ac5f..353e9d5599 100644
--- a/cpp/include/qpid/Url.h
+++ b/cpp/include/qpid/Url.h
@@ -66,7 +66,7 @@ struct Url : public std::vector<Address> {
*@exception Invalid if the url is invalid.
*/
QPID_COMMON_EXTERN void parse(const char* url);
- QPID_COMMON_INLINE_EXTERN void parse(const std::string& url) { parse(url.c_str()); }
+ QPID_COMMON_EXTERN void parse(const std::string& url) { parse(url.c_str()); }
/** Replace contesnts with parsed URL. Replace with empty URL if invalid. */
QPID_COMMON_EXTERN void parseNoThrow(const char* url);
diff --git a/cpp/include/qpid/agent/ManagementAgent.h b/cpp/include/qpid/agent/ManagementAgent.h
index 10bc6527a9..e2451244c1 100644
--- a/cpp/include/qpid/agent/ManagementAgent.h
+++ b/cpp/include/qpid/agent/ManagementAgent.h
@@ -110,8 +110,8 @@ class ManagementAgent
uint16_t intervalSeconds = 10,
bool useExternalThread = false,
const std::string& storeFile = "",
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& mech = "PLAIN",
const std::string& proto = "tcp") = 0;
diff --git a/cpp/include/qpid/agent/QmfAgentImportExport.h b/cpp/include/qpid/agent/QmfAgentImportExport.h
index 3f923ac4b2..e41425a7ba 100644
--- a/cpp/include/qpid/agent/QmfAgentImportExport.h
+++ b/cpp/include/qpid/agent/QmfAgentImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
-#if defined(QMF_EXPORT) || defined (qmf_EXPORTS)
-# define QMF_AGENT_EXTERN QPID_EXPORT
-# define QMF_AGENT_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QMF_AGENT_INLINE_EXTERN QPID_INLINE_EXPORT
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
+#if defined (qmf_EXPORTS)
+#define QMF_AGENT_EXTERN __declspec(dllexport)
+#else
+#define QMF_AGENT_EXTERN __declspec(dllimport)
+#endif
#else
-# define QMF_AGENT_EXTERN QPID_IMPORT
-# define QMF_AGENT_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QMF_AGENT_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QMF_AGENT_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/amqp_0_10/Codecs.h b/cpp/include/qpid/amqp_0_10/Codecs.h
index 73846f33a8..08275402fc 100644
--- a/cpp/include/qpid/amqp_0_10/Codecs.h
+++ b/cpp/include/qpid/amqp_0_10/Codecs.h
@@ -34,14 +34,14 @@ namespace amqp_0_10 {
* Codec for encoding/decoding a map of Variants using the AMQP 0-10
* map encoding.
*/
-class QPID_COMMON_CLASS_EXTERN MapCodec
+class QPID_COMMON_EXTERN MapCodec
{
public:
typedef qpid::types::Variant::Map ObjectType;
- static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
- static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
- static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
- static const QPID_COMMON_EXTERN std::string contentType;
+ static void encode(const ObjectType&, std::string&);
+ static void decode(const std::string&, ObjectType&);
+ static size_t encodedSize(const ObjectType&);
+ static const std::string contentType;
private:
};
@@ -49,14 +49,14 @@ class QPID_COMMON_CLASS_EXTERN MapCodec
* Codec for encoding/decoding a list of Variants using the AMQP 0-10
* list encoding.
*/
-class QPID_COMMON_CLASS_EXTERN ListCodec
+class QPID_COMMON_EXTERN ListCodec
{
public:
typedef qpid::types::Variant::List ObjectType;
- static void QPID_COMMON_EXTERN encode(const ObjectType&, std::string&);
- static void QPID_COMMON_EXTERN decode(const std::string&, ObjectType&);
- static size_t QPID_COMMON_EXTERN encodedSize(const ObjectType&);
- static const QPID_COMMON_EXTERN std::string contentType;
+ static void encode(const ObjectType&, std::string&);
+ static void decode(const std::string&, ObjectType&);
+ static size_t encodedSize(const ObjectType&);
+ static const std::string contentType;
private:
};
diff --git a/cpp/include/qpid/client/ClientImportExport.h b/cpp/include/qpid/client/ClientImportExport.h
index 2a3a5a52e9..42b02e33c3 100644
--- a/cpp/include/qpid/client/ClientImportExport.h
+++ b/cpp/include/qpid/client/ClientImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CLIENT_EXPORT) || defined (qpidclient_EXPORTS)
-# define QPID_CLIENT_EXTERN QPID_EXPORT
-# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_CLIENT_EXTERN __declspec(dllexport)
+#else
+#define QPID_CLIENT_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_CLIENT_EXTERN QPID_IMPORT
-# define QPID_CLIENT_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_CLIENT_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_CLIENT_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/client/Completion.h b/cpp/include/qpid/client/Completion.h
index 9546db9258..99d940f031 100644
--- a/cpp/include/qpid/client/Completion.h
+++ b/cpp/include/qpid/client/Completion.h
@@ -41,7 +41,7 @@ template <class T> class PrivateImplRef;
*
*\ingroup clientapi
*/
-class QPID_CLIENT_CLASS_EXTERN Completion : public Handle<CompletionImpl>
+class Completion : public Handle<CompletionImpl>
{
public:
QPID_CLIENT_EXTERN Completion(CompletionImpl* = 0);
diff --git a/cpp/include/qpid/client/Connection.h b/cpp/include/qpid/client/Connection.h
index c0db0f301d..6ed0d98bc0 100644
--- a/cpp/include/qpid/client/Connection.h
+++ b/cpp/include/qpid/client/Connection.h
@@ -60,7 +60,7 @@ class ConnectionImpl;
*
*/
-class QPID_CLIENT_CLASS_EXTERN Connection
+class Connection
{
framing::ProtocolVersion version;
@@ -102,8 +102,8 @@ class QPID_CLIENT_CLASS_EXTERN Connection
* within a single broker).
*/
QPID_CLIENT_EXTERN void open(const std::string& host, int port = 5672,
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
/**
@@ -124,8 +124,8 @@ class QPID_CLIENT_CLASS_EXTERN Connection
* within a single broker).
*/
QPID_CLIENT_EXTERN void open(const Url& url,
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& virtualhost = "/", uint16_t maxFrameSize=65535);
/**
diff --git a/cpp/include/qpid/client/ConnectionSettings.h b/cpp/include/qpid/client/ConnectionSettings.h
index 2b6b86f891..1c2ee28b1b 100644
--- a/cpp/include/qpid/client/ConnectionSettings.h
+++ b/cpp/include/qpid/client/ConnectionSettings.h
@@ -37,7 +37,7 @@ namespace client {
/**
* Settings for a Connection.
*/
-struct QPID_CLIENT_CLASS_EXTERN ConnectionSettings {
+struct ConnectionSettings {
QPID_CLIENT_EXTERN ConnectionSettings();
QPID_CLIENT_EXTERN virtual ~ConnectionSettings();
diff --git a/cpp/include/qpid/client/FailoverListener.h b/cpp/include/qpid/client/FailoverListener.h
index 53c7c26211..59108eb7cb 100644
--- a/cpp/include/qpid/client/FailoverListener.h
+++ b/cpp/include/qpid/client/FailoverListener.h
@@ -48,7 +48,7 @@ namespace client {
* FailoverListener::decode to extract a list of broker URLs from a
* failover exchange message.
*/
-class QPID_CLIENT_CLASS_EXTERN FailoverListener : private MessageListener, private qpid::sys::Runnable
+class FailoverListener : private MessageListener, private qpid::sys::Runnable
{
public:
/** The name of the standard failover exchange amq.failover */
diff --git a/cpp/include/qpid/client/FailoverManager.h b/cpp/include/qpid/client/FailoverManager.h
index d3a0dbc976..0d30e2ed60 100644
--- a/cpp/include/qpid/client/FailoverManager.h
+++ b/cpp/include/qpid/client/FailoverManager.h
@@ -42,7 +42,7 @@ struct CannotConnectException : qpid::Exception
/**
* Utility to manage failover.
*/
-class QPID_CLIENT_CLASS_EXTERN FailoverManager
+class FailoverManager
{
public:
/**
diff --git a/cpp/include/qpid/client/Future.h b/cpp/include/qpid/client/Future.h
index 630a7e03c0..09088e68f6 100644
--- a/cpp/include/qpid/client/Future.h
+++ b/cpp/include/qpid/client/Future.h
@@ -34,7 +34,7 @@ namespace qpid {
namespace client {
/**@internal */
-class QPID_CLIENT_CLASS_EXTERN Future
+class Future
{
framing::SequenceNumber command;
boost::shared_ptr<FutureResult> result;
diff --git a/cpp/include/qpid/client/FutureResult.h b/cpp/include/qpid/client/FutureResult.h
index ead4929571..b2b663daa1 100644
--- a/cpp/include/qpid/client/FutureResult.h
+++ b/cpp/include/qpid/client/FutureResult.h
@@ -34,7 +34,7 @@ namespace client {
class SessionImpl;
///@internal
-class QPID_CLIENT_CLASS_EXTERN FutureResult : public FutureCompletion
+class FutureResult : public FutureCompletion
{
std::string result;
public:
diff --git a/cpp/include/qpid/client/Handle.h b/cpp/include/qpid/client/Handle.h
index b8315481a9..088e836fcf 100644
--- a/cpp/include/qpid/client/Handle.h
+++ b/cpp/include/qpid/client/Handle.h
@@ -40,22 +40,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QPID_CLIENT_INLINE_EXTERN bool isValid() const { return impl; }
+ QPID_CLIENT_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QPID_CLIENT_INLINE_EXTERN bool isNull() const { return !impl; }
+ QPID_CLIENT_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QPID_CLIENT_INLINE_EXTERN operator bool() const { return impl; }
+ QPID_CLIENT_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QPID_CLIENT_INLINE_EXTERN bool operator !() const { return !impl; }
+ QPID_CLIENT_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QPID_CLIENT_INLINE_EXTERN Handle() :impl() {}
+ QPID_CLIENT_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QPID_CLIENT_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qpid/client/LocalQueue.h b/cpp/include/qpid/client/LocalQueue.h
index 1a19a8499d..70e4cebcf1 100644
--- a/cpp/include/qpid/client/LocalQueue.h
+++ b/cpp/include/qpid/client/LocalQueue.h
@@ -71,7 +71,7 @@ template <class T> class PrivateImplRef;
* </ul>
*/
-class QPID_CLIENT_CLASS_EXTERN LocalQueue : public Handle<LocalQueueImpl> {
+class LocalQueue : public Handle<LocalQueueImpl> {
public:
/** Create a local queue. Subscribe the local queue to a remote broker
* queue with a SubscriptionManager.
diff --git a/cpp/include/qpid/client/Message.h b/cpp/include/qpid/client/Message.h
index ba50dda9ba..2401cbdc92 100644
--- a/cpp/include/qpid/client/Message.h
+++ b/cpp/include/qpid/client/Message.h
@@ -112,7 +112,7 @@ class MessageImpl;
*
*
*/
-class QPID_CLIENT_CLASS_EXTERN Message
+class Message
{
public:
/** Create a Message.
diff --git a/cpp/include/qpid/client/MessageListener.h b/cpp/include/qpid/client/MessageListener.h
index 3ca2fa964a..d200f8cf21 100644
--- a/cpp/include/qpid/client/MessageListener.h
+++ b/cpp/include/qpid/client/MessageListener.h
@@ -84,7 +84,7 @@ namespace client {
*
*/
- class QPID_CLIENT_CLASS_EXTERN MessageListener{
+ class MessageListener{
public:
QPID_CLIENT_EXTERN virtual ~MessageListener();
diff --git a/cpp/include/qpid/client/MessageReplayTracker.h b/cpp/include/qpid/client/MessageReplayTracker.h
index 06a3f29c7d..6f5a0f4ac3 100644
--- a/cpp/include/qpid/client/MessageReplayTracker.h
+++ b/cpp/include/qpid/client/MessageReplayTracker.h
@@ -34,7 +34,7 @@ namespace client {
* Utility to track messages sent asynchronously, allowing those that
* are indoubt to be replayed over a new session.
*/
-class QPID_CLIENT_CLASS_EXTERN MessageReplayTracker
+class MessageReplayTracker
{
public:
QPID_CLIENT_EXTERN MessageReplayTracker(uint flushInterval);
diff --git a/cpp/include/qpid/client/QueueOptions.h b/cpp/include/qpid/client/QueueOptions.h
index 3984b63fdd..f8a4963f06 100644
--- a/cpp/include/qpid/client/QueueOptions.h
+++ b/cpp/include/qpid/client/QueueOptions.h
@@ -35,7 +35,7 @@ enum QueueOrderingPolicy {FIFO, LVQ, LVQ_NO_BROWSE};
* A help class to set options on the Queue. Create a configured args while
* still allowing any custom configuration via the FieldTable base class
*/
-class QPID_CLIENT_CLASS_EXTERN QueueOptions: public framing::FieldTable
+class QueueOptions: public framing::FieldTable
{
public:
QPID_CLIENT_EXTERN QueueOptions();
diff --git a/cpp/include/qpid/client/SessionBase_0_10.h b/cpp/include/qpid/client/SessionBase_0_10.h
index ea50ab32f7..3b5c84e74b 100644
--- a/cpp/include/qpid/client/SessionBase_0_10.h
+++ b/cpp/include/qpid/client/SessionBase_0_10.h
@@ -54,7 +54,7 @@ enum CreditUnit { MESSAGE_CREDIT=0, BYTE_CREDIT=1, UNLIMITED_CREDIT=0xFFFFFFFF }
* Subclasses provide the AMQP commands for a given
* version of the protocol.
*/
-class QPID_CLIENT_CLASS_EXTERN SessionBase_0_10 {
+class SessionBase_0_10 {
public:
///@internal
diff --git a/cpp/include/qpid/client/Subscription.h b/cpp/include/qpid/client/Subscription.h
index bb9b98e8ff..425b6b92e2 100644
--- a/cpp/include/qpid/client/Subscription.h
+++ b/cpp/include/qpid/client/Subscription.h
@@ -39,7 +39,7 @@ class SubscriptionManager;
* A handle to an active subscription. Provides methods to query the subscription status
* and control acknowledgement (acquire and accept) of messages.
*/
-class QPID_CLIENT_CLASS_EXTERN Subscription : public Handle<SubscriptionImpl> {
+class Subscription : public Handle<SubscriptionImpl> {
public:
QPID_CLIENT_EXTERN Subscription(SubscriptionImpl* = 0);
QPID_CLIENT_EXTERN Subscription(const Subscription&);
@@ -91,13 +91,13 @@ class QPID_CLIENT_CLASS_EXTERN Subscription : public Handle<SubscriptionImpl> {
QPID_CLIENT_EXTERN void release(const SequenceSet& messageIds);
/* Acquire a single message */
- QPID_CLIENT_INLINE_EXTERN void acquire(const Message& m) { acquire(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void acquire(const Message& m) { acquire(SequenceSet(m.getId())); }
/* Accept a single message */
- QPID_CLIENT_INLINE_EXTERN void accept(const Message& m) { accept(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void accept(const Message& m) { accept(SequenceSet(m.getId())); }
/* Release a single message */
- QPID_CLIENT_INLINE_EXTERN void release(const Message& m) { release(SequenceSet(m.getId())); }
+ QPID_CLIENT_EXTERN void release(const Message& m) { release(SequenceSet(m.getId())); }
/** Get the session associated with this subscription */
QPID_CLIENT_EXTERN Session getSession() const;
diff --git a/cpp/include/qpid/client/SubscriptionManager.h b/cpp/include/qpid/client/SubscriptionManager.h
index b69819a8ff..e70e05f73a 100644
--- a/cpp/include/qpid/client/SubscriptionManager.h
+++ b/cpp/include/qpid/client/SubscriptionManager.h
@@ -94,7 +94,7 @@ class SubscriptionManagerImpl;
* </ul>
*
*/
-class QPID_CLIENT_CLASS_EXTERN SubscriptionManager : public sys::Runnable, public Handle<SubscriptionManagerImpl>
+class SubscriptionManager : public sys::Runnable, public Handle<SubscriptionManagerImpl>
{
public:
/** Create a new SubscriptionManager associated with a session */
diff --git a/cpp/include/qpid/console/Agent.h b/cpp/include/qpid/console/Agent.h
index 629dd71dee..97d75da250 100644
--- a/cpp/include/qpid/console/Agent.h
+++ b/cpp/include/qpid/console/Agent.h
@@ -31,17 +31,17 @@ namespace console {
*
* \ingroup qmfconsoleapi
*/
- class QPID_CONSOLE_CLASS_EXTERN Agent {
+ class QPID_CONSOLE_EXTERN Agent {
public:
typedef std::vector<Agent*> Vector;
- QPID_CONSOLE_INLINE_EXTERN Agent(Broker* _broker, uint32_t _bank, const std::string& _label) :
+ Agent(Broker* _broker, uint32_t _bank, const std::string& _label) :
broker(_broker), brokerBank(broker->getBrokerBank()),
agentBank(_bank), label(_label) {}
- QPID_CONSOLE_INLINE_EXTERN Broker* getBroker() const { return broker; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getBrokerBank() const { return brokerBank; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getAgentBank() const { return agentBank; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getLabel() const { return label; }
+ Broker* getBroker() const { return broker; }
+ uint32_t getBrokerBank() const { return brokerBank; }
+ uint32_t getAgentBank() const { return agentBank; }
+ const std::string& getLabel() const { return label; }
private:
Broker* broker;
@@ -50,7 +50,7 @@ namespace console {
const std::string label;
};
- std::ostream& operator<<(std::ostream& o, const Agent& agent);
+ QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Agent& agent);
}
}
diff --git a/cpp/include/qpid/console/Broker.h b/cpp/include/qpid/console/Broker.h
index c2ba8ac81f..0b2d1bcb61 100644
--- a/cpp/include/qpid/console/Broker.h
+++ b/cpp/include/qpid/console/Broker.h
@@ -55,12 +55,12 @@ namespace console {
client::ConnectionSettings& settings);
QPID_CONSOLE_EXTERN ~Broker();
- QPID_CONSOLE_INLINE_EXTERN bool isConnected() const { return connected; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getError() const { return error; }
- QPID_CONSOLE_INLINE_EXTERN const std::string& getSessionId() const { return amqpSessionId; }
- QPID_CONSOLE_INLINE_EXTERN const framing::Uuid& getBrokerId() const { return brokerId; }
- QPID_CONSOLE_INLINE_EXTERN uint32_t getBrokerBank() const { return 1; }
- QPID_CONSOLE_INLINE_EXTERN void addBinding(const std::string& key) {
+ QPID_CONSOLE_EXTERN bool isConnected() const { return connected; }
+ QPID_CONSOLE_EXTERN const std::string& getError() const { return error; }
+ QPID_CONSOLE_EXTERN const std::string& getSessionId() const { return amqpSessionId; }
+ QPID_CONSOLE_EXTERN const framing::Uuid& getBrokerId() const { return brokerId; }
+ QPID_CONSOLE_EXTERN uint32_t getBrokerBank() const { return 1; }
+ QPID_CONSOLE_EXTERN void addBinding(const std::string& key) {
connThreadBody.bindExchange("qpid.management", key);
}
QPID_CONSOLE_EXTERN std::string getUrl() const;
@@ -123,10 +123,10 @@ namespace console {
void setBrokerId(const framing::Uuid& id) { brokerId = id; }
void appendAgents(std::vector<Agent*>& agents) const;
- friend std::ostream& operator<<(std::ostream& o, const Broker& k);
+ friend QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Broker& k);
};
- std::ostream& operator<<(std::ostream& o, const Broker& k);
+ QPID_CONSOLE_EXTERN std::ostream& operator<<(std::ostream& o, const Broker& k);
}
}
diff --git a/cpp/include/qpid/console/ClassKey.h b/cpp/include/qpid/console/ClassKey.h
index 5f7c50351a..95cd2627f1 100644
--- a/cpp/include/qpid/console/ClassKey.h
+++ b/cpp/include/qpid/console/ClassKey.h
@@ -33,24 +33,24 @@ namespace console {
*
* \ingroup qmfconsoleapi
*/
- class QPID_CONSOLE_CLASS_EXTERN ClassKey {
+ class QPID_CONSOLE_EXTERN ClassKey {
public:
- QPID_CONSOLE_EXTERN static const int HASH_SIZE = 16;
+ static const int HASH_SIZE = 16;
- QPID_CONSOLE_EXTERN ClassKey(const std::string& package, const std::string& name, const uint8_t* hash);
+ ClassKey(const std::string& package, const std::string& name, const uint8_t* hash);
- const QPID_CONSOLE_EXTERN std::string& getPackageName() const { return package; }
- const QPID_CONSOLE_EXTERN std::string& getClassName() const { return name; }
- const QPID_CONSOLE_EXTERN uint8_t* getHash() const { return hash; }
- QPID_CONSOLE_EXTERN std::string getHashString() const;
- QPID_CONSOLE_EXTERN std::string str() const;
- QPID_CONSOLE_EXTERN bool operator==(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator!=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator<(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator>(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator<=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN bool operator>=(const ClassKey& other) const;
- QPID_CONSOLE_EXTERN void encode(framing::Buffer& buffer) const;
+ const std::string& getPackageName() const { return package; }
+ const std::string& getClassName() const { return name; }
+ const uint8_t* getHash() const { return hash; }
+ std::string getHashString() const;
+ std::string str() const;
+ bool operator==(const ClassKey& other) const;
+ bool operator!=(const ClassKey& other) const;
+ bool operator<(const ClassKey& other) const;
+ bool operator>(const ClassKey& other) const;
+ bool operator<=(const ClassKey& other) const;
+ bool operator>=(const ClassKey& other) const;
+ void encode(framing::Buffer& buffer) const;
private:
std::string package;
diff --git a/cpp/include/qpid/console/ConsoleImportExport.h b/cpp/include/qpid/console/ConsoleImportExport.h
index aac30858f7..c2d7cb3a14 100644
--- a/cpp/include/qpid/console/ConsoleImportExport.h
+++ b/cpp/include/qpid/console/ConsoleImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CONSOLE_EXPORT) || defined (qmfconsole_EXPORTS)
-# define QPID_CONSOLE_EXTERN QPID_EXPORT
-# define QPID_CONSOLE_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_CONSOLE_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_CONSOLE_EXTERN __declspec(dllexport)
+#else
+#define QPID_CONSOLE_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_CONSOLE_EXTERN QPID_IMPORT
-# define QPID_CONSOLE_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_CONSOLE_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_CONSOLE_EXTERN
#endif
#endif
diff --git a/cpp/include/qpid/console/ObjectId.h b/cpp/include/qpid/console/ObjectId.h
index 0722eaebeb..7904c85598 100644
--- a/cpp/include/qpid/console/ObjectId.h
+++ b/cpp/include/qpid/console/ObjectId.h
@@ -40,10 +40,10 @@ namespace console {
ObjectId() : first(0), second(0) {}
ObjectId(framing::Buffer& buffer);
- uint8_t getFlags() const { return (uint8_t)((first & 0xF000000000000000LL) >> 60); }
- uint16_t getSequence() const { return (uint16_t)((first & 0x0FFF000000000000LL) >> 48); }
- uint32_t getBrokerBank() const { return (uint32_t)((first & 0x0000FFFFF0000000LL) >> 28); }
- uint32_t getAgentBank() const { return (uint32_t) (first & 0x000000000FFFFFFFLL); }
+ uint8_t getFlags() const { return (first & 0xF000000000000000LL) >> 60; }
+ uint16_t getSequence() const { return (first & 0x0FFF000000000000LL) >> 48; }
+ uint32_t getBrokerBank() const { return (first & 0x0000FFFFF0000000LL) >> 28; }
+ uint32_t getAgentBank() const { return first & 0x000000000FFFFFFFLL; }
uint64_t getObject() const { return second; }
bool isDurable() const { return getSequence() == 0; }
void decode(framing::Buffer& buffer);
diff --git a/cpp/include/qpid/framing/Array.h b/cpp/include/qpid/framing/Array.h
index 1e97be3bb4..d3bdd36aa6 100644
--- a/cpp/include/qpid/framing/Array.h
+++ b/cpp/include/qpid/framing/Array.h
@@ -34,7 +34,7 @@ namespace framing {
class Buffer;
-class QPID_COMMON_CLASS_EXTERN Array
+class Array
{
public:
typedef boost::shared_ptr<FieldValue> ValuePtr;
@@ -55,25 +55,25 @@ class QPID_COMMON_CLASS_EXTERN Array
//creates a longstr array
QPID_COMMON_EXTERN Array(const std::vector<std::string>& in);
- QPID_COMMON_INLINE_EXTERN TypeCode getType() const { return type; }
+ QPID_COMMON_EXTERN TypeCode getType() const { return type; }
// std collection interface.
- QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
- QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+ QPID_COMMON_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_EXTERN iterator end(){ return values.end(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+ QPID_COMMON_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_EXTERN size_t size() const { return values.size(); }
QPID_COMMON_EXTERN void insert(iterator i, ValuePtr value);
- QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
- QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
- QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+ QPID_COMMON_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_EXTERN void pop_back() { values.pop_back(); }
// Non-std interface
- QPID_COMMON_INLINE_EXTERN void add(ValuePtr value) { push_back(value); }
+ QPID_COMMON_EXTERN void add(ValuePtr value) { push_back(value); }
template <class T>
void collect(std::vector<T>& out) const
diff --git a/cpp/include/qpid/framing/Buffer.h b/cpp/include/qpid/framing/Buffer.h
index 8b08e60762..04583433c5 100644
--- a/cpp/include/qpid/framing/Buffer.h
+++ b/cpp/include/qpid/framing/Buffer.h
@@ -29,14 +29,14 @@
namespace qpid {
namespace framing {
-struct QPID_COMMON_CLASS_EXTERN OutOfBounds : qpid::Exception {
+struct OutOfBounds : qpid::Exception {
OutOfBounds() : qpid::Exception(std::string("Out of Bounds")) {}
};
class Content;
class FieldTable;
-class QPID_COMMON_CLASS_EXTERN Buffer
+class Buffer
{
uint32_t size;
char* data;
@@ -72,12 +72,12 @@ class QPID_COMMON_CLASS_EXTERN Buffer
QPID_COMMON_EXTERN void restore(bool reRecord = false);
QPID_COMMON_EXTERN void reset();
- QPID_COMMON_INLINE_EXTERN uint32_t available() { return size - position; }
- QPID_COMMON_INLINE_EXTERN uint32_t getSize() { return size; }
- QPID_COMMON_INLINE_EXTERN uint32_t getPosition() { return position; }
- QPID_COMMON_INLINE_EXTERN void setPosition(uint32_t p) { position = p; }
- QPID_COMMON_INLINE_EXTERN Iterator getIterator() { return Iterator(*this); }
- QPID_COMMON_INLINE_EXTERN char* getPointer() { return data; }
+ QPID_COMMON_EXTERN uint32_t available() { return size - position; }
+ QPID_COMMON_EXTERN uint32_t getSize() { return size; }
+ QPID_COMMON_EXTERN uint32_t getPosition() { return position; }
+ QPID_COMMON_EXTERN void setPosition(uint32_t p) { position = p; }
+ QPID_COMMON_EXTERN Iterator getIterator() { return Iterator(*this); }
+ QPID_COMMON_EXTERN char* getPointer() { return data; }
QPID_COMMON_EXTERN void putOctet(uint8_t i);
QPID_COMMON_EXTERN void putShort(uint16_t i);
diff --git a/cpp/include/qpid/framing/FieldTable.h b/cpp/include/qpid/framing/FieldTable.h
index bdcef6d7fd..fdb1a28b9d 100644
--- a/cpp/include/qpid/framing/FieldTable.h
+++ b/cpp/include/qpid/framing/FieldTable.h
@@ -56,7 +56,7 @@ class FieldTable
typedef ValueMap::reference reference;
typedef ValueMap::value_type value_type;
- QPID_COMMON_INLINE_EXTERN FieldTable() {};
+ QPID_COMMON_EXTERN FieldTable() {};
QPID_COMMON_EXTERN FieldTable(const FieldTable& ft);
QPID_COMMON_EXTERN ~FieldTable();
QPID_COMMON_EXTERN FieldTable& operator=(const FieldTable& ft);
@@ -65,11 +65,9 @@ class FieldTable
QPID_COMMON_EXTERN void decode(Buffer& buffer);
QPID_COMMON_EXTERN int count() const;
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
- QPID_COMMON_INLINE_EXTERN bool empty() { return size() == 0; }
QPID_COMMON_EXTERN void set(const std::string& name, const ValuePtr& value);
QPID_COMMON_EXTERN ValuePtr get(const std::string& name) const;
- QPID_COMMON_INLINE_EXTERN bool isSet(const std::string& name) const { return get(name).get() != 0; }
+ QPID_COMMON_EXTERN bool isSet(const std::string& name) const { return get(name).get() != 0; }
QPID_COMMON_EXTERN void setString(const std::string& name, const std::string& value);
QPID_COMMON_EXTERN void setInt(const std::string& name, const int value);
diff --git a/cpp/include/qpid/framing/FieldValue.h b/cpp/include/qpid/framing/FieldValue.h
index 458de62fdf..19220e74d5 100644
--- a/cpp/include/qpid/framing/FieldValue.h
+++ b/cpp/include/qpid/framing/FieldValue.h
@@ -41,14 +41,14 @@ namespace framing {
*
* \ingroup clientapi
*/
-class QPID_COMMON_CLASS_EXTERN FieldValueException : public qpid::Exception {};
+class FieldValueException : public qpid::Exception {};
/**
* Exception thrown when we can't perform requested conversion
*
* \ingroup clientapi
*/
-struct QPID_COMMON_CLASS_EXTERN InvalidConversionException : public FieldValueException {
+struct InvalidConversionException : public FieldValueException {
InvalidConversionException() {}
};
@@ -59,7 +59,7 @@ class List;
*
* \ingroup clientapi
*/
-class QPID_COMMON_CLASS_EXTERN FieldValue {
+class FieldValue {
public:
/*
* Abstract type for content of different types
@@ -90,7 +90,7 @@ class QPID_COMMON_CLASS_EXTERN FieldValue {
void encode(Buffer& buffer);
void decode(Buffer& buffer);
QPID_COMMON_EXTERN bool operator==(const FieldValue&) const;
- QPID_COMMON_INLINE_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
+ QPID_COMMON_EXTERN bool operator!=(const FieldValue& v) const { return !(*this == v); }
QPID_COMMON_EXTERN void print(std::ostream& out) const;
@@ -98,7 +98,6 @@ class QPID_COMMON_CLASS_EXTERN FieldValue {
template <typename T> T get() const { throw InvalidConversionException(); }
template <class T, int W> T getIntegerValue() const;
- template <class T> T getIntegerValue() const;
template <class T, int W> T getFloatingPointValue() const;
template <int W> void getFixedWidthValue(unsigned char*) const;
template <class T> bool get(T&) const;
@@ -197,18 +196,6 @@ inline T FieldValue::getIntegerValue() const
}
}
-template <class T>
-inline T FieldValue::getIntegerValue() const
-{
- FixedWidthValue<1>* const fwv = dynamic_cast< FixedWidthValue<1>* const>(data.get());
- if (fwv) {
- uint8_t* octets = fwv->rawOctets();
- return octets[0];
- } else {
- throw InvalidConversionException();
- }
-}
-
template <class T, int W>
inline T FieldValue::getFloatingPointValue() const {
FixedWidthValue<W>* const fwv = dynamic_cast< FixedWidthValue<W>* const>(data.get());
diff --git a/cpp/include/qpid/framing/List.h b/cpp/include/qpid/framing/List.h
index 681445947c..0f17c7884c 100644
--- a/cpp/include/qpid/framing/List.h
+++ b/cpp/include/qpid/framing/List.h
@@ -36,11 +36,10 @@ class FieldValue;
/**
* Representation of an AMQP 0-10 list
*/
-class QPID_COMMON_CLASS_EXTERN List
+class List
{
public:
typedef boost::shared_ptr<FieldValue> ValuePtr;
- typedef ValuePtr value_type;
typedef std::list<ValuePtr> Values;
typedef Values::const_iterator const_iterator;
typedef Values::iterator iterator;
@@ -54,19 +53,19 @@ class QPID_COMMON_CLASS_EXTERN List
QPID_COMMON_EXTERN bool operator==(const List& other) const;
// std collection interface.
- QPID_COMMON_INLINE_EXTERN const_iterator begin() const { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN const_iterator end() const { return values.end(); }
- QPID_COMMON_INLINE_EXTERN iterator begin() { return values.begin(); }
- QPID_COMMON_INLINE_EXTERN iterator end(){ return values.end(); }
+ QPID_COMMON_EXTERN const_iterator begin() const { return values.begin(); }
+ QPID_COMMON_EXTERN const_iterator end() const { return values.end(); }
+ QPID_COMMON_EXTERN iterator begin() { return values.begin(); }
+ QPID_COMMON_EXTERN iterator end(){ return values.end(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr front() const { return values.front(); }
- QPID_COMMON_INLINE_EXTERN ValuePtr back() const { return values.back(); }
- QPID_COMMON_INLINE_EXTERN size_t size() const { return values.size(); }
+ QPID_COMMON_EXTERN ValuePtr front() const { return values.front(); }
+ QPID_COMMON_EXTERN ValuePtr back() const { return values.back(); }
+ QPID_COMMON_EXTERN size_t size() const { return values.size(); }
- QPID_COMMON_INLINE_EXTERN iterator insert(iterator i, ValuePtr value) { return values.insert(i, value); }
- QPID_COMMON_INLINE_EXTERN void erase(iterator i) { values.erase(i); }
- QPID_COMMON_INLINE_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
- QPID_COMMON_INLINE_EXTERN void pop_back() { values.pop_back(); }
+ QPID_COMMON_EXTERN iterator insert(iterator i, ValuePtr value) { return values.insert(i, value); }
+ QPID_COMMON_EXTERN void erase(iterator i) { values.erase(i); }
+ QPID_COMMON_EXTERN void push_back(ValuePtr value) { values.insert(end(), value); }
+ QPID_COMMON_EXTERN void pop_back() { values.pop_back(); }
private:
Values values;
diff --git a/cpp/include/qpid/framing/ProtocolVersion.h b/cpp/include/qpid/framing/ProtocolVersion.h
index 30094c165d..e7e75d75f6 100644
--- a/cpp/include/qpid/framing/ProtocolVersion.h
+++ b/cpp/include/qpid/framing/ProtocolVersion.h
@@ -29,7 +29,7 @@ namespace qpid
namespace framing
{
-class QPID_COMMON_CLASS_EXTERN ProtocolVersion
+class ProtocolVersion
{
private:
uint8_t major_;
@@ -39,16 +39,16 @@ public:
explicit ProtocolVersion(uint8_t _major=0, uint8_t _minor=0)
: major_(_major), minor_(_minor) {}
- QPID_COMMON_INLINE_EXTERN uint8_t getMajor() const { return major_; }
- QPID_COMMON_INLINE_EXTERN void setMajor(uint8_t major) { major_ = major; }
- QPID_COMMON_INLINE_EXTERN uint8_t getMinor() const { return minor_; }
- QPID_COMMON_INLINE_EXTERN void setMinor(uint8_t minor) { minor_ = minor; }
+ QPID_COMMON_EXTERN uint8_t getMajor() const { return major_; }
+ QPID_COMMON_EXTERN void setMajor(uint8_t major) { major_ = major; }
+ QPID_COMMON_EXTERN uint8_t getMinor() const { return minor_; }
+ QPID_COMMON_EXTERN void setMinor(uint8_t minor) { minor_ = minor; }
QPID_COMMON_EXTERN const std::string toString() const;
QPID_COMMON_EXTERN ProtocolVersion& operator=(ProtocolVersion p);
QPID_COMMON_EXTERN bool operator==(ProtocolVersion p) const;
- QPID_COMMON_INLINE_EXTERN bool operator!=(ProtocolVersion p) const { return ! (*this == p); }
+ QPID_COMMON_EXTERN bool operator!=(ProtocolVersion p) const { return ! (*this == p); }
};
} // namespace framing
diff --git a/cpp/include/qpid/framing/SequenceNumber.h b/cpp/include/qpid/framing/SequenceNumber.h
index eed15a4b75..1e53058df8 100644
--- a/cpp/include/qpid/framing/SequenceNumber.h
+++ b/cpp/include/qpid/framing/SequenceNumber.h
@@ -34,7 +34,7 @@ class Buffer;
/**
* 4-byte sequence number that 'wraps around'.
*/
-class QPID_COMMON_CLASS_EXTERN SequenceNumber : public
+class SequenceNumber : public
boost::equality_comparable<
SequenceNumber, boost::less_than_comparable<
SequenceNumber, boost::incrementable<
diff --git a/cpp/include/qpid/framing/SequenceSet.h b/cpp/include/qpid/framing/SequenceSet.h
index 0a78e418ba..39395e9ad7 100644
--- a/cpp/include/qpid/framing/SequenceSet.h
+++ b/cpp/include/qpid/framing/SequenceSet.h
@@ -29,7 +29,7 @@ namespace qpid {
namespace framing {
class Buffer;
-class QPID_COMMON_CLASS_EXTERN SequenceSet : public RangeSet<SequenceNumber> {
+class SequenceSet : public RangeSet<SequenceNumber> {
public:
SequenceSet() {}
SequenceSet(const RangeSet<SequenceNumber>& r)
diff --git a/cpp/include/qpid/framing/StructHelper.h b/cpp/include/qpid/framing/StructHelper.h
index 21f9b91fa9..fc9a7909cc 100644
--- a/cpp/include/qpid/framing/StructHelper.h
+++ b/cpp/include/qpid/framing/StructHelper.h
@@ -30,7 +30,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN StructHelper
+class StructHelper
{
public:
diff --git a/cpp/include/qpid/framing/Uuid.h b/cpp/include/qpid/framing/Uuid.h
index ccfd7e9534..d0a8d02411 100644
--- a/cpp/include/qpid/framing/Uuid.h
+++ b/cpp/include/qpid/framing/Uuid.h
@@ -52,22 +52,22 @@ struct Uuid : public boost::array<uint8_t, 16> {
// boost::array gives us ==, < etc.
/** Copy from 16 bytes of data. */
- QPID_COMMON_EXTERN void assign(const uint8_t* data);
+ void assign(const uint8_t* data);
/** Set to a new unique identifier. */
QPID_COMMON_EXTERN void generate();
/** Set to all zeros. */
- QPID_COMMON_EXTERN void clear();
+ void clear();
/** Test for null (all zeros). */
QPID_COMMON_EXTERN bool isNull() const;
- QPID_COMMON_INLINE_EXTERN operator bool() const { return !isNull(); }
- QPID_COMMON_INLINE_EXTERN bool operator!() const { return isNull(); }
+ operator bool() const { return !isNull(); }
+ bool operator!() const { return isNull(); }
QPID_COMMON_EXTERN void encode(framing::Buffer& buf) const;
QPID_COMMON_EXTERN void decode(framing::Buffer& buf);
- QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const
+ QPID_COMMON_EXTERN uint32_t encodedSize() const
{ return static_cast<uint32_t>(size()); }
/** String value in format 1b4e28ba-2fa1-11d2-883f-b9a761bde3fb. */
diff --git a/cpp/include/qpid/log/Logger.h b/cpp/include/qpid/log/Logger.h
index d255b7e150..783ab7bdb9 100644
--- a/cpp/include/qpid/log/Logger.h
+++ b/cpp/include/qpid/log/Logger.h
@@ -33,10 +33,10 @@ namespace log {
* is handled by Logger::Output-derived classes instantiated by the
* platform's sink-related options.
*/
-class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
+class Logger : private boost::noncopyable {
public:
/** Flags indicating what to include in the log output */
- enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32, HIRES=64};
+ enum FormatFlag { FILE=1, LINE=2, FUNCTION=4, LEVEL=8, TIME=16, THREAD=32};
/**
* Logging output sink.
@@ -93,7 +93,7 @@ class QPID_COMMON_CLASS_EXTERN Logger : private boost::noncopyable {
QPID_COMMON_EXTERN void clear();
/** Get the options used to configure the logger. */
- QPID_COMMON_INLINE_EXTERN const Options& getOptions() const { return options; }
+ QPID_COMMON_EXTERN const Options& getOptions() const { return options; }
private:
diff --git a/cpp/include/qpid/log/Options.h b/cpp/include/qpid/log/Options.h
index 17cbfde9bc..bbc47b47d3 100644
--- a/cpp/include/qpid/log/Options.h
+++ b/cpp/include/qpid/log/Options.h
@@ -39,7 +39,7 @@ struct Options : public qpid::Options {
std::string argv0;
std::string name;
std::vector<std::string> selectors;
- bool time, level, thread, source, function, hiresTs;
+ bool time, level, thread, source, function;
bool trace;
std::string prefix;
std::auto_ptr<SinkOptions> sinkOptions;
diff --git a/cpp/include/qpid/management/ManagementObject.h b/cpp/include/qpid/management/ManagementObject.h
index 16bf21038c..747edda150 100644
--- a/cpp/include/qpid/management/ManagementObject.h
+++ b/cpp/include/qpid/management/ManagementObject.h
@@ -58,14 +58,14 @@ protected:
std::string agentName;
void fromString(const std::string&);
public:
- QPID_COMMON_INLINE_EXTERN ObjectId() : agent(0), first(0), second(0), agentEpoch(0) {}
- QPID_COMMON_INLINE_EXTERN ObjectId(const types::Variant& map) :
+ QPID_COMMON_EXTERN ObjectId() : agent(0), first(0), second(0), agentEpoch(0) {}
+ QPID_COMMON_EXTERN ObjectId(const types::Variant& map) :
agent(0), first(0), second(0), agentEpoch(0) { mapDecode(map.asMap()); }
QPID_COMMON_EXTERN ObjectId(uint8_t flags, uint16_t seq, uint32_t broker);
QPID_COMMON_EXTERN ObjectId(AgentAttachment* _agent, uint8_t flags, uint16_t seq);
QPID_COMMON_EXTERN ObjectId(std::istream&);
QPID_COMMON_EXTERN ObjectId(const std::string&);
- QPID_COMMON_INLINE_EXTERN ObjectId(const std::string& agentAddress, const std::string& key,
+ QPID_COMMON_EXTERN ObjectId(const std::string& agentAddress, const std::string& key,
uint64_t epoch=0) : agent(0), first(0), second(0),
agentEpoch(epoch), v2Key(key), agentName(agentAddress) {}
@@ -76,15 +76,15 @@ public:
QPID_COMMON_EXTERN void mapEncode(types::Variant::Map& map) const;
QPID_COMMON_EXTERN void mapDecode(const types::Variant::Map& map);
QPID_COMMON_EXTERN operator types::Variant::Map() const;
- QPID_COMMON_INLINE_EXTERN uint32_t encodedSize() const { return 16; };
+ QPID_COMMON_EXTERN uint32_t encodedSize() const { return 16; };
QPID_COMMON_EXTERN void encode(std::string& buffer) const;
QPID_COMMON_EXTERN void decode(const std::string& buffer);
QPID_COMMON_EXTERN bool equalV1(const ObjectId &other) const;
- QPID_COMMON_INLINE_EXTERN void setV2Key(const std::string& _key) { v2Key = _key; }
+ QPID_COMMON_EXTERN void setV2Key(const std::string& _key) { v2Key = _key; }
QPID_COMMON_EXTERN void setV2Key(const ManagementObject& object);
- QPID_COMMON_INLINE_EXTERN void setAgentName(const std::string& _name) { agentName = _name; }
- QPID_COMMON_INLINE_EXTERN const std::string& getAgentName() const { return agentName; }
- QPID_COMMON_INLINE_EXTERN const std::string& getV2Key() const { return v2Key; }
+ QPID_COMMON_EXTERN void setAgentName(const std::string& _name) { agentName = _name; }
+ QPID_COMMON_EXTERN const std::string& getAgentName() const { return agentName; }
+ QPID_COMMON_EXTERN const std::string& getV2Key() const { return v2Key; }
friend QPID_COMMON_EXTERN std::ostream& operator<<(std::ostream&, const ObjectId&);
};
@@ -131,7 +131,7 @@ public:
virtual ~ManagementItem() {}
};
-class QPID_COMMON_CLASS_EXTERN ManagementObject : public ManagementItem
+class ManagementObject : public ManagementItem
{
protected:
diff --git a/cpp/include/qpid/messaging/Address.h b/cpp/include/qpid/messaging/Address.h
index 63dce0c49d..bebbfc72f6 100644
--- a/cpp/include/qpid/messaging/Address.h
+++ b/cpp/include/qpid/messaging/Address.h
@@ -119,7 +119,7 @@ class AddressImpl;
*
* An address has value semantics.
*/
-class QPID_MESSAGING_CLASS_EXTERN Address
+class Address
{
public:
QPID_MESSAGING_EXTERN Address();
diff --git a/cpp/include/qpid/messaging/Connection.h b/cpp/include/qpid/messaging/Connection.h
index 165573e2ef..1ad7a7242f 100644
--- a/cpp/include/qpid/messaging/Connection.h
+++ b/cpp/include/qpid/messaging/Connection.h
@@ -42,7 +42,7 @@ class Session;
* A connection represents a network connection to a remote endpoint.
*/
-class QPID_MESSAGING_CLASS_EXTERN Connection : public qpid::messaging::Handle<ConnectionImpl>
+class Connection : public qpid::messaging::Handle<ConnectionImpl>
{
public:
QPID_MESSAGING_EXTERN Connection(ConnectionImpl* impl);
@@ -54,27 +54,27 @@ class QPID_MESSAGING_CLASS_EXTERN Connection : public qpid::messaging::Handle<Co
* username
* password
* heartbeat
- * tcp_nodelay
- * sasl_mechanisms
- * sasl_service
- * sasl_min_ssf
- * sasl_max_ssf
+ * tcp-nodelay
+ * sasl-mechanism
+ * sasl-service
+ * sasl-min-ssf
+ * sasl-max-ssf
* transport
*
* Reconnect behaviour can be controlled through the following options:
*
* reconnect: true/false (enables/disables reconnect entirely)
- * reconnect_timeout: number of seconds (give up and report failure after specified time)
- * reconnect_limit: n (give up and report failure after specified number of attempts)
- * reconnect_interval_min: number of seconds (initial delay between failed reconnection attempts)
- * reconnect_interval_max: number of seconds (maximum delay between failed reconnection attempts)
- * reconnect_interval: shorthand for setting the same reconnect_interval_min/max
- * reconnect_urls: list of alternate urls to try when connecting
+ * reconnect-timeout: number of seconds (give up and report failure after specified time)
+ * reconnect-limit: n (give up and report failure after specified number of attempts)
+ * reconnect-interval-min: number of seconds (initial delay between failed reconnection attempts)
+ * reconnect-interval-max: number of seconds (maximum delay between failed reconnection attempts)
+ * reconnect-interval: shorthand for setting the same reconnect_interval_min/max
+ * reconnect-urls: list of alternate urls to try when connecting
*
- * The reconnect_interval is the time that the client waits
+ * The reconnect-interval is the time that the client waits
* for after a failed attempt to reconnect before retrying. It
- * starts at the value of the min_retry_interval and is
- * doubled every failure until the value of max_retry_interval
+ * starts at the value of the min-retry-interval and is
+ * doubled every failure until the value of max-retry-interval
* is reached.
*/
QPID_MESSAGING_EXTERN Connection(const std::string& url, const qpid::types::Variant::Map& options = qpid::types::Variant::Map());
diff --git a/cpp/include/qpid/messaging/Duration.h b/cpp/include/qpid/messaging/Duration.h
index 6b8f05c7c6..abcf169090 100644
--- a/cpp/include/qpid/messaging/Duration.h
+++ b/cpp/include/qpid/messaging/Duration.h
@@ -32,7 +32,7 @@ namespace messaging {
/** \ingroup messaging
* A duration is a time in milliseconds.
*/
-class QPID_MESSAGING_CLASS_EXTERN Duration
+class Duration
{
public:
QPID_MESSAGING_EXTERN explicit Duration(uint64_t milliseconds);
@@ -46,11 +46,9 @@ class QPID_MESSAGING_CLASS_EXTERN Duration
};
QPID_MESSAGING_EXTERN Duration operator*(const Duration& duration,
- uint64_t multiplier);
+ uint64_t multiplier);
QPID_MESSAGING_EXTERN Duration operator*(uint64_t multiplier,
- const Duration& duration);
-QPID_MESSAGING_EXTERN bool operator==(const Duration& a, const Duration& b);
-QPID_MESSAGING_EXTERN bool operator!=(const Duration& a, const Duration& b);
+ const Duration& duration);
}} // namespace qpid::messaging
diff --git a/cpp/include/qpid/messaging/FailoverUpdates.h b/cpp/include/qpid/messaging/FailoverUpdates.h
index 6d7314620a..14a1a31b63 100644
--- a/cpp/include/qpid/messaging/FailoverUpdates.h
+++ b/cpp/include/qpid/messaging/FailoverUpdates.h
@@ -32,7 +32,7 @@ struct FailoverUpdatesImpl;
* A utility to listen for updates on cluster membership and update
* the list of known urls for a connection accordingly.
*/
-class QPID_MESSAGING_CLASS_EXTERN FailoverUpdates
+class FailoverUpdates
{
public:
QPID_MESSAGING_EXTERN FailoverUpdates(Connection& connection);
diff --git a/cpp/include/qpid/messaging/Handle.h b/cpp/include/qpid/messaging/Handle.h
index 97a8f00b54..1e634ef888 100644
--- a/cpp/include/qpid/messaging/Handle.h
+++ b/cpp/include/qpid/messaging/Handle.h
@@ -40,22 +40,22 @@ template <class T> class Handle {
public:
/**@return true if handle is valid, i.e. not null. */
- QPID_MESSAGING_INLINE_EXTERN bool isValid() const { return impl; }
+ QPID_MESSAGING_EXTERN bool isValid() const { return impl; }
/**@return true if handle is null. It is an error to call any function on a null handle. */
- QPID_MESSAGING_INLINE_EXTERN bool isNull() const { return !impl; }
+ QPID_MESSAGING_EXTERN bool isNull() const { return !impl; }
/** Conversion to bool supports idiom if (handle) { handle->... } */
- QPID_MESSAGING_INLINE_EXTERN operator bool() const { return impl; }
+ QPID_MESSAGING_EXTERN operator bool() const { return impl; }
/** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
- QPID_MESSAGING_INLINE_EXTERN bool operator !() const { return !impl; }
+ QPID_MESSAGING_EXTERN bool operator !() const { return !impl; }
void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; }
protected:
typedef T Impl;
- QPID_MESSAGING_INLINE_EXTERN Handle() :impl() {}
+ QPID_MESSAGING_EXTERN Handle() :impl() {}
// Not implemented,subclasses must implement.
QPID_MESSAGING_EXTERN Handle(const Handle&);
diff --git a/cpp/include/qpid/messaging/ImportExport.h b/cpp/include/qpid/messaging/ImportExport.h
index ab5f21f618..52f3eb8568 100644
--- a/cpp/include/qpid/messaging/ImportExport.h
+++ b/cpp/include/qpid/messaging/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(CLIENT_EXPORT) || defined (qpidmessaging_EXPORTS)
-# define QPID_MESSAGING_EXTERN QPID_EXPORT
-# define QPID_MESSAGING_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_MESSAGING_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_MESSAGING_EXTERN __declspec(dllexport)
+#else
+#define QPID_MESSAGING_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_MESSAGING_EXTERN QPID_IMPORT
-# define QPID_MESSAGING_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_MESSAGING_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_MESSAGING_EXTERN
#endif
#endif /*!QPID_MESSAGING_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/messaging/Message.h b/cpp/include/qpid/messaging/Message.h
index e89a6ce02f..d48af35cc0 100644
--- a/cpp/include/qpid/messaging/Message.h
+++ b/cpp/include/qpid/messaging/Message.h
@@ -39,7 +39,7 @@ struct MessageImpl;
/** \ingroup messaging
* Representation of a message.
*/
-class QPID_MESSAGING_CLASS_EXTERN Message
+class Message
{
public:
QPID_MESSAGING_EXTERN Message(const std::string& bytes = std::string());
@@ -55,58 +55,23 @@ class QPID_MESSAGING_CLASS_EXTERN Message
QPID_MESSAGING_EXTERN void setSubject(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getSubject() const;
- /**
- * Set the content type (i.e. the MIME type) for the message. This
- * should be set by the sending application and indicates to
- * recipients of message how to interpret or decode the content.
- */
QPID_MESSAGING_EXTERN void setContentType(const std::string&);
- /**
- * Returns the content type (i.e. the MIME type) for the
- * message. This can be used to determine how to decode the
- * message content.
- */
QPID_MESSAGING_EXTERN const std::string& getContentType() const;
- /**
- * Set an application defined identifier for the message. At
- * present this must be a stringfied UUID (support for less
- * restrictive IDs is anticipated however).
- */
QPID_MESSAGING_EXTERN void setMessageId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getMessageId() const;
- /**
- * Sets the user id of the message. This should in general be the
- * user-id as which the sending connection authenticated itself as
- * the messaging infrastructure will verify this. See
- * Connection::getAuthenticatedUsername()
- */
QPID_MESSAGING_EXTERN void setUserId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getUserId() const;
- /**
- * Can be used to set application specific correlation identifiers
- * as part of a protocol for message exchange patterns. E.g. a
- * request-reponse pattern might require the correlation-id of the
- * request and response to match, or might use the message-id of
- * the request as the correlation-id on the response etc.
- */
QPID_MESSAGING_EXTERN void setCorrelationId(const std::string&);
QPID_MESSAGING_EXTERN const std::string& getCorrelationId() const;
- /**
- * Sets a priority level on the message. This may be used by the
- * messaging infrastructure to prioritise delivery of higher
- * priority messages.
- */
QPID_MESSAGING_EXTERN void setPriority(uint8_t);
QPID_MESSAGING_EXTERN uint8_t getPriority() const;
/**
- * Set the time to live for this message in milliseconds. This can
- * be used by the messaging infrastructure to discard messages
- * that are no longer of relevance.
+ * Set the time to live for this message in milliseconds.
*/
QPID_MESSAGING_EXTERN void setTtl(Duration ttl);
/**
@@ -114,62 +79,24 @@ class QPID_MESSAGING_CLASS_EXTERN Message
*/
QPID_MESSAGING_EXTERN Duration getTtl() const;
- /**
- * Mark the message as durable. This is a hint to the messaging
- * infrastructure that the message should be persisted or
- * otherwise stored such that failoures or shutdown do not cause
- * it to be lost.
- */
QPID_MESSAGING_EXTERN void setDurable(bool durable);
QPID_MESSAGING_EXTERN bool getDurable() const;
- /**
- * The redelivered flag if set implies that the message *may* have
- * been previously delivered and thus is a hint to the application
- * or messaging infrastructure that if de-duplication is required
- * this message should be examined to determine if it is a
- * duplicate.
- */
QPID_MESSAGING_EXTERN bool getRedelivered() const;
- /**
- * Can be used to provide a hint to the application or messaging
- * infrastructure that if de-duplication is required this message
- * should be examined to determine if it is a duplicate.
- */
QPID_MESSAGING_EXTERN void setRedelivered(bool);
- /**
- * In addition to a payload (i.e. the content), messages can
- * include annotations describing aspectf of the message. In
- * addition to the standard annotations such as TTL and content
- * type, application- or context- specific properties can also be
- * defined. Each message has a map of name values for such custom
- * properties. The value is specified as a Variant.
- */
QPID_MESSAGING_EXTERN const qpid::types::Variant::Map& getProperties() const;
QPID_MESSAGING_EXTERN qpid::types::Variant::Map& getProperties();
- /**
- * Set the content to the data held in the string parameter. Note:
- * this is treated as raw bytes and need not be text. Consider
- * setting the content-type to indicate how the data should be
- * interpreted by recipients.
- */
QPID_MESSAGING_EXTERN void setContent(const std::string&);
/**
- * Copy count bytes from the region pointed to by chars as the
- * message content.
+ * Note that chars are copied.
*/
QPID_MESSAGING_EXTERN void setContent(const char* chars, size_t count);
/** Get the content as a std::string */
QPID_MESSAGING_EXTERN std::string getContent() const;
- /**
- * Get a const pointer to the start of the content data. The
- * memory pointed to is owned by the message. The getContentSize()
- * method indicates how much data there is (i.e. the extent of the
- * memory region pointed to by the return value of this method).
- */
+ /** Get a const pointer to the start of the content data. */
QPID_MESSAGING_EXTERN const char* getContentPtr() const;
/** Get the size of content in bytes. */
QPID_MESSAGING_EXTERN size_t getContentSize() const;
@@ -180,9 +107,9 @@ class QPID_MESSAGING_CLASS_EXTERN Message
friend struct MessageImplAccess;
};
-struct QPID_MESSAGING_CLASS_EXTERN EncodingException : qpid::types::Exception
+struct EncodingException : qpid::types::Exception
{
- QPID_MESSAGING_EXTERN EncodingException(const std::string& msg);
+ EncodingException(const std::string& msg);
};
/**
@@ -195,8 +122,8 @@ struct QPID_MESSAGING_CLASS_EXTERN EncodingException : qpid::types::Exception
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void decode(const Message& message,
- qpid::types::Variant::Map& map,
- const std::string& encoding = std::string());
+ qpid::types::Variant::Map& map,
+ const std::string& encoding = std::string());
/**
* Decodes message content into a Variant::List.
*
@@ -207,8 +134,8 @@ QPID_MESSAGING_EXTERN void decode(const Message& message,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void decode(const Message& message,
- qpid::types::Variant::List& list,
- const std::string& encoding = std::string());
+ qpid::types::Variant::List& list,
+ const std::string& encoding = std::string());
/**
* Encodes a Variant::Map into a message.
*
@@ -219,8 +146,8 @@ QPID_MESSAGING_EXTERN void decode(const Message& message,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::Map& map,
- Message& message,
- const std::string& encoding = std::string());
+ Message& message,
+ const std::string& encoding = std::string());
/**
* Encodes a Variant::List into a message.
*
@@ -231,8 +158,8 @@ QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::Map& map,
* @exception EncodingException
*/
QPID_MESSAGING_EXTERN void encode(const qpid::types::Variant::List& list,
- Message& message,
- const std::string& encoding = std::string());
+ Message& message,
+ const std::string& encoding = std::string());
}} // namespace qpid::messaging
diff --git a/cpp/include/qpid/messaging/Receiver.h b/cpp/include/qpid/messaging/Receiver.h
index 13317dfcbd..6f3ae961db 100644
--- a/cpp/include/qpid/messaging/Receiver.h
+++ b/cpp/include/qpid/messaging/Receiver.h
@@ -41,7 +41,7 @@ class Session;
/** \ingroup messaging
* Interface through which messages are received.
*/
-class QPID_MESSAGING_CLASS_EXTERN Receiver : public qpid::messaging::Handle<ReceiverImpl>
+class Receiver : public qpid::messaging::Handle<ReceiverImpl>
{
public:
QPID_MESSAGING_EXTERN Receiver(ReceiverImpl* impl = 0);
diff --git a/cpp/include/qpid/messaging/Sender.h b/cpp/include/qpid/messaging/Sender.h
index 8e1c5846e9..85658f37cc 100644
--- a/cpp/include/qpid/messaging/Sender.h
+++ b/cpp/include/qpid/messaging/Sender.h
@@ -40,7 +40,7 @@ class Session;
/** \ingroup messaging
* Interface through which messages are sent.
*/
-class QPID_MESSAGING_CLASS_EXTERN Sender : public qpid::messaging::Handle<SenderImpl>
+class Sender : public qpid::messaging::Handle<SenderImpl>
{
public:
QPID_MESSAGING_EXTERN Sender(SenderImpl* impl = 0);
diff --git a/cpp/include/qpid/messaging/Session.h b/cpp/include/qpid/messaging/Session.h
index e8d6efb35d..6c023629e0 100644
--- a/cpp/include/qpid/messaging/Session.h
+++ b/cpp/include/qpid/messaging/Session.h
@@ -46,7 +46,7 @@ class SessionImpl;
* A session represents a distinct 'conversation' which can involve
* sending and receiving messages to and from different addresses.
*/
-class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<SessionImpl>
+class Session : public qpid::messaging::Handle<SessionImpl>
{
public:
QPID_MESSAGING_EXTERN Session(SessionImpl* impl = 0);
@@ -62,12 +62,6 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN void close();
- /**
- * Commits the sessions transaction.
- *
- * @exception TransactionAborted if the original session is lost
- * forcing an automatic rollback.
- */
QPID_MESSAGING_EXTERN void commit();
QPID_MESSAGING_EXTERN void rollback();
@@ -84,10 +78,6 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN void acknowledge(Message&, bool sync=false);
/**
- * Acknowledges all message up to the specified message.
- */
- QPID_MESSAGING_EXTERN void acknowledgeUpTo(Message&, bool sync=false);
- /**
* Rejects the specified message. The broker does not redeliver a
* message that has been rejected. Once a message has been
* acknowledged, it can no longer be rejected.
@@ -145,51 +135,25 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
/**
* Create a new sender through which messages can be sent to the
* specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
*/
QPID_MESSAGING_EXTERN Sender createSender(const Address& address);
- /**
- * Create a new sender through which messages can be sent to the
- * specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
- *
- * @exception MalformedAddress if the syntax of address is not
- * valid
- */
QPID_MESSAGING_EXTERN Sender createSender(const std::string& address);
/**
* Create a new receiver through which messages can be received
* from the specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
*/
QPID_MESSAGING_EXTERN Receiver createReceiver(const Address& address);
- /**
- * Create a new receiver through which messages can be received
- * from the specified address.
- *
- * @exception ResolutionError if there is an error in resolving
- * the address
- *
- * @exception MalformedAddress if the syntax of address is not
- * valid
- */
QPID_MESSAGING_EXTERN Receiver createReceiver(const std::string& address);
/**
* Returns the sender with the specified name.
- * @exception KeyError if there is none for that name.
+ *@exception KeyError if there is none for that name.
*/
QPID_MESSAGING_EXTERN Sender getSender(const std::string& name) const;
/**
* Returns the receiver with the specified name.
- * @exception KeyError if there is none for that name.
+ *@exception KeyError if there is none for that name.
*/
QPID_MESSAGING_EXTERN Receiver getReceiver(const std::string& name) const;
/**
@@ -198,16 +162,7 @@ class QPID_MESSAGING_CLASS_EXTERN Session : public qpid::messaging::Handle<Sessi
*/
QPID_MESSAGING_EXTERN Connection getConnection() const;
- /**
- * @returns true if the session has been rendered invalid by some
- * exception, false if it is valid for use.
- */
QPID_MESSAGING_EXTERN bool hasError();
- /**
- * If the session has been rendered invalid by some exception,
- * this method will result in that exception being thrown on
- * calling this method.
- */
QPID_MESSAGING_EXTERN void checkError();
#ifndef SWIG
diff --git a/cpp/include/qpid/messaging/exceptions.h b/cpp/include/qpid/messaging/exceptions.h
index 31e2488d91..0ff608b343 100644
--- a/cpp/include/qpid/messaging/exceptions.h
+++ b/cpp/include/qpid/messaging/exceptions.h
@@ -10,9 +10,9 @@
* 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
@@ -29,47 +29,34 @@
namespace qpid {
namespace messaging {
-/** \ingroup messaging
+/** \ingroup messaging
*/
-/**
- * This is the base class for all messaging related exceptions thrown
- * by this API.
- */
-struct QPID_MESSAGING_CLASS_EXTERN MessagingException : public qpid::types::Exception
+struct MessagingException : public qpid::types::Exception
{
QPID_MESSAGING_EXTERN MessagingException(const std::string& msg);
QPID_MESSAGING_EXTERN virtual ~MessagingException() throw();
-
+
qpid::types::Variant::Map detail;
//TODO: override what() to include detail if present
};
-/**
- * Thrown when the syntax of the option string used to configure a
- * connection in not valid
- */
-struct QPID_MESSAGING_CLASS_EXTERN InvalidOptionString : public MessagingException
+struct InvalidOptionString : public MessagingException
{
QPID_MESSAGING_EXTERN InvalidOptionString(const std::string& msg);
};
-/**
- * Thrown to indicate a failed lookup of some local object. For
- * example when attempting to retrieve a session, sender or receiver
- * by name.
- */
-struct QPID_MESSAGING_CLASS_EXTERN KeyError : public MessagingException
+struct KeyError : public MessagingException
{
QPID_MESSAGING_EXTERN KeyError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN LinkError : public MessagingException
+struct LinkError : public MessagingException
{
QPID_MESSAGING_EXTERN LinkError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN AddressError : public LinkError
+struct AddressError : public LinkError
{
QPID_MESSAGING_EXTERN AddressError(const std::string&);
};
@@ -78,118 +65,85 @@ struct QPID_MESSAGING_CLASS_EXTERN AddressError : public LinkError
* Thrown when a syntactically correct address cannot be resolved or
* used.
*/
-struct QPID_MESSAGING_CLASS_EXTERN ResolutionError : public AddressError
+struct ResolutionError : public AddressError
{
QPID_MESSAGING_EXTERN ResolutionError(const std::string& msg);
};
-/**
- * Thrown when creating a sender or receiver for an address for which
- * some asserted property of the node is not matched.
- */
-struct QPID_MESSAGING_CLASS_EXTERN AssertionFailed : public ResolutionError
+struct AssertionFailed : public ResolutionError
{
QPID_MESSAGING_EXTERN AssertionFailed(const std::string& msg);
};
-/**
- * Thrown on attempts to create a sender or receiver to a non-existent
- * node.
- */
-struct QPID_MESSAGING_CLASS_EXTERN NotFound : public ResolutionError
+struct NotFound : public ResolutionError
{
QPID_MESSAGING_EXTERN NotFound(const std::string& msg);
};
/**
- * Thrown when an address string with invalid syntax is used.
+ * Thrown when an address string with inalid sytanx is used.
*/
-struct QPID_MESSAGING_CLASS_EXTERN MalformedAddress : public AddressError
+struct MalformedAddress : public AddressError
{
QPID_MESSAGING_EXTERN MalformedAddress(const std::string& msg);
};
-struct QPID_MESSAGING_CLASS_EXTERN ReceiverError : public LinkError
+struct ReceiverError : public LinkError
{
QPID_MESSAGING_EXTERN ReceiverError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN FetchError : public ReceiverError
+struct FetchError : public ReceiverError
{
QPID_MESSAGING_EXTERN FetchError(const std::string&);
};
-/**
- * Thrown by Receiver::fetch(), Receiver::get() and
- * Session::nextReceiver() to indicate that there no message was
- * available before the timeout specified.
- */
-struct QPID_MESSAGING_CLASS_EXTERN NoMessageAvailable : public FetchError
+struct NoMessageAvailable : public FetchError
{
QPID_MESSAGING_EXTERN NoMessageAvailable();
};
-struct QPID_MESSAGING_CLASS_EXTERN SenderError : public LinkError
+struct SenderError : public LinkError
{
QPID_MESSAGING_EXTERN SenderError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN SendError : public SenderError
+struct SendError : public SenderError
{
QPID_MESSAGING_EXTERN SendError(const std::string&);
};
-/**
- * Thrown to indicate that the sender attempted to send a message that
- * would result in the target node on the peer exceeding a
- * preconfigured capacity.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TargetCapacityExceeded : public SendError
+struct TargetCapacityExceeded : public SendError
{
QPID_MESSAGING_EXTERN TargetCapacityExceeded(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN SessionError : public MessagingException
+struct SessionError : public MessagingException
{
QPID_MESSAGING_EXTERN SessionError(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN TransactionError : public SessionError
+struct TransactionError : public SessionError
{
QPID_MESSAGING_EXTERN TransactionError(const std::string&);
};
-/**
- * Thrown on Session::commit() if reconnection results in the
- * transaction being automatically aborted.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TransactionAborted : public TransactionError
+struct TransactionAborted : public TransactionError
{
QPID_MESSAGING_EXTERN TransactionAborted(const std::string&);
};
-/**
- * Thrown to indicate that the application attempted to do something
- * for which it was not authorised by its peer.
- */
-struct QPID_MESSAGING_CLASS_EXTERN UnauthorizedAccess : public SessionError
+struct UnauthorizedAccess : public SessionError
{
QPID_MESSAGING_EXTERN UnauthorizedAccess(const std::string&);
};
-struct QPID_MESSAGING_CLASS_EXTERN ConnectionError : public MessagingException
+struct ConnectionError : public MessagingException
{
QPID_MESSAGING_EXTERN ConnectionError(const std::string&);
};
-/**
- * Thrown to indicate loss of underlying connection. When
- * auto-reconnect is used this will be caught by the library and used
- * to trigger reconnection attempts. If reconnection fails (according
- * to whatever settings have been configured), then an instnace of
- * this class will be thrown to signal that.
- */
-struct QPID_MESSAGING_CLASS_EXTERN TransportFailure : public MessagingException
+struct TransportFailure : public MessagingException
{
QPID_MESSAGING_EXTERN TransportFailure(const std::string&);
};
diff --git a/cpp/include/qpid/sys/ExceptionHolder.h b/cpp/include/qpid/sys/ExceptionHolder.h
index 4bc934cf75..9eff1d64c7 100644
--- a/cpp/include/qpid/sys/ExceptionHolder.h
+++ b/cpp/include/qpid/sys/ExceptionHolder.h
@@ -10,9 +10,9 @@
* 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
@@ -42,11 +42,14 @@ class ExceptionHolder : public Raisable {
public:
ExceptionHolder() {}
// Use default copy & assign.
-
+
/** Take ownership of ex */
template <class Ex> ExceptionHolder(Ex* ex) { wrap(ex); }
- template <class Ex> ExceptionHolder& operator=(Ex* ex) { wrap(ex); return *this; }
+ template <class Ex> ExceptionHolder(const boost::shared_ptr<Ex>& ex) { wrap(ex.release()); }
+ template <class Ex> ExceptionHolder& operator=(Ex* ex) { wrap(ex); return *this; }
+ template <class Ex> ExceptionHolder& operator=(boost::shared_ptr<Ex> ex) { wrap(ex.release()); return *this; }
+
void raise() const { if (wrapper.get()) wrapper->raise() ; }
std::string what() const { return wrapper.get() ? wrapper->what() : std::string(); }
bool empty() const { return !wrapper.get(); }
@@ -63,7 +66,7 @@ class ExceptionHolder : public Raisable {
template <class Ex> void wrap(Ex* ex) { wrapper.reset(new Wrapper<Ex>(ex)); }
boost::shared_ptr<Raisable> wrapper;
};
-
+
}} // namespace qpid::sys
diff --git a/cpp/include/qpid/sys/IntegerTypes.h b/cpp/include/qpid/sys/IntegerTypes.h
index 75fa921de0..89635f033e 100755
--- a/cpp/include/qpid/sys/IntegerTypes.h
+++ b/cpp/include/qpid/sys/IntegerTypes.h
@@ -21,7 +21,7 @@
*
*/
-#if (defined(_WINDOWS) || defined (WIN32))
+#if (defined(_WINDOWS) || defined (WIN32)) && defined(_MSC_VER)
#include "qpid/sys/windows/IntegerTypes.h"
#endif
#if !defined _WINDOWS && !defined WIN32
diff --git a/cpp/include/qpid/sys/Runnable.h b/cpp/include/qpid/sys/Runnable.h
index fed7663cb6..0f1243a277 100644
--- a/cpp/include/qpid/sys/Runnable.h
+++ b/cpp/include/qpid/sys/Runnable.h
@@ -30,7 +30,7 @@ namespace sys {
/**
* Interface for objects that can be run, e.g. in a thread.
*/
-class QPID_COMMON_CLASS_EXTERN Runnable
+class Runnable
{
public:
/** Type to represent a runnable as a Functor */
diff --git a/cpp/include/qpid/sys/Thread.h b/cpp/include/qpid/sys/Thread.h
index f556612908..45a39e796f 100644
--- a/cpp/include/qpid/sys/Thread.h
+++ b/cpp/include/qpid/sys/Thread.h
@@ -25,11 +25,7 @@
#include "qpid/CommonImportExport.h"
#ifdef _WIN32
-# ifdef _MSC_VER
-# define QPID_TSS __declspec(thread)
-# else
-# define QPID_TSS __thread
-# endif
+# define QPID_TSS __declspec(thread)
#elif defined (__GNUC__)
# define QPID_TSS __thread
#elif defined (__SUNPRO_CC)
diff --git a/cpp/include/qpid/sys/Time.h b/cpp/include/qpid/sys/Time.h
index 9c5ac66e9a..d3ab832229 100644
--- a/cpp/include/qpid/sys/Time.h
+++ b/cpp/include/qpid/sys/Time.h
@@ -119,7 +119,7 @@ class Duration {
friend class AbsTime;
public:
- QPID_COMMON_INLINE_EXTERN inline Duration(int64_t time0 = 0);
+ QPID_COMMON_EXTERN inline Duration(int64_t time0 = 0);
QPID_COMMON_EXTERN explicit Duration(const AbsTime& start, const AbsTime& finish);
inline operator int64_t() const;
};
@@ -167,9 +167,6 @@ QPID_COMMON_EXTERN void usleep(uint64_t usecs);
/** Output formatted date/time for now*/
void outputFormattedNow(std::ostream&);
-/** Output unformatted nanosecond-resolution time for now */
-void outputHiresNow(std::ostream&);
-
}}
#endif /*!_sys_Time_h*/
diff --git a/cpp/include/qpid/sys/windows/IntegerTypes.h b/cpp/include/qpid/sys/windows/IntegerTypes.h
index 28b82da1a0..ece1a618e9 100755
--- a/cpp/include/qpid/sys/windows/IntegerTypes.h
+++ b/cpp/include/qpid/sys/windows/IntegerTypes.h
@@ -22,17 +22,13 @@
*/
typedef unsigned char uint8_t;
+typedef char int8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned int uint32_t;
typedef int int32_t;
-#if defined(_MSC_VER)
-typedef signed char int8_t;
typedef unsigned __int64 uint64_t;
typedef __int64 int64_t;
-#else
-#include <stdint.h>
-#endif
// Visual Studio doesn't define other common types, so set them up here too.
typedef unsigned int uint;
diff --git a/cpp/include/qpid/types/Exception.h b/cpp/include/qpid/types/Exception.h
index 483d104cc8..d061a7df0e 100644
--- a/cpp/include/qpid/types/Exception.h
+++ b/cpp/include/qpid/types/Exception.h
@@ -28,7 +28,7 @@
namespace qpid {
namespace types {
-class QPID_TYPES_CLASS_EXTERN Exception : public std::exception
+class Exception : public std::exception
{
public:
QPID_TYPES_EXTERN explicit Exception(const std::string& message=std::string()) throw();
diff --git a/cpp/include/qpid/types/ImportExport.h b/cpp/include/qpid/types/ImportExport.h
index 8fa41884fb..bb10575fcd 100644
--- a/cpp/include/qpid/types/ImportExport.h
+++ b/cpp/include/qpid/types/ImportExport.h
@@ -20,16 +20,14 @@
* under the License.
*/
-#include "qpid/ImportExport.h"
-
+#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
#if defined(TYPES_EXPORT) || defined (qpidtypes_EXPORTS)
-# define QPID_TYPES_EXTERN QPID_EXPORT
-# define QPID_TYPES_CLASS_EXTERN QPID_CLASS_EXPORT
-# define QPID_TYPES_INLINE_EXTERN QPID_INLINE_EXPORT
+#define QPID_TYPES_EXTERN __declspec(dllexport)
+#else
+#define QPID_TYPES_EXTERN __declspec(dllimport)
+#endif
#else
-# define QPID_TYPES_EXTERN QPID_IMPORT
-# define QPID_TYPES_CLASS_EXTERN QPID_CLASS_IMPORT
-# define QPID_TYPES_INLINE_EXTERN QPID_INLINE_IMPORT
+#define QPID_TYPES_EXTERN
#endif
#endif /*!QPID_TYPES_IMPORTEXPORT_H*/
diff --git a/cpp/include/qpid/types/Uuid.h b/cpp/include/qpid/types/Uuid.h
index 02af4c7e7f..467a895184 100644
--- a/cpp/include/qpid/types/Uuid.h
+++ b/cpp/include/qpid/types/Uuid.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace types {
-class QPID_TYPES_CLASS_EXTERN Uuid
+class Uuid
{
public:
static const size_t SIZE;
diff --git a/cpp/include/qpid/types/Variant.h b/cpp/include/qpid/types/Variant.h
index 4459fc4123..9ae672b7c2 100644
--- a/cpp/include/qpid/types/Variant.h
+++ b/cpp/include/qpid/types/Variant.h
@@ -36,7 +36,7 @@ namespace types {
/**
* Thrown when an illegal conversion of a variant is attempted.
*/
-struct QPID_TYPES_CLASS_EXTERN InvalidConversion : public Exception
+struct InvalidConversion : public Exception
{
InvalidConversion(const std::string& msg);
};
@@ -60,14 +60,12 @@ enum VariantType {
VAR_UUID
};
-std::string getTypeName(VariantType type);
-
class VariantImpl;
/**
* Represents a value of variable type.
*/
-class QPID_TYPES_CLASS_EXTERN Variant
+class Variant
{
public:
typedef std::map<std::string, Variant> Map;
diff --git a/cpp/managementgen/Makefile.am b/cpp/managementgen/Makefile.am
index 4fc5edcad4..6c2024ccaa 100644
--- a/cpp/managementgen/Makefile.am
+++ b/cpp/managementgen/Makefile.am
@@ -19,26 +19,20 @@
qmfpythondir = $(pythondir)
dist_bin_SCRIPTS = \
qmf-gen
-
-pkgpyexec_qmfgendir = $(pyexecdir)/qmfgen
-pkgpyexec_qmfgen_PYTHON = \
+nobase_qmfpython_DATA = \
qmfgen/__init__.py \
qmfgen/generate.py \
qmfgen/schema.py \
- qmfgen/management-types.xml
-
-pkgpyexec_qmfgentmpldir = $(pyexecdir)/qmfgen/templates
-pkgpyexec_qmfgentmpl_PYTHON = \
qmfgen/templates/Args.h \
qmfgen/templates/Class.cpp \
qmfgen/templates/Class.h \
- qmfgen/templates/CMakeLists.cmake \
qmfgen/templates/Event.cpp \
qmfgen/templates/Event.h \
qmfgen/templates/Makefile.mk \
qmfgen/templates/Package.cpp \
qmfgen/templates/Package.h \
qmfgen/templates/V2Package.cpp \
- qmfgen/templates/V2Package.h
+ qmfgen/templates/V2Package.h \
+ qmfgen/management-types.xml
EXTRA_DIST = $(nobase_qmfpython_DATA) CMakeLists.txt
diff --git a/cpp/managementgen/qmfgen/schema.py b/cpp/managementgen/qmfgen/schema.py
index 59e951fb6e..afdfe42639 100755
--- a/cpp/managementgen/qmfgen/schema.py
+++ b/cpp/managementgen/qmfgen/schema.py
@@ -1731,9 +1731,9 @@ class SchemaPackage:
stream.write(" qmf::SchemaProperty arg(\"%s\", %s);\n" % (arg.name, typeName))
if subType:
stream.write(" arg.setSubtype(\"%s\");\n" % subType)
- if arg.unit:
+ if stat.unit:
stream.write(" arg.setUnit(\"%s\");\n" % arg.unit)
- if arg.desc:
+ if stat.desc:
stream.write(" arg.setDesc(\"%s\");\n" % arg.desc)
stream.write(" arg.setDirection(%s);\n" % self.qmfv2Dir(arg.dir))
stream.write(" method.addArgument(arg);\n")
diff --git a/cpp/rubygen/0-10/specification.rb b/cpp/rubygen/0-10/specification.rb
index ef193f5fd0..7366599eba 100755
--- a/cpp/rubygen/0-10/specification.rb
+++ b/cpp/rubygen/0-10/specification.rb
@@ -252,7 +252,7 @@ class Specification < CppGen
include "#{@dir}/specification"
namespace(@ns) {
genl "template <class F, class R=typename F::result_type>"
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", "ProxyTemplate") {
+ cpp_class("ProxyTemplate") {
public
genl "ProxyTemplate(F f=F()) : functor(f) {}"
@amqp.classes.each { |c|
diff --git a/cpp/rubygen/MethodBodyDefaultVisitor.rb b/cpp/rubygen/MethodBodyDefaultVisitor.rb
index 11dbcb8f83..4f9b369117 100755
--- a/cpp/rubygen/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/MethodBodyDefaultVisitor.rb
@@ -33,7 +33,7 @@ class MethodBodyDefaultVisitorGen < CppGen
include "qpid/framing/MethodBodyConstVisitor"
namespace(@namespace) {
genl
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") {
+ cpp_class(@classname, "public MethodBodyConstVisitor") {
genl "public:"
genl "virtual void defaultVisit() = 0;"
@amqp.methods_.each { |m|
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index 88720cad5f..69e65a4056 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -61,8 +61,7 @@ end
class Module
# Add trailing _ to avoid conflict with Object methods.
def mangle(sym)
- sym = (sym.to_s+"_").to_sym if (Object.method_defined?(sym) or sym == :type)
- sym
+ (Object.method_defined? sym) ? (sym.to_s+"_").intern : sym
end
# Add attribute reader for XML attribute.
@@ -191,8 +190,7 @@ class AmqpElement
"command-fragments" => "session.command-fragment",
"in-doubt" => "dtx.xid",
"tx-publish" => "str-8",
- "queues" => "str-8",
- "prepared" => "str-8"
+ "queues" => "str-8"
}
def array_type(name)
diff --git a/cpp/rubygen/cppgen.rb b/cpp/rubygen/cppgen.rb
index 7dc21fe1bc..f0995105f1 100755
--- a/cpp/rubygen/cppgen.rb
+++ b/cpp/rubygen/cppgen.rb
@@ -377,9 +377,6 @@ class CppGen < Generator
def cpp_class(name, *bases, &block)
struct_class("class", name, bases, &block);
end
- def cpp_extern_class(scope, name, *bases, &block)
- struct_class("class "+scope, name, bases, &block);
- end
def typedef(type, name) genl "typedef #{type} #{name};\n"; end
diff --git a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
index 4c58ff2bbb..00962de4f9 100755
--- a/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
+++ b/cpp/rubygen/framing.0-10/MethodBodyDefaultVisitor.rb
@@ -33,7 +33,7 @@ class MethodBodyDefaultVisitorGen < CppGen
include "qpid/CommonImportExport.h"
namespace(@namespace) {
genl "class AMQMethodBody;"
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public MethodBodyConstVisitor") {
+ cpp_class(@classname, "public MethodBodyConstVisitor") {
genl "public:"
genl "virtual void defaultVisit(const AMQMethodBody&) = 0;"
@amqp.methods_.each { |m|
diff --git a/cpp/rubygen/framing.0-10/OperationsInvoker.rb b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
index f9b5ce58d8..f9b6cac76b 100755
--- a/cpp/rubygen/framing.0-10/OperationsInvoker.rb
+++ b/cpp/rubygen/framing.0-10/OperationsInvoker.rb
@@ -69,7 +69,7 @@ class OperationsInvokerGen < CppGen
def invoker_h(invoker, target, methods)
return if methods.empty?
genl
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", invoker, "public qpid::framing::Invoker") {
+ cpp_class(invoker, "public qpid::framing::Invoker") {
genl "#{target}& target;"
public
genl("Invoker(#{target}& target_) : target(target_) {}")
diff --git a/cpp/rubygen/framing.0-10/Proxy.rb b/cpp/rubygen/framing.0-10/Proxy.rb
index 3325616754..6e3cb4fd4d 100755
--- a/cpp/rubygen/framing.0-10/Proxy.rb
+++ b/cpp/rubygen/framing.0-10/Proxy.rb
@@ -37,7 +37,7 @@ class ProxyGen < CppGen
def inner_class_decl(c)
cname=c.name.caps
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", cname, "public Proxy") {
+ cpp_class(cname, "public Proxy") {
gen <<EOS
public:
#{cname}(FrameHandler& f) : Proxy(f) {}
@@ -69,7 +69,7 @@ EOS
include "qpid/CommonImportExport.h"
namespace("qpid::framing") {
- cpp_extern_class("QPID_COMMON_CLASS_EXTERN", @classname, "public Proxy") {
+ cpp_class(@classname, "public Proxy") {
public
genl "QPID_COMMON_EXTERN #{@classname}(FrameHandler& out);"
genl
diff --git a/cpp/rubygen/framing.0-10/Session.rb b/cpp/rubygen/framing.0-10/Session.rb
index e800df9b2e..61f0e03a8b 100755
--- a/cpp/rubygen/framing.0-10/Session.rb
+++ b/cpp/rubygen/framing.0-10/Session.rb
@@ -56,8 +56,8 @@ module SyncAsync
def decl_ctor_opeq()
genl
genl "QPID_CLIENT_EXTERN #{@classname}();"
- genl "QPID_CLIENT_INLINE_EXTERN #{@classname}(const #{@version_base}& other);"
- genl "QPID_CLIENT_INLINE_EXTERN #{@classname}& operator=(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}(const #{@version_base}& other);"
+ genl "QPID_CLIENT_EXTERN #{@classname}& operator=(const #{@version_base}& other);"
end
def defn_ctor_opeq(inline="")
diff --git a/cpp/rubygen/framing.0-10/structs.rb b/cpp/rubygen/framing.0-10/structs.rb
index 62b33ce773..c3684aea66 100755
--- a/cpp/rubygen/framing.0-10/structs.rb
+++ b/cpp/rubygen/framing.0-10/structs.rb
@@ -406,7 +406,7 @@ EOS
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN #{classname} #{inheritance} {
+class #{classname} #{inheritance} {
EOS
if (is_packed(s))
indent { s.fields.each { |f| genl "#{f.cpptype.name} #{f.cppname};" unless f.type_ == "bit"} }
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 0dbcf8e2e6..60f505a10e 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -96,7 +96,7 @@ MACRO (add_msvc_version_full verProject verProjectType verProjectFileExt verFN1
inherit_value ("winver_${verProject}_InternalName" "${verProject}")
inherit_value ("winver_${verProject}_OriginalFilename" "${verProject}.${verProjectFileExt}")
inherit_value ("winver_${verProject}_ProductName" "${winver_DESCRIPTION_SUMMARY}")
-
+
# Create strings to be substituted into the template file
set ("winverFileVersionBinary" "${winver_${verProject}_FileVersionBinary}")
set ("winverProductVersionBinary" "${winver_${verProject}_ProductVersionBinary}")
@@ -126,7 +126,7 @@ ENDMACRO (add_msvc_version_full)
#
MACRO (add_msvc_version verProject verProjectType verProjectFileExt)
if (MSVC)
- add_msvc_version_full (${verProject}
+ add_msvc_version_full (${verProject}
${verProjectType}
${verProjectFileExt}
${winver_FILE_VERSION_N1}
@@ -313,6 +313,10 @@ if (NOT Boost_FILESYSTEM_LIBRARY)
set(Boost_FILESYSTEM_LIBRARY boost_filesystem)
endif (NOT Boost_FILESYSTEM_LIBRARY)
+if (NOT Boost_SYSTEM_LIBRARY)
+ set(Boost_SYSTEM_LIBRARY boost_system)
+endif (NOT Boost_SYSTEM_LIBRARY)
+
if (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY boost_unit_test_framework)
endif (NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
@@ -580,15 +584,6 @@ include (ssl.cmake)
check_symbol_exists (LOG_AUTHPRIV "sys/syslog.h" HAVE_LOG_AUTHPRIV)
check_symbol_exists (LOG_FTP "sys/syslog.h" HAVE_LOG_FTP)
-# Allow MSVC user to select 'WinXP-SP3/Windows Server 2003' as build target version
-set (win32_winnt_default OFF)
-if (CMAKE_SYSTEM_NAME STREQUAL Windows)
- if (MSVC)
- set (win32_winnt_default ON)
- endif (MSVC)
-endif (CMAKE_SYSTEM_NAME STREQUAL Windows)
-option(SET_WIN32_WINNT "In Windows-MSVC build: define _WIN32_WINNT=0x0502 to select target version: Windows XP with SP3" ${win32_winnt_default})
-
if (CMAKE_SYSTEM_NAME STREQUAL Windows)
if (MSVC)
add_definitions(
@@ -598,11 +593,10 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
/wd4244
/wd4800
/wd4355
- /wd4267
)
- if (SET_WIN32_WINNT)
- add_definitions(/D "_WIN32_WINNT=0x0502")
- endif (SET_WIN32_WINNT)
+ if (MSVC80)
+ add_definitions(/D "_WIN32_WINNT=0x0501")
+ endif (MSVC80)
# set the RelWithDebInfo compile/link switches to equal Release
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /O2 /Ob2 /D NDEBUG")
@@ -634,7 +628,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
qpid/sys/windows/LockFile.cpp
qpid/sys/windows/PipeHandle.cpp
qpid/sys/windows/PollableCondition.cpp
- qpid/sys/windows/SCM.cpp
qpid/sys/windows/Shlib.cpp
qpid/sys/windows/Socket.cpp
qpid/sys/windows/SocketAddress.cpp
@@ -647,7 +640,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
)
set (qpidcommon_platform_LIBS
- ${Boost_THREAD_LIBRARY} ${windows_ssl_libs} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_DATE_TIME_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ws2_32 )
+ ${windows_ssl_libs} ws2_32
+ )
set (qpidbroker_platform_SOURCES
qpid/broker/windows/BrokerDefaults.cpp
qpid/broker/windows/SaslAuthenticator.cpp
@@ -666,8 +660,9 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
set (qpidd_platform_SOURCES
windows/QpiddBroker.cpp
+ windows/SCM.cpp
)
-
+
set (qpidmessaging_platform_SOURCES
qpid/messaging/HandleInstantiator.cpp
)
@@ -925,6 +920,8 @@ set (qpidmessaging_SOURCES
qpid/client/amqp0_10/SessionImpl.cpp
qpid/client/amqp0_10/SenderImpl.h
qpid/client/amqp0_10/SenderImpl.cpp
+ qpid/client/amqp0_10/SimpleUrlParser.h
+ qpid/client/amqp0_10/SimpleUrlParser.cpp
)
add_msvc_version (qpidmessaging library dll)
@@ -946,7 +943,7 @@ if (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
endif (NOT QPID_GENERATED_HEADERS_IN_SOURCE)
-if (MSVC)
+if (WIN32)
# Install the DtcPlugin project and call it qpidxarm.
set(AMQP_WCF_DIR ${qpid-cpp_SOURCE_DIR}/../wcf)
set(qpidxarm_SOURCES ${AMQP_WCF_DIR}/src/Apache/Qpid/DtcPlugin/DtcPlugin.cpp)
@@ -959,7 +956,7 @@ if (MSVC)
COMPONENT ${QPID_COMPONENT_CLIENT})
install_pdb (qpidxarm ${QPID_COMPONENT_CLIENT})
endif (EXISTS ${qpidxarm_SOURCES})
-endif (MSVC)
+endif (WIN32)
set (qpidbroker_SOURCES
${mgen_broker_cpp}
@@ -977,8 +974,6 @@ set (qpidbroker_SOURCES
qpid/broker/Queue.cpp
qpid/broker/QueueCleaner.cpp
qpid/broker/QueueListeners.cpp
- qpid/broker/FifoDistributor.cpp
- qpid/broker/MessageGroupManager.cpp
qpid/broker/PersistableMessage.cpp
qpid/broker/Bridge.cpp
qpid/broker/Connection.cpp
@@ -995,6 +990,7 @@ set (qpidbroker_SOURCES
qpid/broker/ExchangeRegistry.cpp
qpid/broker/FanOutExchange.cpp
qpid/broker/HeadersExchange.cpp
+ qpid/broker/IncompleteMessageList.cpp
qpid/broker/Link.cpp
qpid/broker/LinkRegistry.cpp
qpid/broker/Message.cpp
@@ -1007,7 +1003,7 @@ set (qpidbroker_SOURCES
qpid/broker/QueueEvents.cpp
qpid/broker/QueuePolicy.cpp
qpid/broker/QueueRegistry.cpp
- qpid/broker/QueueFlowLimit.cpp
+ qpid/broker/RateTracker.cpp
qpid/broker/RecoveryManagerImpl.cpp
qpid/broker/RecoveredEnqueue.cpp
qpid/broker/RecoveredDequeue.cpp
@@ -1073,15 +1069,13 @@ endif (CPACK_GENERATOR STREQUAL "NSIS")
# REVISION => Version of underlying implementation.
# Bump if implementation changes but API/ABI doesn't
# AGE => Number of API/ABI versions this is backward compatible with
-set (qmf_version 2.0.0)
-set (qmf2_version 1.0.0)
+set (qmf_version 1.0.0)
set (qmfengine_version 1.0.0)
set (qmf_SOURCES
qpid/agent/ManagementAgentImpl.cpp
qpid/agent/ManagementAgentImpl.h
)
-
add_msvc_version (qmf library dll)
add_library (qmf SHARED ${qmf_SOURCES})
target_link_libraries (qmf qpidclient)
@@ -1092,88 +1086,6 @@ install (TARGETS qmf OPTIONAL
COMPONENT ${QPID_COMPONENT_QMF})
install_pdb (qmf ${QPID_COMPONENT_QMF})
-if(NOT WIN32)
- set (qmf2_HEADERS
- ../include/qmf/AgentEvent.h
- ../include/qmf/Agent.h
- ../include/qmf/AgentSession.h
- ../include/qmf/ConsoleEvent.h
- ../include/qmf/ConsoleSession.h
- ../include/qmf/DataAddr.h
- ../include/qmf/Data.h
- ../include/qmf/exceptions.h
- ../include/qmf/Handle.h
- ../include/qmf/ImportExport.h
- ../include/qmf/posix/EventNotifier.h
- ../include/qmf/Query.h
- ../include/qmf/Schema.h
- ../include/qmf/SchemaId.h
- ../include/qmf/SchemaMethod.h
- ../include/qmf/SchemaProperty.h
- ../include/qmf/SchemaTypes.h
- ../include/qmf/Subscription.h
- )
-
- set (qmf2_SOURCES
- ${qmf2_HEADERS}
- qmf/agentCapability.h
- qmf/Agent.cpp
- qmf/AgentEvent.cpp
- qmf/AgentEventImpl.h
- qmf/AgentImpl.h
- qmf/AgentSession.cpp
- qmf/AgentSubscription.cpp
- qmf/AgentSubscription.h
- qmf/ConsoleEvent.cpp
- qmf/ConsoleEventImpl.h
- qmf/ConsoleSession.cpp
- qmf/ConsoleSessionImpl.h
- qmf/constants.cpp
- qmf/constants.h
- qmf/DataAddr.cpp
- qmf/DataAddrImpl.h
- qmf/Data.cpp
- qmf/DataImpl.h
- qmf/EventNotifierImpl.h
- qmf/EventNotifierImpl.cpp
- qmf/PosixEventNotifier.cpp
- qmf/PosixEventNotifierImpl.cpp
- qmf/exceptions.cpp
- qmf/Expression.cpp
- qmf/Expression.h
- qmf/Hash.cpp
- qmf/Hash.h
- qmf/PrivateImplRef.h
- qmf/Query.cpp
- qmf/QueryImpl.h
- qmf/Schema.cpp
- qmf/SchemaCache.cpp
- qmf/SchemaCache.h
- qmf/SchemaId.cpp
- qmf/SchemaIdImpl.h
- qmf/SchemaImpl.h
- qmf/SchemaMethod.cpp
- qmf/SchemaMethodImpl.h
- qmf/SchemaProperty.cpp
- qmf/SchemaPropertyImpl.h
- qmf/Subscription.cpp
- qmf/SubscriptionImpl.h
- )
-
- add_msvc_version (qmf2 library dll)
- add_library (qmf2 SHARED ${qmf2_SOURCES})
- target_link_libraries (qmf2 qpidmessaging qpidtypes qpidclient qpidcommon)
- set_target_properties (qmf2 PROPERTIES
- VERSION ${qmf2_version})
- install (TARGETS qmf2 OPTIONAL
- DESTINATION ${QPID_INSTALL_LIBDIR}
- COMPONENT ${QPID_COMPONENT_QMF})
- install (FILES ${qmf2_HEADERS}
- DESTINATION ${QPID_INSTALL_INCLUDEDIR}/qmf
- COMPONENT ${QPID_COMPONENT_QMF})
- install_pdb (qmf2 ${QPID_COMPONENT_QMF})
-endif (NOT WIN32)
-
set (qmfengine_SOURCES
qmf/engine/Agent.cpp
qmf/engine/BrokerProxyImpl.cpp
diff --git a/cpp/src/CMakeWinVersions.cmake b/cpp/src/CMakeWinVersions.cmake
index 0bac7cab47..9bffd2ba0e 100644
--- a/cpp/src/CMakeWinVersions.cmake
+++ b/cpp/src/CMakeWinVersions.cmake
@@ -34,11 +34,11 @@
# set ("winver_PACKAGE_NAME" "qpid-cpp")
# set ("winver_DESCRIPTION_SUMMARY" "Apache Qpid C++")
# set ("winver_FILE_VERSION_N1" "0")
-# set ("winver_FILE_VERSION_N2" "11")
+# set ("winver_FILE_VERSION_N2" "9")
# set ("winver_FILE_VERSION_N3" "0")
# set ("winver_FILE_VERSION_N4" "0")
# set ("winver_PRODUCT_VERSION_N1" "0")
-# set ("winver_PRODUCT_VERSION_N2" "11")
+# set ("winver_PRODUCT_VERSION_N2" "9")
# set ("winver_PRODUCT_VERSION_N3" "0")
# set ("winver_PRODUCT_VERSION_N4" "0")
# set ("winver_LEGAL_COPYRIGHT" "")
@@ -46,10 +46,10 @@
#
# Specification of per-project settings:
#
-# set ("winver_${projectName}_FileVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_ProductVersionBinary" "0,11,0,0")
-# set ("winver_${projectName}_FileVersionString" "0, 11, 0, 0")
-# set ("winver_${projectName}_ProductVersionString" "0, 11, 0, 0")
+# set ("winver_${projectName}_FileVersionBinary" "0,9,0,0")
+# set ("winver_${projectName}_ProductVersionBinary" "0,9,0,0")
+# set ("winver_${projectName}_FileVersionString" "0, 9, 0, 0")
+# set ("winver_${projectName}_ProductVersionString" "0, 9, 0, 0")
# set ("winver_${projectName}_FileDescription" "qpid-cpp-qpidcommon Library")
# set ("winver_${projectName}_LegalCopyright" "")
# set ("winver_${projectName}_InternalName" "qpidcommon")
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 6230a8f6f6..2cd6ad462f 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -37,7 +37,6 @@ windows_dist = \
qpid/sys/windows/IOHandle.cpp \
qpid/sys/windows/IoHandlePrivate.h \
qpid/sys/windows/LockFile.cpp \
- qpid/sys/windows/mingw32_compat.h \
qpid/sys/windows/PollableCondition.cpp \
qpid/sys/windows/PipeHandle.cpp \
../include/qpid/sys/windows/Mutex.h \
@@ -89,7 +88,7 @@ rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate . ../include $(specs) all
$(rgen_srcs) $(srcdir)/rubygen.mk: rgen.timestamp
rgen.timestamp: $(rgen_generator) $(specs)
- $(rgen_cmd) $(srcdir)/rubygen.mk && touch $@
+ $(rgen_cmd) $(srcdir)/rubygen.mk; touch $@
$(rgen_generator):
# The CMake version is needed for dist
@@ -128,14 +127,14 @@ qpidexec_SCRIPTS =
qpidtestdir = $(qpidexecdir)/tests
qpidtest_PROGRAMS =
qpidtest_SCRIPTS =
-tmoduleexecdir = $(libdir)/qpid/tests
-tmoduleexec_LTLIBRARIES=
+tmoduledir = $(libdir)/qpid/tests
+tmodule_LTLIBRARIES=
AM_CXXFLAGS += -DBOOST_FILESYSTEM_VERSION=2
## Automake macros to build libraries and executables.
-qpidd_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduleexecdir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\"
-libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduleexecdir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
+qpidd_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDD_MODULE_DIR=\"$(dmoduledir)\" -DQPIDD_CONF_FILE=\"$(sysconfdir)/qpidd.conf\"
+libqpidclient_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_MODULE_DIR=\"$(cmoduledir)\" -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.conf\"
qpidd_LDADD = \
libqpidbroker.la \
@@ -177,7 +176,7 @@ nobase_include_HEADERS += \
../include/qpid/sys/posix/Time.h \
../include/qpid/sys/posix/check.h
-if HAVE_EPOLL
+if HAVE_EPOLL
poller = qpid/sys/epoll/EpollPoller.cpp
endif
@@ -196,15 +195,15 @@ libqpidcommon_la_SOURCES += $(poller) $(systeminfo)
posix_broker_src = \
qpid/broker/posix/BrokerDefaults.cpp
-lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la
+lib_LTLIBRARIES = libqpidtypes.la libqpidcommon.la libqpidbroker.la libqpidclient.la libqpidmessaging.la
# Definitions for client and daemon plugins
PLUGINLDFLAGS=-no-undefined -module -avoid-version
confdir=$(sysconfdir)/qpid
-dmoduleexecdir=$(libdir)/qpid/daemon
-cmoduleexecdir=$(libdir)/qpid/client
-dmoduleexec_LTLIBRARIES =
-cmoduleexec_LTLIBRARIES =
+dmoduledir=$(libdir)/qpid/daemon
+cmoduledir=$(libdir)/qpid/client
+dmodule_LTLIBRARIES =
+cmodule_LTLIBRARIES =
include cluster.mk
include acl.mk
@@ -246,7 +245,7 @@ rdma_la_LIBADD = \
rdma_la_LDFLAGS = $(PLUGINLDFLAGS)
rdma_la_CXXFLAGS = \
$(AM_CXXFLAGS) -Wno-missing-field-initializers
-dmoduleexec_LTLIBRARIES += \
+dmodule_LTLIBRARIES += \
rdma.la
rdmaconnector_la_SOURCES = \
@@ -258,7 +257,7 @@ rdmaconnector_la_LIBADD = \
rdmaconnector_la_LDFLAGS = $(PLUGINLDFLAGS)
rdmaconnector_la_CXXFLAGS = \
$(AM_CXXFLAGS) -Wno-missing-field-initializers
-cmoduleexec_LTLIBRARIES += \
+cmodule_LTLIBRARIES += \
rdmaconnector.la
# RDMA test/sample programs
@@ -333,7 +332,6 @@ libqpidcommon_la_SOURCES += \
qpid/Address.cpp \
qpid/DataDir.cpp \
qpid/DataDir.h \
- qpid/DisableExceptionLogging.h \
qpid/Exception.cpp \
qpid/Modules.cpp \
qpid/Modules.h \
@@ -343,7 +341,6 @@ libqpidcommon_la_SOURCES += \
qpid/RefCounted.h \
qpid/RefCountedBuffer.cpp \
qpid/RefCountedBuffer.h \
- qpid/BufferRef.h \
qpid/Sasl.h \
qpid/SaslFactory.cpp \
qpid/SaslFactory.h \
@@ -564,7 +561,8 @@ libqpidbroker_la_SOURCES = \
qpid/broker/HandlerImpl.h \
qpid/broker/HeadersExchange.cpp \
qpid/broker/HeadersExchange.h \
- qpid/broker/AsyncCompletion.h \
+ qpid/broker/IncompleteMessageList.cpp \
+ qpid/broker/IncompleteMessageList.h \
qpid/broker/LegacyLVQ.h \
qpid/broker/LegacyLVQ.cpp \
qpid/broker/Link.cpp \
@@ -614,9 +612,9 @@ libqpidbroker_la_SOURCES = \
qpid/broker/QueueRegistry.cpp \
qpid/broker/QueueRegistry.h \
qpid/broker/QueuedMessage.h \
- qpid/broker/QueueFlowLimit.h \
- qpid/broker/QueueFlowLimit.cpp \
qpid/broker/RateFlowcontrol.h \
+ qpid/broker/RateTracker.cpp \
+ qpid/broker/RateTracker.h \
qpid/broker/RecoverableConfig.h \
qpid/broker/RecoverableExchange.h \
qpid/broker/RecoverableMessage.h \
@@ -653,7 +651,6 @@ libqpidbroker_la_SOURCES = \
qpid/broker/SessionState.h \
qpid/broker/SignalHandler.cpp \
qpid/broker/SignalHandler.h \
- qpid/broker/StatefulQueueObserver.h \
qpid/broker/System.cpp \
qpid/broker/System.h \
qpid/broker/ThresholdAlerts.cpp \
@@ -671,11 +668,6 @@ libqpidbroker_la_SOURCES = \
qpid/broker/TxPublish.h \
qpid/broker/Vhost.cpp \
qpid/broker/Vhost.h \
- qpid/broker/MessageDistributor.h \
- qpid/broker/FifoDistributor.h \
- qpid/broker/FifoDistributor.cpp \
- qpid/broker/MessageGroupManager.cpp \
- qpid/broker/MessageGroupManager.h \
qpid/management/ManagementAgent.cpp \
qpid/management/ManagementAgent.h \
qpid/management/ManagementDirectExchange.cpp \
@@ -747,7 +739,7 @@ libqpidclient_la_SOURCES = \
QPIDCLIENT_VERSION_INFO = 2:0:0
libqpidclient_la_LDFLAGS = -version-info $(QPIDCLIENT_VERSION_INFO)
-libqpidtypes_la_LIBADD= -luuid
+libqpidtypes_la_libadd=-luuid
libqpidtypes_la_SOURCES= \
qpid/types/Exception.cpp \
qpid/types/Uuid.cpp \
@@ -794,7 +786,9 @@ libqpidmessaging_la_SOURCES = \
qpid/client/amqp0_10/SessionImpl.h \
qpid/client/amqp0_10/SessionImpl.cpp \
qpid/client/amqp0_10/SenderImpl.h \
- qpid/client/amqp0_10/SenderImpl.cpp
+ qpid/client/amqp0_10/SenderImpl.cpp \
+ qpid/client/amqp0_10/SimpleUrlParser.h \
+ qpid/client/amqp0_10/SimpleUrlParser.cpp
QPIDMESSAGING_VERSION_INFO = 2:0:0
libqpidmessaging_la_LDFLAGS = -version-info $(QPIDMESSAGING_VERSION_INFO)
@@ -807,7 +801,6 @@ nobase_include_HEADERS += \
../include/qpid/Address.h \
../include/qpid/CommonImportExport.h \
../include/qpid/Exception.h \
- ../include/qpid/ImportExport.h \
../include/qpid/InlineAllocator.h \
../include/qpid/InlineVector.h \
../include/qpid/Msg.h \
@@ -890,10 +883,14 @@ nobase_include_HEADERS += \
../include/qpid/types/Variant.h \
../include/qpid/types/ImportExport.h
+# Force build of qpidd during dist phase so help2man will work.
+dist-hook: $(BUILT_SOURCES)
+ $(MAKE) qpidd
+
# Create the default data directory
install-data-local:
$(mkinstalldirs) $(DESTDIR)/$(localstatedir)/lib/qpidd
-# Support for pkg-config
+# Support for pkg-config
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = qpid.pc
diff --git a/cpp/src/acl.mk b/cpp/src/acl.mk
index b8e2ff0e13..bcd1d88335 100644
--- a/cpp/src/acl.mk
+++ b/cpp/src/acl.mk
@@ -18,8 +18,8 @@
#
#
# acl library makefile fragment, to be included in Makefile.am
-#
-dmoduleexec_LTLIBRARIES += acl.la
+#
+dmodule_LTLIBRARIES += acl.la
acl_la_SOURCES = \
qpid/acl/Acl.cpp \
diff --git a/cpp/src/cluster.mk b/cpp/src/cluster.mk
index 3ce4ce25b3..a791b2d41a 100644
--- a/cpp/src/cluster.mk
+++ b/cpp/src/cluster.mk
@@ -18,7 +18,7 @@
#
#
# Cluster library makefile fragment, to be included in Makefile.am
-#
+#
# Optional CMAN support
@@ -34,7 +34,7 @@ endif
if HAVE_LIBCPG
-dmoduleexec_LTLIBRARIES += cluster.la
+dmodule_LTLIBRARIES += cluster.la
cluster_la_SOURCES = \
$(CMAN_SOURCES) \
@@ -102,7 +102,7 @@ cluster_la_CXXFLAGS = $(AM_CXXFLAGS) -fno-strict-aliasing
cluster_la_LDFLAGS = $(PLUGINLDFLAGS)
# The watchdog plugin and helper executable
-dmoduleexec_LTLIBRARIES += watchdog.la
+dmodule_LTLIBRARIES += watchdog.la
watchdog_la_SOURCES = qpid/cluster/WatchDogPlugin.cpp
watchdog_la_LIBADD = libqpidbroker.la
watchdog_la_LDFLAGS = $(PLUGINLDFLAGS)
diff --git a/cpp/src/posix/QpiddBroker.cpp b/cpp/src/posix/QpiddBroker.cpp
index 1cebcfc3ac..86504ba7fc 100644
--- a/cpp/src/posix/QpiddBroker.cpp
+++ b/cpp/src/posix/QpiddBroker.cpp
@@ -138,9 +138,6 @@ struct QpiddDaemon : public Daemon {
brokerPtr->accept();
uint16_t port=brokerPtr->getPort(options->daemon.transport);
ready(port); // Notify parent.
- if (options->parent->broker.enableMgmt && (options->parent->broker.port == 0 || options->daemon.transport != TCP)) {
- dynamic_cast<qmf::org::apache::qpid::broker::Broker*>(brokerPtr->GetManagementObject())->set_port(port);
- }
brokerPtr->run();
}
};
@@ -185,13 +182,8 @@ int QpiddBroker::execute (QpiddOptions *options) {
boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker));
ScopedSetBroker ssb(brokerPtr);
brokerPtr->accept();
- if (options->broker.port == 0 || myOptions->daemon.transport != TCP) {
- uint16_t port = brokerPtr->getPort(myOptions->daemon.transport);
- cout << port << endl;
- if (options->broker.enableMgmt) {
- dynamic_cast<qmf::org::apache::qpid::broker::Broker*>(brokerPtr->GetManagementObject())->set_port(port);
- }
- }
+ if (options->broker.port == 0 || myOptions->daemon.transport != TCP)
+ cout << uint16_t(brokerPtr->getPort(myOptions->daemon.transport)) << endl;
brokerPtr->run();
}
return 0;
diff --git a/cpp/src/qmf.mk b/cpp/src/qmf.mk
index 3b6583bfaf..f3462f1a93 100644
--- a/cpp/src/qmf.mk
+++ b/cpp/src/qmf.mk
@@ -43,7 +43,6 @@ QMF2_API = \
../include/qmf/ConsoleSession.h \
../include/qmf/DataAddr.h \
../include/qmf/Data.h \
- ../include/qmf/posix/EventNotifier.h \
../include/qmf/exceptions.h \
../include/qmf/Handle.h \
../include/qmf/ImportExport.h \
@@ -93,7 +92,6 @@ libqmf2_la_SOURCES = \
qmf/AgentEventImpl.h \
qmf/AgentImpl.h \
qmf/AgentSession.cpp \
- qmf/AgentSessionImpl.h \
qmf/AgentSubscription.cpp \
qmf/AgentSubscription.h \
qmf/ConsoleEvent.cpp \
@@ -106,22 +104,17 @@ libqmf2_la_SOURCES = \
qmf/DataAddrImpl.h \
qmf/Data.cpp \
qmf/DataImpl.h \
- qmf/EventNotifierImpl.cpp \
- qmf/EventNotifierImpl.h \
qmf/exceptions.cpp \
qmf/Expression.cpp \
qmf/Expression.h \
qmf/Hash.cpp \
qmf/Hash.h \
- qmf/PosixEventNotifier.cpp \
- qmf/PosixEventNotifierImpl.cpp \
- qmf/PosixEventNotifierImpl.h \
qmf/PrivateImplRef.h \
qmf/Query.cpp \
qmf/QueryImpl.h \
+ qmf/Schema.cpp \
qmf/SchemaCache.cpp \
qmf/SchemaCache.h \
- qmf/Schema.cpp \
qmf/SchemaId.cpp \
qmf/SchemaIdImpl.h \
qmf/SchemaImpl.h \
diff --git a/cpp/src/qmf/Agent.cpp b/cpp/src/qmf/Agent.cpp
index 684f8e4fba..915f2a1c88 100644
--- a/cpp/src/qmf/Agent.cpp
+++ b/cpp/src/qmf/Agent.cpp
@@ -72,7 +72,7 @@ Schema Agent::getSchema(const SchemaId& s, Duration t) { return impl->getSchema(
AgentImpl::AgentImpl(const std::string& n, uint32_t e, ConsoleSessionImpl& s) :
name(n), directSubject(n), epoch(e), session(s), touched(true), untouchedCount(0), capability(0),
- sender(session.directSender), schemaCache(s.schemaCache)
+ sender(session.directSender), nextCorrelator(1), schemaCache(s.schemaCache)
{
}
@@ -102,11 +102,12 @@ const Variant& AgentImpl::getAttribute(const string& k) const
ConsoleEvent AgentImpl::query(const Query& query, Duration timeout)
{
boost::shared_ptr<SyncContext> context(new SyncContext());
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
ConsoleEvent result;
{
qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
contextMap[correlator] = context;
}
try {
@@ -150,7 +151,12 @@ ConsoleEvent AgentImpl::query(const string& text, Duration timeout)
uint32_t AgentImpl::queryAsync(const Query& query)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
sendQuery(query, correlator);
return correlator;
@@ -166,11 +172,12 @@ uint32_t AgentImpl::queryAsync(const string& text)
ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& args, const DataAddr& addr, Duration timeout)
{
boost::shared_ptr<SyncContext> context(new SyncContext());
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
ConsoleEvent result;
{
qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
contextMap[correlator] = context;
}
try {
@@ -206,7 +213,12 @@ ConsoleEvent AgentImpl::callMethod(const string& method, const Variant::Map& arg
uint32_t AgentImpl::callMethodAsync(const string& method, const Variant::Map& args, const DataAddr& addr)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
sendMethod(method, args, addr, correlator);
return correlator;
@@ -584,7 +596,12 @@ void AgentImpl::sendMethod(const string& method, const Variant::Map& args, const
void AgentImpl::sendSchemaRequest(const SchemaId& id)
{
- uint32_t correlator(session.correlator());
+ uint32_t correlator;
+
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ correlator = nextCorrelator++;
+ }
if (capability >= AGENT_CAPABILITY_V2_SCHEMA) {
Query query(QUERY_SCHEMA, id);
diff --git a/cpp/src/qmf/AgentImpl.h b/cpp/src/qmf/AgentImpl.h
index 09754a3a7e..7fa4f4373a 100644
--- a/cpp/src/qmf/AgentImpl.h
+++ b/cpp/src/qmf/AgentImpl.h
@@ -99,6 +99,7 @@ namespace qmf {
uint32_t capability;
qpid::messaging::Sender sender;
qpid::types::Variant::Map attributes;
+ uint32_t nextCorrelator;
std::map<uint32_t, boost::shared_ptr<SyncContext> > contextMap;
boost::shared_ptr<SchemaCache> schemaCache;
mutable std::set<std::string> packageSet;
diff --git a/cpp/src/qmf/AgentSession.cpp b/cpp/src/qmf/AgentSession.cpp
index 251c25fd44..4c5a72a467 100644
--- a/cpp/src/qmf/AgentSession.cpp
+++ b/cpp/src/qmf/AgentSession.cpp
@@ -19,7 +19,132 @@
*
*/
-#include "qmf/AgentSessionImpl.h"
+#include "qpid/RefCounted.h"
+#include "qmf/PrivateImplRef.h"
+#include "qmf/exceptions.h"
+#include "qmf/AgentSession.h"
+#include "qmf/AgentEventImpl.h"
+#include "qmf/SchemaIdImpl.h"
+#include "qmf/SchemaImpl.h"
+#include "qmf/DataAddrImpl.h"
+#include "qmf/DataImpl.h"
+#include "qmf/QueryImpl.h"
+#include "qmf/agentCapability.h"
+#include "qmf/constants.h"
+#include "qpid/sys/Mutex.h"
+#include "qpid/sys/Condition.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/log/Statement.h"
+#include "qpid/messaging/Connection.h"
+#include "qpid/messaging/Session.h"
+#include "qpid/messaging/Receiver.h"
+#include "qpid/messaging/Sender.h"
+#include "qpid/messaging/Message.h"
+#include "qpid/messaging/AddressParser.h"
+#include "qpid/management/Buffer.h"
+#include <queue>
+#include <map>
+#include <set>
+#include <iostream>
+#include <memory>
+
+using namespace std;
+using namespace qpid::messaging;
+using namespace qmf;
+using qpid::types::Variant;
+
+namespace qmf {
+ class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
+ public:
+ ~AgentSessionImpl();
+
+ //
+ // Methods from API handle
+ //
+ AgentSessionImpl(Connection& c, const string& o);
+ void setDomain(const string& d) { checkOpen(); domain = d; }
+ void setVendor(const string& v) { checkOpen(); attributes["_vendor"] = v; }
+ void setProduct(const string& p) { checkOpen(); attributes["_product"] = p; }
+ void setInstance(const string& i) { checkOpen(); attributes["_instance"] = i; }
+ void setAttribute(const string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; }
+ const string& getName() const { return agentName; }
+ void open();
+ void close();
+ bool nextEvent(AgentEvent& e, Duration t);
+
+ void registerSchema(Schema& s);
+ DataAddr addData(Data& d, const string& n, bool persist);
+ void delData(const DataAddr&);
+
+ void authAccept(AgentEvent& e);
+ void authReject(AgentEvent& e, const string& m);
+ void raiseException(AgentEvent& e, const string& s);
+ void raiseException(AgentEvent& e, const Data& d);
+ void response(AgentEvent& e, const Data& d);
+ void complete(AgentEvent& e);
+ void methodSuccess(AgentEvent& e);
+ void raiseEvent(const Data& d);
+ void raiseEvent(const Data& d, int s);
+
+ private:
+ typedef map<DataAddr, Data, DataAddrCompare> DataIndex;
+ typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap;
+
+ mutable qpid::sys::Mutex lock;
+ qpid::sys::Condition cond;
+ Connection connection;
+ Session session;
+ Sender directSender;
+ Sender topicSender;
+ string domain;
+ Variant::Map attributes;
+ Variant::Map options;
+ string agentName;
+ bool opened;
+ queue<AgentEvent> eventQueue;
+ qpid::sys::Thread* thread;
+ bool threadCanceled;
+ uint32_t bootSequence;
+ uint32_t interval;
+ uint64_t lastHeartbeat;
+ uint64_t lastVisit;
+ bool forceHeartbeat;
+ bool externalStorage;
+ bool autoAllowQueries;
+ bool autoAllowMethods;
+ uint32_t maxSubscriptions;
+ uint32_t minSubInterval;
+ uint32_t subLifetime;
+ bool publicEvents;
+ bool listenOnDirect;
+ bool strictSecurity;
+ uint64_t schemaUpdateTime;
+ string directBase;
+ string topicBase;
+
+ SchemaMap schemata;
+ DataIndex globalIndex;
+ map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex;
+
+ void checkOpen();
+ void setAgentName();
+ void enqueueEvent(const AgentEvent&);
+ void handleLocateRequest(const Variant::List& content, const Message& msg);
+ void handleMethodRequest(const Variant::Map& content, const Message& msg);
+ void handleQueryRequest(const Variant::Map& content, const Message& msg);
+ void handleSchemaRequest(AgentEvent&);
+ void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&);
+ void dispatch(Message);
+ void sendHeartbeat();
+ void send(Message, const Address&);
+ void flushResponses(AgentEvent&, bool);
+ void periodicProcessing(uint64_t);
+ void run();
+ };
+}
+
+typedef qmf::PrivateImplRef<AgentSession> PI;
AgentSession::AgentSession(AgentSessionImpl* impl) { PI::ctor(*this, impl); }
AgentSession::AgentSession(const AgentSession& s) : qmf::Handle<AgentSessionImpl>() { PI::copy(*this, s); }
@@ -36,7 +161,6 @@ const string& AgentSession::getName() const { return impl->getName(); }
void AgentSession::open() { impl->open(); }
void AgentSession::close() { impl->close(); }
bool AgentSession::nextEvent(AgentEvent& e, Duration t) { return impl->nextEvent(e, t); }
-int AgentSession::pendingEvents() const { return impl->pendingEvents(); }
void AgentSession::registerSchema(Schema& s) { impl->registerSchema(s); }
DataAddr AgentSession::addData(Data& d, const string& n, bool p) { return impl->addData(d, n, p); }
void AgentSession::delData(const DataAddr& a) { impl->delData(a); }
@@ -55,11 +179,11 @@ void AgentSession::raiseEvent(const Data& d, int s) { impl->raiseEvent(d, s); }
//========================================================================================
AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) :
- connection(c), domain("default"), opened(false), eventNotifier(0), thread(0), threadCanceled(false),
+ connection(c), domain("default"), opened(false), thread(0), threadCanceled(false),
bootSequence(1), interval(60), lastHeartbeat(0), lastVisit(0), forceHeartbeat(false),
externalStorage(false), autoAllowQueries(true), autoAllowMethods(true),
maxSubscriptions(64), minSubInterval(3000), subLifetime(300), publicEvents(true),
- listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5),
+ listenOnDirect(true), strictSecurity(false),
schemaUpdateTime(uint64_t(qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now())))
{
//
@@ -120,14 +244,7 @@ AgentSessionImpl::AgentSessionImpl(Connection& c, const string& options) :
iter = optMap.find("strict-security");
if (iter != optMap.end())
strictSecurity = iter->second.asBool();
-
- iter = optMap.find("max-thread-wait-time");
- if (iter != optMap.end())
- maxThreadWaitTime = iter->second.asUint32();
}
-
- if (maxThreadWaitTime > interval)
- maxThreadWaitTime = interval;
}
@@ -135,11 +252,6 @@ AgentSessionImpl::~AgentSessionImpl()
{
if (opened)
close();
-
- if (thread) {
- thread->join();
- delete thread;
- }
}
@@ -148,12 +260,6 @@ void AgentSessionImpl::open()
if (opened)
throw QmfException("The session is already open");
- // If the thread exists, join and delete it before creating a new one.
- if (thread) {
- thread->join();
- delete thread;
- }
-
const string addrArgs(";{create:never,node:{type:topic}}");
const string routableAddr("direct-agent.route." + qpid::types::Uuid(true).str());
attributes["_direct_subject"] = routableAddr;
@@ -191,26 +297,19 @@ void AgentSessionImpl::open()
}
-void AgentSessionImpl::closeAsync()
+void AgentSessionImpl::close()
{
if (!opened)
return;
- // Stop the receiver thread. Don't join it until the destructor is called or open() is called.
+ // Stop and join the receiver thread
threadCanceled = true;
- opened = false;
-}
+ thread->join();
+ delete thread;
-
-void AgentSessionImpl::close()
-{
- closeAsync();
-
- if (thread) {
- thread->join();
- delete thread;
- thread = 0;
- }
+ // Close the AMQP session
+ session.close();
+ opened = false;
}
@@ -219,19 +318,13 @@ bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout)
uint64_t milliseconds = timeout.getMilliseconds();
qpid::sys::Mutex::ScopedLock l(lock);
- if (eventQueue.empty() && milliseconds > 0) {
- int64_t nsecs(qpid::sys::TIME_INFINITE);
- if ((uint64_t)(nsecs / 1000000) > milliseconds)
- nsecs = (int64_t) milliseconds * 1000000;
- qpid::sys::Duration then(nsecs);
- cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then));
- }
+ if (eventQueue.empty())
+ cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(),
+ qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC)));
if (!eventQueue.empty()) {
event = eventQueue.front();
eventQueue.pop();
- if (eventQueue.empty())
- alertEventNotifierLH(false);
return true;
}
@@ -239,26 +332,6 @@ bool AgentSessionImpl::nextEvent(AgentEvent& event, Duration timeout)
}
-int AgentSessionImpl::pendingEvents() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventQueue.size();
-}
-
-
-void AgentSessionImpl::setEventNotifier(EventNotifierImpl* notifier)
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- eventNotifier = notifier;
-}
-
-EventNotifierImpl* AgentSessionImpl::getEventNotifier() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventNotifier;
-}
-
-
void AgentSessionImpl::registerSchema(Schema& schema)
{
if (!schema.isFinalized())
@@ -514,10 +587,8 @@ void AgentSessionImpl::enqueueEvent(const AgentEvent& event)
qpid::sys::Mutex::ScopedLock l(lock);
bool notify = eventQueue.empty();
eventQueue.push(event);
- if (notify) {
+ if (notify)
cond.notify();
- alertEventNotifierLH(true);
- }
}
@@ -961,13 +1032,6 @@ void AgentSessionImpl::periodicProcessing(uint64_t seconds)
}
-void AgentSessionImpl::alertEventNotifierLH(bool readable)
-{
- if (eventNotifier)
- eventNotifier->setReadable(readable);
-}
-
-
void AgentSessionImpl::run()
{
QPID_LOG(debug, "AgentSession thread started for agent " << agentName);
@@ -977,7 +1041,7 @@ void AgentSessionImpl::run()
periodicProcessing((uint64_t) qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()) / qpid::sys::TIME_SEC);
Receiver rx;
- bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime);
+ bool valid = session.nextReceiver(rx, Duration::SECOND);
if (threadCanceled)
break;
if (valid) {
@@ -994,19 +1058,6 @@ void AgentSessionImpl::run()
enqueueEvent(AgentEvent(new AgentEventImpl(AGENT_THREAD_FAILED)));
}
- session.close();
QPID_LOG(debug, "AgentSession thread exiting for agent " << agentName);
}
-
-AgentSessionImpl& AgentSessionImplAccess::get(AgentSession& session)
-{
- return *session.impl;
-}
-
-
-const AgentSessionImpl& AgentSessionImplAccess::get(const AgentSession& session)
-{
- return *session.impl;
-}
-
diff --git a/cpp/src/qmf/AgentSessionImpl.h b/cpp/src/qmf/AgentSessionImpl.h
deleted file mode 100644
index ae512a4054..0000000000
--- a/cpp/src/qmf/AgentSessionImpl.h
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef __QMF_AGENT_SESSION_IMPL_H
-#define __QMF_AGENT_SESSION_IMPL_H
-
-/*
- *
- * 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 "qpid/RefCounted.h"
-#include "qmf/PrivateImplRef.h"
-#include "qmf/exceptions.h"
-#include "qmf/AgentSession.h"
-#include "qmf/AgentEventImpl.h"
-#include "qmf/EventNotifierImpl.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/Condition.h"
-#include "qpid/sys/Thread.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/log/Statement.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/messaging/Session.h"
-#include "qpid/messaging/Receiver.h"
-#include "qpid/messaging/Sender.h"
-#include "qpid/messaging/Message.h"
-#include "qpid/messaging/AddressParser.h"
-#include "qpid/management/Buffer.h"
-#include "qpid/RefCounted.h"
-#include "qmf/PrivateImplRef.h"
-#include "qmf/AgentSession.h"
-#include "qmf/exceptions.h"
-#include "qmf/AgentSession.h"
-#include "qmf/SchemaIdImpl.h"
-#include "qmf/SchemaImpl.h"
-#include "qmf/DataAddrImpl.h"
-#include "qmf/DataImpl.h"
-#include "qmf/QueryImpl.h"
-#include "qmf/agentCapability.h"
-#include "qmf/constants.h"
-
-#include <queue>
-#include <map>
-#include <iostream>
-#include <memory>
-
-using namespace std;
-using namespace qpid::messaging;
-using namespace qmf;
-using qpid::types::Variant;
-
-typedef qmf::PrivateImplRef<AgentSession> PI;
-
-namespace qmf {
- class AgentSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
- public:
- ~AgentSessionImpl();
-
- //
- // Methods from API handle
- //
- AgentSessionImpl(Connection& c, const string& o);
- void setDomain(const string& d) { checkOpen(); domain = d; }
- void setVendor(const string& v) { checkOpen(); attributes["_vendor"] = v; }
- void setProduct(const string& p) { checkOpen(); attributes["_product"] = p; }
- void setInstance(const string& i) { checkOpen(); attributes["_instance"] = i; }
- void setAttribute(const string& k, const qpid::types::Variant& v) { checkOpen(); attributes[k] = v; }
- const string& getName() const { return agentName; }
- void open();
- void closeAsync();
- void close();
- bool nextEvent(AgentEvent& e, Duration t);
- int pendingEvents() const;
-
- void setEventNotifier(EventNotifierImpl* eventNotifier);
- EventNotifierImpl* getEventNotifier() const;
-
- void registerSchema(Schema& s);
- DataAddr addData(Data& d, const string& n, bool persist);
- void delData(const DataAddr&);
-
- void authAccept(AgentEvent& e);
- void authReject(AgentEvent& e, const string& m);
- void raiseException(AgentEvent& e, const string& s);
- void raiseException(AgentEvent& e, const Data& d);
- void response(AgentEvent& e, const Data& d);
- void complete(AgentEvent& e);
- void methodSuccess(AgentEvent& e);
- void raiseEvent(const Data& d);
- void raiseEvent(const Data& d, int s);
-
- private:
- typedef map<DataAddr, Data, DataAddrCompare> DataIndex;
- typedef map<SchemaId, Schema, SchemaIdCompare> SchemaMap;
-
- mutable qpid::sys::Mutex lock;
- qpid::sys::Condition cond;
- Connection connection;
- Session session;
- Sender directSender;
- Sender topicSender;
- string domain;
- Variant::Map attributes;
- Variant::Map options;
- string agentName;
- bool opened;
- queue<AgentEvent> eventQueue;
- EventNotifierImpl* eventNotifier;
- qpid::sys::Thread* thread;
- bool threadCanceled;
- uint32_t bootSequence;
- uint32_t interval;
- uint64_t lastHeartbeat;
- uint64_t lastVisit;
- bool forceHeartbeat;
- bool externalStorage;
- bool autoAllowQueries;
- bool autoAllowMethods;
- uint32_t maxSubscriptions;
- uint32_t minSubInterval;
- uint32_t subLifetime;
- bool publicEvents;
- bool listenOnDirect;
- bool strictSecurity;
- uint32_t maxThreadWaitTime;
- uint64_t schemaUpdateTime;
- string directBase;
- string topicBase;
-
- SchemaMap schemata;
- DataIndex globalIndex;
- map<SchemaId, DataIndex, SchemaIdCompareNoHash> schemaIndex;
-
- void checkOpen();
- void setAgentName();
- void enqueueEvent(const AgentEvent&);
- void alertEventNotifierLH(bool readable);
- void handleLocateRequest(const Variant::List& content, const Message& msg);
- void handleMethodRequest(const Variant::Map& content, const Message& msg);
- void handleQueryRequest(const Variant::Map& content, const Message& msg);
- void handleSchemaRequest(AgentEvent&);
- void handleV1SchemaRequest(qpid::management::Buffer&, uint32_t, const Message&);
- void dispatch(Message);
- void sendHeartbeat();
- void send(Message, const Address&);
- void flushResponses(AgentEvent&, bool);
- void periodicProcessing(uint64_t);
- void run();
- };
-
- struct AgentSessionImplAccess {
- static AgentSessionImpl& get(AgentSession& session);
- static const AgentSessionImpl& get(const AgentSession& session);
- };
-}
-
-
-#endif
-
diff --git a/cpp/src/qmf/ConsoleSession.cpp b/cpp/src/qmf/ConsoleSession.cpp
index 2dfc894c58..e12c1152f6 100644
--- a/cpp/src/qmf/ConsoleSession.cpp
+++ b/cpp/src/qmf/ConsoleSession.cpp
@@ -54,7 +54,6 @@ void ConsoleSession::setAgentFilter(const string& f) { impl->setAgentFilter(f);
void ConsoleSession::open() { impl->open(); }
void ConsoleSession::close() { impl->close(); }
bool ConsoleSession::nextEvent(ConsoleEvent& e, Duration t) { return impl->nextEvent(e, t); }
-int ConsoleSession::pendingEvents() const { return impl->pendingEvents(); }
uint32_t ConsoleSession::getAgentCount() const { return impl->getAgentCount(); }
Agent ConsoleSession::getAgent(uint32_t i) const { return impl->getAgent(i); }
Agent ConsoleSession::getConnectedBrokerAgent() const { return impl->getConnectedBrokerAgent(); }
@@ -66,9 +65,9 @@ Subscription ConsoleSession::subscribe(const string& q, const string& f, const s
//========================================================================================
ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) :
- connection(c), domain("default"), maxAgentAgeMinutes(5), listenOnDirect(true), strictSecurity(false), maxThreadWaitTime(5),
- opened(false), eventNotifier(0), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0),
- connectedBrokerInAgentList(false), schemaCache(new SchemaCache()), nextCorrelator(1)
+ connection(c), domain("default"), maxAgentAgeMinutes(5),
+ opened(false), thread(0), threadCanceled(false), lastVisit(0), lastAgePass(0),
+ connectedBrokerInAgentList(false), schemaCache(new SchemaCache())
{
if (!options.empty()) {
qpid::messaging::AddressParser parser(options);
@@ -92,14 +91,7 @@ ConsoleSessionImpl::ConsoleSessionImpl(Connection& c, const string& options) :
iter = optMap.find("strict-security");
if (iter != optMap.end())
strictSecurity = iter->second.asBool();
-
- iter = optMap.find("max-thread-wait-time");
- if (iter != optMap.end())
- maxThreadWaitTime = iter->second.asUint32();
}
-
- if (maxThreadWaitTime > 60)
- maxThreadWaitTime = 60;
}
@@ -107,11 +99,6 @@ ConsoleSessionImpl::~ConsoleSessionImpl()
{
if (opened)
close();
-
- if (thread) {
- thread->join();
- delete thread;
- }
}
@@ -166,12 +153,6 @@ void ConsoleSessionImpl::open()
if (opened)
throw QmfException("The session is already open");
- // If the thread exists, join and delete it before creating a new one.
- if (thread) {
- thread->join();
- delete thread;
- }
-
// Establish messaging addresses
directBase = "qmf." + domain + ".direct";
topicBase = "qmf." + domain + ".topic";
@@ -200,36 +181,30 @@ void ConsoleSessionImpl::open()
// Start the receiver thread
threadCanceled = false;
- opened = true;
thread = new qpid::sys::Thread(*this);
// Send an agent_locate to direct address 'broker' to identify the connected-broker-agent.
sendBrokerLocate();
if (agentQuery)
sendAgentLocate();
+
+ opened = true;
}
-void ConsoleSessionImpl::closeAsync()
+void ConsoleSessionImpl::close()
{
if (!opened)
throw QmfException("The session is already closed");
- // Stop the receiver thread. Don't join it until the destructor is called or open() is called.
+ // Stop and join the receiver thread
threadCanceled = true;
- opened = false;
-}
-
+ thread->join();
+ delete thread;
-void ConsoleSessionImpl::close()
-{
- closeAsync();
-
- if (thread) {
- thread->join();
- delete thread;
- thread = 0;
- }
+ // Close the AMQP session
+ session.close();
+ opened = false;
}
@@ -238,19 +213,13 @@ bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout)
uint64_t milliseconds = timeout.getMilliseconds();
qpid::sys::Mutex::ScopedLock l(lock);
- if (eventQueue.empty() && milliseconds > 0) {
- int64_t nsecs(qpid::sys::TIME_INFINITE);
- if ((uint64_t)(nsecs / 1000000) > milliseconds)
- nsecs = (int64_t) milliseconds * 1000000;
- qpid::sys::Duration then(nsecs);
- cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(), then));
- }
+ if (eventQueue.empty())
+ cond.wait(lock, qpid::sys::AbsTime(qpid::sys::now(),
+ qpid::sys::Duration(milliseconds * qpid::sys::TIME_MSEC)));
if (!eventQueue.empty()) {
event = eventQueue.front();
eventQueue.pop();
- if (eventQueue.empty())
- alertEventNotifierLH(false);
return true;
}
@@ -258,27 +227,6 @@ bool ConsoleSessionImpl::nextEvent(ConsoleEvent& event, Duration timeout)
}
-int ConsoleSessionImpl::pendingEvents() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventQueue.size();
-}
-
-
-void ConsoleSessionImpl::setEventNotifier(EventNotifierImpl* notifier)
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- eventNotifier = notifier;
-}
-
-
-EventNotifierImpl* ConsoleSessionImpl::getEventNotifier() const
-{
- qpid::sys::Mutex::ScopedLock l(lock);
- return eventNotifier;
-}
-
-
uint32_t ConsoleSessionImpl::getAgentCount() const
{
qpid::sys::Mutex::ScopedLock l(lock);
@@ -320,10 +268,8 @@ void ConsoleSessionImpl::enqueueEventLH(const ConsoleEvent& event)
{
bool notify = eventQueue.empty();
eventQueue.push(event);
- if (notify) {
+ if (notify)
cond.notify();
- alertEventNotifierLH(true);
- }
}
@@ -475,23 +421,7 @@ void ConsoleSessionImpl::handleAgentUpdate(const string& agentName, const Varian
iter = content.find("_values");
if (iter == content.end())
return;
- const Variant::Map& in_attrs(iter->second.asMap());
- Variant::Map attrs;
-
- //
- // Copy the map from the message to "attrs". Translate any old-style
- // keys to their new key values in the process.
- //
- for (iter = in_attrs.begin(); iter != in_attrs.end(); iter++) {
- if (iter->first == "epoch")
- attrs[protocol::AGENT_ATTR_EPOCH] = iter->second;
- else if (iter->first == "timestamp")
- attrs[protocol::AGENT_ATTR_TIMESTAMP] = iter->second;
- else if (iter->first == "heartbeat_interval")
- attrs[protocol::AGENT_ATTR_HEARTBEAT_INTERVAL] = iter->second;
- else
- attrs[iter->first] = iter->second;
- }
+ Variant::Map attrs(iter->second.asMap());
iter = attrs.find(protocol::AGENT_ATTR_EPOCH);
if (iter != attrs.end())
@@ -632,13 +562,6 @@ void ConsoleSessionImpl::periodicProcessing(uint64_t seconds)
}
-void ConsoleSessionImpl::alertEventNotifierLH(bool readable)
-{
- if (eventNotifier)
- eventNotifier->setReadable(readable);
-}
-
-
void ConsoleSessionImpl::run()
{
QPID_LOG(debug, "ConsoleSession thread started");
@@ -649,7 +572,7 @@ void ConsoleSessionImpl::run()
qpid::sys::TIME_SEC);
Receiver rx;
- bool valid = session.nextReceiver(rx, Duration::SECOND * maxThreadWaitTime);
+ bool valid = session.nextReceiver(rx, Duration::SECOND);
if (threadCanceled)
break;
if (valid) {
@@ -666,18 +589,6 @@ void ConsoleSessionImpl::run()
enqueueEvent(ConsoleEvent(new ConsoleEventImpl(CONSOLE_THREAD_FAILED)));
}
- session.close();
QPID_LOG(debug, "ConsoleSession thread exiting");
}
-
-ConsoleSessionImpl& ConsoleSessionImplAccess::get(ConsoleSession& session)
-{
- return *session.impl;
-}
-
-
-const ConsoleSessionImpl& ConsoleSessionImplAccess::get(const ConsoleSession& session)
-{
- return *session.impl;
-}
diff --git a/cpp/src/qmf/ConsoleSessionImpl.h b/cpp/src/qmf/ConsoleSessionImpl.h
index e2b30602fa..675c8bcfb5 100644
--- a/cpp/src/qmf/ConsoleSessionImpl.h
+++ b/cpp/src/qmf/ConsoleSessionImpl.h
@@ -27,7 +27,6 @@
#include "qmf/SchemaId.h"
#include "qmf/Schema.h"
#include "qmf/ConsoleEventImpl.h"
-#include "qmf/EventNotifierImpl.h"
#include "qmf/SchemaCache.h"
#include "qmf/Query.h"
#include "qpid/sys/Mutex.h"
@@ -42,13 +41,9 @@
#include "qpid/messaging/Address.h"
#include "qpid/management/Buffer.h"
#include "qpid/types/Variant.h"
-
-#include <boost/shared_ptr.hpp>
#include <map>
#include <queue>
-using namespace std;
-
namespace qmf {
class ConsoleSessionImpl : public virtual qpid::RefCounted, public qpid::sys::Runnable {
public:
@@ -61,14 +56,8 @@ namespace qmf {
void setDomain(const std::string& d) { domain = d; }
void setAgentFilter(const std::string& f);
void open();
- void closeAsync();
void close();
bool nextEvent(ConsoleEvent& e, qpid::messaging::Duration t);
- int pendingEvents() const;
-
- void setEventNotifier(EventNotifierImpl* notifier);
- EventNotifierImpl* getEventNotifier() const;
-
uint32_t getAgentCount() const;
Agent getAgent(uint32_t i) const;
Agent getConnectedBrokerAgent() const { return connectedBrokerAgent; }
@@ -86,11 +75,9 @@ namespace qmf {
uint32_t maxAgentAgeMinutes;
bool listenOnDirect;
bool strictSecurity;
- uint32_t maxThreadWaitTime;
Query agentQuery;
bool opened;
std::queue<ConsoleEvent> eventQueue;
- EventNotifierImpl* eventNotifier;
qpid::sys::Thread* thread;
bool threadCanceled;
uint64_t lastVisit;
@@ -102,8 +89,6 @@ namespace qmf {
std::string directBase;
std::string topicBase;
boost::shared_ptr<SchemaCache> schemaCache;
- qpid::sys::Mutex corrlock;
- uint32_t nextCorrelator;
void enqueueEvent(const ConsoleEvent&);
void enqueueEventLH(const ConsoleEvent&);
@@ -113,17 +98,10 @@ namespace qmf {
void handleAgentUpdate(const std::string&, const qpid::types::Variant::Map&, const qpid::messaging::Message&);
void handleV1SchemaResponse(qpid::management::Buffer&, uint32_t, const qpid::messaging::Message&);
void periodicProcessing(uint64_t);
- void alertEventNotifierLH(bool readable);
void run();
- uint32_t correlator() { qpid::sys::Mutex::ScopedLock l(corrlock); return nextCorrelator++; }
friend class AgentImpl;
};
-
- struct ConsoleSessionImplAccess {
- static ConsoleSessionImpl& get(ConsoleSession& session);
- static const ConsoleSessionImpl& get(const ConsoleSession& session);
- };
}
#endif
diff --git a/cpp/src/qmf/DataAddr.cpp b/cpp/src/qmf/DataAddr.cpp
index d16e12062e..fb51d5787f 100644
--- a/cpp/src/qmf/DataAddr.cpp
+++ b/cpp/src/qmf/DataAddr.cpp
@@ -36,9 +36,7 @@ DataAddr::~DataAddr() { PI::dtor(*this); }
DataAddr& DataAddr::operator=(const DataAddr& s) { return PI::assign(*this, s); }
bool DataAddr::operator==(const DataAddr& o) { return *impl == *o.impl; }
-bool DataAddr::operator==(const DataAddr& o) const { return *impl == *o.impl; }
bool DataAddr::operator<(const DataAddr& o) { return *impl < *o.impl; }
-bool DataAddr::operator<(const DataAddr& o) const { return *impl < *o.impl; }
DataAddr::DataAddr(const qpid::types::Variant::Map& m) { PI::ctor(*this, new DataAddrImpl(m)); }
DataAddr::DataAddr(const string& n, const string& a, uint32_t e) { PI::ctor(*this, new DataAddrImpl(n, a, e)); }
@@ -47,7 +45,7 @@ const string& DataAddr::getAgentName() const { return impl->getAgentName(); }
uint32_t DataAddr::getAgentEpoch() const { return impl->getAgentEpoch(); }
Variant::Map DataAddr::asMap() const { return impl->asMap(); }
-bool DataAddrImpl::operator==(const DataAddrImpl& other) const
+bool DataAddrImpl::operator==(const DataAddrImpl& other)
{
return
agentName == other.agentName &&
@@ -56,7 +54,7 @@ bool DataAddrImpl::operator==(const DataAddrImpl& other) const
}
-bool DataAddrImpl::operator<(const DataAddrImpl& other) const
+bool DataAddrImpl::operator<(const DataAddrImpl& other)
{
if (agentName < other.agentName) return true;
if (agentName > other.agentName) return false;
diff --git a/cpp/src/qmf/DataAddrImpl.h b/cpp/src/qmf/DataAddrImpl.h
index 11d512f0c4..3f9cae9453 100644
--- a/cpp/src/qmf/DataAddrImpl.h
+++ b/cpp/src/qmf/DataAddrImpl.h
@@ -38,8 +38,8 @@ namespace qmf {
//
// Methods from API handle
//
- bool operator==(const DataAddrImpl&) const;
- bool operator<(const DataAddrImpl&) const;
+ bool operator==(const DataAddrImpl&);
+ bool operator<(const DataAddrImpl&);
DataAddrImpl(const qpid::types::Variant::Map&);
DataAddrImpl(const std::string& _name, const std::string& _agentName, uint32_t _agentEpoch=0) :
agentName(_agentName), name(_name), agentEpoch(_agentEpoch) {}
diff --git a/cpp/src/qmf/EventNotifierImpl.cpp b/cpp/src/qmf/EventNotifierImpl.cpp
deleted file mode 100644
index 20114aaa5e..0000000000
--- a/cpp/src/qmf/EventNotifierImpl.cpp
+++ /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.
- */
-
-#include "qmf/EventNotifierImpl.h"
-#include "qmf/AgentSessionImpl.h"
-#include "qmf/ConsoleSessionImpl.h"
-
-EventNotifierImpl::EventNotifierImpl(AgentSession& agentSession)
- : readable(false), agent(agentSession)
-{
- AgentSessionImplAccess::get(agent).setEventNotifier(this);
-}
-
-
-EventNotifierImpl::EventNotifierImpl(ConsoleSession& consoleSession)
- : readable(false), console(consoleSession)
-{
- ConsoleSessionImplAccess::get(console).setEventNotifier(this);
-}
-
-
-EventNotifierImpl::~EventNotifierImpl()
-{
- if (agent.isValid())
- AgentSessionImplAccess::get(agent).setEventNotifier(NULL);
- if (console.isValid())
- ConsoleSessionImplAccess::get(console).setEventNotifier(NULL);
-}
-
-void EventNotifierImpl::setReadable(bool readable)
-{
- update(readable);
- this->readable = readable;
-}
-
-
-bool EventNotifierImpl::isReadable() const
-{
- return this->readable;
-}
diff --git a/cpp/src/qmf/EventNotifierImpl.h b/cpp/src/qmf/EventNotifierImpl.h
deleted file mode 100644
index d85f9979d2..0000000000
--- a/cpp/src/qmf/EventNotifierImpl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __QMF_EVENT_NOTIFIER_IMPL_H
-#define __QMF_EVENT_NOTIFIER_IMPL_H
-
-/*
- * 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/AgentSession.h"
-#include "qmf/ConsoleSession.h"
-
-namespace qmf
-{
- class EventNotifierImpl {
- private:
- bool readable;
- AgentSession agent;
- ConsoleSession console;
-
- public:
- EventNotifierImpl(AgentSession& agentSession);
- EventNotifierImpl(ConsoleSession& consoleSession);
- virtual ~EventNotifierImpl();
-
- void setReadable(bool readable);
- bool isReadable() const;
-
- protected:
- virtual void update(bool readable) = 0;
- };
-}
-
-#endif
-
diff --git a/cpp/src/qmf/PosixEventNotifier.cpp b/cpp/src/qmf/PosixEventNotifier.cpp
deleted file mode 100644
index a364cc155d..0000000000
--- a/cpp/src/qmf/PosixEventNotifier.cpp
+++ /dev/null
@@ -1,65 +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/posix/EventNotifier.h"
-#include "qmf/PosixEventNotifierImpl.h"
-#include "qmf/PrivateImplRef.h"
-
-using namespace qmf;
-using namespace std;
-
-typedef qmf::PrivateImplRef<posix::EventNotifier> PI;
-
-posix::EventNotifier::EventNotifier(PosixEventNotifierImpl* impl) { PI::ctor(*this, impl); }
-
-posix::EventNotifier::EventNotifier(AgentSession& agentSession)
-{
- PI::ctor(*this, new PosixEventNotifierImpl(agentSession));
-}
-
-
-posix::EventNotifier::EventNotifier(ConsoleSession& consoleSession)
-{
- PI::ctor(*this, new PosixEventNotifierImpl(consoleSession));
-}
-
-
-posix::EventNotifier::EventNotifier(const posix::EventNotifier& that)
- : Handle<PosixEventNotifierImpl>()
-{
- PI::copy(*this, that);
-}
-
-
-posix::EventNotifier::~EventNotifier()
-{
- PI::dtor(*this);
-}
-
-posix::EventNotifier& posix::EventNotifier::operator=(const posix::EventNotifier& that)
-{
- return PI::assign(*this, that);
-}
-
-
-int posix::EventNotifier::getHandle() const
-{
- return impl->getHandle();
-}
-
diff --git a/cpp/src/qmf/PosixEventNotifierImpl.cpp b/cpp/src/qmf/PosixEventNotifierImpl.cpp
deleted file mode 100644
index 011dbcc214..0000000000
--- a/cpp/src/qmf/PosixEventNotifierImpl.cpp
+++ /dev/null
@@ -1,112 +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 "PosixEventNotifierImpl.h"
-#include "qpid/log/Statement.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define BUFFER_SIZE 10
-
-using namespace qmf;
-
-PosixEventNotifierImpl::PosixEventNotifierImpl(AgentSession& agentSession)
- : EventNotifierImpl(agentSession)
-{
- openHandle();
-}
-
-
-PosixEventNotifierImpl::PosixEventNotifierImpl(ConsoleSession& consoleSession)
- : EventNotifierImpl(consoleSession)
-{
- openHandle();
-}
-
-
-PosixEventNotifierImpl::~PosixEventNotifierImpl()
-{
- closeHandle();
-}
-
-
-void PosixEventNotifierImpl::update(bool readable)
-{
- char buffer[BUFFER_SIZE];
-
- if(readable && !this->isReadable()) {
- if (::write(myHandle, "1", 1) == -1)
- QPID_LOG(error, "PosixEventNotifierImpl::update write failed: " << errno);
- }
- else if(!readable && this->isReadable()) {
- if (::read(yourHandle, buffer, BUFFER_SIZE) == -1)
- QPID_LOG(error, "PosixEventNotifierImpl::update read failed: " << errno);
- }
-}
-
-
-void PosixEventNotifierImpl::openHandle()
-{
- int pair[2];
-
- if(::pipe(pair) == -1)
- throw QmfException("Unable to open event notifier handle.");
-
- yourHandle = pair[0];
- myHandle = pair[1];
-
- int flags;
-
- flags = ::fcntl(yourHandle, F_GETFL);
- if((::fcntl(yourHandle, F_SETFL, flags | O_NONBLOCK)) == -1)
- throw QmfException("Unable to make remote handle non-blocking.");
-
- flags = ::fcntl(myHandle, F_GETFL);
- if((::fcntl(myHandle, F_SETFL, flags | O_NONBLOCK)) == -1)
- throw QmfException("Unable to make local handle non-blocking.");
-}
-
-
-void PosixEventNotifierImpl::closeHandle()
-{
- if(myHandle > 0) {
- ::close(myHandle);
- myHandle = -1;
- }
-
- if(yourHandle > 0) {
- ::close(yourHandle);
- yourHandle = -1;
- }
-}
-
-
-PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(posix::EventNotifier& notifier)
-{
- return *notifier.impl;
-}
-
-
-const PosixEventNotifierImpl& PosixEventNotifierImplAccess::get(const posix::EventNotifier& notifier)
-{
- return *notifier.impl;
-}
-
diff --git a/cpp/src/qmf/PosixEventNotifierImpl.h b/cpp/src/qmf/PosixEventNotifierImpl.h
deleted file mode 100644
index c8a7446bd5..0000000000
--- a/cpp/src/qmf/PosixEventNotifierImpl.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __QMF_POSIX_EVENT_NOTIFIER_IMPL_H
-#define __QMF_POSIX_EVENT_NOTIFIER_IMPL_H
-
-/*
- * 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/posix/EventNotifier.h"
-#include "qmf/EventNotifierImpl.h"
-#include "qpid/RefCounted.h"
-
-namespace qmf
-{
- class AgentSession;
- class ConsoleSession;
-
- class PosixEventNotifierImpl : public EventNotifierImpl, public virtual qpid::RefCounted
- {
- public:
- PosixEventNotifierImpl(AgentSession& agentSession);
- PosixEventNotifierImpl(ConsoleSession& consoleSession);
- virtual ~PosixEventNotifierImpl();
-
- int getHandle() const { return yourHandle; }
-
- private:
- int myHandle;
- int yourHandle;
-
- void openHandle();
- void closeHandle();
-
- protected:
- void update(bool readable);
- };
-
- struct PosixEventNotifierImplAccess
- {
- static PosixEventNotifierImpl& get(posix::EventNotifier& notifier);
- static const PosixEventNotifierImpl& get(const posix::EventNotifier& notifier);
- };
-
-}
-
-#endif
-
diff --git a/cpp/src/qmf/PrivateImplRef.h b/cpp/src/qmf/PrivateImplRef.h
index 960cbb2e09..8b698c4199 100644
--- a/cpp/src/qmf/PrivateImplRef.h
+++ b/cpp/src/qmf/PrivateImplRef.h
@@ -23,8 +23,8 @@
*/
#include "qmf/ImportExport.h"
-#include "qpid/RefCounted.h"
#include <boost/intrusive_ptr.hpp>
+#include "qpid/RefCounted.h"
namespace qmf {
diff --git a/cpp/src/qmf/engine/ResilientConnection.cpp b/cpp/src/qmf/engine/ResilientConnection.cpp
index 41dd9ff00c..ab65b8d768 100644
--- a/cpp/src/qmf/engine/ResilientConnection.cpp
+++ b/cpp/src/qmf/engine/ResilientConnection.cpp
@@ -334,7 +334,8 @@ void ResilientConnectionImpl::notify()
{
if (notifyFd != -1)
{
- (void) ::write(notifyFd, ".", 1);
+ int unused_ret; //Suppress warnings about ignoring return value.
+ unused_ret = ::write(notifyFd, ".", 1);
}
}
@@ -431,7 +432,8 @@ void ResilientConnectionImpl::EnqueueEvent(ResilientConnectionEvent::EventKind k
if (notifyFd != -1)
{
- (void) ::write(notifyFd, ".", 1);
+ int unused_ret; //Suppress warnings about ignoring return value.
+ unused_ret = ::write(notifyFd, ".", 1);
}
}
diff --git a/cpp/src/qmf/engine/SchemaImpl.cpp b/cpp/src/qmf/engine/SchemaImpl.cpp
index 9d363d3012..e0948a9911 100644
--- a/cpp/src/qmf/engine/SchemaImpl.cpp
+++ b/cpp/src/qmf/engine/SchemaImpl.cpp
@@ -35,17 +35,17 @@ using qpid::framing::Uuid;
SchemaHash::SchemaHash()
{
for (int idx = 0; idx < 16; idx++)
- hash.b[idx] = 0x5A;
+ hash[idx] = 0x5A;
}
void SchemaHash::encode(Buffer& buffer) const
{
- buffer.putBin128(hash.b);
+ buffer.putBin128(hash);
}
void SchemaHash::decode(Buffer& buffer)
{
- buffer.getBin128(hash.b);
+ buffer.getBin128(hash);
}
void SchemaHash::update(uint8_t data)
@@ -55,8 +55,9 @@ void SchemaHash::update(uint8_t data)
void SchemaHash::update(const char* data, uint32_t len)
{
- uint64_t* first = &hash.q[0];
- uint64_t* second = &hash.q[1];
+ uint64_t* first = (uint64_t*) hash;
+ uint64_t* second = (uint64_t*) hash + 1;
+
for (uint32_t idx = 0; idx < len; idx++) {
*first = *first ^ (uint64_t) data[idx];
*second = *second << 1;
diff --git a/cpp/src/qmf/engine/SchemaImpl.h b/cpp/src/qmf/engine/SchemaImpl.h
index 683fb6f8f0..8b079a5ec6 100644
--- a/cpp/src/qmf/engine/SchemaImpl.h
+++ b/cpp/src/qmf/engine/SchemaImpl.h
@@ -35,10 +35,7 @@ namespace engine {
// they've been registered.
class SchemaHash {
- union h {
- uint8_t b[16];
- uint64_t q[2];
- } hash;
+ uint8_t hash[16];
public:
SchemaHash();
void encode(qpid::framing::Buffer& buffer) const;
@@ -50,7 +47,7 @@ namespace engine {
void update(Direction d) { update((uint8_t) d); }
void update(Access a) { update((uint8_t) a); }
void update(bool b) { update((uint8_t) (b ? 1 : 0)); }
- const uint8_t* get() const { return hash.b; }
+ const uint8_t* get() const { return hash; }
bool operator==(const SchemaHash& other) const;
bool operator<(const SchemaHash& other) const;
bool operator>(const SchemaHash& other) const;
diff --git a/cpp/src/qpid/Address.cpp b/cpp/src/qpid/Address.cpp
index bed3d592df..e2b2dfbcdf 100644
--- a/cpp/src/qpid/Address.cpp
+++ b/cpp/src/qpid/Address.cpp
@@ -28,13 +28,7 @@ namespace qpid {
const string Address::TCP("tcp");
ostream& operator<<(ostream& os, const Address& a) {
- // If the host is an IPv6 literal we need to print "[]" around it
- // (we detect IPv6 literals because they contain ":" which is otherwise illegal)
- if (a.host.find(':') != string::npos) {
- return os << a.protocol << ":[" << a.host << "]:" << a.port;
- } else {
- return os << a.protocol << ":" << a.host << ":" << a.port;
- }
+ return os << a.protocol << ":" << a.host << ":" << a.port;
}
bool operator==(const Address& x, const Address& y) {
diff --git a/cpp/src/qpid/BufferRef.h b/cpp/src/qpid/BufferRef.h
deleted file mode 100644
index bfe1f9ebaa..0000000000
--- a/cpp/src/qpid/BufferRef.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef QPID_BUFFERREF_H
-#define QPID_BUFFERREF_H
-
-/*
- *
- * 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 "qpid/RefCounted.h"
-#include <boost/intrusive_ptr.hpp>
-
-namespace qpid {
-
-/** Template for mutable or const buffer references */
-template <class T> class BufferRefT {
- public:
- BufferRefT() : begin_(0), end_(0) {}
-
- BufferRefT(boost::intrusive_ptr<RefCounted> c, T* begin, T* end) :
- counter(c), begin_(begin), end_(end) {}
-
- template <class U> BufferRefT(const BufferRefT<U>& other) :
- counter(other.counter), begin_(other.begin_), end_(other.end_) {}
-
- T* begin() const { return begin_; }
- T* end() const { return end_; }
-
- /** Return a sub-buffer of the current buffer */
- BufferRefT sub_buffer(T* begin, T* end) {
- assert(begin_ <= begin && begin <= end_);
- assert(begin_ <= end && end <= end_);
- assert(begin <= end);
- return BufferRefT(counter, begin, end);
- }
-
- private:
- boost::intrusive_ptr<RefCounted> counter;
- T* begin_;
- T* end_;
-};
-
-/**
- * Reference to a mutable ref-counted buffer.
- */
-typedef BufferRefT<char> BufferRef;
-
-/**
- * Reference to a const ref-counted buffer.
- */
-typedef BufferRefT<const char> ConstBufferRef;
-
-} // namespace qpid
-
-#endif /*!QPID_BUFFERREF_H*/
diff --git a/cpp/src/qpid/DisableExceptionLogging.h b/cpp/src/qpid/DisableExceptionLogging.h
deleted file mode 100644
index 04a9240513..0000000000
--- a/cpp/src/qpid/DisableExceptionLogging.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef QPID_DISABLEEXCEPTIONLOGGING_H
-#define QPID_DISABLEEXCEPTIONLOGGING_H
-
-/*
- *
- * 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 "qpid/CommonImportExport.h"
-
-namespace qpid {
-
-/**
- * Temporarily disable logging in qpid::Exception constructor.
- * Used by log::Logger to avoid logging exceptions during Logger construction.
- */
-struct DisableExceptionLogging
-{
- QPID_COMMON_EXTERN DisableExceptionLogging();
- QPID_COMMON_EXTERN ~DisableExceptionLogging();
-};
-} // namespace qpid
-
-#endif /*!QPID_DISABLEEXCEPTIONLOGGING_H*/
diff --git a/cpp/src/qpid/Exception.cpp b/cpp/src/qpid/Exception.cpp
index a6696f06e1..16a3a13d17 100644
--- a/cpp/src/qpid/Exception.cpp
+++ b/cpp/src/qpid/Exception.cpp
@@ -7,9 +7,9 @@
* 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
@@ -21,25 +21,13 @@
#include "qpid/log/Statement.h"
#include "qpid/Exception.h"
-#include "qpid/DisableExceptionLogging.h"
#include <typeinfo>
#include <assert.h>
#include <string.h>
namespace qpid {
-// Note on static initialization order: if an exception is constructed
-// in a static constructor before disableExceptionLogging has been
-// initialized, the worst that can happen is we lose an exception log
-// message. Since we shouldn't be throwing a lot of exceptions during
-// static construction this seems safe.
-static bool disableExceptionLogging = false;
-
-DisableExceptionLogging::DisableExceptionLogging() { disableExceptionLogging = true; }
-DisableExceptionLogging::~DisableExceptionLogging() { disableExceptionLogging = false; }
-
Exception::Exception(const std::string& msg) throw() : message(msg) {
- if (disableExceptionLogging) return;
QPID_LOG_IF(debug, !msg.empty(), "Exception constructed: " << message);
}
diff --git a/cpp/src/qpid/Modules.cpp b/cpp/src/qpid/Modules.cpp
index 727e05d212..8f58df6ed1 100644
--- a/cpp/src/qpid/Modules.cpp
+++ b/cpp/src/qpid/Modules.cpp
@@ -64,6 +64,7 @@ void tryShlib(const char* libname_, bool noThrow) {
if (!isShlibName(libname)) libname += suffix();
try {
sys::Shlib shlib(libname);
+ QPID_LOG (info, "Loaded Module: " << libname);
}
catch (const std::exception& /*e*/) {
if (!noThrow)
@@ -81,7 +82,7 @@ void loadModuleDir (std::string dirname, bool isDefault)
return;
throw Exception ("Directory not found: " + dirname);
}
- if (!fs::is_directory(dirPath))
+ if (!fs::is_directory(dirPath))
{
throw Exception ("Invalid value for module-dir: " + dirname + " is not a directory");
}
diff --git a/cpp/src/qpid/Options.cpp b/cpp/src/qpid/Options.cpp
index 4b13e349f5..499fb71bc3 100644
--- a/cpp/src/qpid/Options.cpp
+++ b/cpp/src/qpid/Options.cpp
@@ -30,6 +30,23 @@ namespace qpid {
using namespace std;
+/*
+ * ---------------------------------------------
+ * Explanation for Boost 103200 conditional code
+ * ---------------------------------------------
+ *
+ * Please see large comment in Options.h .
+ *
+ */
+
+#if ( BOOST_VERSION == 103200 )
+std::vector<std::string> Options::long_names;
+std::vector<std::string> Options::short_names;
+#endif
+
+
+
+
namespace {
struct EnvOptMapper {
@@ -52,11 +69,49 @@ struct EnvOptMapper {
static const std::string prefix("QPID_");
if (envVar.substr(0, prefix.size()) == prefix) {
string env = envVar.substr(prefix.size());
+#if (BOOST_VERSION >= 103300)
typedef const std::vector< boost::shared_ptr<po::option_description> > OptDescs;
OptDescs::const_iterator i =
find_if(opts.options().begin(), opts.options().end(), boost::bind(matchStr, env, _1));
if (i != opts.options().end())
return (*i)->long_name();
+#else
+ /*
+ * For Boost version 103200 and below.
+ *
+ * In Boost version 103200, the options_description::options member,
+ * used above, is private. So what I will do here is use the
+ * count() funtion, which returns a 1 or 0 indicating presence or
+ * absence of the environment variable.
+ *
+ * If it is present, I will return its name. Env vars do not have
+ * short and long forms, so the name is synonymous with the long
+ * name. (This would not work for command line args.)
+ * And if it's absent -- an empty string.
+ */
+
+
+ /*
+ * The env vars come in unaltered, i.e. QPID_FOO, but the
+ * options are stored normalized as "qpid-foo". Change the
+ * local variable "env" so it can be found by "opts".
+ */
+ for (std::string::iterator i = env.begin(); i != env.end(); ++i)
+ {
+ *i = (*i == '_')
+ ? '-'
+ : ::tolower(*i);
+ }
+
+ if ( opts.count(env.c_str()) > 0 )
+ {
+ return env.c_str();
+ }
+ else
+ {
+ return string();
+ }
+#endif
}
return string();
}
@@ -111,6 +166,10 @@ std::string prettyArg(const std::string& name, const std::string& value) {
Options::Options(const string& name) :
po::options_description(name)
+
+#if ( BOOST_VERSION == 103200 )
+ , m_less_easy(this, this)
+#endif
{
}
@@ -127,6 +186,7 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
parsing="command line options";
if (argc > 0 && argv != 0) {
if (allowUnknown) {
+#if (BOOST_VERSION >= 103300)
// This hideous workaround is required because boost 1.33 has a bug
// that causes 'allow_unregistered' to not work.
po::command_line_parser clp = po::command_line_parser(argc, const_cast<char**>(argv)).
@@ -140,6 +200,113 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
filtopts.options.push_back (*i);
po::store(filtopts, vm);
+#elif ( BOOST_VERSION == 103200 )
+
+ /*
+ * "Tokenize" the argv to get rid of equals signs.
+ */
+ vector<string> tokenized_argv;
+ vector<string>::iterator iter;
+
+ for ( int i = 0; i < argc; ++ i )
+ {
+ string s = argv[i];
+ size_t equals_pos = s.find_first_of ( '=' );
+
+ if ( string::npos == equals_pos ) // There's no equals sign. This is a token.
+ {
+ tokenized_argv.push_back(s);
+ }
+ else
+ {
+ // Two tokens -- before and after the equals position.
+ tokenized_argv.push_back ( s.substr(0, equals_pos) );
+ tokenized_argv.push_back ( s.substr(equals_pos+1) );
+ }
+ }
+
+
+ /*
+ * Now "filter" the tokenized argv, to get rid of all
+ * unrecognized options. Because Boost 103200 has no
+ * facility for dealing gracefully with "unregistered"
+ * options.
+ */
+ vector<string> filtered_argv;
+ vector<string>::iterator the_end = tokenized_argv.end();
+
+ // The program-name gets in for free...
+ iter = tokenized_argv.begin();
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // ...but all other args get checked.
+ while ( iter < the_end )
+ {
+ /*
+ * If this is an argument that is registered,
+ * copy it to filtered_argv and also copy all
+ * of its arguments.
+ */
+ if ( is_registered_option ( * iter ) )
+ {
+ // Store this recognized arg.
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Args are tokens that do not start with a minus.
+ while ( (iter < the_end) && ((* iter)[0] != '-') )
+ {
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+ }
+ }
+ else
+ {
+ // Skip this unrecognized arg.
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Values are tokens that do not start with a minus.
+ while ( (iter < the_end) && ( '-' != (*iter)[0] ) )
+ {
+ ++ iter;
+ }
+ }
+ }
+
+ // Make an array of temporary C strings, because
+ // the interface I can use wants it that way.
+ int new_argc = filtered_argv.size();
+ char ** new_argv = new char * [ new_argc ];
+ int i = 0;
+
+ // cout << "NEW ARGV: |";
+ for ( iter = filtered_argv.begin();
+ iter < filtered_argv.end();
+ ++ iter, ++ i
+ )
+ {
+ new_argv[i] = strdup( (* iter).c_str() );
+ // cout << " " << new_argv[i] ;
+ }
+ // cout << "|\n";
+
+
+ // Use the array of C strings.
+ po::basic_parsed_options<char> bpo = po::parse_command_line(new_argc, const_cast<char**>(new_argv), *this);
+ po::store(bpo, vm);
+
+
+ // Now free the temporary C strings.
+ for ( i = 0; i < new_argc; ++ i )
+ {
+ free ( new_argv[i] );
+ }
+ delete[] new_argv;
+
+#endif
}
else
po::store(po::parse_command_line(argc, const_cast<char**>(argv), *this), vm);
@@ -196,5 +363,107 @@ CommonOptions::CommonOptions(const string& name, const string& configfile)
}
+
+
+#if ( BOOST_VERSION == 103200 )
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ char const * description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, description );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ const po::value_semantic* s)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(const char* name,
+ const po::value_semantic* s,
+ const char* description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s, description );
+ return * this;
+}
+
+
+
+
+
+void
+Options::register_names ( std::string s )
+{
+
+ std::string::size_type comma_pos = s.find_first_of ( ',' );
+
+ if ( std::string::npos == comma_pos )
+ {
+ // There is no short-name.
+ long_names.push_back ( s );
+ }
+ else
+ {
+ std::string long_name = s.substr(0, comma_pos),
+ short_name = s.substr(comma_pos+1);
+ long_names .push_back ( long_name );
+ short_names.push_back ( short_name );
+ }
+
+ /*
+ * There is no way to tell when the adding of new options is finished,
+ * so I re-sort after each one.
+ */
+ std::sort ( long_names .begin(), long_names .end() );
+ std::sort ( short_names.begin(), short_names.end() );
+}
+
+
+
+
+
+bool
+Options::is_registered_option ( std::string s )
+{
+ std::string without_dashes = s.substr ( s.find_first_not_of ( '-' ) );
+ std::vector<std::string>::iterator i;
+
+ // Look among the long names.
+ i = std::find ( long_names.begin(),
+ long_names.end(),
+ without_dashes
+ );
+ if ( i != long_names.end() )
+ return true;
+
+ // Look among the short names.
+ i = std::find ( short_names.begin(),
+ short_names.end(),
+ without_dashes
+ );
+ if ( i != short_names.end() )
+ return true;
+
+
+ return false;
+}
+#endif
+
+
} // namespace qpid
diff --git a/cpp/src/qpid/RefCounted.h b/cpp/src/qpid/RefCounted.h
index f9e0107103..e7a9bf31c1 100644
--- a/cpp/src/qpid/RefCounted.h
+++ b/cpp/src/qpid/RefCounted.h
@@ -53,10 +53,8 @@ protected:
// intrusive_ptr support.
namespace boost {
-template <typename T>
-inline void intrusive_ptr_add_ref(const T* p) { p->qpid::RefCounted::addRef(); }
-template <typename T>
-inline void intrusive_ptr_release(const T* p) { p->qpid::RefCounted::release(); }
+inline void intrusive_ptr_add_ref(const qpid::RefCounted* p) { p->addRef(); }
+inline void intrusive_ptr_release(const qpid::RefCounted* p) { p->release(); }
}
diff --git a/cpp/src/qpid/RefCountedBuffer.cpp b/cpp/src/qpid/RefCountedBuffer.cpp
index a82e1a02ab..9b8f1ebd5e 100644
--- a/cpp/src/qpid/RefCountedBuffer.cpp
+++ b/cpp/src/qpid/RefCountedBuffer.cpp
@@ -20,27 +20,34 @@
*/
#include "qpid/RefCountedBuffer.h"
-#include <stdlib.h>
#include <new>
namespace qpid {
-void RefCountedBuffer::released() const {
+RefCountedBuffer::RefCountedBuffer() : count(0) {}
+
+void RefCountedBuffer::destroy() const {
this->~RefCountedBuffer();
- ::free (reinterpret_cast<void *>(const_cast<RefCountedBuffer *>(this)));
+ ::delete[] reinterpret_cast<const char*>(this);
+}
+
+char* RefCountedBuffer::addr() const {
+ return const_cast<char*>(reinterpret_cast<const char*>(this)+sizeof(RefCountedBuffer));
}
-BufferRef RefCountedBuffer::create(size_t n) {
- void* store=::malloc (n + sizeof(RefCountedBuffer));
- if (NULL == store)
- throw std::bad_alloc();
+RefCountedBuffer::pointer RefCountedBuffer::create(size_t n) {
+ char* store=::new char[n+sizeof(RefCountedBuffer)];
new(store) RefCountedBuffer;
- char* start = reinterpret_cast<char *>(store) + sizeof(RefCountedBuffer);
- return BufferRef(
- boost::intrusive_ptr<RefCounted>(reinterpret_cast<RefCountedBuffer*>(store)),
- start, start+n);
+ return pointer(reinterpret_cast<RefCountedBuffer*>(store));
}
+RefCountedBuffer::pointer::pointer() {}
+RefCountedBuffer::pointer::pointer(RefCountedBuffer* x) : p(x) {}
+RefCountedBuffer::pointer::pointer(const pointer& x) : p(x.p) {}
+RefCountedBuffer::pointer::~pointer() {}
+RefCountedBuffer::pointer& RefCountedBuffer::pointer::operator=(const RefCountedBuffer::pointer& x) { p = x.p; return *this; }
+
+char* RefCountedBuffer::pointer::cp() const { return p ? p->get() : 0; }
} // namespace qpid
diff --git a/cpp/src/qpid/RefCountedBuffer.h b/cpp/src/qpid/RefCountedBuffer.h
index f0ea86130b..75a23862be 100644
--- a/cpp/src/qpid/RefCountedBuffer.h
+++ b/cpp/src/qpid/RefCountedBuffer.h
@@ -22,23 +22,68 @@
*
*/
-#include <qpid/RefCounted.h>
-#include <qpid/BufferRef.h>
+#include <boost/utility.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/intrusive_ptr.hpp>
namespace qpid {
/**
- * Reference-counted byte buffer. No alignment guarantees.
+ * Reference-counted byte buffer.
+ * No alignment guarantees.
*/
-class RefCountedBuffer : public RefCounted {
- public:
+class RefCountedBuffer : boost::noncopyable {
+ mutable boost::detail::atomic_count count;
+ RefCountedBuffer();
+ void destroy() const;
+ char* addr() const;
+
+public:
+ /** Smart char pointer to a reference counted buffer */
+ class pointer {
+ boost::intrusive_ptr<RefCountedBuffer> p;
+ char* cp() const;
+ pointer(RefCountedBuffer* x);
+ friend class RefCountedBuffer;
+
+ public:
+ pointer();
+ pointer(const pointer&);
+ ~pointer();
+ pointer& operator=(const pointer&);
+
+ char* get() { return cp(); }
+ operator char*() { return cp(); }
+ char& operator*() { return *cp(); }
+ char& operator[](size_t i) { return cp()[i]; }
+
+ const char* get() const { return cp(); }
+ operator const char*() const { return cp(); }
+ const char& operator*() const { return *cp(); }
+ const char& operator[](size_t i) const { return cp()[i]; }
+ };
+
/** Create a reference counted buffer of size n */
- static BufferRef create(size_t n);
+ static pointer create(size_t n);
+
+ /** Get a pointer to the start of the buffer. */
+ char* get() { return addr(); }
+ const char* get() const { return addr(); }
+ char& operator[](size_t i) { return get()[i]; }
+ const char& operator[](size_t i) const { return get()[i]; }
- protected:
- void released() const;
+ void addRef() const { ++count; }
+ void release() const { if (--count==0) destroy(); }
+ long refCount() { return count; }
};
} // namespace qpid
+// intrusive_ptr support.
+namespace boost {
+inline void intrusive_ptr_add_ref(const qpid::RefCountedBuffer* p) { p->addRef(); }
+inline void intrusive_ptr_release(const qpid::RefCountedBuffer* p) { p->release(); }
+}
+
+
#endif /*!QPID_REFCOUNTEDBUFFER_H*/
diff --git a/cpp/src/qpid/Sasl.h b/cpp/src/qpid/Sasl.h
index 4d579fa051..9a9d61b037 100644
--- a/cpp/src/qpid/Sasl.h
+++ b/cpp/src/qpid/Sasl.h
@@ -47,8 +47,8 @@ class Sasl
* client supports.
* @param externalSecuritySettings security related details from the underlying transport
*/
- virtual bool start(const std::string& mechanisms, std::string& response,
- const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0;
+ virtual std::string start(const std::string& mechanisms,
+ const qpid::sys::SecuritySettings* externalSecuritySettings = 0) = 0;
virtual std::string step(const std::string& challenge) = 0;
virtual std::string getMechanism() = 0;
virtual std::string getUserId() = 0;
diff --git a/cpp/src/qpid/SaslFactory.cpp b/cpp/src/qpid/SaslFactory.cpp
index a8d1f94c1e..055883abee 100644
--- a/cpp/src/qpid/SaslFactory.cpp
+++ b/cpp/src/qpid/SaslFactory.cpp
@@ -112,7 +112,7 @@ class CyrusSasl : public Sasl
public:
CyrusSasl(const std::string & username, const std::string & password, const std::string & serviceName, const std::string & hostName, int minSsf, int maxSsf, bool allowInteraction);
~CyrusSasl();
- bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings);
+ std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings);
std::string step(const std::string& challenge);
std::string getMechanism();
std::string getUserId();
@@ -182,17 +182,16 @@ CyrusSasl::CyrusSasl(const std::string & username, const std::string & password,
callbacks[i].id = SASL_CB_AUTHNAME;
callbacks[i].proc = (CallbackProc*) &getUserFromSettings;
callbacks[i++].context = &settings;
-
- callbacks[i].id = SASL_CB_PASS;
- if (settings.password.empty()) {
- callbacks[i].proc = 0;
- callbacks[i++].context = 0;
- } else {
- callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings;
- callbacks[i++].context = &settings;
- }
}
+ callbacks[i].id = SASL_CB_PASS;
+ if (settings.password.empty()) {
+ callbacks[i].proc = 0;
+ callbacks[i++].context = 0;
+ } else {
+ callbacks[i].proc = (CallbackProc*) &getPasswordFromSettings;
+ callbacks[i++].context = &settings;
+ }
callbacks[i].id = SASL_CB_LIST_END;
callbacks[i].proc = 0;
@@ -210,7 +209,7 @@ namespace {
const std::string SSL("ssl");
}
-bool CyrusSasl::start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings)
+std::string CyrusSasl::start(const std::string& mechanisms, const SecuritySettings* externalSettings)
{
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")");
int result = sasl_client_new(settings.service.c_str(),
@@ -283,12 +282,7 @@ bool CyrusSasl::start(const std::string& mechanisms, std::string& response, cons
mechanism = std::string(chosenMechanism);
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected "
<< mechanism << " response: '" << std::string(out, outlen) << "'");
- if (out) {
- response = std::string(out, outlen);
- return true;
- } else {
- return false;
- }
+ return std::string(out, outlen);
}
std::string CyrusSasl::step(const std::string& challenge)
diff --git a/cpp/src/qpid/Url.cpp b/cpp/src/qpid/Url.cpp
index f699b60c17..ab796f4642 100644
--- a/cpp/src/qpid/Url.cpp
+++ b/cpp/src/qpid/Url.cpp
@@ -156,12 +156,11 @@ class UrlParser {
return false;
}
- // A liberal interpretation of http://www.ietf.org/rfc/rfc3986.txt.
- // Works for DNS names and and ipv4 and ipv6 literals
+ // TODO aconway 2008-11-20: this does not fully implement
+ // http://www.ietf.org/rfc/rfc3986.txt. Works for DNS names and
+ // ipv4 literals but won't handle ipv6.
//
bool host(string& h) {
- if (ip6literal(h)) return true;
-
const char* start=i;
while (unreserved() || pctEncoded())
;
@@ -170,22 +169,6 @@ class UrlParser {
return true;
}
- // This is a bit too liberal for IPv6 literal addresses, but probably good enough
- bool ip6literal(string& h) {
- if (literal("[")) {
- const char* start = i;
- while (hexDigit() || literal(":") || literal("."))
- ;
- const char* end = i;
- if ( end-start < 2 ) return false; // Smallest valid address is "::"
- if (literal("]")) {
- h.assign(start, end);
- return true;
- }
- }
- return false;
- }
-
bool unreserved() { return (::isalnum(*i) || ::strchr("-._~", *i)) && advance(); }
bool pctEncoded() { return literal("%") && hexDigit() && hexDigit(); }
diff --git a/cpp/src/qpid/acl/Acl.cpp b/cpp/src/qpid/acl/Acl.cpp
index 4b3dda7962..67603015d7 100644
--- a/cpp/src/qpid/acl/Acl.cpp
+++ b/cpp/src/qpid/acl/Acl.cpp
@@ -180,10 +180,7 @@ Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(fals
{
case _qmf::Acl::METHOD_RELOADACLFILE :
readAclFile(text);
- if (text.empty())
- status = Manageable::STATUS_OK;
- else
- status = Manageable::STATUS_USER;
+ status = Manageable::STATUS_USER;
break;
}
diff --git a/cpp/src/qpid/acl/AclPlugin.cpp b/cpp/src/qpid/acl/AclPlugin.cpp
index d611797c49..e4d721ea44 100644
--- a/cpp/src/qpid/acl/AclPlugin.cpp
+++ b/cpp/src/qpid/acl/AclPlugin.cpp
@@ -69,7 +69,7 @@ struct AclPlugin : public Plugin {
}
acl = new Acl(values, b);
- b.setAcl(acl.get());
+ b.setAcl(acl.get());
b.addFinalizer(boost::bind(&AclPlugin::shutdown, this));
}
diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/cpp/src/qpid/agent/ManagementAgentImpl.cpp
index f183ff8e0c..593d403a11 100644
--- a/cpp/src/qpid/agent/ManagementAgentImpl.cpp
+++ b/cpp/src/qpid/agent/ManagementAgentImpl.cpp
@@ -305,47 +305,43 @@ void ManagementAgentImpl::raiseEvent(const ManagementEvent& event, severity_t se
"emerg", "alert", "crit", "error", "warn",
"note", "info", "debug"
};
- string content;
+ sys::Mutex::ScopedLock lock(agentLock);
+ Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE);
+ uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity;
stringstream key;
- Variant::Map headers;
- {
- sys::Mutex::ScopedLock lock(agentLock);
- Buffer outBuffer(eventBuffer, MA_BUFFER_SIZE);
- uint8_t sev = (severity == SEV_DEFAULT) ? event.getSeverity() : (uint8_t) severity;
-
- // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." <<
- // event.getPackageName() << "." << event.getEventName();
- key << "agent.ind.event." << keyifyNameStr(event.getPackageName())
- << "." << keyifyNameStr(event.getEventName())
- << "." << severityStr[sev]
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- Variant::Map map_;
- Variant::Map schemaId;
- Variant::Map values;
-
- map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(),
- event.getEventName(),
- event.getMd5Sum(),
- ManagementItem::CLASS_KIND_EVENT);
- event.mapEncode(values);
- map_["_values"] = values;
- map_["_timestamp"] = uint64_t(Duration(EPOCH, now()));
- map_["_severity"] = sev;
+ // key << "console.event." << assignedBrokerBank << "." << assignedAgentBank << "." <<
+ // event.getPackageName() << "." << event.getEventName();
+ key << "agent.ind.event." << keyifyNameStr(event.getPackageName())
+ << "." << keyifyNameStr(event.getEventName())
+ << "." << severityStr[sev]
+ << "." << vendorNameKey
+ << "." << productNameKey
+ << "." << instanceNameKey;
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_event";
- headers["qmf.agent"] = name_address;
+ Variant::Map map_;
+ Variant::Map schemaId;
+ Variant::Map values;
+ Variant::Map headers;
+ string content;
- Variant::List list;
- list.push_back(map_);
- ListCodec::encode(list, content);
- }
+ map_["_schema_id"] = mapEncodeSchemaId(event.getPackageName(),
+ event.getEventName(),
+ event.getMd5Sum(),
+ ManagementItem::CLASS_KIND_EVENT);
+ event.mapEncode(values);
+ map_["_values"] = values;
+ map_["_timestamp"] = uint64_t(Duration(EPOCH, now()));
+ map_["_severity"] = sev;
+ headers["method"] = "indication";
+ headers["qmf.opcode"] = "_data_indication";
+ headers["qmf.content"] = "_event";
+ headers["qmf.agent"] = name_address;
+
+ Variant::List list;
+ list.push_back(map_);
+ ListCodec::encode(list, content);
connThreadBody.sendBuffer(content, "", headers, topicExchange, key.str(), "amqp/list");
}
@@ -525,12 +521,9 @@ void ManagementAgentImpl::sendException(const string& rte, const string& rtk, co
void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequence, const string& rte, const string& rtk)
{
+ sys::Mutex::ScopedLock lock(agentLock);
string packageName;
SchemaClassKey key;
- uint32_t outLen(0);
- char localBuffer[MA_BUFFER_SIZE];
- Buffer outBuffer(localBuffer, MA_BUFFER_SIZE);
- bool found(false);
inBuffer.getShortString(packageName);
inBuffer.getShortString(key.name);
@@ -538,30 +531,26 @@ void ManagementAgentImpl::handleSchemaRequest(Buffer& inBuffer, uint32_t sequenc
QPID_LOG(trace, "RCVD SchemaRequest: package=" << packageName << " class=" << key.name);
- {
- sys::Mutex::ScopedLock lock(agentLock);
- PackageMap::iterator pIter = packages.find(packageName);
- if (pIter != packages.end()) {
- ClassMap& cMap = pIter->second;
- ClassMap::iterator cIter = cMap.find(key);
- if (cIter != cMap.end()) {
- SchemaClass& schema = cIter->second;
- string body;
-
- encodeHeader(outBuffer, 's', sequence);
- schema.writeSchemaCall(body);
- outBuffer.putRawData(body);
- outLen = MA_BUFFER_SIZE - outBuffer.available();
- outBuffer.reset();
- found = true;
- }
+ PackageMap::iterator pIter = packages.find(packageName);
+ if (pIter != packages.end()) {
+ ClassMap& cMap = pIter->second;
+ ClassMap::iterator cIter = cMap.find(key);
+ if (cIter != cMap.end()) {
+ SchemaClass& schema = cIter->second;
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t outLen;
+ string body;
+
+ encodeHeader(outBuffer, 's', sequence);
+ schema.writeSchemaCall(body);
+ outBuffer.putRawData(body);
+ outLen = MA_BUFFER_SIZE - outBuffer.available();
+ outBuffer.reset();
+ connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk);
+
+ QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name);
}
}
-
- if (found) {
- connThreadBody.sendBuffer(outBuffer, outLen, rte, rtk);
- QPID_LOG(trace, "SENT SchemaInd: package=" << packageName << " class=" << key.name);
- }
}
void ManagementAgentImpl::handleConsoleAddedIndication()
@@ -980,6 +969,18 @@ ManagementAgentImpl::PackageMap::iterator ManagementAgentImpl::findOrAddPackage(
pair<PackageMap::iterator, bool> result =
packages.insert(pair<string, ClassMap>(name, ClassMap()));
+ if (connected) {
+ // Publish a package-indication message
+ Buffer outBuffer(outputBuffer, MA_BUFFER_SIZE);
+ uint32_t outLen;
+
+ encodeHeader(outBuffer, 'p');
+ encodePackageIndication(outBuffer, result.first);
+ outLen = MA_BUFFER_SIZE - outBuffer.available();
+ outBuffer.reset();
+ connThreadBody.sendBuffer(outBuffer, outLen, "qpid.management", "schema.package");
+ }
+
return result.first;
}
@@ -1037,146 +1038,131 @@ void ManagementAgentImpl::encodeClassIndication(Buffer& buf,
QPID_LOG(trace, "SENT ClassInd: package=" << (*pIter).first << " class=" << key.name);
}
-struct MessageItem {
- string content;
- Variant::Map headers;
- string key;
- MessageItem(const Variant::Map& h, const string& k) : headers(h), key(k) {}
-};
-
void ManagementAgentImpl::periodicProcessing()
{
string addr_key_base = "agent.ind.data.";
+ sys::Mutex::ScopedLock lock(agentLock);
list<ObjectId> deleteList;
- list<boost::shared_ptr<MessageItem> > message_list;
+
+ if (!connected)
+ return;
sendHeartbeat();
- {
- sys::Mutex::ScopedLock lock(agentLock);
+ moveNewObjectsLH();
- if (!connected)
- return;
+ //
+ // Clear the been-here flag on all objects in the map.
+ //
+ for (ObjectMap::iterator iter = managementObjects.begin();
+ iter != managementObjects.end();
+ iter++) {
+ ManagementObject* object = iter->second.get();
+ object->setFlags(0);
+ if (publishAllData) {
+ object->setForcePublish(true);
+ }
+ }
+
+ publishAllData = false;
- moveNewObjectsLH();
+ //
+ // Process the entire object map.
+ //
+ uint32_t v2Objs = 0;
+
+ for (ObjectMap::iterator baseIter = managementObjects.begin();
+ baseIter != managementObjects.end();
+ baseIter++) {
+ ManagementObject* baseObject = baseIter->second.get();
//
- // Clear the been-here flag on all objects in the map.
+ // Skip until we find a base object requiring a sent message.
//
- for (ObjectMap::iterator iter = managementObjects.begin();
+ if (baseObject->getFlags() == 1 ||
+ (!baseObject->getConfigChanged() &&
+ !baseObject->getInstChanged() &&
+ !baseObject->getForcePublish() &&
+ !baseObject->isDeleted()))
+ continue;
+
+ std::string packageName = baseObject->getPackageName();
+ std::string className = baseObject->getClassName();
+
+ Variant::List list_;
+ string content;
+ std::stringstream addr_key;
+ Variant::Map headers;
+
+ addr_key << addr_key_base;
+ addr_key << keyifyNameStr(packageName)
+ << "." << keyifyNameStr(className)
+ << "." << vendorNameKey
+ << "." << productNameKey
+ << "." << instanceNameKey;
+
+ headers["method"] = "indication";
+ headers["qmf.opcode"] = "_data_indication";
+ headers["qmf.content"] = "_data";
+ headers["qmf.agent"] = name_address;
+
+ for (ObjectMap::iterator iter = baseIter;
iter != managementObjects.end();
iter++) {
ManagementObject* object = iter->second.get();
- object->setFlags(0);
- if (publishAllData) {
- object->setForcePublish(true);
- }
- }
-
- publishAllData = false;
-
- //
- // Process the entire object map.
- //
- uint32_t v2Objs = 0;
-
- for (ObjectMap::iterator baseIter = managementObjects.begin();
- baseIter != managementObjects.end();
- baseIter++) {
- ManagementObject* baseObject = baseIter->second.get();
-
- //
- // Skip until we find a base object requiring a sent message.
- //
- if (baseObject->getFlags() == 1 ||
- (!baseObject->getConfigChanged() &&
- !baseObject->getInstChanged() &&
- !baseObject->getForcePublish() &&
- !baseObject->isDeleted()))
- continue;
-
- std::string packageName = baseObject->getPackageName();
- std::string className = baseObject->getClassName();
-
- Variant::List list_;
- std::stringstream addr_key;
- Variant::Map headers;
-
- addr_key << addr_key_base;
- addr_key << keyifyNameStr(packageName)
- << "." << keyifyNameStr(className)
- << "." << vendorNameKey
- << "." << productNameKey
- << "." << instanceNameKey;
-
- headers["method"] = "indication";
- headers["qmf.opcode"] = "_data_indication";
- headers["qmf.content"] = "_data";
- headers["qmf.agent"] = name_address;
-
- for (ObjectMap::iterator iter = baseIter;
- iter != managementObjects.end();
- iter++) {
- ManagementObject* object = iter->second.get();
- bool send_stats, send_props;
- if (baseObject->isSameClass(*object) && object->getFlags() == 0) {
- object->setFlags(1);
- if (object->getConfigChanged() || object->getInstChanged())
- object->setUpdateTime();
-
- send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted());
- send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish()));
-
- if (send_stats || send_props) {
- Variant::Map map_;
- Variant::Map values;
- Variant::Map oid;
-
- object->getObjectId().mapEncode(oid);
- map_["_object_id"] = oid;
- map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
- object->getClassName(),
- object->getMd5Sum());
- object->writeTimestamps(map_);
- object->mapEncodeValues(values, send_props, send_stats);
- map_["_values"] = values;
- list_.push_back(map_);
+ bool send_stats, send_props;
+ if (baseObject->isSameClass(*object) && object->getFlags() == 0) {
+ object->setFlags(1);
+ if (object->getConfigChanged() || object->getInstChanged())
+ object->setUpdateTime();
- if (++v2Objs >= maxV2ReplyObjs) {
- v2Objs = 0;
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
- list_.clear();
- }
+ send_props = (object->getConfigChanged() || object->getForcePublish() || object->isDeleted());
+ send_stats = (object->hasInst() && (object->getInstChanged() || object->getForcePublish()));
+
+ if (send_stats || send_props) {
+ Variant::Map map_;
+ Variant::Map values;
+ Variant::Map oid;
+
+ object->getObjectId().mapEncode(oid);
+ map_["_object_id"] = oid;
+ map_["_schema_id"] = mapEncodeSchemaId(object->getPackageName(),
+ object->getClassName(),
+ object->getMd5Sum());
+ object->writeTimestamps(map_);
+ object->mapEncodeValues(values, send_props, send_stats);
+ map_["_values"] = values;
+ list_.push_back(map_);
+
+ if (++v2Objs >= maxV2ReplyObjs) {
+ v2Objs = 0;
+ ListCodec::encode(list_, content);
+
+ connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(), "amqp/list");
+ list_.clear();
+ content.clear();
+ QPID_LOG(trace, "SENT DataIndication");
}
-
- if (object->isDeleted())
- deleteList.push_back(iter->first);
- object->setForcePublish(false);
}
- }
- if (!list_.empty()) {
- boost::shared_ptr<MessageItem> item(new MessageItem(headers, addr_key.str()));
- ListCodec::encode(list_, item->content);
- message_list.push_back(item);
+ if (object->isDeleted())
+ deleteList.push_back(iter->first);
+ object->setForcePublish(false);
}
}
- // Delete flagged objects
- for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin();
- iter != deleteList.rend();
- iter++)
- managementObjects.erase(*iter);
+ if (!list_.empty()) {
+ ListCodec::encode(list_, content);
+ connThreadBody.sendBuffer(content, "", headers, topicExchange, addr_key.str(), "amqp/list");
+ QPID_LOG(trace, "SENT DataIndication");
+ }
}
- while (!message_list.empty()) {
- boost::shared_ptr<MessageItem> item(message_list.front());
- message_list.pop_front();
- connThreadBody.sendBuffer(item->content, "", item->headers, topicExchange, item->key, "amqp/list");
- QPID_LOG(trace, "SENT DataIndication");
- }
+ // Delete flagged objects
+ for (list<ObjectId>::reverse_iterator iter = deleteList.rbegin();
+ iter != deleteList.rend();
+ iter++)
+ managementObjects.erase(*iter);
}
@@ -1378,26 +1364,13 @@ bool ManagementAgentImpl::ConnectionThread::isSleeping() const
void ManagementAgentImpl::PublishThread::run()
{
- uint16_t totalSleep;
- uint16_t sleepTime;
+ uint16_t totalSleep;
while (!shutdown) {
agent.periodicProcessing();
totalSleep = 0;
-
- //
- // Calculate a sleep time that is no greater than 5 seconds and
- // no less than 1 second.
- //
- sleepTime = agent.getInterval();
- if (sleepTime > 5)
- sleepTime = 5;
- else if (sleepTime == 0)
- sleepTime = 1;
-
- while (totalSleep < agent.getInterval() && !shutdown) {
- ::sleep(sleepTime);
- totalSleep += sleepTime;
+ while (totalSleep++ < agent.getInterval() && !shutdown) {
+ ::sleep(1);
}
}
}
diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.h b/cpp/src/qpid/agent/ManagementAgentImpl.h
index 53f3c13a91..bf340777d1 100644
--- a/cpp/src/qpid/agent/ManagementAgentImpl.h
+++ b/cpp/src/qpid/agent/ManagementAgentImpl.h
@@ -62,8 +62,8 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen
uint16_t intervalSeconds = 10,
bool useExternalThread = false,
const std::string& storeFile = "",
- const std::string& uid = "",
- const std::string& pwd = "",
+ const std::string& uid = "guest",
+ const std::string& pwd = "guest",
const std::string& mech = "PLAIN",
const std::string& proto = "tcp");
void init(const management::ConnectionSettings& settings,
diff --git a/cpp/src/qpid/amqp_0_10/Codecs.cpp b/cpp/src/qpid/amqp_0_10/Codecs.cpp
index b976a5d09b..0fbe2a60b9 100644
--- a/cpp/src/qpid/amqp_0_10/Codecs.cpp
+++ b/cpp/src/qpid/amqp_0_10/Codecs.cpp
@@ -127,10 +127,10 @@ Variant toVariant(boost::shared_ptr<FieldValue> in)
switch (in->getType()) {
//Fixed Width types:
case 0x01: out.setEncoding(amqp0_10_binary);
- case 0x02: out = in->getIntegerValue<int8_t>(); break;
- case 0x03: out = in->getIntegerValue<uint8_t>(); break;
+ case 0x02: out = in->getIntegerValue<int8_t, 1>(); break;
+ case 0x03: out = in->getIntegerValue<uint8_t, 1>(); break;
case 0x04: break; //TODO: iso-8859-15 char
- case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t>()); break;
+ case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t, 1>()); break;
case 0x10: out.setEncoding(amqp0_10_binary);
case 0x11: out = in->getIntegerValue<int16_t, 2>(); break;
case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break;
diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp b/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
index 578598a146..b113d49a73 100644
--- a/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
+++ b/cpp/src/qpid/amqp_0_10/SessionHandler.cpp
@@ -130,6 +130,9 @@ void SessionHandler::handleException(const qpid::SessionException& e)
}
namespace {
+bool isControl(const AMQFrame& f) {
+ return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_CONTROL;
+}
bool isCommand(const AMQFrame& f) {
return f.getMethod() && f.getMethod()->type() == framing::SEGMENT_TYPE_COMMAND;
}
@@ -188,10 +191,9 @@ void SessionHandler::detach(const std::string& name) {
void SessionHandler::detached(const std::string& name, uint8_t code) {
CHECK_NAME(name, "session.detached");
awaitingDetached = false;
- if (code != session::DETACH_CODE_NORMAL) {
- sendReady = receiveReady = false;
+ if (code != session::DETACH_CODE_NORMAL)
channelException(convert(code), "session.detached from peer.");
- } else {
+ else {
handleDetach();
}
}
diff --git a/cpp/src/qpid/amqp_0_10/SessionHandler.h b/cpp/src/qpid/amqp_0_10/SessionHandler.h
index 8b072fa05c..a87a1a155f 100644
--- a/cpp/src/qpid/amqp_0_10/SessionHandler.h
+++ b/cpp/src/qpid/amqp_0_10/SessionHandler.h
@@ -41,8 +41,8 @@ namespace amqp_0_10 {
* to a session state.
*/
-class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperations::SessionHandler,
- public framing::FrameHandler::InOutHandler
+class SessionHandler : public framing::AMQP_AllOperations::SessionHandler,
+ public framing::FrameHandler::InOutHandler
{
public:
QPID_COMMON_EXTERN SessionHandler(framing::FrameHandler* out=0, uint16_t channel=0);
@@ -66,7 +66,7 @@ class QPID_COMMON_CLASS_EXTERN SessionHandler : public framing::AMQP_AllOperatio
QPID_COMMON_EXTERN void handleException(const qpid::SessionException& e);
/** True if the handler is ready to send and receive */
- QPID_COMMON_EXTERN bool ready() const;
+ bool ready() const;
// Protocol methods
QPID_COMMON_EXTERN void attach(const std::string& name, bool force);
diff --git a/cpp/src/qpid/broker/AsyncCompletion.h b/cpp/src/qpid/broker/AsyncCompletion.h
deleted file mode 100644
index fef994438f..0000000000
--- a/cpp/src/qpid/broker/AsyncCompletion.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef _AsyncCompletion_
-#define _AsyncCompletion_
-
-/*
- *
- * 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 <boost/intrusive_ptr.hpp>
-
-#include "qpid/broker/BrokerImportExport.h"
-#include "qpid/sys/AtomicValue.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/sys/Monitor.h"
-
-namespace qpid {
-namespace broker {
-
-/**
- * Class to implement asynchronous notification of completion.
- *
- * Use-case: An "initiator" needs to wait for a set of "completers" to
- * finish a unit of work before an action can occur. This object
- * tracks the progress of the set of completers, and allows the action
- * to occur once all completers have signalled that they are done.
- *
- * The initiator and completers may be running in separate threads.
- *
- * The initiating thread is the thread that initiates the action,
- * i.e. the connection read thread.
- *
- * A completing thread is any thread that contributes to completion,
- * e.g. a store thread that does an async write.
- * There may be zero or more completers.
- *
- * When the work is complete, a callback is invoked. The callback
- * may be invoked in the Initiator thread, or one of the Completer
- * threads. The callback is passed a flag indicating whether or not
- * the callback is running under the context of the Initiator thread.
- *
- * Use model:
- * 1) Initiator thread invokes begin()
- * 2) After begin() has been invoked, zero or more Completers invoke
- * startCompleter(). Completers may be running in the same or
- * different thread as the Initiator, as long as they guarantee that
- * startCompleter() is invoked at least once before the Initiator invokes end().
- * 3) Completers may invoke finishCompleter() at any time, even after the
- * initiator has invoked end(). finishCompleter() may be called from any
- * thread.
- * 4) startCompleter()/finishCompleter() calls "nest": for each call to
- * startCompleter(), a corresponding call to finishCompleter() must be made.
- * Once the last finishCompleter() is called, the Completer must no longer
- * reference the completion object.
- * 5) The Initiator invokes end() at the point where it has finished
- * dispatching work to the Completers, and is prepared for the callback
- * handler to be invoked. Note: if there are no outstanding Completers
- * pending when the Initiator invokes end(), the callback will be invoked
- * directly, and the sync parameter will be set true. This indicates to the
- * Initiator that the callback is executing in the context of the end() call,
- * and the Initiator is free to optimize the handling of the completion,
- * assuming no need for synchronization with Completer threads.
- */
-
-class AsyncCompletion
-{
- public:
-
- /** Supplied by the Initiator to the end() method, allows for a callback
- * when all outstanding completers are done. If the callback cannot be
- * made during the end() call, the clone() method must supply a copy of
- * this callback object that persists after end() returns. The cloned
- * callback object will be used by the last completer thread, and
- * released when the callback returns.
- */
- class Callback : public RefCounted
- {
- public:
- virtual void completed(bool) = 0;
- virtual boost::intrusive_ptr<Callback> clone() = 0;
- };
-
- private:
- mutable qpid::sys::AtomicValue<uint32_t> completionsNeeded;
- mutable qpid::sys::Monitor callbackLock;
- bool inCallback, active;
-
- void invokeCallback(bool sync) {
- qpid::sys::Mutex::ScopedLock l(callbackLock);
- if (active) {
- if (callback.get()) {
- inCallback = true;
- {
- qpid::sys::Mutex::ScopedUnlock ul(callbackLock);
- callback->completed(sync);
- }
- inCallback = false;
- callback = boost::intrusive_ptr<Callback>();
- callbackLock.notifyAll();
- }
- active = false;
- }
- }
-
- protected:
- /** Invoked when all completers have signalled that they have completed
- * (via calls to finishCompleter()). bool == true if called via end()
- */
- boost::intrusive_ptr<Callback> callback;
-
- public:
- AsyncCompletion() : completionsNeeded(0), inCallback(false), active(true) {};
- virtual ~AsyncCompletion() { cancel(); }
-
-
- /** True when all outstanding operations have compeleted
- */
- bool isDone()
- {
- return !active;
- }
-
- /** Called to signal the start of an asynchronous operation. The operation
- * is considered pending until finishCompleter() is called.
- * E.g. called when initiating an async store operation.
- */
- void startCompleter() { ++completionsNeeded; }
-
- /** Called by completer to signal that it has finished the operation started
- * when startCompleter() was invoked.
- * e.g. called when async write complete.
- */
- void finishCompleter()
- {
- if (--completionsNeeded == 0) {
- invokeCallback(false);
- }
- }
-
- /** called by initiator before any calls to startCompleter can be done.
- */
- void begin()
- {
- ++completionsNeeded;
- }
-
- /** called by initiator after all potential completers have called
- * startCompleter().
- */
- void end(Callback& cb)
- {
- assert(completionsNeeded.get() > 0); // ensure begin() has been called!
- // the following only "decrements" the count if it is 1. This means
- // there are no more outstanding completers and we are done.
- if (completionsNeeded.boolCompareAndSwap(1, 0)) {
- // done! Complete immediately
- cb.completed(true);
- return;
- }
-
- // the compare-and-swap did not succeed. This means there are
- // outstanding completers pending (count > 1). Get a persistent
- // Callback object to use when the last completer is done.
- // Decrement after setting up the callback ensures that pending
- // completers cannot touch the callback until it is ready.
- callback = cb.clone();
- if (--completionsNeeded == 0) {
- // note that a completer may have completed during the
- // callback setup or decrement:
- invokeCallback(true);
- }
- }
-
- /** may be called by Initiator to cancel the callback. Will wait for
- * callback to complete if in progress.
- */
- virtual void cancel() {
- qpid::sys::Mutex::ScopedLock l(callbackLock);
- while (inCallback) callbackLock.wait();
- callback = boost::intrusive_ptr<Callback>();
- active = false;
- }
-};
-
-}} // qpid::broker::
-#endif /*!_AsyncCompletion_*/
diff --git a/cpp/src/qpid/broker/Bridge.cpp b/cpp/src/qpid/broker/Bridge.cpp
index c709606c17..7fbbf4e2c4 100644
--- a/cpp/src/qpid/broker/Bridge.cpp
+++ b/cpp/src/qpid/broker/Bridge.cpp
@@ -164,12 +164,6 @@ void Bridge::destroy()
listener(this);
}
-bool Bridge::isSessionReady() const
-{
- SessionHandler& sessionHandler = conn->getChannel(id);
- return sessionHandler.ready();
-}
-
void Bridge::setPersistenceId(uint64_t pId) const
{
persistenceId = pId;
diff --git a/cpp/src/qpid/broker/Bridge.h b/cpp/src/qpid/broker/Bridge.h
index 8b4559a871..a846254c57 100644
--- a/cpp/src/qpid/broker/Bridge.h
+++ b/cpp/src/qpid/broker/Bridge.h
@@ -59,8 +59,6 @@ public:
void destroy();
bool isDurable() { return args.i_durable; }
- bool isSessionReady() const;
-
management::ManagementObject* GetManagementObject() const;
management::Manageable::status_t ManagementMethod(uint32_t methodId,
management::Args& args,
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp
index ec3cf9d340..3c692fc368 100644
--- a/cpp/src/qpid/broker/Broker.cpp
+++ b/cpp/src/qpid/broker/Broker.cpp
@@ -20,7 +20,6 @@
*/
#include "qpid/broker/Broker.h"
-#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/DirectExchange.h"
#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/HeadersExchange.h"
@@ -32,26 +31,12 @@
#include "qpid/broker/TopicExchange.h"
#include "qpid/broker/Link.h"
#include "qpid/broker/ExpiryPolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-#include "qpid/broker/MessageGroupManager.h"
#include "qmf/org/apache/qpid/broker/Package.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerCreate.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerDelete.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerQuery.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h"
#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerSetTimestampConfig.h"
-#include "qmf/org/apache/qpid/broker/ArgsBrokerGetTimestampConfig.h"
-#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h"
-#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h"
-#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h"
-#include "qmf/org/apache/qpid/broker/EventQueueDelete.h"
-#include "qmf/org/apache/qpid/broker/EventBind.h"
-#include "qmf/org/apache/qpid/broker/EventUnbind.h"
-#include "qpid/amqp_0_10/Codecs.h"
#include "qpid/management/ManagementDirectExchange.h"
#include "qpid/management/ManagementTopicExchange.h"
#include "qpid/log/Logger.h"
@@ -59,9 +44,7 @@
#include "qpid/log/Statement.h"
#include "qpid/log/posix/SinkOptions.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/framing/FieldTable.h"
#include "qpid/framing/ProtocolInitiation.h"
-#include "qpid/framing/reply_exceptions.h"
#include "qpid/framing/Uuid.h"
#include "qpid/sys/ProtocolFactory.h"
#include "qpid/sys/Poller.h"
@@ -93,10 +76,7 @@ using qpid::management::ManagementAgent;
using qpid::management::ManagementObject;
using qpid::management::Manageable;
using qpid::management::Args;
-using qpid::management::getManagementExecutionContext;
-using qpid::types::Variant;
using std::string;
-using std::make_pair;
namespace _qmf = qmf::org::apache::qpid::broker;
@@ -123,12 +103,7 @@ Broker::Options::Options(const std::string& name) :
maxSessionRate(0),
asyncQueueEvents(false), // Must be false in a cluster.
qmf2Support(true),
- qmf1Support(true),
- queueFlowStopRatio(80),
- queueFlowResumeRatio(70),
- queueThresholdEventRatio(80),
- defaultMsgGroup("qpid.no-group"),
- timestampRcvMsgs(false) // set the 0.10 timestamp delivery property
+ qmf1Support(true)
{
int c = sys::SystemInfo::concurrency();
workerThreads=c+1;
@@ -159,14 +134,9 @@ Broker::Options::Options(const std::string& name) :
("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections")
("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted")
("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)")
- ("sasl-config", optValue(saslConfigPath, "DIR"), "gets sasl config info from nonstandard location")
+ ("sasl-config", optValue(saslConfigPath, "FILE"), "gets sasl config from nonstandard location")
("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)")
- ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication")
- ("default-flow-stop-threshold", optValue(queueFlowStopRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is activated.")
- ("default-flow-resume-threshold", optValue(queueFlowResumeRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is de-activated.")
- ("default-event-threshold-ratio", optValue(queueThresholdEventRatio, "%age of limit"), "The ratio of any specified queue limit at which an event will be raised")
- ("default-message-group", optValue(defaultMsgGroup, "GROUP-IDENTIFER"), "Group identifier to assign to messages delivered to a message group queue that do not contain an identifier.")
- ("enable-timestamp", optValue(timestampRcvMsgs, "yes|no"), "Add current time to each received message.");
+ ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication");
}
const std::string empty;
@@ -196,10 +166,9 @@ Broker::Broker(const Broker::Options& conf) :
conf.replayFlushLimit*1024, // convert kb to bytes.
conf.replayHardLimit*1024),
*this),
- queueCleaner(queues, &timer),
- queueEvents(poller,!conf.asyncQueueEvents),
+ queueCleaner(queues, timer),
+ queueEvents(poller,!conf.asyncQueueEvents),
recovery(true),
- inCluster(false),
clusterUpdatee(false),
expiryPolicy(new ExpiryPolicy),
connectionCounter(conf.maxConnections),
@@ -256,11 +225,8 @@ Broker::Broker(const Broker::Options& conf) :
// Early-Initialize plugins
Plugin::earlyInitAll(*this);
- QueueFlowLimit::setDefaults(conf.queueLimit, conf.queueFlowStopRatio, conf.queueFlowResumeRatio);
- MessageGroupManager::setDefaults(conf.defaultMsgGroup);
-
// If no plugin store module registered itself, set up the null store.
- if (NullMessageStore::isNullStore(store.get()))
+ if (NullMessageStore::isNullStore(store.get()))
setStore();
exchanges.declare(empty, DirectExchange::typeName); // Default exchange.
@@ -305,11 +271,6 @@ Broker::Broker(const Broker::Options& conf) :
else
QPID_LOG(info, "Management not enabled");
- // this feature affects performance, so let's be sure that gets logged!
- if (conf.timestampRcvMsgs) {
- QPID_LOG(notice, "Receive message timestamping is ENABLED.");
- }
-
/**
* SASL setup, can fail and terminate startup
*/
@@ -384,14 +345,14 @@ void Broker::run() {
Dispatcher d(poller);
int numIOThreads = config.workerThreads;
std::vector<Thread> t(numIOThreads-1);
-
+
// Run n-1 io threads
for (int i=0; i<numIOThreads-1; ++i)
t[i] = Thread(d);
-
+
// Run final thread
d.run();
-
+
// Now wait for n-1 io threads to exit
for (int i=0; i<numIOThreads-1; ++i) {
t[i].join();
@@ -438,9 +399,9 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
{
case _qmf::Broker::METHOD_ECHO :
QPID_LOG (debug, "Broker::echo("
- << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence
- << ", "
- << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body
+ << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence
+ << ", "
+ << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body
<< ")");
status = Manageable::STATUS_OK;
break;
@@ -448,9 +409,8 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
_qmf::ArgsBrokerConnect& hp=
dynamic_cast<_qmf::ArgsBrokerConnect&>(args);
+ QPID_LOG (debug, "Broker::connect()");
string transport = hp.i_transport.empty() ? TCP_TRANSPORT : hp.i_transport;
- QPID_LOG (debug, "Broker::connect() " << hp.i_host << ":" << hp.i_port << "; transport=" << transport <<
- "; durable=" << (hp.i_durable?"T":"F") << "; authMech=\"" << hp.i_authMechanism << "\"");
if (!getProtocolFactory(transport)) {
QPID_LOG(error, "Transport '" << transport << "' not supported");
return Manageable::STATUS_NOT_IMPLEMENTED;
@@ -467,9 +427,9 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
_qmf::ArgsBrokerQueueMoveMessages& moveArgs=
dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args);
QPID_LOG (debug, "Broker::queueMoveMessages()");
- if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty, moveArgs.i_filter))
+ if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty))
status = Manageable::STATUS_OK;
- else
+ else
return Manageable::STATUS_PARAMETER_INVALID;
break;
}
@@ -483,38 +443,6 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
QPID_LOG (debug, "Broker::getLogLevel()");
status = Manageable::STATUS_OK;
break;
- case _qmf::Broker::METHOD_CREATE :
- {
- _qmf::ArgsBrokerCreate& a = dynamic_cast<_qmf::ArgsBrokerCreate&>(args);
- createObject(a.i_type, a.i_name, a.i_properties, a.i_strict, getManagementExecutionContext());
- status = Manageable::STATUS_OK;
- break;
- }
- case _qmf::Broker::METHOD_DELETE :
- {
- _qmf::ArgsBrokerDelete& a = dynamic_cast<_qmf::ArgsBrokerDelete&>(args);
- deleteObject(a.i_type, a.i_name, a.i_options, getManagementExecutionContext());
- status = Manageable::STATUS_OK;
- break;
- }
- case _qmf::Broker::METHOD_QUERY :
- {
- _qmf::ArgsBrokerQuery& a = dynamic_cast<_qmf::ArgsBrokerQuery&>(args);
- status = queryObject(a.i_type, a.i_name, a.o_results, getManagementExecutionContext());
- break;
- }
- case _qmf::Broker::METHOD_GETTIMESTAMPCONFIG:
- {
- _qmf::ArgsBrokerGetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerGetTimestampConfig&>(args);
- status = getTimestampConfig(a.o_receive, getManagementExecutionContext());
- break;
- }
- case _qmf::Broker::METHOD_SETTIMESTAMPCONFIG:
- {
- _qmf::ArgsBrokerSetTimestampConfig& a = dynamic_cast<_qmf::ArgsBrokerSetTimestampConfig&>(args);
- status = setTimestampConfig(a.i_receive, getManagementExecutionContext());
- break;
- }
default:
QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << methodId << "]");
status = Manageable::STATUS_NOT_IMPLEMENTED;
@@ -524,240 +452,6 @@ Manageable::status_t Broker::ManagementMethod (uint32_t methodId,
return status;
}
-namespace
-{
-const std::string TYPE_QUEUE("queue");
-const std::string TYPE_EXCHANGE("exchange");
-const std::string TYPE_TOPIC("topic");
-const std::string TYPE_BINDING("binding");
-const std::string DURABLE("durable");
-const std::string AUTO_DELETE("auto-delete");
-const std::string ALTERNATE_EXCHANGE("alternate-exchange");
-const std::string EXCHANGE_TYPE("exchange-type");
-const std::string QUEUE_NAME("queue");
-const std::string EXCHANGE_NAME("exchange");
-
-const std::string ATTRIBUTE_TIMESTAMP_0_10("timestamp-0.10");
-
-const std::string _TRUE("true");
-const std::string _FALSE("false");
-}
-
-struct InvalidBindingIdentifier : public qpid::Exception
-{
- InvalidBindingIdentifier(const std::string& name) : qpid::Exception(name) {}
- std::string getPrefix() const { return "invalid binding"; }
-};
-
-struct BindingIdentifier
-{
- std::string exchange;
- std::string queue;
- std::string key;
-
- BindingIdentifier(const std::string& name)
- {
- std::vector<std::string> path;
- split(path, name, "/");
- switch (path.size()) {
- case 1:
- queue = path[0];
- break;
- case 2:
- exchange = path[0];
- queue = path[1];
- break;
- case 3:
- exchange = path[0];
- queue = path[1];
- key = path[2];
- break;
- default:
- throw InvalidBindingIdentifier(name);
- }
- }
-};
-
-struct ObjectAlreadyExists : public qpid::Exception
-{
- ObjectAlreadyExists(const std::string& name) : qpid::Exception(name) {}
- std::string getPrefix() const { return "object already exists"; }
-};
-
-struct UnknownObjectType : public qpid::Exception
-{
- UnknownObjectType(const std::string& type) : qpid::Exception(type) {}
- std::string getPrefix() const { return "unknown object type"; }
-};
-
-void Broker::createObject(const std::string& type, const std::string& name,
- const Variant::Map& properties, bool /*strict*/, const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- //TODO: implement 'strict' option (check there are no unrecognised properties)
- QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ")");
- if (type == TYPE_QUEUE) {
- bool durable(false);
- bool autodelete(false);
- std::string alternateExchange;
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == DURABLE) durable = i->second;
- else if (i->first == AUTO_DELETE) autodelete = i->second;
- else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- std::pair<boost::shared_ptr<Queue>, bool> result =
- createQueue(name, durable, autodelete, 0, alternateExchange, arguments, userId, connectionId);
- if (!result.second) {
- throw ObjectAlreadyExists(name);
- }
- } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) {
- bool durable(false);
- std::string exchangeType("topic");
- std::string alternateExchange;
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == DURABLE) durable = i->second;
- else if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString();
- else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- try {
- std::pair<boost::shared_ptr<Exchange>, bool> result =
- createExchange(name, exchangeType, durable, alternateExchange, arguments, userId, connectionId);
- if (!result.second) {
- throw ObjectAlreadyExists(name);
- }
- } catch (const UnknownExchangeTypeException&) {
- throw Exception(QPID_MSG("Invalid exchange type: " << exchangeType));
- }
- } else if (type == TYPE_BINDING) {
- BindingIdentifier binding(name);
- std::string exchangeType("topic");
- Variant::Map extensions;
- for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) {
- // extract durable, auto-delete and alternate-exchange properties
- if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString();
- //treat everything else as extension properties
- else extensions[i->first] = i->second;
- }
- framing::FieldTable arguments;
- amqp_0_10::translate(extensions, arguments);
-
- bind(binding.queue, binding.exchange, binding.key, arguments, userId, connectionId);
- } else {
- throw UnknownObjectType(type);
- }
-}
-
-void Broker::deleteObject(const std::string& type, const std::string& name,
- const Variant::Map& options, const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ")");
- if (type == TYPE_QUEUE) {
- deleteQueue(name, userId, connectionId);
- } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) {
- deleteExchange(name, userId, connectionId);
- } else if (type == TYPE_BINDING) {
- BindingIdentifier binding(name);
- unbind(binding.queue, binding.exchange, binding.key, userId, connectionId);
- } else {
- throw UnknownObjectType(type);
- }
-
-}
-
-Manageable::status_t Broker::queryObject(const std::string& type,
- const std::string& name,
- Variant::Map& results,
- const ConnectionState* context)
-{
- std::string userId;
- std::string connectionId;
- if (context) {
- userId = context->getUserId();
- connectionId = context->getUrl();
- }
- QPID_LOG (debug, "Broker::query(" << type << ", " << name << ")");
-
- if (type == TYPE_QUEUE)
- return queryQueue( name, userId, connectionId, results );
-
- if (type == TYPE_EXCHANGE ||
- type == TYPE_TOPIC ||
- type == TYPE_BINDING)
- return Manageable::STATUS_NOT_IMPLEMENTED;
-
- throw UnknownObjectType(type);
-}
-
-Manageable::status_t Broker::queryQueue( const std::string& name,
- const std::string& userId,
- const std::string& /*connectionId*/,
- Variant::Map& results )
-{
- (void) results;
- if (acl) {
- if (!acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_QUEUE, name, NULL) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << userId));
- }
-
- boost::shared_ptr<Queue> q(queues.find(name));
- if (!q) {
- QPID_LOG(error, "Query failed: queue not found, name=" << name);
- return Manageable::STATUS_UNKNOWN_OBJECT;
- }
- q->query( results );
- return Manageable::STATUS_OK;;
-}
-
-Manageable::status_t Broker::getTimestampConfig(bool& receive,
- const ConnectionState* context)
-{
- std::string name; // none needed for broker
- std::string userId = context->getUserId();
- if (acl && !acl->authorise(userId, acl::ACT_ACCESS, acl::OBJ_BROKER, name, NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp get request from " << userId));
- }
- receive = config.timestampRcvMsgs;
- return Manageable::STATUS_OK;
-}
-
-Manageable::status_t Broker::setTimestampConfig(const bool receive,
- const ConnectionState* context)
-{
- std::string name; // none needed for broker
- std::string userId = context->getUserId();
- if (acl && !acl->authorise(userId, acl::ACT_UPDATE, acl::OBJ_BROKER, name, NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied broker timestamp set request from " << userId));
- }
- config.timestampRcvMsgs = receive;
- QPID_LOG(notice, "Receive message timestamping is " << ((config.timestampRcvMsgs) ? "ENABLED." : "DISABLED."));
- return Manageable::STATUS_OK;
-}
-
void Broker::setLogLevel(const std::string& level)
{
QPID_LOG(notice, "Changing log level to " << level);
@@ -772,7 +466,7 @@ std::string Broker::getLogLevel()
const std::vector<std::string>& selectors = qpid::log::Logger::instance().getOptions().selectors;
for (std::vector<std::string>::const_iterator i = selectors.begin(); i != selectors.end(); ++i) {
if (i != selectors.begin()) level += std::string(",");
- level += *i;
+ level += *i;
}
return level;
}
@@ -805,7 +499,7 @@ void Broker::accept() {
}
void Broker::connect(
- const std::string& host, const std::string& port, const std::string& transport,
+ const std::string& host, uint16_t port, const std::string& transport,
boost::function2<void, int, std::string> failed,
sys::ConnectionCodec::Factory* f)
{
@@ -821,14 +515,13 @@ void Broker::connect(
{
url.throwIfEmpty();
const Address& addr=url[0];
- connect(addr.host, boost::lexical_cast<std::string>(addr.port), addr.protocol, failed, f);
+ connect(addr.host, addr.port, addr.protocol, failed, f);
}
uint32_t Broker::queueMoveMessages(
const std::string& srcQueue,
const std::string& destQueue,
- uint32_t qty,
- const Variant::Map& filter)
+ uint32_t qty)
{
Queue::shared_ptr src_queue = queues.find(srcQueue);
if (!src_queue)
@@ -837,7 +530,7 @@ uint32_t Broker::queueMoveMessages(
if (!dest_queue)
return 0;
- return src_queue->move(dest_queue, qty, &filter);
+ return src_queue->move(dest_queue, qty);
}
@@ -855,228 +548,9 @@ bool Broker::deferDeliveryImpl(const std::string& ,
void Broker::setClusterTimer(std::auto_ptr<sys::Timer> t) {
clusterTimer = t;
- queueCleaner.setTimer(clusterTimer.get());
- dtxManager.setTimer(*clusterTimer.get());
}
const std::string Broker::TCP_TRANSPORT("tcp");
-
-std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue(
- const std::string& name,
- bool durable,
- bool autodelete,
- const OwnershipToken* owner,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _FALSE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- params.insert(make_pair(acl::PROP_EXCLUSIVE, owner ? _TRUE : _FALSE));
- params.insert(make_pair(acl::PROP_AUTODELETE, autodelete ? _TRUE : _FALSE));
- params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type")));
- params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count"))));
- params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size"))));
-
- if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_QUEUE,name,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId));
- }
-
- Exchange::shared_ptr alternate;
- if (!alternateExchange.empty()) {
- alternate = exchanges.get(alternateExchange);
- if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange));
- }
-
- std::pair<Queue::shared_ptr, bool> result = queues.declare(name, durable, autodelete, owner, alternate, arguments);
- if (result.second) {
- //add default binding:
- result.first->bind(exchanges.getDefault(), name);
-
- if (managementAgent.get()) {
- //TODO: debatable whether we should raise an event here for
- //create when this is a 'declare' event; ideally add a create
- //event instead?
- managementAgent->raiseEvent(
- _qmf::EventQueueDeclare(connectionId, userId, name,
- durable, owner, autodelete,
- ManagementAgent::toMap(arguments),
- "created"));
- }
- }
- return result;
-}
-
-void Broker::deleteQueue(const std::string& name, const std::string& userId,
- const std::string& connectionId, QueueFunctor check)
-{
- if (acl && !acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_QUEUE,name,NULL)) {
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << userId));
- }
-
- Queue::shared_ptr queue = queues.find(name);
- if (queue) {
- if (check) check(queue);
- queues.destroy(name);
- queue->destroyed();
- } else {
- throw framing::NotFoundException(QPID_MSG("Delete failed. No such queue: " << name));
- }
-
- if (managementAgent.get())
- managementAgent->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, name));
-
-}
-
-std::pair<Exchange::shared_ptr, bool> Broker::createExchange(
- const std::string& name,
- const std::string& type,
- bool durable,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_TYPE, type));
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _FALSE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_EXCHANGE,name,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << userId));
- }
-
- Exchange::shared_ptr alternate;
- if (!alternateExchange.empty()) {
- alternate = exchanges.get(alternateExchange);
- if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange));
- }
-
- std::pair<Exchange::shared_ptr, bool> result;
- result = exchanges.declare(name, type, durable, arguments);
- if (result.second) {
- if (alternate) {
- result.first->setAlternate(alternate);
- alternate->incAlternateUsers();
- }
- if (durable) {
- store->create(*result.first, arguments);
- }
- if (managementAgent.get()) {
- //TODO: debatable whether we should raise an event here for
- //create when this is a 'declare' event; ideally add a create
- //event instead?
- managementAgent->raiseEvent(_qmf::EventExchangeDeclare(connectionId,
- userId,
- name,
- type,
- alternateExchange,
- durable,
- false,
- ManagementAgent::toMap(arguments),
- "created"));
- }
- }
- return result;
-}
-
-void Broker::deleteExchange(const std::string& name, const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << userId));
- }
-
- if (name.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Delete not allowed for default exchange"));
- }
- Exchange::shared_ptr exchange(exchanges.get(name));
- if (!exchange) throw framing::NotFoundException(QPID_MSG("Delete failed. No such exchange: " << name));
- if (exchange->inUseAsAlternate()) throw framing::NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange."));
- if (exchange->isDurable()) store->destroy(*exchange);
- if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers();
- exchanges.destroy(name);
-
- if (managementAgent.get())
- managementAgent->raiseEvent(_qmf::EventExchangeDelete(connectionId, userId, name));
-
-}
-
-void Broker::bind(const std::string& queueName,
- const std::string& exchangeName,
- const std::string& key,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
- params.insert(make_pair(acl::PROP_ROUTINGKEY, key));
-
- if (!acl->authorise(userId,acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,&params))
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << userId));
- }
- if (exchangeName.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Bind not allowed for default exchange"));
- }
-
- Queue::shared_ptr queue = queues.find(queueName);
- Exchange::shared_ptr exchange = exchanges.get(exchangeName);
- if (!queue) {
- throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName));
- } else if (!exchange) {
- throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName));
- } else {
- if (queue->bind(exchange, key, arguments)) {
- if (managementAgent.get()) {
- managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName,
- queueName, key, ManagementAgent::toMap(arguments)));
- }
- }
- }
-}
-
-void Broker::unbind(const std::string& queueName,
- const std::string& exchangeName,
- const std::string& key,
- const std::string& userId,
- const std::string& connectionId)
-{
- if (acl) {
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
- params.insert(make_pair(acl::PROP_ROUTINGKEY, key));
- if (!acl->authorise(userId,acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << userId));
- }
- if (exchangeName.empty()) {
- throw framing::InvalidArgumentException(QPID_MSG("Unbind not allowed for default exchange"));
- }
- Queue::shared_ptr queue = queues.find(queueName);
- Exchange::shared_ptr exchange = exchanges.get(exchangeName);
- if (!queue) {
- throw framing::NotFoundException(QPID_MSG("Unbind failed. No such queue: " << queueName));
- } else if (!exchange) {
- throw framing::NotFoundException(QPID_MSG("Unbind failed. No such exchange: " << exchangeName));
- } else {
- if (exchange->unbind(queue, key, 0)) {
- if (exchange->isDurable() && queue->isDurable()) {
- store->unbind(*exchange, *queue, key, qpid::framing::FieldTable());
- }
- if (managementAgent.get()) {
- managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key));
- }
- }
- }
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index b3b751be98..cd6f81dc70 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -10,9 +10,9 @@
* 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
@@ -49,7 +49,6 @@
#include "qpid/framing/ProtocolInitiation.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/Timer.h"
-#include "qpid/types/Variant.h"
#include "qpid/RefCounted.h"
#include "qpid/broker/AclModule.h"
#include "qpid/sys/Mutex.h"
@@ -58,7 +57,7 @@
#include <string>
#include <vector>
-namespace qpid {
+namespace qpid {
namespace sys {
class ProtocolFactory;
@@ -69,7 +68,6 @@ struct Url;
namespace broker {
-class ConnectionState;
class ExpiryPolicy;
class Message;
@@ -82,7 +80,7 @@ struct NoSuchTransportException : qpid::Exception
};
/**
- * A broker instance.
+ * A broker instance.
*/
class Broker : public sys::Runnable, public Plugin::Target,
public management::Manageable,
@@ -118,34 +116,29 @@ public:
bool asyncQueueEvents;
bool qmf2Support;
bool qmf1Support;
- uint queueFlowStopRatio; // producer flow control: on
- uint queueFlowResumeRatio; // producer flow control: off
- uint16_t queueThresholdEventRatio;
- std::string defaultMsgGroup;
- bool timestampRcvMsgs;
private:
std::string getHome();
};
-
+
class ConnectionCounter {
int maxConnections;
int connectionCount;
sys::Mutex connectionCountLock;
public:
ConnectionCounter(int mc): maxConnections(mc),connectionCount(0) {};
- void inc_connectionCount() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ void inc_connectionCount() {
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
connectionCount++;
- }
- void dec_connectionCount() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ }
+ void dec_connectionCount() {
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
connectionCount--;
}
bool allowConnection() {
- sys::ScopedLock<sys::Mutex> l(connectionCountLock);
+ sys::ScopedLock<sys::Mutex> l(connectionCountLock);
return (maxConnections <= connectionCount);
- }
+ }
};
private:
@@ -155,20 +148,7 @@ public:
void setStore ();
void setLogLevel(const std::string& level);
std::string getLogLevel();
- void createObject(const std::string& type, const std::string& name,
- const qpid::types::Variant::Map& properties, bool strict, const ConnectionState* context);
- void deleteObject(const std::string& type, const std::string& name,
- const qpid::types::Variant::Map& options, const ConnectionState* context);
- Manageable::status_t queryObject(const std::string& type, const std::string& name,
- qpid::types::Variant::Map& results, const ConnectionState* context);
- Manageable::status_t queryQueue( const std::string& name,
- const std::string& userId,
- const std::string& connectionId,
- qpid::types::Variant::Map& results);
- Manageable::status_t getTimestampConfig(bool& receive,
- const ConnectionState* context);
- Manageable::status_t setTimestampConfig(const bool receive,
- const ConnectionState* context);
+
boost::shared_ptr<sys::Poller> poller;
sys::Timer timer;
std::auto_ptr<sys::Timer> clusterTimer;
@@ -196,10 +176,10 @@ public:
const boost::intrusive_ptr<Message>& msg);
std::string federationTag;
bool recovery;
- bool inCluster, clusterUpdatee;
+ bool clusterUpdatee;
boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
ConnectionCounter connectionCounter;
-
+
public:
virtual ~Broker();
@@ -255,7 +235,7 @@ public:
QPID_BROKER_EXTERN void accept();
/** Create a connection to another broker. */
- void connect(const std::string& host, const std::string& port,
+ void connect(const std::string& host, uint16_t port,
const std::string& transport,
boost::function2<void, int, std::string> failed,
sys::ConnectionCodec::Factory* =0);
@@ -267,10 +247,9 @@ public:
/** Move messages from one queue to another.
A zero quantity means to move all messages
*/
- uint32_t queueMoveMessages( const std::string& srcQueue,
+ uint32_t queueMoveMessages( const std::string& srcQueue,
const std::string& destQueue,
- uint32_t qty,
- const qpid::types::Variant::Map& filter);
+ uint32_t qty);
boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(const std::string& name = TCP_TRANSPORT) const;
@@ -294,20 +273,11 @@ public:
void setRecovery(bool set) { recovery = set; }
bool getRecovery() const { return recovery; }
- /** True of this broker is part of a cluster.
- * Only valid after early initialization of plugins is complete.
- */
- bool isInCluster() const { return inCluster; }
- void setInCluster(bool set) { inCluster = set; }
-
- /** True if this broker is joining a cluster and in the process of
- * receiving a state update.
- */
- bool isClusterUpdatee() const { return clusterUpdatee; }
void setClusterUpdatee(bool set) { clusterUpdatee = set; }
+ bool isClusterUpdatee() const { return clusterUpdatee; }
management::ManagementAgent* getManagementAgent() { return managementAgent.get(); }
-
+
ConnectionCounter& getConnectionCounter() {return connectionCounter;}
/**
@@ -320,43 +290,6 @@ public:
const boost::intrusive_ptr<Message>& msg)> deferDelivery;
bool isAuthenticating ( ) { return config.auth; }
- bool isTimestamping() { return config.timestampRcvMsgs; }
-
- typedef boost::function1<void, boost::shared_ptr<Queue> > QueueFunctor;
-
- std::pair<boost::shared_ptr<Queue>, bool> createQueue(
- const std::string& name,
- bool durable,
- bool autodelete,
- const OwnershipToken* owner,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId);
- void deleteQueue(const std::string& name,
- const std::string& userId,
- const std::string& connectionId,
- QueueFunctor check = QueueFunctor());
- std::pair<Exchange::shared_ptr, bool> createExchange(
- const std::string& name,
- const std::string& type,
- bool durable,
- const std::string& alternateExchange,
- const qpid::framing::FieldTable& args,
- const std::string& userId, const std::string& connectionId);
- void deleteExchange(const std::string& name, const std::string& userId,
- const std::string& connectionId);
- void bind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const qpid::framing::FieldTable& arguments,
- const std::string& userId,
- const std::string& connectionId);
- void unbind(const std::string& queue,
- const std::string& exchange,
- const std::string& key,
- const std::string& userId,
- const std::string& connectionId);
};
}}
diff --git a/cpp/src/qpid/broker/BrokerImportExport.h b/cpp/src/qpid/broker/BrokerImportExport.h
index ee05788063..4edf8c9844 100644
--- a/cpp/src/qpid/broker/BrokerImportExport.h
+++ b/cpp/src/qpid/broker/BrokerImportExport.h
@@ -20,23 +20,14 @@
* under the License.
*/
-#if defined(WIN32) && !defined(QPID_DECLARE_STATIC)
-# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS)
-# define QPID_BROKER_EXTERN __declspec(dllexport)
-# else
-# define QPID_BROKER_EXTERN __declspec(dllimport)
-# endif
-# ifdef _MSC_VER
-# define QPID_BROKER_CLASS_EXTERN
-# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN
-# else
-# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN
-# define QPID_BROKER_INLINE_EXTERN
-# endif
+#if defined(WIN32) && !defined(QPID_BROKER_STATIC)
+#if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS)
+#define QPID_BROKER_EXTERN __declspec(dllexport)
#else
-# define QPID_BROKER_EXTERN
-# define QPID_BROKER_CLASS_EXTERN
-# define QPID_BROKER_INLINE_EXTERN
+#define QPID_BROKER_EXTERN __declspec(dllimport)
+#endif
+#else
+#define QPID_BROKER_EXTERN
#endif
#endif
diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp
index 0b3059d26c..460799280e 100644
--- a/cpp/src/qpid/broker/Connection.cpp
+++ b/cpp/src/qpid/broker/Connection.cpp
@@ -156,7 +156,16 @@ Connection::~Connection()
void Connection::received(framing::AMQFrame& frame) {
// Received frame on connection so delay timeout
restartTimeout();
- adapter.handle(frame);
+
+ if (frame.getChannel() == 0 && frame.getMethod()) {
+ adapter.handle(frame);
+ } else {
+ if (adapter.isOpen())
+ getChannel(frame.getChannel()).in(frame);
+ else
+ close(connection::CLOSE_CODE_FRAMING_ERROR, "Connection not yet open, invalid frame received.");
+ }
+
if (isLink) //i.e. we are acting as the client to another broker
recordFromServer(frame);
else
@@ -269,7 +278,8 @@ void Connection::setUserId(const string& userId)
ConnectionState::setUserId(userId);
// In a cluster, the cluster code will raise the connect event
// when the connection is replicated to the cluster.
- if (!broker.isInCluster()) raiseConnectEvent();
+ if (!sys::isCluster())
+ raiseConnectEvent();
}
void Connection::raiseConnectEvent() {
@@ -279,11 +289,11 @@ void Connection::raiseConnectEvent() {
}
}
-void Connection::setUserProxyAuth(bool b)
+void Connection::setFederationLink(bool b)
{
- ConnectionState::setUserProxyAuth(b);
+ ConnectionState::setFederationLink(b);
if (mgmtObject != 0)
- mgmtObject->set_userProxyAuth(b);
+ mgmtObject->set_federationLink(b);
}
void Connection::close(connection::CloseCode code, const string& text)
@@ -322,30 +332,31 @@ void Connection::closed(){ // Physically closed, suspend open sessions.
try {
while (!channels.empty())
ptr_map_ptr(channels.begin())->handleDetach();
+ while (!exclusiveQueues.empty()) {
+ boost::shared_ptr<Queue> q(exclusiveQueues.front());
+ q->releaseExclusiveOwnership();
+ if (q->canAutoDelete()) {
+ Queue::tryAutoDelete(broker, q);
+ }
+ exclusiveQueues.erase(exclusiveQueues.begin());
+ }
} catch(std::exception& e) {
QPID_LOG(error, QPID_MSG("While closing connection: " << e.what()));
assert(0);
}
}
-void Connection::doIoCallbacks() {
- {
- ScopedLock<Mutex> l(ioCallbackLock);
- // Although IO callbacks execute in the connection thread context, they are
- // not cluster safe because they are queued for execution in non-IO threads.
- ClusterUnsafeScope cus;
- while (!ioCallbacks.empty()) {
- boost::function0<void> cb = ioCallbacks.front();
- ioCallbacks.pop();
- ScopedUnlock<Mutex> ul(ioCallbackLock);
- cb(); // Lend the IO thread for management processing
- }
- }
-}
-
bool Connection::doOutput() {
try {
- doIoCallbacks();
+ {
+ ScopedLock<Mutex> l(ioCallbackLock);
+ while (!ioCallbacks.empty()) {
+ boost::function0<void> cb = ioCallbacks.front();
+ ioCallbacks.pop();
+ ScopedUnlock<Mutex> ul(ioCallbackLock);
+ cb(); // Lend the IO thread for management processing
+ }
+ }
if (mgmtClosing) {
closed();
close(connection::CLOSE_CODE_CONNECTION_FORCED, "Closed by Management Request");
@@ -465,8 +476,8 @@ void Connection::OutboundFrameTracker::abort() { next->abort(); }
void Connection::OutboundFrameTracker::activateOutput() { next->activateOutput(); }
void Connection::OutboundFrameTracker::giveReadCredit(int32_t credit) { next->giveReadCredit(credit); }
void Connection::OutboundFrameTracker::send(framing::AMQFrame& f)
-{
- next->send(f);
+{
+ next->send(f);
con.sent(f);
}
void Connection::OutboundFrameTracker::wrap(sys::ConnectionOutputHandlerPtr& p)
diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h
index 3522d70b35..b751848d73 100644
--- a/cpp/src/qpid/broker/Connection.h
+++ b/cpp/src/qpid/broker/Connection.h
@@ -125,7 +125,7 @@ class Connection : public sys::ConnectionInputHandler,
const std::string& getUserId() const { return ConnectionState::getUserId(); }
const std::string& getMgmtId() const { return mgmtId; }
management::ManagementAgent* getAgent() const { return agent; }
- void setUserProxyAuth(bool b);
+ void setFederationLink(bool b);
/** Connection does not delete the listener. 0 resets. */
void setErrorListener(ErrorListener* l) { errorListener=l; }
ErrorListener* getErrorListener() { return errorListener; }
@@ -153,16 +153,13 @@ class Connection : public sys::ConnectionInputHandler,
void addManagementObject();
const qpid::sys::SecuritySettings& getExternalSecuritySettings() const
- {
+ {
return securitySettings;
}
/** @return true if the initial connection negotiation is complete. */
bool isOpen();
- // Used by cluster during catch-up, see cluster::OutputInterceptor
- void doIoCallbacks();
-
private:
typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap;
typedef std::vector<boost::shared_ptr<Queue> >::iterator queue_iterator;
@@ -204,7 +201,7 @@ class Connection : public sys::ConnectionInputHandler,
sys::ConnectionOutputHandler* next;
};
OutboundFrameTracker outboundTracker;
-
+
void sent(const framing::AMQFrame& f);
public:
diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp
index 7cd91ae539..3f97e5b9de 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/cpp/src/qpid/broker/ConnectionHandler.cpp
@@ -26,7 +26,6 @@
#include "qpid/broker/SecureConnection.h"
#include "qpid/Url.h"
#include "qpid/framing/AllInvoker.h"
-#include "qpid/framing/ConnectionStartOkBody.h"
#include "qpid/framing/enum.h"
#include "qpid/log/Statement.h"
#include "qpid/sys/SecurityLayer.h"
@@ -64,31 +63,13 @@ void ConnectionHandler::heartbeat()
handler->proxy.heartbeat();
}
-bool ConnectionHandler::handle(const framing::AMQMethodBody& method)
-{
- //Need special handling for start-ok, in order to distinguish
- //between null and empty response
- if (method.isA<ConnectionStartOkBody>()) {
- handler->startOk(dynamic_cast<const ConnectionStartOkBody&>(method));
- return true;
- } else {
- return invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler), method);
- }
-}
-
void ConnectionHandler::handle(framing::AMQFrame& frame)
{
AMQMethodBody* method=frame.getBody()->getMethod();
Connection::ErrorListener* errorListener = handler->connection.getErrorListener();
try{
- if (method && handle(*method)) {
- // This is a connection control frame, nothing more to do.
- } else if (isOpen()) {
+ if (!invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler.get()), *method)) {
handler->connection.getChannel(frame.getChannel()).in(frame);
- } else {
- handler->proxy.close(
- connection::CLOSE_CODE_FRAMING_ERROR,
- "Connection not yet open, invalid frame received.");
}
}catch(ConnectionException& e){
if (errorListener) errorListener->connectionError(e.what());
@@ -108,10 +89,13 @@ ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient, bool
ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) :
proxy(c.getOutput()),
- connection(c), serverMode(!isClient), secured(0),
+ connection(c), serverMode(!isClient), acl(0), secured(0),
isOpen(false)
{
if (serverMode) {
+
+ acl = connection.getBroker().getAcl();
+
FieldTable properties;
Array mechanisms(0x95);
@@ -134,20 +118,13 @@ ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow)
ConnectionHandler::Handler::~Handler() {}
-void ConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/,
- const string& /*mechanism*/,
- const string& /*response*/,
+void ConnectionHandler::Handler::startOk(const framing::FieldTable& clientProperties,
+ const string& mechanism,
+ const string& response,
const string& /*locale*/)
{
- //Need special handling for start-ok, in order to distinguish
- //between null and empty response -> should never use this method
- assert(false);
-}
-
-void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
-{
try {
- authenticator->start(body.getMechanism(), body.hasResponse() ? &body.getResponse() : 0);
+ authenticator->start(mechanism, response);
} catch (std::exception& /*e*/) {
management::ManagementAgent* agent = connection.getAgent();
if (agent) {
@@ -159,14 +136,9 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
}
throw;
}
- const framing::FieldTable& clientProperties = body.getClientProperties();
connection.setFederationLink(clientProperties.get(QPID_FED_LINK));
- if (clientProperties.isSet(QPID_FED_TAG)) {
- connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG));
- }
+ connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG));
if (connection.isFederationLink()) {
- AclModule* acl = connection.getBroker().getAcl();
- FieldTable properties;
if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){
proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,"ACL denied creating a federation link");
return;
@@ -211,7 +183,7 @@ void ConnectionHandler::Handler::secureOk(const string& response)
void ConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/,
uint16_t framemax, uint16_t heartbeat)
{
- if (framemax) connection.setFrameMax(framemax);
+ connection.setFrameMax(framemax);
connection.setHeartbeatInterval(heartbeat);
}
@@ -284,6 +256,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
false ); // disallow interaction
}
std::string supportedMechanismsList;
+ bool requestedMechanismIsSupported = false;
Array::const_iterator i;
/*
@@ -296,9 +269,11 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
if (i != supportedMechanisms.begin())
supportedMechanismsList += SPACE;
supportedMechanismsList += (*i)->get<std::string>();
+ requestedMechanismIsSupported = true;
}
}
else {
+ requestedMechanismIsSupported = false;
/*
The caller has requested a mechanism. If it's available,
make sure it ends up at the head of the list.
@@ -307,6 +282,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
string currentMechanism = (*i)->get<std::string>();
if ( requestedMechanism == currentMechanism ) {
+ requestedMechanismIsSupported = true;
supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList;
} else {
if (i != supportedMechanisms.begin())
@@ -316,9 +292,7 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
}
}
- if (serverProperties.isSet(QPID_FED_TAG)) {
- connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG));
- }
+ connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG));
FieldTable ft;
ft.setInt(QPID_FED_LINK,1);
@@ -327,21 +301,11 @@ void ConnectionHandler::Handler::start(const FieldTable& serverProperties,
string response;
if (sasl.get()) {
const qpid::sys::SecuritySettings& ss = connection.getExternalSecuritySettings();
- if (sasl->start ( requestedMechanism.empty()
- ? supportedMechanismsList
- : requestedMechanism,
- response,
- & ss )) {
- proxy.startOk ( ft, sasl->getMechanism(), response, en_US );
- } else {
- //response was null
- ConnectionStartOkBody body;
- body.setClientProperties(ft);
- body.setMechanism(sasl->getMechanism());
- //Don't set response, as none was given
- body.setLocale(en_US);
- proxy.send(body);
- }
+ response = sasl->start ( requestedMechanism.empty()
+ ? supportedMechanismsList
+ : requestedMechanism,
+ & ss );
+ proxy.startOk ( ft, sasl->getMechanism(), response, en_US );
}
else {
response = ((char)0) + username + ((char)0) + password;
diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h
index 05c5f00c57..b32167669e 100644
--- a/cpp/src/qpid/broker/ConnectionHandler.h
+++ b/cpp/src/qpid/broker/ConnectionHandler.h
@@ -26,10 +26,8 @@
#include "qpid/broker/SaslAuthenticator.h"
#include "qpid/framing/amqp_types.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/framing/AMQMethodBody.h"
#include "qpid/framing/AMQP_AllOperations.h"
#include "qpid/framing/AMQP_AllProxy.h"
-#include "qpid/framing/ConnectionStartOkBody.h"
#include "qpid/framing/enum.h"
#include "qpid/framing/FrameHandler.h"
#include "qpid/framing/ProtocolInitiation.h"
@@ -59,12 +57,12 @@ class ConnectionHandler : public framing::FrameHandler
Connection& connection;
bool serverMode;
std::auto_ptr<SaslAuthenticator> authenticator;
+ AclModule* acl;
SecureConnection* secured;
bool isOpen;
Handler(Connection& connection, bool isClient, bool isShadow=false);
~Handler();
- void startOk(const qpid::framing::ConnectionStartOkBody& body);
void startOk(const qpid::framing::FieldTable& clientProperties,
const std::string& mechanism, const std::string& response,
const std::string& locale);
@@ -98,7 +96,7 @@ class ConnectionHandler : public framing::FrameHandler
};
std::auto_ptr<Handler> handler;
- bool handle(const qpid::framing::AMQMethodBody& method);
+
public:
ConnectionHandler(Connection& connection, bool isClient, bool isShadow=false );
void close(framing::connection::CloseCode code, const std::string& text);
diff --git a/cpp/src/qpid/broker/ConnectionState.h b/cpp/src/qpid/broker/ConnectionState.h
index fdd3c4ddc0..774c37408d 100644
--- a/cpp/src/qpid/broker/ConnectionState.h
+++ b/cpp/src/qpid/broker/ConnectionState.h
@@ -46,7 +46,6 @@ class ConnectionState : public ConnectionToken, public management::Manageable
framemax(65535),
heartbeat(0),
heartbeatmax(120),
- userProxyAuth(false), // Can proxy msgs with non-matching auth ids when true (used by federation links & clustering)
federationLink(true),
clientSupportsThrottling(false),
clusterOrderOut(0)
@@ -68,10 +67,8 @@ class ConnectionState : public ConnectionToken, public management::Manageable
void setUrl(const std::string& _url) { url = _url; }
const std::string& getUrl() const { return url; }
- void setUserProxyAuth(const bool b) { userProxyAuth = b; }
- bool isUserProxyAuth() const { return userProxyAuth || federationPeerTag.size() > 0; } // links can proxy msgs with non-matching auth ids
- void setFederationLink(bool b) { federationLink = b; } // deprecated - use setFederationPeerTag() instead
- bool isFederationLink() const { return federationPeerTag.size() > 0; }
+ void setFederationLink(bool b) { federationLink = b; }
+ bool isFederationLink() const { return federationLink; }
void setFederationPeerTag(const std::string& tag) { federationPeerTag = std::string(tag); }
const std::string& getFederationPeerTag() const { return federationPeerTag; }
std::vector<Url>& getKnownHosts() { return knownHosts; }
@@ -82,6 +79,7 @@ class ConnectionState : public ConnectionToken, public management::Manageable
Broker& getBroker() { return broker; }
Broker& broker;
+ std::vector<boost::shared_ptr<Queue> > exclusiveQueues;
//contained output tasks
sys::AggregateOutput outputTasks;
@@ -108,7 +106,6 @@ class ConnectionState : public ConnectionToken, public management::Manageable
uint16_t heartbeatmax;
std::string userId;
std::string url;
- bool userProxyAuth;
bool federationLink;
std::string federationPeerTag;
std::vector<Url> knownHosts;
diff --git a/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h
index 2af9b0c121..b96443fa7c 100644
--- a/cpp/src/qpid/broker/Consumer.h
+++ b/cpp/src/qpid/broker/Consumer.h
@@ -29,33 +29,22 @@ namespace qpid {
namespace broker {
class Queue;
-class QueueListeners;
class Consumer {
const bool acquires;
- // inListeners allows QueueListeners to efficiently track if this instance is registered
- // for notifications without having to search its containers
- bool inListeners;
- // the name is generated by broker and is unique within broker scope. It is not
- // provided or known by the remote Consumer.
- const std::string name;
- public:
- typedef boost::shared_ptr<Consumer> shared_ptr;
-
+ public:
+ typedef boost::shared_ptr<Consumer> shared_ptr;
+
framing::SequenceNumber position;
-
- Consumer(const std::string& _name, bool preAcquires = true)
- : acquires(preAcquires), inListeners(false), name(_name), position(0) {}
+
+ Consumer(bool preAcquires = true) : acquires(preAcquires) {}
bool preAcquires() const { return acquires; }
- const std::string& getName() const { return name; }
-
virtual bool deliver(QueuedMessage& msg) = 0;
virtual void notify() = 0;
virtual bool filter(boost::intrusive_ptr<Message>) { return true; }
virtual bool accept(boost::intrusive_ptr<Message>) { return true; }
virtual OwnershipToken* getSession() = 0;
virtual ~Consumer(){}
- friend class QueueListeners;
};
}}
diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp
index c36538beb7..b30e5f18cb 100644
--- a/cpp/src/qpid/broker/Daemon.cpp
+++ b/cpp/src/qpid/broker/Daemon.cpp
@@ -93,10 +93,11 @@ void Daemon::fork()
catch (const exception& e) {
QPID_LOG(critical, "Unexpected error: " << e.what());
uint16_t port = 0;
- (void) write(pipeFds[1], &port, sizeof(uint16_t));
+ int unused_ret; //Supress warning about ignoring return value.
+ unused_ret = write(pipeFds[1], &port, sizeof(uint16_t));
std::string pipeFailureMessage = e.what();
- (void) write ( pipeFds[1],
+ unused_ret = write ( pipeFds[1],
pipeFailureMessage.c_str(),
strlen(pipeFailureMessage.c_str())
);
diff --git a/cpp/src/qpid/broker/DeliverableMessage.h b/cpp/src/qpid/broker/DeliverableMessage.h
index c8d21001eb..ce613e7b6e 100644
--- a/cpp/src/qpid/broker/DeliverableMessage.h
+++ b/cpp/src/qpid/broker/DeliverableMessage.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace broker {
- class QPID_BROKER_CLASS_EXTERN DeliverableMessage : public Deliverable{
+ class DeliverableMessage : public Deliverable{
boost::intrusive_ptr<Message> msg;
public:
QPID_BROKER_EXTERN DeliverableMessage(const boost::intrusive_ptr<Message>& msg);
diff --git a/cpp/src/qpid/broker/DeliveryRecord.cpp b/cpp/src/qpid/broker/DeliveryRecord.cpp
index 0b8fe95d5e..9443eb6ea5 100644
--- a/cpp/src/qpid/broker/DeliveryRecord.cpp
+++ b/cpp/src/qpid/broker/DeliveryRecord.cpp
@@ -75,7 +75,7 @@ void DeliveryRecord::deliver(framing::FrameHandler& h, DeliveryId deliveryId, ui
{
id = deliveryId;
if (msg.payload->getRedelivered()){
- msg.payload->setRedelivered();
+ msg.payload->getProperties<framing::DeliveryProperties>()->setRedelivered(true);
}
msg.payload->adjustTtl();
@@ -131,20 +131,18 @@ void DeliveryRecord::committed() const{
void DeliveryRecord::reject()
{
- if (acquired && !ended) {
- Exchange::shared_ptr alternate = queue->getAlternateExchange();
- if (alternate) {
- DeliverableMessage delivery(msg.payload);
- alternate->routeWithAlternate(delivery);
- QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to "
- << alternate->getName());
- } else {
- //just drop it
- QPID_LOG(info, "Dropping rejected message from " << queue->getName());
- }
- dequeue();
- setEnded();
+ Exchange::shared_ptr alternate = queue->getAlternateExchange();
+ if (alternate) {
+ DeliverableMessage delivery(msg.payload);
+ alternate->route(delivery, msg.payload->getRoutingKey(), msg.payload->getApplicationHeaders());
+ QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to "
+ << alternate->getName());
+ } else {
+ //just drop it
+ QPID_LOG(info, "Dropping rejected message from " << queue->getName());
}
+
+ dequeue();
}
uint32_t DeliveryRecord::getCredit() const
@@ -153,7 +151,7 @@ uint32_t DeliveryRecord::getCredit() const
}
void DeliveryRecord::acquire(DeliveryIds& results) {
- if (queue->acquire(msg, tag)) {
+ if (queue->acquire(msg)) {
acquired = true;
results.push_back(id);
if (!acceptExpected) {
diff --git a/cpp/src/qpid/broker/DeliveryRecord.h b/cpp/src/qpid/broker/DeliveryRecord.h
index 5a331357be..d388ba94be 100644
--- a/cpp/src/qpid/broker/DeliveryRecord.h
+++ b/cpp/src/qpid/broker/DeliveryRecord.h
@@ -46,7 +46,7 @@ class DeliveryRecord
{
QueuedMessage msg;
mutable boost::shared_ptr<Queue> queue;
- std::string tag; // name of consumer
+ std::string tag;
DeliveryId id;
bool acquired : 1;
bool acceptExpected : 1;
@@ -90,7 +90,7 @@ class DeliveryRecord
bool isAcquired() const { return acquired; }
bool isComplete() const { return completed; }
- bool isRedundant() const { return ended && (!windowing || completed || cancelled); }
+ bool isRedundant() const { return ended && (!windowing || completed); }
bool isCancelled() const { return cancelled; }
bool isAccepted() const { return !acceptExpected; }
bool isEnded() const { return ended; }
diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp
index 5591539853..5b8104c77c 100644
--- a/cpp/src/qpid/broker/DirectExchange.cpp
+++ b/cpp/src/qpid/broker/DirectExchange.cpp
@@ -94,7 +94,7 @@ bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, con
propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin);
if (bk.fedBinding.countFedBindings(queue->getName()) == 0)
- unbind(queue, routingKey, args);
+ unbind(queue, routingKey, 0);
} else if (fedOp == fedOpReorigin) {
/** gather up all the keys that need rebinding in a local vector
@@ -124,24 +124,20 @@ bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, con
return true;
}
-bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args)
+bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* /*args*/)
{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
bool propagate = false;
- QPID_LOG(debug, "Unbinding key [" << routingKey << "] from queue " << queue->getName()
- << " on exchange " << getName() << " origin=" << fedOrigin << ")" );
+ QPID_LOG(debug, "Unbind key [" << routingKey << "] from queue " << queue->getName());
+
{
Mutex::ScopedLock l(lock);
BoundKey& bk = bindings[routingKey];
if (bk.queues.remove_if(MatchQueue(queue))) {
- propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin);
+ propagate = bk.fedBinding.delOrigin();
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
- if (bk.queues.empty()) {
- bindings.erase(routingKey);
- }
} else {
return false;
}
diff --git a/cpp/src/qpid/broker/DtxAck.cpp b/cpp/src/qpid/broker/DtxAck.cpp
index c558681d62..bca3f90bbe 100644
--- a/cpp/src/qpid/broker/DtxAck.cpp
+++ b/cpp/src/qpid/broker/DtxAck.cpp
@@ -32,10 +32,6 @@ DtxAck::DtxAck(const qpid::framing::SequenceSet& acked, DeliveryRecords& unacked
not1(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked)));
}
-DtxAck::DtxAck(DeliveryRecords& unacked) {
- pending = unacked;
-}
-
bool DtxAck::prepare(TransactionContext* ctxt) throw()
{
try{
diff --git a/cpp/src/qpid/broker/DtxAck.h b/cpp/src/qpid/broker/DtxAck.h
index 16c3ff8ba0..166147e58d 100644
--- a/cpp/src/qpid/broker/DtxAck.h
+++ b/cpp/src/qpid/broker/DtxAck.h
@@ -1,6 +1,3 @@
-#ifndef QPID_BROKER_DTXACK_H
-#define QPID_BROKER_DTXACK_H
-
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,6 +18,9 @@
* under the License.
*
*/
+#ifndef _DtxAck_
+#define _DtxAck_
+
#include <algorithm>
#include <functional>
#include <list>
@@ -29,21 +29,20 @@
#include "qpid/broker/TxOp.h"
namespace qpid {
-namespace broker {
-class DtxAck : public TxOp{
- DeliveryRecords pending;
+ namespace broker {
+ class DtxAck : public TxOp{
+ DeliveryRecords pending;
- public:
- DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked);
- DtxAck(DeliveryRecords& unacked);
- virtual bool prepare(TransactionContext* ctxt) throw();
- virtual void commit() throw();
- virtual void rollback() throw();
- virtual ~DtxAck(){}
- virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
- const DeliveryRecords& getPending() const { return pending; }
-};
+ public:
+ DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked);
+ virtual bool prepare(TransactionContext* ctxt) throw();
+ virtual void commit() throw();
+ virtual void rollback() throw();
+ virtual ~DtxAck(){}
+ virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
+ };
+ }
+}
-}} // qpid::broker
-#endif /*!QPID_BROKER_DTXACK_H*/
+#endif
diff --git a/cpp/src/qpid/broker/DtxBuffer.cpp b/cpp/src/qpid/broker/DtxBuffer.cpp
index 13177d3b72..f1b8169cf7 100644
--- a/cpp/src/qpid/broker/DtxBuffer.cpp
+++ b/cpp/src/qpid/broker/DtxBuffer.cpp
@@ -23,11 +23,8 @@
using namespace qpid::broker;
using qpid::sys::Mutex;
-DtxBuffer::DtxBuffer(
- const std::string& _xid,
- bool ended_, bool suspended_, bool failed_, bool expired_)
- : xid(_xid), ended(ended_), suspended(suspended_), failed(failed_), expired(expired_)
-{}
+DtxBuffer::DtxBuffer(const std::string& _xid)
+ : xid(_xid), ended(false), suspended(false), failed(false), expired(false) {}
DtxBuffer::~DtxBuffer() {}
@@ -37,7 +34,7 @@ void DtxBuffer::markEnded()
ended = true;
}
-bool DtxBuffer::isEnded() const
+bool DtxBuffer::isEnded()
{
Mutex::ScopedLock locker(lock);
return ended;
@@ -48,7 +45,7 @@ void DtxBuffer::setSuspended(bool isSuspended)
suspended = isSuspended;
}
-bool DtxBuffer::isSuspended() const
+bool DtxBuffer::isSuspended()
{
return suspended;
}
@@ -61,13 +58,13 @@ void DtxBuffer::fail()
ended = true;
}
-bool DtxBuffer::isRollbackOnly() const
+bool DtxBuffer::isRollbackOnly()
{
Mutex::ScopedLock locker(lock);
return failed;
}
-std::string DtxBuffer::getXid() const
+const std::string& DtxBuffer::getXid()
{
return xid;
}
@@ -79,13 +76,8 @@ void DtxBuffer::timedout()
fail();
}
-bool DtxBuffer::isExpired() const
+bool DtxBuffer::isExpired()
{
Mutex::ScopedLock locker(lock);
return expired;
}
-
-bool DtxBuffer::isFailed() const
-{
- return failed;
-}
diff --git a/cpp/src/qpid/broker/DtxBuffer.h b/cpp/src/qpid/broker/DtxBuffer.h
index cabd37647a..1511cb032f 100644
--- a/cpp/src/qpid/broker/DtxBuffer.h
+++ b/cpp/src/qpid/broker/DtxBuffer.h
@@ -7,9 +7,9 @@
* 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
@@ -26,34 +26,31 @@
#include "qpid/sys/Mutex.h"
namespace qpid {
-namespace broker {
-class DtxBuffer : public TxBuffer{
- mutable sys::Mutex lock;
- const std::string xid;
- bool ended;
- bool suspended;
- bool failed;
- bool expired;
+ namespace broker {
+ class DtxBuffer : public TxBuffer{
+ sys::Mutex lock;
+ const std::string xid;
+ bool ended;
+ bool suspended;
+ bool failed;
+ bool expired;
- public:
- typedef boost::shared_ptr<DtxBuffer> shared_ptr;
+ public:
+ typedef boost::shared_ptr<DtxBuffer> shared_ptr;
- QPID_BROKER_EXTERN DtxBuffer(
- const std::string& xid = "",
- bool ended=false, bool suspended=false, bool failed=false, bool expired=false);
- QPID_BROKER_EXTERN ~DtxBuffer();
- QPID_BROKER_EXTERN void markEnded();
- bool isEnded() const;
- void setSuspended(bool suspended);
- bool isSuspended() const;
- void fail();
- bool isRollbackOnly() const;
- void timedout();
- bool isExpired() const;
- bool isFailed() const;
- std::string getXid() const;
-};
-}
+ QPID_BROKER_EXTERN DtxBuffer(const std::string& xid = "");
+ QPID_BROKER_EXTERN ~DtxBuffer();
+ QPID_BROKER_EXTERN void markEnded();
+ bool isEnded();
+ void setSuspended(bool suspended);
+ bool isSuspended();
+ void fail();
+ bool isRollbackOnly();
+ void timedout();
+ bool isExpired();
+ const std::string& getXid();
+ };
+ }
}
diff --git a/cpp/src/qpid/broker/DtxManager.cpp b/cpp/src/qpid/broker/DtxManager.cpp
index febd547478..3caa41c3f4 100644
--- a/cpp/src/qpid/broker/DtxManager.cpp
+++ b/cpp/src/qpid/broker/DtxManager.cpp
@@ -7,9 +7,9 @@
* 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
@@ -34,7 +34,7 @@ using qpid::ptr_map_ptr;
using namespace qpid::broker;
using namespace qpid::framing;
-DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(&t) {}
+DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(t) {}
DtxManager::~DtxManager() {}
@@ -53,8 +53,8 @@ void DtxManager::recover(const std::string& xid, std::auto_ptr<TPCTransactionCon
createWork(xid)->recover(txn, ops);
}
-bool DtxManager::prepare(const std::string& xid)
-{
+bool DtxManager::prepare(const std::string& xid)
+{
QPID_LOG(debug, "preparing: " << xid);
try {
return getWork(xid)->prepare();
@@ -64,8 +64,8 @@ bool DtxManager::prepare(const std::string& xid)
}
}
-bool DtxManager::commit(const std::string& xid, bool onePhase)
-{
+bool DtxManager::commit(const std::string& xid, bool onePhase)
+{
QPID_LOG(debug, "committing: " << xid);
try {
bool result = getWork(xid)->commit(onePhase);
@@ -77,8 +77,8 @@ bool DtxManager::commit(const std::string& xid, bool onePhase)
}
}
-void DtxManager::rollback(const std::string& xid)
-{
+void DtxManager::rollback(const std::string& xid)
+{
QPID_LOG(debug, "rolling back: " << xid);
try {
getWork(xid)->rollback();
@@ -91,7 +91,7 @@ void DtxManager::rollback(const std::string& xid)
DtxWorkRecord* DtxManager::getWork(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
throw NotFoundException(QPID_MSG("Unrecognised xid " << xid));
@@ -99,14 +99,9 @@ DtxWorkRecord* DtxManager::getWork(const std::string& xid)
return ptr_map_ptr(i);
}
-bool DtxManager::exists(const std::string& xid) {
- Mutex::ScopedLock locker(lock);
- return work.find(xid) != work.end();
-}
-
void DtxManager::remove(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
throw NotFoundException(QPID_MSG("Unrecognised xid " << xid));
@@ -115,15 +110,14 @@ void DtxManager::remove(const std::string& xid)
}
}
-DtxWorkRecord* DtxManager::createWork(const std::string& xid)
+DtxWorkRecord* DtxManager::createWork(std::string xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i != work.end()) {
throw NotAllowedException(QPID_MSG("Xid " << xid << " is already known (use 'join' to add work to an existing xid)"));
} else {
- std::string ncxid = xid; // Work around const correctness problems in ptr_map.
- return ptr_map_ptr(work.insert(ncxid, new DtxWorkRecord(ncxid, store)).first);
+ return ptr_map_ptr(work.insert(xid, new DtxWorkRecord(xid, store)).first);
}
}
@@ -137,7 +131,7 @@ void DtxManager::setTimeout(const std::string& xid, uint32_t secs)
}
timeout = intrusive_ptr<DtxTimeout>(new DtxTimeout(secs, *this, xid));
record->setTimeout(timeout);
- timer->add(timeout);
+ timer.add(timeout);
}
uint32_t DtxManager::getTimeout(const std::string& xid)
@@ -148,7 +142,7 @@ uint32_t DtxManager::getTimeout(const std::string& xid)
void DtxManager::timedout(const std::string& xid)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
WorkMap::iterator i = work.find(xid);
if (i == work.end()) {
QPID_LOG(warning, "Transaction timeout failed: no record for xid");
@@ -159,7 +153,7 @@ void DtxManager::timedout(const std::string& xid)
}
}
-DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
+DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
: TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxCleanup"), mgr(_mgr), xid(_xid) {}
void DtxManager::DtxCleanup::fire()
diff --git a/cpp/src/qpid/broker/DtxManager.h b/cpp/src/qpid/broker/DtxManager.h
index 11895695a3..680b62eeb2 100644
--- a/cpp/src/qpid/broker/DtxManager.h
+++ b/cpp/src/qpid/broker/DtxManager.h
@@ -7,9 +7,9 @@
* 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
@@ -26,8 +26,8 @@
#include "qpid/broker/DtxWorkRecord.h"
#include "qpid/broker/TransactionalStore.h"
#include "qpid/framing/amqp_types.h"
+#include "qpid/sys/Timer.h"
#include "qpid/sys/Mutex.h"
-#include "qpid/ptr_map.h"
namespace qpid {
namespace broker {
@@ -39,21 +39,22 @@ class DtxManager{
{
DtxManager& mgr;
const std::string& xid;
-
- DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid);
+
+ DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid);
void fire();
};
WorkMap work;
TransactionalStore* store;
qpid::sys::Mutex lock;
- qpid::sys::Timer* timer;
+ qpid::sys::Timer& timer;
void remove(const std::string& xid);
- DtxWorkRecord* createWork(const std::string& xid);
+ DtxWorkRecord* getWork(const std::string& xid);
+ DtxWorkRecord* createWork(std::string xid);
public:
- DtxManager(sys::Timer&);
+ DtxManager(qpid::sys::Timer&);
~DtxManager();
void start(const std::string& xid, DtxBuffer::shared_ptr work);
void join(const std::string& xid, DtxBuffer::shared_ptr work);
@@ -65,15 +66,6 @@ public:
uint32_t getTimeout(const std::string& xid);
void timedout(const std::string& xid);
void setStore(TransactionalStore* store);
- void setTimer(sys::Timer& t) { timer = &t; }
-
- // Used by cluster for replication.
- template<class F> void each(F f) const {
- for (WorkMap::const_iterator i = work.begin(); i != work.end(); ++i)
- f(*ptr_map_ptr(i));
- }
- DtxWorkRecord* getWork(const std::string& xid);
- bool exists(const std::string& xid);
};
}
diff --git a/cpp/src/qpid/broker/DtxTimeout.cpp b/cpp/src/qpid/broker/DtxTimeout.cpp
index 58700846ef..c4c52ec40a 100644
--- a/cpp/src/qpid/broker/DtxTimeout.cpp
+++ b/cpp/src/qpid/broker/DtxTimeout.cpp
@@ -25,7 +25,7 @@
using namespace qpid::broker;
DtxTimeout::DtxTimeout(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid)
- : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout-"+_xid), timeout(_timeout), mgr(_mgr), xid(_xid)
+ : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout"), timeout(_timeout), mgr(_mgr), xid(_xid)
{
}
diff --git a/cpp/src/qpid/broker/DtxTimeout.h b/cpp/src/qpid/broker/DtxTimeout.h
index 1fcb4cee2a..680a210e4f 100644
--- a/cpp/src/qpid/broker/DtxTimeout.h
+++ b/cpp/src/qpid/broker/DtxTimeout.h
@@ -7,9 +7,9 @@
* 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
@@ -29,9 +29,7 @@ namespace broker {
class DtxManager;
-struct DtxTimeoutException : public Exception {
- DtxTimeoutException(const std::string& msg=std::string()) : Exception(msg) {}
-};
+struct DtxTimeoutException : public Exception {};
struct DtxTimeout : public sys::TimerTask
{
@@ -39,7 +37,7 @@ struct DtxTimeout : public sys::TimerTask
DtxManager& mgr;
const std::string xid;
- DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid);
+ DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid);
void fire();
};
diff --git a/cpp/src/qpid/broker/DtxWorkRecord.cpp b/cpp/src/qpid/broker/DtxWorkRecord.cpp
index a413fe418d..9f33e698db 100644
--- a/cpp/src/qpid/broker/DtxWorkRecord.cpp
+++ b/cpp/src/qpid/broker/DtxWorkRecord.cpp
@@ -7,9 +7,9 @@
* 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
@@ -28,19 +28,19 @@ using qpid::sys::Mutex;
using namespace qpid::broker;
using namespace qpid::framing;
-DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) :
+DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) :
xid(_xid), store(_store), completed(false), rolledback(false), prepared(false), expired(false) {}
-DtxWorkRecord::~DtxWorkRecord()
+DtxWorkRecord::~DtxWorkRecord()
{
- if (timeout.get()) {
+ if (timeout.get()) {
timeout->cancel();
}
}
bool DtxWorkRecord::prepare()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (check()) {
txn = store->begin(xid);
if (prepare(txn.get())) {
@@ -68,7 +68,7 @@ bool DtxWorkRecord::prepare(TransactionContext* _txn)
bool DtxWorkRecord::commit(bool onePhase)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (check()) {
if (prepared) {
//already prepared i.e. 2pc
@@ -78,13 +78,13 @@ bool DtxWorkRecord::commit(bool onePhase)
store->commit(*txn);
txn.reset();
-
+
std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit));
return true;
} else {
//1pc commit optimisation, don't need a 2pc transaction context:
if (!onePhase) {
- throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!"));
+ throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!"));
}
std::auto_ptr<TransactionContext> localtxn = store->begin();
if (prepare(localtxn.get())) {
@@ -107,16 +107,16 @@ bool DtxWorkRecord::commit(bool onePhase)
void DtxWorkRecord::rollback()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
check();
abort();
}
void DtxWorkRecord::add(DtxBuffer::shared_ptr ops)
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
if (expired) {
- throw DtxTimeoutException(QPID_MSG("Branch with xid " << xid << " has timed out."));
+ throw DtxTimeoutException();
}
if (completed) {
throw CommandInvalidException(QPID_MSG("Branch with xid " << xid << " has been completed!"));
@@ -163,7 +163,7 @@ void DtxWorkRecord::recover(std::auto_ptr<TPCTransactionContext> _txn, DtxBuffer
void DtxWorkRecord::timedout()
{
- Mutex::ScopedLock locker(lock);
+ Mutex::ScopedLock locker(lock);
expired = true;
rolledback = true;
if (!completed) {
@@ -175,17 +175,3 @@ void DtxWorkRecord::timedout()
}
abort();
}
-
-size_t DtxWorkRecord::indexOf(const DtxBuffer::shared_ptr& buf) {
- Work::iterator i = std::find(work.begin(), work.end(), buf);
- if (i == work.end()) throw NotFoundException(
- QPID_MSG("Can't find DTX buffer for xid: " << buf->getXid()));
- return i - work.begin();
-}
-
-DtxBuffer::shared_ptr DtxWorkRecord::operator[](size_t i) const {
- if (i > work.size())
- throw NotFoundException(
- QPID_MSG("Can't find DTX buffer " << i << " for xid: " << xid));
- return work[i];
-}
diff --git a/cpp/src/qpid/broker/DtxWorkRecord.h b/cpp/src/qpid/broker/DtxWorkRecord.h
index 331e42fefd..aec2d2aed4 100644
--- a/cpp/src/qpid/broker/DtxWorkRecord.h
+++ b/cpp/src/qpid/broker/DtxWorkRecord.h
@@ -73,19 +73,9 @@ public:
void timedout();
void setTimeout(boost::intrusive_ptr<DtxTimeout> t) { timeout = t; }
boost::intrusive_ptr<DtxTimeout> getTimeout() { return timeout; }
- std::string getXid() const { return xid; }
- bool isCompleted() const { return completed; }
- bool isRolledback() const { return rolledback; }
- bool isPrepared() const { return prepared; }
- bool isExpired() const { return expired; }
-
- // Used by cluster update;
- size_t size() const { return work.size(); }
- DtxBuffer::shared_ptr operator[](size_t i) const;
- uint32_t getTimeout() const { return timeout? timeout->timeout : 0; }
- size_t indexOf(const DtxBuffer::shared_ptr&);
};
-}} // qpid::broker
+}
+}
#endif
diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp
index d68845062d..d143471559 100644
--- a/cpp/src/qpid/broker/Exchange.cpp
+++ b/cpp/src/qpid/broker/Exchange.cpp
@@ -19,18 +19,16 @@
*
*/
-#include "qpid/broker/Broker.h"
-#include "qpid/broker/DeliverableMessage.h"
#include "qpid/broker/Exchange.h"
#include "qpid/broker/ExchangeRegistry.h"
#include "qpid/broker/FedOps.h"
+#include "qpid/broker/Broker.h"
+#include "qpid/management/ManagementAgent.h"
#include "qpid/broker/Queue.h"
+#include "qpid/log/Statement.h"
#include "qpid/framing/MessageProperties.h"
#include "qpid/framing/reply_exceptions.h"
-#include "qpid/log/Statement.h"
-#include "qpid/management/ManagementAgent.h"
-#include "qpid/sys/ExceptionHolder.h"
-#include <stdexcept>
+#include "qpid/broker/DeliverableMessage.h"
using namespace qpid::broker;
using namespace qpid::framing;
@@ -58,7 +56,7 @@ Exchange::PreRoute::PreRoute(Deliverable& msg, Exchange* _p):parent(_p) {
if (parent->sequence){
parent->sequenceNo++;
- msg.getMessage().insertCustomProperty(qpidMsgSequence,parent->sequenceNo);
+ msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders().setInt64(qpidMsgSequence,parent->sequenceNo);
}
if (parent->ive) {
parent->lastMsg = &( msg.getMessage());
@@ -72,36 +70,6 @@ Exchange::PreRoute::~PreRoute(){
}
}
-namespace {
-/** Store information about an exception to be thrown later.
- * If multiple exceptions are stored, save the first of the "most severe"
- * exceptions, SESSION is les sever than CONNECTION etc.
- */
-class ExInfo {
- public:
- enum Type { NONE, SESSION, CONNECTION, OTHER };
-
- ExInfo(string exchange) : type(NONE), exchange(exchange) {}
- void store(Type type_, const qpid::sys::ExceptionHolder& exception_, const boost::shared_ptr<Queue>& queue) {
- QPID_LOG(warning, "Exchange " << exchange << " cannot deliver to queue "
- << queue->getName() << ": " << exception_.what());
- if (type < type_) { // Replace less severe exception
- type = type_;
- exception = exception_;
- }
- }
-
- void raise() {
- exception.raise();
- }
-
- private:
- Type type;
- string exchange;
- qpid::sys::ExceptionHolder exception;
-};
-}
-
void Exchange::doRoute(Deliverable& msg, ConstBindingList b)
{
int count = 0;
@@ -112,25 +80,11 @@ void Exchange::doRoute(Deliverable& msg, ConstBindingList b)
msg.getMessage().blockContentRelease();
}
-
- ExInfo error(getName()); // Save exception to throw at the end.
for(std::vector<Binding::shared_ptr>::const_iterator i = b->begin(); i != b->end(); i++, count++) {
- try {
- msg.deliverTo((*i)->queue);
- if ((*i)->mgmtBinding != 0)
- (*i)->mgmtBinding->inc_msgMatched();
- }
- catch (const SessionException& e) {
- error.store(ExInfo::SESSION, framing::createSessionException(e.code, e.what()),(*i)->queue);
- }
- catch (const ConnectionException& e) {
- error.store(ExInfo::CONNECTION, framing::createConnectionException(e.code, e.what()), (*i)->queue);
- }
- catch (const std::exception& e) {
- error.store(ExInfo::OTHER, qpid::sys::ExceptionHolder(new Exception(e.what())), (*i)->queue);
- }
+ msg.deliverTo((*i)->queue);
+ if ((*i)->mgmtBinding != 0)
+ (*i)->mgmtBinding->inc_msgMatched();
}
- error.raise();
}
if (mgmtExchange != 0)
@@ -161,7 +115,7 @@ void Exchange::routeIVE(){
Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) :
name(_name), durable(false), persistenceId(0), sequence(false),
- sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false)
+ sequenceNo(0), ive(false), mgmtExchange(0), broker(b)
{
if (parent != 0 && broker != 0)
{
@@ -179,7 +133,7 @@ Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) :
Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::FieldTable& _args,
Manageable* parent, Broker* b)
: name(_name), durable(_durable), alternateUsers(0), persistenceId(0),
- args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false)
+ args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b)
{
if (parent != 0 && broker != 0)
{
@@ -201,11 +155,7 @@ Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::Fiel
}
ive = _args.get(qpidIVE);
- if (ive) {
- if (broker && broker->isInCluster())
- throw framing::NotImplementedException("Cannot use Initial Value Exchanges in a cluster");
- QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value");
- }
+ if (ive) QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value");
}
Exchange::~Exchange ()
@@ -390,14 +340,5 @@ bool Exchange::MatchQueue::operator()(Exchange::Binding::shared_ptr b)
}
void Exchange::setProperties(const boost::intrusive_ptr<Message>& msg) {
- msg->setExchange(getName());
-}
-
-bool Exchange::routeWithAlternate(Deliverable& msg)
-{
- route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders());
- if (!msg.delivered && alternate) {
- alternate->route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders());
- }
- return msg.delivered;
+ msg->getProperties<DeliveryProperties>()->setExchange(getName());
}
diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h
index b12af9a1dd..3c8b5ca2cd 100644
--- a/cpp/src/qpid/broker/Exchange.h
+++ b/cpp/src/qpid/broker/Exchange.h
@@ -10,9 +10,9 @@
* 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
@@ -39,7 +39,7 @@ namespace broker {
class Broker;
class ExchangeRegistry;
-class QPID_BROKER_CLASS_EXTERN Exchange : public PersistableExchange, public management::Manageable {
+class Exchange : public PersistableExchange, public management::Manageable {
public:
struct Binding : public management::Manageable {
typedef boost::shared_ptr<Binding> shared_ptr;
@@ -82,15 +82,15 @@ protected:
private:
Exchange* parent;
};
-
+
typedef boost::shared_ptr<const std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > ConstBindingList;
typedef boost::shared_ptr< std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > BindingList;
void doRoute(Deliverable& msg, ConstBindingList b);
void routeIVE();
-
+
struct MatchQueue {
- const boost::shared_ptr<Queue> queue;
+ const boost::shared_ptr<Queue> queue;
MatchQueue(boost::shared_ptr<Queue> q);
bool operator()(Exchange::Binding::shared_ptr b);
};
@@ -133,15 +133,15 @@ protected:
/** Returns true if propagation is needed. */
bool delOrigin(const std::string& queueName, const std::string& origin){
- if (origin.empty()) { // no remote == local binding
- if (localBindings > 0)
- localBindings--;
- return localBindings == 0;
- }
- size_t match = fedBindings[queueName].erase(origin);
- if (fedBindings[queueName].empty())
- fedBindings.erase(queueName);
- return match != 0;
+ fedBindings[queueName].erase(origin);
+ return true;
+ }
+
+ /** Returns true if propagation is needed. */
+ bool delOrigin() {
+ if (localBindings > 0)
+ localBindings--;
+ return localBindings == 0;
}
uint32_t count() {
@@ -149,11 +149,7 @@ protected:
}
uint32_t countFedBindings(const std::string& queueName) {
- // don't use '[]' - it may increase size of fedBindings!
- std::map<std::string, originSet>::iterator i;
- if ((i = fedBindings.find(queueName)) != fedBindings.end())
- return i->second.size();
- return 0;
+ return fedBindings[queueName].size();
}
};
@@ -166,7 +162,7 @@ public:
Broker* broker = 0);
QPID_BROKER_EXTERN Exchange(const std::string& _name, bool _durable, const qpid::framing::FieldTable& _args,
management::Manageable* parent = 0, Broker* broker = 0);
- QPID_BROKER_INLINE_EXTERN virtual ~Exchange();
+ QPID_BROKER_EXTERN virtual ~Exchange();
const std::string& getName() const { return name; }
bool isDurable() { return durable; }
@@ -195,7 +191,7 @@ public:
virtual bool isBound(boost::shared_ptr<Queue> queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args) = 0;
QPID_BROKER_EXTERN virtual void setProperties(const boost::intrusive_ptr<Message>&);
virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0;
-
+
//PersistableExchange:
QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const;
uint64_t getPersistenceId() const { return persistenceId; }
@@ -226,20 +222,14 @@ public:
*/
void recoveryComplete(ExchangeRegistry& exchanges);
- bool routeWithAlternate(Deliverable& message);
-
- void destroy() { destroyed = true; }
- bool isDestroyed() const { return destroyed; }
-
protected:
qpid::sys::Mutex bridgeLock;
std::vector<DynamicBridge*> bridgeVector;
Broker* broker;
- bool destroyed;
QPID_BROKER_EXTERN virtual void handleHelloRequest();
void propagateFedOp(const std::string& routingKey, const std::string& tags,
- const std::string& op, const std::string& origin,
+ const std::string& op, const std::string& origin,
qpid::framing::FieldTable* extra_args=0);
};
diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp
index 1c8d26c4f7..99b121cbce 100644
--- a/cpp/src/qpid/broker/ExchangeRegistry.cpp
+++ b/cpp/src/qpid/broker/ExchangeRegistry.cpp
@@ -7,9 +7,9 @@
* 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
@@ -39,7 +39,7 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, c
return declare(name, type, false, FieldTable());
}
-pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type,
+pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type,
bool durable, const FieldTable& args){
RWlock::ScopedWlock locker(lock);
ExchangeMap::iterator i = exchanges.find(name);
@@ -61,7 +61,7 @@ pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, c
}else{
FunctionMap::iterator i = factory.find(type);
if (i == factory.end()) {
- throw UnknownExchangeTypeException();
+ throw UnknownExchangeTypeException();
} else {
exchange = i->second(name, durable, args, parent, broker);
}
@@ -82,7 +82,6 @@ void ExchangeRegistry::destroy(const string& name){
RWlock::ScopedWlock locker(lock);
ExchangeMap::iterator i = exchanges.find(name);
if (i != exchanges.end()) {
- i->second->destroy();
exchanges.erase(i);
}
}
@@ -105,7 +104,7 @@ void ExchangeRegistry::registerType(const std::string& type, FactoryFunction f)
}
-namespace
+namespace
{
const std::string empty;
}
diff --git a/cpp/src/qpid/broker/ExpiryPolicy.cpp b/cpp/src/qpid/broker/ExpiryPolicy.cpp
index 62cb3fc116..64a12d918a 100644
--- a/cpp/src/qpid/broker/ExpiryPolicy.cpp
+++ b/cpp/src/qpid/broker/ExpiryPolicy.cpp
@@ -7,9 +7,9 @@
* 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
@@ -27,12 +27,12 @@ namespace broker {
ExpiryPolicy::~ExpiryPolicy() {}
+void ExpiryPolicy::willExpire(Message&) {}
+
bool ExpiryPolicy::hasExpired(Message& m) {
return m.getExpiration() < sys::AbsTime::now();
}
-sys::AbsTime ExpiryPolicy::getCurrentTime() {
- return sys::AbsTime::now();
-}
+void ExpiryPolicy::forget(Message&) {}
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/ExpiryPolicy.h b/cpp/src/qpid/broker/ExpiryPolicy.h
index 2caf00ce00..40e793bf2c 100644
--- a/cpp/src/qpid/broker/ExpiryPolicy.h
+++ b/cpp/src/qpid/broker/ExpiryPolicy.h
@@ -10,9 +10,9 @@
* 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
@@ -26,11 +26,6 @@
#include "qpid/broker/BrokerImportExport.h"
namespace qpid {
-
-namespace sys {
-class AbsTime;
-}
-
namespace broker {
class Message;
@@ -38,12 +33,13 @@ class Message;
/**
* Default expiry policy.
*/
-class QPID_BROKER_CLASS_EXTERN ExpiryPolicy : public RefCounted
+class ExpiryPolicy : public RefCounted
{
public:
QPID_BROKER_EXTERN virtual ~ExpiryPolicy();
+ QPID_BROKER_EXTERN virtual void willExpire(Message&);
QPID_BROKER_EXTERN virtual bool hasExpired(Message&);
- QPID_BROKER_EXTERN virtual qpid::sys::AbsTime getCurrentTime();
+ QPID_BROKER_EXTERN virtual void forget(Message&);
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Fairshare.cpp b/cpp/src/qpid/broker/Fairshare.cpp
index 313aa746f1..e6bbf86691 100644
--- a/cpp/src/qpid/broker/Fairshare.cpp
+++ b/cpp/src/qpid/broker/Fairshare.cpp
@@ -24,7 +24,6 @@
#include "qpid/log/Statement.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/assign/list_of.hpp>
namespace qpid {
namespace broker {
@@ -105,80 +104,51 @@ bool Fairshare::setState(Messages& m, uint priority, uint count)
return fairshare && fairshare->setState(priority, count);
}
-int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys)
+int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::string& key)
{
- qpid::framing::FieldTable::ValuePtr v;
- std::vector<std::string>::const_iterator i = keys.begin();
- while (!v && i != keys.end()) {
- v = settings.get(*i++);
- }
-
+ qpid::framing::FieldTable::ValuePtr v = settings.get(key);
if (!v) {
return 0;
} else if (v->convertsTo<int>()) {
return v->get<int>();
} else if (v->convertsTo<std::string>()){
std::string s = v->get<std::string>();
- try {
- return boost::lexical_cast<int>(s);
+ try {
+ return boost::lexical_cast<int>(s);
} catch(const boost::bad_lexical_cast&) {
- QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << s);
+ QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s);
return 0;
}
} else {
- QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << *v);
+ QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << *v);
return 0;
}
}
-int getIntegerSettingForKey(const qpid::framing::FieldTable& settings, const std::string& key)
-{
- return getIntegerSetting(settings, boost::assign::list_of<std::string>(key));
-}
-
-int getSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys, int minvalue, int maxvalue)
-{
- return std::max(minvalue,std::min(getIntegerSetting(settings, keys), maxvalue));
-}
-
-std::auto_ptr<Fairshare> getFairshareForKey(const qpid::framing::FieldTable& settings, uint levels, const std::string& key)
-{
- uint defaultLimit = getIntegerSettingForKey(settings, key);
- std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit));
- for (uint i = 0; i < levels; i++) {
- std::string levelKey = (boost::format("%1%-%2%") % key % i).str();
- if(settings.isSet(levelKey)) {
- fairshare->setLimit(i, getIntegerSettingForKey(settings, levelKey));
- }
- }
- if (!fairshare->isNull()) {
- return fairshare;
- } else {
- return std::auto_ptr<Fairshare>();
- }
-}
-
-std::auto_ptr<Fairshare> getFairshare(const qpid::framing::FieldTable& settings,
- uint levels,
- const std::vector<std::string>& keys)
+int getSetting(const qpid::framing::FieldTable& settings, const std::string& key, int minvalue, int maxvalue)
{
- std::auto_ptr<Fairshare> fairshare;
- for (std::vector<std::string>::const_iterator i = keys.begin(); i != keys.end() && !fairshare.get(); ++i) {
- fairshare = getFairshareForKey(settings, levels, *i);
- }
- return fairshare;
+ return std::max(minvalue,std::min(getIntegerSetting(settings, key), maxvalue));
}
std::auto_ptr<Messages> Fairshare::create(const qpid::framing::FieldTable& settings)
{
- using boost::assign::list_of;
std::auto_ptr<Messages> result;
- size_t levels = getSetting(settings, list_of<std::string>("qpid.priorities")("x-qpid-priorities"), 0, 100);
+ size_t levels = getSetting(settings, "x-qpid-priorities", 1, 100);
if (levels) {
- std::auto_ptr<Fairshare> fairshare =
- getFairshare(settings, levels, list_of<std::string>("qpid.fairshare")("x-qpid-fairshare"));
- if (fairshare.get()) result = fairshare;
- else result = std::auto_ptr<Messages>(new PriorityQueue(levels));
+ uint defaultLimit = getIntegerSetting(settings, "x-qpid-fairshare");
+ std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit));
+ for (uint i = 0; i < levels; i++) {
+ std::string key = (boost::format("x-qpid-fairshare-%1%") % i).str();
+ if(settings.isSet(key)) {
+ fairshare->setLimit(i, getIntegerSetting(settings, key));
+ }
+ }
+
+ if (fairshare->isNull()) {
+ result = std::auto_ptr<Messages>(new PriorityQueue(levels));
+ } else {
+ result = fairshare;
+ }
}
return result;
}
diff --git a/cpp/src/qpid/broker/Fairshare.h b/cpp/src/qpid/broker/Fairshare.h
index 1b25721e0c..6c4b87f857 100644
--- a/cpp/src/qpid/broker/Fairshare.h
+++ b/cpp/src/qpid/broker/Fairshare.h
@@ -41,18 +41,18 @@ class Fairshare : public PriorityQueue
bool getState(uint& priority, uint& count) const;
bool setState(uint priority, uint count);
void setLimit(size_t level, uint limit);
- bool isNull();
static std::auto_ptr<Messages> create(const qpid::framing::FieldTable& settings);
static bool getState(const Messages&, uint& priority, uint& count);
static bool setState(Messages&, uint priority, uint count);
private:
std::vector<uint> limits;
-
+
uint priority;
uint count;
-
+
uint currentLevel();
uint nextLevel();
+ bool isNull();
bool limitReached();
bool findFrontLevel(uint& p, PriorityLevels&);
};
diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp
index 5879fa0892..ac2c914a97 100644
--- a/cpp/src/qpid/broker/FanOutExchange.cpp
+++ b/cpp/src/qpid/broker/FanOutExchange.cpp
@@ -18,7 +18,6 @@
* under the License.
*
*/
-#include "qpid/log/Statement.h"
#include "qpid/broker/FanOutExchange.h"
#include "qpid/broker/FedOps.h"
#include <algorithm>
@@ -66,7 +65,7 @@ bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const
} else if (fedOp == fedOpUnbind) {
propagate = fedBinding.delOrigin(queue->getName(), fedOrigin);
if (fedBinding.countFedBindings(queue->getName()) == 0)
- unbind(queue, "", args);
+ unbind(queue, "", 0);
} else if (fedOp == fedOpReorigin) {
if (fedBinding.hasLocal()) {
propagateFedOp(string(), string(), fedOpBind, string());
@@ -79,16 +78,12 @@ bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const
return true;
}
-bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args)
+bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* /*args*/)
{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
bool propagate = false;
- QPID_LOG(debug, "Unbinding queue " << queue->getName()
- << " from exchange " << getName() << " origin=" << fedOrigin << ")" );
-
if (bindings.remove_if(MatchQueue(queue))) {
- propagate = fedBinding.delOrigin(queue->getName(), fedOrigin);
+ propagate = fedBinding.delOrigin();
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
diff --git a/cpp/src/qpid/broker/FifoDistributor.cpp b/cpp/src/qpid/broker/FifoDistributor.cpp
deleted file mode 100644
index cdb32d8c8c..0000000000
--- a/cpp/src/qpid/broker/FifoDistributor.cpp
+++ /dev/null
@@ -1,58 +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 "qpid/broker/Queue.h"
-#include "qpid/broker/FifoDistributor.h"
-
-using namespace qpid::broker;
-
-FifoDistributor::FifoDistributor(Messages& container)
- : messages(container) {}
-
-bool FifoDistributor::nextConsumableMessage( Consumer::shared_ptr&, QueuedMessage& next )
-{
- if (!messages.empty()) {
- next = messages.front(); // by default, consume oldest msg
- return true;
- }
- return false;
-}
-
-bool FifoDistributor::allocate(const std::string&, const QueuedMessage& )
-{
- // by default, all messages present on the queue may be allocated as they have yet to
- // be acquired.
- return true;
-}
-
-bool FifoDistributor::nextBrowsableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- if (!messages.empty() && messages.next(c->position, next))
- return true;
- return false;
-}
-
-void FifoDistributor::query(qpid::types::Variant::Map&) const
-{
- // nothing to see here....
-}
-
diff --git a/cpp/src/qpid/broker/FifoDistributor.h b/cpp/src/qpid/broker/FifoDistributor.h
deleted file mode 100644
index 245537ed12..0000000000
--- a/cpp/src/qpid/broker/FifoDistributor.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _broker_FifoDistributor_h
-#define _broker_FifoDistributor_h
-
-/*
- *
- * 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.
- *
- */
-
-/** Simple MessageDistributor for FIFO Queues - the HEAD message is always the next
- * available message for consumption.
- */
-
-#include "qpid/broker/MessageDistributor.h"
-
-namespace qpid {
-namespace broker {
-
-class Messages;
-
-class FifoDistributor : public MessageDistributor
-{
- public:
- FifoDistributor(Messages& container);
-
- /** Locking Note: all methods assume the caller is holding the Queue::messageLock
- * during the method call.
- */
-
- /** MessageDistributor interface */
-
- bool nextConsumableMessage( Consumer::shared_ptr& consumer, QueuedMessage& next );
- bool allocate(const std::string& consumer, const QueuedMessage& target);
- bool nextBrowsableMessage( Consumer::shared_ptr& consumer, QueuedMessage& next );
- void query(qpid::types::Variant::Map&) const;
-
- private:
- Messages& messages;
-};
-
-}}
-
-#endif
diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp
index 4bda70d313..82ac5911ee 100644
--- a/cpp/src/qpid/broker/HeadersExchange.cpp
+++ b/cpp/src/qpid/broker/HeadersExchange.cpp
@@ -112,14 +112,9 @@ bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, co
{
Mutex::ScopedLock l(lock);
- //NOTE: do not include the fed op/tags/origin in the
- //arguments as when x-match is 'all' these would prevent
- //matching (they are internally added properties
- //controlling binding propagation but not relevant to
- //actual routing)
- Binding::shared_ptr binding (new Binding (bindingKey, queue, this, extra_args));
+ Binding::shared_ptr binding (new Binding (bindingKey, queue, this, *args));
BoundKey bk(binding);
- if (bindings.add_unless(bk, MatchArgs(queue, &extra_args))) {
+ if (bindings.add_unless(bk, MatchArgs(queue, args))) {
binding->startManagement();
propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin);
if (mgmtExchange != 0) {
@@ -163,13 +158,12 @@ bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, co
return true;
}
-bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable *args){
+bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable*){
bool propagate = false;
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
{
Mutex::ScopedLock l(lock);
- FedUnbindModifier modifier(queue->getName(), fedOrigin);
+ FedUnbindModifier modifier;
MatchKey match_key(queue, bindingKey);
bindings.modify_if(match_key, modifier);
propagate = modifier.shouldPropagate;
@@ -336,7 +330,11 @@ HeadersExchange::FedUnbindModifier::FedUnbindModifier() : shouldUnbind(false), s
bool HeadersExchange::FedUnbindModifier::operator()(BoundKey & bk)
{
- shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin);
+ if ("" == fedOrigin) {
+ shouldPropagate = bk.fedBinding.delOrigin();
+ } else {
+ shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin);
+ }
if (bk.fedBinding.countFedBindings(queueName) == 0)
{
shouldUnbind = true;
diff --git a/cpp/src/qpid/broker/IncompleteMessageList.cpp b/cpp/src/qpid/broker/IncompleteMessageList.cpp
new file mode 100644
index 0000000000..34d92fa752
--- /dev/null
+++ b/cpp/src/qpid/broker/IncompleteMessageList.cpp
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpid/broker/IncompleteMessageList.h"
+
+namespace qpid {
+namespace broker {
+
+IncompleteMessageList::IncompleteMessageList() :
+ callback(boost::bind(&IncompleteMessageList::enqueueComplete, this, _1))
+{}
+
+IncompleteMessageList::~IncompleteMessageList()
+{
+ // No lock here. We are relying on Messsag::reset*CompleteCallback
+ // to ensure no callbacks are in progress before they return.
+ for (Messages::iterator i = incomplete.begin(); i != incomplete.end(); ++i) {
+ (*i)->resetEnqueueCompleteCallback();
+ (*i)->resetDequeueCompleteCallback();
+ }
+}
+
+void IncompleteMessageList::add(boost::intrusive_ptr<Message> msg)
+{
+ sys::Mutex::ScopedLock l(lock);
+ msg->setEnqueueCompleteCallback(callback);
+ incomplete.push_back(msg);
+}
+
+void IncompleteMessageList::enqueueComplete(const boost::intrusive_ptr<Message>& ) {
+ sys::Mutex::ScopedLock l(lock);
+ lock.notify();
+}
+
+void IncompleteMessageList::process(const CompletionListener& listen, bool sync)
+{
+ sys::Mutex::ScopedLock l(lock);
+ while (!incomplete.empty()) {
+ boost::intrusive_ptr<Message>& msg = incomplete.front();
+ if (!msg->isEnqueueComplete()) {
+ if (sync){
+ {
+ sys::Mutex::ScopedUnlock u(lock);
+ msg->flush(); // Can re-enter IncompleteMessageList::enqueueComplete
+ }
+ while (!msg->isEnqueueComplete())
+ lock.wait();
+ } else {
+ //leave the message as incomplete for now
+ return;
+ }
+ }
+ listen(msg);
+ incomplete.pop_front();
+ }
+}
+
+void IncompleteMessageList::each(const CompletionListener& listen) {
+ Messages snapshot;
+ {
+ sys::Mutex::ScopedLock l(lock);
+ snapshot = incomplete;
+ }
+ std::for_each(incomplete.begin(), incomplete.end(), listen);
+}
+
+}}
diff --git a/cpp/src/qpid/broker/IncompleteMessageList.h b/cpp/src/qpid/broker/IncompleteMessageList.h
new file mode 100644
index 0000000000..a4debd1233
--- /dev/null
+++ b/cpp/src/qpid/broker/IncompleteMessageList.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+#ifndef _IncompleteMessageList_
+#define _IncompleteMessageList_
+
+#include "qpid/broker/BrokerImportExport.h"
+#include "qpid/sys/Monitor.h"
+#include "qpid/broker/Message.h"
+#include <boost/intrusive_ptr.hpp>
+#include <boost/function.hpp>
+#include <list>
+
+namespace qpid {
+namespace broker {
+
+class IncompleteMessageList
+{
+ typedef std::list< boost::intrusive_ptr<Message> > Messages;
+
+ void enqueueComplete(const boost::intrusive_ptr<Message>&);
+
+ sys::Monitor lock;
+ Messages incomplete;
+ Message::MessageCallback callback;
+
+public:
+ typedef Message::MessageCallback CompletionListener;
+
+ QPID_BROKER_EXTERN IncompleteMessageList();
+ QPID_BROKER_EXTERN ~IncompleteMessageList();
+
+ QPID_BROKER_EXTERN void add(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN void process(const CompletionListener& l, bool sync);
+ void each(const CompletionListener& l);
+};
+
+
+}}
+
+#endif
diff --git a/cpp/src/qpid/broker/LegacyLVQ.cpp b/cpp/src/qpid/broker/LegacyLVQ.cpp
index 3262e343a3..a811a86492 100644
--- a/cpp/src/qpid/broker/LegacyLVQ.cpp
+++ b/cpp/src/qpid/broker/LegacyLVQ.cpp
@@ -93,7 +93,11 @@ void LegacyLVQ::removeIf(Predicate p)
//purging of an LVQ is not enabled if the broker is clustered
//(expired messages will be removed on delivery and consolidated
//by key as part of normal LVQ operation).
- if (!broker || !broker->isInCluster())
+
+ //TODO: Is there a neater way to check whether broker is
+ //clustered? Here we assume that if the clustered timer is the
+ //same as the regular timer, we are not clustered:
+ if (!broker || &(broker->getClusterTimer()) == &(broker->getTimer()))
MessageMap::removeIf(p);
}
diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp
index 8010bf43e7..e1091df724 100644
--- a/cpp/src/qpid/broker/Link.cpp
+++ b/cpp/src/qpid/broker/Link.cpp
@@ -7,9 +7,9 @@
* 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
@@ -30,6 +30,7 @@
#include "qpid/framing/enum.h"
#include "qpid/framing/reply_exceptions.h"
#include "qpid/broker/AclModule.h"
+#include "qpid/sys/ClusterSafe.h"
using namespace qpid::broker;
using qpid::framing::Buffer;
@@ -56,8 +57,8 @@ Link::Link(LinkRegistry* _links,
string& _password,
Broker* _broker,
Manageable* parent)
- : links(_links), store(_store), host(_host), port(_port),
- transport(_transport),
+ : links(_links), store(_store), host(_host), port(_port),
+ transport(_transport),
durable(_durable),
authMechanism(_authMechanism), username(_username), password(_password),
persistenceId(0), mgmtObject(0), broker(_broker), state(0),
@@ -96,8 +97,7 @@ void Link::setStateLH (int newState)
return;
state = newState;
-
- if (hideManagement())
+ if (mgmtObject == 0)
return;
switch (state)
@@ -117,12 +117,12 @@ void Link::startConnectionLH ()
// Set the state before calling connect. It is possible that connect
// will fail synchronously and call Link::closed before returning.
setStateLH(STATE_CONNECTING);
- broker->connect (host, boost::lexical_cast<std::string>(port), transport,
+ broker->connect (host, port, transport,
boost::bind (&Link::closed, this, _1, _2));
QPID_LOG (debug, "Inter-broker link connecting to " << host << ":" << port);
} catch(std::exception& e) {
setStateLH(STATE_WAITING);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError (e.what());
}
}
@@ -133,7 +133,8 @@ void Link::established ()
addr << host << ":" << port;
QPID_LOG (info, "Inter-broker link established to " << addr.str());
- if (!hideManagement() && agent)
+ // Don't raise the management event in a cluster, other members wont't get this call.
+ if (!sys::isCluster())
agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str()));
{
@@ -153,11 +154,12 @@ void Link::closed (int, std::string text)
connection = 0;
+ // Don't raise the management event in a cluster, other members wont't get this call.
if (state == STATE_OPERATIONAL) {
stringstream addr;
addr << host << ":" << port;
QPID_LOG (warning, "Inter-broker link disconnected from " << addr.str());
- if (!hideManagement() && agent)
+ if (!sys::isCluster())
agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str()));
}
@@ -170,7 +172,7 @@ void Link::closed (int, std::string text)
if (state != STATE_FAILED)
{
setStateLH(STATE_WAITING);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError (text);
}
@@ -219,7 +221,7 @@ void Link::cancel(Bridge::shared_ptr bridge)
{
{
Mutex::ScopedLock mutex(lock);
-
+
for (Bridges::iterator i = created.begin(); i != created.end(); i++) {
if ((*i).get() == bridge.get()) {
created.erase(i);
@@ -248,19 +250,6 @@ void Link::ioThreadProcessing()
return;
QPID_LOG(debug, "Link::ioThreadProcessing()");
- // check for bridge session errors and recover
- if (!active.empty()) {
- Bridges::iterator removed = std::remove_if(
- active.begin(), active.end(), !boost::bind(&Bridge::isSessionReady, _1));
- for (Bridges::iterator i = removed; i != active.end(); ++i) {
- Bridge::shared_ptr bridge = *i;
- bridge->closed();
- bridge->cancel(*connection);
- created.push_back(bridge);
- }
- active.erase(removed, active.end());
- }
-
//process any pending creates and/or cancellations
if (!created.empty()) {
for (Bridges::iterator i = created.begin(); i != created.end(); ++i) {
@@ -288,9 +277,9 @@ void Link::maintenanceVisit ()
{
Mutex::ScopedLock mutex(lock);
- if (connection && updateUrls) {
+ if (connection && updateUrls) {
urls.reset(connection->getKnownHosts());
- QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls);
+ QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls);
updateUrls = false;
}
@@ -309,7 +298,7 @@ void Link::maintenanceVisit ()
}
}
}
- else if (state == STATE_OPERATIONAL && (!active.empty() || !created.empty() || !cancellations.empty()) && connection != 0)
+ else if (state == STATE_OPERATIONAL && (!created.empty() || !cancellations.empty()) && connection != 0)
connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this));
}
@@ -320,7 +309,7 @@ void Link::reconnect(const qpid::Address& a)
port = a.port;
transport = a.protocol;
startConnectionLH();
- if (!hideManagement()) {
+ if (mgmtObject != 0) {
stringstream errorString;
errorString << "Failed over to " << a;
mgmtObject->set_lastError(errorString.str());
@@ -330,7 +319,7 @@ void Link::reconnect(const qpid::Address& a)
bool Link::tryFailover()
{
Address next;
- if (urls.next(next) &&
+ if (urls.next(next) &&
(next.host != host || next.port != port || next.protocol != transport)) {
links->changeAddress(Address(transport, host, port), next);
QPID_LOG(debug, "Link failing over to " << host << ":" << port);
@@ -340,12 +329,6 @@ bool Link::tryFailover()
}
}
-// Management updates for a linke are inconsistent in a cluster, so they are
-// suppressed.
-bool Link::hideManagement() const {
- return !mgmtObject || ( broker && broker->isInCluster());
-}
-
uint Link::nextChannel()
{
Mutex::ScopedLock mutex(lock);
@@ -358,7 +341,7 @@ void Link::notifyConnectionForced(const string text)
Mutex::ScopedLock mutex(lock);
setStateLH(STATE_FAILED);
- if (!hideManagement())
+ if (mgmtObject != 0)
mgmtObject->set_lastError(text);
}
@@ -380,7 +363,7 @@ Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
string authMechanism;
string username;
string password;
-
+
buffer.getShortString(host);
port = buffer.getShort();
buffer.getShortString(transport);
@@ -392,7 +375,7 @@ Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer)
return links.declare(host, port, transport, durable, authMechanism, username, password).first;
}
-void Link::encode(Buffer& buffer) const
+void Link::encode(Buffer& buffer) const
{
buffer.putShortString(string("link"));
buffer.putShortString(host);
@@ -404,8 +387,8 @@ void Link::encode(Buffer& buffer) const
buffer.putShortString(password);
}
-uint32_t Link::encodedSize() const
-{
+uint32_t Link::encodedSize() const
+{
return host.size() + 1 // short-string (host)
+ 5 // short-string ("link")
+ 2 // port
diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h
index 4badd8b3a1..75a680ff5d 100644
--- a/cpp/src/qpid/broker/Link.h
+++ b/cpp/src/qpid/broker/Link.h
@@ -10,9 +10,9 @@
* 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
@@ -85,7 +85,6 @@ namespace qpid {
void destroy(); // Called when mgmt deletes this link
void ioThreadProcessing(); // Called on connection's IO thread by request
bool tryFailover(); // Called during maintenance visit
- bool hideManagement() const;
public:
typedef boost::shared_ptr<Link> shared_ptr;
@@ -123,12 +122,12 @@ namespace qpid {
void notifyConnectionForced(const std::string text);
void setPassive(bool p);
-
+
// PersistableConfig:
void setPersistenceId(uint64_t id) const;
uint64_t getPersistenceId() const { return persistenceId; }
uint32_t encodedSize() const;
- void encode(framing::Buffer& buffer) const;
+ void encode(framing::Buffer& buffer) const;
const std::string& getName() const;
static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer);
@@ -136,7 +135,6 @@ namespace qpid {
// Manageable entry points
management::ManagementObject* GetManagementObject(void) const;
management::Manageable::status_t ManagementMethod(uint32_t, management::Args&, std::string&);
-
};
}
}
diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp
index e9885f5462..7b1c75db74 100644
--- a/cpp/src/qpid/broker/LinkRegistry.cpp
+++ b/cpp/src/qpid/broker/LinkRegistry.cpp
@@ -7,9 +7,9 @@
* 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
@@ -381,7 +381,7 @@ std::string LinkRegistry::createKey(const std::string& host, uint16_t port) {
return keystream.str();
}
-void LinkRegistry::setPassive(bool p)
+void LinkRegistry::setPassive(bool p)
{
Mutex::ScopedLock locker(lock);
passiveChanged = p != passive;
diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp
index d13109dad1..c589669e5a 100644
--- a/cpp/src/qpid/broker/Message.cpp
+++ b/cpp/src/qpid/broker/Message.cpp
@@ -7,9 +7,9 @@
* 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
@@ -30,7 +30,6 @@
#include "qpid/framing/SendContent.h"
#include "qpid/framing/SequenceNumber.h"
#include "qpid/framing/TypeFilter.h"
-#include "qpid/framing/reply_exceptions.h"
#include "qpid/log/Statement.h"
#include <time.h>
@@ -50,16 +49,27 @@ TransferAdapter Message::TRANSFER;
Message::Message(const framing::SequenceNumber& id) :
frames(id), persistenceId(0), redelivered(false), loaded(false),
- staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
- expiration(FAR_FUTURE), dequeueCallback(0),
- inCallback(false), requiredCredit(0), isManagementMessage(false), copyHeaderOnWrite(false)
-{}
+ staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
+ expiration(FAR_FUTURE), enqueueCallback(0), dequeueCallback(0),
+ inCallback(false), requiredCredit(0) {}
-Message::~Message() {}
+Message::Message(const Message& original) :
+ PersistableMessage(), frames(original.frames), persistenceId(0), redelivered(false), loaded(false),
+ staged(false), forcePersistentPolicy(false), publisher(0), adapter(0),
+ expiration(original.expiration), enqueueCallback(0), dequeueCallback(0),
+ inCallback(false), requiredCredit(0)
+{
+ setExpiryPolicy(original.expiryPolicy);
+}
+
+Message::~Message()
+{
+ if (expiryPolicy)
+ expiryPolicy->forget(*this);
+}
void Message::forcePersistent()
{
- sys::Mutex::ScopedLock l(lock);
// only set forced bit if we actually need to force.
if (! getAdapter().isPersistent(frames) ){
forcePersistentPolicy = true;
@@ -76,7 +86,7 @@ std::string Message::getRoutingKey() const
return getAdapter().getRoutingKey(frames);
}
-std::string Message::getExchangeName() const
+std::string Message::getExchangeName() const
{
return getAdapter().getExchange(frames);
}
@@ -85,7 +95,7 @@ const boost::shared_ptr<Exchange> Message::getExchange(ExchangeRegistry& registr
{
if (!exchange) {
exchange = registry.get(getExchangeName());
- }
+ }
return exchange;
}
@@ -96,19 +106,16 @@ bool Message::isImmediate() const
const FieldTable* Message::getApplicationHeaders() const
{
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getApplicationHeaders(frames);
}
std::string Message::getAppId() const
{
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getAppId(frames);
}
bool Message::isPersistent() const
{
- sys::Mutex::ScopedLock l(lock);
return (getAdapter().isPersistent(frames) || forcePersistentPolicy);
}
@@ -188,7 +195,7 @@ void Message::decodeContent(framing::Buffer& buffer)
} else {
//adjust header flags
MarkLastSegment f;
- frames.map_if(f, TypeFilter<HEADER_BODY>());
+ frames.map_if(f, TypeFilter<HEADER_BODY>());
}
//mark content loaded
loaded = true;
@@ -240,7 +247,7 @@ void Message::destroy()
bool Message::getContentFrame(const Queue& queue, AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const
{
intrusive_ptr<const PersistableMessage> pmsg(this);
-
+
bool done = false;
string& data = frame.castBody<AMQContentBody>()->getData();
store->loadContent(queue, pmsg, data, offset, maxContentSize);
@@ -265,7 +272,7 @@ void Message::sendContent(const Queue& queue, framing::FrameHandler& out, uint16
uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead();
bool morecontent = true;
for (uint64_t offset = 0; morecontent; offset += maxContentSize)
- {
+ {
AMQFrame frame((AMQContentBody()));
morecontent = getContentFrame(queue, frame, maxContentSize, offset);
out.handle(frame);
@@ -283,10 +290,7 @@ void Message::sendHeader(framing::FrameHandler& out, uint16_t /*maxFrameSize*/)
{
sys::Mutex::ScopedLock l(lock);
Relay f(out);
- frames.map_if(f, TypeFilter<HEADER_BODY>());
- //as frame (and pointer to body) has now been passed to handler,
- //subsequent modifications should use a copy
- copyHeaderOnWrite = true;
+ frames.map_if(f, TypeFilter<HEADER_BODY>());
}
// TODO aconway 2007-11-09: Obsolete, remove. Was used to cover over
@@ -316,14 +320,13 @@ bool Message::isContentLoaded() const
}
-namespace
+namespace
{
const std::string X_QPID_TRACE("x-qpid.trace");
}
bool Message::isExcluded(const std::vector<std::string>& excludes) const
{
- sys::Mutex::ScopedLock l(lock);
const FieldTable* headers = getApplicationHeaders();
if (headers) {
std::string traceStr = headers->getAsString(X_QPID_TRACE);
@@ -342,30 +345,11 @@ bool Message::isExcluded(const std::vector<std::string>& excludes) const
return false;
}
-class CloneHeaderBody
-{
-public:
- void operator()(AMQFrame& f)
- {
- f.cloneBody();
- }
-};
-
-AMQHeaderBody* Message::getHeaderBody()
-{
- if (copyHeaderOnWrite) {
- CloneHeaderBody f;
- frames.map_if(f, TypeFilter<HEADER_BODY>());
- copyHeaderOnWrite = false;
- }
- return frames.getHeaders();
-}
-
void Message::addTraceId(const std::string& id)
{
sys::Mutex::ScopedLock l(lock);
if (isA<MessageTransferBody>()) {
- FieldTable& headers = getModifiableProperties<MessageProperties>()->getApplicationHeaders();
+ FieldTable& headers = getProperties<MessageProperties>()->getApplicationHeaders();
std::string trace = headers.getAsString(X_QPID_TRACE);
if (trace.empty()) {
headers.setString(X_QPID_TRACE, id);
@@ -373,22 +357,13 @@ void Message::addTraceId(const std::string& id)
trace += ",";
trace += id;
headers.setString(X_QPID_TRACE, trace);
- }
+ }
}
}
-void Message::setTimestamp()
-{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
- time_t now = ::time(0);
- props->setTimestamp(now); // AMQP-0.10: posix time_t - secs since Epoch
-}
-
-void Message::computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e)
+void Message::setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e)
{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
+ DeliveryProperties* props = getProperties<DeliveryProperties>();
if (props->getTtl()) {
// AMQP requires setting the expiration property to be posix
// time_t in seconds. TTL is in milliseconds
@@ -397,70 +372,26 @@ void Message::computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e)
time_t now = ::time(0);
props->setExpiration(now + (props->getTtl()/1000));
}
- if (e) {
- // Use higher resolution time for the internal expiry calculation.
- // Prevent overflow as a signed int64_t
- Duration ttl(std::min(props->getTtl() * TIME_MSEC,
- (uint64_t) std::numeric_limits<int64_t>::max()));
- expiration = AbsTime(e->getCurrentTime(), ttl);
- setExpiryPolicy(e);
- }
+ // Use higher resolution time for the internal expiry calculation.
+ expiration = AbsTime(AbsTime::now(), Duration(props->getTtl() * TIME_MSEC));
+ setExpiryPolicy(e);
}
}
void Message::adjustTtl()
{
- sys::Mutex::ScopedLock l(lock);
- DeliveryProperties* props = getModifiableProperties<DeliveryProperties>();
+ DeliveryProperties* props = getProperties<DeliveryProperties>();
if (props->getTtl()) {
- if (expiration < FAR_FUTURE) {
- sys::AbsTime current(
- expiryPolicy ? expiryPolicy->getCurrentTime() : sys::AbsTime::now());
- sys::Duration ttl(current, getExpiration());
- // convert from ns to ms; set to 1 if expired
- props->setTtl(int64_t(ttl) >= 1000000 ? int64_t(ttl)/1000000 : 1);
- }
+ sys::Mutex::ScopedLock l(lock);
+ sys::Duration d(sys::AbsTime::now(), getExpiration());
+ props->setTtl(int64_t(d) > 0 ? int64_t(d)/1000000 : 1); // convert from ns to ms; set to 1 if expired
}
}
-void Message::setRedelivered()
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<framing::DeliveryProperties>()->setRedelivered(true);
-}
-
-void Message::insertCustomProperty(const std::string& key, int64_t value)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().setInt64(key,value);
-}
-
-void Message::insertCustomProperty(const std::string& key, const std::string& value)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().setString(key,value);
-}
-
-void Message::removeCustomProperty(const std::string& key)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->getApplicationHeaders().erase(key);
-}
-
-void Message::setExchange(const std::string& exchange)
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<DeliveryProperties>()->setExchange(exchange);
-}
-
-void Message::clearApplicationHeadersFlag()
-{
- sys::Mutex::ScopedLock l(lock);
- getModifiableProperties<MessageProperties>()->clearApplicationHeadersFlag();
-}
-
void Message::setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) {
expiryPolicy = e;
+ if (expiryPolicy)
+ expiryPolicy->willExpire(*this);
}
bool Message::hasExpired()
@@ -484,12 +415,30 @@ struct ScopedSet {
};
}
+void Message::allEnqueuesComplete() {
+ ScopedSet ss(callbackLock, inCallback);
+ MessageCallback* cb = enqueueCallback;
+ if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
+}
+
void Message::allDequeuesComplete() {
ScopedSet ss(callbackLock, inCallback);
MessageCallback* cb = dequeueCallback;
if (cb && *cb) (*cb)(intrusive_ptr<Message>(this));
}
+void Message::setEnqueueCompleteCallback(MessageCallback& cb) {
+ sys::Mutex::ScopedLock l(callbackLock);
+ while (inCallback) callbackLock.wait();
+ enqueueCallback = &cb;
+}
+
+void Message::resetEnqueueCompleteCallback() {
+ sys::Mutex::ScopedLock l(callbackLock);
+ while (inCallback) callbackLock.wait();
+ enqueueCallback = 0;
+}
+
void Message::setDequeueCompleteCallback(MessageCallback& cb) {
sys::Mutex::ScopedLock l(callbackLock);
while (inCallback) callbackLock.wait();
@@ -503,11 +452,12 @@ void Message::resetDequeueCompleteCallback() {
}
uint8_t Message::getPriority() const {
- sys::Mutex::ScopedLock l(lock);
return getAdapter().getPriority(frames);
}
-bool Message::getIsManagementMessage() const { return isManagementMessage; }
-void Message::setIsManagementMessage(bool b) { isManagementMessage = b; }
+framing::FieldTable& Message::getOrInsertHeaders()
+{
+ return getProperties<MessageProperties>()->getApplicationHeaders();
+}
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h
index dda45d73e6..f7dd2734b6 100644
--- a/cpp/src/qpid/broker/Message.h
+++ b/cpp/src/qpid/broker/Message.h
@@ -10,9 +10,9 @@
* 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
@@ -29,21 +29,17 @@
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Time.h"
#include <boost/function.hpp>
-#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
-#include <memory>
#include <string>
#include <vector>
namespace qpid {
-
+
namespace framing {
-class AMQBody;
-class AMQHeaderBody;
class FieldTable;
class SequenceNumber;
}
-
+
namespace broker {
class ConnectionToken;
class Exchange;
@@ -55,10 +51,11 @@ class ExpiryPolicy;
class Message : public PersistableMessage {
public:
typedef boost::function<void (const boost::intrusive_ptr<Message>&)> MessageCallback;
-
+
QPID_BROKER_EXTERN Message(const framing::SequenceNumber& id = framing::SequenceNumber());
+ QPID_BROKER_EXTERN Message(const Message&);
QPID_BROKER_EXTERN ~Message();
-
+
uint64_t getPersistenceId() const { return persistenceId; }
void setPersistenceId(uint64_t _persistenceId) const { persistenceId = _persistenceId; }
@@ -78,31 +75,27 @@ public:
bool isImmediate() const;
QPID_BROKER_EXTERN const framing::FieldTable* getApplicationHeaders() const;
QPID_BROKER_EXTERN std::string getAppId() const;
+ framing::FieldTable& getOrInsertHeaders();
QPID_BROKER_EXTERN bool isPersistent() const;
bool requiresAccept();
- /** determine msg expiration time using the TTL value if present */
- QPID_BROKER_EXTERN void computeExpiration(const boost::intrusive_ptr<ExpiryPolicy>& e);
+ QPID_BROKER_EXTERN void setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e);
void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e);
bool hasExpired();
sys::AbsTime getExpiration() const { return expiration; }
- void setExpiration(sys::AbsTime exp) { expiration = exp; }
void adjustTtl();
- void setRedelivered();
- QPID_BROKER_EXTERN void insertCustomProperty(const std::string& key, int64_t value);
- QPID_BROKER_EXTERN void insertCustomProperty(const std::string& key, const std::string& value);
- QPID_BROKER_EXTERN void removeCustomProperty(const std::string& key);
- void setExchange(const std::string&);
- void clearApplicationHeadersFlag();
- /** set the timestamp delivery property to the current time-of-day */
- QPID_BROKER_EXTERN void setTimestamp();
-
- framing::FrameSet& getFrames() { return frames; }
- const framing::FrameSet& getFrames() const { return frames; }
+
+ framing::FrameSet& getFrames() { return frames; }
+ const framing::FrameSet& getFrames() const { return frames; }
+
+ template <class T> T* getProperties() {
+ qpid::framing::AMQHeaderBody* p = frames.getHeaders();
+ return p->get<T>(true);
+ }
template <class T> const T* getProperties() const {
- const qpid::framing::AMQHeaderBody* p = frames.getHeaders();
- return p->get<T>();
+ qpid::framing::AMQHeaderBody* p = frames.getHeaders();
+ return p->get<T>(true);
}
template <class T> const T* hasProperties() const {
@@ -110,11 +103,6 @@ public:
return p->get<T>();
}
- template <class T> void eraseProperties() {
- qpid::framing::AMQHeaderBody* p = frames.getHeaders();
- p->erase<T>();
- }
-
template <class T> const T* getMethod() const {
return frames.as<T>();
}
@@ -147,7 +135,7 @@ public:
QPID_BROKER_EXTERN void decodeHeader(framing::Buffer& buffer);
QPID_BROKER_EXTERN void decodeContent(framing::Buffer& buffer);
-
+
void QPID_BROKER_EXTERN tryReleaseContent();
void releaseContent();
void releaseContent(MessageStore* s);//deprecated, use 'setStore(store); releaseContent();' instead
@@ -161,19 +149,24 @@ public:
bool isExcluded(const std::vector<std::string>& excludes) const;
void addTraceId(const std::string& id);
+
+ void forcePersistent();
+ bool isForcedPersistent();
+
- void forcePersistent();
- bool isForcedPersistent();
+ /** Call cb when enqueue is complete, may call immediately. Holds cb by reference. */
+ void setEnqueueCompleteCallback(MessageCallback& cb);
+ void resetEnqueueCompleteCallback();
/** Call cb when dequeue is complete, may call immediately. Holds cb by reference. */
void setDequeueCompleteCallback(MessageCallback& cb);
void resetDequeueCompleteCallback();
uint8_t getPriority() const;
- bool getIsManagementMessage() const;
- void setIsManagementMessage(bool b);
+
private:
MessageAdapter& getAdapter() const;
+ void allEnqueuesComplete();
void allDequeuesComplete();
mutable sys::Mutex lock;
@@ -183,7 +176,7 @@ public:
bool redelivered;
bool loaded;
bool staged;
- bool forcePersistentPolicy; // used to force message as durable, via a broker policy
+ bool forcePersistentPolicy; // used to force message as durable, via a broker policy
ConnectionToken* publisher;
mutable MessageAdapter* adapter;
qpid::sys::AbsTime expiration;
@@ -194,20 +187,11 @@ public:
mutable boost::intrusive_ptr<Message> empty;
sys::Monitor callbackLock;
+ MessageCallback* enqueueCallback;
MessageCallback* dequeueCallback;
bool inCallback;
uint32_t requiredCredit;
- bool isManagementMessage;
- mutable bool copyHeaderOnWrite;
-
- /**
- * Expects lock to be held
- */
- template <class T> T* getModifiableProperties() {
- return getHeaderBody()->get<T>(true);
- }
- qpid::framing::AMQHeaderBody* getHeaderBody();
};
}}
diff --git a/cpp/src/qpid/broker/MessageBuilder.h b/cpp/src/qpid/broker/MessageBuilder.h
index b99b8efee6..75dfd6781d 100644
--- a/cpp/src/qpid/broker/MessageBuilder.h
+++ b/cpp/src/qpid/broker/MessageBuilder.h
@@ -33,7 +33,7 @@ namespace qpid {
class Message;
class MessageStore;
- class QPID_BROKER_CLASS_EXTERN MessageBuilder : public framing::FrameHandler{
+ class MessageBuilder : public framing::FrameHandler{
public:
QPID_BROKER_EXTERN MessageBuilder(MessageStore* const store);
QPID_BROKER_EXTERN void handle(framing::AMQFrame& frame);
diff --git a/cpp/src/qpid/broker/MessageDistributor.h b/cpp/src/qpid/broker/MessageDistributor.h
deleted file mode 100644
index 090393c160..0000000000
--- a/cpp/src/qpid/broker/MessageDistributor.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _broker_MessageDistributor_h
-#define _broker_MessageDistributor_h
-
-/*
- *
- * 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.
- *
- */
-
-/** Abstraction used by Queue to determine the next "most desirable" message to provide to
- * a particular consuming client
- */
-
-
-#include "qpid/broker/Consumer.h"
-
-namespace qpid {
-namespace broker {
-
-struct QueuedMessage;
-
-class MessageDistributor
-{
- public:
- virtual ~MessageDistributor() {};
-
- /** Locking Note: all methods assume the caller is holding the Queue::messageLock
- * during the method call.
- */
-
- /** Determine the next message available for consumption by the consumer
- * @param consumer the consumer that needs a message to consume
- * @param next set to the next message that the consumer may consume.
- * @return true if message is available and next is set
- */
- virtual bool nextConsumableMessage( Consumer::shared_ptr& consumer,
- QueuedMessage& next ) = 0;
-
- /** Allow the comsumer to take ownership of the given message.
- * @param consumer the name of the consumer that is attempting to acquire the message
- * @param qm the message to be acquired, previously returned from nextConsumableMessage()
- * @return true if ownership is permitted, false if ownership cannot be assigned.
- */
- virtual bool allocate( const std::string& consumer,
- const QueuedMessage& target) = 0;
-
- /** Determine the next message available for browsing by the consumer
- * @param consumer the consumer that is browsing the queue
- * @param next set to the next message that the consumer may browse.
- * @return true if a message is available and next is returned
- */
- virtual bool nextBrowsableMessage( Consumer::shared_ptr& consumer,
- QueuedMessage& next ) = 0;
-
- /** hook to add any interesting management state to the status map */
- virtual void query(qpid::types::Variant::Map&) const = 0;
-};
-
-}}
-
-#endif
diff --git a/cpp/src/qpid/broker/MessageGroupManager.cpp b/cpp/src/qpid/broker/MessageGroupManager.cpp
deleted file mode 100644
index 07b05f3b92..0000000000
--- a/cpp/src/qpid/broker/MessageGroupManager.cpp
+++ /dev/null
@@ -1,411 +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 "qpid/framing/FieldTable.h"
-#include "qpid/types/Variant.h"
-#include "qpid/log/Statement.h"
-#include "qpid/broker/Queue.h"
-#include "qpid/broker/MessageGroupManager.h"
-
-using namespace qpid::broker;
-
-namespace {
- const std::string GROUP_QUERY_KEY("qpid.message_group_queue");
- const std::string GROUP_HEADER_KEY("group_header_key");
- const std::string GROUP_STATE_KEY("group_state");
- const std::string GROUP_ID_KEY("group_id");
- const std::string GROUP_MSG_COUNT("msg_count");
- const std::string GROUP_TIMESTAMP("timestamp");
- const std::string GROUP_CONSUMER("consumer");
-}
-
-
-const std::string MessageGroupManager::qpidMessageGroupKey("qpid.group_header_key");
-const std::string MessageGroupManager::qpidSharedGroup("qpid.shared_msg_group");
-const std::string MessageGroupManager::qpidMessageGroupTimestamp("qpid.group_timestamp");
-
-
-void MessageGroupManager::unFree( const GroupState& state )
-{
- GroupFifo::iterator pos = freeGroups.find( state.members.front() );
- assert( pos != freeGroups.end() && pos->second == &state );
- freeGroups.erase( pos );
-}
-
-void MessageGroupManager::own( GroupState& state, const std::string& owner )
-{
- state.owner = owner;
- unFree( state );
-}
-
-void MessageGroupManager::disown( GroupState& state )
-{
- state.owner.clear();
- assert(state.members.size());
- assert(freeGroups.find(state.members.front()) == freeGroups.end());
- freeGroups[state.members.front()] = &state;
-}
-
-const std::string MessageGroupManager::getGroupId( const QueuedMessage& qm ) const
-{
- const qpid::framing::FieldTable* headers = qm.payload->getApplicationHeaders();
- if (!headers) return defaultGroupId;
- qpid::framing::FieldTable::ValuePtr id = headers->get( groupIdHeader );
- if (!id || !id->convertsTo<std::string>()) return defaultGroupId;
- return id->get<std::string>();
-}
-
-
-void MessageGroupManager::enqueued( const QueuedMessage& qm )
-{
- // @todo KAG optimization - store reference to group state in QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupState &state(messageGroups[group]);
- state.members.push_back(qm.position);
- uint32_t total = state.members.size();
- QPID_LOG( trace, "group queue " << qName <<
- ": added message to group id=" << group << " total=" << total );
- if (total == 1) {
- // newly created group, no owner
- state.group = group;
- assert(freeGroups.find(qm.position) == freeGroups.end());
- freeGroups[qm.position] = &state;
- }
-}
-
-
-void MessageGroupManager::acquired( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- state.acquired += 1;
- QPID_LOG( trace, "group queue " << qName <<
- ": acquired message in group id=" << group << " acquired=" << state.acquired );
-}
-
-
-void MessageGroupManager::requeued( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- assert( state.acquired != 0 );
- state.acquired -= 1;
- if (state.acquired == 0 && state.owned()) {
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << state.owner << " released group id=" << gs->first);
- disown(state);
- }
- QPID_LOG( trace, "group queue " << qName <<
- ": requeued message to group id=" << group << " acquired=" << state.acquired );
-}
-
-
-void MessageGroupManager::dequeued( const QueuedMessage& qm )
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- // issue: const-ness??
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- assert( state.members.size() != 0 );
- assert( state.acquired != 0 );
- state.acquired -= 1;
-
- // likely to be at or near begin() if dequeued in order
- bool reFreeNeeded = false;
- if (state.members.front() == qm.position) {
- if (!state.owned()) {
- // will be on the freeGroups list if mgmt is dequeueing rather than a consumer!
- // if on freelist, it is indexed by first member, which is about to be removed!
- unFree(state);
- reFreeNeeded = true;
- }
- state.members.pop_front();
- } else {
- GroupState::PositionFifo::iterator pos = state.members.begin() + 1;
- GroupState::PositionFifo::iterator end = state.members.end();
- while (pos != end) {
- if (*pos == qm.position) {
- state.members.erase(pos);
- break;
- }
- ++pos;
- }
- }
-
- uint32_t total = state.members.size();
- if (total == 0) {
- QPID_LOG( trace, "group queue " << qName << ": deleting group id=" << gs->first);
- messageGroups.erase( gs );
- } else if (state.acquired == 0 && state.owned()) {
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << state.owner << " released group id=" << gs->first);
- disown(state);
- } else if (reFreeNeeded) {
- disown(state);
- }
- QPID_LOG( trace, "group queue " << qName <<
- ": dequeued message from group id=" << group << " total=" << total );
-}
-
-bool MessageGroupManager::nextConsumableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- if (messages.empty())
- return false;
-
- if (!freeGroups.empty()) {
- framing::SequenceNumber nextFree = freeGroups.begin()->first;
- if (nextFree < c->position) { // next free group's msg is older than current position
- bool ok = messages.find(nextFree, next);
- (void) ok; assert( ok );
- } else {
- if (!messages.next( c->position, next ))
- return false; // shouldn't happen - should find nextFree
- }
- } else { // no free groups available
- if (!messages.next( c->position, next ))
- return false;
- }
-
- do {
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- std::string group( getGroupId( next ) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
- if (!state.owned() || state.owner == c->getName()) {
- return true;
- }
- } while (messages.next( next.position, next ));
- return false;
-}
-
-
-bool MessageGroupManager::allocate(const std::string& consumer, const QueuedMessage& qm)
-{
- // @todo KAG avoid lookup: retrieve direct reference to group state from QueuedMessage
- std::string group( getGroupId(qm) );
- GroupMap::iterator gs = messageGroups.find( group );
- assert( gs != messageGroups.end() );
- GroupState& state( gs->second );
-
- if (!state.owned()) {
- own( state, consumer );
- QPID_LOG( trace, "group queue " << qName <<
- ": consumer name=" << consumer << " has acquired group id=" << gs->first);
- return true;
- }
- return state.owner == consumer;
-}
-
-bool MessageGroupManager::nextBrowsableMessage( Consumer::shared_ptr& c, QueuedMessage& next )
-{
- // browse: allow access to any available msg, regardless of group ownership (?ok?)
- if (!messages.empty() && messages.next(c->position, next))
- return true;
- return false;
-}
-
-void MessageGroupManager::query(qpid::types::Variant::Map& status) const
-{
- /** Add a description of the current state of the message groups for this queue.
- FORMAT:
- { "qpid.message_group_queue":
- { "group_header_key" : "<KEY>",
- "group_state" :
- [ { "group_id" : "<name>",
- "msg_count" : <int>,
- "timestamp" : <absTime>,
- "consumer" : <consumer name> },
- {...} // one for each known group
- ]
- }
- }
- **/
-
- assert(status.find(GROUP_QUERY_KEY) == status.end());
- qpid::types::Variant::Map state;
- qpid::types::Variant::List groups;
-
- state[GROUP_HEADER_KEY] = groupIdHeader;
- for (GroupMap::const_iterator g = messageGroups.begin();
- g != messageGroups.end(); ++g) {
- qpid::types::Variant::Map info;
- info[GROUP_ID_KEY] = g->first;
- info[GROUP_MSG_COUNT] = g->second.members.size();
- info[GROUP_TIMESTAMP] = 0; /** @todo KAG - NEED HEAD MSG TIMESTAMP */
- info[GROUP_CONSUMER] = g->second.owner;
- groups.push_back(info);
- }
- state[GROUP_STATE_KEY] = groups;
- status[GROUP_QUERY_KEY] = state;
-}
-
-
-boost::shared_ptr<MessageGroupManager> MessageGroupManager::create( const std::string& qName,
- Messages& messages,
- const qpid::framing::FieldTable& settings )
-{
- boost::shared_ptr<MessageGroupManager> empty;
-
- if (settings.isSet(qpidMessageGroupKey)) {
-
- // @todo: remove once "sticky" consumers are supported - see QPID-3347
- if (!settings.isSet(qpidSharedGroup)) {
- QPID_LOG( error, "Only shared groups are supported in this version of the broker. Use '--shared-groups' in qpid-config." );
- return empty;
- }
-
- std::string headerKey = settings.getAsString(qpidMessageGroupKey);
- if (headerKey.empty()) {
- QPID_LOG( error, "A Message Group header key must be configured, queue=" << qName);
- return empty;
- }
- unsigned int timestamp = settings.getAsInt(qpidMessageGroupTimestamp);
-
- boost::shared_ptr<MessageGroupManager> manager( new MessageGroupManager( headerKey, qName, messages, timestamp ) );
-
- QPID_LOG( debug, "Configured Queue '" << qName <<
- "' for message grouping using header key '" << headerKey << "'" <<
- " (timestamp=" << timestamp << ")");
- return manager;
- }
- return empty;
-}
-
-std::string MessageGroupManager::defaultGroupId;
-void MessageGroupManager::setDefaults(const std::string& groupId) // static
-{
- defaultGroupId = groupId;
-}
-
-/** Cluster replication:
-
- state map format:
-
- { "group-state": [ {"name": <group-name>,
- "owner": <consumer-name>-or-empty,
- "acquired-ct": <acquired count>,
- "positions": [Seqnumbers, ... ]},
- {...}
- ]
- }
-*/
-
-namespace {
- const std::string GROUP_NAME("name");
- const std::string GROUP_OWNER("owner");
- const std::string GROUP_ACQUIRED_CT("acquired-ct");
- const std::string GROUP_POSITIONS("positions");
- const std::string GROUP_STATE("group-state");
-}
-
-
-/** Runs on UPDATER to snapshot current state */
-void MessageGroupManager::getState(qpid::framing::FieldTable& state ) const
-{
- using namespace qpid::framing;
- state.clear();
- framing::Array groupState(TYPE_CODE_MAP);
- for (GroupMap::const_iterator g = messageGroups.begin();
- g != messageGroups.end(); ++g) {
-
- framing::FieldTable group;
- group.setString(GROUP_NAME, g->first);
- group.setString(GROUP_OWNER, g->second.owner);
- group.setInt(GROUP_ACQUIRED_CT, g->second.acquired);
- framing::Array positions(TYPE_CODE_UINT32);
- for (GroupState::PositionFifo::const_iterator p = g->second.members.begin();
- p != g->second.members.end(); ++p)
- positions.push_back(framing::Array::ValuePtr(new IntegerValue( *p )));
- group.setArray(GROUP_POSITIONS, positions);
- groupState.push_back(framing::Array::ValuePtr(new FieldTableValue(group)));
- }
- state.setArray(GROUP_STATE, groupState);
-
- QPID_LOG(debug, "Queue \"" << qName << "\": replicating message group state, key=" << groupIdHeader);
-}
-
-
-/** called on UPDATEE to set state from snapshot */
-void MessageGroupManager::setState(const qpid::framing::FieldTable& state)
-{
- using namespace qpid::framing;
- messageGroups.clear();
- //consumers.clear();
- freeGroups.clear();
-
- framing::Array groupState(TYPE_CODE_MAP);
-
- bool ok = state.getArray(GROUP_STATE, groupState);
- if (!ok) {
- QPID_LOG(error, "Unable to find message group state information for queue \"" <<
- qName << "\": cluster inconsistency error!");
- return;
- }
-
- for (framing::Array::const_iterator g = groupState.begin();
- g != groupState.end(); ++g) {
- framing::FieldTable group;
- ok = framing::getEncodedValue<FieldTable>(*g, group);
- if (!ok) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": table encoding error!");
- return;
- }
- MessageGroupManager::GroupState state;
- if (!group.isSet(GROUP_NAME) || !group.isSet(GROUP_OWNER) || !group.isSet(GROUP_ACQUIRED_CT)) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": fields missing error!");
- return;
- }
- state.group = group.getAsString(GROUP_NAME);
- state.owner = group.getAsString(GROUP_OWNER);
- state.acquired = group.getAsInt(GROUP_ACQUIRED_CT);
- framing::Array positions(TYPE_CODE_UINT32);
- ok = group.getArray(GROUP_POSITIONS, positions);
- if (!ok) {
- QPID_LOG(error, "Invalid message group state information for queue \"" <<
- qName << "\": position encoding error!");
- return;
- }
-
- for (Array::const_iterator p = positions.begin(); p != positions.end(); ++p)
- state.members.push_back((*p)->getIntegerValue<uint32_t, 4>());
- messageGroups[state.group] = state;
- if (!state.owned()) {
- assert(state.members.size());
- freeGroups[state.members.front()] = &messageGroups[state.group];
- }
- }
-
- QPID_LOG(debug, "Queue \"" << qName << "\": message group state replicated, key =" << groupIdHeader)
-}
diff --git a/cpp/src/qpid/broker/MessageGroupManager.h b/cpp/src/qpid/broker/MessageGroupManager.h
deleted file mode 100644
index 6c81ec14d1..0000000000
--- a/cpp/src/qpid/broker/MessageGroupManager.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef _broker_MessageGroupManager_h
-#define _broker_MessageGroupManager_h
-
-/*
- *
- * 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 managing message grouping on Queues */
-
-#include "qpid/broker/StatefulQueueObserver.h"
-#include "qpid/broker/MessageDistributor.h"
-
-
-namespace qpid {
-namespace broker {
-
-class QueueObserver;
-class MessageDistributor;
-
-class MessageGroupManager : public StatefulQueueObserver, public MessageDistributor
-{
- static std::string defaultGroupId; // assigned if no group id header present
-
- const std::string groupIdHeader; // msg header holding group identifier
- const unsigned int timestamp; // mark messages with timestamp if set
- Messages& messages; // parent Queue's in memory message container
- const std::string qName; // name of parent queue (for logs)
-
- struct GroupState {
- // note: update getState()/setState() when changing this object's state implementation
- typedef std::deque<framing::SequenceNumber> PositionFifo;
-
- std::string group; // group identifier
- std::string owner; // consumer with outstanding acquired messages
- uint32_t acquired; // count of outstanding acquired messages
- PositionFifo members; // msgs belonging to this group
-
- GroupState() : acquired(0) {}
- bool owned() const {return !owner.empty();}
- };
- typedef std::map<std::string, struct GroupState> GroupMap;
- typedef std::map<framing::SequenceNumber, struct GroupState *> GroupFifo;
-
- GroupMap messageGroups; // index: group name
- GroupFifo freeGroups; // ordered by oldest free msg
- //Consumers consumers; // index: consumer name
-
- static const std::string qpidMessageGroupKey;
- static const std::string qpidSharedGroup; // if specified, one group can be consumed by multiple receivers
- static const std::string qpidMessageGroupTimestamp;
-
- const std::string getGroupId( const QueuedMessage& qm ) const;
- void unFree( const GroupState& state );
- void own( GroupState& state, const std::string& owner );
- void disown( GroupState& state );
-
- public:
-
- static QPID_BROKER_EXTERN void setDefaults(const std::string& groupId);
- static boost::shared_ptr<MessageGroupManager> create( const std::string& qName,
- Messages& messages,
- const qpid::framing::FieldTable& settings );
-
- MessageGroupManager(const std::string& header, const std::string& _qName,
- Messages& container, unsigned int _timestamp=0 )
- : StatefulQueueObserver(std::string("MessageGroupManager:") + header),
- groupIdHeader( header ), timestamp(_timestamp), messages(container), qName(_qName) {}
-
- // QueueObserver iface
- void enqueued( const QueuedMessage& qm );
- void acquired( const QueuedMessage& qm );
- void requeued( const QueuedMessage& qm );
- void dequeued( const QueuedMessage& qm );
- void consumerAdded( const Consumer& ) {};
- void consumerRemoved( const Consumer& ) {};
- void getState(qpid::framing::FieldTable& state ) const;
- void setState(const qpid::framing::FieldTable&);
-
- // MessageDistributor iface
- bool nextConsumableMessage(Consumer::shared_ptr& c, QueuedMessage& next);
- bool allocate(const std::string& c, const QueuedMessage& qm);
- bool nextBrowsableMessage(Consumer::shared_ptr& c, QueuedMessage& next);
- void query(qpid::types::Variant::Map&) const;
-
- bool match(const qpid::types::Variant::Map*, const QueuedMessage&) const;
-};
-
-}}
-
-#endif
diff --git a/cpp/src/qpid/broker/Messages.h b/cpp/src/qpid/broker/Messages.h
index 448f17432a..0d75417640 100644
--- a/cpp/src/qpid/broker/Messages.h
+++ b/cpp/src/qpid/broker/Messages.h
@@ -32,8 +32,7 @@ struct QueuedMessage;
/**
* This interface abstracts out the access to the messages held for
- * delivery by a Queue instance. Note the the assumption at present is
- * that all locking is done in the Queue itself.
+ * delivery by a Queue instance.
*/
class Messages
{
@@ -76,6 +75,7 @@ class Messages
* @return true if there is another message, false otherwise.
*/
virtual bool next(const framing::SequenceNumber&, QueuedMessage&) = 0;
+
/**
* Note: Caller is responsible for ensuring that there is a front
* (e.g. empty() returns false)
diff --git a/cpp/src/qpid/broker/NullMessageStore.cpp b/cpp/src/qpid/broker/NullMessageStore.cpp
index 43f600eaf1..dc8615d58b 100644
--- a/cpp/src/qpid/broker/NullMessageStore.cpp
+++ b/cpp/src/qpid/broker/NullMessageStore.cpp
@@ -126,25 +126,21 @@ std::auto_ptr<TPCTransactionContext> NullMessageStore::begin(const std::string&
void NullMessageStore::prepare(TPCTransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.insert(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::commit(TransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.erase(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::abort(TransactionContext& ctxt)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
prepared.erase(DummyCtxt::getXid(ctxt));
}
void NullMessageStore::collectPreparedXids(std::set<std::string>& out)
{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock);
out.insert(prepared.begin(), prepared.end());
}
diff --git a/cpp/src/qpid/broker/NullMessageStore.h b/cpp/src/qpid/broker/NullMessageStore.h
index c6f402662e..e148ec4d51 100644
--- a/cpp/src/qpid/broker/NullMessageStore.h
+++ b/cpp/src/qpid/broker/NullMessageStore.h
@@ -25,7 +25,6 @@
#include "qpid/broker/BrokerImportExport.h"
#include "qpid/broker/MessageStore.h"
#include "qpid/broker/Queue.h"
-#include "qpid/sys/Mutex.h"
#include <boost/intrusive_ptr.hpp>
@@ -35,11 +34,10 @@ namespace broker {
/**
* A null implementation of the MessageStore interface
*/
-class QPID_BROKER_CLASS_EXTERN NullMessageStore : public MessageStore
+class NullMessageStore : public MessageStore
{
std::set<std::string> prepared;
uint64_t nextPersistenceId;
- qpid::sys::Mutex lock;
public:
QPID_BROKER_EXTERN NullMessageStore();
diff --git a/cpp/src/qpid/broker/PersistableMessage.cpp b/cpp/src/qpid/broker/PersistableMessage.cpp
index 7ba28eb293..e5fbb71cbd 100644
--- a/cpp/src/qpid/broker/PersistableMessage.cpp
+++ b/cpp/src/qpid/broker/PersistableMessage.cpp
@@ -34,6 +34,7 @@ class MessageStore;
PersistableMessage::~PersistableMessage() {}
PersistableMessage::PersistableMessage() :
+ asyncEnqueueCounter(0),
asyncDequeueCounter(0),
store(0)
{}
@@ -67,6 +68,24 @@ bool PersistableMessage::isContentReleased() const
return contentReleaseState.released;
}
+bool PersistableMessage::isEnqueueComplete() {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ return asyncEnqueueCounter == 0;
+}
+
+void PersistableMessage::enqueueComplete() {
+ bool notify = false;
+ {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ if (asyncEnqueueCounter > 0) {
+ if (--asyncEnqueueCounter == 0) {
+ notify = true;
+ }
+ }
+ }
+ if (notify)
+ allEnqueuesComplete();
+}
bool PersistableMessage::isStoredOnQueue(PersistableQueue::shared_ptr queue){
if (store && (queue->getPersistenceId()!=0)) {
@@ -90,7 +109,12 @@ void PersistableMessage::addToSyncList(PersistableQueue::shared_ptr queue, Messa
void PersistableMessage::enqueueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) {
addToSyncList(queue, _store);
- enqueueStart();
+ enqueueAsync();
+}
+
+void PersistableMessage::enqueueAsync() {
+ sys::ScopedLock<sys::Mutex> l(asyncEnqueueLock);
+ asyncEnqueueCounter++;
}
bool PersistableMessage::isDequeueComplete() {
diff --git a/cpp/src/qpid/broker/PersistableMessage.h b/cpp/src/qpid/broker/PersistableMessage.h
index d29c2c45b4..96fb922c1a 100644
--- a/cpp/src/qpid/broker/PersistableMessage.h
+++ b/cpp/src/qpid/broker/PersistableMessage.h
@@ -31,7 +31,6 @@
#include "qpid/framing/amqp_types.h"
#include "qpid/sys/Mutex.h"
#include "qpid/broker/PersistableQueue.h"
-#include "qpid/broker/AsyncCompletion.h"
namespace qpid {
namespace broker {
@@ -44,19 +43,18 @@ class MessageStore;
class PersistableMessage : public Persistable
{
typedef std::list< boost::weak_ptr<PersistableQueue> > syncList;
+ sys::Mutex asyncEnqueueLock;
sys::Mutex asyncDequeueLock;
sys::Mutex storeLock;
-
+
/**
- * "Ingress" messages == messages sent _to_ the broker.
- * Tracks the number of outstanding asynchronous operations that must
- * complete before an inbound message can be considered fully received by the
- * broker. E.g. all enqueues have completed, the message has been written
- * to store, credit has been replenished, etc. Once all outstanding
- * operations have completed, the transfer of this message from the client
- * may be considered complete.
+ * Tracks the number of outstanding asynchronous enqueue
+ * operations. When the message is enqueued asynchronously the
+ * count is incremented; when that enqueue completes it is
+ * decremented. Thus when it is 0, there are no outstanding
+ * enqueues.
*/
- AsyncCompletion ingressCompletion;
+ int asyncEnqueueCounter;
/**
* Tracks the number of outstanding asynchronous dequeue
@@ -67,6 +65,7 @@ class PersistableMessage : public Persistable
*/
int asyncDequeueCounter;
+ void enqueueAsync();
void dequeueAsync();
syncList synclist;
@@ -81,6 +80,8 @@ class PersistableMessage : public Persistable
ContentReleaseState contentReleaseState;
protected:
+ /** Called when all enqueues are complete for this message. */
+ virtual void allEnqueuesComplete() = 0;
/** Called when all dequeues are complete for this message. */
virtual void allDequeuesComplete() = 0;
@@ -114,12 +115,9 @@ class PersistableMessage : public Persistable
virtual QPID_BROKER_EXTERN bool isPersistent() const = 0;
- /** track the progress of a message received by the broker - see ingressCompletion above */
- QPID_BROKER_INLINE_EXTERN bool isIngressComplete() { return ingressCompletion.isDone(); }
- QPID_BROKER_INLINE_EXTERN AsyncCompletion& getIngressCompletion() { return ingressCompletion; }
+ QPID_BROKER_EXTERN bool isEnqueueComplete();
- QPID_BROKER_INLINE_EXTERN void enqueueStart() { ingressCompletion.startCompleter(); }
- QPID_BROKER_INLINE_EXTERN void enqueueComplete() { ingressCompletion.finishCompleter(); }
+ QPID_BROKER_EXTERN void enqueueComplete();
QPID_BROKER_EXTERN void enqueueAsync(PersistableQueue::shared_ptr queue,
MessageStore* _store);
@@ -135,6 +133,7 @@ class PersistableMessage : public Persistable
bool isStoredOnQueue(PersistableQueue::shared_ptr queue);
void addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store);
+
};
}}
diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp
index 4627b1409a..27c1cc4ad7 100644
--- a/cpp/src/qpid/broker/Queue.cpp
+++ b/cpp/src/qpid/broker/Queue.cpp
@@ -7,9 +7,9 @@
* 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
@@ -31,10 +31,7 @@
#include "qpid/broker/MessageStore.h"
#include "qpid/broker/NullMessageStore.h"
#include "qpid/broker/QueueRegistry.h"
-#include "qpid/broker/QueueFlowLimit.h"
#include "qpid/broker/ThresholdAlerts.h"
-#include "qpid/broker/FifoDistributor.h"
-#include "qpid/broker/MessageGroupManager.h"
#include "qpid/StringUtils.h"
#include "qpid/log/Statement.h"
@@ -44,7 +41,6 @@
#include "qpid/sys/ClusterSafe.h"
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Time.h"
-#include "qpid/types/Variant.h"
#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h"
#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h"
@@ -68,7 +64,7 @@ using std::mem_fun;
namespace _qmf = qmf::org::apache::qpid::broker;
-namespace
+namespace
{
const std::string qpidMaxSize("qpid.max_size");
const std::string qpidMaxCount("qpid.max_count");
@@ -90,16 +86,16 @@ const int ENQUEUE_ONLY=1;
const int ENQUEUE_AND_DEQUEUE=2;
}
-Queue::Queue(const string& _name, bool _autodelete,
+Queue::Queue(const string& _name, bool _autodelete,
MessageStore* const _store,
const OwnershipToken* const _owner,
Manageable* parent,
Broker* b) :
- name(_name),
+ name(_name),
autodelete(_autodelete),
store(_store),
- owner(_owner),
+ owner(_owner),
consumerCount(0),
exclusive(0),
noLocal(false),
@@ -114,8 +110,7 @@ Queue::Queue(const string& _name, bool _autodelete,
broker(b),
deleted(false),
barrier(*this),
- autoDeleteTimeout(0),
- allocator(new FifoDistributor( *messages ))
+ autoDeleteTimeout(0)
{
if (parent != 0 && broker != 0) {
ManagementAgent* agent = broker->getManagementAgent();
@@ -168,8 +163,13 @@ void Queue::deliver(boost::intrusive_ptr<Message> msg){
//drop message
QPID_LOG(info, "Dropping excluded message from " << getName());
} else {
- enqueue(0, msg);
- push(msg);
+ // if no store then mark as enqueued
+ if (!enqueue(0, msg)){
+ push(msg);
+ msg->enqueueComplete();
+ }else {
+ push(msg);
+ }
QPID_LOG(debug, "Message " << msg << " enqueued on " << name);
}
}
@@ -183,10 +183,11 @@ void Queue::recover(boost::intrusive_ptr<Message>& msg){
if (policy.get()) policy->recoverEnqueued(msg);
push(msg, true);
- if (store){
+ if (store){
// setup synclist for recovered messages, so they don't get re-stored on lastNodeFailure
- msg->addToSyncList(shared_from_this(), store);
+ msg->addToSyncList(shared_from_this(), store);
}
+ msg->enqueueComplete(); // mark the message as enqueued
if (store && (!msg->isContentLoaded() || msg->checkContentReleasable())) {
//content has not been loaded, need to ensure that lazy loading mode is set:
@@ -210,13 +211,14 @@ void Queue::process(boost::intrusive_ptr<Message>& msg){
void Queue::requeue(const QueuedMessage& msg){
assertClusterSafe();
QueueListeners::NotificationSet copy;
- {
+ {
Mutex::ScopedLock locker(messageLock);
if (!isEnqueued(msg)) return;
+ msg.payload->enqueueComplete(); // mark the message as enqueued
messages->reinsert(msg);
listeners.populate(copy);
- // for persistLastNode - don't force a message twice to disk, but force it if no force before
+ // for persistLastNode - don't force a message twice to disk, but force it if no force before
if(inLastNodeFailure && persistLastNode && !msg.payload->isStoredOnQueue(shared_from_this())) {
msg.payload->forcePersistent();
if (msg.payload->isForcedPersistent() ){
@@ -224,17 +226,16 @@ void Queue::requeue(const QueuedMessage& msg){
enqueue(0, payload);
}
}
- observeRequeue(msg, locker);
}
copy.notify();
}
-bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message)
+bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message)
{
Mutex::ScopedLock locker(messageLock);
assertClusterSafe();
QPID_LOG(debug, "Attempting to acquire message at " << position);
- if (acquire(position, message, locker)) {
+ if (messages->remove(position, message)) {
QPID_LOG(debug, "Acquired message at " << position << " from " << name);
return true;
} else {
@@ -243,24 +244,9 @@ bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& mess
}
}
-bool Queue::acquire(const QueuedMessage& msg, const std::string& consumer)
-{
- Mutex::ScopedLock locker(messageLock);
- assertClusterSafe();
- QPID_LOG(debug, consumer << " attempting to acquire message at " << msg.position);
-
- if (!allocator->allocate( consumer, msg )) {
- QPID_LOG(debug, "Not permitted to acquire msg at " << msg.position << " from '" << name);
- return false;
- }
-
- QueuedMessage copy(msg);
- if (acquire( msg.position, copy, locker)) {
- QPID_LOG(debug, "Acquired message at " << msg.position << " from " << name);
- return true;
- }
- QPID_LOG(debug, "Could not acquire message at " << msg.position << " from " << name << "; no message at that position");
- return false;
+bool Queue::acquire(const QueuedMessage& msg) {
+ QueuedMessage copy = msg;
+ return acquireMessageAt(msg.position, copy);
}
void Queue::notifyListener()
@@ -276,7 +262,7 @@ void Queue::notifyListener()
set.notify();
}
-bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
+bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
{
checkNotDeleted();
if (c->preAcquires()) {
@@ -288,71 +274,52 @@ bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
case NO_MESSAGES:
default:
return false;
- }
+ }
} else {
return browseNextMessage(m, c);
}
}
-Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
+Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
{
while (true) {
Mutex::ScopedLock locker(messageLock);
- QueuedMessage msg;
-
- if (!allocator->nextConsumableMessage(c, msg)) { // no next available
- QPID_LOG(debug, "No messages available to dispatch to consumer " <<
- c->getName() << " on queue '" << name << "'");
+ if (messages->empty()) {
+ QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'");
listeners.addListener(c);
return NO_MESSAGES;
- }
-
- if (msg.payload->hasExpired()) {
- QPID_LOG(debug, "Message expired from queue '" << name << "'");
- c->position = msg.position;
- acquire( msg.position, msg, locker);
- dequeue( 0, msg );
- continue;
- }
-
- // a message is available for this consumer - can the consumer use it?
+ } else {
+ QueuedMessage msg = messages->front();
+ if (msg.payload->hasExpired()) {
+ QPID_LOG(debug, "Message expired from queue '" << name << "'");
+ popAndDequeue();
+ continue;
+ }
- if (c->filter(msg.payload)) {
- if (c->accept(msg.payload)) {
- bool ok = allocator->allocate( c->getName(), msg ); // inform allocator
- (void) ok; assert(ok);
- ok = acquire( msg.position, msg, locker);
- (void) ok; assert(ok);
- m = msg;
- c->position = m.position;
- return CONSUMED;
+ if (c->filter(msg.payload)) {
+ if (c->accept(msg.payload)) {
+ m = msg;
+ pop();
+ return CONSUMED;
+ } else {
+ //message(s) are available but consumer hasn't got enough credit
+ QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'");
+ return CANT_CONSUME;
+ }
} else {
- //message(s) are available but consumer hasn't got enough credit
- QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'");
+ //consumer will never want this message
+ QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'");
return CANT_CONSUME;
- }
- } else {
- //consumer will never want this message
- QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'");
- c->position = msg.position;
- return CANT_CONSUME;
+ }
}
}
}
-bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
-{
- while (true) {
- Mutex::ScopedLock locker(messageLock);
- QueuedMessage msg;
-
- if (!allocator->nextBrowsableMessage(c, msg)) { // no next available
- QPID_LOG(debug, "No browsable messages available for consumer " <<
- c->getName() << " on queue '" << name << "'");
- listeners.addListener(c);
- return false;
- }
+bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr c)
+{
+ QueuedMessage msg(this);
+ while (seek(msg, c)) {
if (c->filter(msg.payload) && !msg.payload->hasExpired()) {
if (c->accept(msg.payload)) {
//consumer wants the message
@@ -366,8 +333,8 @@ bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr& c)
}
} else {
//consumer will never want this message, continue seeking
- QPID_LOG(debug, "Browser skipping message from '" << name << "'");
c->position = msg.position;
+ QPID_LOG(debug, "Browser skipping message from '" << name << "'");
}
}
return false;
@@ -397,71 +364,61 @@ bool Queue::dispatch(Consumer::shared_ptr c)
}
}
-bool Queue::find(SequenceNumber pos, QueuedMessage& msg) const {
-
+// Find the next message
+bool Queue::seek(QueuedMessage& msg, Consumer::shared_ptr c) {
Mutex::ScopedLock locker(messageLock);
- if (messages->find(pos, msg))
+ if (messages->next(c->position, msg)) {
return true;
- return false;
+ } else {
+ listeners.addListener(c);
+ return false;
+ }
+}
+
+QueuedMessage Queue::find(SequenceNumber pos) const {
+
+ Mutex::ScopedLock locker(messageLock);
+ QueuedMessage msg;
+ messages->find(pos, msg);
+ return msg;
}
void Queue::consume(Consumer::shared_ptr c, bool requestExclusive){
assertClusterSafe();
- {
- Mutex::ScopedLock locker(consumerLock);
- if(exclusive) {
+ Mutex::ScopedLock locker(consumerLock);
+ if(exclusive) {
+ throw ResourceLockedException(
+ QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed."));
+ } else if(requestExclusive) {
+ if(consumerCount) {
throw ResourceLockedException(
- QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed."));
- } else if(requestExclusive) {
- if(consumerCount) {
- throw ResourceLockedException(
- QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied."));
- } else {
- exclusive = c->getSession();
- }
- }
- consumerCount++;
- if (mgmtObject != 0)
- mgmtObject->inc_consumerCount ();
- //reset auto deletion timer if necessary
- if (autoDeleteTimeout && autoDeleteTask) {
- autoDeleteTask->cancel();
+ QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied."));
+ } else {
+ exclusive = c->getSession();
}
}
- Mutex::ScopedLock locker(messageLock);
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->consumerAdded(*c);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of new consumer for queue " << getName() << ": " << e.what());
- }
+ consumerCount++;
+ if (mgmtObject != 0)
+ mgmtObject->inc_consumerCount ();
+ //reset auto deletion timer if necessary
+ if (autoDeleteTimeout && autoDeleteTask) {
+ autoDeleteTask->cancel();
}
}
void Queue::cancel(Consumer::shared_ptr c){
removeListener(c);
- {
- Mutex::ScopedLock locker(consumerLock);
- consumerCount--;
- if(exclusive) exclusive = 0;
- if (mgmtObject != 0)
- mgmtObject->dec_consumerCount ();
- }
- Mutex::ScopedLock locker(messageLock);
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->consumerRemoved(*c);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of removed consumer for queue " << getName() << ": " << e.what());
- }
- }
+ Mutex::ScopedLock locker(consumerLock);
+ consumerCount--;
+ if(exclusive) exclusive = 0;
+ if (mgmtObject != 0)
+ mgmtObject->dec_consumerCount ();
}
QueuedMessage Queue::get(){
Mutex::ScopedLock locker(messageLock);
QueuedMessage msg(this);
- if (messages->pop(msg))
- observeAcquire(msg, locker);
+ messages->pop(msg);
return msg;
}
@@ -475,135 +432,22 @@ bool collect_if_expired(std::deque<QueuedMessage>& expired, QueuedMessage& messa
}
}
-/**
- *@param lapse: time since the last purgeExpired
- */
-void Queue::purgeExpired(qpid::sys::Duration lapse)
+void Queue::purgeExpired()
{
//As expired messages are discarded during dequeue also, only
//bother explicitly expiring if the rate of dequeues since last
- //attempt is less than one per second.
- int count = dequeueSincePurge.get();
- dequeueSincePurge -= count;
- int seconds = int64_t(lapse)/qpid::sys::TIME_SEC;
- if (seconds == 0 || count / seconds < 1) {
+ //attempt is less than one per second.
+
+ if (dequeueTracker.sampleRatePerSecond() < 1) {
std::deque<QueuedMessage> expired;
{
Mutex::ScopedLock locker(messageLock);
- messages->removeIf(boost::bind(&collect_if_expired, boost::ref(expired), _1));
- }
-
- for (std::deque<QueuedMessage>::const_iterator i = expired.begin();
- i != expired.end(); ++i) {
- {
- Mutex::ScopedLock locker(messageLock);
- observeAcquire(*i, locker);
- }
- dequeue( 0, *i );
+ messages->removeIf(boost::bind(&collect_if_expired, expired, _1));
}
+ for_each(expired.begin(), expired.end(), bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
}
}
-
-namespace {
- // for use with purge/move below - collect messages that match a given filter
- //
- class MessageFilter
- {
- public:
- static const std::string typeKey;
- static const std::string paramsKey;
- static MessageFilter *create( const ::qpid::types::Variant::Map *filter );
- virtual bool match( const QueuedMessage& ) const { return true; }
- virtual ~MessageFilter() {}
- protected:
- MessageFilter() {};
- };
- const std::string MessageFilter::typeKey("filter_type");
- const std::string MessageFilter::paramsKey("filter_params");
-
- // filter by message header string value exact match
- class HeaderMatchFilter : public MessageFilter
- {
- public:
- /* Config:
- { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "<header name>",
- 'header_value' : "<value to match>"
- }
- }
- */
- static const std::string typeKey;
- static const std::string headerKey;
- static const std::string valueKey;
- HeaderMatchFilter( const std::string& _header, const std::string& _value )
- : MessageFilter (), header(_header), value(_value) {}
- bool match( const QueuedMessage& msg ) const
- {
- const qpid::framing::FieldTable* headers = msg.payload->getApplicationHeaders();
- if (!headers) return false;
- FieldTable::ValuePtr h = headers->get(header);
- if (!h || !h->convertsTo<std::string>()) return false;
- return h->get<std::string>() == value;
- }
- private:
- const std::string header;
- const std::string value;
- };
- const std::string HeaderMatchFilter::typeKey("header_match_str");
- const std::string HeaderMatchFilter::headerKey("header_key");
- const std::string HeaderMatchFilter::valueKey("header_value");
-
- // factory to create correct filter based on map
- MessageFilter* MessageFilter::create( const ::qpid::types::Variant::Map *filter )
- {
- using namespace qpid::types;
- if (filter && !filter->empty()) {
- Variant::Map::const_iterator i = filter->find(MessageFilter::typeKey);
- if (i != filter->end()) {
-
- if (i->second.asString() == HeaderMatchFilter::typeKey) {
- Variant::Map::const_iterator p = filter->find(MessageFilter::paramsKey);
- if (p != filter->end() && p->second.getType() == VAR_MAP) {
- Variant::Map::const_iterator k = p->second.asMap().find(HeaderMatchFilter::headerKey);
- Variant::Map::const_iterator v = p->second.asMap().find(HeaderMatchFilter::valueKey);
- if (k != p->second.asMap().end() && v != p->second.asMap().end()) {
- std::string headerKey(k->second.asString());
- std::string value(v->second.asString());
- QPID_LOG(debug, "Message filtering by header value configured. key: " << headerKey << " value: " << value );
- return new HeaderMatchFilter( headerKey, value );
- }
- }
- }
- }
- QPID_LOG(error, "Ignoring unrecognized message filter: '" << *filter << "'");
- }
- return new MessageFilter();
- }
-
- // used by removeIf() to collect all messages matching a filter, maximum match count is
- // optional.
- struct Collector {
- const uint32_t maxMatches;
- MessageFilter& filter;
- std::deque<QueuedMessage> matches;
- Collector(MessageFilter& filter, uint32_t max)
- : maxMatches(max), filter(filter) {}
- bool operator() (QueuedMessage& qm)
- {
- if (maxMatches == 0 || matches.size() < maxMatches) {
- if (filter.match( qm )) {
- matches.push_back(qm);
- return true;
- }
- }
- return false;
- }
- };
-
-} // end namespace
-
-
/**
* purge - for purging all or some messages on a queue
* depending on the purge_request
@@ -615,77 +459,63 @@ namespace {
* The dest exchange may be supplied to re-route messages through the exchange.
* It is safe to re-route messages such that they arrive back on the same queue,
* even if the queue is ordered by priority.
- *
- * An optional filter can be supplied that will be applied against each message. The
- * message is purged only if the filter matches. See MessageDistributor for more detail.
*/
-uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest,
- const qpid::types::Variant::Map *filter)
+uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest)
{
- std::auto_ptr<MessageFilter> mf(MessageFilter::create(filter));
- Collector c(*mf.get(), purge_request);
-
Mutex::ScopedLock locker(messageLock);
- messages->removeIf( boost::bind<bool>(boost::ref(c), _1) );
- for (std::deque<QueuedMessage>::iterator qmsg = c.matches.begin();
- qmsg != c.matches.end(); ++qmsg) {
- // Update observers and message state:
- observeAcquire(*qmsg, locker);
- dequeue(0, *qmsg);
- // now reroute if necessary
+ uint32_t purge_count = purge_request; // only comes into play if >0
+ std::deque<DeliverableMessage> rerouteQueue;
+
+ uint32_t count = 0;
+ // Either purge them all or just the some (purge_count) while the queue isn't empty.
+ while((!purge_request || purge_count--) && !messages->empty()) {
if (dest.get()) {
- assert(qmsg->payload);
- DeliverableMessage dmsg(qmsg->payload);
- dest->routeWithAlternate(dmsg);
+ //
+ // If there is a destination exchange, stage the messages onto a reroute queue
+ // so they don't wind up getting purged more than once.
+ //
+ DeliverableMessage msg(messages->front().payload);
+ rerouteQueue.push_back(msg);
}
+ popAndDequeue();
+ count++;
}
- return c.matches.size();
-}
-
-uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty,
- const qpid::types::Variant::Map *filter)
-{
- std::auto_ptr<MessageFilter> mf(MessageFilter::create(filter));
- Collector c(*mf.get(), qty);
- Mutex::ScopedLock locker(messageLock);
- messages->removeIf( boost::bind<bool>(boost::ref(c), _1) );
-
- for (std::deque<QueuedMessage>::iterator qmsg = c.matches.begin();
- qmsg != c.matches.end(); ++qmsg) {
- // Update observers and message state:
- observeAcquire(*qmsg, locker);
- dequeue(0, *qmsg);
- // and move to destination Queue.
- assert(qmsg->payload);
- destq->deliver(qmsg->payload);
+ //
+ // Re-route purged messages into the destination exchange. Note that there's no need
+ // to test dest.get() here because if it is NULL, the rerouteQueue will be empty.
+ //
+ while (!rerouteQueue.empty()) {
+ DeliverableMessage msg(rerouteQueue.front());
+ rerouteQueue.pop_front();
+ dest->route(msg, msg.getMessage().getRoutingKey(),
+ msg.getMessage().getApplicationHeaders());
}
- return c.matches.size();
+
+ return count;
}
-/** Acquire the front (oldest) message from the in-memory queue.
- * assumes messageLock held by caller
- */
-void Queue::pop(const Mutex::ScopedLock& locker)
-{
- assertClusterSafe();
- QueuedMessage msg;
- if (messages->pop(msg)) {
- observeAcquire(msg, locker);
- ++dequeueSincePurge;
+uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty) {
+ Mutex::ScopedLock locker(messageLock);
+ uint32_t move_count = qty; // only comes into play if qty >0
+ uint32_t count = 0; // count how many were moved for returning
+
+ while((!qty || move_count--) && !messages->empty()) {
+ QueuedMessage qmsg = messages->front();
+ boost::intrusive_ptr<Message> msg = qmsg.payload;
+ destq->deliver(msg); // deliver message to the destination queue
+ pop();
+ dequeue(0, qmsg);
+ count++;
}
+ return count;
}
-/** Acquire the message at the given position, return true and msg if acquire succeeds */
-bool Queue::acquire(const qpid::framing::SequenceNumber& position, QueuedMessage& msg,
- const Mutex::ScopedLock& locker)
+void Queue::pop()
{
- if (messages->remove(position, msg)) {
- observeAcquire(msg, locker);
- ++dequeueSincePurge;
- return true;
- }
- return false;
+ assertClusterSafe();
+ messages->pop();
+ ++dequeueTracker;
}
void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
@@ -694,15 +524,13 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
QueuedMessage removed;
bool dequeueRequired = false;
{
- Mutex::ScopedLock locker(messageLock);
+ Mutex::ScopedLock locker(messageLock);
QueuedMessage qm(this, msg, ++sequence);
- if (insertSeqNo) msg->insertCustomProperty(seqNoKey, sequence);
-
+ if (insertSeqNo) msg->getOrInsertHeaders().setInt64(seqNoKey, sequence);
+
dequeueRequired = messages->push(qm, removed);
- if (dequeueRequired)
- observeAcquire(removed, locker);
listeners.populate(copy);
- observeEnqueue(qm, locker);
+ enqueued(qm);
}
copy.notify();
if (dequeueRequired) {
@@ -718,7 +546,7 @@ void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){
void isEnqueueComplete(uint32_t* result, const QueuedMessage& message)
{
- if (message.payload->isIngressComplete()) (*result)++;
+ if (message.payload->isEnqueueComplete()) (*result)++;
}
/** function only provided for unit tests, or code not in critical message path */
@@ -778,7 +606,7 @@ void Queue::setLastNodeFailure()
}
-// return true if store exists,
+// return true if store exists,
bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck)
{
ScopedUse u(barrier);
@@ -792,21 +620,24 @@ bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg
policy->getPendingDequeues(dequeues);
}
//depending on policy, may have some dequeues that need to performed without holding the lock
- for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
+ for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1));
}
if (inLastNodeFailure && persistLastNode){
msg->forcePersistent();
}
-
+
if (traceId.size()) {
+ //copy on write: take deep copy of message before modifying it
+ //as the frames may already be available for delivery on other
+ //threads
+ boost::intrusive_ptr<Message> copy(new Message(*msg));
+ msg = copy;
msg->addTraceId(traceId);
}
if ((msg->isPersistent() || msg->checkContentReleasable()) && store) {
- // mark the message as being enqueued - the store MUST CALL msg->enqueueComplete()
- // when it considers the message stored.
- msg->enqueueAsync(shared_from_this(), store);
+ msg->enqueueAsync(shared_from_this(), store); //increment to async counter -- for message sent to more than one queue
boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg);
store->enqueue(ctxt, pmsg, *this);
return true;
@@ -823,10 +654,10 @@ bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg
void Queue::enqueueAborted(boost::intrusive_ptr<Message> msg)
{
Mutex::ScopedLock locker(messageLock);
- if (policy.get()) policy->enqueueAborted(msg);
+ if (policy.get()) policy->enqueueAborted(msg);
}
-// return true if store exists,
+// return true if store exists,
bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
{
ScopedUse u(barrier);
@@ -835,8 +666,8 @@ bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
{
Mutex::ScopedLock locker(messageLock);
if (!isEnqueued(msg)) return false;
- if (!ctxt) {
- observeDequeue(msg, locker);
+ if (!ctxt) {
+ dequeued(msg);
}
}
// This check prevents messages which have been forced persistent on one queue from dequeuing
@@ -856,7 +687,7 @@ bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg)
void Queue::dequeueCommitted(const QueuedMessage& msg)
{
Mutex::ScopedLock locker(messageLock);
- observeDequeue(msg, locker);
+ dequeued(msg);
if (mgmtObject != 0) {
mgmtObject->inc_msgTxnDequeues();
mgmtObject->inc_byteTxnDequeues(msg.payload->contentSize());
@@ -864,23 +695,21 @@ void Queue::dequeueCommitted(const QueuedMessage& msg)
}
/**
- * Removes the first (oldest) message from the in-memory delivery queue as well dequeing
- * it from the logical (and persistent if applicable) queue
+ * Removes a message from the in-memory delivery queue as well
+ * dequeing it from the logical (and persistent if applicable) queue
*/
-void Queue::popAndDequeue(const Mutex::ScopedLock& held)
+void Queue::popAndDequeue()
{
- if (!messages->empty()) {
- QueuedMessage msg = messages->front();
- pop(held);
- dequeue(0, msg);
- }
+ QueuedMessage msg = messages->front();
+ pop();
+ dequeue(0, msg);
}
/**
* Updates policy and management when a message has been dequeued,
* expects messageLock to be held
*/
-void Queue::observeDequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
+void Queue::dequeued(const QueuedMessage& msg)
{
if (policy.get()) policy->dequeued(msg);
mgntDeqStats(msg.payload);
@@ -893,33 +722,6 @@ void Queue::observeDequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
}
}
-/** updates queue observers when a message has become unavailable for transfer,
- * expects messageLock to be held
- */
-void Queue::observeAcquire(const QueuedMessage& msg, const Mutex::ScopedLock&)
-{
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->acquired(msg);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of message removal for queue " << getName() << ": " << e.what());
- }
- }
-}
-
-/** updates queue observers when a message has become re-available for transfer,
- * expects messageLock to be held
- */
-void Queue::observeRequeue(const QueuedMessage& msg, const Mutex::ScopedLock&)
-{
- for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) {
- try{
- (*i)->requeued(msg);
- } catch (const std::exception& e) {
- QPID_LOG(warning, "Exception on notification of message requeue for queue " << getName() << ": " << e.what());
- }
- }
-}
void Queue::create(const FieldTable& _settings)
{
@@ -927,7 +729,7 @@ void Queue::create(const FieldTable& _settings)
if (store) {
store->create(*this, _settings);
}
- configureImpl(_settings);
+ configure(_settings);
}
@@ -940,8 +742,8 @@ int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::stri
return v->get<int>();
} else if (v->convertsTo<std::string>()){
std::string s = v->get<std::string>();
- try {
- return boost::lexical_cast<int>(s);
+ try {
+ return boost::lexical_cast<int>(s);
} catch(const boost::bad_lexical_cast&) {
QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s);
return 0;
@@ -952,45 +754,15 @@ int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::stri
}
}
-bool getBoolSetting(const qpid::framing::FieldTable& settings, const std::string& key)
+void Queue::configure(const FieldTable& _settings, bool recovering)
{
- qpid::framing::FieldTable::ValuePtr v = settings.get(key);
- if (!v) {
- return false;
- } else if (v->convertsTo<int>()) {
- return v->get<int>() != 0;
- } else if (v->convertsTo<std::string>()){
- std::string s = v->get<std::string>();
- if (s == "True") return true;
- if (s == "true") return true;
- if (s == "False") return false;
- if (s == "false") return false;
- try {
- return boost::lexical_cast<bool>(s);
- } catch(const boost::bad_lexical_cast&) {
- QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << s);
- return false;
- }
- } else {
- QPID_LOG(warning, "Ignoring invalid boolean value for " << key << ": " << *v);
- return false;
- }
-}
-
-void Queue::configure(const FieldTable& _settings)
-{
- settings = _settings;
- configureImpl(settings);
-}
-void Queue::configureImpl(const FieldTable& _settings)
-{
eventMode = _settings.getAsInt(qpidQueueEventGeneration);
if (eventMode && broker) {
broker->getQueueEvents().observe(*this, eventMode == ENQUEUE_ONLY);
}
- if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK &&
+ if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK &&
(!store || NullMessageStore::isNullStore(store) || (broker && !(broker->getQueueEvents().isSync())) )) {
if ( NullMessageStore::isNullStore(store)) {
QPID_LOG(warning, "Flow to disk not valid for non-persisted queue:" << getName());
@@ -1004,43 +776,32 @@ void Queue::configureImpl(const FieldTable& _settings)
setPolicy(QueuePolicy::createQueuePolicy(getName(), _settings));
}
if (broker && broker->getManagementAgent()) {
- ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings, broker->getOptions().queueThresholdEventRatio);
+ ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings);
}
//set this regardless of owner to allow use of no-local with exclusive consumers also
- noLocal = getBoolSetting(_settings, qpidNoLocal);
+ noLocal = _settings.get(qpidNoLocal);
QPID_LOG(debug, "Configured queue " << getName() << " with no-local=" << noLocal);
std::string lvqKey = _settings.getAsString(qpidLastValueQueueKey);
if (lvqKey.size()) {
QPID_LOG(debug, "Configured queue " << getName() << " as Last Value Queue with key " << lvqKey);
messages = std::auto_ptr<Messages>(new MessageMap(lvqKey));
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
- } else if (getBoolSetting(_settings, qpidLastValueQueueNoBrowse)) {
+ } else if (_settings.get(qpidLastValueQueueNoBrowse)) {
QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue with 'no-browse' on");
messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, true, broker);
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
- } else if (getBoolSetting(_settings, qpidLastValueQueue)) {
+ } else if (_settings.get(qpidLastValueQueue)) {
QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue");
messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, false, broker);
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
} else {
std::auto_ptr<Messages> m = Fairshare::create(_settings);
if (m.get()) {
messages = m;
- allocator = boost::shared_ptr<MessageDistributor>(new FifoDistributor( *messages ));
QPID_LOG(debug, "Configured queue " << getName() << " as priority queue.");
- } else { // default (FIFO) queue type
- // override default message allocator if message groups configured.
- boost::shared_ptr<MessageGroupManager> mgm(MessageGroupManager::create( getName(), *messages, _settings));
- if (mgm) {
- allocator = mgm;
- addObserver(mgm);
- }
}
}
-
- persistLastNode = getBoolSetting(_settings, qpidPersistLastNode);
+
+ persistLastNode= _settings.get(qpidPersistLastNode);
if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node for: " << getName());
traceId = _settings.getAsString(qpidTraceIdentity);
@@ -1048,32 +809,32 @@ void Queue::configureImpl(const FieldTable& _settings)
if (excludeList.size()) {
split(traceExclude, excludeList, ", ");
}
- QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId
+ QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId
<< "' and qpid.trace.exclude='"<< excludeList << "' i.e. " << traceExclude.size() << " elements");
FieldTable::ValuePtr p =_settings.get(qpidInsertSequenceNumbers);
if (p && p->convertsTo<std::string>()) insertSequenceNumbers(p->get<std::string>());
autoDeleteTimeout = getIntegerSetting(_settings, qpidAutoDeleteTimeout);
- if (autoDeleteTimeout)
- QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout);
+ if (autoDeleteTimeout)
+ QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout);
- if (mgmtObject != 0) {
+ if (mgmtObject != 0)
mgmtObject->set_arguments(ManagementAgent::toMap(_settings));
- }
- QueueFlowLimit::observe(*this, _settings);
+ if ( isDurable() && ! getPersistenceId() && ! recovering )
+ store->create(*this, _settings);
}
-void Queue::destroyed()
+void Queue::destroy()
{
- unbind(broker->getExchanges());
if (alternateExchange.get()) {
Mutex::ScopedLock locker(messageLock);
while(!messages->empty()){
DeliverableMessage msg(messages->front().payload);
- alternateExchange->routeWithAlternate(msg);
- popAndDequeue(locker);
+ alternateExchange->route(msg, msg.getMessage().getRoutingKey(),
+ msg.getMessage().getApplicationHeaders());
+ popAndDequeue();
}
alternateExchange->decAlternateUsers();
}
@@ -1085,7 +846,6 @@ void Queue::destroyed()
store = 0;//ensure we make no more calls to the store for this queue
}
if (autoDeleteTask) autoDeleteTask = boost::intrusive_ptr<TimerTask>();
- notifyDeleted();
}
void Queue::notifyDeleted()
@@ -1105,9 +865,9 @@ void Queue::bound(const string& exchange, const string& key,
bindings.add(exchange, key, args);
}
-void Queue::unbind(ExchangeRegistry& exchanges)
+void Queue::unbind(ExchangeRegistry& exchanges, Queue::shared_ptr shared_ref)
{
- bindings.unbind(exchanges, shared_from_this());
+ bindings.unbind(exchanges, shared_ref);
}
void Queue::setPolicy(std::auto_ptr<QueuePolicy> _policy)
@@ -1120,9 +880,9 @@ const QueuePolicy* Queue::getPolicy()
return policy.get();
}
-uint64_t Queue::getPersistenceId() const
-{
- return persistenceId;
+uint64_t Queue::getPersistenceId() const
+{
+ return persistenceId;
}
void Queue::setPersistenceId(uint64_t _persistenceId) const
@@ -1136,11 +896,11 @@ void Queue::setPersistenceId(uint64_t _persistenceId) const
persistenceId = _persistenceId;
}
-void Queue::encode(Buffer& buffer) const
+void Queue::encode(Buffer& buffer) const
{
buffer.putShortString(name);
buffer.put(settings);
- if (policy.get()) {
+ if (policy.get()) {
buffer.put(*policy);
}
buffer.putShortString(alternateExchange.get() ? alternateExchange->getName() : std::string(""));
@@ -1154,14 +914,13 @@ uint32_t Queue::encodedSize() const
+ (policy.get() ? (*policy).encodedSize() : 0);
}
-Queue::shared_ptr Queue::restore( QueueRegistry& queues, Buffer& buffer )
+Queue::shared_ptr Queue::decode ( QueueRegistry& queues, Buffer& buffer, bool recovering )
{
string name;
buffer.getShortString(name);
- FieldTable settings;
- buffer.get(settings);
- boost::shared_ptr<Exchange> alternate;
- std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true, false, 0, alternate, settings, true);
+ std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true);
+ buffer.get(result.first->settings);
+ result.first->configure(result.first->settings, recovering );
if (result.first->policy.get() && buffer.available() >= result.first->policy->encodedSize()) {
buffer.get ( *(result.first->policy) );
}
@@ -1193,10 +952,11 @@ boost::shared_ptr<Exchange> Queue::getAlternateExchange()
void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue)
{
- if (broker.getQueues().destroyIf(queue->getName(),
+ if (broker.getQueues().destroyIf(queue->getName(),
boost::bind(boost::mem_fn(&Queue::canAutoDelete), queue))) {
QPID_LOG(debug, "Auto-deleting " << queue->getName());
- queue->destroyed();
+ queue->unbind(broker.getExchanges(), queue);
+ queue->destroy();
}
}
@@ -1205,7 +965,7 @@ struct AutoDeleteTask : qpid::sys::TimerTask
Broker& broker;
Queue::shared_ptr queue;
- AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime)
+ AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime)
: qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion"), broker(b), queue(q) {}
void fire()
@@ -1223,27 +983,27 @@ void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue)
if (queue->autoDeleteTimeout && queue->canAutoDelete()) {
AbsTime time(now(), Duration(queue->autoDeleteTimeout * TIME_SEC));
queue->autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(broker, queue, time));
- broker.getClusterTimer().add(queue->autoDeleteTask);
+ broker.getClusterTimer().add(queue->autoDeleteTask);
QPID_LOG(debug, "Timed auto-delete for " << queue->getName() << " initiated");
} else {
tryAutoDeleteImpl(broker, queue);
}
}
-bool Queue::isExclusiveOwner(const OwnershipToken* const o) const
-{
+bool Queue::isExclusiveOwner(const OwnershipToken* const o) const
+{
Mutex::ScopedLock locker(ownershipLock);
- return o == owner;
+ return o == owner;
}
-void Queue::releaseExclusiveOwnership()
-{
+void Queue::releaseExclusiveOwnership()
+{
Mutex::ScopedLock locker(ownershipLock);
- owner = 0;
+ owner = 0;
}
-bool Queue::setExclusiveOwner(const OwnershipToken* const o)
-{
+bool Queue::setExclusiveOwner(const OwnershipToken* const o)
+{
//reset auto deletion timer if necessary
if (autoDeleteTimeout && autoDeleteTask) {
autoDeleteTask->cancel();
@@ -1252,25 +1012,25 @@ bool Queue::setExclusiveOwner(const OwnershipToken* const o)
if (owner) {
return false;
} else {
- owner = o;
+ owner = o;
return true;
}
}
-bool Queue::hasExclusiveOwner() const
-{
+bool Queue::hasExclusiveOwner() const
+{
Mutex::ScopedLock locker(ownershipLock);
- return owner != 0;
+ return owner != 0;
}
-bool Queue::hasExclusiveConsumer() const
-{
- return exclusive;
+bool Queue::hasExclusiveConsumer() const
+{
+ return exclusive;
}
void Queue::setExternalQueueStore(ExternalQueueStore* inst) {
- if (externalQueueStore!=inst && externalQueueStore)
- delete externalQueueStore;
+ if (externalQueueStore!=inst && externalQueueStore)
+ delete externalQueueStore;
externalQueueStore = inst;
if (inst) {
@@ -1295,7 +1055,7 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
case _qmf::Queue::METHOD_PURGE :
{
_qmf::ArgsQueuePurge& purgeArgs = (_qmf::ArgsQueuePurge&) args;
- purge(purgeArgs.i_request, boost::shared_ptr<Exchange>(), &purgeArgs.i_filter);
+ purge(purgeArgs.i_request);
status = Manageable::STATUS_OK;
}
break;
@@ -1316,7 +1076,7 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
}
}
- purge(rerouteArgs.i_request, dest, &rerouteArgs.i_filter);
+ purge(rerouteArgs.i_request, dest);
status = Manageable::STATUS_OK;
}
break;
@@ -1325,14 +1085,6 @@ Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, str
return status;
}
-
-void Queue::query(qpid::types::Variant::Map& results) const
-{
- Mutex::ScopedLock locker(messageLock);
- /** @todo add any interesting queue state into results */
- if (allocator) allocator->query(results);
-}
-
void Queue::setPosition(SequenceNumber n) {
Mutex::ScopedLock locker(messageLock);
sequence = n;
@@ -1367,10 +1119,7 @@ void Queue::insertSequenceNumbers(const std::string& key)
QPID_LOG(debug, "Inserting sequence numbers as " << key);
}
-/** updates queue observers and state when a message has become available for transfer,
- * expects messageLock to be held
- */
-void Queue::observeEnqueue(const QueuedMessage& m, const Mutex::ScopedLock&)
+void Queue::enqueued(const QueuedMessage& m)
{
for (Observers::iterator i = observers.begin(); i != observers.end(); ++i) {
try {
@@ -1393,8 +1142,7 @@ void Queue::updateEnqueued(const QueuedMessage& m)
if (policy.get()) {
policy->recoverEnqueued(payload);
}
- Mutex::ScopedLock locker(messageLock);
- observeEnqueue(m, locker);
+ enqueued(m);
} else {
QPID_LOG(warning, "Queue informed of enqueued message that has no payload");
}
@@ -1418,7 +1166,6 @@ void Queue::checkNotDeleted()
void Queue::addObserver(boost::shared_ptr<QueueObserver> observer)
{
- Mutex::ScopedLock locker(messageLock);
observers.insert(observer);
}
@@ -1428,32 +1175,6 @@ void Queue::flush()
if (u.acquired && store) store->flush(*this);
}
-
-bool Queue::bind(boost::shared_ptr<Exchange> exchange, const std::string& key,
- const qpid::framing::FieldTable& arguments)
-{
- if (exchange->bind(shared_from_this(), key, &arguments)) {
- bound(exchange->getName(), key, arguments);
- if (exchange->isDurable() && isDurable()) {
- store->bind(*exchange, *this, key, arguments);
- }
- return true;
- } else {
- return false;
- }
-}
-
-
-const Broker* Queue::getBroker()
-{
- return broker;
-}
-
-void Queue::setDequeueSincePurge(uint32_t value) {
- dequeueSincePurge = value;
-}
-
-
Queue::UsageBarrier::UsageBarrier(Queue& q) : parent(q), count(0) {}
bool Queue::UsageBarrier::acquire()
diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h
index 59ae41e768..12a3d273be 100644
--- a/cpp/src/qpid/broker/Queue.h
+++ b/cpp/src/qpid/broker/Queue.h
@@ -10,9 +10,9 @@
* 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
@@ -32,9 +32,9 @@
#include "qpid/broker/QueueBindings.h"
#include "qpid/broker/QueueListeners.h"
#include "qpid/broker/QueueObserver.h"
+#include "qpid/broker/RateTracker.h"
#include "qpid/framing/FieldTable.h"
-#include "qpid/sys/AtomicValue.h"
#include "qpid/sys/Monitor.h"
#include "qpid/sys/Timer.h"
#include "qpid/management/Manageable.h"
@@ -59,7 +59,7 @@ class MessageStore;
class QueueEvents;
class QueueRegistry;
class TransactionContext;
-class MessageDistributor;
+class Exchange;
/**
* The brokers representation of an amqp queue. Messages are
@@ -74,13 +74,13 @@ class Queue : public boost::enable_shared_from_this<Queue>,
{
Queue& parent;
uint count;
-
+
UsageBarrier(Queue&);
bool acquire();
void release();
void destroy();
};
-
+
struct ScopedUse
{
UsageBarrier& barrier;
@@ -88,7 +88,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
ScopedUse(UsageBarrier& b) : barrier(b), acquired(barrier.acquire()) {}
~ScopedUse() { if (acquired) barrier.release(); }
};
-
+
typedef std::set< boost::shared_ptr<QueueObserver> > Observers;
enum ConsumeCode {NO_MESSAGES=0, CANT_CONSUME=1, CONSUMED=2};
@@ -119,7 +119,7 @@ class Queue : public boost::enable_shared_from_this<Queue>,
boost::shared_ptr<Exchange> alternateExchange;
framing::SequenceNumber sequence;
qmf::org::apache::qpid::broker::Queue* mgmtObject;
- sys::AtomicValue<uint32_t> dequeueSincePurge; // Count dequeues since last purge.
+ RateTracker dequeueTracker;
int eventMode;
Observers observers;
bool insertSeqNo;
@@ -129,36 +129,26 @@ class Queue : public boost::enable_shared_from_this<Queue>,
UsageBarrier barrier;
int autoDeleteTimeout;
boost::intrusive_ptr<qpid::sys::TimerTask> autoDeleteTask;
- boost::shared_ptr<MessageDistributor> allocator;
void push(boost::intrusive_ptr<Message>& msg, bool isRecovery=false);
void setPolicy(std::auto_ptr<QueuePolicy> policy);
- bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
- ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
- bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr& c);
+ bool seek(QueuedMessage& msg, Consumer::shared_ptr position);
+ bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
+ ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
+ bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr c);
void notifyListener();
void removeListener(Consumer::shared_ptr);
bool isExcluded(boost::intrusive_ptr<Message>& msg);
- /** update queue observers, stats, policy, etc when the messages' state changes. Lock
- * must be held by caller */
- void observeEnqueue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeAcquire(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeRequeue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
- void observeDequeue(const QueuedMessage& msg, const sys::Mutex::ScopedLock& lock);
-
- /** modify the Queue's message container - assumes messageLock held */
- void pop(const sys::Mutex::ScopedLock& held); // acquire front msg
- void popAndDequeue(const sys::Mutex::ScopedLock& held); // acquire and dequeue front msg
- // acquire message @ position, return true and set msg if acquire succeeds
- bool acquire(const qpid::framing::SequenceNumber& position, QueuedMessage& msg,
- const sys::Mutex::ScopedLock& held);
-
+ void enqueued(const QueuedMessage& msg);
+ void dequeued(const QueuedMessage& msg);
+ void pop();
+ void popAndDequeue();
+ QueuedMessage getFront();
void forcePersistent(QueuedMessage& msg);
int getEventMode();
- void configureImpl(const qpid::framing::FieldTable& settings);
inline void mgntEnqStats(const boost::intrusive_ptr<Message>& msg)
{
@@ -182,9 +172,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
}
}
}
-
+
void checkNotDeleted();
- void notifyDeleted();
public:
@@ -193,50 +182,29 @@ class Queue : public boost::enable_shared_from_this<Queue>,
typedef std::vector<shared_ptr> vector;
QPID_BROKER_EXTERN Queue(const std::string& name,
- bool autodelete = false,
- MessageStore* const store = 0,
+ bool autodelete = false,
+ MessageStore* const store = 0,
const OwnershipToken* const owner = 0,
management::Manageable* parent = 0,
Broker* broker = 0);
QPID_BROKER_EXTERN ~Queue();
- /** allow the Consumer to consume or browse the next available message */
QPID_BROKER_EXTERN bool dispatch(Consumer::shared_ptr);
- /** allow the Consumer to acquire a message that it has browsed.
- * @param msg - message to be acquired.
- * @return false if message is no longer available for acquire.
- */
- QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg, const std::string& consumer);
+ void create(const qpid::framing::FieldTable& settings);
- /**
- * Used to configure a new queue and create a persistent record
- * for it in store if required.
- */
- QPID_BROKER_EXTERN void create(const qpid::framing::FieldTable& settings);
-
- /**
- * Used to reconfigure a recovered queue (does not create
- * persistent record in store).
- */
- QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings);
- void destroyed();
+ // "recovering" means we are doing a MessageStore recovery.
+ QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings,
+ bool recovering = false);
+ void destroy();
+ void notifyDeleted();
QPID_BROKER_EXTERN void bound(const std::string& exchange,
const std::string& key,
const qpid::framing::FieldTable& args);
- //TODO: get unbind out of the public interface; only there for purposes of one unit test
- QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges);
- /**
- * Bind self to specified exchange, and record that binding for unbinding on delete.
- */
- bool bind(boost::shared_ptr<Exchange> exchange, const std::string& key,
- const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable());
+ QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges,
+ Queue::shared_ptr shared_ref);
- /** Acquire the message at the given position if it is available for acquire. Not to
- * be used by clients, but used by the broker for queue management.
- * @param message - set to the acquired message if true returned.
- * @return true if the message has been acquired.
- */
+ QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg);
QPID_BROKER_EXTERN bool acquireMessageAt(const qpid::framing::SequenceNumber& position, QueuedMessage& message);
/**
@@ -265,14 +233,11 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bool exclusive = false);
QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c);
- uint32_t purge(const uint32_t purge_request=0, //defaults to all messages
- boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>(),
- const ::qpid::types::Variant::Map *filter=0);
- QPID_BROKER_EXTERN void purgeExpired(sys::Duration);
+ uint32_t purge(const uint32_t purge_request=0, boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>()); //defaults to all messages
+ QPID_BROKER_EXTERN void purgeExpired();
//move qty # of messages to destination Queue destq
- uint32_t move(const Queue::shared_ptr destq, uint32_t qty,
- const qpid::types::Variant::Map *filter=0);
+ uint32_t move(const Queue::shared_ptr destq, uint32_t qty);
QPID_BROKER_EXTERN uint32_t getMessageCount() const;
QPID_BROKER_EXTERN uint32_t getEnqueueCompleteMessageCount() const;
@@ -311,8 +276,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* Inform queue of messages that were enqueued, have since
* been acquired but not yet accepted or released (and
* thus are still logically on the queue) - used in
- * clustered broker.
- */
+ * clustered broker.
+ */
void updateEnqueued(const QueuedMessage& msg);
/**
@@ -323,14 +288,14 @@ class Queue : public boost::enable_shared_from_this<Queue>,
* accepted it).
*/
bool isEnqueued(const QueuedMessage& msg);
-
+
/**
- * Acquires the next available (oldest) message
+ * Gets the next available message
*/
QPID_BROKER_EXTERN QueuedMessage get();
- /** Get the message at position pos, returns true if found and sets msg */
- QPID_BROKER_EXTERN bool find(framing::SequenceNumber pos, QueuedMessage& msg ) const;
+ /** Get the message at position pos */
+ QPID_BROKER_EXTERN QueuedMessage find(framing::SequenceNumber pos) const;
const QueuePolicy* getPolicy();
@@ -344,13 +309,8 @@ class Queue : public boost::enable_shared_from_this<Queue>,
void encode(framing::Buffer& buffer) const;
uint32_t encodedSize() const;
- /**
- * Restores a queue from encoded data (used in recovery)
- *
- * Note: restored queue will be neither auto-deleted or have an
- * exclusive owner
- */
- static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer);
+ // "recovering" means we are doing a MessageStore recovery.
+ static Queue::shared_ptr decode(QueueRegistry& queues, framing::Buffer& buffer, bool recovering = false );
static void tryAutoDelete(Broker& broker, Queue::shared_ptr);
virtual void setExternalQueueStore(ExternalQueueStore* inst);
@@ -359,7 +319,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
management::ManagementObject* GetManagementObject (void) const;
management::Manageable::status_t
ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
- void query(::qpid::types::Variant::Map&) const;
/** Apply f to each Message on the queue. */
template <class F> void eachMessage(F f) {
@@ -372,11 +331,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
bindings.eachBinding(f);
}
- /** Apply f to each Observer on the queue */
- template <class F> void eachObserver(F f) {
- std::for_each<Observers::iterator, F>(observers.begin(), observers.end(), f);
- }
-
/** Set the position sequence number for the next message on the queue.
* Must be >= the current sequence number.
* Used by cluster to replicate queues.
@@ -404,11 +358,6 @@ class Queue : public boost::enable_shared_from_this<Queue>,
void recoverPrepared(boost::intrusive_ptr<Message>& msg);
void flush();
-
- const Broker* getBroker();
-
- uint32_t getDequeueSincePurge() { return dequeueSincePurge.get(); }
- void setDequeueSincePurge(uint32_t value);
};
}
}
diff --git a/cpp/src/qpid/broker/QueueCleaner.cpp b/cpp/src/qpid/broker/QueueCleaner.cpp
index 838bc28be8..3499ea8a4d 100644
--- a/cpp/src/qpid/broker/QueueCleaner.cpp
+++ b/cpp/src/qpid/broker/QueueCleaner.cpp
@@ -7,9 +7,9 @@
* 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
@@ -27,7 +27,7 @@
namespace qpid {
namespace broker {
-QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer* t) : queues(q), timer(t) {}
+QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer& t) : queues(q), timer(t) {}
QueueCleaner::~QueueCleaner()
{
@@ -36,16 +36,10 @@ QueueCleaner::~QueueCleaner()
void QueueCleaner::start(qpid::sys::Duration p)
{
- period = p;
task = new Task(*this, p);
- timer->add(task);
+ timer.add(task);
}
-void QueueCleaner::setTimer(qpid::sys::Timer* timer) {
- this->timer = timer;
-}
-
-
QueueCleaner::Task::Task(QueueCleaner& p, qpid::sys::Duration d) : sys::TimerTask(d,"QueueCleaner"), parent(p) {}
void QueueCleaner::Task::fire()
@@ -71,9 +65,9 @@ void QueueCleaner::fired()
std::vector<Queue::shared_ptr> copy;
CollectQueues collect(&copy);
queues.eachQueue(collect);
- std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1, period));
+ std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1));
task->setupNextFire();
- timer->add(task);
+ timer.add(task);
}
diff --git a/cpp/src/qpid/broker/QueueCleaner.h b/cpp/src/qpid/broker/QueueCleaner.h
index ffebfe3e1b..11c2d180ac 100644
--- a/cpp/src/qpid/broker/QueueCleaner.h
+++ b/cpp/src/qpid/broker/QueueCleaner.h
@@ -10,9 +10,9 @@
* 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
@@ -35,15 +35,14 @@ class QueueRegistry;
class QueueCleaner
{
public:
- QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer* timer);
+ QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer& timer);
QPID_BROKER_EXTERN ~QueueCleaner();
- QPID_BROKER_EXTERN void start(sys::Duration period);
- QPID_BROKER_EXTERN void setTimer(sys::Timer* timer);
+ QPID_BROKER_EXTERN void start(qpid::sys::Duration period);
private:
class Task : public sys::TimerTask
{
public:
- Task(QueueCleaner& parent, sys::Duration duration);
+ Task(QueueCleaner& parent, qpid::sys::Duration duration);
void fire();
private:
QueueCleaner& parent;
@@ -51,8 +50,7 @@ class QueueCleaner
boost::intrusive_ptr<sys::TimerTask> task;
QueueRegistry& queues;
- sys::Timer* timer;
- sys::Duration period;
+ sys::Timer& timer;
void fired();
};
diff --git a/cpp/src/qpid/broker/QueueEvents.cpp b/cpp/src/qpid/broker/QueueEvents.cpp
index c66bdabf0f..2c540ff1ad 100644
--- a/cpp/src/qpid/broker/QueueEvents.cpp
+++ b/cpp/src/qpid/broker/QueueEvents.cpp
@@ -129,10 +129,6 @@ class EventGenerator : public QueueObserver
{
if (!enqueueOnly) manager.dequeued(m);
}
-
- void acquired(const QueuedMessage&) {};
- void requeued(const QueuedMessage&) {};
-
private:
QueueEvents& manager;
const bool enqueueOnly;
diff --git a/cpp/src/qpid/broker/QueueFlowLimit.cpp b/cpp/src/qpid/broker/QueueFlowLimit.cpp
deleted file mode 100644
index f15bb45c01..0000000000
--- a/cpp/src/qpid/broker/QueueFlowLimit.cpp
+++ /dev/null
@@ -1,410 +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 "qpid/broker/QueueFlowLimit.h"
-#include "qpid/broker/Broker.h"
-#include "qpid/broker/Queue.h"
-#include "qpid/Exception.h"
-#include "qpid/framing/FieldValue.h"
-#include "qpid/framing/reply_exceptions.h"
-#include "qpid/log/Statement.h"
-#include "qpid/sys/Mutex.h"
-#include "qpid/broker/SessionState.h"
-#include "qpid/sys/ClusterSafe.h"
-
-#include "qmf/org/apache/qpid/broker/Queue.h"
-
-#include <sstream>
-
-using namespace qpid::broker;
-using namespace qpid::framing;
-
-namespace {
- /** ensure that the configured flow control stop and resume values are
- * valid with respect to the maximum queue capacity, and each other
- */
- template <typename T>
- void validateFlowConfig(T max, T& stop, T& resume, const std::string& type, const std::string& queue)
- {
- if (resume > stop) {
- throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_resume_" << type
- << "=" << resume
- << " must be less than qpid.flow_stop_" << type
- << "=" << stop));
- }
- if (resume == 0) resume = stop;
- if (max != 0 && (max < stop)) {
- throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_stop_" << type
- << "=" << stop
- << " must be less than qpid.max_" << type
- << "=" << max));
- }
- }
-
- /** extract a capacity value as passed in an argument map
- */
- uint64_t getCapacity(const FieldTable& settings, const std::string& key, uint64_t defaultValue)
- {
- FieldTable::ValuePtr v = settings.get(key);
-
- int64_t result = 0;
-
- if (!v) return defaultValue;
- if (v->getType() == 0x23) {
- QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>());
- } else if (v->getType() == 0x33) {
- QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>());
- } else if (v->convertsTo<int64_t>()) {
- result = v->get<int64_t>();
- QPID_LOG(debug, "Got integer value for " << key << ": " << result);
- if (result >= 0) return result;
- } else if (v->convertsTo<string>()) {
- string s(v->get<string>());
- QPID_LOG(debug, "Got string value for " << key << ": " << s);
- std::istringstream convert(s);
- if (convert >> result && result >= 0) return result;
- }
-
- QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")");
- return defaultValue;
- }
-}
-
-
-
-QueueFlowLimit::QueueFlowLimit(Queue *_queue,
- uint32_t _flowStopCount, uint32_t _flowResumeCount,
- uint64_t _flowStopSize, uint64_t _flowResumeSize)
- : StatefulQueueObserver(std::string("QueueFlowLimit")), queue(_queue), queueName("<unknown>"),
- flowStopCount(_flowStopCount), flowResumeCount(_flowResumeCount),
- flowStopSize(_flowStopSize), flowResumeSize(_flowResumeSize),
- flowStopped(false), count(0), size(0), queueMgmtObj(0), broker(0)
-{
- uint32_t maxCount(0);
- uint64_t maxSize(0);
-
- if (queue) {
- queueName = _queue->getName();
- if (queue->getPolicy()) {
- maxSize = _queue->getPolicy()->getMaxSize();
- maxCount = _queue->getPolicy()->getMaxCount();
- }
- broker = queue->getBroker();
- queueMgmtObj = dynamic_cast<_qmfBroker::Queue*> (queue->GetManagementObject());
- if (queueMgmtObj) {
- queueMgmtObj->set_flowStopped(isFlowControlActive());
- }
- }
- validateFlowConfig( maxCount, flowStopCount, flowResumeCount, "count", queueName );
- validateFlowConfig( maxSize, flowStopSize, flowResumeSize, "size", queueName );
- QPID_LOG(info, "Queue \"" << queueName << "\": Flow limit created: flowStopCount=" << flowStopCount
- << ", flowResumeCount=" << flowResumeCount
- << ", flowStopSize=" << flowStopSize << ", flowResumeSize=" << flowResumeSize );
-}
-
-
-QueueFlowLimit::~QueueFlowLimit()
-{
- sys::Mutex::ScopedLock l(indexLock);
- if (!index.empty()) {
- // we're gone - release all pending msgs
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin();
- itr != index.end(); ++itr)
- if (itr->second)
- try {
- itr->second->getIngressCompletion().finishCompleter();
- } catch (...) {} // ignore - not safe for a destructor to throw.
- index.clear();
- }
-}
-
-
-void QueueFlowLimit::enqueued(const QueuedMessage& msg)
-{
- sys::Mutex::ScopedLock l(indexLock);
-
- ++count;
- size += msg.payload->contentSize();
-
- if (!flowStopped) {
- if (flowStopCount && count > flowStopCount) {
- flowStopped = true;
- QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopCount << " enqueued messages. Producer flow control activated." );
- } else if (flowStopSize && size > flowStopSize) {
- flowStopped = true;
- QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopSize << " enqueued bytes. Producer flow control activated." );
- }
- if (flowStopped && queueMgmtObj) {
- queueMgmtObj->set_flowStopped(true);
- queueMgmtObj->inc_flowStoppedCount();
- }
- }
-
- if (flowStopped || !index.empty()) {
- // ignore flow control if we are populating the queue due to cluster replication:
- if (broker && broker->isClusterUpdatee()) {
- QPID_LOG(trace, "Queue \"" << queueName << "\": ignoring flow control for msg pos=" << msg.position);
- return;
- }
- QPID_LOG(trace, "Queue \"" << queueName << "\": setting flow control for msg pos=" << msg.position);
- msg.payload->getIngressCompletion().startCompleter(); // don't complete until flow resumes
- bool unique;
- unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(msg.position, msg.payload)).second;
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!unique) assert(unique);
- }
-}
-
-
-
-void QueueFlowLimit::dequeued(const QueuedMessage& msg)
-{
- sys::Mutex::ScopedLock l(indexLock);
-
- if (count > 0) {
- --count;
- } else {
- throw Exception(QPID_MSG("Flow limit count underflow on dequeue. Queue=" << queueName));
- }
-
- uint64_t _size = msg.payload->contentSize();
- if (_size <= size) {
- size -= _size;
- } else {
- throw Exception(QPID_MSG("Flow limit size underflow on dequeue. Queue=" << queueName));
- }
-
- if (flowStopped &&
- (flowResumeSize == 0 || size < flowResumeSize) &&
- (flowResumeCount == 0 || count < flowResumeCount)) {
- flowStopped = false;
- if (queueMgmtObj)
- queueMgmtObj->set_flowStopped(false);
- QPID_LOG(info, "Queue \"" << queueName << "\": has drained below the flow control resume level. Producer flow control deactivated." );
- }
-
- if (!index.empty()) {
- if (!flowStopped) {
- // flow enabled - release all pending msgs
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin();
- itr != index.end(); ++itr)
- if (itr->second)
- itr->second->getIngressCompletion().finishCompleter();
- index.clear();
- } else {
- // even if flow controlled, we must release this msg as it is being dequeued
- std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.find(msg.position);
- if (itr != index.end()) { // this msg is flow controlled, release it:
- msg.payload->getIngressCompletion().finishCompleter();
- index.erase(itr);
- }
- }
- }
-}
-
-
-void QueueFlowLimit::encode(Buffer& buffer) const
-{
- buffer.putLong(flowStopCount);
- buffer.putLong(flowResumeCount);
- buffer.putLongLong(flowStopSize);
- buffer.putLongLong(flowResumeSize);
- buffer.putLong(count);
- buffer.putLongLong(size);
-}
-
-
-void QueueFlowLimit::decode ( Buffer& buffer )
-{
- flowStopCount = buffer.getLong();
- flowResumeCount = buffer.getLong();
- flowStopSize = buffer.getLongLong();
- flowResumeSize = buffer.getLongLong();
- count = buffer.getLong();
- size = buffer.getLongLong();
-}
-
-
-uint32_t QueueFlowLimit::encodedSize() const {
- return sizeof(uint32_t) + // flowStopCount
- sizeof(uint32_t) + // flowResumecount
- sizeof(uint64_t) + // flowStopSize
- sizeof(uint64_t) + // flowResumeSize
- sizeof(uint32_t) + // count
- sizeof(uint64_t); // size
-}
-
-
-const std::string QueueFlowLimit::flowStopCountKey("qpid.flow_stop_count");
-const std::string QueueFlowLimit::flowResumeCountKey("qpid.flow_resume_count");
-const std::string QueueFlowLimit::flowStopSizeKey("qpid.flow_stop_size");
-const std::string QueueFlowLimit::flowResumeSizeKey("qpid.flow_resume_size");
-uint64_t QueueFlowLimit::defaultMaxSize;
-uint QueueFlowLimit::defaultFlowStopRatio;
-uint QueueFlowLimit::defaultFlowResumeRatio;
-
-
-void QueueFlowLimit::setDefaults(uint64_t maxQueueSize, uint flowStopRatio, uint flowResumeRatio)
-{
- defaultMaxSize = maxQueueSize;
- defaultFlowStopRatio = flowStopRatio;
- defaultFlowResumeRatio = flowResumeRatio;
-
- /** @todo KAG: Verify valid range on Broker::Options instead of here */
- if (flowStopRatio > 100 || flowResumeRatio > 100)
- throw InvalidArgumentException(QPID_MSG("Default queue flow ratios must be between 0 and 100, inclusive:"
- << " flowStopRatio=" << flowStopRatio
- << " flowResumeRatio=" << flowResumeRatio));
- if (flowResumeRatio > flowStopRatio)
- throw InvalidArgumentException(QPID_MSG("Default queue flow stop ratio must be >= flow resume ratio:"
- << " flowStopRatio=" << flowStopRatio
- << " flowResumeRatio=" << flowResumeRatio));
-}
-
-
-void QueueFlowLimit::observe(Queue& queue, const qpid::framing::FieldTable& settings)
-{
- QueueFlowLimit *ptr = createLimit( &queue, settings );
- if (ptr) {
- boost::shared_ptr<QueueFlowLimit> observer(ptr);
- queue.addObserver(observer);
- }
-}
-
-/** returns ptr to a QueueFlowLimit, else 0 if no limit */
-QueueFlowLimit *QueueFlowLimit::createLimit(Queue *queue, const qpid::framing::FieldTable& settings)
-{
- std::string type(QueuePolicy::getType(settings));
-
- if (type == QueuePolicy::RING || type == QueuePolicy::RING_STRICT) {
- // The size of a RING queue is limited by design - no need for flow control.
- return 0;
- }
-
- if (settings.get(flowStopCountKey) || settings.get(flowStopSizeKey) ||
- settings.get(flowResumeCountKey) || settings.get(flowResumeSizeKey)) {
- // user provided (some) flow settings manually...
- uint32_t flowStopCount = getCapacity(settings, flowStopCountKey, 0);
- uint32_t flowResumeCount = getCapacity(settings, flowResumeCountKey, 0);
- uint64_t flowStopSize = getCapacity(settings, flowStopSizeKey, 0);
- uint64_t flowResumeSize = getCapacity(settings, flowResumeSizeKey, 0);
- if (flowStopCount == 0 && flowStopSize == 0) { // disable flow control
- return 0;
- }
- return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
-
- if (defaultFlowStopRatio) { // broker has a default ratio setup...
- uint64_t maxByteCount = getCapacity(settings, QueuePolicy::maxSizeKey, defaultMaxSize);
- uint64_t flowStopSize = (uint64_t)(maxByteCount * (defaultFlowStopRatio/100.0) + 0.5);
- uint64_t flowResumeSize = (uint64_t)(maxByteCount * (defaultFlowResumeRatio/100.0));
- uint32_t maxMsgCount = getCapacity(settings, QueuePolicy::maxCountKey, 0); // no size by default
- uint32_t flowStopCount = (uint32_t)(maxMsgCount * (defaultFlowStopRatio/100.0) + 0.5);
- uint32_t flowResumeCount = (uint32_t)(maxMsgCount * (defaultFlowResumeRatio/100.0));
-
- return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
- return 0;
-}
-
-/* Cluster replication */
-
-namespace {
- /** pack a set of sequence number ranges into a framing::Array */
- void buildSeqRangeArray(qpid::framing::Array *seqs,
- const qpid::framing::SequenceNumber& first,
- const qpid::framing::SequenceNumber& last)
- {
- seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(first)));
- seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(last)));
- }
-}
-
-/** Runs on UPDATER to snapshot current state */
-void QueueFlowLimit::getState(qpid::framing::FieldTable& state ) const
-{
- sys::Mutex::ScopedLock l(indexLock);
- state.clear();
-
- framing::SequenceSet ss;
- if (!index.empty()) {
- /* replicate the set of messages pending flow control */
- for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::const_iterator itr = index.begin();
- itr != index.end(); ++itr) {
- ss.add(itr->first);
- }
- framing::Array seqs(TYPE_CODE_UINT32);
- typedef boost::function<void(framing::SequenceNumber, framing::SequenceNumber)> arrayBuilder;
- ss.for_each((arrayBuilder)boost::bind(&buildSeqRangeArray, &seqs, _1, _2));
- state.setArray("pendingMsgSeqs", seqs);
- }
- QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicating pending msgs, range=" << ss);
-}
-
-
-/** called on UPDATEE to set state from snapshot */
-void QueueFlowLimit::setState(const qpid::framing::FieldTable& state)
-{
- sys::Mutex::ScopedLock l(indexLock);
- index.clear();
-
- framing::SequenceSet fcmsg;
- framing::Array seqArray(TYPE_CODE_UINT32);
- if (state.getArray("pendingMsgSeqs", seqArray)) {
- assert((seqArray.count() & 0x01) == 0); // must be even since they are sequence ranges
- framing::Array::const_iterator i = seqArray.begin();
- while (i != seqArray.end()) {
- framing::SequenceNumber first((*i)->getIntegerValue<uint32_t, 4>());
- ++i;
- framing::SequenceNumber last((*i)->getIntegerValue<uint32_t, 4>());
- ++i;
- fcmsg.add(first, last);
- for (SequenceNumber seq = first; seq <= last; ++seq) {
- QueuedMessage msg;
- queue->find(seq, msg); // fyi: may not be found if msg is acquired & unacked
- bool unique;
- unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(seq, msg.payload)).second;
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!unique) assert(unique);
- }
- }
- }
-
- flowStopped = index.size() != 0;
- if (queueMgmtObj) {
- queueMgmtObj->set_flowStopped(isFlowControlActive());
- }
- QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicated the pending msgs, range=" << fcmsg)
-}
-
-
-namespace qpid {
- namespace broker {
-
-std::ostream& operator<<(std::ostream& out, const QueueFlowLimit& f)
-{
- out << "; flowStopCount=" << f.flowStopCount << ", flowResumeCount=" << f.flowResumeCount;
- out << "; flowStopSize=" << f.flowStopSize << ", flowResumeSize=" << f.flowResumeSize;
- return out;
-}
-
- }
-}
-
diff --git a/cpp/src/qpid/broker/QueueFlowLimit.h b/cpp/src/qpid/broker/QueueFlowLimit.h
deleted file mode 100644
index ad8a2720ef..0000000000
--- a/cpp/src/qpid/broker/QueueFlowLimit.h
+++ /dev/null
@@ -1,132 +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.
- *
- */
-#ifndef _QueueFlowLimit_
-#define _QueueFlowLimit_
-
-#include <list>
-#include <set>
-#include <iostream>
-#include <memory>
-#include "qpid/broker/BrokerImportExport.h"
-#include "qpid/broker/QueuedMessage.h"
-#include "qpid/broker/StatefulQueueObserver.h"
-#include "qpid/framing/FieldTable.h"
-#include "qpid/sys/AtomicValue.h"
-#include "qpid/sys/Mutex.h"
-
-namespace qmf {
-namespace org {
-namespace apache {
-namespace qpid {
-namespace broker {
- class Queue;
-}}}}}
-namespace _qmfBroker = qmf::org::apache::qpid::broker;
-
-namespace qpid {
-namespace broker {
-
-class Broker;
-
-/**
- * Producer flow control: when level is > flowStop*, flow control is ON.
- * then level is < flowResume*, flow control is OFF. If == 0, flow control
- * is not used. If both byte and msg count thresholds are set, then
- * passing _either_ level may turn flow control ON, but _both_ must be
- * below level before flow control will be turned OFF.
- */
- class QueueFlowLimit : public StatefulQueueObserver
-{
- static uint64_t defaultMaxSize;
- static uint defaultFlowStopRatio;
- static uint defaultFlowResumeRatio;
-
- Queue *queue;
- std::string queueName;
-
- uint32_t flowStopCount;
- uint32_t flowResumeCount;
- uint64_t flowStopSize;
- uint64_t flowResumeSize;
- bool flowStopped; // true = producers held in flow control
-
- // current queue utilization
- uint32_t count;
- uint64_t size;
-
- public:
- static QPID_BROKER_EXTERN const std::string flowStopCountKey;
- static QPID_BROKER_EXTERN const std::string flowResumeCountKey;
- static QPID_BROKER_EXTERN const std::string flowStopSizeKey;
- static QPID_BROKER_EXTERN const std::string flowResumeSizeKey;
-
- QPID_BROKER_EXTERN virtual ~QueueFlowLimit();
-
- /** the queue has added QueuedMessage. Returns true if flow state changes */
- QPID_BROKER_EXTERN void enqueued(const QueuedMessage&);
- /** the queue has removed QueuedMessage. Returns true if flow state changes */
- QPID_BROKER_EXTERN void dequeued(const QueuedMessage&);
- /** ignored */
- QPID_BROKER_EXTERN void acquired(const QueuedMessage&) {};
- QPID_BROKER_EXTERN void requeued(const QueuedMessage&) {};
-
- /** for clustering: */
- QPID_BROKER_EXTERN void getState(qpid::framing::FieldTable&) const;
- QPID_BROKER_EXTERN void setState(const qpid::framing::FieldTable&);
-
- uint32_t getFlowStopCount() const { return flowStopCount; }
- uint32_t getFlowResumeCount() const { return flowResumeCount; }
- uint64_t getFlowStopSize() const { return flowStopSize; }
- uint64_t getFlowResumeSize() const { return flowResumeSize; }
-
- uint32_t getFlowCount() const { return count; }
- uint64_t getFlowSize() const { return size; }
- bool isFlowControlActive() const { return flowStopped; }
- bool monitorFlowControl() const { return flowStopCount || flowStopSize; }
-
- void encode(framing::Buffer& buffer) const;
- void decode(framing::Buffer& buffer);
- uint32_t encodedSize() const;
-
- static QPID_BROKER_EXTERN void observe(Queue& queue, const qpid::framing::FieldTable& settings);
- static QPID_BROKER_EXTERN void setDefaults(uint64_t defaultMaxSize, uint defaultFlowStopRatio, uint defaultFlowResumeRatio);
-
- friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueueFlowLimit&);
-
- protected:
- // msgs waiting for flow to become available.
- std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> > index;
- mutable qpid::sys::Mutex indexLock;
-
- _qmfBroker::Queue *queueMgmtObj;
-
- const Broker *broker;
-
- QPID_BROKER_EXTERN QueueFlowLimit(Queue *queue,
- uint32_t flowStopCount, uint32_t flowResumeCount,
- uint64_t flowStopSize, uint64_t flowResumeSize);
- static QPID_BROKER_EXTERN QueueFlowLimit *createLimit(Queue *queue, const qpid::framing::FieldTable& settings);
-};
-
-}}
-
-
-#endif
diff --git a/cpp/src/qpid/broker/QueueListeners.cpp b/cpp/src/qpid/broker/QueueListeners.cpp
index 591f4443bb..4d2c57d6b4 100644
--- a/cpp/src/qpid/broker/QueueListeners.cpp
+++ b/cpp/src/qpid/broker/QueueListeners.cpp
@@ -26,25 +26,19 @@ namespace broker {
void QueueListeners::addListener(Consumer::shared_ptr c)
{
- if (!c->inListeners) {
- if (c->acquires) {
- add(consumers, c);
- } else {
- add(browsers, c);
- }
- c->inListeners = true;
+ if (c->preAcquires()) {
+ add(consumers, c);
+ } else {
+ add(browsers, c);
}
}
void QueueListeners::removeListener(Consumer::shared_ptr c)
{
- if (c->inListeners) {
- if (c->acquires) {
- remove(consumers, c);
- } else {
- remove(browsers, c);
- }
- c->inListeners = false;
+ if (c->preAcquires()) {
+ remove(consumers, c);
+ } else {
+ remove(browsers, c);
}
}
@@ -52,20 +46,18 @@ void QueueListeners::populate(NotificationSet& set)
{
if (consumers.size()) {
set.consumer = consumers.front();
- consumers.pop_front();
- set.consumer->inListeners = false;
+ consumers.erase(consumers.begin());
} else {
- // Don't swap the deques, hang on to the memory allocated.
+ // Don't swap the vectors, hang on to the memory allocated.
set.browsers = browsers;
browsers.clear();
- for (Listeners::iterator i = set.browsers.begin(); i != set.browsers.end(); i++)
- (*i)->inListeners = false;
}
}
void QueueListeners::add(Listeners& listeners, Consumer::shared_ptr c)
{
- listeners.push_back(c);
+ Listeners::iterator i = std::find(listeners.begin(), listeners.end(), c);
+ if (i == listeners.end()) listeners.push_back(c);
}
void QueueListeners::remove(Listeners& listeners, Consumer::shared_ptr c)
@@ -81,7 +73,9 @@ void QueueListeners::NotificationSet::notify()
}
bool QueueListeners::contains(Consumer::shared_ptr c) const {
- return c->inListeners;
+ return
+ std::find(browsers.begin(), browsers.end(), c) != browsers.end() ||
+ std::find(consumers.begin(), consumers.end(), c) != consumers.end();
}
void QueueListeners::ListenerSet::notifyAll()
diff --git a/cpp/src/qpid/broker/QueueListeners.h b/cpp/src/qpid/broker/QueueListeners.h
index 0659499253..59d1c84ca4 100644
--- a/cpp/src/qpid/broker/QueueListeners.h
+++ b/cpp/src/qpid/broker/QueueListeners.h
@@ -22,7 +22,7 @@
*
*/
#include "qpid/broker/Consumer.h"
-#include <deque>
+#include <vector>
namespace qpid {
namespace broker {
@@ -40,7 +40,7 @@ namespace broker {
class QueueListeners
{
public:
- typedef std::deque<Consumer::shared_ptr> Listeners;
+ typedef std::vector<Consumer::shared_ptr> Listeners;
class NotificationSet
{
diff --git a/cpp/src/qpid/broker/QueueObserver.h b/cpp/src/qpid/broker/QueueObserver.h
index b58becd2ae..a711213dee 100644
--- a/cpp/src/qpid/broker/QueueObserver.h
+++ b/cpp/src/qpid/broker/QueueObserver.h
@@ -24,52 +24,18 @@
namespace qpid {
namespace broker {
-struct QueuedMessage;
-class Consumer;
-
+class QueuedMessage;
/**
- * Interface for notifying classes who want to act as 'observers' of a queue of particular
- * events.
- *
- * The events that are monitored reflect the relationship between a particular message and
- * the queue it has been delivered to. A message can be considered in one of three states
- * with respect to the queue:
- *
- * 1) "Available" - available for transfer to consumers (i.e. for browse or acquire),
- *
- * 2) "Acquired" - owned by a particular consumer, no longer available to other consumers
- * (by either browse or acquire), but still considered on the queue.
- *
- * 3) "Dequeued" - removed from the queue and no longer available to any consumer.
- *
- * The queue events that are observable are:
- *
- * "Enqueued" - the message is "Available" - on the queue for transfer to any consumer
- * (e.g. browse or acquire)
- *
- * "Acquired" - - a consumer has claimed exclusive access to it. It is no longer available
- * for other consumers to browse or acquire, but it is not yet considered dequeued as it
- * may be requeued by the consumer.
- *
- * "Requeued" - a previously-acquired message is released by its owner: it is put back on
- * the queue at its original position and returns to the "Available" state.
- *
- * "Dequeued" - a message is no longer queued. At this point, the queue no longer tracks
- * the message, and the broker considers the consumer's transaction complete.
+ * Interface for notifying classes who want to act as 'observers' of a
+ * queue of particular events.
*/
class QueueObserver
{
public:
virtual ~QueueObserver() {}
-
- // note: the Queue will hold the messageLock while calling these methods!
virtual void enqueued(const QueuedMessage&) = 0;
virtual void dequeued(const QueuedMessage&) = 0;
- virtual void acquired(const QueuedMessage&) = 0;
- virtual void requeued(const QueuedMessage&) = 0;
- virtual void consumerAdded( const Consumer& ) {};
- virtual void consumerRemoved( const Consumer& ) {};
- private:
+ private:
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/QueuePolicy.cpp b/cpp/src/qpid/broker/QueuePolicy.cpp
index 0c245700af..4168221ad0 100644
--- a/cpp/src/qpid/broker/QueuePolicy.cpp
+++ b/cpp/src/qpid/broker/QueuePolicy.cpp
@@ -117,30 +117,30 @@ void QueuePolicy::update(FieldTable& settings)
settings.setString(typeKey, type);
}
-template <typename T>
-T getCapacity(const FieldTable& settings, const std::string& key, T defaultValue)
+uint32_t QueuePolicy::getCapacity(const FieldTable& settings, const std::string& key, uint32_t defaultValue)
{
FieldTable::ValuePtr v = settings.get(key);
- T result = 0;
+ int32_t result = 0;
if (!v) return defaultValue;
if (v->getType() == 0x23) {
QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>());
} else if (v->getType() == 0x33) {
QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>());
- } else if (v->convertsTo<T>()) {
- result = v->get<T>();
+ } else if (v->convertsTo<int>()) {
+ result = v->get<int>();
QPID_LOG(debug, "Got integer value for " << key << ": " << result);
if (result >= 0) return result;
} else if (v->convertsTo<string>()) {
string s(v->get<string>());
QPID_LOG(debug, "Got string value for " << key << ": " << s);
std::istringstream convert(s);
- if (convert >> result && result >= 0 && convert.eof()) return result;
+ if (convert >> result && result >= 0) return result;
}
- throw IllegalArgumentException(QPID_MSG("Cannot convert " << key << " to unsigned integer: " << *v));
+ QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")");
+ return defaultValue;
}
std::string QueuePolicy::getType(const FieldTable& settings)
@@ -247,7 +247,7 @@ bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
{
// If the message is bigger than the queue size, give up
- if (getMaxSize() && m->contentSize() > getMaxSize()) {
+ if (m->contentSize() > getMaxSize()) {
QPID_LOG(debug, "Message too large for ring queue " << name
<< " [" << *this << "] "
<< ": message size = " << m->contentSize() << " bytes"
@@ -269,7 +269,8 @@ bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m)
do {
QueuedMessage oldest = queue.front();
- if (oldest.queue->acquireMessageAt(oldest.position, oldest) || !strict) {
+
+ if (oldest.queue->acquire(oldest) || !strict) {
queue.pop_front();
pendingDequeues.push_back(oldest);
QPID_LOG(debug, "Ring policy triggered in " << name
@@ -319,8 +320,8 @@ std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const qpid::framing::F
std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings)
{
- uint32_t maxCount = getCapacity<int32_t>(settings, maxCountKey, 0);
- uint64_t maxSize = getCapacity<int64_t>(settings, maxSizeKey, defaultMaxSize);
+ uint32_t maxCount = getCapacity(settings, maxCountKey, 0);
+ uint32_t maxSize = getCapacity(settings, maxSizeKey, defaultMaxSize);
if (maxCount || maxSize) {
return createQueuePolicy(name, maxCount, maxSize, getType(settings));
} else {
diff --git a/cpp/src/qpid/broker/QueuePolicy.h b/cpp/src/qpid/broker/QueuePolicy.h
index ec7f846704..3cdd63784d 100644
--- a/cpp/src/qpid/broker/QueuePolicy.h
+++ b/cpp/src/qpid/broker/QueuePolicy.h
@@ -43,7 +43,8 @@ class QueuePolicy
uint32_t count;
uint64_t size;
bool policyExceeded;
-
+
+ static uint32_t getCapacity(const qpid::framing::FieldTable& settings, const std::string& key, uint32_t defaultValue);
protected:
uint64_t getCurrentQueueSize() const { return size; }
diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp
index 135a3543d9..ea2531dae7 100644
--- a/cpp/src/qpid/broker/QueueRegistry.cpp
+++ b/cpp/src/qpid/broker/QueueRegistry.cpp
@@ -21,7 +21,6 @@
#include "qpid/broker/Queue.h"
#include "qpid/broker/QueueRegistry.h"
#include "qpid/broker/QueueEvents.h"
-#include "qpid/broker/Exchange.h"
#include "qpid/log/Statement.h"
#include <sstream>
#include <assert.h>
@@ -37,13 +36,7 @@ QueueRegistry::~QueueRegistry(){}
std::pair<Queue::shared_ptr, bool>
QueueRegistry::declare(const string& declareName, bool durable,
- bool autoDelete, const OwnershipToken* owner,
- boost::shared_ptr<Exchange> alternate,
- const qpid::framing::FieldTable& arguments,
- bool recovering/*true if this declare is a
- result of recovering queue
- definition from persistente
- record*/)
+ bool autoDelete, const OwnershipToken* owner)
{
RWlock::ScopedWlock locker(lock);
string name = declareName.empty() ? generateName() : declareName;
@@ -52,17 +45,6 @@ QueueRegistry::declare(const string& declareName, bool durable,
if (i == queues.end()) {
Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner, parent, broker));
- if (alternate) {
- queue->setAlternateExchange(alternate);//need to do this *before* create
- alternate->incAlternateUsers();
- }
- if (!recovering) {
- //apply settings & create persistent record if required
- queue->create(arguments);
- } else {
- //i.e. recovering a queue for which we already have a persistent record
- queue->configure(arguments);
- }
queues[name] = queue;
if (lastNode) queue->setLastNodeFailure();
diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h
index 8a32a64f05..57859fe639 100644
--- a/cpp/src/qpid/broker/QueueRegistry.h
+++ b/cpp/src/qpid/broker/QueueRegistry.h
@@ -24,7 +24,6 @@
#include "qpid/broker/BrokerImportExport.h"
#include "qpid/sys/Mutex.h"
#include "qpid/management/Manageable.h"
-#include "qpid/framing/FieldTable.h"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm>
@@ -35,7 +34,6 @@ namespace broker {
class Queue;
class QueueEvents;
-class Exchange;
class OwnershipToken;
class Broker;
class MessageStore;
@@ -62,10 +60,7 @@ class QueueRegistry {
const std::string& name,
bool durable = false,
bool autodelete = false,
- const OwnershipToken* owner = 0,
- boost::shared_ptr<Exchange> alternateExchange = boost::shared_ptr<Exchange>(),
- const qpid::framing::FieldTable& args = framing::FieldTable(),
- bool recovering = false);
+ const OwnershipToken* owner = 0);
/**
* Destroy the named queue.
diff --git a/cpp/src/qpid/broker/RateTracker.cpp b/cpp/src/qpid/broker/RateTracker.cpp
new file mode 100644
index 0000000000..048349b658
--- /dev/null
+++ b/cpp/src/qpid/broker/RateTracker.cpp
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 "qpid/broker/RateTracker.h"
+
+using qpid::sys::AbsTime;
+using qpid::sys::Duration;
+using qpid::sys::TIME_SEC;
+
+namespace qpid {
+namespace broker {
+
+RateTracker::RateTracker() : currentCount(0), lastCount(0), lastTime(AbsTime::now()) {}
+
+RateTracker& RateTracker::operator++()
+{
+ ++currentCount;
+ return *this;
+}
+
+double RateTracker::sampleRatePerSecond()
+{
+ int32_t increment = currentCount - lastCount;
+ AbsTime now = AbsTime::now();
+ Duration interval(lastTime, now);
+ lastCount = currentCount;
+ lastTime = now;
+ //if sampling at higher frequency than supported, will just return the number of increments
+ if (interval < TIME_SEC) return increment;
+ else if (increment == 0) return 0;
+ else return increment / (interval / TIME_SEC);
+}
+
+}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/RateTracker.h b/cpp/src/qpid/broker/RateTracker.h
new file mode 100644
index 0000000000..0c20b37312
--- /dev/null
+++ b/cpp/src/qpid/broker/RateTracker.h
@@ -0,0 +1,57 @@
+#ifndef QPID_BROKER_RATETRACKER_H
+#define QPID_BROKER_RATETRACKER_H
+
+/*
+ *
+ * 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 "qpid/sys/Time.h"
+
+namespace qpid {
+namespace broker {
+
+/**
+ * Simple rate tracker: represents some value that can be incremented,
+ * then can periodcially sample the rate of increments.
+ */
+class RateTracker
+{
+ public:
+ RateTracker();
+ /**
+ * Increments the count being tracked. Can be called concurrently
+ * with other calls to this operator as well as with calls to
+ * sampleRatePerSecond().
+ */
+ RateTracker& operator++();
+ /**
+ * Returns the rate of increments per second since last
+ * called. Calls to this method should be serialised, but can be
+ * called concurrently with the increment operator
+ */
+ double sampleRatePerSecond();
+ private:
+ volatile int32_t currentCount;
+ int32_t lastCount;
+ qpid::sys::AbsTime lastTime;
+};
+}} // namespace qpid::broker
+
+#endif /*!QPID_BROKER_RATETRACKER_H*/
diff --git a/cpp/src/qpid/broker/RecoveredDequeue.cpp b/cpp/src/qpid/broker/RecoveredDequeue.cpp
index cd6735328f..38cb8043c9 100644
--- a/cpp/src/qpid/broker/RecoveredDequeue.cpp
+++ b/cpp/src/qpid/broker/RecoveredDequeue.cpp
@@ -43,6 +43,7 @@ void RecoveredDequeue::commit() throw()
void RecoveredDequeue::rollback() throw()
{
+ msg->enqueueComplete();
queue->process(msg);
}
diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.cpp b/cpp/src/qpid/broker/RecoveredEnqueue.cpp
index 6d2eaee6c4..6263c63e3d 100644
--- a/cpp/src/qpid/broker/RecoveredEnqueue.cpp
+++ b/cpp/src/qpid/broker/RecoveredEnqueue.cpp
@@ -36,6 +36,7 @@ bool RecoveredEnqueue::prepare(TransactionContext*) throw(){
}
void RecoveredEnqueue::commit() throw(){
+ msg->enqueueComplete();
queue->process(msg);
}
diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
index d08409695e..2f04943581 100644
--- a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
+++ b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp
@@ -113,7 +113,7 @@ RecoverableExchange::shared_ptr RecoveryManagerImpl::recoverExchange(framing::Bu
RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer)
{
- Queue::shared_ptr queue = Queue::restore(queues, buffer);
+ Queue::shared_ptr queue = Queue::decode(queues, buffer, true);
try {
Exchange::shared_ptr exchange = exchanges.getDefault();
if (exchange) {
@@ -252,6 +252,7 @@ void RecoverableMessageImpl::dequeue(DtxBuffer::shared_ptr buffer, Queue::shared
void RecoverableMessageImpl::enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue)
{
+ msg->enqueueComplete(); // recoved nmessage to enqueued in store already
buffer->enlist(TxOp::shared_ptr(new RecoveredEnqueue(queue, msg)));
}
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp
index d7adbd68ab..acdb4934d4 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp
@@ -30,7 +30,6 @@
#include <boost/format.hpp>
#if HAVE_SASL
-#include <sys/stat.h>
#include <sasl/sasl.h>
#include "qpid/sys/cyrus/CyrusSecurityLayer.h"
using qpid::sys::cyrus::CyrusSecurityLayer;
@@ -58,7 +57,7 @@ public:
NullAuthenticator(Connection& connection, bool encrypt);
~NullAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string&) {}
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -82,7 +81,7 @@ public:
~CyrusAuthenticator();
void init();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string& response);
void getError(std::string& error);
void getUid(std::string& uid) { getUsername(uid); }
@@ -99,33 +98,11 @@ void SaslAuthenticator::init(const std::string& saslName, std::string const & sa
// Check if we have a version of SASL that supports sasl_set_path()
#if (SASL_VERSION_FULL >= ((2<<16)|(1<<8)|22))
// If we are not given a sasl path, do nothing and allow the default to be used.
- if ( saslConfigPath.empty() ) {
- QPID_LOG ( info, "SASL: no config path set - using default." );
- }
- else {
- struct stat st;
-
- // Make sure the directory exists and we can read up to it.
- if ( ::stat ( saslConfigPath.c_str(), & st) ) {
- // Note: not using strerror() here because I think its messages are a little too hazy.
- if ( errno == ENOENT )
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: no such directory: " << saslConfigPath ) );
- if ( errno == EACCES )
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot read parent of: " << saslConfigPath ) );
- // catch-all stat failure
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: cannot stat: " << saslConfigPath ) );
- }
-
- // Make sure the directory is readable.
- if ( ::access ( saslConfigPath.c_str(), R_OK ) ) {
- throw Exception ( QPID_MSG ( "SASL: sasl_set_path failed: directory not readable:" << saslConfigPath ) );
- }
-
- // This shouldn't fail now, but check anyway.
- int code = sasl_set_path(SASL_PATH_TYPE_CONFIG, const_cast<char *>(saslConfigPath.c_str()));
+ if ( ! saslConfigPath.empty() ) {
+ int code = sasl_set_path(SASL_PATH_TYPE_CONFIG,
+ const_cast<char *>(saslConfigPath.c_str()));
if(SASL_OK != code)
throw Exception(QPID_MSG("SASL: sasl_set_path failed [" << code << "] " ));
-
QPID_LOG(info, "SASL: config path set to " << saslConfigPath );
}
#endif
@@ -187,7 +164,7 @@ void NullAuthenticator::getMechanisms(Array& mechanisms)
mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));//useful for testing
}
-void NullAuthenticator::start(const string& mechanism, const string* response)
+void NullAuthenticator::start(const string& mechanism, const string& response)
{
if (encrypt) {
#if HAVE_SASL
@@ -203,16 +180,16 @@ void NullAuthenticator::start(const string& mechanism, const string* response)
}
}
if (mechanism == "PLAIN") { // Old behavior
- if (response && response->size() > 0) {
+ if (response.size() > 0) {
string uid;
- string::size_type i = response->find((char)0);
- if (i == 0 && response->size() > 1) {
+ string::size_type i = response.find((char)0);
+ if (i == 0 && response.size() > 1) {
//no authorization id; use authentication id
- i = response->find((char)0, 1);
- if (i != string::npos) uid = response->substr(1, i-1);
+ i = response.find((char)0, 1);
+ if (i != string::npos) uid = response.substr(1, i-1);
} else if (i != string::npos) {
//authorization id is first null delimited field
- uid = response->substr(0, i);
+ uid = response.substr(0, i);
}//else not a valid SASL PLAIN response, throw error?
if (!uid.empty()) {
//append realm if it has not already been added
@@ -399,22 +376,18 @@ void CyrusAuthenticator::getMechanisms(Array& mechanisms)
}
}
-void CyrusAuthenticator::start(const string& mechanism, const string* response)
+void CyrusAuthenticator::start(const string& mechanism, const string& response)
{
const char *challenge;
unsigned int challenge_len;
- // This should be at same debug level as mech list in getMechanisms().
- QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism);
+ QPID_LOG(debug, "SASL: Starting authentication with mechanism: " << mechanism);
int code = sasl_server_start(sasl_conn,
mechanism.c_str(),
- (response ? response->c_str() : 0), (response ? response->size() : 0),
+ response.c_str(), response.length(),
&challenge, &challenge_len);
processAuthenticationStep(code, challenge, challenge_len);
- qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
- cnxMgmt->set_saslMechanism(mechanism);
}
void CyrusAuthenticator::step(const string& response)
@@ -451,12 +424,10 @@ void CyrusAuthenticator::processAuthenticationStep(int code, const char *challen
client.secure(challenge_str);
} else {
std::string uid;
- //save error detail before trying to retrieve username as error in doing so will overwrite it
- std::string errordetail = sasl_errdetail(sasl_conn);
if (!getUsername(uid)) {
- QPID_LOG(info, "SASL: Authentication failed (no username available yet):" << errordetail);
+ QPID_LOG(info, "SASL: Authentication failed (no username available):" << sasl_errdetail(sasl_conn));
} else {
- QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << errordetail);
+ QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << sasl_errdetail(sasl_conn));
}
// TODO: Change to more specific exceptions, when they are
@@ -488,9 +459,6 @@ std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFr
if (ssf) {
securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize));
}
- qmf::org::apache::qpid::broker::Connection* cnxMgmt = connection.getMgmtObject();
- if ( cnxMgmt )
- cnxMgmt->set_saslSsf(ssf);
return securityLayer;
}
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h
index 4e5d43214c..cfbe1a0cd1 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.h
+++ b/cpp/src/qpid/broker/SaslAuthenticator.h
@@ -41,7 +41,7 @@ class SaslAuthenticator
public:
virtual ~SaslAuthenticator() {}
virtual void getMechanisms(framing::Array& mechanisms) = 0;
- virtual void start(const std::string& mechanism, const std::string* response) = 0;
+ virtual void start(const std::string& mechanism, const std::string& response) = 0;
virtual void step(const std::string& response) = 0;
virtual void getUid(std::string&) {}
virtual bool getUsername(std::string&) { return false; };
diff --git a/cpp/src/qpid/broker/SemanticState.cpp b/cpp/src/qpid/broker/SemanticState.cpp
index fbcb21eab9..c91cfba2f8 100644
--- a/cpp/src/qpid/broker/SemanticState.cpp
+++ b/cpp/src/qpid/broker/SemanticState.cpp
@@ -70,12 +70,14 @@ SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss)
deliveryAdapter(da),
tagGenerator("sgen"),
dtxSelected(false),
- authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isUserProxyAuth()),
+ authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isFederationLink()),
userID(getSession().getConnection().getUserId()),
userName(getSession().getConnection().getUserId().substr(0,getSession().getConnection().getUserId().find('@'))),
isDefaultRealm(userID.find('@') != std::string::npos && getSession().getBroker().getOptions().realm == userID.substr(userID.find('@')+1,userID.size())),
closeComplete(false)
-{}
+{
+ acl = getSession().getBroker().getAcl();
+}
SemanticState::~SemanticState() {
closed();
@@ -86,7 +88,7 @@ void SemanticState::closed() {
//prevent requeued messages being redelivered to consumers
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
disable(i->second);
- }
+ }
if (dtxBuffer.get()) {
dtxBuffer->fail();
}
@@ -105,24 +107,16 @@ bool SemanticState::exists(const string& consumerTag){
return consumers.find(consumerTag) != consumers.end();
}
-namespace {
- const std::string SEPARATOR("::");
-}
-
-void SemanticState::consume(const string& tag,
+void SemanticState::consume(const string& tag,
Queue::shared_ptr queue, bool ackRequired, bool acquire,
bool exclusive, const string& resumeId, uint64_t resumeTtl, const FieldTable& arguments)
{
- // "tag" is only guaranteed to be unique to this session (see AMQP 0-10 Message.subscribe, destination).
- // Create a globally unique name so the broker can identify individual consumers
- std::string name = session.getSessionId().str() + SEPARATOR + tag;
- ConsumerImpl::shared_ptr c(new ConsumerImpl(this, name, queue, ackRequired, acquire, exclusive, tag, resumeId, resumeTtl, arguments));
+ ConsumerImpl::shared_ptr c(new ConsumerImpl(this, tag, queue, ackRequired, acquire, exclusive, resumeId, resumeTtl, arguments));
queue->consume(c, exclusive);//may throw exception
consumers[tag] = c;
}
-bool SemanticState::cancel(const string& tag)
-{
+void SemanticState::cancel(const string& tag){
ConsumerImplMap::iterator i = consumers.find(tag);
if (i != consumers.end()) {
cancel(i->second);
@@ -130,13 +124,7 @@ bool SemanticState::cancel(const string& tag)
//should cancel all unacked messages for this consumer so that
//they are not redelivered on recovery
for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::cancel, _1, tag));
- //can also remove any records that are now redundant
- DeliveryRecords::iterator removed =
- remove_if(unacked.begin(), unacked.end(), bind(&DeliveryRecord::isRedundant, _1));
- unacked.erase(removed, unacked.end());
- return true;
- } else {
- return false;
+
}
}
@@ -179,8 +167,8 @@ void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join)
if (!dtxSelected) {
throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx"));
}
- dtxBuffer.reset(new DtxBuffer(xid));
- txBuffer = dtxBuffer;
+ dtxBuffer = DtxBuffer::shared_ptr(new DtxBuffer(xid));
+ txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer);
if (join) {
mgr.join(xid, dtxBuffer);
} else {
@@ -206,7 +194,7 @@ void SemanticState::endDtx(const std::string& xid, bool fail)
dtxBuffer->fail();
} else {
dtxBuffer->markEnded();
- }
+ }
dtxBuffer.reset();
}
@@ -248,7 +236,7 @@ void SemanticState::resumeDtx(const std::string& xid)
checkDtxTimeout();
dtxBuffer->setSuspended(false);
- txBuffer = dtxBuffer;
+ txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer);
}
void SemanticState::checkDtxTimeout()
@@ -266,33 +254,31 @@ void SemanticState::record(const DeliveryRecord& delivery)
const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency");
-SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
- const string& _name,
- Queue::shared_ptr _queue,
+SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
+ const string& _name,
+ Queue::shared_ptr _queue,
bool ack,
bool _acquire,
bool _exclusive,
- const string& _tag,
const string& _resumeId,
uint64_t _resumeTtl,
const framing::FieldTable& _arguments
-) :
- Consumer(_name, _acquire),
- parent(_parent),
- queue(_queue),
- ackExpected(ack),
+) :
+ Consumer(_acquire),
+ parent(_parent),
+ name(_name),
+ queue(_queue),
+ ackExpected(ack),
acquire(_acquire),
- blocked(true),
+ blocked(true),
windowing(true),
- windowActive(false),
exclusive(_exclusive),
resumeId(_resumeId),
- tag(_tag),
resumeTtl(_resumeTtl),
arguments(_arguments),
- msgCredit(0),
+ msgCredit(0),
byteCredit(0),
notifyEnabled(true),
syncFrequency(_arguments.getAsInt(QPID_SYNC_FREQUENCY)),
@@ -303,10 +289,10 @@ SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent,
{
ManagementAgent* agent = parent->session.getBroker().getManagementAgent();
qpid::management::Manageable* ms = dynamic_cast<qpid::management::Manageable*> (&(parent->session));
-
+
if (agent != 0)
{
- mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId(), getTag(),
+ mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId() ,name,
!acquire, ackExpected, exclusive, ManagementAgent::toMap(arguments));
agent->addObject (mgmtObject);
mgmtObject->set_creditMode("WINDOW");
@@ -338,16 +324,16 @@ bool SemanticState::ConsumerImpl::deliver(QueuedMessage& msg)
{
assertClusterSafe();
allocateCredit(msg.payload);
- DeliveryRecord record(msg, queue, getTag(), acquire, !ackExpected, windowing);
+ DeliveryRecord record(msg, queue, name, acquire, !ackExpected, windowing);
bool sync = syncFrequency && ++deliveryCount >= syncFrequency;
if (sync) deliveryCount = 0;//reset
parent->deliver(record, sync);
+ if (!ackExpected && acquire) record.setEnded();//allows message to be released now its been delivered
if (windowing || ackExpected || !acquire) {
parent->record(record);
- }
- if (acquire && !ackExpected) { // auto acquire && auto accept
- queue->dequeue(0 /*ctxt*/, msg);
- record.setEnded();
+ }
+ if (acquire && !ackExpected) {
+ queue->dequeue(0, msg);
}
if (mgmtObject) { mgmtObject->inc_delivered(); }
return true;
@@ -365,7 +351,7 @@ bool SemanticState::ConsumerImpl::accept(intrusive_ptr<Message> msg)
// checkCredit fails because the message is to big, we should
// remain on queue's listener list for possible smaller messages
// in future.
- //
+ //
blocked = !(filter(msg) && checkCredit(msg));
return !blocked;
}
@@ -377,7 +363,7 @@ struct ConsumerName {
};
ostream& operator<<(ostream& o, const ConsumerName& pc) {
- return o << pc.consumer.getTag() << " on "
+ return o << pc.consumer.getName() << " on "
<< pc.consumer.getParent().getSession().getSessionId();
}
}
@@ -386,7 +372,7 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
{
assertClusterSafe();
uint32_t originalMsgCredit = msgCredit;
- uint32_t originalByteCredit = byteCredit;
+ uint32_t originalByteCredit = byteCredit;
if (msgCredit != 0xFFFFFFFF) {
msgCredit--;
}
@@ -396,7 +382,7 @@ void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg)
QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this)
<< ", was " << " bytes: " << originalByteCredit << " msgs: " << originalMsgCredit
<< " now bytes: " << byteCredit << " msgs: " << msgCredit);
-
+
}
bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg)
@@ -410,7 +396,7 @@ bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg)
return enoughCredit;
}
-SemanticState::ConsumerImpl::~ConsumerImpl()
+SemanticState::ConsumerImpl::~ConsumerImpl()
{
if (mgmtObject != 0)
mgmtObject->resourceDestroy ();
@@ -428,7 +414,7 @@ void SemanticState::unsubscribe(ConsumerImpl::shared_ptr c)
Queue::shared_ptr queue = c->getQueue();
if(queue) {
queue->cancel(c);
- if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) {
+ if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) {
Queue::tryAutoDelete(session.getBroker(), queue);
}
}
@@ -470,23 +456,23 @@ const std::string nullstring;
}
void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) {
- msg->computeExpiration(getSession().getBroker().getExpiryPolicy());
-
+ msg->setTimestamp(getSession().getBroker().getExpiryPolicy());
+
std::string exchangeName = msg->getExchangeName();
- if (!cacheExchange || cacheExchange->getName() != exchangeName || cacheExchange->isDestroyed())
+ if (!cacheExchange || cacheExchange->getName() != exchangeName)
cacheExchange = session.getBroker().getExchanges().get(exchangeName);
cacheExchange->setProperties(msg);
/* verify the userid if specified: */
std::string id =
msg->hasProperties<MessageProperties>() ? msg->getProperties<MessageProperties>()->getUserId() : nullstring;
+
if (authMsg && !id.empty() && !(id == userID || (isDefaultRealm && id == userName)))
{
QPID_LOG(debug, "authorised user id : " << userID << " but user id in message declared as " << id);
throw UnauthorizedAccessException(QPID_MSG("authorised user id : " << userID << " but user id in message declared as " << id));
}
- AclModule* acl = getSession().getBroker().getAcl();
if (acl && acl->doTransferAcl())
{
if (!acl->authorise(getSession().getConnection().getUserId(),acl::ACT_PUBLISH,acl::OBJ_EXCHANGE,exchangeName, msg->getRoutingKey() ))
@@ -498,7 +484,7 @@ void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) {
if (!strategy.delivered) {
//TODO:if discard-unroutable, just drop it
- //TODO:else if accept-mode is explicit, reject it
+ //TODO:else if accept-mode is explicit, reject it
//else route it to alternate exchange
if (cacheExchange->getAlternate()) {
cacheExchange->getAlternate()->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders());
@@ -527,7 +513,7 @@ void SemanticState::ConsumerImpl::requestDispatch()
}
bool SemanticState::complete(DeliveryRecord& delivery)
-{
+{
ConsumerImplMap::iterator i = consumers.find(delivery.getTag());
if (i != consumers.end()) {
i->second->complete(delivery);
@@ -539,7 +525,7 @@ void SemanticState::ConsumerImpl::complete(DeliveryRecord& delivery)
{
if (!delivery.isComplete()) {
delivery.complete();
- if (windowing && windowActive) {
+ if (windowing) {
if (msgCredit != 0xFFFFFFFF) msgCredit++;
if (byteCredit != 0xFFFFFFFF) byteCredit += delivery.getCredit();
}
@@ -555,7 +541,7 @@ void SemanticState::recover(bool requeue)
unacked.clear();
for_each(copy.rbegin(), copy.rend(), mem_fun_ref(&DeliveryRecord::requeue));
}else{
- for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this));
+ for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this));
//unconfirmed messages re redelivered and therefore have their
//id adjusted, confirmed messages are not and so the ordering
//w.r.t id is lost
@@ -568,61 +554,50 @@ void SemanticState::deliver(DeliveryRecord& msg, bool sync)
return deliveryAdapter.deliver(msg, sync);
}
-const SemanticState::ConsumerImpl::shared_ptr SemanticState::find(const std::string& destination) const
-{
- ConsumerImpl::shared_ptr consumer;
- if (!find(destination, consumer)) {
- throw NotFoundException(QPID_MSG("Unknown destination " << destination << " session=" << session.getSessionId()));
- } else {
- return consumer;
- }
-}
-
-bool SemanticState::find(const std::string& destination, ConsumerImpl::shared_ptr& consumer) const
+SemanticState::ConsumerImpl& SemanticState::find(const std::string& destination)
{
- // @todo KAG gsim: shouldn't the consumers map be locked????
- ConsumerImplMap::const_iterator i = consumers.find(destination);
+ ConsumerImplMap::iterator i = consumers.find(destination);
if (i == consumers.end()) {
- return false;
+ throw NotFoundException(QPID_MSG("Unknown destination " << destination));
+ } else {
+ return *(i->second);
}
- consumer = i->second;
- return true;
}
void SemanticState::setWindowMode(const std::string& destination)
{
- find(destination)->setWindowMode();
+ find(destination).setWindowMode();
}
void SemanticState::setCreditMode(const std::string& destination)
{
- find(destination)->setCreditMode();
+ find(destination).setCreditMode();
}
void SemanticState::addByteCredit(const std::string& destination, uint32_t value)
{
- ConsumerImpl::shared_ptr c = find(destination);
- c->addByteCredit(value);
- c->requestDispatch();
+ ConsumerImpl& c = find(destination);
+ c.addByteCredit(value);
+ c.requestDispatch();
}
void SemanticState::addMessageCredit(const std::string& destination, uint32_t value)
{
- ConsumerImpl::shared_ptr c = find(destination);
- c->addMessageCredit(value);
- c->requestDispatch();
+ ConsumerImpl& c = find(destination);
+ c.addMessageCredit(value);
+ c.requestDispatch();
}
void SemanticState::flush(const std::string& destination)
{
- find(destination)->flush();
+ find(destination).flush();
}
void SemanticState::stop(const std::string& destination)
{
- find(destination)->stop();
+ find(destination).stop();
}
void SemanticState::ConsumerImpl::setWindowMode()
@@ -646,7 +621,6 @@ void SemanticState::ConsumerImpl::setCreditMode()
void SemanticState::ConsumerImpl::addByteCredit(uint32_t value)
{
assertClusterSafe();
- if (windowing) windowActive = true;
if (byteCredit != 0xFFFFFFFF) {
if (value == 0xFFFFFFFF) byteCredit = value;
else byteCredit += value;
@@ -656,7 +630,6 @@ void SemanticState::ConsumerImpl::addByteCredit(uint32_t value)
void SemanticState::ConsumerImpl::addMessageCredit(uint32_t value)
{
assertClusterSafe();
- if (windowing) windowActive = true;
if (msgCredit != 0xFFFFFFFF) {
if (value == 0xFFFFFFFF) msgCredit = value;
else msgCredit += value;
@@ -677,8 +650,7 @@ void SemanticState::ConsumerImpl::flush()
{
while(haveCredit() && queue->dispatch(shared_from_this()))
;
- msgCredit = 0;
- byteCredit = 0;
+ stop();
}
void SemanticState::ConsumerImpl::stop()
@@ -686,7 +658,6 @@ void SemanticState::ConsumerImpl::stop()
assertClusterSafe();
msgCredit = 0;
byteCredit = 0;
- windowActive = false;
}
Queue::shared_ptr SemanticState::getQueue(const string& name) const {
@@ -702,7 +673,7 @@ Queue::shared_ptr SemanticState::getQueue(const string& name) const {
}
AckRange SemanticState::findRange(DeliveryId first, DeliveryId last)
-{
+{
return DeliveryRecord::findRange(unacked, first, last);
}
@@ -720,21 +691,14 @@ void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedeliver
DeliveryRecords::reverse_iterator start(range.end);
DeliveryRecords::reverse_iterator end(range.start);
for_each(start, end, boost::bind(&DeliveryRecord::release, _1, setRedelivered));
-
- DeliveryRecords::iterator removed =
- remove_if(range.start, range.end, bind(&DeliveryRecord::isRedundant, _1));
- unacked.erase(removed, range.end);
}
void SemanticState::reject(DeliveryId first, DeliveryId last)
{
AckRange range = findRange(first, last);
for_each(range.start, range.end, mem_fun_ref(&DeliveryRecord::reject));
- //may need to remove the delivery records as well
- for (DeliveryRecords::iterator i = range.start; i != unacked.end() && i->getId() <= last; ) {
- if (i->isRedundant()) i = unacked.erase(i);
- else i++;
- }
+ //need to remove the delivery records as well
+ unacked.erase(range.start, range.end);
}
bool SemanticState::ConsumerImpl::doOutput()
@@ -797,13 +761,13 @@ void SemanticState::accepted(const SequenceSet& commands) {
//in transactional mode, don't dequeue or remove, just
//maintain set of acknowledged messages:
accumulatedAck.add(commands);
-
+
if (dtxBuffer.get()) {
//if enlisted in a dtx, copy the relevant slice from
//unacked and record it against that transaction
TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, unacked));
accumulatedAck.clear();
- dtxBuffer->enlist(txAck);
+ dtxBuffer->enlist(txAck);
//mark the relevant messages as 'ended' in unacked
//if the messages are already completed, they can be
@@ -825,6 +789,7 @@ void SemanticState::accepted(const SequenceSet& commands) {
}
void SemanticState::completed(const SequenceSet& commands) {
+ assertClusterSafe();
DeliveryRecords::iterator removed =
remove_if(unacked.begin(), unacked.end(),
isInSequenceSetAnd(commands,
@@ -835,6 +800,7 @@ void SemanticState::completed(const SequenceSet& commands) {
void SemanticState::attached()
{
+ assertClusterSafe();
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
i->second->enableNotify();
session.getConnection().outputTasks.addOutputTask(i->second.get());
@@ -844,6 +810,7 @@ void SemanticState::attached()
void SemanticState::detached()
{
+ assertClusterSafe();
for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) {
i->second->disableNotify();
session.getConnection().outputTasks.removeOutputTask(i->second.get());
diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h
index 6d88dd56d9..b2e648410a 100644
--- a/cpp/src/qpid/broker/SemanticState.h
+++ b/cpp/src/qpid/broker/SemanticState.h
@@ -65,7 +65,7 @@ class SessionContext;
*
* Message delivery is driven by ConsumerImpl::doOutput(), which is
* called when a client's socket is ready to write data.
- *
+ *
*/
class SemanticState : private boost::noncopyable {
public:
@@ -75,15 +75,14 @@ class SemanticState : private boost::noncopyable {
{
mutable qpid::sys::Mutex lock;
SemanticState* const parent;
+ const std::string name;
const boost::shared_ptr<Queue> queue;
const bool ackExpected;
const bool acquire;
bool blocked;
bool windowing;
- bool windowActive;
bool exclusive;
std::string resumeId;
- const std::string tag; // <destination> from AMQP 0-10 Message.subscribe command
uint64_t resumeTtl;
framing::FieldTable arguments;
uint32_t msgCredit;
@@ -100,16 +99,15 @@ class SemanticState : private boost::noncopyable {
public:
typedef boost::shared_ptr<ConsumerImpl> shared_ptr;
- ConsumerImpl(SemanticState* parent,
+ ConsumerImpl(SemanticState* parent,
const std::string& name, boost::shared_ptr<Queue> queue,
bool ack, bool acquire, bool exclusive,
- const std::string& tag, const std::string& resumeId,
- uint64_t resumeTtl, const framing::FieldTable& arguments);
+ const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments);
~ConsumerImpl();
OwnershipToken* getSession();
- bool deliver(QueuedMessage& msg);
- bool filter(boost::intrusive_ptr<Message> msg);
- bool accept(boost::intrusive_ptr<Message> msg);
+ bool deliver(QueuedMessage& msg);
+ bool filter(boost::intrusive_ptr<Message> msg);
+ bool accept(boost::intrusive_ptr<Message> msg);
void disableNotify();
void enableNotify();
@@ -124,13 +122,15 @@ class SemanticState : private boost::noncopyable {
void addMessageCredit(uint32_t value);
void flush();
void stop();
- void complete(DeliveryRecord&);
+ void complete(DeliveryRecord&);
boost::shared_ptr<Queue> getQueue() const { return queue; }
bool isBlocked() const { return blocked; }
bool setBlocked(bool set) { std::swap(set, blocked); return set; }
bool doOutput();
+ std::string getName() const { return name; }
+
bool isAckExpected() const { return ackExpected; }
bool isAcquire() const { return acquire; }
bool isWindowing() const { return windowing; }
@@ -138,7 +138,6 @@ class SemanticState : private boost::noncopyable {
uint32_t getMsgCredit() const { return msgCredit; }
uint32_t getByteCredit() const { return byteCredit; }
std::string getResumeId() const { return resumeId; };
- const std::string& getTag() const { return tag; }
uint64_t getResumeTtl() const { return resumeTtl; }
const framing::FieldTable& getArguments() const { return arguments; }
@@ -149,10 +148,9 @@ class SemanticState : private boost::noncopyable {
management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text);
};
- typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap;
-
private:
typedef std::map<std::string, ConsumerImpl::shared_ptr> ConsumerImplMap;
+ typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap;
SessionContext& session;
DeliveryAdapter& deliveryAdapter;
@@ -165,6 +163,7 @@ class SemanticState : private boost::noncopyable {
DtxBufferMap suspendedXids;
framing::SequenceSet accumulatedAck;
boost::shared_ptr<Exchange> cacheExchange;
+ AclModule* acl;
const bool authMsg;
const std::string userID;
const std::string userName;
@@ -182,16 +181,14 @@ class SemanticState : private boost::noncopyable {
void disable(ConsumerImpl::shared_ptr);
public:
-
SemanticState(DeliveryAdapter&, SessionContext&);
~SemanticState();
SessionContext& getSession() { return session; }
const SessionContext& getSession() const { return session; }
- const ConsumerImpl::shared_ptr find(const std::string& destination) const;
- bool find(const std::string& destination, ConsumerImpl::shared_ptr&) const;
-
+ ConsumerImpl& find(const std::string& destination);
+
/**
* Get named queue, never returns 0.
* @return: named queue
@@ -199,16 +196,16 @@ class SemanticState : private boost::noncopyable {
* @exception: ConnectionException if name="" and session has no default.
*/
boost::shared_ptr<Queue> getQueue(const std::string& name) const;
-
+
bool exists(const std::string& consumerTag);
- void consume(const std::string& destination,
- boost::shared_ptr<Queue> queue,
+ void consume(const std::string& destination,
+ boost::shared_ptr<Queue> queue,
bool ackRequired, bool acquire, bool exclusive,
const std::string& resumeId=std::string(), uint64_t resumeTtl=0,
const framing::FieldTable& = framing::FieldTable());
- bool cancel(const std::string& tag);
+ void cancel(const std::string& tag);
void setWindowMode(const std::string& destination);
void setCreditMode(const std::string& destination);
@@ -221,13 +218,12 @@ class SemanticState : private boost::noncopyable {
void commit(MessageStore* const store);
void rollback();
void selectDtx();
- bool getDtxSelected() const { return dtxSelected; }
void startDtx(const std::string& xid, DtxManager& mgr, bool join);
void endDtx(const std::string& xid, bool fail);
void suspendDtx(const std::string& xid);
void resumeDtx(const std::string& xid);
void recover(bool requeue);
- void deliver(DeliveryRecord& message, bool sync);
+ void deliver(DeliveryRecord& message, bool sync);
void acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired);
void release(DeliveryId first, DeliveryId last, bool setRedelivered);
void reject(DeliveryId first, DeliveryId last);
@@ -248,12 +244,9 @@ class SemanticState : private boost::noncopyable {
DeliveryRecords& getUnacked() { return unacked; }
framing::SequenceSet getAccumulatedAck() const { return accumulatedAck; }
TxBuffer::shared_ptr getTxBuffer() const { return txBuffer; }
- DtxBuffer::shared_ptr getDtxBuffer() const { return dtxBuffer; }
void setTxBuffer(const TxBuffer::shared_ptr& txb) { txBuffer = txb; }
- void setDtxBuffer(const DtxBuffer::shared_ptr& dtxb) { dtxBuffer = dtxb; txBuffer = dtxb; }
void setAccumulatedAck(const framing::SequenceSet& s) { accumulatedAck = s; }
void record(const DeliveryRecord& delivery);
- DtxBufferMap& getSuspendedXids() { return suspendedXids; }
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionAdapter.cpp b/cpp/src/qpid/broker/SessionAdapter.cpp
index 63c4b660b2..3d62e73185 100644
--- a/cpp/src/qpid/broker/SessionAdapter.cpp
+++ b/cpp/src/qpid/broker/SessionAdapter.cpp
@@ -24,7 +24,6 @@
#include "qpid/log/Statement.h"
#include "qpid/framing/SequenceSet.h"
#include "qpid/management/ManagementAgent.h"
-#include "qpid/broker/SessionState.h"
#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h"
#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h"
#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h"
@@ -65,56 +64,53 @@ void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const
const string& alternateExchange,
bool passive, bool durable, bool /*autoDelete*/, const FieldTable& args){
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_TYPE, type));
+ params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
+ params.insert(make_pair(acl::PROP_PASSIVE, std::string(passive ? _TRUE : _FALSE) ));
+ params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE)));
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,&params) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange declare request from " << getConnection().getUserId()));
+ }
+
//TODO: implement autoDelete
Exchange::shared_ptr alternate;
if (!alternateExchange.empty()) {
alternate = getBroker().getExchanges().get(alternateExchange);
}
if(passive){
- AclModule* acl = getBroker().getAcl();
- if (acl) {
- //TODO: why does a passive declare require create
- //permission? The purpose of the passive flag is to state
- //that the exchange should *not* created. For
- //authorisation a passive declare is similar to
- //exchange-query.
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_TYPE, type));
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _TRUE));
- params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE));
- if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,&params) )
- throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << getConnection().getUserId()));
- }
Exchange::shared_ptr actual(getBroker().getExchanges().get(exchange));
checkType(actual, type);
checkAlternate(actual, alternate);
- }else{
+ }else{
if(exchange.find("amq.") == 0 || exchange.find("qpid.") == 0) {
throw framing::NotAllowedException(QPID_MSG("Exchange names beginning with \"amq.\" or \"qpid.\" are reserved. (exchange=\"" << exchange << "\")"));
}
try{
- std::pair<Exchange::shared_ptr, bool> response =
- getBroker().createExchange(exchange, type, durable, alternateExchange, args,
- getConnection().getUserId(), getConnection().getUrl());
- if (!response.second) {
- //exchange already there, not created
+ std::pair<Exchange::shared_ptr, bool> response = getBroker().getExchanges().declare(exchange, type, durable, args);
+ if (response.second) {
+ if (alternate) {
+ response.first->setAlternate(alternate);
+ alternate->incAlternateUsers();
+ }
+ if (durable) {
+ getBroker().getStore().create(*response.first, args);
+ }
+ } else {
checkType(response.first, type);
checkAlternate(response.first, alternate);
- ManagementAgent* agent = getBroker().getManagementAgent();
- if (agent)
- agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(),
- getConnection().getUserId(),
- exchange,
- type,
- alternateExchange,
- durable,
- false,
- ManagementAgent::toMap(args),
- "existing"));
}
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(), getConnection().getUserId(), exchange, type,
+ alternateExchange, durable, false, ManagementAgent::toMap(args),
+ response.second ? "created" : "existing"));
+
}catch(UnknownExchangeTypeException& /*e*/){
- throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type));
+ throw CommandInvalidException(QPID_MSG("Exchange type not implemented: " << type));
}
}
}
@@ -138,8 +134,22 @@ void SessionAdapter::ExchangeHandlerImpl::checkAlternate(Exchange::shared_ptr ex
void SessionAdapter::ExchangeHandlerImpl::delete_(const string& name, bool /*ifUnused*/)
{
- //TODO: implement if-unused
- getBroker().deleteExchange(name, getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << getConnection().getUserId()));
+ }
+
+ //TODO: implement unused
+ Exchange::shared_ptr exchange(getBroker().getExchanges().get(name));
+ if (exchange->inUseAsAlternate()) throw NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange."));
+ if (exchange->isDurable()) getBroker().getStore().destroy(*exchange);
+ if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers();
+ getBroker().getExchanges().destroy(name);
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventExchangeDelete(getConnection().getUrl(), getConnection().getUserId(), name));
}
ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& name)
@@ -159,19 +169,67 @@ ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& nam
}
void SessionAdapter::ExchangeHandlerImpl::bind(const string& queueName,
- const string& exchangeName, const string& routingKey,
- const FieldTable& arguments)
+ const string& exchangeName, const string& routingKey,
+ const FieldTable& arguments)
{
- getBroker().bind(queueName, exchangeName, routingKey, arguments,
- getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
+ params.insert(make_pair(acl::PROP_ROUTINGKEY, routingKey));
+
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,&params))
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr queue = getQueue(queueName);
+ Exchange::shared_ptr exchange = getBroker().getExchanges().get(exchangeName);
+ if(exchange){
+ string exchangeRoutingKey = routingKey.empty() && queueName.empty() ? queue->getName() : routingKey;
+ if (exchange->bind(queue, exchangeRoutingKey, &arguments)) {
+ queue->bound(exchangeName, routingKey, arguments);
+ if (exchange->isDurable() && queue->isDurable()) {
+ getBroker().getStore().bind(*exchange, *queue, routingKey, arguments);
+ }
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventBind(getConnection().getUrl(), getConnection().getUserId(), exchangeName,
+ queueName, exchangeRoutingKey, ManagementAgent::toMap(arguments)));
+ }
+ }else{
+ throw NotFoundException("Bind failed. No such exchange: " + exchangeName);
+ }
}
void SessionAdapter::ExchangeHandlerImpl::unbind(const string& queueName,
const string& exchangeName,
const string& routingKey)
{
- getBroker().unbind(queueName, exchangeName, routingKey,
- getConnection().getUserId(), getConnection().getUrl());
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_QUEUENAME, queueName));
+ params.insert(make_pair(acl::PROP_ROUTINGKEY, routingKey));
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,&params) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr queue = getQueue(queueName);
+ if (!queue.get()) throw NotFoundException("Unbind failed. No such exchange: " + exchangeName);
+
+ Exchange::shared_ptr exchange = getBroker().getExchanges().get(exchangeName);
+ if (!exchange.get()) throw NotFoundException("Unbind failed. No such exchange: " + exchangeName);
+
+ //TODO: revise unbind to rely solely on binding key (not args)
+ if (exchange->unbind(queue, routingKey, 0)) {
+ if (exchange->isDurable() && queue->isDurable())
+ getBroker().getStore().unbind(*exchange, *queue, routingKey, FieldTable());
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventUnbind(getConnection().getUrl(), getConnection().getUserId(), exchangeName, queueName, routingKey));
+ }
}
ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string& exchangeName,
@@ -274,42 +332,52 @@ QueueQueryResult SessionAdapter::QueueHandlerImpl::query(const string& name)
void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string& alternateExchange,
bool passive, bool durable, bool exclusive,
bool autoDelete, const qpid::framing::FieldTable& arguments)
-{
+{
+ AclModule* acl = getBroker().getAcl();
+ if (acl) {
+ std::map<acl::Property, std::string> params;
+ params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
+ params.insert(make_pair(acl::PROP_PASSIVE, std::string(passive ? _TRUE : _FALSE) ));
+ params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE)));
+ params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE)));
+ params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE)));
+ params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type")));
+ params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count"))));
+ params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size"))));
+
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,&params) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId()));
+ }
+
+ Exchange::shared_ptr alternate;
+ if (!alternateExchange.empty()) {
+ alternate = getBroker().getExchanges().get(alternateExchange);
+ }
Queue::shared_ptr queue;
if (passive && !name.empty()) {
- AclModule* acl = getBroker().getAcl();
- if (acl) {
- //TODO: why does a passive declare require create
- //permission? The purpose of the passive flag is to state
- //that the queue should *not* created. For
- //authorisation a passive declare is similar to
- //queue-query (or indeed a qmf query).
- std::map<acl::Property, std::string> params;
- params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
- params.insert(make_pair(acl::PROP_PASSIVE, _TRUE));
- params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE)));
- params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE)));
- params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE)));
- params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type")));
- params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count"))));
- params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size"))));
- if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,&params) )
- throw UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId()));
- }
- queue = getQueue(name);
+ queue = getQueue(name);
//TODO: check alternate-exchange is as expected
} else {
- std::pair<Queue::shared_ptr, bool> queue_created =
- getBroker().createQueue(name, durable,
- autoDelete,
- exclusive ? &session : 0,
- alternateExchange,
- arguments,
- getConnection().getUserId(),
- getConnection().getUrl());
+ std::pair<Queue::shared_ptr, bool> queue_created =
+ getBroker().getQueues().declare(name, durable,
+ autoDelete,
+ exclusive ? &session : 0);
queue = queue_created.first;
assert(queue);
if (queue_created.second) { // This is a new queue
+ if (alternate) {
+ queue->setAlternateExchange(alternate);
+ alternate->incAlternateUsers();
+ }
+
+ //apply settings & create persistent record if required
+ try { queue_created.first->create(arguments); }
+ catch (...) { getBroker().getQueues().destroy(name); throw; }
+
+ //add default binding:
+ getBroker().getExchanges().getDefault()->bind(queue, name, 0);
+ queue->bound(getBroker().getExchanges().getDefault()->getName(), name, arguments);
+
//handle automatic cleanup:
if (exclusive) {
exclusiveQueues.push_back(queue);
@@ -318,20 +386,21 @@ void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string&
if (exclusive && queue->setExclusiveOwner(&session)) {
exclusiveQueues.push_back(queue);
}
- ManagementAgent* agent = getBroker().getManagementAgent();
- if (agent)
- agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(),
- name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments),
- "existing"));
}
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(),
+ name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments),
+ queue_created.second ? "created" : "existing"));
}
- if (exclusive && !queue->isExclusiveOwner(&session))
+ if (exclusive && !queue->isExclusiveOwner(&session))
throw ResourceLockedException(QPID_MSG("Cannot grant exclusive access to queue "
<< queue->getName()));
-}
-
+}
+
+
void SessionAdapter::QueueHandlerImpl::purge(const string& queue){
AclModule* acl = getBroker().getAcl();
if (acl)
@@ -340,32 +409,40 @@ void SessionAdapter::QueueHandlerImpl::purge(const string& queue){
throw UnauthorizedAccessException(QPID_MSG("ACL denied queue purge request from " << getConnection().getUserId()));
}
getQueue(queue)->purge();
-}
+}
+
+void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty){
-void SessionAdapter::QueueHandlerImpl::checkDelete(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty)
-{
- if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session)) {
+ AclModule* acl = getBroker().getAcl();
+ if (acl)
+ {
+ if (!acl->authorise(getConnection().getUserId(),acl::ACT_DELETE,acl::OBJ_QUEUE,queue,NULL) )
+ throw UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << getConnection().getUserId()));
+ }
+
+ Queue::shared_ptr q = getQueue(queue);
+ if (q->hasExclusiveOwner() && !q->isExclusiveOwner(&session))
throw ResourceLockedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; it is exclusive to another session"));
- } else if(ifEmpty && queue->getMessageCount() > 0) {
- throw PreconditionFailedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; queue not empty"));
- } else if(ifUnused && queue->getConsumerCount() > 0) {
- throw PreconditionFailedException(QPID_MSG("Cannot delete queue "
- << queue->getName() << "; queue in use"));
- } else if (queue->isExclusiveOwner(&session)) {
+ << queue << "; it is exclusive to another session"));
+ if(ifEmpty && q->getMessageCount() > 0){
+ throw PreconditionFailedException("Queue not empty.");
+ }else if(ifUnused && q->getConsumerCount() > 0){
+ throw PreconditionFailedException("Queue in use.");
+ }else{
//remove the queue from the list of exclusive queues if necessary
- QueueVector::iterator i = std::find(exclusiveQueues.begin(),
- exclusiveQueues.end(),
- queue);
- if (i < exclusiveQueues.end()) exclusiveQueues.erase(i);
- }
-}
-
-void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty)
-{
- getBroker().deleteQueue(queue, getConnection().getUserId(), getConnection().getUrl(),
- boost::bind(&SessionAdapter::QueueHandlerImpl::checkDelete, this, _1, ifUnused, ifEmpty));
+ if(q->isExclusiveOwner(&getConnection())){
+ QueueVector::iterator i = std::find(getConnection().exclusiveQueues.begin(), getConnection().exclusiveQueues.end(), q);
+ if(i < getConnection().exclusiveQueues.end()) getConnection().exclusiveQueues.erase(i);
+ }
+ q->destroy();
+ getBroker().getQueues().destroy(queue);
+ q->unbind(getBroker().getExchanges(), q);
+
+ ManagementAgent* agent = getBroker().getManagementAgent();
+ if (agent)
+ agent->raiseEvent(_qmf::EventQueueDelete(getConnection().getUrl(), getConnection().getUserId(), queue));
+ q->notifyDeleted();
+ }
}
SessionAdapter::MessageHandlerImpl::MessageHandlerImpl(SemanticState& s) :
@@ -431,9 +508,7 @@ SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName,
void
SessionAdapter::MessageHandlerImpl::cancel(const string& destination )
{
- if (!state.cancel(destination)) {
- throw NotFoundException(QPID_MSG("No such subscription: " << destination));
- }
+ state.cancel(destination);
ManagementAgent* agent = getBroker().getManagementAgent();
if (agent)
@@ -512,12 +587,7 @@ framing::MessageResumeResult SessionAdapter::MessageHandlerImpl::resume(const st
-void SessionAdapter::ExecutionHandlerImpl::sync()
-{
- session.addPendingExecutionSync();
- /** @todo KAG - need a generic mechanism to allow a command to returning "not completed" status back to SessionState */
-
-}
+void SessionAdapter::ExecutionHandlerImpl::sync() {} //essentially a no-op
void SessionAdapter::ExecutionHandlerImpl::result(const SequenceNumber& /*commandId*/, const string& /*value*/)
{
diff --git a/cpp/src/qpid/broker/SessionAdapter.h b/cpp/src/qpid/broker/SessionAdapter.h
index 8987c4812f..ca27fb6e1d 100644
--- a/cpp/src/qpid/broker/SessionAdapter.h
+++ b/cpp/src/qpid/broker/SessionAdapter.h
@@ -138,7 +138,6 @@ class Queue;
bool isLocal(const ConnectionToken* t) const;
void destroyExclusiveQueues();
- void checkDelete(boost::shared_ptr<Queue> queue, bool ifUnused, bool ifEmpty);
template <class F> void eachExclusiveQueue(F f)
{
std::for_each(exclusiveQueues.begin(), exclusiveQueues.end(), f);
diff --git a/cpp/src/qpid/broker/SessionContext.h b/cpp/src/qpid/broker/SessionContext.h
index 253ce8dcf2..afbbb2cc22 100644
--- a/cpp/src/qpid/broker/SessionContext.h
+++ b/cpp/src/qpid/broker/SessionContext.h
@@ -46,7 +46,6 @@ class SessionContext : public OwnershipToken, public sys::OutputControl
virtual Broker& getBroker() = 0;
virtual uint16_t getChannel() const = 0;
virtual const SessionId& getSessionId() const = 0;
- virtual void addPendingExecutionSync() = 0;
};
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionHandler.cpp b/cpp/src/qpid/broker/SessionHandler.cpp
index 752fa55535..69b364ad7b 100644
--- a/cpp/src/qpid/broker/SessionHandler.cpp
+++ b/cpp/src/qpid/broker/SessionHandler.cpp
@@ -40,6 +40,11 @@ SessionHandler::SessionHandler(Connection& c, ChannelId ch)
SessionHandler::~SessionHandler() {}
+namespace {
+ClassId classId(AMQMethodBody* m) { return m ? m->amqpMethodId() : 0; }
+MethodId methodId(AMQMethodBody* m) { return m ? m->amqpClassId() : 0; }
+} // namespace
+
void SessionHandler::connectionException(framing::connection::CloseCode code, const std::string& msg) {
// NOTE: must tell the error listener _before_ calling connection.close()
if (connection.getErrorListener()) connection.getErrorListener()->connectionError(msg);
diff --git a/cpp/src/qpid/broker/SessionState.cpp b/cpp/src/qpid/broker/SessionState.cpp
index 1ab17e9893..1ca7b6dfc1 100644
--- a/cpp/src/qpid/broker/SessionState.cpp
+++ b/cpp/src/qpid/broker/SessionState.cpp
@@ -25,7 +25,6 @@
#include "qpid/broker/SessionManager.h"
#include "qpid/broker/SessionHandler.h"
#include "qpid/broker/RateFlowcontrol.h"
-#include "qpid/sys/ClusterSafe.h"
#include "qpid/sys/Timer.h"
#include "qpid/framing/AMQContentBody.h"
#include "qpid/framing/AMQHeaderBody.h"
@@ -61,9 +60,9 @@ SessionState::SessionState(
semanticState(*this, *this),
adapter(semanticState),
msgBuilder(&broker.getStore()),
+ enqueuedOp(boost::bind(&SessionState::enqueued, this, _1)),
mgmtObject(0),
- rateFlowcontrol(0),
- asyncCommandCompleter(new AsyncCommandCompleter(this))
+ rateFlowcontrol(0)
{
uint32_t maxRate = broker.getOptions().maxSessionRate;
if (maxRate) {
@@ -96,7 +95,6 @@ void SessionState::addManagementObject() {
}
SessionState::~SessionState() {
- asyncCommandCompleter->cancel();
semanticState.closed();
if (mgmtObject != 0)
mgmtObject->resourceDestroy ();
@@ -127,7 +125,6 @@ bool SessionState::isLocal(const ConnectionToken* t) const
void SessionState::detach() {
QPID_LOG(debug, getId() << ": detached on broker.");
- asyncCommandCompleter->detached();
disableOutput();
handler = 0;
if (mgmtObject != 0)
@@ -148,7 +145,6 @@ void SessionState::attach(SessionHandler& h) {
mgmtObject->set_connectionRef (h.getConnection().GetManagementObject()->getObjectId());
mgmtObject->set_channelId (h.getChannel());
}
- asyncCommandCompleter->attached();
}
void SessionState::abort() {
@@ -206,17 +202,15 @@ Manageable::status_t SessionState::ManagementMethod (uint32_t methodId,
}
void SessionState::handleCommand(framing::AMQMethodBody* method, const SequenceNumber& id) {
- currentCommandComplete = true; // assumed, can be overridden by invoker method (this sucks).
Invoker::Result invocation = invoke(adapter, *method);
- if (currentCommandComplete) receiverCompleted(id);
-
+ receiverCompleted(id);
if (!invocation.wasHandled()) {
throw NotImplementedException(QPID_MSG("Not implemented: " << *method));
} else if (invocation.hasResult()) {
getProxy().getExecution().result(id, invocation.getResult());
}
-
- if (method->isSync() && currentCommandComplete) {
+ if (method->isSync()) {
+ incomplete.process(enqueuedOp, true);
sendAcceptAndCompletion();
}
}
@@ -259,14 +253,23 @@ void SessionState::handleContent(AMQFrame& frame, const SequenceNumber& id)
header.setEof(false);
msg->getFrames().append(header);
}
- if (broker.isTimestamping())
- msg->setTimestamp();
msg->setPublisher(&getConnection());
- msg->getIngressCompletion().begin();
semanticState.handle(msg);
msgBuilder.end();
- IncompleteIngressMsgXfer xfer(this, msg);
- msg->getIngressCompletion().end(xfer); // allows msg to complete xfer
+
+ if (msg->isEnqueueComplete()) {
+ enqueued(msg);
+ } else {
+ incomplete.add(msg);
+ }
+
+ //hold up execution until async enqueue is complete
+ if (msg->getFrames().getMethod()->isSync()) {
+ incomplete.process(enqueuedOp, true);
+ sendAcceptAndCompletion();
+ } else {
+ incomplete.process(enqueuedOp, false);
+ }
}
// Handle producer session flow control
@@ -316,41 +319,11 @@ void SessionState::sendAcceptAndCompletion()
sendCompletion();
}
-/** Invoked when the given inbound message is finished being processed
- * by all interested parties (eg. it is done being enqueued to all queues,
- * its credit has been accounted for, etc). At this point, msg is considered
- * by this receiver as 'completed' (as defined by AMQP 0_10)
- */
-void SessionState::completeRcvMsg(SequenceNumber id,
- bool requiresAccept,
- bool requiresSync)
+void SessionState::enqueued(boost::intrusive_ptr<Message> msg)
{
- // Mark this as a cluster-unsafe scope since it can be called in
- // journal threads or connection threads as part of asynchronous
- // command completion.
- sys::ClusterUnsafeScope cus;
-
- bool callSendCompletion = false;
- receiverCompleted(id);
- if (requiresAccept)
- // will cause msg's seq to appear in the next message.accept we send.
- accepted.add(id);
-
- // Are there any outstanding Execution.Sync commands pending the
- // completion of this msg? If so, complete them.
- while (!pendingExecutionSyncs.empty() &&
- receiverGetIncomplete().front() >= pendingExecutionSyncs.front()) {
- const SequenceNumber id = pendingExecutionSyncs.front();
- pendingExecutionSyncs.pop();
- QPID_LOG(debug, getId() << ": delayed execution.sync " << id << " is completed.");
- receiverCompleted(id);
- callSendCompletion = true; // likely peer is pending for this completion.
- }
-
- // if the sender has requested immediate notification of the completion...
- if (requiresSync || callSendCompletion) {
- sendAcceptAndCompletion();
- }
+ receiverCompleted(msg->getCommandId());
+ if (msg->requiresAccept())
+ accepted.add(msg->getCommandId());
}
void SessionState::handleIn(AMQFrame& frame) {
@@ -423,176 +396,4 @@ framing::AMQP_ClientProxy& SessionState::getClusterOrderProxy() {
return handler->getClusterOrderProxy();
}
-
-// Current received command is an execution.sync command.
-// Complete this command only when all preceding commands have completed.
-// (called via the invoker() in handleCommand() above)
-void SessionState::addPendingExecutionSync()
-{
- SequenceNumber syncCommandId = receiverGetCurrent();
- if (receiverGetIncomplete().front() < syncCommandId) {
- currentCommandComplete = false;
- pendingExecutionSyncs.push(syncCommandId);
- asyncCommandCompleter->flushPendingMessages();
- QPID_LOG(debug, getId() << ": delaying completion of execution.sync " << syncCommandId);
- }
-}
-
-
-/** factory for creating a reference-counted IncompleteIngressMsgXfer object
- * which will be attached to a message that will be completed asynchronously.
- */
-boost::intrusive_ptr<AsyncCompletion::Callback>
-SessionState::IncompleteIngressMsgXfer::clone()
-{
- // Optimization: this routine is *only* invoked when the message needs to be asynchronously completed.
- // If the client is pending the message.transfer completion, flush now to force immediate write to journal.
- if (requiresSync)
- msg->flush();
- else {
- // otherwise, we need to track this message in order to flush it if an execution.sync arrives
- // before it has been completed (see flushPendingMessages())
- pending = true;
- completerContext->addPendingMessage(msg);
- }
-
- return boost::intrusive_ptr<SessionState::IncompleteIngressMsgXfer>(new SessionState::IncompleteIngressMsgXfer(*this));
-}
-
-
-/** Invoked by the asynchronous completer associated with a received
- * msg that is pending Completion. May be invoked by the IO thread
- * (sync == true), or some external thread (!sync).
- */
-void SessionState::IncompleteIngressMsgXfer::completed(bool sync)
-{
- if (pending) completerContext->deletePendingMessage(id);
- if (!sync) {
- /** note well: this path may execute in any thread. It is safe to access
- * the scheduledCompleterContext, since *this has a shared pointer to it.
- * but not session!
- */
- session = 0;
- QPID_LOG(debug, ": async completion callback scheduled for msg seq=" << id);
- completerContext->scheduleMsgCompletion(id, requiresAccept, requiresSync);
- } else {
- // this path runs directly from the ac->end() call in handleContent() above,
- // so *session is definately valid.
- if (session->isAttached()) {
- QPID_LOG(debug, ": receive completed for msg seq=" << id);
- session->completeRcvMsg(id, requiresAccept, requiresSync);
- }
- }
- completerContext = boost::intrusive_ptr<AsyncCommandCompleter>();
-}
-
-
-/** Scheduled from an asynchronous command's completed callback to run on
- * the IO thread.
- */
-void SessionState::AsyncCommandCompleter::schedule(boost::intrusive_ptr<AsyncCommandCompleter> ctxt)
-{
- ctxt->completeCommands();
-}
-
-
-/** Track an ingress message that is pending completion */
-void SessionState::AsyncCommandCompleter::addPendingMessage(boost::intrusive_ptr<Message> msg)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- std::pair<SequenceNumber, boost::intrusive_ptr<Message> > item(msg->getCommandId(), msg);
- bool unique = pendingMsgs.insert(item).second;
- if (!unique) {
- assert(false);
- }
-}
-
-
-/** pending message has completed */
-void SessionState::AsyncCommandCompleter::deletePendingMessage(SequenceNumber id)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- pendingMsgs.erase(id);
-}
-
-
-/** done when an execution.sync arrives */
-void SessionState::AsyncCommandCompleter::flushPendingMessages()
-{
- std::map<SequenceNumber, boost::intrusive_ptr<Message> > copy;
- {
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- pendingMsgs.swap(copy); // we've only tracked these in case a flush is needed, so nuke 'em now.
- }
- // drop lock, so it is safe to call "flush()"
- for (std::map<SequenceNumber, boost::intrusive_ptr<Message> >::iterator i = copy.begin();
- i != copy.end(); ++i) {
- i->second->flush();
- }
-}
-
-
-/** mark an ingress Message.Transfer command as completed.
- * This method must be thread safe - it may run on any thread.
- */
-void SessionState::AsyncCommandCompleter::scheduleMsgCompletion(SequenceNumber cmd,
- bool requiresAccept,
- bool requiresSync)
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
-
- if (session && isAttached) {
- MessageInfo msg(cmd, requiresAccept, requiresSync);
- completedMsgs.push_back(msg);
- if (completedMsgs.size() == 1) {
- session->getConnection().requestIOProcessing(boost::bind(&schedule,
- session->asyncCommandCompleter));
- }
- }
-}
-
-
-/** Cause the session to complete all completed commands.
- * Executes on the IO thread.
- */
-void SessionState::AsyncCommandCompleter::completeCommands()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
-
- // when session is destroyed, it clears the session pointer via cancel().
- if (session && session->isAttached()) {
- for (std::vector<MessageInfo>::iterator msg = completedMsgs.begin();
- msg != completedMsgs.end(); ++msg) {
- session->completeRcvMsg(msg->cmd, msg->requiresAccept, msg->requiresSync);
- }
- }
- completedMsgs.clear();
-}
-
-
-/** cancel any pending calls to scheduleComplete */
-void SessionState::AsyncCommandCompleter::cancel()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- session = 0;
-}
-
-
-/** inform the completer that the session has attached,
- * allows command completion scheduling from any thread */
-void SessionState::AsyncCommandCompleter::attached()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- isAttached = true;
-}
-
-
-/** inform the completer that the session has detached,
- * disables command completion scheduling from any thread */
-void SessionState::AsyncCommandCompleter::detached()
-{
- qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock);
- isAttached = false;
-}
-
}} // namespace qpid::broker
diff --git a/cpp/src/qpid/broker/SessionState.h b/cpp/src/qpid/broker/SessionState.h
index 506af85c47..be79eb0eab 100644
--- a/cpp/src/qpid/broker/SessionState.h
+++ b/cpp/src/qpid/broker/SessionState.h
@@ -30,15 +30,13 @@
#include "qmf/org/apache/qpid/broker/Session.h"
#include "qpid/broker/SessionAdapter.h"
#include "qpid/broker/DeliveryAdapter.h"
-#include "qpid/broker/AsyncCompletion.h"
+#include "qpid/broker/IncompleteMessageList.h"
#include "qpid/broker/MessageBuilder.h"
#include "qpid/broker/SessionContext.h"
#include "qpid/broker/SemanticState.h"
-#include "qpid/sys/Monitor.h"
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
-#include <boost/intrusive_ptr.hpp>
#include <set>
#include <vector>
@@ -125,10 +123,6 @@ class SessionState : public qpid::SessionState,
const SessionId& getSessionId() const { return getId(); }
- // Used by ExecutionHandler sync command processing. Notifies
- // the SessionState of a received Execution.Sync command.
- void addPendingExecutionSync();
-
// Used to delay creation of management object for sessions
// belonging to inter-broker bridges
void addManagementObject();
@@ -136,10 +130,7 @@ class SessionState : public qpid::SessionState,
private:
void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id);
void handleContent(framing::AMQFrame& frame, const framing::SequenceNumber& id);
-
- // indicate that the given ingress msg has been completely received by the
- // broker, and the msg's message.transfer command can be considered completed.
- void completeRcvMsg(SequenceNumber id, bool requiresAccept, bool requiresSync);
+ void enqueued(boost::intrusive_ptr<Message> msg);
void handleIn(framing::AMQFrame& frame);
void handleOut(framing::AMQFrame& frame);
@@ -165,6 +156,8 @@ class SessionState : public qpid::SessionState,
SemanticState semanticState;
SessionAdapter adapter;
MessageBuilder msgBuilder;
+ IncompleteMessageList incomplete;
+ IncompleteMessageList::CompletionListener enqueuedOp;
qmf::org::apache::qpid::broker::Session* mgmtObject;
qpid::framing::SequenceSet accepted;
@@ -173,110 +166,6 @@ class SessionState : public qpid::SessionState,
boost::scoped_ptr<RateFlowcontrol> rateFlowcontrol;
boost::intrusive_ptr<sys::TimerTask> flowControlTimer;
- // sequence numbers for pending received Execution.Sync commands
- std::queue<SequenceNumber> pendingExecutionSyncs;
- bool currentCommandComplete;
-
- /** This class provides a context for completing asynchronous commands in a thread
- * safe manner. Asynchronous commands save their completion state in this class.
- * This class then schedules the completeCommands() method in the IO thread.
- * While running in the IO thread, completeCommands() may safely complete all
- * saved commands without the risk of colliding with other operations on this
- * SessionState.
- */
- class AsyncCommandCompleter : public RefCounted {
- private:
- SessionState *session;
- bool isAttached;
- qpid::sys::Mutex completerLock;
-
- // special-case message.transfer commands for optimization
- struct MessageInfo {
- SequenceNumber cmd; // message.transfer command id
- bool requiresAccept;
- bool requiresSync;
- MessageInfo(SequenceNumber c, bool a, bool s)
- : cmd(c), requiresAccept(a), requiresSync(s) {}
- };
- std::vector<MessageInfo> completedMsgs;
- // If an ingress message does not require a Sync, we need to
- // hold a reference to it in case an Execution.Sync command is received and we
- // have to manually flush the message.
- std::map<SequenceNumber, boost::intrusive_ptr<Message> > pendingMsgs;
-
- /** complete all pending commands, runs in IO thread */
- void completeCommands();
-
- /** for scheduling a run of "completeCommands()" on the IO thread */
- static void schedule(boost::intrusive_ptr<AsyncCommandCompleter>);
-
- public:
- AsyncCommandCompleter(SessionState *s) : session(s), isAttached(s->isAttached()) {};
- ~AsyncCommandCompleter() {};
-
- /** track a message pending ingress completion */
- void addPendingMessage(boost::intrusive_ptr<Message> m);
- void deletePendingMessage(SequenceNumber id);
- void flushPendingMessages();
- /** schedule the processing of a completed ingress message.transfer command */
- void scheduleMsgCompletion(SequenceNumber cmd,
- bool requiresAccept,
- bool requiresSync);
- void cancel(); // called by SessionState destructor.
- void attached(); // called by SessionState on attach()
- void detached(); // called by SessionState on detach()
- };
- boost::intrusive_ptr<AsyncCommandCompleter> asyncCommandCompleter;
-
- /** Abstract class that represents a single asynchronous command that is
- * pending completion.
- */
- class AsyncCommandContext : public AsyncCompletion::Callback
- {
- public:
- AsyncCommandContext( SessionState *ss, SequenceNumber _id )
- : id(_id), completerContext(ss->asyncCommandCompleter) {}
- virtual ~AsyncCommandContext() {}
-
- protected:
- SequenceNumber id;
- boost::intrusive_ptr<AsyncCommandCompleter> completerContext;
- };
-
- /** incomplete Message.transfer commands - inbound to broker from client
- */
- class IncompleteIngressMsgXfer : public SessionState::AsyncCommandContext
- {
- public:
- IncompleteIngressMsgXfer( SessionState *ss,
- boost::intrusive_ptr<Message> m )
- : AsyncCommandContext(ss, m->getCommandId()),
- session(ss),
- msg(m),
- requiresAccept(m->requiresAccept()),
- requiresSync(m->getFrames().getMethod()->isSync()),
- pending(false) {}
- IncompleteIngressMsgXfer( const IncompleteIngressMsgXfer& x )
- : AsyncCommandContext(x.session, x.msg->getCommandId()),
- session(x.session),
- msg(x.msg),
- requiresAccept(x.requiresAccept),
- requiresSync(x.requiresSync),
- pending(x.pending) {}
-
- virtual ~IncompleteIngressMsgXfer() {};
-
- virtual void completed(bool);
- virtual boost::intrusive_ptr<AsyncCompletion::Callback> clone();
-
- private:
- SessionState *session; // only valid if sync flag in callback is true
- boost::intrusive_ptr<Message> msg;
- bool requiresAccept;
- bool requiresSync;
- bool pending; // true if msg saved on pending list...
- };
-
friend class SessionManager;
};
diff --git a/cpp/src/qpid/broker/StatefulQueueObserver.h b/cpp/src/qpid/broker/StatefulQueueObserver.h
deleted file mode 100644
index c682d460b7..0000000000
--- a/cpp/src/qpid/broker/StatefulQueueObserver.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef QPID_BROKER_STATEFULQUEUEOBSERVER_H
-#define QPID_BROKER_STATEFULQUEUEOBSERVER_H
-
-/*
- *
- * 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 "qpid/broker/QueueObserver.h"
-#include "qpid/framing/FieldTable.h"
-
-namespace qpid {
-namespace broker {
-
-/**
- * Specialized type of QueueObserver that maintains internal state that has to
- * be replicated across clustered brokers.
- */
-class StatefulQueueObserver : public QueueObserver
-{
- public:
- StatefulQueueObserver(std::string _id) : id(_id) {}
- virtual ~StatefulQueueObserver() {}
-
- /** This identifier must uniquely identify this particular observer amoung
- * all observers on a queue. For cluster replication, this id will be used
- * to identify the peer queue observer for synchronization across
- * brokers.
- */
- const std::string& getId() const { return id; }
-
- /** This method should return the observer's internal state as an opaque
- * map.
- */
- virtual void getState(qpid::framing::FieldTable& state ) const = 0;
-
- /** The input map represents the internal state of the peer observer that
- * this observer should synchonize to.
- */
- virtual void setState(const qpid::framing::FieldTable&) = 0;
-
-
- private:
- std::string id;
-};
-}} // namespace qpid::broker
-
-#endif /*!QPID_BROKER_STATEFULQUEUEOBSERVER_H*/
diff --git a/cpp/src/qpid/broker/ThresholdAlerts.cpp b/cpp/src/qpid/broker/ThresholdAlerts.cpp
index 3c9e210d4d..4f35884af8 100644
--- a/cpp/src/qpid/broker/ThresholdAlerts.cpp
+++ b/cpp/src/qpid/broker/ThresholdAlerts.cpp
@@ -28,52 +28,6 @@
namespace qpid {
namespace broker {
-namespace {
-const qmf::org::apache::qpid::broker::EventQueueThresholdExceeded EVENT("dummy", 0, 0);
-bool isQMFv2(const boost::intrusive_ptr<Message> message)
-{
- const qpid::framing::MessageProperties* props = message->getProperties<qpid::framing::MessageProperties>();
- return props && props->getAppId() == "qmf2";
-}
-
-bool isThresholdEvent(const boost::intrusive_ptr<Message> message)
-{
- if (message->getIsManagementMessage()) {
- //is this a qmf event? if so is it a threshold event?
- if (isQMFv2(message)) {
- const qpid::framing::FieldTable* headers = message->getApplicationHeaders();
- if (headers && headers->getAsString("qmf.content") == "_event") {
- //decode as list
- std::string content = message->getFrames().getContent();
- qpid::types::Variant::List list;
- qpid::amqp_0_10::ListCodec::decode(content, list);
- if (list.empty() || list.front().getType() != qpid::types::VAR_MAP) return false;
- qpid::types::Variant::Map map = list.front().asMap();
- try {
- std::string eventName = map["_schema_id"].asMap()["_class_name"].asString();
- return eventName == EVENT.getEventName();
- } catch (const std::exception& e) {
- QPID_LOG(error, "Error checking for recursive threshold alert: " << e.what());
- }
- }
- } else {
- std::string content = message->getFrames().getContent();
- qpid::framing::Buffer buffer(const_cast<char*>(content.data()), content.size());
- if (buffer.getOctet() == 'A' && buffer.getOctet() == 'M' && buffer.getOctet() == '2' && buffer.getOctet() == 'e') {
- buffer.getLong();//sequence
- std::string packageName;
- buffer.getShortString(packageName);
- if (packageName != EVENT.getPackageName()) return false;
- std::string eventName;
- buffer.getShortString(eventName);
- return eventName == EVENT.getEventName();
- }
- }
- }
- return false;
-}
-}
-
ThresholdAlerts::ThresholdAlerts(const std::string& n,
qpid::management::ManagementAgent& a,
const uint32_t ct,
@@ -90,14 +44,8 @@ void ThresholdAlerts::enqueued(const QueuedMessage& m)
if ((countThreshold && count >= countThreshold) || (sizeThreshold && size >= sizeThreshold)) {
if ((repeatInterval == 0 && lastAlert == qpid::sys::EPOCH)
|| qpid::sys::Duration(lastAlert, qpid::sys::now()) > repeatInterval) {
- //Note: Raising an event may result in messages being
- //enqueued on queues; it may even be that this event
- //causes a message to be enqueued on the queue we are
- //tracking, and so we need to avoid recursing
- if (isThresholdEvent(m.payload)) return;
- lastAlert = qpid::sys::now();
agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size));
- QPID_LOG(info, "Threshold event triggered for " << name << ", count=" << count << ", size=" << size);
+ lastAlert = qpid::sys::now();
}
}
}
@@ -127,12 +75,12 @@ void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& a
}
void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::framing::FieldTable& settings, uint16_t limitRatio)
+ const qpid::framing::FieldTable& settings)
{
qpid::types::Variant::Map map;
qpid::amqp_0_10::translate(settings, map);
- observe(queue, agent, map, limitRatio);
+ observe(queue, agent, map);
}
template <class T>
@@ -170,19 +118,19 @@ class Option
};
void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::types::Variant::Map& settings, uint16_t limitRatio)
+ const qpid::types::Variant::Map& settings)
{
//Note: aliases are keys defined by java broker
Option<int64_t> repeatInterval("qpid.alert_repeat_gap", 60);
repeatInterval.addAlias("x-qpid-minimum-alert-repeat-gap");
- //If no explicit threshold settings were given use specified
- //percentage of any limit from the policy.
+ //If no explicit threshold settings were given use 80% of any
+ //limit from the policy.
const QueuePolicy* policy = queue.getPolicy();
- Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy && limitRatio ? (policy->getMaxCount()*limitRatio/100) : 0));
+ Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy ? policy->getMaxCount()*0.8 : 0));
countThreshold.addAlias("x-qpid-maximum-message-count");
- Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy && limitRatio ? (policy->getMaxSize()*limitRatio/100) : 0));
+ Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy ? policy->getMaxSize()*0.8 : 0));
sizeThreshold.addAlias("x-qpid-maximum-message-size");
observe(queue, agent, countThreshold.get(settings), sizeThreshold.get(settings), repeatInterval.get(settings));
diff --git a/cpp/src/qpid/broker/ThresholdAlerts.h b/cpp/src/qpid/broker/ThresholdAlerts.h
index 2b4a46b736..e1f59252c4 100644
--- a/cpp/src/qpid/broker/ThresholdAlerts.h
+++ b/cpp/src/qpid/broker/ThresholdAlerts.h
@@ -50,17 +50,14 @@ class ThresholdAlerts : public QueueObserver
const long repeatInterval);
void enqueued(const QueuedMessage&);
void dequeued(const QueuedMessage&);
- void acquired(const QueuedMessage&) {};
- void requeued(const QueuedMessage&) {};
-
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
const uint64_t countThreshold,
const uint64_t sizeThreshold,
const long repeatInterval);
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::framing::FieldTable& settings, uint16_t limitRatio);
+ const qpid::framing::FieldTable& settings);
static void observe(Queue& queue, qpid::management::ManagementAgent& agent,
- const qpid::types::Variant::Map& settings, uint16_t limitRatio);
+ const qpid::types::Variant::Map& settings);
private:
const std::string name;
qpid::management::ManagementAgent& agent;
diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp
index 644a3d628e..1b0fe71bcf 100644
--- a/cpp/src/qpid/broker/TopicExchange.cpp
+++ b/cpp/src/qpid/broker/TopicExchange.cpp
@@ -221,7 +221,6 @@ TopicExchange::TopicExchange(const std::string& _name, bool _durable,
bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args)
{
- ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit.
string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind);
string fedTags(args ? args->getAsString(qpidFedTags) : "");
string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
@@ -250,21 +249,21 @@ bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, cons
if (mgmtExchange != 0) {
mgmtExchange->inc_bindingCount();
}
- QPID_LOG(debug, "Binding key [" << routingPattern << "] to queue " << queue->getName()
- << " on exchange " << getName() << " (origin=" << fedOrigin << ")");
+ QPID_LOG(debug, "Bound key [" << routingPattern << "] to queue " << queue->getName()
+ << " (origin=" << fedOrigin << ")");
}
} else if (fedOp == fedOpUnbind) {
- RWlock::ScopedWlock l(lock);
- BindingKey* bk = getQueueBinding(queue, routingPattern);
- if (bk) {
- QPID_LOG(debug, "FedOpUnbind [" << routingPattern << "] from exchange " << getName()
- << " on queue=" << queue->getName() << " origin=" << fedOrigin);
- propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
- // if this was the last binding for the queue, delete the binding
- if (bk->fedBinding.countFedBindings(queue->getName()) == 0) {
- deleteBinding(queue, routingPattern, bk);
+ bool reallyUnbind = false;
+ {
+ RWlock::ScopedWlock l(lock);
+ BindingKey* bk = bindingTree.getBindingKey(routingPattern);
+ if (bk) {
+ propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
+ reallyUnbind = bk->fedBinding.countFedBindings(queue->getName()) == 0;
}
}
+ if (reallyUnbind)
+ unbind(queue, routingPattern, 0);
} else if (fedOp == fedOpReorigin) {
/** gather up all the keys that need rebinding in a local vector
* while holding the lock. Then propagate once the lock is
@@ -282,38 +281,20 @@ bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, cons
}
}
- cc.clearCache(); // clear the cache before we IVE route.
routeIVE();
if (propagate)
propagateFedOp(routingKey, fedTags, fedOp, fedOrigin);
return true;
}
-bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* args)
-{
- string fedOrigin(args ? args->getAsString(qpidFedOrigin) : "");
- QPID_LOG(debug, "Unbinding key [" << constRoutingKey << "] from queue " << queue->getName()
- << " on exchange " << getName() << " origin=" << fedOrigin << ")" );
-
- ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit.
+bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* /*args*/){
RWlock::ScopedWlock l(lock);
string routingKey = normalize(constRoutingKey);
- BindingKey* bk = getQueueBinding(queue, routingKey);
+ BindingKey* bk = bindingTree.getBindingKey(routingKey);
if (!bk) return false;
- bool propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin);
- deleteBinding(queue, routingKey, bk);
- if (propagate)
- propagateFedOp(routingKey, string(), fedOpUnbind, string());
- return true;
-}
-
-
-bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
- const std::string& routingKey,
- BindingKey *bk)
-{
- // Note well: write lock held by caller
Binding::vector& qv(bk->bindingVector);
+ bool propagate = false;
+
Binding::vector::iterator q;
for (q = qv.begin(); q != qv.end(); q++)
if ((*q)->queue == queue)
@@ -322,55 +303,42 @@ bool TopicExchange::deleteBinding(Queue::shared_ptr queue,
qv.erase(q);
assert(nBindings > 0);
nBindings--;
-
+ propagate = bk->fedBinding.delOrigin();
if(qv.empty()) {
bindingTree.removeBindingKey(routingKey);
}
if (mgmtExchange != 0) {
mgmtExchange->dec_bindingCount();
}
- QPID_LOG(debug, "Unbound key [" << routingKey << "] from queue " << queue->getName()
- << " on exchange " << getName());
+ QPID_LOG(debug, "Unbound [" << routingKey << "] from queue " << queue->getName());
+
+ if (propagate)
+ propagateFedOp(routingKey, string(), fedOpUnbind, string());
return true;
}
-/** returns a pointer to the BindingKey if the given queue is bound to this
- * exchange using the routing pattern. 0 if queue binding does not exist.
- */
-TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern)
+bool TopicExchange::isBound(Queue::shared_ptr queue, const string& pattern)
{
// Note well: lock held by caller....
BindingKey *bk = bindingTree.getBindingKey(pattern); // Exact match against binding pattern
- if (!bk) return 0;
+ if (!bk) return false;
Binding::vector& qv(bk->bindingVector);
Binding::vector::iterator q;
for (q = qv.begin(); q != qv.end(); q++)
if ((*q)->queue == queue)
break;
- return (q != qv.end()) ? bk : 0;
+ return q != qv.end();
}
void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/)
{
// Note: PERFORMANCE CRITICAL!!!
- BindingList b;
- std::map<std::string, BindingList>::iterator it;
- { // only lock the cache for read
- RWlock::ScopedRlock cl(cacheLock);
- it = bindingCache.find(routingKey);
- if (it != bindingCache.end()) {
- b = it->second;
- }
- }
+ BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
PreRoute pr(msg, this);
- if (!b.get()) // no cache hit
+ BindingsFinderIter bindingsFinder(b);
{
RWlock::ScopedRlock l(lock);
- b = BindingList(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >);
- BindingsFinderIter bindingsFinder(b);
bindingTree.iterateMatch(routingKey, bindingsFinder);
- RWlock::ScopedWlock cwl(cacheLock);
- bindingCache[routingKey] = b; // update cache
}
doRoute(msg, b);
}
@@ -380,7 +348,7 @@ bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routing
RWlock::ScopedRlock l(lock);
if (routingKey && queue) {
string key(normalize(*routingKey));
- return getQueueBinding(queue, key) != 0;
+ return isBound(queue, key);
} else if (!routingKey && !queue) {
return nBindings > 0;
} else if (routingKey) {
diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h
index 636918f8a1..a6c457dcb3 100644
--- a/cpp/src/qpid/broker/TopicExchange.h
+++ b/cpp/src/qpid/broker/TopicExchange.h
@@ -56,7 +56,7 @@ class TopicExchange : public virtual Exchange {
// | +-->d-->...
// +-->x-->y-->...
//
- class QPID_BROKER_CLASS_EXTERN BindingNode {
+ class BindingNode {
public:
typedef boost::shared_ptr<BindingNode> shared_ptr;
@@ -135,31 +135,8 @@ class TopicExchange : public virtual Exchange {
BindingNode bindingTree;
unsigned long nBindings;
qpid::sys::RWlock lock; // protects bindingTree and nBindings
- qpid::sys::RWlock cacheLock; // protects cache
- std::map<std::string, BindingList> bindingCache; // cache of matched routes.
- class ClearCache {
- private:
- qpid::sys::RWlock* cacheLock;
- std::map<std::string, BindingList>* bindingCache;
- bool cleared;
- public:
- ClearCache(qpid::sys::RWlock* l, std::map<std::string, BindingList>* bc): cacheLock(l),
- bindingCache(bc),cleared(false) {};
- void clearCache() {
- qpid::sys::RWlock::ScopedWlock l(*cacheLock);
- if (!cleared) {
- bindingCache->clear();
- cleared =true;
- }
- };
- ~ClearCache(){
- clearCache();
- };
- };
- BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern);
- bool deleteBinding(Queue::shared_ptr queue,
- const std::string& routingKey,
- BindingKey *bk);
+
+ bool isBound(Queue::shared_ptr queue, const std::string& pattern);
class ReOriginIter;
class BindingsFinderIter;
diff --git a/cpp/src/qpid/broker/TxBuffer.cpp b/cpp/src/qpid/broker/TxBuffer.cpp
index d92e6ace48..b509778e89 100644
--- a/cpp/src/qpid/broker/TxBuffer.cpp
+++ b/cpp/src/qpid/broker/TxBuffer.cpp
@@ -76,5 +76,5 @@ bool TxBuffer::commitLocal(TransactionalStore* const store)
}
void TxBuffer::accept(TxOpConstVisitor& v) const {
- std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v)));
+ std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v)));
}
diff --git a/cpp/src/qpid/broker/TxPublish.cpp b/cpp/src/qpid/broker/TxPublish.cpp
index 9c2cf4a467..36a451e62c 100644
--- a/cpp/src/qpid/broker/TxPublish.cpp
+++ b/cpp/src/qpid/broker/TxPublish.cpp
@@ -90,7 +90,14 @@ void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){
void TxPublish::prepare(TransactionContext* ctxt, const boost::shared_ptr<Queue> queue)
{
- queue->enqueue(ctxt, msg);
+ if (!queue->enqueue(ctxt, msg)){
+ /**
+ * if not store then mark message for ack and deleivery once
+ * commit happens, as async IO will never set it when no store
+ * exists
+ */
+ msg->enqueueComplete();
+ }
}
TxPublish::Commit::Commit(intrusive_ptr<Message>& _msg) : msg(_msg){}
diff --git a/cpp/src/qpid/broker/TxPublish.h b/cpp/src/qpid/broker/TxPublish.h
index dba7878af2..effa585676 100644
--- a/cpp/src/qpid/broker/TxPublish.h
+++ b/cpp/src/qpid/broker/TxPublish.h
@@ -7,9 +7,9 @@
* 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
@@ -34,58 +34,57 @@
#include <boost/intrusive_ptr.hpp>
namespace qpid {
-namespace broker {
-/**
- * Defines the behaviour for publish operations on a
- * transactional channel. Messages are routed through
- * exchanges when received but are not at that stage delivered
- * to the matching queues, rather the queues are held in an
- * instance of this class. On prepare() the message is marked
- * enqueued to the relevant queues in the MessagesStore. On
- * commit() the messages will be passed to the queue for
- * dispatch or to be added to the in-memory queue.
- */
-class QPID_BROKER_CLASS_EXTERN TxPublish : public TxOp, public Deliverable{
+ namespace broker {
+ /**
+ * Defines the behaviour for publish operations on a
+ * transactional channel. Messages are routed through
+ * exchanges when received but are not at that stage delivered
+ * to the matching queues, rather the queues are held in an
+ * instance of this class. On prepare() the message is marked
+ * enqueued to the relevant queues in the MessagesStore. On
+ * commit() the messages will be passed to the queue for
+ * dispatch or to be added to the in-memory queue.
+ */
+ class TxPublish : public TxOp, public Deliverable{
- class Commit{
- boost::intrusive_ptr<Message>& msg;
- public:
- Commit(boost::intrusive_ptr<Message>& msg);
- void operator()(const boost::shared_ptr<Queue>& queue);
- };
- class Rollback{
- boost::intrusive_ptr<Message>& msg;
- public:
- Rollback(boost::intrusive_ptr<Message>& msg);
- void operator()(const boost::shared_ptr<Queue>& queue);
- };
+ class Commit{
+ boost::intrusive_ptr<Message>& msg;
+ public:
+ Commit(boost::intrusive_ptr<Message>& msg);
+ void operator()(const boost::shared_ptr<Queue>& queue);
+ };
+ class Rollback{
+ boost::intrusive_ptr<Message>& msg;
+ public:
+ Rollback(boost::intrusive_ptr<Message>& msg);
+ void operator()(const boost::shared_ptr<Queue>& queue);
+ };
- boost::intrusive_ptr<Message> msg;
- std::list<boost::shared_ptr<Queue> > queues;
- std::list<boost::shared_ptr<Queue> > prepared;
+ boost::intrusive_ptr<Message> msg;
+ std::list<boost::shared_ptr<Queue> > queues;
+ std::list<boost::shared_ptr<Queue> > prepared;
- void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>);
+ void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>);
- public:
- QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg);
- QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw();
- QPID_BROKER_EXTERN virtual void commit() throw();
- QPID_BROKER_EXTERN virtual void rollback() throw();
+ public:
+ QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg);
+ QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw();
+ QPID_BROKER_EXTERN virtual void commit() throw();
+ QPID_BROKER_EXTERN virtual void rollback() throw();
- virtual Message& getMessage() { return *msg; };
+ virtual Message& getMessage() { return *msg; };
+
+ QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue);
- QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue);
+ virtual ~TxPublish(){}
+ virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
- virtual ~TxPublish(){}
- virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); }
+ QPID_BROKER_EXTERN uint64_t contentSize();
- QPID_BROKER_EXTERN uint64_t contentSize();
-
- boost::intrusive_ptr<Message> getMessage() const { return msg; }
- const std::list<boost::shared_ptr<Queue> >& getQueues() const { return queues; }
- const std::list<boost::shared_ptr<Queue> >& getPrepared() const { return prepared; }
-};
-}
+ boost::intrusive_ptr<Message> getMessage() const { return msg; }
+ const std::list<boost::shared_ptr<Queue> > getQueues() const { return queues; }
+ };
+ }
}
diff --git a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
index b65440b5ad..b6862f0418 100644
--- a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
+++ b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp
@@ -31,16 +31,10 @@ const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA");
std::string
Broker::Options::getHome() {
std::string home;
-#ifdef _MSC_VER
char home_c[MAX_PATH+1];
size_t unused;
if (0 == getenv_s (&unused, home_c, sizeof(home_c), "HOME"))
home += home_c;
-#else
- char *home_c = getenv("HOME");
- if (home_c)
- home += home_c;
-#endif
return home;
}
diff --git a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
index 2acc09cded..608a8f7dae 100644
--- a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp
@@ -42,7 +42,7 @@ public:
NullAuthenticator(Connection& connection);
~NullAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string&) {}
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -57,7 +57,7 @@ public:
SspiAuthenticator(Connection& connection);
~SspiAuthenticator();
void getMechanisms(framing::Array& mechanisms);
- void start(const std::string& mechanism, const std::string* response);
+ void start(const std::string& mechanism, const std::string& response);
void step(const std::string& response);
std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize);
};
@@ -93,15 +93,14 @@ NullAuthenticator::~NullAuthenticator() {}
void NullAuthenticator::getMechanisms(Array& mechanisms)
{
mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS")));
- mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));
}
-void NullAuthenticator::start(const string& mechanism, const string* response)
+void NullAuthenticator::start(const string& mechanism, const string& response)
{
QPID_LOG(warning, "SASL: No Authentication Performed");
if (mechanism == "PLAIN") { // Old behavior
- if (response && response->size() > 0 && (*response).c_str()[0] == (char) 0) {
- string temp = response->substr(1);
+ if (response.size() > 0 && response[0] == (char) 0) {
+ string temp = response.substr(1);
string::size_type i = temp.find((char)0);
string uid = temp.substr(0, i);
string pwd = temp.substr(i + 1);
@@ -139,7 +138,7 @@ void SspiAuthenticator::getMechanisms(Array& mechanisms)
QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN");
}
-void SspiAuthenticator::start(const string& mechanism, const string* response)
+void SspiAuthenticator::start(const string& mechanism, const string& response)
{
QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism);
if (mechanism == "ANONYMOUS") {
@@ -152,19 +151,16 @@ void SspiAuthenticator::start(const string& mechanism, const string* response)
// PLAIN's response is composed of 3 strings separated by 0 bytes:
// authorization id, authentication id (user), clear-text password.
- if (!response || response->size() == 0)
+ if (response.size() == 0)
throw ConnectionForcedException("Authentication failed");
- string::size_type i = response->find((char)0);
- string auth = response->substr(0, i);
- string::size_type j = response->find((char)0, i+1);
- string uid = response->substr(i+1, j-1);
- string pwd = response->substr(j+1);
- string dot(".");
+ string::size_type i = response.find((char)0);
+ string auth = response.substr(0, i);
+ string::size_type j = response.find((char)0, i+1);
+ string uid = response.substr(i+1, j-1);
+ string pwd = response.substr(j+1);
int error = 0;
- if (!LogonUser(const_cast<char*>(uid.c_str()),
- const_cast<char*>(dot.c_str()),
- const_cast<char*>(pwd.c_str()),
+ if (!LogonUser(uid.c_str(), ".", pwd.c_str(),
LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT,
&userToken))
@@ -180,7 +176,7 @@ void SspiAuthenticator::start(const string& mechanism, const string* response)
client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0);
}
-void SspiAuthenticator::step(const string& /*response*/)
+void SspiAuthenticator::step(const string& response)
{
QPID_LOG(info, "SASL: Need another step!!!");
}
diff --git a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
index 1dff1ddc8f..fd0e537192 100644
--- a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
+++ b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp
@@ -27,14 +27,10 @@
#include "qpid/sys/AsynchIOHandler.h"
#include "qpid/sys/ConnectionCodec.h"
#include "qpid/sys/Socket.h"
-#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/SystemInfo.h"
#include "qpid/sys/windows/SslAsynchIO.h"
-
#include <boost/bind.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
#include <memory>
-
// security.h needs to see this to distinguish from kernel use.
#define SECURITY_WIN32
#include <security.h>
@@ -72,10 +68,9 @@ struct SslServerOptions : qpid::Options
};
class SslProtocolFactory : public qpid::sys::ProtocolFactory {
+ qpid::sys::Socket listener;
const bool tcpNoDelay;
- boost::ptr_vector<Socket> listeners;
- boost::ptr_vector<AsynchAcceptor> acceptors;
- uint16_t listeningPort;
+ const uint16_t listeningPort;
std::string brokerHost;
const bool clientAuthSelected;
std::auto_ptr<qpid::sys::AsynchAcceptor> acceptor;
@@ -83,14 +78,15 @@ class SslProtocolFactory : public qpid::sys::ProtocolFactory {
CredHandle credHandle;
public:
- SslProtocolFactory(const SslServerOptions&, const std::string& host, const std::string& port, int backlog, bool nodelay);
+ SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay);
~SslProtocolFactory();
void accept(sys::Poller::shared_ptr, sys::ConnectionCodec::Factory*);
- void connect(sys::Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(sys::Poller::shared_ptr, const std::string& host, int16_t port,
sys::ConnectionCodec::Factory*,
ConnectFailedCallback failed);
uint16_t getPort() const;
+ std::string getHost() const;
bool supports(const std::string& capability);
private:
@@ -119,7 +115,6 @@ static struct SslPlugin : public Plugin {
try {
const broker::Broker::Options& opts = broker->getOptions();
ProtocolFactory::shared_ptr protocol(new SslProtocolFactory(options,
- "", boost::lexical_cast<std::string>(options.port),
opts.connectionBacklog,
opts.tcpNoDelay));
QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort());
@@ -132,13 +127,12 @@ static struct SslPlugin : public Plugin {
} sslPlugin;
SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
- const std::string& host, const std::string& port, int backlog,
+ int backlog,
bool nodelay)
: tcpNoDelay(nodelay),
+ listeningPort(listener.listen(options.port, backlog)),
clientAuthSelected(options.clientAuth) {
- // Make sure that certificate store is good before listening to sockets
- // to avoid having open and listening sockets when there is no cert store
SecInvalidateHandle(&credHandle);
// Get the certificate for this server.
@@ -183,23 +177,6 @@ SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options,
throw QPID_WINDOWS_ERROR(status);
::CertFreeCertificateContext(certContext);
::CertCloseStore(certStoreHandle, 0);
-
- // Listen to socket(s)
- SocketAddress sa(host, port);
-
- // We must have at least one resolved address
- QPID_LOG(info, "SSL Listening to: " << sa.asString())
- Socket* s = new Socket;
- listeningPort = s->listen(sa, backlog);
- listeners.push_back(s);
-
- // Try any other resolved addresses
- while (sa.nextAddress()) {
- QPID_LOG(info, "SSL Listening to: " << sa.asString())
- Socket* s = new Socket;
- s->listen(sa, backlog);
- listeners.push_back(s);
- }
}
SslProtocolFactory::~SslProtocolFactory() {
@@ -260,19 +237,21 @@ uint16_t SslProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string SslProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void SslProtocolFactory::accept(sys::Poller::shared_ptr poller,
sys::ConnectionCodec::Factory* fact) {
- for (unsigned i = 0; i<listeners.size(); ++i) {
- acceptors.push_back(
- AsynchAcceptor::create(listeners[i],
- boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false)));
- acceptors[i].start(poller);
- }
+ acceptor.reset(
+ AsynchAcceptor::create(listener,
+ boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false)));
+ acceptor->start(poller);
}
void SslProtocolFactory::connect(sys::Poller::shared_ptr poller,
const std::string& host,
- const std::string& port,
+ int16_t port,
sys::ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
diff --git a/cpp/src/qpid/client/ConnectionHandler.cpp b/cpp/src/qpid/client/ConnectionHandler.cpp
index ab0d8e0700..8dc1e8338a 100644
--- a/cpp/src/qpid/client/ConnectionHandler.cpp
+++ b/cpp/src/qpid/client/ConnectionHandler.cpp
@@ -22,7 +22,6 @@
#include "qpid/client/ConnectionHandler.h"
#include "qpid/SaslFactory.h"
-#include "qpid/StringUtils.h"
#include "qpid/client/Bounds.h"
#include "qpid/framing/amqp_framing.h"
#include "qpid/framing/all_method_bodies.h"
@@ -143,9 +142,7 @@ void ConnectionHandler::outgoing(AMQFrame& frame)
void ConnectionHandler::waitForOpen()
{
waitFor(ESTABLISHED);
- if (getState() == FAILED) {
- throw TransportFailure(errorText);
- } else if (getState() == CLOSED) {
+ if (getState() == FAILED || getState() == CLOSED) {
throw ConnectionException(errorCode, errorText);
}
}
@@ -205,24 +202,6 @@ void ConnectionHandler::fail(const std::string& message)
namespace {
std::string SPACE(" ");
-
-std::string join(const std::vector<std::string>& in)
-{
- std::string result;
- for (std::vector<std::string>::const_iterator i = in.begin(); i != in.end(); ++i) {
- if (result.size()) result += SPACE;
- result += *i;
- }
- return result;
-}
-
-void intersection(const std::vector<std::string>& a, const std::vector<std::string>& b, std::vector<std::string>& results)
-{
- for (std::vector<std::string>::const_iterator i = a.begin(); i != a.end(); ++i) {
- if (std::find(b.begin(), b.end(), *i) != b.end()) results.push_back(*i);
- }
-}
-
}
void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& mechanisms, const Array& /*locales*/)
@@ -237,35 +216,26 @@ void ConnectionHandler::start(const FieldTable& /*serverProps*/, const Array& me
maxSsf
);
- std::vector<std::string> mechlist;
- if (mechanism.empty()) {
- //mechlist is simply what the server offers
- mechanisms.collect(mechlist);
- } else {
- //mechlist is the intersection of those indicated by user and
- //those supported by server, in the order listed by user
- std::vector<std::string> allowed = split(mechanism, " ");
- std::vector<std::string> supported;
- mechanisms.collect(supported);
- intersection(allowed, supported, mechlist);
- if (mechlist.empty()) {
- throw Exception(QPID_MSG("Desired mechanism(s) not valid: " << mechanism << " (supported: " << join(supported) << ")"));
+ std::string mechlist;
+ bool chosenMechanismSupported = mechanism.empty();
+ for (Array::const_iterator i = mechanisms.begin(); i != mechanisms.end(); ++i) {
+ if (!mechanism.empty() && mechanism == (*i)->get<std::string>()) {
+ chosenMechanismSupported = true;
+ mechlist = (*i)->get<std::string>() + SPACE + mechlist;
+ } else {
+ if (i != mechanisms.begin()) mechlist += SPACE;
+ mechlist += (*i)->get<std::string>();
}
}
+ if (!chosenMechanismSupported) {
+ fail("Selected mechanism not supported: " + mechanism);
+ }
+
if (sasl.get()) {
- string response;
- if (sasl->start(join(mechlist), response, getSecuritySettings ? getSecuritySettings() : 0)) {
- proxy.startOk(properties, sasl->getMechanism(), response, locale);
- } else {
- //response was null
- ConnectionStartOkBody body;
- body.setClientProperties(properties);
- body.setMechanism(sasl->getMechanism());
- //Don't set response, as none was given
- body.setLocale(locale);
- proxy.send(body);
- }
+ string response = sasl->start(mechanism.empty() ? mechlist : mechanism,
+ getSecuritySettings ? getSecuritySettings() : 0);
+ proxy.startOk(properties, sasl->getMechanism(), response, locale);
} else {
//TODO: verify that desired mechanism and locale are supported
string response = ((char)0) + username + ((char)0) + password;
diff --git a/cpp/src/qpid/client/ConnectionImpl.cpp b/cpp/src/qpid/client/ConnectionImpl.cpp
index db97f1e0f4..40c004f166 100644
--- a/cpp/src/qpid/client/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/ConnectionImpl.cpp
@@ -36,7 +36,6 @@
#include <boost/bind.hpp>
#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <limits>
@@ -259,16 +258,16 @@ void ConnectionImpl::open()
connector->setInputHandler(&handler);
connector->setShutdownHandler(this);
try {
- std::string p = boost::lexical_cast<std::string>(port);
- connector->connect(host, p);
-
+ connector->connect(host, port);
+
} catch (const std::exception& e) {
QPID_LOG(debug, "Failed to connect to " << protocol << ":" << host << ":" << port << " " << e.what());
connector.reset();
- throw TransportFailure(e.what());
+ throw;
}
connector->init();
-
+ QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port);
+
// Enable heartbeat if requested
uint16_t heartbeat = static_cast<ConnectionSettings&>(handler).heartbeat;
if (heartbeat) {
@@ -282,7 +281,6 @@ void ConnectionImpl::open()
// - in that case in connector.reset() above;
// - or when we are deleted
handler.waitForOpen();
- QPID_LOG(info, *this << " connected to " << protocol << ":" << host << ":" << port);
// If the SASL layer has provided an "operational" userId for the connection,
// put it in the negotiated settings.
diff --git a/cpp/src/qpid/client/Connector.h b/cpp/src/qpid/client/Connector.h
index bc611ffe0d..586012f9d6 100644
--- a/cpp/src/qpid/client/Connector.h
+++ b/cpp/src/qpid/client/Connector.h
@@ -61,7 +61,7 @@ class Connector : public framing::OutputHandler
static void registerFactory(const std::string& proto, Factory* connectorFactory);
virtual ~Connector() {};
- virtual void connect(const std::string& host, const std::string& port) = 0;
+ virtual void connect(const std::string& host, int port) = 0;
virtual void init() {};
virtual void close() = 0;
virtual void send(framing::AMQFrame& frame) = 0;
diff --git a/cpp/src/qpid/client/RdmaConnector.cpp b/cpp/src/qpid/client/RdmaConnector.cpp
index 664640f5e7..6af607198c 100644
--- a/cpp/src/qpid/client/RdmaConnector.cpp
+++ b/cpp/src/qpid/client/RdmaConnector.cpp
@@ -95,7 +95,7 @@ class RdmaConnector : public Connector, public sys::Codec
std::string identifier;
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void close();
void send(framing::AMQFrame& frame);
void abort() {} // TODO: need to fix this for heartbeat timeouts to work
@@ -173,7 +173,7 @@ RdmaConnector::~RdmaConnector() {
}
}
-void RdmaConnector::connect(const std::string& host, const std::string& port){
+void RdmaConnector::connect(const std::string& host, int port){
Mutex::ScopedLock l(dataConnectedLock);
assert(!dataConnected);
@@ -184,7 +184,7 @@ void RdmaConnector::connect(const std::string& host, const std::string& port){
boost::bind(&RdmaConnector::disconnected, this),
boost::bind(&RdmaConnector::rejected, this, poller, _1, _2));
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
acon->start(poller, sa);
}
diff --git a/cpp/src/qpid/client/SessionImpl.cpp b/cpp/src/qpid/client/SessionImpl.cpp
index 7cf4ef648e..b507625b11 100644
--- a/cpp/src/qpid/client/SessionImpl.cpp
+++ b/cpp/src/qpid/client/SessionImpl.cpp
@@ -170,7 +170,6 @@ Demux& SessionImpl::getDemux()
void SessionImpl::waitForCompletion(const SequenceNumber& id)
{
Lock l(state);
- sys::Waitable::ScopedWait w(state);
waitForCompletionImpl(id);
}
diff --git a/cpp/src/qpid/client/SslConnector.cpp b/cpp/src/qpid/client/SslConnector.cpp
index 26c2335eda..35c7e6bdf6 100644
--- a/cpp/src/qpid/client/SslConnector.cpp
+++ b/cpp/src/qpid/client/SslConnector.cpp
@@ -114,7 +114,7 @@ class SslConnector : public Connector
std::string identifier;
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void init();
void close();
void send(framing::AMQFrame& frame);
@@ -190,14 +190,14 @@ SslConnector::~SslConnector() {
close();
}
-void SslConnector::connect(const std::string& host, const std::string& port){
+void SslConnector::connect(const std::string& host, int port){
Mutex::ScopedLock l(closedLock);
assert(closed);
try {
socket.connect(host, port);
} catch (const std::exception& e) {
socket.close();
- throw TransportFailure(e.what());
+ throw ConnectionException(framing::connection::CLOSE_CODE_FRAMING_ERROR, e.what());
}
identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
diff --git a/cpp/src/qpid/client/TCPConnector.cpp b/cpp/src/qpid/client/TCPConnector.cpp
index 0070b24ec0..e284d57bec 100644
--- a/cpp/src/qpid/client/TCPConnector.cpp
+++ b/cpp/src/qpid/client/TCPConnector.cpp
@@ -88,7 +88,7 @@ TCPConnector::~TCPConnector() {
close();
}
-void TCPConnector::connect(const std::string& host, const std::string& port) {
+void TCPConnector::connect(const std::string& host, int port) {
Mutex::ScopedLock l(lock);
assert(closed);
connector = AsynchConnector::create(
@@ -117,11 +117,11 @@ void TCPConnector::connected(const Socket&) {
void TCPConnector::start(sys::AsynchIO* aio_) {
aio = aio_;
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 32; i++) {
aio->queueReadBuffer(new Buff(maxFrameSize));
}
- identifier = str(format("[%1%]") % socket.getFullAddress());
+ identifier = str(format("[%1% %2%]") % socket.getLocalPort() % socket.getPeerAddress());
}
void TCPConnector::initAmqp() {
diff --git a/cpp/src/qpid/client/TCPConnector.h b/cpp/src/qpid/client/TCPConnector.h
index eb3f696013..c756469182 100644
--- a/cpp/src/qpid/client/TCPConnector.h
+++ b/cpp/src/qpid/client/TCPConnector.h
@@ -98,7 +98,7 @@ class TCPConnector : public Connector, public sys::Codec
protected:
virtual ~TCPConnector();
- void connect(const std::string& host, const std::string& port);
+ void connect(const std::string& host, int port);
void start(sys::AsynchIO* aio_);
void initAmqp();
virtual void connectFailed(const std::string& msg);
diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
index d2accddcd0..bfb20118b5 100644
--- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
+++ b/cpp/src/qpid/client/amqp0_10/AcceptTracker.cpp
@@ -30,23 +30,12 @@ void AcceptTracker::State::accept()
unaccepted.clear();
}
-SequenceSet AcceptTracker::State::accept(qpid::framing::SequenceNumber id, bool cumulative)
+void AcceptTracker::State::accept(qpid::framing::SequenceNumber id)
{
- SequenceSet accepting;
- if (cumulative) {
- for (SequenceSet::iterator i = unaccepted.begin(); i != unaccepted.end() && *i <= id; ++i) {
- accepting.add(*i);
- }
- unconfirmed.add(accepting);
- unaccepted.remove(accepting);
- } else {
- if (unaccepted.contains(id)) {
- unaccepted.remove(id);
- unconfirmed.add(id);
- accepting.add(id);
- }
+ if (unaccepted.contains(id)) {
+ unaccepted.remove(id);
+ unconfirmed.add(id);
}
- return accepting;
}
void AcceptTracker::State::release()
@@ -70,18 +59,6 @@ void AcceptTracker::delivered(const std::string& destination, const qpid::framin
destinationState[destination].unaccepted.add(id);
}
-namespace
-{
-const size_t FLUSH_FREQUENCY = 1024;
-}
-
-void AcceptTracker::addToPending(qpid::client::AsyncSession& session, const Record& record)
-{
- pending.push_back(record);
- if (pending.size() % FLUSH_FREQUENCY == 0) session.flush();
-}
-
-
void AcceptTracker::accept(qpid::client::AsyncSession& session)
{
for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) {
@@ -90,19 +67,20 @@ void AcceptTracker::accept(qpid::client::AsyncSession& session)
Record record;
record.status = session.messageAccept(aggregateState.unaccepted);
record.accepted = aggregateState.unaccepted;
- addToPending(session, record);
+ pending.push_back(record);
aggregateState.accept();
}
-void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session, bool cumulative)
+void AcceptTracker::accept(qpid::framing::SequenceNumber id, qpid::client::AsyncSession& session)
{
for (StateMap::iterator i = destinationState.begin(); i != destinationState.end(); ++i) {
- i->second.accept(id, cumulative);
+ i->second.accept(id);
}
Record record;
- record.accepted = aggregateState.accept(id, cumulative);
+ record.accepted.add(id);
record.status = session.messageAccept(record.accepted);
- addToPending(session, record);
+ pending.push_back(record);
+ aggregateState.accept(id);
}
void AcceptTracker::release(qpid::client::AsyncSession& session)
diff --git a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
index 85209c3b87..87890e41cc 100644
--- a/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
+++ b/cpp/src/qpid/client/amqp0_10/AcceptTracker.h
@@ -42,7 +42,7 @@ class AcceptTracker
public:
void delivered(const std::string& destination, const qpid::framing::SequenceNumber& id);
void accept(qpid::client::AsyncSession&);
- void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&, bool cumulative);
+ void accept(qpid::framing::SequenceNumber, qpid::client::AsyncSession&);
void release(qpid::client::AsyncSession&);
uint32_t acceptsPending();
uint32_t acceptsPending(const std::string& destination);
@@ -62,7 +62,7 @@ class AcceptTracker
qpid::framing::SequenceSet unconfirmed;
void accept();
- qpid::framing::SequenceSet accept(qpid::framing::SequenceNumber, bool cumulative);
+ void accept(qpid::framing::SequenceNumber);
void release();
uint32_t acceptsPending();
void completed(qpid::framing::SequenceSet&);
@@ -79,7 +79,6 @@ class AcceptTracker
StateMap destinationState;
Records pending;
- void addToPending(qpid::client::AsyncSession&, const Record&);
void checkPending();
void completed(qpid::framing::SequenceSet&);
};
diff --git a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
index 16e5fde075..f1295a3b66 100644
--- a/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
+++ b/cpp/src/qpid/client/amqp0_10/AddressResolution.cpp
@@ -129,10 +129,6 @@ const std::string HEADERS_EXCHANGE("headers");
const std::string XML_EXCHANGE("xml");
const std::string WILDCARD_ANY("#");
-//exchange prefixes:
-const std::string PREFIX_AMQ("amq.");
-const std::string PREFIX_QPID("qpid.");
-
const Verifier verifier;
}
@@ -203,7 +199,6 @@ class Exchange : protected Node
void checkCreate(qpid::client::AsyncSession&, CheckMode);
void checkAssert(qpid::client::AsyncSession&, CheckMode);
void checkDelete(qpid::client::AsyncSession&, CheckMode);
- bool isReservedName();
protected:
const std::string specifiedType;
@@ -238,8 +233,6 @@ class Subscription : public Exchange, public MessageSource
const bool reliable;
const bool durable;
const std::string actualType;
- const bool exclusiveQueue;
- const bool exclusiveSubscription;
FieldTable queueOptions;
FieldTable subscriptionOptions;
Bindings bindings;
@@ -314,7 +307,6 @@ struct Opt
Opt& operator/(const std::string& name);
operator bool() const;
std::string str() const;
- bool asBool(bool defaultValue) const;
const Variant::List& asList() const;
void collect(qpid::framing::FieldTable& args) const;
@@ -346,12 +338,6 @@ Opt::operator bool() const
return value && !value->isVoid() && value->asBool();
}
-bool Opt::asBool(bool defaultValue) const
-{
- if (value) return value->asBool();
- else return defaultValue;
-}
-
std::string Opt::str() const
{
if (value) return value->asString();
@@ -495,7 +481,7 @@ std::string Subscription::getSubscriptionName(const std::string& base, const std
if (name.empty()) {
return (boost::format("%1%_%2%") % base % Uuid(true).str()).str();
} else {
- return name;
+ return (boost::format("%1%_%2%") % base % name).str();
}
}
@@ -504,9 +490,7 @@ Subscription::Subscription(const Address& address, const std::string& type)
queue(getSubscriptionName(name, (Opt(address)/LINK/NAME).str())),
reliable(AddressResolution::is_reliable(address)),
durable(Opt(address)/LINK/DURABLE),
- actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type),
- exclusiveQueue((Opt(address)/LINK/X_DECLARE/EXCLUSIVE).asBool(true)),
- exclusiveSubscription((Opt(address)/LINK/X_SUBSCRIBE/EXCLUSIVE).asBool(exclusiveQueue))
+ actualType(type.empty() ? (specifiedType.empty() ? TOPIC_EXCHANGE : specifiedType) : type)
{
(Opt(address)/LINK/X_DECLARE/ARGUMENTS).collect(queueOptions);
(Opt(address)/LINK/X_SUBSCRIBE/ARGUMENTS).collect(subscriptionOptions);
@@ -566,7 +550,7 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
checkAssert(session, FOR_RECEIVER);
//create subscription queue:
- session.queueDeclare(arg::queue=queue, arg::exclusive=exclusiveQueue,
+ session.queueDeclare(arg::queue=queue, arg::exclusive=true,
arg::autoDelete=!reliable, arg::durable=durable, arg::arguments=queueOptions);
//'default' binding:
bindings.bind(session);
@@ -575,15 +559,15 @@ void Subscription::subscribe(qpid::client::AsyncSession& session, const std::str
linkBindings.bind(session);
//subscribe to subscription queue:
AcceptMode accept = reliable ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE;
- session.messageSubscribe(arg::queue=queue, arg::destination=destination,
- arg::exclusive=exclusiveSubscription, arg::acceptMode=accept, arg::arguments=subscriptionOptions);
+ session.messageSubscribe(arg::queue=queue, arg::destination=destination,
+ arg::exclusive=true, arg::acceptMode=accept, arg::arguments=subscriptionOptions);
}
void Subscription::cancel(qpid::client::AsyncSession& session, const std::string& destination)
{
linkBindings.unbind(session);
session.messageCancel(destination);
- if (exclusiveQueue) session.queueDelete(arg::queue=queue, arg::ifUnused=true);
+ session.queueDelete(arg::queue=queue);
checkDelete(session, FOR_RECEIVER);
}
@@ -777,32 +761,18 @@ Exchange::Exchange(const Address& a) : Node(a),
linkBindings.setDefaultExchange(name);
}
-bool Exchange::isReservedName()
-{
- return name.find(PREFIX_AMQ) != std::string::npos || name.find(PREFIX_QPID) != std::string::npos;
-}
-
void Exchange::checkCreate(qpid::client::AsyncSession& session, CheckMode mode)
{
if (enabled(createPolicy, mode)) {
try {
- if (isReservedName()) {
- try {
- sync(session).exchangeDeclare(arg::exchange=name, arg::passive=true);
- } catch (const qpid::framing::NotFoundException& /*e*/) {
- throw ResolutionError((boost::format("Cannot create exchange %1%; names beginning with \"amq.\" or \"qpid.\" are reserved.") % name).str());
- }
-
- } else {
- std::string type = specifiedType;
- if (type.empty()) type = TOPIC_EXCHANGE;
- session.exchangeDeclare(arg::exchange=name,
- arg::type=type,
- arg::durable=durable,
- arg::autoDelete=autoDelete,
- arg::alternateExchange=alternateExchange,
- arg::arguments=arguments);
- }
+ std::string type = specifiedType;
+ if (type.empty()) type = TOPIC_EXCHANGE;
+ session.exchangeDeclare(arg::exchange=name,
+ arg::type=type,
+ arg::durable=durable,
+ arg::autoDelete=autoDelete,
+ arg::alternateExchange=alternateExchange,
+ arg::arguments=arguments);
nodeBindings.bind(session);
session.sync();
} catch (const qpid::framing::NotAllowedException& e) {
@@ -852,7 +822,7 @@ void Exchange::checkAssert(qpid::client::AsyncSession& session, CheckMode mode)
FieldTable::ValuePtr v = result.getArguments().get(i->first);
if (!v) {
throw AssertionFailed((boost::format("Option %1% not set for %2%") % i->first % name).str());
- } else if (*i->second != *v) {
+ } else if (i->second != v) {
throw AssertionFailed((boost::format("Option %1% does not match for %2%, expected %3%, got %4%")
% i->first % name % *(i->second) % *v).str());
}
diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
index cc6e9b9ab2..5a545c1f6a 100644
--- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.cpp
@@ -20,6 +20,7 @@
*/
#include "ConnectionImpl.h"
#include "SessionImpl.h"
+#include "SimpleUrlParser.h"
#include "qpid/messaging/exceptions.h"
#include "qpid/messaging/Session.h"
#include "qpid/messaging/PrivateImplRef.h"
@@ -38,18 +39,26 @@ using qpid::types::Variant;
using qpid::types::VAR_LIST;
using qpid::framing::Uuid;
-namespace {
-void merge(const std::string& value, std::vector<std::string>& list) {
- if (std::find(list.begin(), list.end(), value) == list.end())
- list.push_back(value);
+void convert(const Variant::List& from, std::vector<std::string>& to)
+{
+ for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i) {
+ to.push_back(i->asString());
+ }
}
-void merge(const Variant::List& from, std::vector<std::string>& to)
+template <class T> bool setIfFound(const Variant::Map& map, const std::string& key, T& value)
{
- for (Variant::List::const_iterator i = from.begin(); i != from.end(); ++i)
- merge(i->asString(), to);
+ Variant::Map::const_iterator i = map.find(key);
+ if (i != map.end()) {
+ value = (T) i->second;
+ QPID_LOG(debug, "option " << key << " specified as " << i->second);
+ return true;
+ } else {
+ return false;
+ }
}
+namespace {
std::string asString(const std::vector<std::string>& v) {
std::stringstream os;
os << "[";
@@ -62,8 +71,49 @@ std::string asString(const std::vector<std::string>& v) {
}
}
+template <> bool setIfFound< std::vector<std::string> >(const Variant::Map& map,
+ const std::string& key,
+ std::vector<std::string>& value)
+{
+ Variant::Map::const_iterator i = map.find(key);
+ if (i != map.end()) {
+ value.clear();
+ if (i->second.getType() == VAR_LIST) {
+ convert(i->second.asList(), value);
+ } else {
+ value.push_back(i->second.asString());
+ }
+ QPID_LOG(debug, "option " << key << " specified as " << asString(value));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void convert(const Variant::Map& from, ConnectionSettings& to)
+{
+ setIfFound(from, "username", to.username);
+ setIfFound(from, "password", to.password);
+ setIfFound(from, "sasl-mechanism", to.mechanism);
+ setIfFound(from, "sasl-service", to.service);
+ setIfFound(from, "sasl-min-ssf", to.minSsf);
+ setIfFound(from, "sasl-max-ssf", to.maxSsf);
+
+ setIfFound(from, "heartbeat", to.heartbeat);
+ setIfFound(from, "tcp-nodelay", to.tcpNoDelay);
+
+ setIfFound(from, "locale", to.locale);
+ setIfFound(from, "max-channels", to.maxChannels);
+ setIfFound(from, "max-frame-size", to.maxFrameSize);
+ setIfFound(from, "bounds", to.bounds);
+
+ setIfFound(from, "transport", to.protocol);
+
+ setIfFound(from, "ssl-cert-name", to.sslCertName);
+}
+
ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& options) :
- replaceUrls(false), reconnect(false), timeout(-1), limit(-1),
+ reconnect(false), timeout(-1), limit(-1),
minReconnectInterval(3), maxReconnectInterval(60),
retries(0), reconnectOnLimitExceeded(true)
{
@@ -74,69 +124,27 @@ ConnectionImpl::ConnectionImpl(const std::string& url, const Variant::Map& optio
void ConnectionImpl::setOptions(const Variant::Map& options)
{
- for (Variant::Map::const_iterator i = options.begin(); i != options.end(); ++i) {
- setOption(i->first, i->second);
+ sys::Mutex::ScopedLock l(lock);
+ convert(options, settings);
+ setIfFound(options, "reconnect", reconnect);
+ setIfFound(options, "reconnect-timeout", timeout);
+ setIfFound(options, "reconnect-limit", limit);
+ int64_t reconnectInterval;
+ if (setIfFound(options, "reconnect-interval", reconnectInterval)) {
+ minReconnectInterval = maxReconnectInterval = reconnectInterval;
+ } else {
+ setIfFound(options, "reconnect-interval-min", minReconnectInterval);
+ setIfFound(options, "reconnect-interval-max", maxReconnectInterval);
}
+ setIfFound(options, "reconnect-urls", urls);
+ setIfFound(options, "x-reconnect-on-limit-exceeded", reconnectOnLimitExceeded);
}
void ConnectionImpl::setOption(const std::string& name, const Variant& value)
{
- sys::Mutex::ScopedLock l(lock);
- if (name == "reconnect") {
- reconnect = value;
- } else if (name == "reconnect-timeout" || name == "reconnect_timeout") {
- timeout = value;
- } else if (name == "reconnect-limit" || name == "reconnect_limit") {
- limit = value;
- } else if (name == "reconnect-interval" || name == "reconnect_interval") {
- maxReconnectInterval = minReconnectInterval = value;
- } else if (name == "reconnect-interval-min" || name == "reconnect_interval_min") {
- minReconnectInterval = value;
- } else if (name == "reconnect-interval-max" || name == "reconnect_interval_max") {
- maxReconnectInterval = value;
- } else if (name == "reconnect-urls-replace" || name == "reconnect_urls_replace") {
- replaceUrls = value.asBool();
- } else if (name == "reconnect-urls" || name == "reconnect_urls") {
- if (replaceUrls) urls.clear();
- if (value.getType() == VAR_LIST) {
- merge(value.asList(), urls);
- } else {
- merge(value.asString(), urls);
- }
- } else if (name == "username") {
- settings.username = value.asString();
- } else if (name == "password") {
- settings.password = value.asString();
- } else if (name == "sasl-mechanism" || name == "sasl_mechanism" ||
- name == "sasl-mechanisms" || name == "sasl_mechanisms") {
- settings.mechanism = value.asString();
- } else if (name == "sasl-service" || name == "sasl_service") {
- settings.service = value.asString();
- } else if (name == "sasl-min-ssf" || name == "sasl_min_ssf") {
- settings.minSsf = value;
- } else if (name == "sasl-max-ssf" || name == "sasl_max_ssf") {
- settings.maxSsf = value;
- } else if (name == "heartbeat") {
- settings.heartbeat = value;
- } else if (name == "tcp-nodelay" || name == "tcp_nodelay") {
- settings.tcpNoDelay = value;
- } else if (name == "locale") {
- settings.locale = value.asString();
- } else if (name == "max-channels" || name == "max_channels") {
- settings.maxChannels = value;
- } else if (name == "max-frame-size" || name == "max_frame_size") {
- settings.maxFrameSize = value;
- } else if (name == "bounds") {
- settings.bounds = value;
- } else if (name == "transport") {
- settings.protocol = value.asString();
- } else if (name == "ssl-cert-name" || name == "ssl_cert_name") {
- settings.sslCertName = value.asString();
- } else if (name == "x-reconnect-on-limit-exceeded" || name == "x_reconnect_on_limit_exceeded") {
- reconnectOnLimitExceeded = value;
- } else {
- throw qpid::messaging::MessagingException(QPID_MSG("Invalid option: " << name << " not recognised"));
- }
+ Variant::Map options;
+ options[name] = value;
+ setOptions(options);
}
@@ -206,7 +214,7 @@ qpid::messaging::Session ConnectionImpl::newSession(bool transactional, const st
sessions[name] = impl;
break;
} catch (const qpid::TransportFailure&) {
- reopen();
+ open();
} catch (const qpid::SessionException& e) {
throw qpid::messaging::SessionError(e.what());
} catch (const std::exception& e) {
@@ -227,15 +235,6 @@ void ConnectionImpl::open()
catch (const qpid::Exception& e) { throw messaging::ConnectionError(e.what()); }
}
-void ConnectionImpl::reopen()
-{
- if (!reconnect) {
- throw qpid::messaging::TransportFailure("Failed to connect (reconnect disabled)");
- }
- open();
-}
-
-
bool expired(const qpid::sys::AbsTime& start, int64_t timeout)
{
if (timeout == 0) return true;
@@ -263,9 +262,14 @@ void ConnectionImpl::connect(const qpid::sys::AbsTime& started)
}
void ConnectionImpl::mergeUrls(const std::vector<Url>& more, const sys::Mutex::ScopedLock&) {
- for (std::vector<Url>::const_iterator i = more.begin(); i != more.end(); ++i)
- merge(i->str(), urls);
- QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls));
+ if (more.size()) {
+ for (size_t i = 0; i < more.size(); ++i) {
+ if (std::find(urls.begin(), urls.end(), more[i].str()) == urls.end()) {
+ urls.push_back(more[i].str());
+ }
+ }
+ QPID_LOG(debug, "Added known-hosts, reconnect-urls=" << asString(urls));
+ }
}
bool ConnectionImpl::tryConnect()
@@ -274,14 +278,21 @@ bool ConnectionImpl::tryConnect()
for (std::vector<std::string>::const_iterator i = urls.begin(); i != urls.end(); ++i) {
try {
QPID_LOG(info, "Trying to connect to " << *i << "...");
- Url url(*i);
- if (url.getUser().size()) settings.username = url.getUser();
- if (url.getPass().size()) settings.password = url.getPass();
- connection.open(url, settings);
+ //TODO: when url support is more complete can avoid this test here
+ if (i->find("amqp:") == 0) {
+ Url url(*i);
+ connection.open(url, settings);
+ } else {
+ SimpleUrlParser::parse(*i, settings);
+ connection.open(settings);
+ }
QPID_LOG(info, "Connected to " << *i);
mergeUrls(connection.getInitialBrokers(), l);
return resetSessions(l);
- } catch (const qpid::TransportFailure& e) {
+ } catch (const qpid::ConnectionException& e) {
+ //TODO: need to fix timeout on
+ //qpid::client::Connection::open() so that it throws
+ //TransportFailure rather than a ConnectionException
QPID_LOG(info, "Failed to connect to " << *i << ": " << e.what());
}
}
diff --git a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
index 1b58cbbe3e..09f2038312 100644
--- a/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/ConnectionImpl.h
@@ -43,7 +43,6 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
public:
ConnectionImpl(const std::string& url, const qpid::types::Variant::Map& options);
void open();
- void reopen();
bool isOpen() const;
void close();
qpid::messaging::Session newSession(bool transactional, const std::string& name);
@@ -60,7 +59,6 @@ class ConnectionImpl : public qpid::messaging::ConnectionImpl
qpid::sys::Semaphore semaphore;//used to coordinate reconnection
Sessions sessions;
qpid::client::Connection connection;
- bool replaceUrls; // Replace rather than merging with reconnect-urls
std::vector<std::string> urls;
qpid::client::ConnectionSettings settings;
bool reconnect;
diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
index 3badaf40ba..71e89bdba1 100644
--- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
+++ b/cpp/src/qpid/client/amqp0_10/IncomingMessages.cpp
@@ -144,10 +144,10 @@ void IncomingMessages::accept()
acceptTracker.accept(session);
}
-void IncomingMessages::accept(qpid::framing::SequenceNumber id, bool cumulative)
+void IncomingMessages::accept(qpid::framing::SequenceNumber id)
{
sys::Mutex::ScopedLock l(lock);
- acceptTracker.accept(id, session, cumulative);
+ acceptTracker.accept(id, session);
}
@@ -301,7 +301,6 @@ const std::string SUBJECT("qpid.subject");
const std::string X_APP_ID("x-amqp-0-10.app-id");
const std::string X_ROUTING_KEY("x-amqp-0-10.routing-key");
const std::string X_CONTENT_ENCODING("x-amqp-0-10.content-encoding");
-const std::string X_TIMESTAMP("x-amqp-0-10.timestamp");
}
void populateHeaders(qpid::messaging::Message& message,
@@ -335,13 +334,10 @@ void populateHeaders(qpid::messaging::Message& message,
if (messageProperties->hasContentEncoding()) {
message.getProperties()[X_CONTENT_ENCODING] = messageProperties->getContentEncoding();
}
- // routing-key, timestamp, others?
+ // routing-key, others?
if (deliveryProperties && deliveryProperties->hasRoutingKey()) {
message.getProperties()[X_ROUTING_KEY] = deliveryProperties->getRoutingKey();
}
- if (deliveryProperties && deliveryProperties->hasTimestamp()) {
- message.getProperties()[X_TIMESTAMP] = deliveryProperties->getTimestamp();
- }
}
}
diff --git a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
index 9053b70312..f6a291bc68 100644
--- a/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
+++ b/cpp/src/qpid/client/amqp0_10/IncomingMessages.h
@@ -72,7 +72,7 @@ class IncomingMessages
bool get(Handler& handler, qpid::sys::Duration timeout);
bool getNextDestination(std::string& destination, qpid::sys::Duration timeout);
void accept();
- void accept(qpid::framing::SequenceNumber id, bool cumulative);
+ void accept(qpid::framing::SequenceNumber id);
void releaseAll();
void releasePending(const std::string& destination);
diff --git a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
index d93416da75..82358961c8 100644
--- a/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
+++ b/cpp/src/qpid/client/amqp0_10/OutgoingMessage.cpp
@@ -59,9 +59,7 @@ void OutgoingMessage::convert(const qpid::messaging::Message& from)
message.getMessageProperties().setReplyTo(AddressResolution::convert(address));
}
translate(from.getProperties(), message.getMessageProperties().getApplicationHeaders());
- if (from.getTtl().getMilliseconds()) {
- message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds());
- }
+ message.getDeliveryProperties().setTtl(from.getTtl().getMilliseconds());
if (from.getDurable()) {
message.getDeliveryProperties().setDeliveryMode(DELIVERY_MODE_PERSISTENT);
}
diff --git a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
index f2f0f1a9e5..e1b75ec0cf 100644
--- a/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/SenderImpl.cpp
@@ -135,7 +135,6 @@ void SenderImpl::sendUnreliable(const qpid::messaging::Message& m)
void SenderImpl::replay(const sys::Mutex::ScopedLock&)
{
for (OutgoingMessages::iterator i = outgoing.begin(); i != outgoing.end(); ++i) {
- i->message.setRedelivered(true);
sink->send(session, name, *i);
}
}
@@ -148,7 +147,7 @@ uint32_t SenderImpl::checkPendingSends(bool flush) {
uint32_t SenderImpl::checkPendingSends(bool flush, const sys::Mutex::ScopedLock&)
{
if (flush) {
- session.flush();
+ session.flush();
flushed = true;
} else {
flushed = false;
diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
index be5eab1f2b..75a71997fd 100644
--- a/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
+++ b/cpp/src/qpid/client/amqp0_10/SessionImpl.cpp
@@ -60,14 +60,12 @@ SessionImpl::SessionImpl(ConnectionImpl& c, bool t) : connection(&c), transactio
void SessionImpl::checkError()
{
- ScopedLock l(lock);
qpid::client::SessionBase_0_10Access s(session);
s.get()->assertOpen();
}
bool SessionImpl::hasError()
{
- ScopedLock l(lock);
qpid::client::SessionBase_0_10Access s(session);
return s.get()->hasError();
}
@@ -114,14 +112,13 @@ void SessionImpl::release(qpid::messaging::Message& m)
execute1<Release>(m);
}
-void SessionImpl::acknowledge(qpid::messaging::Message& m, bool cumulative)
+void SessionImpl::acknowledge(qpid::messaging::Message& m)
{
//Should probably throw an exception on failure here, or indicate
//it through a return type at least. Failure means that the
//message may be redelivered; i.e. the application cannot delete
//any state necessary for preventing reprocessing of the message
- Acknowledge2 ack(*this, m, cumulative);
- execute(ack);
+ execute1<Acknowledge1>(m);
}
void SessionImpl::close()
@@ -131,29 +128,27 @@ void SessionImpl::close()
senders.clear();
receivers.clear();
} else {
- Senders sCopy;
- Receivers rCopy;
- {
- ScopedLock l(lock);
- senders.swap(sCopy);
- receivers.swap(rCopy);
- }
- for (Senders::iterator i = sCopy.begin(); i != sCopy.end(); ++i)
- {
- // outside the lock, will call senderCancelled
- i->second.close();
+ while (true) {
+ Sender s;
+ {
+ ScopedLock l(lock);
+ if (senders.empty()) break;
+ s = senders.begin()->second;
+ }
+ s.close(); // outside the lock, will call senderCancelled
}
- for (Receivers::iterator i = rCopy.begin(); i != rCopy.end(); ++i)
- {
- // outside the lock, will call receiverCancelled
- i->second.close();
+ while (true) {
+ Receiver r;
+ {
+ ScopedLock l(lock);
+ if (receivers.empty()) break;
+ r = receivers.begin()->second;
+ }
+ r.close(); // outside the lock, will call receiverCancelled
}
}
connection->closed(*this);
- if (!hasError()) {
- ScopedLock l(lock);
- session.close();
- }
+ if (!hasError()) session.close();
}
template <class T, class S> boost::intrusive_ptr<S> getImplPtr(T& t)
@@ -436,11 +431,8 @@ uint32_t SessionImpl::getUnsettledAcksImpl(const std::string* destination)
void SessionImpl::syncImpl(bool block)
{
- {
- ScopedLock l(lock);
- if (block) session.sync();
- else session.flush();
- }
+ if (block) session.sync();
+ else session.flush();
//cleanup unconfirmed accept records:
incoming.pendingAccept();
}
@@ -475,10 +467,10 @@ void SessionImpl::acknowledgeImpl()
if (!transactional) incoming.accept();
}
-void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m, bool cumulative)
+void SessionImpl::acknowledgeImpl(qpid::messaging::Message& m)
{
ScopedLock l(lock);
- if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId(), cumulative);
+ if (!transactional) incoming.accept(MessageImplAccess::get(m).getInternalId());
}
void SessionImpl::rejectImpl(qpid::messaging::Message& m)
@@ -517,7 +509,7 @@ void SessionImpl::senderCancelled(const std::string& name)
void SessionImpl::reconnect()
{
- connection->reopen();
+ connection->open();
}
bool SessionImpl::backoff()
diff --git a/cpp/src/qpid/client/amqp0_10/SessionImpl.h b/cpp/src/qpid/client/amqp0_10/SessionImpl.h
index c7dea77d18..2a2aa47df6 100644
--- a/cpp/src/qpid/client/amqp0_10/SessionImpl.h
+++ b/cpp/src/qpid/client/amqp0_10/SessionImpl.h
@@ -63,7 +63,7 @@ class SessionImpl : public qpid::messaging::SessionImpl
void acknowledge(bool sync);
void reject(qpid::messaging::Message&);
void release(qpid::messaging::Message&);
- void acknowledge(qpid::messaging::Message& msg, bool cumulative);
+ void acknowledge(qpid::messaging::Message& msg);
void close();
void sync(bool block);
qpid::messaging::Sender createSender(const qpid::messaging::Address& address);
@@ -139,7 +139,7 @@ class SessionImpl : public qpid::messaging::SessionImpl
void commitImpl();
void rollbackImpl();
void acknowledgeImpl();
- void acknowledgeImpl(qpid::messaging::Message&, bool cumulative);
+ void acknowledgeImpl(qpid::messaging::Message&);
void rejectImpl(qpid::messaging::Message&);
void releaseImpl(qpid::messaging::Message&);
void closeImpl();
@@ -204,13 +204,12 @@ class SessionImpl : public qpid::messaging::SessionImpl
void operator()() { impl.releaseImpl(message); }
};
- struct Acknowledge2 : Command
+ struct Acknowledge1 : Command
{
qpid::messaging::Message& message;
- bool cumulative;
- Acknowledge2(SessionImpl& i, qpid::messaging::Message& m, bool c) : Command(i), message(m), cumulative(c) {}
- void operator()() { impl.acknowledgeImpl(message, cumulative); }
+ Acknowledge1(SessionImpl& i, qpid::messaging::Message& m) : Command(i), message(m) {}
+ void operator()() { impl.acknowledgeImpl(message); }
};
struct CreateSender;
diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp
new file mode 100644
index 0000000000..327c2274a6
--- /dev/null
+++ b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.cpp
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "SimpleUrlParser.h"
+#include "qpid/client/ConnectionSettings.h"
+#include "qpid/Exception.h"
+#include <boost/lexical_cast.hpp>
+
+namespace qpid {
+namespace client {
+namespace amqp0_10 {
+
+bool split(const std::string& in, char delim, std::pair<std::string, std::string>& result)
+{
+ std::string::size_type i = in.find(delim);
+ if (i != std::string::npos) {
+ result.first = in.substr(0, i);
+ if (i+1 < in.size()) {
+ result.second = in.substr(i+1);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void parseUsernameAndPassword(const std::string& in, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(in, '/', parts)) {
+ result.username = in;
+ } else {
+ result.username = parts.first;
+ result.password = parts.second;
+ }
+}
+
+void parseHostAndPort(const std::string& in, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(in, ':', parts)) {
+ result.host = in;
+ } else {
+ result.host = parts.first;
+ if (parts.second.size()) {
+ result.port = boost::lexical_cast<uint16_t>(parts.second);
+ }
+ }
+}
+
+void SimpleUrlParser::parse(const std::string& url, qpid::client::ConnectionSettings& result)
+{
+ std::pair<std::string, std::string> parts;
+ if (!split(url, '@', parts)) {
+ parseHostAndPort(url, result);
+ } else {
+ parseUsernameAndPassword(parts.first, result);
+ parseHostAndPort(parts.second, result);
+ }
+}
+
+}}} // namespace qpid::client::amqp0_10
diff --git a/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h
new file mode 100644
index 0000000000..24f90ca9d6
--- /dev/null
+++ b/cpp/src/qpid/client/amqp0_10/SimpleUrlParser.h
@@ -0,0 +1,42 @@
+#ifndef QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H
+#define QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H
+
+/*
+ *
+ * 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 <string>
+
+namespace qpid {
+namespace client {
+
+struct ConnectionSettings;
+
+namespace amqp0_10 {
+
+/**
+ * Parses a simple url of the form user/password@hostname:port
+ */
+struct SimpleUrlParser
+{
+ static void parse(const std::string& url, qpid::client::ConnectionSettings& result);
+};
+}}} // namespace qpid::client::amqp0_10
+
+#endif /*!QPID_CLIENT_AMQP0_10_SIMPLEURLPARSER_H*/
diff --git a/cpp/src/qpid/client/windows/SaslFactory.cpp b/cpp/src/qpid/client/windows/SaslFactory.cpp
index 53d825771b..63c7fa3d1f 100644
--- a/cpp/src/qpid/client/windows/SaslFactory.cpp
+++ b/cpp/src/qpid/client/windows/SaslFactory.cpp
@@ -71,7 +71,7 @@ class WindowsSasl : public Sasl
public:
WindowsSasl( const std::string &, const std::string &, const std::string &, const std::string &, int, int );
~WindowsSasl();
- bool start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings);
+ std::string start(const std::string& mechanisms, const SecuritySettings* externalSettings);
std::string step(const std::string& challenge);
std::string getMechanism();
std::string getUserId();
@@ -121,8 +121,8 @@ WindowsSasl::~WindowsSasl()
{
}
-bool WindowsSasl::start(const std::string& mechanisms, std::string& response,
- const SecuritySettings* /*externalSettings*/)
+std::string WindowsSasl::start(const std::string& mechanisms,
+ const SecuritySettings* /*externalSettings*/)
{
QPID_LOG(debug, "WindowsSasl::start(" << mechanisms << ")");
@@ -142,18 +142,18 @@ bool WindowsSasl::start(const std::string& mechanisms, std::string& response,
if (!haveAnon && !havePlain)
throw InternalErrorException(QPID_MSG("Sasl error: no common mechanism"));
+ std::string resp = "";
if (havePlain) {
mechanism = PLAIN;
- response = ((char)0) + settings.username + ((char)0) + settings.password;
+ resp = ((char)0) + settings.username + ((char)0) + settings.password;
}
else {
mechanism = ANONYMOUS;
- response = "";
}
- return true;
+ return resp;
}
-std::string WindowsSasl::step(const std::string& /*challenge*/)
+std::string WindowsSasl::step(const std::string& challenge)
{
// Shouldn't get this for PLAIN...
throw InternalErrorException(QPID_MSG("Sasl step error"));
@@ -169,7 +169,7 @@ std::string WindowsSasl::getUserId()
return std::string(); // TODO - when GSSAPI is supported, return userId for connection.
}
-std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t /*maxFrameSize*/)
+std::auto_ptr<SecurityLayer> WindowsSasl::getSecurityLayer(uint16_t maxFrameSize)
{
return std::auto_ptr<SecurityLayer>(0);
}
diff --git a/cpp/src/qpid/client/windows/SslConnector.cpp b/cpp/src/qpid/client/windows/SslConnector.cpp
index 785c817928..a33713e1a8 100644
--- a/cpp/src/qpid/client/windows/SslConnector.cpp
+++ b/cpp/src/qpid/client/windows/SslConnector.cpp
@@ -77,7 +77,7 @@ public:
framing::ProtocolVersion pVersion,
const ConnectionSettings&,
ConnectionImpl*);
- virtual void connect(const std::string& host, const std::string& port);
+ virtual void connect(const std::string& host, int port);
virtual void connected(const Socket&);
unsigned int getSSF();
};
@@ -153,7 +153,7 @@ SslConnector::~SslConnector()
// Will this get reach via virtual method via boost::bind????
-void SslConnector::connect(const std::string& host, const std::string& port) {
+void SslConnector::connect(const std::string& host, int port) {
brokerHost = host;
TCPConnector::connect(host, port);
}
diff --git a/cpp/src/qpid/cluster/Cluster.cpp b/cpp/src/qpid/cluster/Cluster.cpp
index e6e3de64f2..dd4882774b 100644
--- a/cpp/src/qpid/cluster/Cluster.cpp
+++ b/cpp/src/qpid/cluster/Cluster.cpp
@@ -36,45 +36,45 @@
*
* IMPORTANT NOTE: any time code is added to the broker that uses timers,
* the cluster may need to be updated to take account of this.
- *
+ *
*
* USE OF TIMESTAMPS IN THE BROKER
- *
+ *
* The following are the current areas where broker uses timers or timestamps:
- *
+ *
* - Producer flow control: broker::SemanticState uses
* connection::getClusterOrderOutput. a FrameHandler that sends
* frames to the client via the cluster. Used by broker::SessionState
- *
+ *
* - QueueCleaner, Message TTL: uses ExpiryPolicy, which is
* implemented by cluster::ExpiryPolicy.
- *
+ *
* - Connection heartbeat: sends connection controls, not part of
* session command counting so OK to ignore.
- *
+ *
* - LinkRegistry: only cluster elder is ever active for links.
- *
+ *
* - management::ManagementBroker: uses MessageHandler supplied by cluster
* to send messages to the broker via the cluster.
+ *
+ * - Dtx: not yet supported with cluster.
*
- * cluster::ExpiryPolicy uses cluster time.
+ * cluster::ExpiryPolicy implements the strategy for message expiry.
*
* ClusterTimer implements periodic timed events in the cluster context.
- * Used for:
- * - periodic management events.
- * - DTX transaction timeouts.
+ * Used for periodic management events.
*
* <h1>CLUSTER PROTOCOL OVERVIEW</h1>
- *
+ *
* Messages sent to/from CPG are called Events.
*
* An Event carries a ConnectionId, which includes a MemberId and a
* connection number.
- *
+ *
* Events are either
* - Connection events: non-0 connection number and are associated with a connection.
* - Cluster Events: 0 connection number, are not associated with a connection.
- *
+ *
* Events are further categorized as:
* - Control: carries method frame(s) that affect cluster behavior.
* - Data: carries raw data received from a client connection.
@@ -146,7 +146,6 @@
#include "qpid/framing/AMQP_AllOperations.h"
#include "qpid/framing/AllInvoker.h"
#include "qpid/framing/ClusterConfigChangeBody.h"
-#include "qpid/framing/ClusterClockBody.h"
#include "qpid/framing/ClusterConnectionDeliverCloseBody.h"
#include "qpid/framing/ClusterConnectionAbortBody.h"
#include "qpid/framing/ClusterRetractOfferBody.h"
@@ -199,7 +198,7 @@ namespace _qmf = ::qmf::org::apache::qpid::cluster;
* Currently use SVN revision to avoid clashes with versions from
* different branches.
*/
-const uint32_t Cluster::CLUSTER_VERSION = 1159329;
+const uint32_t Cluster::CLUSTER_VERSION = 1058747;
struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
qpid::cluster::Cluster& cluster;
@@ -215,7 +214,7 @@ struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
{
cluster.initialStatus(
member, version, active, clusterId,
- framing::cluster::StoreState(storeState), shutdownId,
+ framing::cluster::StoreState(storeState), shutdownId,
firstConfig, l);
}
void ready(const std::string& url) {
@@ -231,21 +230,21 @@ struct ClusterDispatcher : public framing::AMQP_AllOperations::ClusterHandler {
cluster.updateOffer(member, updatee, l);
}
void retractOffer(uint64_t updatee) { cluster.retractOffer(member, updatee, l); }
+ void messageExpired(uint64_t id) { cluster.messageExpired(member, id, l); }
void errorCheck(uint8_t type, const framing::SequenceNumber& frameSeq) {
cluster.errorCheck(member, type, frameSeq, l);
}
void timerWakeup(const std::string& name) { cluster.timerWakeup(member, name, l); }
- void timerDrop(const std::string& name) { cluster.timerDrop(member, name, l); }
+ void timerDrop(const std::string& name) { cluster.timerWakeup(member, name, l); }
void shutdown(const Uuid& id) { cluster.shutdown(member, id, l); }
void deliverToQueue(const std::string& queue, const std::string& message) {
cluster.deliverToQueue(queue, message, l);
}
- void clock(uint64_t time) { cluster.clock(time, l); }
bool invoke(AMQBody& body) { return framing::invoke(*this, body).wasHandled(); }
};
Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
- settings(set),
+ settings(set),
broker(b),
mgmtObject(0),
poller(b.getPoller()),
@@ -254,7 +253,7 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
self(cpg.self()),
clusterId(true),
mAgent(0),
- expiryPolicy(new ExpiryPolicy(*this)),
+ expiryPolicy(new ExpiryPolicy(mcast, self, broker.getTimer())),
mcast(cpg, poller, boost::bind(&Cluster::leave, this)),
dispatcher(cpg, poller, boost::bind(&Cluster::leave, this)),
deliverEventQueue(boost::bind(&Cluster::deliveredEvent, this, _1),
@@ -278,11 +277,8 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
lastBroker(false),
updateRetracted(false),
updateClosed(false),
- error(*this),
- acl(0)
+ error(*this)
{
- broker.setInCluster(true);
-
// We give ownership of the timer to the broker and keep a plain pointer.
// This is OK as it means the timer has the same lifetime as the broker.
timer = new ClusterTimer(*this);
@@ -303,7 +299,7 @@ Cluster::Cluster(const ClusterSettings& set, broker::Broker& b) :
// Load my store status before we go into initialization
if (! broker::NullMessageStore::isNullStore(&broker.getStore())) {
store.load();
- clusterId = store.getClusterId();
+ clusterId = store.getClusterId();
QPID_LOG(notice, "Cluster store state: " << store)
}
cpg.join(name);
@@ -364,15 +360,14 @@ void Cluster::addShadowConnection(const boost::intrusive_ptr<Connection>& c) {
// Safe to use connections here because we're pre-catchup, stalled
// and discarding, so deliveredFrame is not processing any
// connection events.
- assert(discarding);
+ assert(discarding);
pair<ConnectionMap::iterator, bool> ib
= connections.insert(ConnectionMap::value_type(c->getId(), c));
- // Like this to avoid tripping up unused variable warning when NDEBUG set
- if (!ib.second) assert(ib.second);
+ assert(ib.second);
}
void Cluster::erase(const ConnectionId& id) {
- Lock l(lock);
+ Lock l(lock);
erase(id,l);
}
@@ -398,9 +393,9 @@ std::vector<Url> Cluster::getUrls() const {
std::vector<Url> Cluster::getUrls(Lock&) const {
return map.memberUrls();
-}
+}
-void Cluster::leave() {
+void Cluster::leave() {
Lock l(lock);
leave(l);
}
@@ -410,7 +405,7 @@ void Cluster::leave() {
QPID_LOG(warning, *this << " error leaving cluster: " << e.what()); \
} do {} while(0)
-void Cluster::leave(Lock&) {
+void Cluster::leave(Lock&) {
if (state != LEFT) {
state = LEFT;
QPID_LOG(notice, *this << " leaving cluster " << name);
@@ -429,7 +424,7 @@ void Cluster::deliver(
uint32_t nodeid,
uint32_t pid,
void* msg,
- int msg_len)
+ int msg_len)
{
MemberId from(nodeid, pid);
framing::Buffer buf(static_cast<char*>(msg), msg_len);
@@ -460,7 +455,7 @@ void Cluster::deliveredEvent(const Event& e) {
EventFrame ef(e, e.getFrame());
// Stop the deliverEventQueue on update offers.
// This preserves the connection decoder fragments for an update.
- // Only do this for the two brokers that are directly involved in this
+ // Only do this for the two brokers that are directly involved in this
// offer: the one making the offer, or the one receiving it.
const ClusterUpdateOfferBody* offer = castUpdateOffer(ef.frame.getBody());
if (offer && ( e.getMemberId() == self || MemberId(offer->getUpdatee()) == self) ) {
@@ -470,7 +465,7 @@ void Cluster::deliveredEvent(const Event& e) {
}
deliverFrame(ef);
}
- else if(!discarding) {
+ else if(!discarding) {
if (e.isControl())
deliverFrame(EventFrame(e, e.getFrame()));
else {
@@ -512,7 +507,7 @@ void Cluster::deliveredFrame(const EventFrame& efConst) {
// the event queue.
e.frame = AMQFrame(
ClusterRetractOfferBody(ProtocolVersion(), offer->getUpdatee()));
- deliverEventQueue.start();
+ deliverEventQueue.start();
}
// Process each frame through the error checker.
if (error.isUnresolved()) {
@@ -520,14 +515,14 @@ void Cluster::deliveredFrame(const EventFrame& efConst) {
while (error.canProcess()) // There is a frame ready to process.
processFrame(error.getNext(), l);
}
- else
+ else
processFrame(e, l);
}
void Cluster::processFrame(const EventFrame& e, Lock& l) {
if (e.isCluster()) {
- QPID_LOG_IF(trace, loggable(e.frame), *this << " DLVR: " << e);
+ QPID_LOG(trace, *this << " DLVR: " << e);
ClusterDispatcher dispatch(*this, e.connectionId.getMember(), l);
if (!framing::invoke(dispatch, *e.frame.getBody()).wasHandled())
throw Exception(QPID_MSG("Invalid cluster control"));
@@ -536,15 +531,14 @@ void Cluster::processFrame(const EventFrame& e, Lock& l) {
map.incrementFrameSeq();
ConnectionPtr connection = getConnection(e, l);
if (connection) {
- QPID_LOG_IF(trace, loggable(e.frame),
- *this << " DLVR " << map.getFrameSeq() << ": " << e);
+ QPID_LOG(trace, *this << " DLVR " << map.getFrameSeq() << ": " << e);
connection->deliveredFrame(e);
}
else
- throw Exception(QPID_MSG("Unknown connection: " << e));
+ QPID_LOG(trace, *this << " DROP (no connection): " << e);
}
else // Drop connection frames while state < CATCHUP
- QPID_LOG_IF(trace, loggable(e.frame), *this << " DROP (joining): " << e);
+ QPID_LOG(trace, *this << " DROP (joining): " << e);
}
// Called in deliverFrameQueue thread
@@ -583,7 +577,7 @@ Cluster::ConnectionVector Cluster::getConnections(Lock&) {
}
// CPG config-change callback.
-void Cluster::configChange (
+void Cluster::configChange (
cpg_handle_t /*handle*/,
const cpg_name */*group*/,
const cpg_address *members, int nMembers,
@@ -613,7 +607,7 @@ void Cluster::setReady(Lock&) {
}
// Set the management status from the Cluster::state.
-//
+//
// NOTE: Management updates are sent based on property changes. In
// order to keep consistency across the cluster, we touch the local
// management status property even if it is locally unchanged for any
@@ -624,7 +618,7 @@ void Cluster::setMgmtStatus(Lock&) {
}
void Cluster::initMapCompleted(Lock& l) {
- // Called on completion of the initial status map.
+ // Called on completion of the initial status map.
QPID_LOG(debug, *this << " initial status map complete. ");
setMgmtStatus(l);
if (state == PRE_INIT) {
@@ -671,8 +665,6 @@ void Cluster::initMapCompleted(Lock& l) {
else { // I can go ready.
discarding = false;
setReady(l);
- // Must be called *before* memberUpdate so first update will be generated.
- failoverExchange->setReady();
memberUpdate(l);
updateMgmtMembership(l);
mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self);
@@ -709,8 +701,8 @@ void Cluster::configChange(const MemberId&,
if (initMap.isResendNeeded()) {
mcast.mcastControl(
ClusterInitialStatusBody(
- ProtocolVersion(), CLUSTER_VERSION, state > INIT, clusterId,
- store.getState(), store.getShutdownId(),
+ ProtocolVersion(), CLUSTER_VERSION, state > INIT, clusterId,
+ store.getState(), store.getShutdownId(),
initMap.getFirstConfigStr()
),
self);
@@ -725,20 +717,6 @@ void Cluster::configChange(const MemberId&,
updateMgmtMembership(l); // Update on every config change for consistency
}
-struct ClusterClockTask : public sys::TimerTask {
- Cluster& cluster;
- sys::Timer& timer;
-
- ClusterClockTask(Cluster& cluster, sys::Timer& timer, uint16_t clockInterval)
- : TimerTask(Duration(clockInterval * TIME_MSEC),"ClusterClock"), cluster(cluster), timer(timer) {}
-
- void fire() {
- cluster.sendClockUpdate();
- setupNextFire();
- timer.add(this);
- }
-};
-
void Cluster::becomeElder(Lock&) {
if (elder) return; // We were already the elder.
// We are the oldest, reactive links if necessary
@@ -746,8 +724,6 @@ void Cluster::becomeElder(Lock&) {
elder = true;
broker.getLinks().setPassive(false);
timer->becomeElder();
-
- clockTimer.add(new ClusterClockTask(*this, clockTimer, settings.clockInterval));
}
void Cluster::makeOffer(const MemberId& id, Lock& ) {
@@ -783,7 +759,7 @@ std::string Cluster::debugSnapshot() {
// point we know the poller has stopped so no poller callbacks will be
// invoked. We must ensure that CPG has also shut down so no CPG
// callbacks will be invoked.
-//
+//
void Cluster::brokerShutdown() {
sys::ClusterSafeScope css; // Don't trigger cluster-safe asserts.
try { cpg.shutdown(); }
@@ -799,7 +775,7 @@ void Cluster::updateRequest(const MemberId& id, const std::string& url, Lock& l)
}
void Cluster::initialStatus(const MemberId& member, uint32_t version, bool active,
- const framing::Uuid& id,
+ const framing::Uuid& id,
framing::cluster::StoreState store,
const framing::Uuid& shutdownId,
const std::string& firstConfig,
@@ -857,8 +833,6 @@ void Cluster::updateOffer(const MemberId& updater, uint64_t updateeInt, Lock& l)
else if (updatee == self && url) {
assert(state == JOINER);
state = UPDATEE;
- acl = broker.getAcl();
- broker.setAcl(0); // Disable ACL during update
QPID_LOG(notice, *this << " receiving update from " << updater);
checkUpdateIn(l);
}
@@ -870,7 +844,7 @@ void Cluster::updateOffer(const MemberId& updater, uint64_t updateeInt, Lock& l)
if (updatee != self && url) {
QPID_LOG(debug, debugSnapshot());
if (mAgent) mAgent->clusterUpdate();
- // Updatee will call clusterUpdate() via checkUpdateIn() when update completes
+ // Updatee will call clusterUpdate when update completes
}
}
@@ -951,15 +925,13 @@ void Cluster::checkUpdateIn(Lock& l) {
if (!updateClosed) return; // Wait till update connection closes.
if (updatedMap) { // We're up to date
map = *updatedMap;
+ failoverExchange->setUrls(getUrls(l));
mcast.mcastControl(ClusterReadyBody(ProtocolVersion(), myUrl.str()), self);
state = CATCHUP;
memberUpdate(l);
- // Must be called *after* memberUpdate() to avoid sending an extra update.
- failoverExchange->setReady();
// NB: don't updateMgmtMembership() here as we are not in the deliver
// thread. It will be updated on delivery of the "ready" we just mcast.
broker.setClusterUpdatee(false);
- broker.setAcl(acl); // Restore ACL
discarding = false; // OK to set, we're stalled for update.
QPID_LOG(notice, *this << " update complete, starting catch-up.");
QPID_LOG(debug, debugSnapshot()); // OK to call because we're stalled.
@@ -969,10 +941,6 @@ void Cluster::checkUpdateIn(Lock& l) {
mAgent->suppress(false); // Enable management output.
mAgent->clusterUpdate();
}
- // Restore alternate exchange settings on exchanges.
- broker.getExchanges().eachExchange(
- boost::bind(&broker::Exchange::recoveryComplete, _1,
- boost::ref(broker.getExchanges())));
enableClusterSafe(); // Enable cluster-safe assertions
deliverEventQueue.start();
}
@@ -1001,7 +969,7 @@ void Cluster::updateOutDone(Lock& l) {
void Cluster::updateOutError(const std::exception& e) {
Monitor::ScopedLock l(lock);
- QPID_LOG(error, *this << " error sending update: " << e.what());
+ QPID_LOG(error, *this << " error sending update: " << e.what());
updateOutDone(l);
}
@@ -1099,7 +1067,7 @@ void Cluster::memberUpdate(Lock& l) {
void Cluster::updateMgmtMembership(Lock& l) {
if (!mgmtObject) return;
std::vector<Url> urls = getUrls(l);
- mgmtObject->set_clusterSize(urls.size());
+ mgmtObject->set_clusterSize(urls.size());
string urlstr;
for(std::vector<Url>::iterator i = urls.begin(); i != urls.end(); i++ ) {
if (i != urls.begin()) urlstr += ";";
@@ -1146,6 +1114,10 @@ void Cluster::setClusterId(const Uuid& uuid, Lock&) {
QPID_LOG(notice, *this << " cluster-uuid = " << clusterId);
}
+void Cluster::messageExpired(const MemberId&, uint64_t id, Lock&) {
+ expiryPolicy->deliverExpire(id);
+}
+
void Cluster::errorCheck(const MemberId& from, uint8_t type, framing::SequenceNumber frameSeq, Lock&) {
// If we see an errorCheck here (rather than in the ErrorCheck
// class) then we have processed succesfully past the point of the
@@ -1183,35 +1155,6 @@ void Cluster::deliverToQueue(const std::string& queue, const std::string& messag
q->deliver(msg);
}
-sys::AbsTime Cluster::getClusterTime() {
- Mutex::ScopedLock l(lock);
- return clusterTime;
-}
-
-// This method is called during update on the updatee to set the initial cluster time.
-void Cluster::clock(const uint64_t time) {
- Mutex::ScopedLock l(lock);
- clock(time, l);
-}
-
-// called when broadcast message received
-void Cluster::clock(const uint64_t time, Lock&) {
- clusterTime = AbsTime(EPOCH, time);
- AbsTime now = AbsTime::now();
-
- if (!elder) {
- clusterTimeOffset = Duration(now, clusterTime);
- }
-}
-
-// called by elder timer to send clock broadcast
-void Cluster::sendClockUpdate() {
- Mutex::ScopedLock l(lock);
- int64_t nanosecondsSinceEpoch = Duration(EPOCH, now());
- nanosecondsSinceEpoch += clusterTimeOffset;
- mcast.mcastControl(ClusterClockBody(ProtocolVersion(), nanosecondsSinceEpoch), self);
-}
-
bool Cluster::deferDeliveryImpl(const std::string& queue,
const boost::intrusive_ptr<broker::Message>& msg)
{
@@ -1224,12 +1167,4 @@ bool Cluster::deferDeliveryImpl(const std::string& queue,
return true;
}
-bool Cluster::loggable(const AMQFrame& f) {
- const AMQMethodBody* method = (f.getMethod());
- if (!method) return true; // Not a method
- bool isClock = method->amqpClassId() == ClusterClockBody::CLASS_ID
- && method->amqpMethodId() == ClusterClockBody::METHOD_ID;
- return !isClock;
-}
-
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Cluster.h b/cpp/src/qpid/cluster/Cluster.h
index ccec4948e6..8f73c6acca 100644
--- a/cpp/src/qpid/cluster/Cluster.h
+++ b/cpp/src/qpid/cluster/Cluster.h
@@ -56,25 +56,17 @@ namespace qpid {
namespace broker {
class Message;
-class AclModule;
}
namespace framing {
-class AMQFrame;
class AMQBody;
-struct Uuid;
-}
-
-namespace sys {
-class Timer;
-class AbsTime;
-class Duration;
+class Uuid;
}
namespace cluster {
class Connection;
-struct EventFrame;
+class EventFrame;
class ClusterTimer;
class UpdateDataExchange;
@@ -97,10 +89,10 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void initialize();
// Connection map.
- void addLocalConnection(const ConnectionPtr&);
- void addShadowConnection(const ConnectionPtr&);
- void erase(const ConnectionId&);
-
+ void addLocalConnection(const ConnectionPtr&);
+ void addShadowConnection(const ConnectionPtr&);
+ void erase(const ConnectionId&);
+
// URLs of current cluster members.
std::vector<std::string> getIds() const;
std::vector<Url> getUrls() const;
@@ -115,7 +107,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void updateInRetracted();
// True if we are expecting to receive catch-up connections.
bool isExpectingUpdate();
-
+
MemberId getId() const;
broker::Broker& getBroker() const;
Multicaster& getMulticast() { return mcast; }
@@ -143,12 +135,6 @@ class Cluster : private Cpg::Handler, public management::Manageable {
bool deferDeliveryImpl(const std::string& queue,
const boost::intrusive_ptr<broker::Message>& msg);
- sys::AbsTime getClusterTime();
- void sendClockUpdate();
- void clock(const uint64_t time);
-
- static bool loggable(const framing::AMQFrame&); // True if the frame should be logged.
-
private:
typedef sys::Monitor::ScopedLock Lock;
@@ -158,10 +144,10 @@ class Cluster : private Cpg::Handler, public management::Manageable {
/** Version number of the cluster protocol, to avoid mixed versions. */
static const uint32_t CLUSTER_VERSION;
-
+
// NB: A dummy Lock& parameter marks functions that must only be
// called with Cluster::lock locked.
-
+
void leave(Lock&);
std::vector<std::string> getIds(Lock&) const;
std::vector<Url> getUrls(Lock&) const;
@@ -170,11 +156,11 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void brokerShutdown();
// == Called in deliverEventQueue thread
- void deliveredEvent(const Event&);
+ void deliveredEvent(const Event&);
// == Called in deliverFrameQueue thread
- void deliveredFrame(const EventFrame&);
- void processFrame(const EventFrame&, Lock&);
+ void deliveredFrame(const EventFrame&);
+ void processFrame(const EventFrame&, Lock&);
// Cluster controls implement XML methods from cluster.xml.
void updateRequest(const MemberId&, const std::string&, Lock&);
@@ -194,12 +180,12 @@ class Cluster : private Cpg::Handler, public management::Manageable {
const std::string& left,
const std::string& joined,
Lock& l);
+ void messageExpired(const MemberId&, uint64_t, Lock& l);
void errorCheck(const MemberId&, uint8_t type, SequenceNumber frameSeq, Lock&);
void timerWakeup(const MemberId&, const std::string& name, Lock&);
void timerDrop(const MemberId&, const std::string& name, Lock&);
void shutdown(const MemberId&, const framing::Uuid& shutdownId, Lock&);
void deliverToQueue(const std::string& queue, const std::string& message, Lock&);
- void clock(const uint64_t time, Lock&);
// Helper functions
ConnectionPtr getConnection(const EventFrame&, Lock&);
@@ -209,7 +195,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void setReady(Lock&);
void memberUpdate(Lock&);
void setClusterId(const framing::Uuid&, Lock&);
- void erase(const ConnectionId&, Lock&);
+ void erase(const ConnectionId&, Lock&);
void requestUpdate(Lock& );
void initMapCompleted(Lock&);
void becomeElder(Lock&);
@@ -217,7 +203,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
void updateMgmtMembership(Lock&);
// == Called in CPG dispatch thread
- void deliver( // CPG deliver callback.
+ void deliver( // CPG deliver callback.
cpg_handle_t /*handle*/,
const struct cpg_name *group,
uint32_t /*nodeid*/,
@@ -226,7 +212,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
int /*msg_len*/);
void deliverEvent(const Event&);
-
+
void configChange( // CPG config change callback.
cpg_handle_t /*handle*/,
const struct cpg_name */*group*/,
@@ -277,7 +263,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
// Used only in deliverEventQueue thread or when stalled for update.
Decoder decoder;
bool discarding;
-
+
// Remaining members are protected by lock.
mutable sys::Monitor lock;
@@ -290,7 +276,7 @@ class Cluster : private Cpg::Handler, public management::Manageable {
JOINER, ///< Sent update request, waiting for update offer.
UPDATEE, ///< Stalled receive queue at update offer, waiting for update to complete.
CATCHUP, ///< Update complete, unstalled but has not yet seen own "ready" event.
- READY, ///< Fully operational
+ READY, ///< Fully operational
OFFER, ///< Sent an offer, waiting for accept/reject.
UPDATER, ///< Offer accepted, sending a state update.
LEFT ///< Final state, left the cluster.
@@ -310,13 +296,9 @@ class Cluster : private Cpg::Handler, public management::Manageable {
ErrorCheck error;
UpdateReceiver updateReceiver;
ClusterTimer* timer;
- sys::Timer clockTimer;
- sys::AbsTime clusterTime;
- sys::Duration clusterTimeOffset;
- broker::AclModule* acl;
friend std::ostream& operator<<(std::ostream&, const Cluster&);
- friend struct ClusterDispatcher;
+ friend class ClusterDispatcher;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/ClusterMap.cpp b/cpp/src/qpid/cluster/ClusterMap.cpp
index a8389095c9..040e129970 100644
--- a/cpp/src/qpid/cluster/ClusterMap.cpp
+++ b/cpp/src/qpid/cluster/ClusterMap.cpp
@@ -50,6 +50,11 @@ void insertFieldTableFromMapValue(FieldTable& ft, const ClusterMap::Map::value_t
ft.setString(vt.first.str(), vt.second.str());
}
+void assignFieldTable(FieldTable& ft, const ClusterMap::Map& map) {
+ ft.clear();
+ for_each(map.begin(), map.end(), bind(&insertFieldTableFromMapValue, ref(ft), _1));
+}
+
}
ClusterMap::ClusterMap() : frameSeq(0) {}
diff --git a/cpp/src/qpid/cluster/ClusterPlugin.cpp b/cpp/src/qpid/cluster/ClusterPlugin.cpp
index 69ba095f16..2962daaa07 100644
--- a/cpp/src/qpid/cluster/ClusterPlugin.cpp
+++ b/cpp/src/qpid/cluster/ClusterPlugin.cpp
@@ -72,7 +72,6 @@ struct ClusterOptions : public Options {
("cluster-cman", optValue(settings.quorum), "Integrate with Cluster Manager (CMAN) cluster.")
#endif
("cluster-size", optValue(settings.size, "N"), "Wait for N cluster members before allowing clients to connect.")
- ("cluster-clock-interval", optValue(settings.clockInterval,"N"), "How often to broadcast the current time to the cluster nodes, in milliseconds. A value between 5 and 1000 is recommended.")
("cluster-read-max", optValue(settings.readMax,"N"), "Experimental: flow-control limit reads per connection. 0=no limit.")
;
}
diff --git a/cpp/src/qpid/cluster/ClusterSettings.h b/cpp/src/qpid/cluster/ClusterSettings.h
index 2f7b5be20a..8e708aa139 100644
--- a/cpp/src/qpid/cluster/ClusterSettings.h
+++ b/cpp/src/qpid/cluster/ClusterSettings.h
@@ -35,9 +35,8 @@ struct ClusterSettings {
size_t readMax;
std::string username, password, mechanism;
size_t size;
- uint16_t clockInterval;
- ClusterSettings() : quorum(false), readMax(10), size(1), clockInterval(10)
+ ClusterSettings() : quorum(false), readMax(10), size(1)
{}
Url getUrl(uint16_t port) const {
diff --git a/cpp/src/qpid/cluster/ClusterTimer.cpp b/cpp/src/qpid/cluster/ClusterTimer.cpp
index b4f7d00f38..f6e1c7a849 100644
--- a/cpp/src/qpid/cluster/ClusterTimer.cpp
+++ b/cpp/src/qpid/cluster/ClusterTimer.cpp
@@ -70,7 +70,6 @@ void ClusterTimer::add(intrusive_ptr<TimerTask> task)
if (i != map.end())
throw Exception(QPID_MSG("Task already exists with name " << task->getName()));
map[task->getName()] = task;
-
// Only the elder actually activates the task with the Timer base class.
if (cluster.isElder()) {
QPID_LOG(trace, "Elder activating cluster timer task " << task->getName());
@@ -113,9 +112,6 @@ void ClusterTimer::deliverWakeup(const std::string& name) {
else {
intrusive_ptr<TimerTask> t = i->second;
map.erase(i);
- // Move the nextFireTime so readyToFire() is true. This is to ensure we
- // don't get an error if the fired task calls setupNextFire()
- t->setFired();
Timer::fire(t);
}
}
diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp
index 394749aad2..e9b718e6de 100644
--- a/cpp/src/qpid/cluster/Connection.cpp
+++ b/cpp/src/qpid/cluster/Connection.cpp
@@ -7,9 +7,9 @@
* 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
@@ -24,8 +24,6 @@
#include "Cluster.h"
#include "UpdateReceiver.h"
#include "qpid/assert.h"
-#include "qpid/broker/DtxAck.h"
-#include "qpid/broker/DtxBuffer.h"
#include "qpid/broker/SessionState.h"
#include "qpid/broker/SemanticState.h"
#include "qpid/broker/TxBuffer.h"
@@ -37,7 +35,6 @@
#include "qpid/broker/Fairshare.h"
#include "qpid/broker/Link.h"
#include "qpid/broker/Bridge.h"
-#include "qpid/broker/StatefulQueueObserver.h"
#include "qpid/broker/Queue.h"
#include "qpid/framing/enum.h"
#include "qpid/framing/AMQFrame.h"
@@ -81,7 +78,7 @@ const std::string shadowPrefix("[shadow]");
Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
const std::string& mgmtId,
const ConnectionId& id, const qpid::sys::SecuritySettings& external)
- : cluster(c), self(id), catchUp(false), announced(false), output(*this, out),
+ : cluster(c), self(id), catchUp(false), output(*this, out),
connectionCtor(&output, cluster.getBroker(), mgmtId, external, false, 0, true),
expectProtocolHeader(false),
mcastFrameHandler(cluster.getMulticast(), self),
@@ -93,15 +90,13 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
const std::string& mgmtId, MemberId member,
bool isCatchUp, bool isLink, const qpid::sys::SecuritySettings& external
-) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), announced(false), output(*this, out),
+) : cluster(c), self(member, ++idCounter), catchUp(isCatchUp), output(*this, out),
connectionCtor(&output, cluster.getBroker(),
mgmtId,
external,
isLink,
isCatchUp ? ++catchUpId : 0,
- // The first catch-up connection is not considered a shadow
- // as it needs to be authenticated.
- isCatchUp && self.second > 1),
+ isCatchUp), // isCatchUp => shadow
expectProtocolHeader(isLink),
mcastFrameHandler(cluster.getMulticast(), self),
updateIn(c.getUpdateReceiver()),
@@ -118,7 +113,7 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out,
if (!updateIn.nextShadowMgmtId.empty())
connectionCtor.mgmtId = updateIn.nextShadowMgmtId;
updateIn.nextShadowMgmtId.clear();
- }
+ }
init();
QPID_LOG(debug, cluster << " local connection " << *this);
}
@@ -148,7 +143,7 @@ void Connection::init() {
// Called when we have consumed a read buffer to give credit to the
// connection layer to continue reading.
void Connection::giveReadCredit(int credit) {
- if (cluster.getSettings().readMax && credit)
+ if (cluster.getSettings().readMax && credit)
output.giveReadCredit(credit);
}
@@ -171,7 +166,7 @@ void Connection::announce(
AMQFrame frame;
while (frame.decode(buf))
connection->received(frame);
- connection->setUserId(username);
+ connection->setUserId(username);
}
// Do managment actions now that the connection is replicated.
connection->raiseConnectEvent();
@@ -198,7 +193,7 @@ void Connection::received(framing::AMQFrame& f) {
<< *this << ": " << f);
return;
}
- QPID_LOG_IF(trace, Cluster::loggable(f), cluster << " RECV " << *this << ": " << f);
+ QPID_LOG(trace, cluster << " RECV " << *this << ": " << f);
if (isLocal()) { // Local catch-up connection.
currentChannel = f.getChannel();
if (!framing::invoke(*this, *f.getBody()).wasHandled())
@@ -206,7 +201,7 @@ void Connection::received(framing::AMQFrame& f) {
}
else { // Shadow or updated catch-up connection.
if (f.getMethod() && f.getMethod()->isA<ConnectionCloseBody>()) {
- if (isShadow())
+ if (isShadow())
cluster.addShadowConnection(this);
AMQFrame ok((ConnectionCloseOkBody()));
connection->getOutput().send(ok);
@@ -218,9 +213,16 @@ void Connection::received(framing::AMQFrame& f) {
}
}
-bool Connection::checkUnsupported(const AMQBody&) {
- // Throw an exception for unsupported commands. Currently all are supported.
- return false;
+bool Connection::checkUnsupported(const AMQBody& body) {
+ std::string message;
+ if (body.getMethod()) {
+ switch (body.getMethod()->amqpClassId()) {
+ case DTX_CLASS_ID: message = "DTX transactions are not currently supported by cluster."; break;
+ }
+ }
+ if (!message.empty())
+ connection->close(connection::CLOSE_CODE_FRAMING_ERROR, message);
+ return !message.empty();
}
struct GiveReadCreditOnExit {
@@ -239,7 +241,7 @@ void Connection::deliverDoOutput(uint32_t limit) {
void Connection::deliveredFrame(const EventFrame& f) {
GiveReadCreditOnExit gc(*this, f.readCredit);
assert(!catchUp);
- currentChannel = f.frame.getChannel();
+ currentChannel = f.frame.getChannel();
if (f.frame.getBody() // frame can be emtpy with just readCredit
&& !framing::invoke(*this, *f.frame.getBody()).wasHandled() // Connection contol.
&& !checkUnsupported(*f.frame.getBody())) // Unsupported operation.
@@ -253,7 +255,7 @@ void Connection::deliveredFrame(const EventFrame& f) {
}
}
-// A local connection is closed by the network layer. Called in the connection thread.
+// A local connection is closed by the network layer.
void Connection::closed() {
try {
if (isUpdated()) {
@@ -270,9 +272,8 @@ void Connection::closed() {
// closed and process any outstanding frames from the cluster
// until self-delivery of deliver-close.
output.closeOutput();
- if (announced)
- cluster.getMulticast().mcastControl(
- ClusterConnectionDeliverCloseBody(), self);
+ cluster.getMulticast().mcastControl(
+ ClusterConnectionDeliverCloseBody(), self);
}
}
catch (const std::exception& e) {
@@ -286,7 +287,7 @@ void Connection::deliverClose () {
cluster.erase(self);
}
-// Close the connection
+// Close the connection
void Connection::close() {
if (connection.get()) {
QPID_LOG(debug, cluster << " closed connection " << *this);
@@ -319,10 +320,10 @@ size_t Connection::decode(const char* data, size_t size) {
while (localDecoder.decode(buf))
received(localDecoder.getFrame());
if (!wasOpen && connection->isOpen()) {
- // Connections marked with setUserProxyAuth are allowed to proxy
+ // Connections marked as federation links are allowed to proxy
// messages with user-ID that doesn't match the connection's
// authenticated ID. This is important for updates.
- connection->setUserProxyAuth(isCatchUp());
+ connection->setFederationLink(isCatchUp());
}
}
else { // Multicast local connections.
@@ -331,9 +332,9 @@ size_t Connection::decode(const char* data, size_t size) {
if (!checkProtocolHeader(ptr, size)) // Updates ptr
return 0; // Incomplete header
- if (!connection->isOpen())
+ if (!connection->isOpen())
processInitialFrames(ptr, end-ptr); // Updates ptr
-
+
if (connection->isOpen() && end - ptr > 0) {
// We're multi-casting, we will give read credit on delivery.
grc.credit = 0;
@@ -383,7 +384,6 @@ void Connection::processInitialFrames(const char*& ptr, size_t size) {
connection->getUserId(),
initialFrames),
getId());
- announced = true;
initialFrames.clear();
}
}
@@ -406,11 +406,11 @@ void Connection::shadowSetUser(const std::string& userId) {
void Connection::consumerState(const string& name, bool blocked, bool notifyEnabled, const SequenceNumber& position)
{
- broker::SemanticState::ConsumerImpl::shared_ptr c = semanticState().find(name);
- c->position = position;
- c->setBlocked(blocked);
- if (notifyEnabled) c->enableNotify(); else c->disableNotify();
- updateIn.consumerNumbering.add(c);
+ broker::SemanticState::ConsumerImpl& c = semanticState().find(name);
+ c.position = position;
+ c.setBlocked(blocked);
+ if (notifyEnabled) c.enableNotify(); else c.disableNotify();
+ updateIn.consumerNumbering.add(c.shared_from_this());
}
@@ -421,8 +421,7 @@ void Connection::sessionState(
const SequenceNumber& expected,
const SequenceNumber& received,
const SequenceSet& unknownCompleted,
- const SequenceSet& receivedIncomplete,
- bool dtxSelected)
+ const SequenceSet& receivedIncomplete)
{
sessionState().setState(
replayStart,
@@ -432,10 +431,8 @@ void Connection::sessionState(
received,
unknownCompleted,
receivedIncomplete);
- if (dtxSelected) semanticState().selectDtx();
- QPID_LOG(debug, cluster << " received session state update for "
- << sessionState().getId());
- // The output tasks will be added later in the update process.
+ QPID_LOG(debug, cluster << " received session state update for " << sessionState().getId());
+ // The output tasks will be added later in the update process.
connection->getOutputTasks().removeAll();
}
@@ -444,7 +441,7 @@ void Connection::outputTask(uint16_t channel, const std::string& name) {
if (!session)
throw Exception(QPID_MSG(cluster << " channel not attached " << *this
<< "[" << channel << "] "));
- OutputTask* task = session->getSemanticState().find(name).get();
+ OutputTask* task = &session->getSemanticState().find(name);
connection->getOutputTasks().addOutputTask(task);
}
@@ -464,24 +461,11 @@ void Connection::shadowReady(
output.setSendMax(sendMax);
}
-void Connection::setDtxBuffer(const UpdateReceiver::DtxBufferRef& bufRef) {
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- broker::DtxWorkRecord* record = mgr.getWork(bufRef.xid);
- broker::DtxBuffer::shared_ptr buffer = (*record)[bufRef.index];
- if (bufRef.suspended)
- bufRef.semanticState->getSuspendedXids()[bufRef.xid] = buffer;
- else
- bufRef.semanticState->setDtxBuffer(buffer);
-}
-
-// Marks the end of the update.
void Connection::membership(const FieldTable& joiners, const FieldTable& members,
const framing::SequenceNumber& frameSeq)
{
QPID_LOG(debug, cluster << " incoming update complete on connection " << *this);
updateIn.consumerNumbering.clear();
- for_each(updateIn.dtxBuffers.begin(), updateIn.dtxBuffers.end(),
- boost::bind(&Connection::setDtxBuffer, this, _1));
closeUpdated();
cluster.updateInDone(ClusterMap(joiners, members, frameSeq));
}
@@ -494,7 +478,7 @@ void Connection::retractOffer() {
void Connection::closeUpdated() {
self.second = 0; // Mark this as completed update connection.
- if (connection.get())
+ if (connection.get())
connection->close(connection::CLOSE_CODE_NORMAL, "OK");
}
@@ -545,20 +529,12 @@ void Connection::deliveryRecord(const string& qname,
m = getUpdateMessage();
m.queue = queue.get();
m.position = position;
- if (enqueued) queue->updateEnqueued(m); //inform queue of the message
+ if (enqueued) queue->updateEnqueued(m); //inform queue of the message
} else { // Message at original position in original queue
- queue->find(position, m);
+ m = queue->find(position);
}
- // FIXME aconway 2011-08-19: removed:
- // if (!m.payload)
- // throw Exception(QPID_MSG("deliveryRecord no update message"));
- //
- // It seems this could happen legitimately in the case one
- // session browses message M, then another session acquires
- // it. In that case the browsers delivery record is !acquired
- // but the message is not on its original Queue. In that case
- // we'll get a deliveryRecord with no payload for the browser.
- //
+ if (!m.payload)
+ throw Exception(QPID_MSG("deliveryRecord no update message"));
}
broker::DeliveryRecord dr(m, queue, tag, acquired, accepted, windowing, credit);
@@ -566,11 +542,7 @@ void Connection::deliveryRecord(const string& qname,
if (cancelled) dr.cancel(dr.getTag());
if (completed) dr.complete();
if (ended) dr.setEnded(); // Exsitance of message
-
- if (dtxBuffer) // Record for next dtx-ack
- dtxAckRecords.push_back(dr);
- else
- semanticState().record(dr); // Record on session's unacked list.
+ semanticState().record(dr); // Part of the session's unacked list.
}
void Connection::queuePosition(const string& qname, const SequenceNumber& position) {
@@ -584,46 +556,8 @@ void Connection::queueFairshareState(const std::string& qname, const uint8_t pri
}
}
-
-namespace {
-// find a StatefulQueueObserver that matches a given identifier
-class ObserverFinder {
- const std::string id;
- boost::shared_ptr<broker::QueueObserver> target;
- ObserverFinder(const ObserverFinder&) {}
- public:
- ObserverFinder(const std::string& _id) : id(_id) {}
- broker::StatefulQueueObserver *getObserver()
- {
- if (target)
- return dynamic_cast<broker::StatefulQueueObserver *>(target.get());
- return 0;
- }
- void operator() (boost::shared_ptr<broker::QueueObserver> o)
- {
- if (!target) {
- broker::StatefulQueueObserver *p = dynamic_cast<broker::StatefulQueueObserver *>(o.get());
- if (p && p->getId() == id) {
- target = o;
- }
- }
- }
-};
-}
-
-
-void Connection::queueObserverState(const std::string& qname, const std::string& observerId, const FieldTable& state)
-{
- boost::shared_ptr<broker::Queue> queue(findQueue(qname));
- ObserverFinder finder(observerId); // find this observer
- queue->eachObserver<ObserverFinder &>(finder);
- broker::StatefulQueueObserver *so = finder.getObserver();
- if (so) {
- so->setState( state );
- QPID_LOG(debug, "updated queue observer " << observerId << "'s state on queue " << qname << "; ...");
- return;
- }
- QPID_LOG(error, "Failed to find observer " << observerId << " state on queue " << qname << "; this will result in inconsistencies.");
+void Connection::expiryId(uint64_t id) {
+ cluster.getExpiryPolicy().setId(id);
}
std::ostream& operator<<(std::ostream& o, const Connection& c) {
@@ -640,7 +574,6 @@ std::ostream& operator<<(std::ostream& o, const Connection& c) {
void Connection::txStart() {
txBuffer.reset(new broker::TxBuffer());
}
-
void Connection::txAccept(const framing::SequenceSet& acked) {
txBuffer->enlist(boost::shared_ptr<broker::TxAccept>(
new broker::TxAccept(acked, semanticState().getUnacked())));
@@ -656,11 +589,9 @@ void Connection::txEnqueue(const std::string& queue) {
new broker::RecoveredEnqueue(findQueue(queue), getUpdateMessage().payload)));
}
-void Connection::txPublish(const framing::Array& queues, bool delivered)
-{
- boost::shared_ptr<broker::TxPublish> txPub(
- new broker::TxPublish(getUpdateMessage().payload));
- for (framing::Array::const_iterator i = queues.begin(); i != queues.end(); ++i)
+void Connection::txPublish(const framing::Array& queues, bool delivered) {
+ boost::shared_ptr<broker::TxPublish> txPub(new broker::TxPublish(getUpdateMessage().payload));
+ for (framing::Array::const_iterator i = queues.begin(); i != queues.end(); ++i)
txPub->deliverTo(findQueue((*i)->get<std::string>()));
txPub->delivered = delivered;
txBuffer->enlist(txPub);
@@ -674,51 +605,6 @@ void Connection::accumulatedAck(const qpid::framing::SequenceSet& s) {
semanticState().setAccumulatedAck(s);
}
-void Connection::dtxStart(const std::string& xid,
- bool ended,
- bool suspended,
- bool failed,
- bool expired)
-{
- dtxBuffer.reset(new broker::DtxBuffer(xid, ended, suspended, failed, expired));
- txBuffer = dtxBuffer;
-}
-
-void Connection::dtxEnd() {
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- std::string xid = dtxBuffer->getXid();
- if (mgr.exists(xid))
- mgr.join(xid, dtxBuffer);
- else
- mgr.start(xid, dtxBuffer);
- dtxBuffer.reset();
- txBuffer.reset();
-}
-
-// Sent after all DeliveryRecords for a dtx-ack have been collected in dtxAckRecords
-void Connection::dtxAck() {
- dtxBuffer->enlist(
- boost::shared_ptr<broker::DtxAck>(new broker::DtxAck(dtxAckRecords)));
- dtxAckRecords.clear();
-}
-
-void Connection::dtxBufferRef(const std::string& xid, uint32_t index, bool suspended) {
- // Save the association between DtxBuffers and the session so we
- // can set the DtxBuffers at the end of the update when the
- // DtxManager has been replicated.
- updateIn.dtxBuffers.push_back(
- UpdateReceiver::DtxBufferRef(xid, index, suspended, &semanticState()));
-}
-
-// Sent at end of work record.
-void Connection::dtxWorkRecord(const std::string& xid, bool prepared, uint32_t timeout)
-{
- broker::DtxManager& mgr = cluster.getBroker().getDtxManager();
- if (timeout) mgr.setTimeout(xid, timeout);
- if (prepared) mgr.prepare(xid);
-}
-
-
void Connection::exchange(const std::string& encoded) {
Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
broker::Exchange::shared_ptr ex = broker::Exchange::decode(cluster.getBroker().getExchanges(), buf);
@@ -728,6 +614,12 @@ void Connection::exchange(const std::string& encoded) {
QPID_LOG(debug, cluster << " updated exchange " << ex->getName());
}
+void Connection::queue(const std::string& encoded) {
+ Buffer buf(const_cast<char*>(encoded.data()), encoded.size());
+ broker::Queue::shared_ptr q = broker::Queue::decode(cluster.getBroker().getQueues(), buf);
+ QPID_LOG(debug, cluster << " updated queue " << q->getName());
+}
+
void Connection::sessionError(uint16_t , const std::string& msg) {
// Ignore errors before isOpen(), we're not multicasting yet.
if (connection->isOpen())
@@ -786,23 +678,6 @@ void Connection::config(const std::string& encoded) {
else throw Exception(QPID_MSG("Update failed, invalid kind of config: " << kind));
}
-void Connection::doCatchupIoCallbacks() {
- // We need to process IO callbacks during the catch-up phase in
- // order to service asynchronous completions for messages
- // transferred during catch-up.
-
- if (catchUp) getBrokerConnection()->doIoCallbacks();
-}
-
-void Connection::clock(uint64_t time) {
- QPID_LOG(debug, "Cluster connection received time update");
- cluster.clock(time);
-}
-
-void Connection::queueDequeueSincePurgeState(const std::string& qname, uint32_t dequeueSincePurge) {
- boost::shared_ptr<broker::Queue> queue(findQueue(qname));
- queue->setDequeueSincePurge(dequeueSincePurge);
-}
}} // Namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Connection.h b/cpp/src/qpid/cluster/Connection.h
index fe66b77238..7ee85bf1aa 100644
--- a/cpp/src/qpid/cluster/Connection.h
+++ b/cpp/src/qpid/cluster/Connection.h
@@ -10,9 +10,9 @@
* 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
@@ -24,12 +24,11 @@
#include "types.h"
#include "OutputInterceptor.h"
+#include "EventFrame.h"
#include "McastFrameHandler.h"
#include "UpdateReceiver.h"
-#include "qpid/RefCounted.h"
#include "qpid/broker/Connection.h"
-#include "qpid/broker/DeliveryRecord.h"
#include "qpid/broker/SecureConnection.h"
#include "qpid/broker/SemanticState.h"
#include "qpid/amqp_0_10/Connection.h"
@@ -48,7 +47,7 @@ namespace framing { class AMQFrame; }
namespace broker {
class SemanticState;
-struct QueuedMessage;
+class QueuedMessage;
class TxBuffer;
class TxAccept;
}
@@ -56,7 +55,6 @@ class TxAccept;
namespace cluster {
class Cluster;
class Event;
-struct EventFrame;
/** Intercept broker::Connection calls for shadow and local cluster connections. */
class Connection :
@@ -64,7 +62,7 @@ class Connection :
public sys::ConnectionInputHandler,
public framing::AMQP_AllOperations::ClusterConnectionHandler,
private broker::Connection::ErrorListener
-
+
{
public:
@@ -75,7 +73,7 @@ class Connection :
Connection(Cluster&, sys::ConnectionOutputHandler& out, const std::string& mgmtId, const ConnectionId& id,
const qpid::sys::SecuritySettings& external);
~Connection();
-
+
ConnectionId getId() const { return self; }
broker::Connection* getBrokerConnection() { return connection.get(); }
const broker::Connection* getBrokerConnection() const { return connection.get(); }
@@ -110,9 +108,9 @@ class Connection :
void deliveredFrame(const EventFrame&);
void consumerState(const std::string& name, bool blocked, bool notifyEnabled, const qpid::framing::SequenceNumber& position);
-
+
// ==== Used in catch-up mode to build initial state.
- //
+ //
// State update methods.
void shadowPrepare(const std::string&);
@@ -124,11 +122,10 @@ class Connection :
const framing::SequenceNumber& expected,
const framing::SequenceNumber& received,
const framing::SequenceSet& unknownCompleted,
- const SequenceSet& receivedIncomplete,
- bool dtxSelected);
-
+ const SequenceSet& receivedIncomplete);
+
void outputTask(uint16_t channel, const std::string& name);
-
+
void shadowReady(uint64_t memberId,
uint64_t connectionId,
const std::string& managementId,
@@ -156,7 +153,7 @@ class Connection :
void queuePosition(const std::string&, const framing::SequenceNumber&);
void queueFairshareState(const std::string&, const uint8_t priority, const uint8_t count);
- void queueObserverState(const std::string&, const std::string&, const framing::FieldTable&);
+ void expiryId(uint64_t);
void txStart();
void txAccept(const framing::SequenceSet&);
@@ -166,18 +163,8 @@ class Connection :
void txEnd();
void accumulatedAck(const framing::SequenceSet&);
- // Dtx state
- void dtxStart(const std::string& xid,
- bool ended,
- bool suspended,
- bool failed,
- bool expired);
- void dtxEnd();
- void dtxAck();
- void dtxBufferRef(const std::string& xid, uint32_t index, bool suspended);
- void dtxWorkRecord(const std::string& xid, bool prepared, uint32_t timeout);
-
- // Encoded exchange replication.
+ // Encoded queue/exchange replication.
+ void queue(const std::string& encoded);
void exchange(const std::string& encoded);
void giveReadCredit(int credit);
@@ -202,12 +189,6 @@ class Connection :
void setSecureConnection ( broker::SecureConnection * sc );
- void doCatchupIoCallbacks();
-
- void clock(uint64_t time);
-
- void queueDequeueSincePurgeState(const std::string&, uint32_t);
-
private:
struct NullFrameHandler : public framing::FrameHandler {
void handle(framing::AMQFrame&) {}
@@ -252,7 +233,7 @@ class Connection :
// Error listener functions
void connectionError(const std::string&);
void sessionError(uint16_t channel, const std::string&);
-
+
void init();
bool checkUnsupported(const framing::AMQBody& body);
void deliverDoOutput(uint32_t limit);
@@ -264,11 +245,10 @@ class Connection :
broker::SemanticState& semanticState();
broker::QueuedMessage getUpdateMessage();
void closeUpdated();
- void setDtxBuffer(const UpdateReceiver::DtxBuffers::value_type &);
+
Cluster& cluster;
ConnectionId self;
bool catchUp;
- bool announced;
OutputInterceptor output;
framing::FrameDecoder localDecoder;
ConnectionCtor connectionCtor;
@@ -276,9 +256,6 @@ class Connection :
framing::SequenceNumber deliverSeq;
framing::ChannelId currentChannel;
boost::shared_ptr<broker::TxBuffer> txBuffer;
- boost::shared_ptr<broker::DtxBuffer> dtxBuffer;
- broker::DeliveryRecords dtxAckRecords;
- broker::DtxWorkRecord* dtxCurrent;
bool expectProtocolHeader;
McastFrameHandler mcastFrameHandler;
UpdateReceiver& updateIn;
diff --git a/cpp/src/qpid/cluster/Decoder.h b/cpp/src/qpid/cluster/Decoder.h
index 3b5ada4a81..2e2af2868f 100644
--- a/cpp/src/qpid/cluster/Decoder.h
+++ b/cpp/src/qpid/cluster/Decoder.h
@@ -31,7 +31,7 @@
namespace qpid {
namespace cluster {
-struct EventFrame;
+class EventFrame;
class EventHeader;
/**
diff --git a/cpp/src/qpid/cluster/ErrorCheck.h b/cpp/src/qpid/cluster/ErrorCheck.h
index a417b2ec25..de8cedafb3 100644
--- a/cpp/src/qpid/cluster/ErrorCheck.h
+++ b/cpp/src/qpid/cluster/ErrorCheck.h
@@ -33,7 +33,7 @@
namespace qpid {
namespace cluster {
-struct EventFrame;
+class EventFrame;
class Cluster;
class Multicaster;
class Connection;
diff --git a/cpp/src/qpid/cluster/Event.cpp b/cpp/src/qpid/cluster/Event.cpp
index da2bc89d8c..cd775ce2f1 100644
--- a/cpp/src/qpid/cluster/Event.cpp
+++ b/cpp/src/qpid/cluster/Event.cpp
@@ -7,9 +7,9 @@
* 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
@@ -23,7 +23,6 @@
#include "qpid/cluster/Cpg.h"
#include "qpid/framing/Buffer.h"
#include "qpid/framing/AMQFrame.h"
-#include "qpid/RefCountedBuffer.h"
#include "qpid/assert.h"
#include <ostream>
#include <iterator>
diff --git a/cpp/src/qpid/cluster/Event.h b/cpp/src/qpid/cluster/Event.h
index 13283edff7..07f74d3ba5 100644
--- a/cpp/src/qpid/cluster/Event.h
+++ b/cpp/src/qpid/cluster/Event.h
@@ -10,9 +10,9 @@
* 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
@@ -23,7 +23,7 @@
*/
#include "qpid/cluster/types.h"
-#include "qpid/BufferRef.h"
+#include "qpid/RefCountedBuffer.h"
#include "qpid/framing/AMQFrame.h"
#include <sys/uio.h> // For iovec
#include <iosfwd>
@@ -53,7 +53,7 @@ class EventHeader {
/** Size of payload data, excluding header. */
size_t getSize() const { return size; }
- /** Size of header + payload. */
+ /** Size of header + payload. */
size_t getStoreSize() const { return size + HEADER_SIZE; }
bool isCluster() const { return connectionId.getNumber() == 0; }
@@ -62,7 +62,7 @@ class EventHeader {
protected:
static const size_t HEADER_SIZE;
-
+
EventType type;
ConnectionId connectionId;
size_t size;
@@ -86,25 +86,25 @@ class Event : public EventHeader {
/** Create a control event. */
static Event control(const framing::AMQFrame&, const ConnectionId&);
-
+
// Data excluding header.
- char* getData() { return store.begin() + HEADER_SIZE; }
- const char* getData() const { return store.begin() + HEADER_SIZE; }
+ char* getData() { return store + HEADER_SIZE; }
+ const char* getData() const { return store + HEADER_SIZE; }
// Store including header
- char* getStore() { return store.begin(); }
- const char* getStore() const { return store.begin(); }
-
- const framing::AMQFrame& getFrame() const;
+ char* getStore() { return store; }
+ const char* getStore() const { return store; }
+ const framing::AMQFrame& getFrame() const;
+
operator framing::Buffer() const;
iovec toIovec() const;
-
+
private:
void encodeHeader() const;
- BufferRef store;
+ RefCountedBuffer::pointer store;
mutable framing::AMQFrame frame;
};
diff --git a/cpp/src/qpid/cluster/EventFrame.h b/cpp/src/qpid/cluster/EventFrame.h
index 6b702a9bf8..61447c5525 100644
--- a/cpp/src/qpid/cluster/EventFrame.h
+++ b/cpp/src/qpid/cluster/EventFrame.h
@@ -10,9 +10,9 @@
* 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
@@ -48,7 +48,7 @@ struct EventFrame
ConnectionId connectionId;
- framing::AMQFrame frame;
+ framing::AMQFrame frame;
int readCredit; ///< last frame in an event, give credit when processed.
EventType type;
};
diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.cpp b/cpp/src/qpid/cluster/ExpiryPolicy.cpp
index 0ef5c2a35d..d9a7b0122a 100644
--- a/cpp/src/qpid/cluster/ExpiryPolicy.cpp
+++ b/cpp/src/qpid/cluster/ExpiryPolicy.cpp
@@ -21,21 +21,106 @@
#include "qpid/broker/Message.h"
#include "qpid/cluster/ExpiryPolicy.h"
-#include "qpid/cluster/Cluster.h"
+#include "qpid/cluster/Multicaster.h"
+#include "qpid/framing/ClusterMessageExpiredBody.h"
#include "qpid/sys/Time.h"
+#include "qpid/sys/Timer.h"
#include "qpid/log/Statement.h"
namespace qpid {
namespace cluster {
-ExpiryPolicy::ExpiryPolicy(Cluster& cluster) : cluster(cluster) {}
+ExpiryPolicy::ExpiryPolicy(Multicaster& m, const MemberId& id, sys::Timer& t)
+ : expiryId(1), expiredPolicy(new Expired), mcast(m), memberId(id), timer(t) {}
+struct ExpiryTask : public sys::TimerTask {
+ ExpiryTask(const boost::intrusive_ptr<ExpiryPolicy>& policy, uint64_t id, sys::AbsTime when)
+ : TimerTask(when,"ExpiryPolicy"), expiryPolicy(policy), expiryId(id) {}
+ void fire() { expiryPolicy->sendExpire(expiryId); }
+ boost::intrusive_ptr<ExpiryPolicy> expiryPolicy;
+ const uint64_t expiryId;
+};
+
+// Called while receiving an update
+void ExpiryPolicy::setId(uint64_t id) {
+ sys::Mutex::ScopedLock l(lock);
+ expiryId = id;
+}
+
+// Called while giving an update
+uint64_t ExpiryPolicy::getId() const {
+ sys::Mutex::ScopedLock l(lock);
+ return expiryId;
+}
+
+// Called in enqueuing connection thread
+void ExpiryPolicy::willExpire(broker::Message& m) {
+ uint64_t id;
+ {
+ // When messages are fanned out to multiple queues, update sends
+ // them as independenty messages so we can have multiple messages
+ // with the same expiry ID.
+ //
+ sys::Mutex::ScopedLock l(lock);
+ id = expiryId++;
+ if (!id) { // This is an update of an already-expired message.
+ m.setExpiryPolicy(expiredPolicy);
+ }
+ else {
+ assert(unexpiredByMessage.find(&m) == unexpiredByMessage.end());
+ // If this is an update, the id may already exist
+ unexpiredById.insert(IdMessageMap::value_type(id, &m));
+ unexpiredByMessage[&m] = id;
+ }
+ }
+ timer.add(new ExpiryTask(this, id, m.getExpiration()));
+}
+
+// Called in dequeueing connection thread
+void ExpiryPolicy::forget(broker::Message& m) {
+ sys::Mutex::ScopedLock l(lock);
+ MessageIdMap::iterator i = unexpiredByMessage.find(&m);
+ assert(i != unexpiredByMessage.end());
+ unexpiredById.erase(i->second);
+ unexpiredByMessage.erase(i);
+}
+
+// Called in dequeueing connection or cleanup thread.
bool ExpiryPolicy::hasExpired(broker::Message& m) {
- return m.getExpiration() < cluster.getClusterTime();
+ sys::Mutex::ScopedLock l(lock);
+ return unexpiredByMessage.find(&m) == unexpiredByMessage.end();
+}
+
+// Called in timer thread
+void ExpiryPolicy::sendExpire(uint64_t id) {
+ {
+ sys::Mutex::ScopedLock l(lock);
+ // Don't multicast an expiry notice if message is already forgotten.
+ if (unexpiredById.find(id) == unexpiredById.end()) return;
+ }
+ mcast.mcastControl(framing::ClusterMessageExpiredBody(framing::ProtocolVersion(), id), memberId);
}
-sys::AbsTime ExpiryPolicy::getCurrentTime() {
- return cluster.getClusterTime();
+// Called in CPG deliver thread.
+void ExpiryPolicy::deliverExpire(uint64_t id) {
+ sys::Mutex::ScopedLock l(lock);
+ std::pair<IdMessageMap::iterator, IdMessageMap::iterator> expired = unexpiredById.equal_range(id);
+ IdMessageMap::iterator i = expired.first;
+ while (i != expired.second) {
+ i->second->setExpiryPolicy(expiredPolicy); // hasExpired() == true;
+ unexpiredByMessage.erase(i->second);
+ unexpiredById.erase(i++);
+ }
}
+// Called in update thread on the updater.
+boost::optional<uint64_t> ExpiryPolicy::getId(broker::Message& m) {
+ sys::Mutex::ScopedLock l(lock);
+ MessageIdMap::iterator i = unexpiredByMessage.find(&m);
+ return i == unexpiredByMessage.end() ? boost::optional<uint64_t>() : i->second;
+}
+
+bool ExpiryPolicy::Expired::hasExpired(broker::Message&) { return true; }
+void ExpiryPolicy::Expired::willExpire(broker::Message&) { }
+
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/ExpiryPolicy.h b/cpp/src/qpid/cluster/ExpiryPolicy.h
index d8ddbca8b3..77a656aa68 100644
--- a/cpp/src/qpid/cluster/ExpiryPolicy.h
+++ b/cpp/src/qpid/cluster/ExpiryPolicy.h
@@ -36,8 +36,12 @@ namespace broker {
class Message;
}
+namespace sys {
+class Timer;
+}
+
namespace cluster {
-class Cluster;
+class Multicaster;
/**
* Cluster expiry policy
@@ -45,13 +49,43 @@ class Cluster;
class ExpiryPolicy : public broker::ExpiryPolicy
{
public:
- ExpiryPolicy(Cluster& cluster);
+ ExpiryPolicy(Multicaster&, const MemberId&, sys::Timer&);
+ void willExpire(broker::Message&);
bool hasExpired(broker::Message&);
- qpid::sys::AbsTime getCurrentTime();
+ void forget(broker::Message&);
+
+ // Send expiration notice to cluster.
+ void sendExpire(uint64_t);
+ // Cluster delivers expiry notice.
+ void deliverExpire(uint64_t);
+
+ void setId(uint64_t id);
+ uint64_t getId() const;
+
+ boost::optional<uint64_t> getId(broker::Message&);
+
private:
- Cluster& cluster;
+ typedef std::map<broker::Message*, uint64_t> MessageIdMap;
+ // When messages are fanned out to multiple queues, update sends
+ // them as independenty messages so we can have multiple messages
+ // with the same expiry ID.
+ typedef std::multimap<uint64_t, broker::Message*> IdMessageMap;
+
+ struct Expired : public broker::ExpiryPolicy {
+ bool hasExpired(broker::Message&);
+ void willExpire(broker::Message&);
+ };
+
+ mutable sys::Mutex lock;
+ MessageIdMap unexpiredByMessage;
+ IdMessageMap unexpiredById;
+ uint64_t expiryId;
+ boost::intrusive_ptr<Expired> expiredPolicy;
+ Multicaster& mcast;
+ MemberId memberId;
+ sys::Timer& timer;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/FailoverExchange.cpp b/cpp/src/qpid/cluster/FailoverExchange.cpp
index cfbe34a460..84232dac1b 100644
--- a/cpp/src/qpid/cluster/FailoverExchange.cpp
+++ b/cpp/src/qpid/cluster/FailoverExchange.cpp
@@ -7,9 +7,9 @@
* 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
@@ -39,10 +39,8 @@ using namespace broker;
using namespace framing;
const string FailoverExchange::typeName("amq.failover");
-
-FailoverExchange::FailoverExchange(management::Manageable* parent, Broker* b)
- : Exchange(typeName, parent, b ), ready(false)
-{
+
+FailoverExchange::FailoverExchange(management::Manageable* parent, Broker* b) : Exchange(typeName, parent, b ) {
if (mgmtExchange != 0)
mgmtExchange->set_type(typeName);
}
@@ -55,17 +53,16 @@ void FailoverExchange::setUrls(const vector<Url>& u) {
void FailoverExchange::updateUrls(const vector<Url>& u) {
Lock l(lock);
urls=u;
- if (ready && !urls.empty()) {
- std::for_each(queues.begin(), queues.end(),
- boost::bind(&FailoverExchange::sendUpdate, this, _1));
- }
+ if (urls.empty()) return;
+ std::for_each(queues.begin(), queues.end(),
+ boost::bind(&FailoverExchange::sendUpdate, this, _1));
}
string FailoverExchange::getType() const { return typeName; }
bool FailoverExchange::bind(Queue::shared_ptr queue, const string&, const framing::FieldTable*) {
Lock l(lock);
- if (ready) sendUpdate(queue);
+ sendUpdate(queue);
return queues.insert(queue).second;
}
@@ -87,7 +84,7 @@ void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue) {
// Called with lock held.
if (urls.empty()) return;
framing::Array array(0x95);
- for (Urls::const_iterator i = urls.begin(); i != urls.end(); ++i)
+ for (Urls::const_iterator i = urls.begin(); i != urls.end(); ++i)
array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str())));
const ProtocolVersion v;
boost::intrusive_ptr<Message> msg(new Message);
@@ -99,12 +96,9 @@ void FailoverExchange::sendUpdate(const Queue::shared_ptr& queue) {
header.get<MessageProperties>(true)->getApplicationHeaders().setArray(typeName, array);
AMQFrame headerFrame(header);
headerFrame.setFirstSegment(false);
- msg->getFrames().append(headerFrame);
+ msg->getFrames().append(headerFrame);
DeliverableMessage(msg).deliverTo(queue);
}
-void FailoverExchange::setReady() {
- ready = true;
-}
}} // namespace cluster
diff --git a/cpp/src/qpid/cluster/FailoverExchange.h b/cpp/src/qpid/cluster/FailoverExchange.h
index c3e50c6929..2e1edfc0ae 100644
--- a/cpp/src/qpid/cluster/FailoverExchange.h
+++ b/cpp/src/qpid/cluster/FailoverExchange.h
@@ -10,9 +10,9 @@
* 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
@@ -46,8 +46,6 @@ class FailoverExchange : public broker::Exchange
void setUrls(const std::vector<Url>&);
/** Set the URLs and send an update.*/
void updateUrls(const std::vector<Url>&);
- /** Flag the failover exchange as ready to generate updates (caught up) */
- void setReady();
// Exchange overrides
std::string getType() const;
@@ -58,7 +56,7 @@ class FailoverExchange : public broker::Exchange
private:
void sendUpdate(const boost::shared_ptr<broker::Queue>&);
-
+
typedef sys::Mutex::ScopedLock Lock;
typedef std::vector<Url> Urls;
typedef std::set<boost::shared_ptr<broker::Queue> > Queues;
@@ -66,7 +64,7 @@ class FailoverExchange : public broker::Exchange
sys::Mutex lock;
Urls urls;
Queues queues;
- bool ready;
+
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/Multicaster.cpp b/cpp/src/qpid/cluster/Multicaster.cpp
index 217641841c..8916de9628 100644
--- a/cpp/src/qpid/cluster/Multicaster.cpp
+++ b/cpp/src/qpid/cluster/Multicaster.cpp
@@ -21,7 +21,6 @@
#include "qpid/cluster/Multicaster.h"
#include "qpid/cluster/Cpg.h"
-#include "qpid/cluster/Cluster.h"
#include "qpid/log/Statement.h"
#include "qpid/framing/AMQBody.h"
#include "qpid/framing/AMQFrame.h"
@@ -59,7 +58,7 @@ void Multicaster::mcast(const Event& e) {
return;
}
}
- QPID_LOG_IF(trace, e.isControl() && Cluster::loggable(e.getFrame()), "MCAST " << e);
+ QPID_LOG(trace, "MCAST " << e);
if (bypass) { // direct, don't queue
iovec iov = e.toIovec();
while (!cpg.mcast(&iov, 1))
diff --git a/cpp/src/qpid/cluster/OutputInterceptor.cpp b/cpp/src/qpid/cluster/OutputInterceptor.cpp
index 4bf03eefa2..1354dab17b 100644
--- a/cpp/src/qpid/cluster/OutputInterceptor.cpp
+++ b/cpp/src/qpid/cluster/OutputInterceptor.cpp
@@ -7,9 +7,9 @@
* 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
@@ -45,11 +45,12 @@ void OutputInterceptor::send(framing::AMQFrame& f) {
}
void OutputInterceptor::activateOutput() {
- sys::Mutex::ScopedLock l(lock);
- if (parent.isCatchUp())
+ if (parent.isCatchUp()) {
+ sys::Mutex::ScopedLock l(lock);
next->activateOutput();
+ }
else
- sendDoOutput(sendMax, l);
+ sendDoOutput(sendMax);
}
void OutputInterceptor::abort() {
@@ -65,38 +66,29 @@ void OutputInterceptor::giveReadCredit(int32_t credit) {
}
// Called in write thread when the IO layer has no more data to write.
-// We only process IO callbacks in the write thread during catch-up.
-// Normally we run doOutput only on delivery of doOutput requests.
-bool OutputInterceptor::doOutput() {
- parent.doCatchupIoCallbacks();
- return false;
-}
+// We do nothing in the write thread, we run doOutput only on delivery
+// of doOutput requests.
+bool OutputInterceptor::doOutput() { return false; }
-// Send output up to limit, calculate new limit.
+// Send output up to limit, calculate new limit.
void OutputInterceptor::deliverDoOutput(uint32_t limit) {
- sys::Mutex::ScopedLock l(lock);
sentDoOutput = false;
sendMax = limit;
size_t newLimit = limit;
if (parent.isLocal()) {
- size_t buffered = next->getBuffered();
+ size_t buffered = getBuffered();
if (buffered == 0 && sent == sendMax) // Could have sent more, increase the limit.
- newLimit = sendMax*2;
+ newLimit = sendMax*2;
else if (buffered > 0 && sent > 1) // Data left unsent, reduce the limit.
newLimit = (sendMax + sent) / 2;
}
sent = 0;
- while (sent < limit) {
- {
- sys::Mutex::ScopedUnlock u(lock);
- if (!parent.getBrokerConnection()->doOutput()) break;
- }
+ while (sent < limit && parent.getBrokerConnection()->doOutput())
++sent;
- }
- if (sent == limit) sendDoOutput(newLimit, l);
+ if (sent == limit) sendDoOutput(newLimit);
}
-void OutputInterceptor::sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&) {
+void OutputInterceptor::sendDoOutput(size_t newLimit) {
if (parent.isLocal() && !sentDoOutput && !closing) {
sentDoOutput = true;
parent.getCluster().getMulticast().mcastControl(
@@ -105,7 +97,6 @@ void OutputInterceptor::sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLo
}
}
-// Called in connection thread when local connection closes.
void OutputInterceptor::closeOutput() {
sys::Mutex::ScopedLock l(lock);
closing = true;
diff --git a/cpp/src/qpid/cluster/OutputInterceptor.h b/cpp/src/qpid/cluster/OutputInterceptor.h
index 3abf5273a0..65bd82a4fc 100644
--- a/cpp/src/qpid/cluster/OutputInterceptor.h
+++ b/cpp/src/qpid/cluster/OutputInterceptor.h
@@ -10,9 +10,9 @@
* 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
@@ -58,13 +58,13 @@ class OutputInterceptor : public sys::ConnectionOutputHandler {
uint32_t getSendMax() const { return sendMax; }
void setSendMax(uint32_t sendMax_) { sendMax=sendMax_; }
-
+
cluster::Connection& parent;
-
+
private:
typedef sys::Mutex::ScopedLock Locker;
- void sendDoOutput(size_t newLimit, const sys::Mutex::ScopedLock&);
+ void sendDoOutput(size_t newLimit);
mutable sys::Mutex lock;
bool closing;
diff --git a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
index 2672d8360c..6ddef66226 100644
--- a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
+++ b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp
@@ -7,9 +7,9 @@
* 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
@@ -48,7 +48,7 @@ SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, cons
if (clusterCodec) {
SecureConnectionPtr sc(new SecureConnection());
clusterCodec->setSecureConnection(sc.get());
- sc->setCodec(codec);
+ sc->setCodec(codec);
return sc.release();
}
return 0;
@@ -63,7 +63,7 @@ SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id,
if (clusterCodec) {
SecureConnectionPtr sc(new SecureConnection());
clusterCodec->setSecureConnection(sc.get());
- sc->setCodec(codec);
+ sc->setCodec(codec);
return sc.release();
}
return 0;
diff --git a/cpp/src/qpid/cluster/UpdateClient.cpp b/cpp/src/qpid/cluster/UpdateClient.cpp
index 2446c12f2b..8f751add9b 100644
--- a/cpp/src/qpid/cluster/UpdateClient.cpp
+++ b/cpp/src/qpid/cluster/UpdateClient.cpp
@@ -7,9 +7,9 @@
* 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
@@ -26,9 +26,9 @@
#include "qpid/cluster/Decoder.h"
#include "qpid/cluster/ExpiryPolicy.h"
#include "qpid/cluster/UpdateDataExchange.h"
-#include "qpid/client/SessionBase_0_10Access.h"
-#include "qpid/client/ConnectionAccess.h"
-#include "qpid/client/SessionImpl.h"
+#include "qpid/client/SessionBase_0_10Access.h"
+#include "qpid/client/ConnectionAccess.h"
+#include "qpid/client/SessionImpl.h"
#include "qpid/client/ConnectionImpl.h"
#include "qpid/client/Future.h"
#include "qpid/broker/Broker.h"
@@ -45,13 +45,10 @@
#include "qpid/broker/SessionState.h"
#include "qpid/broker/TxOpVisitor.h"
#include "qpid/broker/DtxAck.h"
-#include "qpid/broker/DtxBuffer.h"
-#include "qpid/broker/DtxWorkRecord.h"
#include "qpid/broker/TxAccept.h"
#include "qpid/broker/TxPublish.h"
#include "qpid/broker/RecoveredDequeue.h"
#include "qpid/broker/RecoveredEnqueue.h"
-#include "qpid/broker/StatefulQueueObserver.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/framing/ClusterConnectionMembershipBody.h"
#include "qpid/framing/ClusterConnectionShadowReadyBody.h"
@@ -67,7 +64,6 @@
#include <boost/bind.hpp>
#include <boost/cast.hpp>
#include <algorithm>
-#include <iterator>
#include <sstream>
namespace qpid {
@@ -86,20 +82,11 @@ using namespace framing;
namespace arg=client::arg;
using client::SessionBase_0_10Access;
-// Reserved exchange/queue name for catch-up, avoid clashes with user queues/exchanges.
-const std::string UpdateClient::UPDATE("x-qpid.cluster-update");
-// Name for header used to carry expiration information.
-const std::string UpdateClient::X_QPID_EXPIRATION = "x-qpid.expiration";
-// Headers used to flag headers/properties added by the UpdateClient so they can be
-// removed on the other side.
-const std::string UpdateClient::X_QPID_NO_MESSAGE_PROPS = "x-qpid.no-message-props";
-const std::string UpdateClient::X_QPID_NO_HEADERS = "x-qpid.no-headers";
-
std::ostream& operator<<(std::ostream& o, const UpdateClient& c) {
return o << "cluster(" << c.updaterId << " UPDATER)";
}
-struct ClusterConnectionProxy : public AMQP_AllProxy::ClusterConnection, public framing::FrameHandler
+struct ClusterConnectionProxy : public AMQP_AllProxy::ClusterConnection, public framing::FrameHandler
{
boost::shared_ptr<qpid::client::ConnectionImpl> connection;
@@ -133,7 +120,7 @@ void send(client::AsyncSession& s, const AMQBody& body) {
// TODO aconway 2008-09-24: optimization: update connections/sessions in parallel.
UpdateClient::UpdateClient(const MemberId& updater, const MemberId& updatee, const Url& url,
- broker::Broker& broker, const ClusterMap& m, ExpiryPolicy& expiry_,
+ broker::Broker& broker, const ClusterMap& m, ExpiryPolicy& expiry_,
const Cluster::ConnectionVector& cons, Decoder& decoder_,
const boost::function<void()>& ok,
const boost::function<void(const std::exception&)>& fail,
@@ -147,11 +134,13 @@ UpdateClient::UpdateClient(const MemberId& updater, const MemberId& updatee, con
UpdateClient::~UpdateClient() {}
+// Reserved exchange/queue name for catch-up, avoid clashes with user queues/exchanges.
+const std::string UpdateClient::UPDATE("qpid.cluster-update");
+
void UpdateClient::run() {
try {
connection.open(updateeUrl, connectionSettings);
session = connection.newSession(UPDATE);
- session.sync();
update();
done();
} catch (const std::exception& e) {
@@ -165,13 +154,6 @@ void UpdateClient::update() {
<< " at " << updateeUrl);
Broker& b = updaterBroker;
- if(b.getExpiryPolicy()) {
- QPID_LOG(debug, *this << "Updating updatee with cluster time");
- qpid::sys::AbsTime clusterTime = b.getExpiryPolicy()->getCurrentTime();
- int64_t time = qpid::sys::Duration(qpid::sys::EPOCH, clusterTime);
- ClusterConnectionProxy(session).clock(time);
- }
-
updateManagementSetupState();
b.getExchanges().eachExchange(boost::bind(&UpdateClient::updateExchange, this, _1));
@@ -181,20 +163,16 @@ void UpdateClient::update() {
// longer on their original queue.
session.queueDeclare(arg::queue=UPDATE, arg::autoDelete=true);
session.sync();
-
std::for_each(connections.begin(), connections.end(),
boost::bind(&UpdateClient::updateConnection, this, _1));
-
- // some Queue Observers need session state & msgs synced first, so sync observers now
- b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueObservers, this, _1));
+ session.queueDelete(arg::queue=UPDATE);
// Update queue listeners: must come after sessions so consumerNumbering is populated
b.getQueues().eachQueue(boost::bind(&UpdateClient::updateQueueListeners, this, _1));
+ ClusterConnectionProxy(session).expiryId(expiry.getId());
updateLinks();
updateManagementAgent();
- updateDtxManager();
- session.queueDelete(arg::queue=UPDATE);
session.close();
@@ -206,7 +184,7 @@ void UpdateClient::update() {
// NOTE: connection will be closed from the other end, don't close
// it here as that causes a race.
-
+
// TODO aconway 2010-03-15: This sleep avoids the race condition
// described in // https://bugzilla.redhat.com/show_bug.cgi?id=568831.
// It allows the connection to fully close before destroying the
@@ -298,7 +276,7 @@ class MessageUpdater {
framing::SequenceNumber lastPos;
client::AsyncSession session;
ExpiryPolicy& expiry;
-
+
public:
MessageUpdater(const string& q, const client::AsyncSession s, ExpiryPolicy& expiry_) : queue(q), haveLastPos(false), session(s), expiry(expiry_) {
@@ -315,6 +293,7 @@ class MessageUpdater {
}
}
+
void updateQueuedMessage(const broker::QueuedMessage& message) {
// Send the queue position if necessary.
if (!haveLastPos || message.position - lastPos != 1) {
@@ -323,23 +302,10 @@ class MessageUpdater {
}
lastPos = message.position;
- // if the ttl > 0, we need to send the calculated expiration time to the updatee
- const DeliveryProperties* dprops =
- message.payload->getProperties<DeliveryProperties>();
- if (dprops && dprops->getTtl() > 0) {
- bool hadMessageProps =
- message.payload->hasProperties<framing::MessageProperties>();
- const framing::MessageProperties* mprops =
- message.payload->getProperties<framing::MessageProperties>();
- bool hadApplicationHeaders = mprops->hasApplicationHeaders();
- message.payload->insertCustomProperty(UpdateClient::X_QPID_EXPIRATION,
- sys::Duration(sys::EPOCH, message.payload->getExpiration()));
- // If message properties or application headers didn't exist
- // prior to us adding data, we want to remove them on the other side.
- if (!hadMessageProps)
- message.payload->insertCustomProperty(UpdateClient::X_QPID_NO_MESSAGE_PROPS, 0);
- else if (!hadApplicationHeaders)
- message.payload->insertCustomProperty(UpdateClient::X_QPID_NO_HEADERS, 0);
+ // Send the expiry ID if necessary.
+ if (message.payload->getProperties<DeliveryProperties>()->getTtl()) {
+ boost::optional<uint64_t> expiryId = expiry.getId(*message.payload);
+ ClusterConnectionProxy(session).expiryId(expiryId?*expiryId:0);
}
// We can't send a broker::Message via the normal client API,
@@ -352,7 +318,7 @@ class MessageUpdater {
framing::MessageTransferBody transfer(
*message.payload->getFrames().as<framing::MessageTransferBody>());
transfer.setDestination(UpdateClient::UPDATE);
-
+
sb.get()->send(transfer, message.payload->getFrames(),
!message.payload->isContentReleased());
if (message.payload->isContentReleased()){
@@ -360,10 +326,9 @@ class MessageUpdater {
uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead();
bool morecontent = true;
for (uint64_t offset = 0; morecontent; offset += maxContentSize)
- {
+ {
AMQFrame frame((AMQContentBody()));
- morecontent = message.payload->getContentFrame(
- *(message.queue), frame, maxContentSize, offset);
+ morecontent = message.payload->getContentFrame(*(message.queue), frame, maxContentSize, offset);
sb.get()->sendRawFrame(frame);
}
}
@@ -392,8 +357,6 @@ void UpdateClient::updateQueue(client::AsyncSession& s, const boost::shared_ptr<
if (qpid::broker::Fairshare::getState(q->getMessages(), priority, count)) {
ClusterConnectionProxy(s).queueFairshareState(q->getName(), priority, count);
}
-
- ClusterConnectionProxy(s).queueDequeueSincePurgeState(q->getName(), q->getDequeueSincePurge());
}
void UpdateClient::updateExclusiveQueue(const boost::shared_ptr<broker::Queue>& q) {
@@ -409,11 +372,7 @@ void UpdateClient::updateNonExclusiveQueue(const boost::shared_ptr<broker::Queue
}
void UpdateClient::updateBinding(client::AsyncSession& s, const std::string& queue, const QueueBinding& binding) {
- if (binding.exchange.size())
- s.exchangeBind(queue, binding.exchange, binding.key, binding.args);
- //else its the default exchange and there is no need to replicate
- //the binding, the creation of the queue will have done so
- //automatically
+ s.exchangeBind(queue, binding.exchange, binding.key, binding.args);
}
void UpdateClient::updateOutputTask(const sys::OutputTask* task) {
@@ -421,8 +380,8 @@ void UpdateClient::updateOutputTask(const sys::OutputTask* task) {
boost::polymorphic_downcast<const SemanticState::ConsumerImpl*> (task);
SemanticState::ConsumerImpl* ci = const_cast<SemanticState::ConsumerImpl*>(cci);
uint16_t channel = ci->getParent().getSession().getChannel();
- ClusterConnectionProxy(shadowConnection).outputTask(channel, ci->getTag());
- QPID_LOG(debug, *this << " updating output task " << ci->getTag()
+ ClusterConnectionProxy(shadowConnection).outputTask(channel, ci->getName());
+ QPID_LOG(debug, *this << " updating output task " << ci->getName()
<< " channel=" << channel);
}
@@ -430,7 +389,7 @@ void UpdateClient::updateConnection(const boost::intrusive_ptr<Connection>& upda
QPID_LOG(debug, *this << " updating connection " << *updateConnection);
assert(updateConnection->getBrokerConnection());
broker::Connection& bc = *updateConnection->getBrokerConnection();
-
+
// Send the management ID first on the main connection.
std::string mgmtId = updateConnection->getBrokerConnection()->getMgmtId();
ClusterConnectionProxy(session).shadowPrepare(mgmtId);
@@ -467,7 +426,7 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
QPID_LOG(debug, *this << " updating session " << ss->getId());
- // Create a client session to update session state.
+ // Create a client session to update session state.
boost::shared_ptr<client::ConnectionImpl> cimpl = client::ConnectionAccess::getImpl(shadowConnection);
boost::shared_ptr<client::SessionImpl> simpl = cimpl->newSession(ss->getId().getName(), ss->getTimeout(), sh.getChannel());
simpl->disableAutoDetach();
@@ -486,19 +445,19 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
QPID_LOG(debug, *this << " updating unacknowledged messages.");
broker::DeliveryRecords& drs = ss->getSemanticState().getUnacked();
std::for_each(drs.begin(), drs.end(),
- boost::bind(&UpdateClient::updateUnacked, this, _1, shadowSession));
+ boost::bind(&UpdateClient::updateUnacked, this, _1));
- updateTransactionState(ss->getSemanticState());
+ updateTxState(ss->getSemanticState()); // Tx transaction state.
// Adjust command counter for message in progress, will be sent after state update.
boost::intrusive_ptr<Message> inProgress = ss->getMessageInProgress();
SequenceNumber received = ss->receiverGetReceived().command;
- if (inProgress)
+ if (inProgress)
--received;
// Sync the session to ensure all responses from broker have been processed.
shadowSession.sync();
-
+
// Reset command-sequence state.
proxy.sessionState(
ss->senderGetReplayPoint().command,
@@ -507,8 +466,7 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
std::max(received, ss->receiverGetExpected().command),
received,
ss->receiverGetUnknownComplete(),
- ss->receiverGetIncomplete(),
- ss->getSemanticState().getDtxSelected()
+ ss->receiverGetIncomplete()
);
// Send frames for partial message in progress.
@@ -521,13 +479,13 @@ void UpdateClient::updateSession(broker::SessionHandler& sh) {
void UpdateClient::updateConsumer(
const broker::SemanticState::ConsumerImpl::shared_ptr& ci)
{
- QPID_LOG(debug, *this << " updating consumer " << ci->getTag() << " on "
+ QPID_LOG(debug, *this << " updating consumer " << ci->getName() << " on "
<< shadowSession.getId());
using namespace message;
shadowSession.messageSubscribe(
arg::queue = ci->getQueue()->getName(),
- arg::destination = ci->getTag(),
+ arg::destination = ci->getName(),
arg::acceptMode = ci->isAckExpected() ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE,
arg::acquireMode = ci->isAcquire() ? ACQUIRE_MODE_PRE_ACQUIRED : ACQUIRE_MODE_NOT_ACQUIRED,
arg::exclusive = ci->isExclusive(),
@@ -535,32 +493,29 @@ void UpdateClient::updateConsumer(
arg::resumeTtl = ci->getResumeTtl(),
arg::arguments = ci->getArguments()
);
- shadowSession.messageSetFlowMode(ci->getTag(), ci->isWindowing() ? FLOW_MODE_WINDOW : FLOW_MODE_CREDIT);
- shadowSession.messageFlow(ci->getTag(), CREDIT_UNIT_MESSAGE, ci->getMsgCredit());
- shadowSession.messageFlow(ci->getTag(), CREDIT_UNIT_BYTE, ci->getByteCredit());
+ shadowSession.messageSetFlowMode(ci->getName(), ci->isWindowing() ? FLOW_MODE_WINDOW : FLOW_MODE_CREDIT);
+ shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_MESSAGE, ci->getMsgCredit());
+ shadowSession.messageFlow(ci->getName(), CREDIT_UNIT_BYTE, ci->getByteCredit());
ClusterConnectionProxy(shadowSession).consumerState(
- ci->getTag(),
+ ci->getName(),
ci->isBlocked(),
ci->isNotifyEnabled(),
ci->position
);
consumerNumbering.add(ci.get());
- QPID_LOG(debug, *this << " updated consumer " << ci->getTag()
+ QPID_LOG(debug, *this << " updated consumer " << ci->getName()
<< " on " << shadowSession.getId());
}
-
-void UpdateClient::updateUnacked(const broker::DeliveryRecord& dr,
- client::AsyncSession& updateSession)
-{
- if (!dr.isEnded() && dr.isAcquired()) {
- assert(dr.getMessage().payload);
+
+void UpdateClient::updateUnacked(const broker::DeliveryRecord& dr) {
+ if (!dr.isEnded() && dr.isAcquired() && dr.getMessage().payload) {
// If the message is acquired then it is no longer on the
// updatees queue, put it on the update queue for updatee to pick up.
//
- MessageUpdater(UPDATE, updateSession, expiry).updateQueuedMessage(dr.getMessage());
+ MessageUpdater(UPDATE, shadowSession, expiry).updateQueuedMessage(dr.getMessage());
}
- ClusterConnectionProxy(updateSession).deliveryRecord(
+ ClusterConnectionProxy(shadowSession).deliveryRecord(
dr.getQueue()->getName(),
dr.getMessage().position,
dr.getTag(),
@@ -581,12 +536,10 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
TxOpUpdater(UpdateClient& dc, client::AsyncSession s, ExpiryPolicy& expiry)
: MessageUpdater(UpdateClient::UPDATE, s, expiry), parent(dc), session(s), proxy(s) {}
- void operator()(const broker::DtxAck& ack) {
- std::for_each(ack.getPending().begin(), ack.getPending().end(),
- boost::bind(&UpdateClient::updateUnacked, &parent, _1, session));
- proxy.dtxAck();
+ void operator()(const broker::DtxAck& ) {
+ throw InternalErrorException("DTX transactions not currently supported by cluster.");
}
-
+
void operator()(const broker::RecoveredDequeue& rdeq) {
updateMessage(rdeq.getMessage());
proxy.txEnqueue(rdeq.getQueue()->getName());
@@ -601,18 +554,13 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
proxy.txAccept(txAccept.getAcked());
}
- typedef std::list<Queue::shared_ptr> QueueList;
-
- void copy(const QueueList& l, Array& a) {
- for (QueueList::const_iterator i = l.begin(); i!=l.end(); ++i)
- a.push_back(Array::ValuePtr(new Str8Value((*i)->getName())));
- }
-
void operator()(const broker::TxPublish& txPub) {
updateMessage(txPub.getMessage());
- assert(txPub.getQueues().empty() || txPub.getPrepared().empty());
+ typedef std::list<Queue::shared_ptr> QueueList;
+ const QueueList& qlist = txPub.getQueues();
Array qarray(TYPE_CODE_STR8);
- copy(txPub.getQueues().empty() ? txPub.getPrepared() : txPub.getQueues(), qarray);
+ for (QueueList::const_iterator i = qlist.begin(); i != qlist.end(); ++i)
+ qarray.push_back(Array::ValuePtr(new Str8Value((*i)->getName())));
proxy.txPublish(qarray, txPub.delivered);
}
@@ -621,44 +569,18 @@ class TxOpUpdater : public broker::TxOpConstVisitor, public MessageUpdater {
client::AsyncSession session;
ClusterConnectionProxy proxy;
};
-
-void UpdateClient::updateBufferRef(const broker::DtxBuffer::shared_ptr& dtx,bool suspended)
-{
- ClusterConnectionProxy proxy(shadowSession);
- broker::DtxWorkRecord* record =
- updaterBroker.getDtxManager().getWork(dtx->getXid());
- proxy.dtxBufferRef(dtx->getXid(), record->indexOf(dtx), suspended);
-
-}
-
-void UpdateClient::updateTransactionState(broker::SemanticState& s) {
+
+void UpdateClient::updateTxState(broker::SemanticState& s) {
+ QPID_LOG(debug, *this << " updating TX transaction state.");
ClusterConnectionProxy proxy(shadowSession);
proxy.accumulatedAck(s.getAccumulatedAck());
- broker::TxBuffer::shared_ptr tx = s.getTxBuffer();
- broker::DtxBuffer::shared_ptr dtx = s.getDtxBuffer();
- if (dtx) {
- updateBufferRef(dtx, false); // Current transaction.
- } else if (tx) {
+ broker::TxBuffer::shared_ptr txBuffer = s.getTxBuffer();
+ if (txBuffer) {
proxy.txStart();
TxOpUpdater updater(*this, shadowSession, expiry);
- tx->accept(updater);
+ txBuffer->accept(updater);
proxy.txEnd();
}
- for (SemanticState::DtxBufferMap::iterator i = s.getSuspendedXids().begin();
- i != s.getSuspendedXids().end();
- ++i)
- {
- updateBufferRef(i->second, true);
- }
-}
-
-void UpdateClient::updateDtxBuffer(const broker::DtxBuffer::shared_ptr& dtx) {
- ClusterConnectionProxy proxy(session);
- proxy.dtxStart(
- dtx->getXid(), dtx->isEnded(), dtx->isSuspended(), dtx->isFailed(), dtx->isExpired());
- TxOpUpdater updater(*this, session, expiry);
- dtx->accept(updater);
- proxy.dtxEnd();
}
void UpdateClient::updateQueueListeners(const boost::shared_ptr<broker::Queue>& queue) {
@@ -693,35 +615,4 @@ void UpdateClient::updateBridge(const boost::shared_ptr<broker::Bridge>& bridge)
ClusterConnectionProxy(session).config(encode(*bridge));
}
-void UpdateClient::updateQueueObservers(const boost::shared_ptr<broker::Queue>& q)
-{
- q->eachObserver(boost::bind(&UpdateClient::updateObserver, this, q, _1));
-}
-
-void UpdateClient::updateObserver(const boost::shared_ptr<broker::Queue>& q,
- boost::shared_ptr<broker::QueueObserver> o)
-{
- qpid::framing::FieldTable state;
- broker::StatefulQueueObserver *so = dynamic_cast<broker::StatefulQueueObserver *>(o.get());
- if (so) {
- so->getState( state );
- std::string id(so->getId());
- QPID_LOG(debug, *this << " updating queue " << q->getName() << "'s observer " << id);
- ClusterConnectionProxy(session).queueObserverState( q->getName(), id, state );
- }
-}
-
-void UpdateClient::updateDtxManager() {
- broker::DtxManager& dtm = updaterBroker.getDtxManager();
- dtm.each(boost::bind(&UpdateClient::updateDtxWorkRecord, this, _1));
-}
-
-void UpdateClient::updateDtxWorkRecord(const broker::DtxWorkRecord& r) {
- QPID_LOG(debug, *this << " updating DTX transaction: " << r.getXid());
- for (size_t i = 0; i < r.size(); ++i)
- updateDtxBuffer(r[i]);
- ClusterConnectionProxy(session).dtxWorkRecord(
- r.getXid(), r.isPrepared(), r.getTimeout());
-}
-
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateClient.h b/cpp/src/qpid/cluster/UpdateClient.h
index 481ee357c7..7520bb82cb 100644
--- a/cpp/src/qpid/cluster/UpdateClient.h
+++ b/cpp/src/qpid/cluster/UpdateClient.h
@@ -10,9 +10,9 @@
* 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
@@ -34,7 +34,7 @@
namespace qpid {
-struct Url;
+class Url;
namespace broker {
@@ -42,8 +42,8 @@ class Broker;
class Queue;
class Exchange;
class QueueBindings;
-struct QueueBinding;
-struct QueuedMessage;
+class QueueBinding;
+class QueuedMessage;
class SessionHandler;
class DeliveryRecord;
class SessionState;
@@ -51,8 +51,7 @@ class SemanticState;
class Decoder;
class Link;
class Bridge;
-class QueueObserver;
-class DtxBuffer;
+
} // namespace broker
namespace cluster {
@@ -69,26 +68,21 @@ class ExpiryPolicy;
class UpdateClient : public sys::Runnable {
public:
static const std::string UPDATE; // Name for special update queue and exchange.
- static const std::string X_QPID_EXPIRATION; // Update message expiration
- // Flag to remove props/headers that were added by the UpdateClient
- static const std::string X_QPID_NO_MESSAGE_PROPS;
- static const std::string X_QPID_NO_HEADERS;
-
static client::Connection catchUpConnection();
-
+
UpdateClient(const MemberId& updater, const MemberId& updatee, const Url&,
broker::Broker& donor, const ClusterMap& map, ExpiryPolicy& expiry,
const std::vector<boost::intrusive_ptr<Connection> >&, Decoder&,
const boost::function<void()>& done,
const boost::function<void(const std::exception&)>& fail,
- const client::ConnectionSettings&
+ const client::ConnectionSettings&
);
~UpdateClient();
void update();
void run(); // Will delete this when finished.
- void updateUnacked(const broker::DeliveryRecord&, client::AsyncSession&);
+ void updateUnacked(const broker::DeliveryRecord&);
private:
void updateQueue(client::AsyncSession&, const boost::shared_ptr<broker::Queue>&);
@@ -100,8 +94,7 @@ class UpdateClient : public sys::Runnable {
void updateBinding(client::AsyncSession&, const std::string& queue, const broker::QueueBinding& binding);
void updateConnection(const boost::intrusive_ptr<Connection>& connection);
void updateSession(broker::SessionHandler& s);
- void updateBufferRef(const broker::DtxBuffer::shared_ptr& dtx, bool suspended);
- void updateTransactionState(broker::SemanticState& s);
+ void updateTxState(broker::SemanticState& s);
void updateOutputTask(const sys::OutputTask* task);
void updateConsumer(const broker::SemanticState::ConsumerImpl::shared_ptr&);
void updateQueueListeners(const boost::shared_ptr<broker::Queue>&);
@@ -111,11 +104,6 @@ class UpdateClient : public sys::Runnable {
void updateLinks();
void updateLink(const boost::shared_ptr<broker::Link>&);
void updateBridge(const boost::shared_ptr<broker::Bridge>&);
- void updateQueueObservers(const boost::shared_ptr<broker::Queue>&);
- void updateObserver(const boost::shared_ptr<broker::Queue>&, boost::shared_ptr<broker::QueueObserver>);
- void updateDtxManager();
- void updateDtxBuffer(const boost::shared_ptr<broker::DtxBuffer>& );
- void updateDtxWorkRecord(const broker::DtxWorkRecord&);
Numbering<broker::SemanticState::ConsumerImpl*> consumerNumbering;
diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.cpp b/cpp/src/qpid/cluster/UpdateDataExchange.cpp
index e5cd82e3d3..2a079b8881 100644
--- a/cpp/src/qpid/cluster/UpdateDataExchange.cpp
+++ b/cpp/src/qpid/cluster/UpdateDataExchange.cpp
@@ -36,8 +36,13 @@ const std::string UpdateDataExchange::MANAGEMENT_AGENTS_KEY("management-agents")
const std::string UpdateDataExchange::MANAGEMENT_SCHEMAS_KEY("management-schemas");
const std::string UpdateDataExchange::MANAGEMENT_DELETED_OBJECTS_KEY("management-deleted-objects");
+std::ostream& operator<<(std::ostream& o, const UpdateDataExchange& c) {
+ return o << "cluster(" << c.clusterId << " UPDATER)";
+}
+
UpdateDataExchange::UpdateDataExchange(Cluster& cluster) :
- Exchange(EXCHANGE_NAME, &cluster)
+ Exchange(EXCHANGE_NAME, &cluster),
+ clusterId(cluster.getId())
{}
void UpdateDataExchange::route(broker::Deliverable& msg, const std::string& routingKey,
@@ -57,9 +62,11 @@ void UpdateDataExchange::updateManagementAgent(management::ManagementAgent* agen
framing::Buffer buf1(const_cast<char*>(managementAgents.data()), managementAgents.size());
agent->importAgents(buf1);
+ QPID_LOG(debug, *this << " updated management agents.");
framing::Buffer buf2(const_cast<char*>(managementSchemas.data()), managementSchemas.size());
agent->importSchemas(buf2);
+ QPID_LOG(debug, *this << " updated management schemas.");
using amqp_0_10::ListCodec;
using types::Variant;
@@ -71,6 +78,7 @@ void UpdateDataExchange::updateManagementAgent(management::ManagementAgent* agen
new management::ManagementAgent::DeletedObject(*i)));
}
agent->importDeletedObjects(objects);
+ QPID_LOG(debug, *this << " updated management deleted objects.");
}
diff --git a/cpp/src/qpid/cluster/UpdateDataExchange.h b/cpp/src/qpid/cluster/UpdateDataExchange.h
index d2f6c35ad0..8c493e400a 100644
--- a/cpp/src/qpid/cluster/UpdateDataExchange.h
+++ b/cpp/src/qpid/cluster/UpdateDataExchange.h
@@ -74,9 +74,11 @@ class UpdateDataExchange : public broker::Exchange
void updateManagementAgent(management::ManagementAgent* agent);
private:
+ MemberId clusterId;
std::string managementAgents;
std::string managementSchemas;
std::string managementDeletedObjects;
+ friend std::ostream& operator<<(std::ostream&, const UpdateDataExchange&);
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateExchange.cpp b/cpp/src/qpid/cluster/UpdateExchange.cpp
index cb1376004e..11937f296f 100644
--- a/cpp/src/qpid/cluster/UpdateExchange.cpp
+++ b/cpp/src/qpid/cluster/UpdateExchange.cpp
@@ -7,9 +7,9 @@
* 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
@@ -19,7 +19,6 @@
*
*/
#include "qpid/framing/MessageTransferBody.h"
-#include "qpid/framing/FieldTable.h"
#include "qpid/broker/Message.h"
#include "UpdateExchange.h"
@@ -28,8 +27,6 @@ namespace cluster {
using framing::MessageTransferBody;
using framing::DeliveryProperties;
-using framing::MessageProperties;
-using framing::FieldTable;
UpdateExchange::UpdateExchange(management::Manageable* parent)
: broker::Exchange(UpdateClient::UPDATE, parent),
@@ -37,7 +34,6 @@ UpdateExchange::UpdateExchange(management::Manageable* parent)
void UpdateExchange::setProperties(const boost::intrusive_ptr<broker::Message>& msg) {
- // Copy exchange name to destination property.
MessageTransferBody* transfer = msg->getMethod<MessageTransferBody>();
assert(transfer);
const DeliveryProperties* props = msg->getProperties<DeliveryProperties>();
@@ -46,23 +42,6 @@ void UpdateExchange::setProperties(const boost::intrusive_ptr<broker::Message>&
transfer->setDestination(props->getExchange());
else
transfer->clearDestinationFlag();
-
- // Copy expiration from x-property if present.
- if (msg->hasProperties<MessageProperties>()) {
- const MessageProperties* mprops = msg->getProperties<MessageProperties>();
- if (mprops->hasApplicationHeaders()) {
- const FieldTable& headers = mprops->getApplicationHeaders();
- if (headers.isSet(UpdateClient::X_QPID_EXPIRATION)) {
- msg->setExpiration(
- sys::AbsTime(sys::EPOCH, headers.getAsInt64(UpdateClient::X_QPID_EXPIRATION)));
- msg->removeCustomProperty(UpdateClient::X_QPID_EXPIRATION);
- // Erase props/headers that were added by the UpdateClient
- if (headers.isSet(UpdateClient::X_QPID_NO_MESSAGE_PROPS))
- msg->eraseProperties<MessageProperties>();
- else if (headers.isSet(UpdateClient::X_QPID_NO_HEADERS))
- msg->clearApplicationHeadersFlag();
- }
- }
- }
}
+
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/UpdateReceiver.h b/cpp/src/qpid/cluster/UpdateReceiver.h
index 81ee3a5ffe..7e8ce47662 100644
--- a/cpp/src/qpid/cluster/UpdateReceiver.h
+++ b/cpp/src/qpid/cluster/UpdateReceiver.h
@@ -39,20 +39,6 @@ class UpdateReceiver {
/** Management-id for the next shadow connection */
std::string nextShadowMgmtId;
-
- /** Record the position of a DtxBuffer in the DtxManager (xid + index)
- * and the association with a session, either suspended or current.
- */
- struct DtxBufferRef {
- std::string xid;
- uint32_t index; // Index in WorkRecord in DtxManager
- bool suspended; // Is this a suspended or current transaction?
- broker::SemanticState* semanticState; // Associated session
- DtxBufferRef(const std::string& x, uint32_t i, bool s, broker::SemanticState* ss)
- : xid(x), index(i), suspended(s), semanticState(ss) {}
- };
- typedef std::vector<DtxBufferRef> DtxBuffers;
- DtxBuffers dtxBuffers;
};
}} // namespace qpid::cluster
diff --git a/cpp/src/qpid/cluster/types.h b/cpp/src/qpid/cluster/types.h
index bfb4fd5b9e..0795e5e77a 100644
--- a/cpp/src/qpid/cluster/types.h
+++ b/cpp/src/qpid/cluster/types.h
@@ -24,7 +24,6 @@
#include "config.h"
#include "qpid/Url.h"
-#include "qpid/RefCounted.h"
#include "qpid/sys/IntegerTypes.h"
#include <boost/intrusive_ptr.hpp>
#include <utility>
diff --git a/cpp/src/qpid/console/SessionManager.cpp b/cpp/src/qpid/console/SessionManager.cpp
index 910ae22be8..80c5959417 100644
--- a/cpp/src/qpid/console/SessionManager.cpp
+++ b/cpp/src/qpid/console/SessionManager.cpp
@@ -362,11 +362,12 @@ void SessionManager::handleCommandComplete(Broker* broker, Buffer& inBuffer, uin
void SessionManager::handleClassInd(Broker* broker, Buffer& inBuffer, uint32_t)
{
+ uint8_t kind;
string packageName;
string className;
uint8_t hash[16];
- /*kind*/ (void) inBuffer.getOctet();
+ kind = inBuffer.getOctet();
inBuffer.getShortString(packageName);
inBuffer.getShortString(className);
inBuffer.getBin128(hash);
diff --git a/cpp/src/qpid/framing/AMQBody.h b/cpp/src/qpid/framing/AMQBody.h
index 56d1d250c1..60ac2d3b7e 100644
--- a/cpp/src/qpid/framing/AMQBody.h
+++ b/cpp/src/qpid/framing/AMQBody.h
@@ -46,7 +46,7 @@ struct AMQBodyConstVisitor {
virtual void visit(const AMQMethodBody&) = 0;
};
-class QPID_COMMON_CLASS_EXTERN AMQBody : public RefCounted {
+class AMQBody : public RefCounted {
public:
AMQBody() {}
QPID_COMMON_EXTERN virtual ~AMQBody();
diff --git a/cpp/src/qpid/framing/AMQContentBody.h b/cpp/src/qpid/framing/AMQContentBody.h
index e25451e354..69813b221c 100644
--- a/cpp/src/qpid/framing/AMQContentBody.h
+++ b/cpp/src/qpid/framing/AMQContentBody.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQContentBody : public AMQBody
+class AMQContentBody : public AMQBody
{
string data;
@@ -37,15 +37,15 @@ public:
QPID_COMMON_EXTERN AMQContentBody();
QPID_COMMON_EXTERN AMQContentBody(const string& data);
inline virtual ~AMQContentBody(){}
- inline uint8_t type() const { return CONTENT_BODY; };
- inline const string& getData() const { return data; }
- inline string& getData() { return data; }
+ QPID_COMMON_EXTERN inline uint8_t type() const { return CONTENT_BODY; };
+ QPID_COMMON_EXTERN inline const string& getData() const { return data; }
+ QPID_COMMON_EXTERN inline string& getData() { return data; }
QPID_COMMON_EXTERN uint32_t encodedSize() const;
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN void decode(Buffer& buffer, uint32_t size);
QPID_COMMON_EXTERN void print(std::ostream& out) const;
- void accept(AMQBodyConstVisitor& v) const { v.visit(*this); }
- boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
+ QPID_COMMON_EXTERN void accept(AMQBodyConstVisitor& v) const { v.visit(*this); }
+ QPID_COMMON_EXTERN boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
};
}
diff --git a/cpp/src/qpid/framing/AMQFrame.cpp b/cpp/src/qpid/framing/AMQFrame.cpp
index 5b9673f0d0..cd60cd971f 100644
--- a/cpp/src/qpid/framing/AMQFrame.cpp
+++ b/cpp/src/qpid/framing/AMQFrame.cpp
@@ -139,11 +139,6 @@ bool AMQFrame::decode(Buffer& buffer)
return true;
}
-void AMQFrame::cloneBody()
-{
- body = body->clone();
-}
-
std::ostream& operator<<(std::ostream& out, const AMQFrame& f)
{
return
diff --git a/cpp/src/qpid/framing/AMQFrame.h b/cpp/src/qpid/framing/AMQFrame.h
index 4f6faf4199..d7b04f0f65 100644
--- a/cpp/src/qpid/framing/AMQFrame.h
+++ b/cpp/src/qpid/framing/AMQFrame.h
@@ -33,7 +33,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock
+class AMQFrame : public AMQDataBlock
{
public:
QPID_COMMON_EXTERN AMQFrame(const boost::intrusive_ptr<AMQBody>& b=0);
@@ -59,11 +59,6 @@ class QPID_COMMON_CLASS_EXTERN AMQFrame : public AMQDataBlock
return boost::polymorphic_downcast<const T*>(getBody());
}
- /**
- * Take a deep copy of the body currently referenced
- */
- QPID_COMMON_EXTERN void cloneBody();
-
QPID_COMMON_EXTERN void encode(Buffer& buffer) const;
QPID_COMMON_EXTERN bool decode(Buffer& buffer);
QPID_COMMON_EXTERN uint32_t encodedSize() const;
diff --git a/cpp/src/qpid/framing/AMQHeaderBody.h b/cpp/src/qpid/framing/AMQHeaderBody.h
index 452154eb5c..8d96e35720 100644
--- a/cpp/src/qpid/framing/AMQHeaderBody.h
+++ b/cpp/src/qpid/framing/AMQHeaderBody.h
@@ -10,9 +10,9 @@
* 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
@@ -35,7 +35,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
+class AMQHeaderBody : public AMQBody
{
template <class T> struct OptProps { boost::optional<T> props; };
template <class Base, class T>
@@ -58,7 +58,7 @@ class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
}
else
return Base::decode(buffer, size, type);
- }
+ }
void print(std::ostream& out) const {
const boost::optional<T>& p=this->OptProps<T>::props;
if (p) out << *p;
@@ -77,7 +77,7 @@ class QPID_COMMON_CLASS_EXTERN AMQHeaderBody : public AMQBody
typedef PropSet<PropSet<Empty, DeliveryProperties>, MessageProperties> Properties;
Properties properties;
-
+
public:
inline uint8_t type() const { return HEADER_BODY; }
@@ -99,10 +99,6 @@ public:
return properties.OptProps<T>::props.get_ptr();
}
- template <class T> void erase() {
- properties.OptProps<T>::props.reset();
- }
-
boost::intrusive_ptr<AMQBody> clone() const { return BodyFactory::copy(*this); }
};
diff --git a/cpp/src/qpid/framing/AMQHeartbeatBody.h b/cpp/src/qpid/framing/AMQHeartbeatBody.h
index 19ac2be013..9b1fe8a4c1 100644
--- a/cpp/src/qpid/framing/AMQHeartbeatBody.h
+++ b/cpp/src/qpid/framing/AMQHeartbeatBody.h
@@ -29,7 +29,7 @@
namespace qpid {
namespace framing {
-class QPID_COMMON_CLASS_EXTERN AMQHeartbeatBody : public AMQBody
+class AMQHeartbeatBody : public AMQBody
{
public:
QPID_COMMON_EXTERN virtual ~AMQHeartbeatBody();
diff --git a/cpp/src/qpid/framing/FieldTable.cpp b/cpp/src/qpid/framing/FieldTable.cpp
index f80d2f9fb1..023e4af819 100644
--- a/cpp/src/qpid/framing/FieldTable.cpp
+++ b/cpp/src/qpid/framing/FieldTable.cpp
@@ -129,7 +129,7 @@ FieldTable::ValuePtr FieldTable::get(const std::string& name) const
namespace {
template <class T> T default_value() { return T(); }
template <> int default_value<int>() { return 0; }
- //template <> uint64_t default_value<uint64_t>() { return 0; }
+ template <> uint64_t default_value<uint64_t>() { return 0; }
}
template <class T>
@@ -198,12 +198,10 @@ void FieldTable::encode(Buffer& buffer) const {
void FieldTable::decode(Buffer& buffer){
clear();
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
uint32_t len = buffer.getLong();
if (len) {
uint32_t available = buffer.available();
- if ((available < len) || (available < 4))
+ if (available < len)
throw IllegalArgumentException(QPID_MSG("Not enough data for field table."));
uint32_t count = buffer.getLong();
uint32_t leftover = available - len;
diff --git a/cpp/src/qpid/framing/List.cpp b/cpp/src/qpid/framing/List.cpp
index d7ea172bac..963ebc206b 100644
--- a/cpp/src/qpid/framing/List.cpp
+++ b/cpp/src/qpid/framing/List.cpp
@@ -49,9 +49,6 @@ void List::encode(Buffer& buffer) const
void List::decode(Buffer& buffer)
{
values.clear();
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least "
- " 4 bytes but only " << buffer.available() << " available"));
uint32_t size = buffer.getLong();
uint32_t available = buffer.available();
if (available < size) {
@@ -59,9 +56,6 @@ void List::decode(Buffer& buffer)
<< size << " bytes but only " << available << " available"));
}
if (size) {
- if (buffer.available() < 4)
- throw IllegalArgumentException(QPID_MSG("Not enough data for list, expected at least "
- " 4 bytes but only " << buffer.available() << " available"));
uint32_t count = buffer.getLong();
for (uint32_t i = 0; i < count; i++) {
ValuePtr value(new FieldValue);
diff --git a/cpp/src/qpid/framing/MethodBodyFactory.h b/cpp/src/qpid/framing/MethodBodyFactory.h
index 88bc444795..607ec9d959 100644
--- a/cpp/src/qpid/framing/MethodBodyFactory.h
+++ b/cpp/src/qpid/framing/MethodBodyFactory.h
@@ -22,7 +22,6 @@
*
*/
#include "qpid/framing/amqp_types.h"
-#include "qpid/framing/AMQBody.h"
#include <boost/intrusive_ptr.hpp>
namespace qpid {
diff --git a/cpp/src/qpid/framing/SendContent.h b/cpp/src/qpid/framing/SendContent.h
index 1c464b9c8b..745c948c9e 100644
--- a/cpp/src/qpid/framing/SendContent.h
+++ b/cpp/src/qpid/framing/SendContent.h
@@ -37,7 +37,7 @@ namespace framing {
*/
class SendContent
{
- FrameHandler& handler;
+ mutable FrameHandler& handler;
const uint16_t maxFrameSize;
uint expectedFrameCount;
uint frameCount;
diff --git a/cpp/src/qpid/framing/TransferContent.h b/cpp/src/qpid/framing/TransferContent.h
index 9a698a1823..5fe1a513a9 100644
--- a/cpp/src/qpid/framing/TransferContent.h
+++ b/cpp/src/qpid/framing/TransferContent.h
@@ -32,7 +32,7 @@ namespace qpid {
namespace framing {
/** Message content */
-class QPID_COMMON_CLASS_EXTERN TransferContent : public MethodContent
+class TransferContent : public MethodContent
{
AMQHeaderBody header;
std::string data;
diff --git a/cpp/src/qpid/framing/Uuid.cpp b/cpp/src/qpid/framing/Uuid.cpp
index b3d1e2e1e4..945c0a4d24 100644
--- a/cpp/src/qpid/framing/Uuid.cpp
+++ b/cpp/src/qpid/framing/Uuid.cpp
@@ -59,9 +59,7 @@ void Uuid::clear() {
// Force int 0/!0 to false/true; avoids compile warnings.
bool Uuid::isNull() const {
- // This const cast is for Solaris which has a
- // uuid_is_null that takes a non const argument
- return !!uuid_is_null(const_cast<uint8_t*>(data()));
+ return !!uuid_is_null(data());
}
void Uuid::encode(Buffer& buf) const {
diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp
index 1600822142..2217cdddbd 100644
--- a/cpp/src/qpid/log/Logger.cpp
+++ b/cpp/src/qpid/log/Logger.cpp
@@ -22,7 +22,6 @@
#include "qpid/memory.h"
#include "qpid/sys/Thread.h"
#include "qpid/sys/Time.h"
-#include "qpid/DisableExceptionLogging.h"
#include <boost/pool/detail/singleton.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
@@ -49,16 +48,11 @@ Logger& Logger::instance() {
}
Logger::Logger() : flags(0) {
- // Disable automatic logging in Exception constructors to avoid
- // re-entrant use of logger singleton if there is an error in
- // option parsing.
- DisableExceptionLogging del;
-
// Initialize myself from env variables so all programs
// (e.g. tests) can use logging even if they don't parse
// command line args.
Options opts("");
- opts.parse(0, 0);
+ opts.parse(0, 0);
configure(opts);
}
@@ -79,12 +73,8 @@ void Logger::log(const Statement& s, const std::string& msg) {
std::ostringstream os;
if (!prefix.empty())
os << prefix << ": ";
- if (flags&TIME) {
- if (flags&HIRES)
- qpid::sys::outputHiresNow(os);
- else
- qpid::sys::outputFormattedNow(os);
- }
+ if (flags&TIME)
+ qpid::sys::outputFormattedNow(os);
if (flags&LEVEL)
os << LevelTraits::name(s.level) << " ";
if (flags&THREAD)
@@ -133,8 +123,7 @@ int Logger::format(const Options& opts) {
bitIf(opts.time, TIME) |
bitIf(opts.source, (FILE|LINE)) |
bitIf(opts.function, FUNCTION) |
- bitIf(opts.thread, THREAD) |
- bitIf(opts.hiresTs, HIRES);
+ bitIf(opts.thread, THREAD);
format(flags);
return flags;
}
@@ -151,7 +140,7 @@ void Logger::configure(const Options& opts) {
Options o(opts);
if (o.trace)
o.selectors.push_back("trace+");
- format(o);
+ format(o);
select(Selector(o));
setPrefix(opts.prefix);
options.sinkOptions->setup(this);
diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp
index 0001d00bdf..24ef413cbc 100644
--- a/cpp/src/qpid/log/Options.cpp
+++ b/cpp/src/qpid/log/Options.cpp
@@ -38,7 +38,6 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
thread(false),
source(false),
function(false),
- hiresTs(false),
trace(false),
sinkOptions (SinkOptions::create(argv0_))
{
@@ -66,7 +65,6 @@ Options::Options(const std::string& argv0_, const std::string& name_) :
("log-source", optValue(source,"yes|no"), "Include source file:line in log messages")
("log-thread", optValue(thread,"yes|no"), "Include thread ID in log messages")
("log-function", optValue(function,"yes|no"), "Include function signature in log messages")
- ("log-hires-timestamp", optValue(hiresTs,"yes|no"), "Use unformatted hi-res timestamp in log messages")
("log-prefix", optValue(prefix,"STRING"), "Prefix to append to all log messages")
;
add(*sinkOptions);
@@ -82,7 +80,6 @@ Options::Options(const Options &o) :
thread(o.thread),
source(o.source),
function(o.function),
- hiresTs(o.hiresTs),
trace(o.trace),
prefix(o.prefix),
sinkOptions (SinkOptions::create(o.argv0))
@@ -100,7 +97,6 @@ Options& Options::operator=(const Options& x) {
thread = x.thread;
source = x.source;
function = x.function;
- hiresTs = x.hiresTs;
trace = x.trace;
prefix = x.prefix;
*sinkOptions = *x.sinkOptions;
diff --git a/cpp/src/qpid/log/Statement.cpp b/cpp/src/qpid/log/Statement.cpp
index 7dfdf08703..6a32b50096 100644
--- a/cpp/src/qpid/log/Statement.cpp
+++ b/cpp/src/qpid/log/Statement.cpp
@@ -27,6 +27,8 @@ namespace qpid {
namespace log {
namespace {
+using namespace std;
+
struct NonPrint { bool operator()(unsigned char c) { return !isprint(c) && !isspace(c); } };
const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
@@ -37,7 +39,7 @@ std::string quote(const std::string& str) {
if (n==0) return str;
std::string ret;
ret.reserve(str.size()+2*n); // Avoid extra allocations.
- for (std::string::const_iterator i = str.begin(); i != str.end(); ++i) {
+ for (string::const_iterator i = str.begin(); i != str.end(); ++i) {
if (nonPrint(*i)) {
ret.push_back('\\');
ret.push_back('x');
@@ -48,6 +50,7 @@ std::string quote(const std::string& str) {
}
return ret;
}
+
}
void Statement::log(const std::string& message) {
diff --git a/cpp/src/qpid/log/posix/SinkOptions.cpp b/cpp/src/qpid/log/posix/SinkOptions.cpp
index ffa7633e3b..292e9147f6 100644
--- a/cpp/src/qpid/log/posix/SinkOptions.cpp
+++ b/cpp/src/qpid/log/posix/SinkOptions.cpp
@@ -180,7 +180,7 @@ qpid::log::SinkOptions& SinkOptions::operator=(const qpid::log::SinkOptions& rhs
}
void SinkOptions::detached(void) {
- if (logToStderr && !logToStdout && !logToSyslog && logFile.empty()) {
+ if (logToStderr && !logToStdout && !logToSyslog) {
logToStderr = false;
logToSyslog = true;
}
diff --git a/cpp/src/qpid/log/windows/SinkOptions.cpp b/cpp/src/qpid/log/windows/SinkOptions.cpp
index 0c74bea64e..28f4b267e0 100644
--- a/cpp/src/qpid/log/windows/SinkOptions.cpp
+++ b/cpp/src/qpid/log/windows/SinkOptions.cpp
@@ -53,7 +53,7 @@ static int eventTypes[qpid::log::LevelTraits::COUNT] = {
class EventLogOutput : public qpid::log::Logger::Output {
public:
- EventLogOutput(const std::string& /*sourceName*/) : logHandle(0)
+ EventLogOutput(const std::string& sourceName) : logHandle(0)
{
logHandle = OpenEventLog(0, "Application");
}
@@ -83,7 +83,7 @@ private:
HANDLE logHandle;
};
-SinkOptions::SinkOptions(const std::string& /*argv0*/)
+SinkOptions::SinkOptions(const std::string& argv0)
: qpid::log::SinkOptions(),
logToStderr(true),
logToStdout(false),
diff --git a/cpp/src/qpid/log/windows/SinkOptions.h b/cpp/src/qpid/log/windows/SinkOptions.h
index f270c504a2..605822fd46 100644
--- a/cpp/src/qpid/log/windows/SinkOptions.h
+++ b/cpp/src/qpid/log/windows/SinkOptions.h
@@ -26,7 +26,7 @@ namespace qpid {
namespace log {
namespace windows {
-struct QPID_COMMON_CLASS_EXTERN SinkOptions : public qpid::log::SinkOptions {
+struct SinkOptions : public qpid::log::SinkOptions {
QPID_COMMON_EXTERN SinkOptions(const std::string& argv0);
virtual ~SinkOptions() {}
diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp
index 5799a1adca..23c999a98a 100644
--- a/cpp/src/qpid/management/ManagementAgent.cpp
+++ b/cpp/src/qpid/management/ManagementAgent.cpp
@@ -31,7 +31,6 @@
#include <qpid/broker/Message.h>
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/sys/Time.h"
-#include "qpid/sys/Thread.h"
#include "qpid/broker/ConnectionState.h"
#include "qpid/broker/AclModule.h"
#include "qpid/types/Variant.h"
@@ -75,18 +74,6 @@ namespace {
}
return n2;
}
-
-struct ScopedManagementContext
-{
- ScopedManagementContext(const qpid::broker::ConnectionState* context)
- {
- setManagementExecutionContext(context);
- }
- ~ScopedManagementContext()
- {
- setManagementExecutionContext(0);
- }
-};
}
@@ -548,7 +535,6 @@ void ManagementAgent::sendBufferLH(Buffer& buf,
dp->setRoutingKey(routingKey);
msg->getFrames().append(content);
- msg->setIsManagementMessage(true);
{
sys::Mutex::ScopedUnlock u(userLock);
@@ -614,7 +600,7 @@ void ManagementAgent::sendBufferLH(const string& data,
props->setAppId("qmf2");
for (i = headers.begin(); i != headers.end(); ++i) {
- msg->insertCustomProperty(i->first, i->second.asString());
+ msg->getOrInsertHeaders().setString(i->first, i->second.asString());
}
DeliveryProperties* dp =
@@ -622,10 +608,9 @@ void ManagementAgent::sendBufferLH(const string& data,
dp->setRoutingKey(routingKey);
if (ttl_msec) {
dp->setTtl(ttl_msec);
- msg->computeExpiration(broker->getExpiryPolicy());
+ msg->setTimestamp(broker->getExpiryPolicy());
}
msg->getFrames().append(content);
- msg->setIsManagementMessage(true);
{
sys::Mutex::ScopedUnlock u(userLock);
@@ -2252,7 +2237,6 @@ void ManagementAgent::dispatchAgentCommandLH(Message& msg, bool viaLocal)
uint32_t bufferLen = inBuffer.getPosition();
inBuffer.reset();
- ScopedManagementContext context((const qpid::broker::ConnectionState*) msg.getPublisher());
const framing::FieldTable *headers = msg.getApplicationHeaders();
if (headers && msg.getAppId() == "qmf2")
{
@@ -2756,14 +2740,200 @@ void ManagementAgent::debugSnapshot(const char* title) {
title << ": new objects" << dumpVector(newManagementObjects));
}
-
Variant::Map ManagementAgent::toMap(const FieldTable& from)
{
Variant::Map map;
- qpid::amqp_0_10::translate(from, map);
+
+ for (FieldTable::const_iterator iter = from.begin(); iter != from.end(); iter++) {
+ const string& key(iter->first);
+ const FieldTable::ValuePtr& val(iter->second);
+
+ map[key] = toVariant(val);
+ }
+
return map;
}
+Variant::List ManagementAgent::toList(const List& from)
+{
+ Variant::List _list;
+
+ for (List::const_iterator iter = from.begin(); iter != from.end(); iter++) {
+ const List::ValuePtr& val(*iter);
+
+ _list.push_back(toVariant(val));
+ }
+
+ return _list;
+}
+
+qpid::framing::FieldTable ManagementAgent::fromMap(const Variant::Map& from)
+{
+ qpid::framing::FieldTable ft;
+
+ for (Variant::Map::const_iterator iter = from.begin();
+ iter != from.end();
+ iter++) {
+ const string& key(iter->first);
+ const Variant& val(iter->second);
+
+ ft.set(key, toFieldValue(val));
+ }
+
+ return ft;
+}
+
+
+List ManagementAgent::fromList(const Variant::List& from)
+{
+ List fa;
+
+ for (Variant::List::const_iterator iter = from.begin();
+ iter != from.end();
+ iter++) {
+ const Variant& val(*iter);
+
+ fa.push_back(toFieldValue(val));
+ }
+
+ return fa;
+}
+
+
+boost::shared_ptr<FieldValue> ManagementAgent::toFieldValue(const Variant& in)
+{
+
+ switch(in.getType()) {
+
+ case types::VAR_VOID: return boost::shared_ptr<FieldValue>(new VoidValue());
+ case types::VAR_BOOL: return boost::shared_ptr<FieldValue>(new BoolValue(in.asBool()));
+ case types::VAR_UINT8: return boost::shared_ptr<FieldValue>(new Unsigned8Value(in.asUint8()));
+ case types::VAR_UINT16: return boost::shared_ptr<FieldValue>(new Unsigned16Value(in.asUint16()));
+ case types::VAR_UINT32: return boost::shared_ptr<FieldValue>(new Unsigned32Value(in.asUint32()));
+ case types::VAR_UINT64: return boost::shared_ptr<FieldValue>(new Unsigned64Value(in.asUint64()));
+ case types::VAR_INT8: return boost::shared_ptr<FieldValue>(new Integer8Value(in.asInt8()));
+ case types::VAR_INT16: return boost::shared_ptr<FieldValue>(new Integer16Value(in.asInt16()));
+ case types::VAR_INT32: return boost::shared_ptr<FieldValue>(new Integer32Value(in.asInt32()));
+ case types::VAR_INT64: return boost::shared_ptr<FieldValue>(new Integer64Value(in.asInt64()));
+ case types::VAR_FLOAT: return boost::shared_ptr<FieldValue>(new FloatValue(in.asFloat()));
+ case types::VAR_DOUBLE: return boost::shared_ptr<FieldValue>(new DoubleValue(in.asDouble()));
+ case types::VAR_STRING: return boost::shared_ptr<FieldValue>(new Str16Value(in.asString()));
+ case types::VAR_UUID: return boost::shared_ptr<FieldValue>(new UuidValue(in.asUuid().data()));
+ case types::VAR_MAP: return boost::shared_ptr<FieldValue>(new FieldTableValue(ManagementAgent::fromMap(in.asMap())));
+ case types::VAR_LIST: return boost::shared_ptr<FieldValue>(new ListValue(ManagementAgent::fromList(in.asList())));
+ }
+
+ QPID_LOG(error, "Unknown Variant type - not converted: [" << in.getType() << "]");
+ return boost::shared_ptr<FieldValue>(new VoidValue());
+}
+
+// stolen from qpid/client/amqp0_10/Codecs.cpp - TODO: make Codecs public, and remove this dup.
+Variant ManagementAgent::toVariant(const boost::shared_ptr<FieldValue>& in)
+{
+ const string iso885915("iso-8859-15");
+ const string utf8("utf8");
+ const string utf16("utf16");
+ //const string binary("binary");
+ const string amqp0_10_binary("amqp0-10:binary");
+ //const string amqp0_10_bit("amqp0-10:bit");
+ const string amqp0_10_datetime("amqp0-10:datetime");
+ const string amqp0_10_struct("amqp0-10:struct");
+ Variant out;
+
+ //based on AMQP 0-10 typecode, pick most appropriate variant type
+ switch (in->getType()) {
+ //Fixed Width types:
+ case 0x00: //bin8
+ case 0x01: out.setEncoding(amqp0_10_binary); // int8
+ case 0x02: out = in->getIntegerValue<int8_t, 1>(); break; //uint8
+ case 0x03: out = in->getIntegerValue<uint8_t, 1>(); break; //
+ // case 0x04: break; //TODO: iso-8859-15 char // char
+ case 0x08: out = static_cast<bool>(in->getIntegerValue<uint8_t, 1>()); break; // bool int8
+
+ case 0x10: out.setEncoding(amqp0_10_binary); // bin16
+ case 0x11: out = in->getIntegerValue<int16_t, 2>(); break; // int16
+ case 0x12: out = in->getIntegerValue<uint16_t, 2>(); break; //uint16
+
+ case 0x20: out.setEncoding(amqp0_10_binary); // bin32
+ case 0x21: out = in->getIntegerValue<int32_t, 4>(); break; // int32
+ case 0x22: out = in->getIntegerValue<uint32_t, 4>(); break; // uint32
+
+ case 0x23: out = in->get<float>(); break; // float(32)
+
+ // case 0x27: break; //TODO: utf-32 char
+
+ case 0x30: out.setEncoding(amqp0_10_binary); // bin64
+ case 0x31: out = in->getIntegerValue<int64_t, 8>(); break; //int64
+
+ case 0x38: out.setEncoding(amqp0_10_datetime); //treat datetime as uint64_t, but set encoding
+ case 0x32: out = in->getIntegerValue<uint64_t, 8>(); break; //uint64
+ case 0x33: out = in->get<double>(); break; // double
+
+ case 0x48: // uuid
+ {
+ unsigned char data[16];
+ in->getFixedWidthValue<16>(data);
+ out = qpid::types::Uuid(data);
+ } break;
+
+ //TODO: figure out whether and how to map values with codes 0x40-0xd8
+
+ case 0xf0: break;//void, which is the default value for Variant
+ // case 0xf1: out.setEncoding(amqp0_10_bit); break;//treat 'bit' as void, which is the default value for Variant
+
+ //Variable Width types:
+ //strings:
+ case 0x80: // str8
+ case 0x90: // str16
+ case 0xa0: // str32
+ out = in->get<string>();
+ out.setEncoding(amqp0_10_binary);
+ break;
+
+ case 0x84: // str8
+ case 0x94: // str16
+ out = in->get<string>();
+ out.setEncoding(iso885915);
+ break;
+
+ case 0x85: // str8
+ case 0x95: // str16
+ out = in->get<string>();
+ out.setEncoding(utf8);
+ break;
+
+ case 0x86: // str8
+ case 0x96: // str16
+ out = in->get<string>();
+ out.setEncoding(utf16);
+ break;
+
+ case 0xab: // str32
+ out = in->get<string>();
+ out.setEncoding(amqp0_10_struct);
+ break;
+
+ case 0xa8: // map
+ out = ManagementAgent::toMap(in->get<FieldTable>());
+ break;
+
+ case 0xa9: // list of variant types
+ out = ManagementAgent::toList(in->get<List>());
+ break;
+ //case 0xaa: //convert amqp0-10 array (uniform type) into variant list
+ // out = Variant::List();
+ // translate<Array>(in, out.asList(), &toVariant);
+ // break;
+
+ default:
+ //error?
+ QPID_LOG(error, "Unknown FieldValue type - not converted: [" << (unsigned int)(in->getType()) << "]");
+ break;
+ }
+
+ return out;
+}
+
// Build up a list of the current set of deleted objects that are pending their
// next (last) publish-ment.
@@ -2915,21 +3085,3 @@ bool ManagementAgent::moveDeletedObjectsLH() {
}
return !deleteList.empty();
}
-
-namespace qpid {
-namespace management {
-
-namespace {
-QPID_TSS const qpid::broker::ConnectionState* executionContext = 0;
-}
-
-void setManagementExecutionContext(const qpid::broker::ConnectionState* ctxt)
-{
- executionContext = ctxt;
-}
-const qpid::broker::ConnectionState* getManagementExecutionContext()
-{
- return executionContext;
-}
-
-}}
diff --git a/cpp/src/qpid/management/ManagementAgent.h b/cpp/src/qpid/management/ManagementAgent.h
index c21f384433..0db19594a7 100644
--- a/cpp/src/qpid/management/ManagementAgent.h
+++ b/cpp/src/qpid/management/ManagementAgent.h
@@ -41,9 +41,6 @@
#include <map>
namespace qpid {
-namespace broker {
-class ConnectionState;
-}
namespace management {
class ManagementAgent
@@ -145,7 +142,13 @@ public:
const framing::Uuid& getUuid() const { return uuid; }
void setUuid(const framing::Uuid& id) { uuid = id; writeData(); }
+ // TODO: remove these when Variant API moved into common library.
static types::Variant::Map toMap(const framing::FieldTable& from);
+ static framing::FieldTable fromMap(const types::Variant::Map& from);
+ static types::Variant::List toList(const framing::List& from);
+ static framing::List fromList(const types::Variant::List& from);
+ static boost::shared_ptr<framing::FieldValue> toFieldValue(const types::Variant& in);
+ static types::Variant toVariant(const boost::shared_ptr<framing::FieldValue>& val);
// For Clustering: management objects that have been marked as
// "deleted", but are waiting for their last published object
@@ -419,8 +422,6 @@ private:
void debugSnapshot(const char* title);
};
-void setManagementExecutionContext(const qpid::broker::ConnectionState*);
-const qpid::broker::ConnectionState* getManagementExecutionContext();
}}
-
+
#endif /*!_ManagementAgent_*/
diff --git a/cpp/src/qpid/messaging/AddressParser.cpp b/cpp/src/qpid/messaging/AddressParser.cpp
index d76210ee5d..4c8f35fbc5 100644
--- a/cpp/src/qpid/messaging/AddressParser.cpp
+++ b/cpp/src/qpid/messaging/AddressParser.cpp
@@ -151,7 +151,7 @@ bool AddressParser::readValueIfExists(Variant& value)
bool AddressParser::readString(std::string& value, char delimiter)
{
if (readChar(delimiter)) {
- std::string::size_type start = current;
+ std::string::size_type start = current++;
while (!eos()) {
if (input.at(current) == delimiter) {
if (current > start) {
@@ -201,8 +201,7 @@ bool AddressParser::readSimpleValue(Variant& value)
{
std::string s;
if (readWord(s)) {
- value.parse(s);
- if (value.getType() == VAR_STRING) value.setEncoding("utf8");
+ value.parse(s);
return true;
} else {
return false;
diff --git a/cpp/src/qpid/messaging/Duration.cpp b/cpp/src/qpid/messaging/Duration.cpp
index a23e9f5bcb..a2c443c746 100644
--- a/cpp/src/qpid/messaging/Duration.cpp
+++ b/cpp/src/qpid/messaging/Duration.cpp
@@ -37,16 +37,6 @@ Duration operator*(uint64_t multiplier, const Duration& duration)
return Duration(duration.getMilliseconds() * multiplier);
}
-bool operator==(const Duration& a, const Duration& b)
-{
- return a.getMilliseconds() == b.getMilliseconds();
-}
-
-bool operator!=(const Duration& a, const Duration& b)
-{
- return a.getMilliseconds() != b.getMilliseconds();
-}
-
const Duration Duration::FOREVER(std::numeric_limits<uint64_t>::max());
const Duration Duration::IMMEDIATE(0);
const Duration Duration::SECOND(1000);
diff --git a/cpp/src/qpid/messaging/Message.cpp b/cpp/src/qpid/messaging/Message.cpp
index ef70c103e9..83cdfd3c55 100644
--- a/cpp/src/qpid/messaging/Message.cpp
+++ b/cpp/src/qpid/messaging/Message.cpp
@@ -21,7 +21,6 @@
#include "qpid/messaging/Message.h"
#include "qpid/messaging/MessageImpl.h"
#include "qpid/amqp_0_10/Codecs.h"
-#include <qpid/Exception.h>
#include <boost/format.hpp>
namespace qpid {
@@ -116,11 +115,7 @@ template <class C> struct MessageCodec
static void decode(const Message& message, typename C::ObjectType& object, const std::string& encoding)
{
checkEncoding(message, encoding);
- try {
- C::decode(message.getContent(), object);
- } catch (const qpid::Exception &ex) {
- throw EncodingException(ex.what());
- }
+ C::decode(message.getContent(), object);
}
static void encode(const typename C::ObjectType& map, Message& message, const std::string& encoding)
diff --git a/cpp/src/qpid/messaging/Session.cpp b/cpp/src/qpid/messaging/Session.cpp
index cccfd9a873..496953a8e5 100644
--- a/cpp/src/qpid/messaging/Session.cpp
+++ b/cpp/src/qpid/messaging/Session.cpp
@@ -39,8 +39,7 @@ Session& Session::operator=(const Session& s) { return PI::assign(*this, s); }
void Session::commit() { impl->commit(); }
void Session::rollback() { impl->rollback(); }
void Session::acknowledge(bool sync) { impl->acknowledge(sync); }
-void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m, false); sync(s); }
-void Session::acknowledgeUpTo(Message& m, bool s) { impl->acknowledge(m, true); sync(s); }
+void Session::acknowledge(Message& m, bool s) { impl->acknowledge(m); sync(s); }
void Session::reject(Message& m) { impl->reject(m); }
void Session::release(Message& m) { impl->release(m); }
void Session::close() { impl->close(); }
diff --git a/cpp/src/qpid/messaging/SessionImpl.h b/cpp/src/qpid/messaging/SessionImpl.h
index 60ae615253..02a254e4f2 100644
--- a/cpp/src/qpid/messaging/SessionImpl.h
+++ b/cpp/src/qpid/messaging/SessionImpl.h
@@ -41,7 +41,7 @@ class SessionImpl : public virtual qpid::RefCounted
virtual void commit() = 0;
virtual void rollback() = 0;
virtual void acknowledge(bool sync) = 0;
- virtual void acknowledge(Message&, bool cumulative) = 0;
+ virtual void acknowledge(Message&) = 0;
virtual void reject(Message&) = 0;
virtual void release(Message&) = 0;
virtual void close() = 0;
diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.cpp b/cpp/src/qpid/replication/ReplicatingEventListener.cpp
index 0ced4d9161..b7d52372f4 100644
--- a/cpp/src/qpid/replication/ReplicatingEventListener.cpp
+++ b/cpp/src/qpid/replication/ReplicatingEventListener.cpp
@@ -69,9 +69,10 @@ void ReplicatingEventListener::deliverDequeueMessage(const QueuedMessage& dequeu
void ReplicatingEventListener::deliverEnqueueMessage(const QueuedMessage& enqueued)
{
boost::intrusive_ptr<Message> msg(cloneMessage(*(enqueued.queue), enqueued.payload));
- msg->insertCustomProperty(REPLICATION_TARGET_QUEUE, enqueued.queue->getName());
- msg->insertCustomProperty(REPLICATION_EVENT_TYPE, ENQUEUE);
- msg->insertCustomProperty(QUEUE_MESSAGE_POSITION,enqueued.position);
+ FieldTable& headers = msg->getProperties<MessageProperties>()->getApplicationHeaders();
+ headers.setString(REPLICATION_TARGET_QUEUE, enqueued.queue->getName());
+ headers.setInt(REPLICATION_EVENT_TYPE, ENQUEUE);
+ headers.setInt(QUEUE_MESSAGE_POSITION,enqueued.position);
route(msg);
}
diff --git a/cpp/src/qpid/replication/ReplicationExchange.cpp b/cpp/src/qpid/replication/ReplicationExchange.cpp
index 89a2bf516d..4b6d25ac7d 100644
--- a/cpp/src/qpid/replication/ReplicationExchange.cpp
+++ b/cpp/src/qpid/replication/ReplicationExchange.cpp
@@ -97,10 +97,11 @@ void ReplicationExchange::handleEnqueueEvent(const FieldTable* args, Deliverable
} else {
queue->setPosition(seqno1);
- msg.getMessage().removeCustomProperty(REPLICATION_TARGET_QUEUE);
- msg.getMessage().removeCustomProperty(REPLICATION_EVENT_SEQNO);
- msg.getMessage().removeCustomProperty(REPLICATION_EVENT_TYPE);
- msg.getMessage().removeCustomProperty(QUEUE_MESSAGE_POSITION);
+ FieldTable& headers = msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders();
+ headers.erase(REPLICATION_TARGET_QUEUE);
+ headers.erase(REPLICATION_EVENT_SEQNO);
+ headers.erase(REPLICATION_EVENT_TYPE);
+ headers.erase(QUEUE_MESSAGE_POSITION);
msg.deliverTo(queue);
QPID_LOG(debug, "Enqueued replicated message onto " << queueName);
if (mgmtExchange != 0) {
diff --git a/cpp/src/qpid/store/StorageProvider.h b/cpp/src/qpid/store/StorageProvider.h
index d162cc58ec..bc8d187517 100644
--- a/cpp/src/qpid/store/StorageProvider.h
+++ b/cpp/src/qpid/store/StorageProvider.h
@@ -54,7 +54,7 @@ struct QueueEntry {
QueueEntry(uint64_t id, TplStatus tpl = NONE, const std::string& x = "")
: queueId(id), tplStatus(tpl), xid(x) {}
- bool operator==(const QueueEntry& rhs) const {
+ bool operator==(const QueueEntry& rhs) {
if (queueId != rhs.queueId) return false;
if (tplStatus == NONE && rhs.tplStatus == NONE) return true;
return xid == rhs.xid;
diff --git a/cpp/src/qpid/sys/AggregateOutput.h b/cpp/src/qpid/sys/AggregateOutput.h
index d7c0ff29e3..6dad998bb0 100644
--- a/cpp/src/qpid/sys/AggregateOutput.h
+++ b/cpp/src/qpid/sys/AggregateOutput.h
@@ -41,7 +41,7 @@ namespace sys {
* doOutput is called in another.
*/
-class QPID_COMMON_CLASS_EXTERN AggregateOutput : public OutputTask, public OutputControl
+class AggregateOutput : public OutputTask, public OutputControl
{
typedef std::deque<OutputTask*> TaskList;
diff --git a/cpp/src/qpid/sys/AsynchIO.h b/cpp/src/qpid/sys/AsynchIO.h
index 41f74f7ed0..50da8fa4fc 100644
--- a/cpp/src/qpid/sys/AsynchIO.h
+++ b/cpp/src/qpid/sys/AsynchIO.h
@@ -64,8 +64,8 @@ public:
// deletes. To correctly manage heaps when needed, the allocate and
// delete should both be done from the same class/library.
QPID_COMMON_EXTERN static AsynchConnector* create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb);
virtual void start(boost::shared_ptr<Poller> poller) = 0;
diff --git a/cpp/src/qpid/sys/AsynchIOHandler.h b/cpp/src/qpid/sys/AsynchIOHandler.h
index b9867606c4..e1885bac79 100644
--- a/cpp/src/qpid/sys/AsynchIOHandler.h
+++ b/cpp/src/qpid/sys/AsynchIOHandler.h
@@ -57,7 +57,7 @@ class AsynchIOHandler : public OutputControl {
QPID_COMMON_EXTERN ~AsynchIOHandler();
QPID_COMMON_EXTERN void init(AsynchIO* a, int numBuffs);
- QPID_COMMON_INLINE_EXTERN void setClient() { isClient = true; }
+ QPID_COMMON_EXTERN void setClient() { isClient = true; }
// Output side
QPID_COMMON_EXTERN void abort();
diff --git a/cpp/src/qpid/sys/AtomicValue.h b/cpp/src/qpid/sys/AtomicValue.h
index bf995f991e..6e90eafead 100644
--- a/cpp/src/qpid/sys/AtomicValue.h
+++ b/cpp/src/qpid/sys/AtomicValue.h
@@ -22,12 +22,7 @@
*
*/
-// Have to check for clang before gcc as clang pretends to be gcc too
-#if defined( __clang__ )
-// Use the clang doesn't support atomic builtins for 64 bit values, so use the slow versions
-#include "qpid/sys/AtomicValue_mutex.h"
-
-#elif defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) )
+#if defined( __GNUC__ ) && __GNUC__ >= 4 && ( defined( __i686__ ) || defined( __x86_64__ ) )
// Use the Gnu C built-in atomic operations if compiling with gcc on a suitable platform.
#include "qpid/sys/AtomicValue_gcc.h"
diff --git a/cpp/src/qpid/sys/AtomicValue_gcc.h b/cpp/src/qpid/sys/AtomicValue_gcc.h
index 724bae422e..d022b07c1d 100644
--- a/cpp/src/qpid/sys/AtomicValue_gcc.h
+++ b/cpp/src/qpid/sys/AtomicValue_gcc.h
@@ -10,9 +10,9 @@
* 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
@@ -39,9 +39,6 @@ class AtomicValue
public:
AtomicValue(T init=0) : value(init) {}
- // Not atomic. Don't call concurrently with atomic ops.
- AtomicValue<T>& operator=(T newValue) { value = newValue; return *this; }
-
// Update and return new value.
inline T operator+=(T n) { return __sync_add_and_fetch(&value, n); }
inline T operator-=(T n) { return __sync_sub_and_fetch(&value, n); }
@@ -57,11 +54,11 @@ class AtomicValue
/** If current value == testval then set to newval. Returns the old value. */
T valueCompareAndSwap(T testval, T newval) { return __sync_val_compare_and_swap(&value, testval, newval); }
- /** If current value == testval then set to newval. Returns true if the swap was performed. */
+ /** If current value == testval then set to newval. Returns true if the swap was performed. */
bool boolCompareAndSwap(T testval, T newval) { return __sync_bool_compare_and_swap(&value, testval, newval); }
T get() const { return const_cast<AtomicValue<T>*>(this)->fetchAndAdd(static_cast<T>(0)); }
-
+
private:
T value;
};
diff --git a/cpp/src/qpid/sys/ClusterSafe.cpp b/cpp/src/qpid/sys/ClusterSafe.cpp
index dd37615145..c6b527dfdf 100644
--- a/cpp/src/qpid/sys/ClusterSafe.cpp
+++ b/cpp/src/qpid/sys/ClusterSafe.cpp
@@ -34,6 +34,8 @@ QPID_TSS bool inContext = false;
bool isClusterSafe() { return !inCluster || inContext; }
+bool isCluster() { return inCluster; }
+
void assertClusterSafe() {
if (!isClusterSafe()) {
QPID_LOG(critical, "Modified cluster state outside of cluster context");
@@ -51,16 +53,6 @@ ClusterSafeScope::~ClusterSafeScope() {
inContext = save;
}
-ClusterUnsafeScope::ClusterUnsafeScope() {
- save = inContext;
- inContext = false;
-}
-
-ClusterUnsafeScope::~ClusterUnsafeScope() {
- assert(!inContext);
- inContext = save;
-}
-
void enableClusterSafe() { inCluster = true; }
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/ClusterSafe.h b/cpp/src/qpid/sys/ClusterSafe.h
index 27e4eb46a5..15675e8cc5 100644
--- a/cpp/src/qpid/sys/ClusterSafe.h
+++ b/cpp/src/qpid/sys/ClusterSafe.h
@@ -52,9 +52,14 @@ QPID_COMMON_EXTERN void assertClusterSafe();
*/
QPID_COMMON_EXTERN bool isClusterSafe();
+/** Return true in a clustered broker */
+QPID_COMMON_EXTERN bool isCluster();
+
/**
- * Mark a scope as cluster safe. Sets isClusterSafe in constructor and resets
- * to previous value in destructor.
+ * Base class for classes that encapsulate state which is replicated
+ * to all members of a cluster. Acts as a marker for clustered state
+ * and provides functions to assist detecting bugs in cluster
+ * behavior.
*/
class ClusterSafeScope {
public:
@@ -65,18 +70,6 @@ class ClusterSafeScope {
};
/**
- * Mark a scope as cluster unsafe. Clears isClusterSafe in constructor and resets
- * to previous value in destructor.
- */
-class ClusterUnsafeScope {
- public:
- QPID_COMMON_EXTERN ClusterUnsafeScope();
- QPID_COMMON_EXTERN ~ClusterUnsafeScope();
- private:
- bool save;
-};
-
-/**
* Enable cluster-safe assertions. By default they are no-ops.
* Called by cluster code.
*/
diff --git a/cpp/src/qpid/sys/CopyOnWriteArray.h b/cpp/src/qpid/sys/CopyOnWriteArray.h
index 41384fc5a4..45a231dfd8 100644
--- a/cpp/src/qpid/sys/CopyOnWriteArray.h
+++ b/cpp/src/qpid/sys/CopyOnWriteArray.h
@@ -43,12 +43,6 @@ public:
CopyOnWriteArray() {}
CopyOnWriteArray(const CopyOnWriteArray& c) : array(c.array) {}
- bool empty()
- {
- Mutex::ScopedLock l(lock);
- return array ? array->empty() : true;
- }
-
void add(T& t)
{
Mutex::ScopedLock l(lock);
diff --git a/cpp/src/qpid/sys/PollableQueue.h b/cpp/src/qpid/sys/PollableQueue.h
index 03b9d0084d..81c2301c1e 100644
--- a/cpp/src/qpid/sys/PollableQueue.h
+++ b/cpp/src/qpid/sys/PollableQueue.h
@@ -10,9 +10,9 @@
* 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
@@ -28,8 +28,7 @@
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <algorithm>
-#include <deque>
-#include "qpid/log/Statement.h" // FIXME aconway 2011-08-05:
+#include <vector>
namespace qpid {
namespace sys {
@@ -45,7 +44,7 @@ class Poller;
template <class T>
class PollableQueue {
public:
- typedef std::deque<T> Batch;
+ typedef std::vector<T> Batch;
typedef T value_type;
/**
@@ -69,11 +68,11 @@ class PollableQueue {
const boost::shared_ptr<sys::Poller>& poller);
~PollableQueue();
-
+
/** Push a value onto the queue. Thread safe */
void push(const T& t);
- /** Start polling. */
+ /** Start polling. */
void start();
/** Stop polling and wait for the current callback, if any, to complete. */
@@ -91,14 +90,14 @@ class PollableQueue {
* ensure clean shutdown with no events left on the queue.
*/
void shutdown();
-
+
private:
typedef sys::Monitor::ScopedLock ScopedLock;
typedef sys::Monitor::ScopedUnlock ScopedUnlock;
void dispatch(PollableCondition& cond);
void process();
-
+
mutable sys::Monitor lock;
Callback callback;
PollableCondition condition;
@@ -108,7 +107,7 @@ class PollableQueue {
};
template <class T> PollableQueue<T>::PollableQueue(
- const Callback& cb, const boost::shared_ptr<sys::Poller>& p)
+ const Callback& cb, const boost::shared_ptr<sys::Poller>& p)
: callback(cb),
condition(boost::bind(&PollableQueue<T>::dispatch, this, _1), p),
stopped(true)
@@ -152,7 +151,7 @@ template <class T> void PollableQueue<T>::process() {
putBack = callback(batch);
}
// put back unprocessed items.
- queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end()));
+ queue.insert(queue.begin(), putBack, typename Batch::const_iterator(batch.end()));
batch.clear();
}
}
diff --git a/cpp/src/qpid/sys/Poller.h b/cpp/src/qpid/sys/Poller.h
index 01ee139ee6..ec53b79bad 100644
--- a/cpp/src/qpid/sys/Poller.h
+++ b/cpp/src/qpid/sys/Poller.h
@@ -120,7 +120,7 @@ class PollerHandle {
friend struct Poller::Event;
PollerHandlePrivate* const impl;
- QPID_COMMON_INLINE_EXTERN virtual void processEvent(Poller::EventType) {};
+ QPID_COMMON_EXTERN virtual void processEvent(Poller::EventType) {};
public:
QPID_COMMON_EXTERN PollerHandle(const IOHandle& h);
diff --git a/cpp/src/qpid/sys/ProtocolFactory.h b/cpp/src/qpid/sys/ProtocolFactory.h
index 4d198a92da..b233b2da1a 100644
--- a/cpp/src/qpid/sys/ProtocolFactory.h
+++ b/cpp/src/qpid/sys/ProtocolFactory.h
@@ -39,10 +39,11 @@ class ProtocolFactory : public qpid::SharedObject<ProtocolFactory>
virtual ~ProtocolFactory() = 0;
virtual uint16_t getPort() const = 0;
+ virtual std::string getHost() const = 0;
virtual void accept(boost::shared_ptr<Poller>, ConnectionCodec::Factory*) = 0;
virtual void connect(
boost::shared_ptr<Poller>,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* codec,
ConnectFailedCallback failed) = 0;
virtual bool supports(const std::string& /*capability*/) { return false; }
diff --git a/cpp/src/qpid/sys/RdmaIOPlugin.cpp b/cpp/src/qpid/sys/RdmaIOPlugin.cpp
index 6769e5383c..d53db20598 100644
--- a/cpp/src/qpid/sys/RdmaIOPlugin.cpp
+++ b/cpp/src/qpid/sys/RdmaIOPlugin.cpp
@@ -31,6 +31,7 @@
#include "qpid/sys/SecuritySettings.h"
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
#include <memory>
#include <netdb.h>
@@ -211,9 +212,10 @@ void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) {
if (readError) {
return;
}
+ size_t decoded = 0;
try {
if (codec) {
- (void) codec->decode(buff->bytes(), buff->dataCount());
+ decoded = codec->decode(buff->bytes(), buff->dataCount());
}else{
// Need to start protocol processing
initProtocolIn(buff);
@@ -228,7 +230,9 @@ void RdmaIOHandler::readbuff(Rdma::AsynchIO&, Rdma::Buffer* buff) {
void RdmaIOHandler::initProtocolIn(Rdma::Buffer* buff) {
framing::Buffer in(buff->bytes(), buff->dataCount());
framing::ProtocolInitiation protocolInit;
+ size_t decoded = 0;
if (protocolInit.decode(in)) {
+ decoded = in.getPosition();
QPID_LOG(debug, "Rdma: RECV [" << identifier << "] INIT(" << protocolInit << ")");
codec = factory->create(protocolInit.getVersion(), *this, identifier, SecuritySettings());
@@ -250,9 +254,10 @@ class RdmaIOProtocolFactory : public ProtocolFactory {
public:
RdmaIOProtocolFactory(int16_t port, int backlog);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const string& host, const std::string& port, ConnectionCodec::Factory*, ConnectFailedCallback);
+ void connect(Poller::shared_ptr, const string& host, int16_t port, ConnectionCodec::Factory*, ConnectFailedCallback);
uint16_t getPort() const;
+ string getHost() const;
private:
bool request(Rdma::Connection::intrusive_ptr, const Rdma::ConnectionParams&, ConnectionCodec::Factory*);
@@ -342,7 +347,18 @@ uint16_t RdmaIOProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+string RdmaIOProtocolFactory::getHost() const {
+ //return listener.getSockname();
+ return "";
+}
+
void RdmaIOProtocolFactory::accept(Poller::shared_ptr poller, ConnectionCodec::Factory* fact) {
+ ::sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(listeningPort);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
listener.reset(
new Rdma::Listener(
Rdma::ConnectionParams(65536, Rdma::DEFAULT_WR_ENTRIES),
@@ -371,7 +387,7 @@ void RdmaIOProtocolFactory::connected(Poller::shared_ptr poller, Rdma::Connectio
void RdmaIOProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* f,
ConnectFailedCallback failed)
{
@@ -383,7 +399,7 @@ void RdmaIOProtocolFactory::connect(
boost::bind(&RdmaIOProtocolFactory::disconnected, this, _1),
boost::bind(&RdmaIOProtocolFactory::rejected, this, _1, _2, failed));
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
c->start(poller, sa);
}
diff --git a/cpp/src/qpid/sys/Socket.h b/cpp/src/qpid/sys/Socket.h
index 25f1c5fb9d..7d50afc59f 100644
--- a/cpp/src/qpid/sys/Socket.h
+++ b/cpp/src/qpid/sys/Socket.h
@@ -33,21 +33,21 @@ namespace sys {
class Duration;
class SocketAddress;
-class QPID_COMMON_CLASS_EXTERN Socket : public IOHandle
+class Socket : public IOHandle
{
public:
/** Create a socket wrapper for descriptor. */
QPID_COMMON_EXTERN Socket();
- /** Create a new Socket which is the same address family as this one */
- QPID_COMMON_EXTERN Socket* createSameTypeSocket() const;
+ /** Set timeout for read and write */
+ void setTimeout(const Duration& interval) const;
/** Set socket non blocking */
void setNonblocking() const;
QPID_COMMON_EXTERN void setTcpNoDelay() const;
- QPID_COMMON_EXTERN void connect(const std::string& host, const std::string& port) const;
+ QPID_COMMON_EXTERN void connect(const std::string& host, uint16_t port) const;
QPID_COMMON_EXTERN void connect(const SocketAddress&) const;
QPID_COMMON_EXTERN void close() const;
@@ -57,9 +57,19 @@ public:
*@param backlog maximum number of pending connections.
*@return The bound port.
*/
- QPID_COMMON_EXTERN int listen(const std::string& host = "", const std::string& port = "0", int backlog = 10) const;
+ QPID_COMMON_EXTERN int listen(uint16_t port = 0, int backlog = 10) const;
QPID_COMMON_EXTERN int listen(const SocketAddress&, int backlog = 10) const;
+ /** Returns the "socket name" ie the address bound to
+ * the near end of the socket
+ */
+ QPID_COMMON_EXTERN std::string getSockname() const;
+
+ /** Returns the "peer name" ie the address bound to
+ * the remote end of the socket
+ */
+ std::string getPeername() const;
+
/**
* Returns an address (host and port) for the remote end of the
* socket
@@ -74,13 +84,16 @@ public:
/**
* Returns the full address of the connection: local and remote host and port.
*/
- QPID_COMMON_INLINE_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); }
+ QPID_COMMON_EXTERN std::string getFullAddress() const { return getLocalAddress()+"-"+getPeerAddress(); }
+
+ QPID_COMMON_EXTERN uint16_t getLocalPort() const;
+ uint16_t getRemotePort() const;
/**
* Returns the error code stored in the socket. This may be used
* to determine the result of a non-blocking connect.
*/
- QPID_COMMON_EXTERN int getError() const;
+ int getError() const;
/** Accept a connection from a socket that is already listening
* and has an incoming connection
@@ -95,11 +108,8 @@ private:
/** Create socket */
void createSocket(const SocketAddress&) const;
- /** Construct socket with existing handle */
Socket(IOHandlePrivate*);
-
- mutable std::string localname;
- mutable std::string peername;
+ mutable std::string connectname;
mutable bool nonblocking;
mutable bool nodelay;
};
diff --git a/cpp/src/qpid/sys/SocketAddress.h b/cpp/src/qpid/sys/SocketAddress.h
index dcca109d94..27b9642f2c 100644
--- a/cpp/src/qpid/sys/SocketAddress.h
+++ b/cpp/src/qpid/sys/SocketAddress.h
@@ -27,7 +27,6 @@
#include <string>
struct addrinfo;
-struct sockaddr;
namespace qpid {
namespace sys {
@@ -42,19 +41,12 @@ public:
QPID_COMMON_EXTERN SocketAddress& operator=(const SocketAddress&);
QPID_COMMON_EXTERN ~SocketAddress();
- QPID_COMMON_EXTERN bool nextAddress();
- QPID_COMMON_EXTERN std::string asString(bool numeric=true) const;
- QPID_COMMON_EXTERN void setAddrInfoPort(uint16_t port);
-
- QPID_COMMON_EXTERN static std::string asString(::sockaddr const * const addr, size_t addrlen);
- QPID_COMMON_EXTERN static uint16_t getPort(::sockaddr const * const addr);
-
+ std::string asString() const;
private:
std::string host;
std::string port;
mutable ::addrinfo* addrInfo;
- mutable ::addrinfo* currentAddrInfo;
};
}}
diff --git a/cpp/src/qpid/sys/SslPlugin.cpp b/cpp/src/qpid/sys/SslPlugin.cpp
index 471a0cef60..b0e791d60b 100644
--- a/cpp/src/qpid/sys/SslPlugin.cpp
+++ b/cpp/src/qpid/sys/SslPlugin.cpp
@@ -66,11 +66,12 @@ class SslProtocolFactory : public ProtocolFactory {
public:
SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(Poller::shared_ptr, const std::string& host, int16_t port,
ConnectionCodec::Factory*,
boost::function2<void, int, std::string> failed);
uint16_t getPort() const;
+ std::string getHost() const;
bool supports(const std::string& capability);
private:
@@ -94,7 +95,7 @@ static struct SslPlugin : public Plugin {
// Only provide to a Broker
if (broker) {
if (options.certDbPath.empty()) {
- QPID_LOG(notice, "SSL plugin not enabled, you must set --ssl-cert-db to enable it.");
+ QPID_LOG(info, "SSL plugin not enabled, you must set --ssl-cert-db to enable it.");
} else {
try {
ssl::initNSS(options, true);
@@ -145,6 +146,10 @@ uint16_t SslProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string SslProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void SslProtocolFactory::accept(Poller::shared_ptr poller,
ConnectionCodec::Factory* fact) {
acceptor.reset(
@@ -155,7 +160,7 @@ void SslProtocolFactory::accept(Poller::shared_ptr poller,
void SslProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
diff --git a/cpp/src/qpid/sys/StateMonitor.h b/cpp/src/qpid/sys/StateMonitor.h
index eac37a8543..5a92756f3a 100644
--- a/cpp/src/qpid/sys/StateMonitor.h
+++ b/cpp/src/qpid/sys/StateMonitor.h
@@ -41,9 +41,9 @@ class StateMonitor : public Waitable
struct Set : public std::bitset<MaxEnum + 1> {
Set() {}
Set(Enum s) { set(s); }
- Set(Enum s, Enum t) { std::bitset<MaxEnum + 1>::set(s).set(t); }
- Set(Enum s, Enum t, Enum u) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u); }
- Set(Enum s, Enum t, Enum u, Enum v) { std::bitset<MaxEnum + 1>::set(s).set(t).set(u).set(v); }
+ Set(Enum s, Enum t) { set(s).set(t); }
+ Set(Enum s, Enum t, Enum u) { set(s).set(t).set(u); }
+ Set(Enum s, Enum t, Enum u, Enum v) { set(s).set(t).set(u).set(v); }
};
@@ -60,13 +60,13 @@ class StateMonitor : public Waitable
operator Enum() const { return state; }
/** @pre Caller holds a ScopedLock */
- void waitFor(Enum s) { ScopedWait w(*this); while (s != state) wait(); }
+ void waitFor(Enum s) { ScopedWait(*this); while (s != state) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitFor(Set s) { ScopedWait w(*this); while (!s.test(state)) wait(); }
+ void waitFor(Set s) { ScopedWait(*this); while (!s.test(state)) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitNot(Enum s) { ScopedWait w(*this); while (s == state) wait(); }
+ void waitNot(Enum s) { ScopedWait(*this); while (s == state) wait(); }
/** @pre Caller holds a ScopedLock */
- void waitNot(Set s) { ScopedWait w(*this); while (s.test(state)) wait(); }
+ void waitNot(Set s) { ScopedWait(*this); while (s.test(state)) wait(); }
private:
Enum state;
diff --git a/cpp/src/qpid/sys/TCPIOPlugin.cpp b/cpp/src/qpid/sys/TCPIOPlugin.cpp
index 85d8c1db87..a6528f9ad9 100644
--- a/cpp/src/qpid/sys/TCPIOPlugin.cpp
+++ b/cpp/src/qpid/sys/TCPIOPlugin.cpp
@@ -25,31 +25,31 @@
#include "qpid/Plugin.h"
#include "qpid/sys/Socket.h"
-#include "qpid/sys/SocketAddress.h"
#include "qpid/sys/Poller.h"
#include "qpid/broker/Broker.h"
#include "qpid/log/Statement.h"
#include <boost/bind.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
+#include <memory>
namespace qpid {
namespace sys {
class AsynchIOProtocolFactory : public ProtocolFactory {
const bool tcpNoDelay;
- boost::ptr_vector<Socket> listeners;
- boost::ptr_vector<AsynchAcceptor> acceptors;
- uint16_t listeningPort;
+ Socket listener;
+ const uint16_t listeningPort;
+ std::auto_ptr<AsynchAcceptor> acceptor;
public:
- AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay);
+ AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay);
void accept(Poller::shared_ptr, ConnectionCodec::Factory*);
- void connect(Poller::shared_ptr, const std::string& host, const std::string& port,
+ void connect(Poller::shared_ptr, const std::string& host, int16_t port,
ConnectionCodec::Factory*,
ConnectFailedCallback);
uint16_t getPort() const;
+ std::string getHost() const;
private:
void established(Poller::shared_ptr, const Socket&, ConnectionCodec::Factory*,
@@ -61,49 +61,23 @@ class AsynchIOProtocolFactory : public ProtocolFactory {
static class TCPIOPlugin : public Plugin {
void earlyInitialize(Target&) {
}
-
+
void initialize(Target& target) {
broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
// Only provide to a Broker
if (broker) {
const broker::Broker::Options& opts = broker->getOptions();
- ProtocolFactory::shared_ptr protocolt(
- new AsynchIOProtocolFactory(
- "", boost::lexical_cast<std::string>(opts.port),
- opts.connectionBacklog,
- opts.tcpNoDelay));
- QPID_LOG(notice, "Listening on TCP/TCP6 port " << protocolt->getPort());
- broker->registerProtocolFactory("tcp", protocolt);
+ ProtocolFactory::shared_ptr protocol(new AsynchIOProtocolFactory(opts.port, opts.connectionBacklog,
+ opts.tcpNoDelay));
+ QPID_LOG(notice, "Listening on TCP port " << protocol->getPort());
+ broker->registerProtocolFactory("tcp", protocol);
}
}
} tcpPlugin;
-AsynchIOProtocolFactory::AsynchIOProtocolFactory(const std::string& host, const std::string& port, int backlog, bool nodelay) :
- tcpNoDelay(nodelay)
-{
- SocketAddress sa(host, port);
-
- // We must have at least one resolved address
- QPID_LOG(info, "Listening to: " << sa.asString())
- Socket* s = new Socket;
- uint16_t lport = s->listen(sa, backlog);
- QPID_LOG(debug, "Listened to: " << lport);
- listeners.push_back(s);
-
- listeningPort = lport;
-
- // Try any other resolved addresses
- while (sa.nextAddress()) {
- // Hack to ensure that all listening connections are on the same port
- sa.setAddrInfoPort(listeningPort);
- QPID_LOG(info, "Listening to: " << sa.asString())
- Socket* s = new Socket;
- uint16_t lport = s->listen(sa, backlog);
- QPID_LOG(debug, "Listened to: " << lport);
- listeners.push_back(s);
- }
-
-}
+AsynchIOProtocolFactory::AsynchIOProtocolFactory(int16_t port, int backlog, bool nodelay) :
+ tcpNoDelay(nodelay), listeningPort(listener.listen(port, backlog))
+{}
void AsynchIOProtocolFactory::established(Poller::shared_ptr poller, const Socket& s,
ConnectionCodec::Factory* f, bool isClient) {
@@ -133,14 +107,16 @@ uint16_t AsynchIOProtocolFactory::getPort() const {
return listeningPort; // Immutable no need for lock.
}
+std::string AsynchIOProtocolFactory::getHost() const {
+ return listener.getSockname();
+}
+
void AsynchIOProtocolFactory::accept(Poller::shared_ptr poller,
ConnectionCodec::Factory* fact) {
- for (unsigned i = 0; i<listeners.size(); ++i) {
- acceptors.push_back(
- AsynchAcceptor::create(listeners[i],
- boost::bind(&AsynchIOProtocolFactory::established, this, poller, _1, fact, false)));
- acceptors[i].start(poller);
- }
+ acceptor.reset(
+ AsynchAcceptor::create(listener,
+ boost::bind(&AsynchIOProtocolFactory::established, this, poller, _1, fact, false)));
+ acceptor->start(poller);
}
void AsynchIOProtocolFactory::connectFailed(
@@ -154,7 +130,7 @@ void AsynchIOProtocolFactory::connectFailed(
void AsynchIOProtocolFactory::connect(
Poller::shared_ptr poller,
- const std::string& host, const std::string& port,
+ const std::string& host, int16_t port,
ConnectionCodec::Factory* fact,
ConnectFailedCallback failed)
{
@@ -163,8 +139,8 @@ void AsynchIOProtocolFactory::connect(
// upon connection failure or by the AsynchIO upon connection
// shutdown. The allocated AsynchConnector frees itself when it
// is no longer needed.
+
Socket* socket = new Socket();
- try {
AsynchConnector* c = AsynchConnector::create(
*socket,
host,
@@ -174,12 +150,6 @@ void AsynchIOProtocolFactory::connect(
boost::bind(&AsynchIOProtocolFactory::connectFailed,
this, _1, _2, _3, failed));
c->start(poller);
- } catch (std::exception&) {
- // TODO: Design question - should we do the error callback and also throw?
- int errCode = socket->getError();
- connectFailed(*socket, errCode, strError(errCode), failed);
- throw;
- }
}
}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/Timer.cpp b/cpp/src/qpid/sys/Timer.cpp
index 47752e4584..a97ccd1bd1 100644
--- a/cpp/src/qpid/sys/Timer.cpp
+++ b/cpp/src/qpid/sys/Timer.cpp
@@ -75,12 +75,6 @@ void TimerTask::cancel() {
cancelled = true;
}
-void TimerTask::setFired() {
- // Set nextFireTime to just before now, making readyToFire() true.
- nextFireTime = AbsTime(sys::now(), Duration(-1));
-}
-
-
Timer::Timer() :
active(false),
late(50 * TIME_MSEC),
@@ -137,14 +131,12 @@ void Timer::run()
bool warningsEnabled;
QPID_LOG_TEST(warning, warningsEnabled);
if (warningsEnabled) {
- if (overrun > overran) {
- if (delay > overran) // if delay is significant to an overrun.
- warn.lateAndOverran(t->name, delay, overrun, Duration(start, end));
- else
- warn.overran(t->name, overrun, Duration(start, end));
- }
+ if (delay > late && overrun > overran)
+ warn.lateAndOverran(t->name, delay, overrun, Duration(start, end));
else if (delay > late)
warn.late(t->name, delay);
+ else if (overrun > overran)
+ warn.overran(t->name, overrun, Duration(start, end));
}
continue;
} else {
@@ -191,11 +183,7 @@ void Timer::stop()
// Allow subclasses to override behavior when firing a task.
void Timer::fire(boost::intrusive_ptr<TimerTask> t) {
- try {
- t->fireTask();
- } catch (const std::exception& e) {
- QPID_LOG(error, "Exception thrown by timer task " << t->getName() << ": " << e.what());
- }
+ t->fireTask();
}
// Provided for subclasses: called when a task is droped.
diff --git a/cpp/src/qpid/sys/Timer.h b/cpp/src/qpid/sys/Timer.h
index fccb17dbc2..98ba39ce38 100644
--- a/cpp/src/qpid/sys/Timer.h
+++ b/cpp/src/qpid/sys/Timer.h
@@ -7,9 +7,9 @@
* 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
@@ -64,10 +64,6 @@ class TimerTask : public RefCounted {
std::string getName() const { return name; }
- // Move the nextFireTime so readyToFire is true.
- // Used by the cluster, where tasks are fired on cluster events, not on local time.
- QPID_COMMON_EXTERN void setFired();
-
protected:
// Must be overridden with callback
virtual void fire() = 0;
diff --git a/cpp/src/qpid/sys/TimerWarnings.cpp b/cpp/src/qpid/sys/TimerWarnings.cpp
index 85e26da54a..48a56eb472 100644
--- a/cpp/src/qpid/sys/TimerWarnings.cpp
+++ b/cpp/src/qpid/sys/TimerWarnings.cpp
@@ -56,22 +56,20 @@ void TimerWarnings::log() {
std::string task = i->first;
TaskStats& stats = i->second;
if (stats.lateDelay.count)
- QPID_LOG(info, task << " task late "
+ QPID_LOG(warning, task << " task late "
<< stats.lateDelay.count << " times by "
<< stats.lateDelay.average()/TIME_MSEC << "ms on average.");
-
if (stats.overranOverrun.count)
- QPID_LOG(info, task << " task overran "
+ QPID_LOG(warning, task << " task overran "
<< stats.overranOverrun.count << " times by "
<< stats.overranOverrun.average()/TIME_MSEC << "ms (taking "
<< stats.overranTime.average() << "ns) on average.");
- if (stats.lateAndOverranOverrun.count)
- QPID_LOG(info, task << " task late and overran "
- << stats.lateAndOverranOverrun.count << " times: late "
- << stats.lateAndOverranDelay.average()/TIME_MSEC << "ms, overran "
- << stats.lateAndOverranOverrun.average()/TIME_MSEC << "ms (taking "
- << stats.lateAndOverranTime.average() << "ns) on average.");
+ if (stats.lateAndOverranDelay.count)
+ QPID_LOG(warning, task << " task overran "
+ << stats.overranOverrun.count << " times by "
+ << stats.overranOverrun.average()/TIME_MSEC << "ms (taking "
+ << stats.overranTime.average() << "ns) on average.");
}
nextReport = AbsTime(now(), interval);
diff --git a/cpp/src/qpid/sys/alloca.h b/cpp/src/qpid/sys/alloca.h
index b3f59b7c3f..e989670e4f 100644
--- a/cpp/src/qpid/sys/alloca.h
+++ b/cpp/src/qpid/sys/alloca.h
@@ -21,22 +21,19 @@
*
*/
-#if (defined(_WINDOWS) || defined (WIN32))
-# include <malloc.h>
-
-# if defined(_MSC_VER)
-# ifdef alloc
-# undef alloc
-# endif
-# define alloc _alloc
-# ifdef alloca
-# undef alloca
-# endif
-# define alloca _alloca
-# endif
+#if (defined(_WINDOWS) || defined (WIN32)) && defined(_MSC_VER)
+#include <malloc.h>
+#ifdef alloc
+# undef alloc
+#endif
+#define alloc _alloc
+#ifdef alloca
+# undef alloca
+#endif
+#define alloca _alloca
#endif
#if !defined _WINDOWS && !defined WIN32
-# include <alloca.h>
+#include <alloca.h>
#endif
#endif /*!QPID_SYS_ALLOCA_H*/
diff --git a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
index 249b769051..454ce62495 100644
--- a/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
+++ b/cpp/src/qpid/sys/cyrus/CyrusSecurityLayer.cpp
@@ -57,7 +57,6 @@ size_t CyrusSecurityLayer::decode(const char* input, size_t size)
copied += count;
decodeBuffer.position += count;
size_t decodedSize = codec->decode(decodeBuffer.data, decodeBuffer.position);
- if (decodedSize == 0) break;
if (decodedSize < decodeBuffer.position) {
::memmove(decodeBuffer.data, decodeBuffer.data + decodedSize, decodeBuffer.position - decodedSize);
}
@@ -107,7 +106,7 @@ size_t CyrusSecurityLayer::encode(const char* buffer, size_t size)
bool CyrusSecurityLayer::canEncode()
{
- return codec && (encrypted || codec->canEncode());
+ return encrypted || codec->canEncode();
}
void CyrusSecurityLayer::init(qpid::sys::Codec* c)
diff --git a/cpp/src/qpid/sys/epoll/EpollPoller.cpp b/cpp/src/qpid/sys/epoll/EpollPoller.cpp
index dcc9d9181c..9ad05c71a3 100644
--- a/cpp/src/qpid/sys/epoll/EpollPoller.cpp
+++ b/cpp/src/qpid/sys/epoll/EpollPoller.cpp
@@ -384,12 +384,7 @@ void PollerPrivate::resetMode(PollerHandlePrivate& eh) {
epe.data.u64 = 0; // Keep valgrind happy
epe.data.ptr = &eh;
- int rc = ::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe);
- // If something has closed the fd in the meantime try adding it back
- if (rc ==-1 && errno == ENOENT) {
- rc = ::epoll_ctl(epollFd, EPOLL_CTL_ADD, eh.fd(), &epe);
- }
- QPID_POSIX_CHECK(rc);
+ QPID_POSIX_CHECK(::epoll_ctl(epollFd, EPOLL_CTL_MOD, eh.fd(), &epe));
eh.setActive();
return;
diff --git a/cpp/src/qpid/sys/posix/AsynchIO.cpp b/cpp/src/qpid/sys/posix/AsynchIO.cpp
index dab8bd09c6..119a6aa8a4 100644
--- a/cpp/src/qpid/sys/posix/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/posix/AsynchIO.cpp
@@ -149,12 +149,11 @@ private:
ConnectedCallback connCallback;
FailedCallback failCallback;
const Socket& socket;
- SocketAddress sa;
public:
AsynchConnector(const Socket& socket,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb);
void start(Poller::shared_ptr poller);
@@ -162,8 +161,8 @@ public:
};
AsynchConnector::AsynchConnector(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb) :
DispatchHandle(s,
@@ -172,13 +171,11 @@ AsynchConnector::AsynchConnector(const Socket& s,
boost::bind(&AsynchConnector::connComplete, this, _1)),
connCallback(connCb),
failCallback(failCb),
- socket(s),
- sa(hostname, port)
+ socket(s)
{
socket.setNonblocking();
-
+ SocketAddress sa(hostname, boost::lexical_cast<std::string>(port));
// Note, not catching any exceptions here, also has effect of destructing
- QPID_LOG(info, "Connecting: " << sa.asString());
socket.connect(sa);
}
@@ -194,26 +191,11 @@ void AsynchConnector::stop()
void AsynchConnector::connComplete(DispatchHandle& h)
{
+ h.stopWatch();
int errCode = socket.getError();
if (errCode == 0) {
- h.stopWatch();
connCallback(socket);
} else {
- // Retry while we cause an immediate exception
- // (asynch failure will be handled by re-entering here at the top)
- while (sa.nextAddress()) {
- try {
- // Try next address without deleting ourselves
- QPID_LOG(debug, "Ignored socket connect error: " << strError(errCode));
- QPID_LOG(info, "Retrying connect: " << sa.asString());
- socket.connect(sa);
- return;
- } catch (const std::exception& e) {
- QPID_LOG(debug, "Ignored socket connect exception: " << e.what());
- }
- errCode = socket.getError();
- }
- h.stopWatch();
failCallback(socket, errCode, strError(errCode));
}
DispatchHandle::doDelete();
@@ -607,8 +589,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s,
}
AsynchConnector* AsynchConnector::create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb)
{
diff --git a/cpp/src/qpid/sys/posix/LockFile.cpp b/cpp/src/qpid/sys/posix/LockFile.cpp
index f5a6c292cb..1862ff6ac9 100755
--- a/cpp/src/qpid/sys/posix/LockFile.cpp
+++ b/cpp/src/qpid/sys/posix/LockFile.cpp
@@ -58,7 +58,8 @@ LockFile::~LockFile() {
if (impl) {
int f = impl->fd;
if (f >= 0) {
- (void) ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value.
+ int unused_ret;
+ unused_ret = ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value.
::close(f);
impl->fd = -1;
}
diff --git a/cpp/src/qpid/sys/posix/Socket.cpp b/cpp/src/qpid/sys/posix/Socket.cpp
index 4a6dc66f80..7b906f33e8 100644
--- a/cpp/src/qpid/sys/posix/Socket.cpp
+++ b/cpp/src/qpid/sys/posix/Socket.cpp
@@ -7,9 +7,9 @@
* 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
@@ -34,35 +34,65 @@
#include <netdb.h>
#include <cstdlib>
#include <string.h>
+#include <iostream>
+
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
namespace qpid {
namespace sys {
namespace {
-std::string getName(int fd, bool local)
+std::string getName(int fd, bool local, bool includeService = false)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
+ ::sockaddr_storage name; // big enough for any socket address
+ ::socklen_t namelen = sizeof(name);
+
+ int result = -1;
if (local) {
- QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) );
+ result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
} else {
- QPID_POSIX_CHECK( ::getpeername(fd, name, &namelen) );
+ result = ::getpeername(fd, (::sockaddr*)&name, &namelen);
}
- return SocketAddress::asString(name, namelen);
+ QPID_POSIX_CHECK(result);
+
+ char servName[NI_MAXSERV];
+ char dispName[NI_MAXHOST];
+ if (includeService) {
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName),
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return std::string(dispName) + ":" + std::string(servName);
+
+ } else {
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, dispName, sizeof(dispName), 0, 0, NI_NUMERICHOST) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return dispName;
+ }
}
-uint16_t getLocalPort(int fd)
+std::string getService(int fd, bool local)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
+ ::sockaddr_storage name; // big enough for any socket address
+ ::socklen_t namelen = sizeof(name);
+
+ int result = -1;
+ if (local) {
+ result = ::getsockname(fd, (::sockaddr*)&name, &namelen);
+ } else {
+ result = ::getpeername(fd, (::sockaddr*)&name, &namelen);
+ }
- QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) );
+ QPID_POSIX_CHECK(result);
- return SocketAddress::getPort(name);
+ char servName[NI_MAXSERV];
+ if (int rc=::getnameinfo((::sockaddr*)&name, namelen, 0, 0,
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw QPID_POSIX_ERROR(rc);
+ return servName;
}
}
@@ -89,11 +119,6 @@ void Socket::createSocket(const SocketAddress& sa) const
try {
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
- if (getAddrInfo(sa).ai_family == AF_INET6) {
- int flag = 1;
- int result = ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&flag, sizeof(flag));
- QPID_POSIX_CHECK(result);
- }
} catch (std::exception&) {
::close(s);
socket = -1;
@@ -101,18 +126,13 @@ void Socket::createSocket(const SocketAddress& sa) const
}
}
-Socket* Socket::createSameTypeSocket() const {
- int& socket = impl->fd;
- // Socket currently has no actual socket attached
- if (socket == -1)
- return new Socket;
-
- ::sockaddr_storage sa;
- ::socklen_t salen = sizeof(sa);
- QPID_POSIX_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
- int s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
- if (s < 0) throw QPID_POSIX_ERROR(errno);
- return new Socket(new IOHandlePrivate(s));
+void Socket::setTimeout(const Duration& interval) const
+{
+ const int& socket = impl->fd;
+ struct timeval tv;
+ toTimeval(tv, interval);
+ setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
}
void Socket::setNonblocking() const {
@@ -129,27 +149,20 @@ void Socket::setTcpNoDelay() const
nodelay = true;
if (socket != -1) {
int flag = 1;
- int result = ::setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
+ int result = setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
QPID_POSIX_CHECK(result);
}
}
-void Socket::connect(const std::string& host, const std::string& port) const
+void Socket::connect(const std::string& host, uint16_t port) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
connect(sa);
}
void Socket::connect(const SocketAddress& addr) const
{
- // The display name for an outbound connection needs to be the name that was specified
- // for the address rather than a resolved IP address as we don't know which of
- // the IP addresses is actually the one that will be connected to.
- peername = addr.asString(false);
-
- // However the string we compare with the local port must be numeric or it might not
- // match when it should as getLocalAddress() will always be numeric
- std::string connectname = addr.asString();
+ connectname = addr.asString();
createSocket(addr);
@@ -157,24 +170,7 @@ void Socket::connect(const SocketAddress& addr) const
// TODO the correct thing to do here is loop on failure until you've used all the returned addresses
if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) &&
(errno != EINPROGRESS)) {
- throw Exception(QPID_MSG(strError(errno) << ": " << peername));
- }
- // When connecting to a port on the same host which no longer has
- // a process associated with it, the OS occasionally chooses the
- // remote port (which is unoccupied) as the port to bind the local
- // end of the socket, resulting in a "circular" connection.
- //
- // This seems like something the OS should prevent but I have
- // confirmed that sporadic hangs in
- // cluster_tests.LongTests.test_failover on RHEL5 are caused by
- // such a circular connection.
- //
- // Raise an error if we see such a connection, since we know there is
- // no listener on the peer address.
- //
- if (getLocalAddress() == connectname) {
- close();
- throw Exception(QPID_MSG("Connection refused: " << peername));
+ throw Exception(QPID_MSG(strError(errno) << ": " << connectname));
}
}
@@ -187,9 +183,9 @@ Socket::close() const
socket = -1;
}
-int Socket::listen(const std::string& host, const std::string& port, int backlog) const
+int Socket::listen(uint16_t port, int backlog) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa("", boost::lexical_cast<std::string>(port));
return listen(sa, backlog);
}
@@ -199,24 +195,26 @@ int Socket::listen(const SocketAddress& sa, int backlog) const
const int& socket = impl->fd;
int yes=1;
- QPID_POSIX_CHECK(::setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
+ QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0)
throw Exception(QPID_MSG("Can't bind to port " << sa.asString() << ": " << strError(errno)));
if (::listen(socket, backlog) < 0)
throw Exception(QPID_MSG("Can't listen on port " << sa.asString() << ": " << strError(errno)));
- return getLocalPort(socket);
+ struct sockaddr_in name;
+ socklen_t namelen = sizeof(name);
+ if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
+ throw QPID_POSIX_ERROR(errno);
+
+ return ntohs(name.sin_port);
}
Socket* Socket::accept() const
{
int afd = ::accept(impl->fd, 0, 0);
- if ( afd >= 0) {
- Socket* s = new Socket(new IOHandlePrivate(afd));
- s->localname = localname;
- return s;
- }
+ if ( afd >= 0)
+ return new Socket(new IOHandlePrivate(afd));
else if (errno == EAGAIN)
return 0;
else throw QPID_POSIX_ERROR(errno);
@@ -232,20 +230,37 @@ int Socket::write(const void *buf, size_t count) const
return ::write(impl->fd, buf, count);
}
+std::string Socket::getSockname() const
+{
+ return getName(impl->fd, true);
+}
+
+std::string Socket::getPeername() const
+{
+ return getName(impl->fd, false);
+}
+
std::string Socket::getPeerAddress() const
{
- if (peername.empty()) {
- peername = getName(impl->fd, false);
+ if (connectname.empty()) {
+ connectname = getName(impl->fd, false, true);
}
- return peername;
+ return connectname;
}
std::string Socket::getLocalAddress() const
{
- if (localname.empty()) {
- localname = getName(impl->fd, true);
- }
- return localname;
+ return getName(impl->fd, true, true);
+}
+
+uint16_t Socket::getLocalPort() const
+{
+ return std::atoi(getService(impl->fd, true).c_str());
+}
+
+uint16_t Socket::getRemotePort() const
+{
+ return std::atoi(getService(impl->fd, true).c_str());
}
int Socket::getError() const
diff --git a/cpp/src/qpid/sys/posix/SocketAddress.cpp b/cpp/src/qpid/sys/posix/SocketAddress.cpp
index 077942ef2f..8f5f29d793 100644
--- a/cpp/src/qpid/sys/posix/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/posix/SocketAddress.cpp
@@ -21,13 +21,11 @@
#include "qpid/sys/SocketAddress.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
+#include "qpid/sys/posix/check.h"
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
#include <string.h>
+#include <netdb.h>
namespace qpid {
namespace sys {
@@ -48,9 +46,15 @@ SocketAddress::SocketAddress(const SocketAddress& sa) :
SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
{
- SocketAddress temp(sa);
+ if (&sa != this) {
+ host = sa.host;
+ port = sa.port;
- std::swap(temp, *this);
+ if (addrInfo) {
+ ::freeaddrinfo(addrInfo);
+ addrInfo = 0;
+ }
+ }
return *this;
}
@@ -61,61 +65,9 @@ SocketAddress::~SocketAddress()
}
}
-std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen)
-{
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (int rc=::getnameinfo(addr, addrlen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- std::string s;
- switch (addr->sa_family) {
- case AF_INET: s += dispName; break;
- case AF_INET6: s += "["; s += dispName; s+= "]"; break;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
- s += ":";
- s += servName;
- return s;
-}
-
-uint16_t SocketAddress::getPort(::sockaddr const * const addr)
+std::string SocketAddress::asString() const
{
- switch (addr->sa_family) {
- case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port);
- case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port);
- default:throw Exception(QPID_MSG("Unexpected socket type"));
- }
-}
-
-std::string SocketAddress::asString(bool numeric) const
-{
- if (!numeric)
- return host + ":" + port;
- // Canonicalise into numeric id
- const ::addrinfo& ai = getAddrInfo(*this);
-
- return asString(ai.ai_addr, ai.ai_addrlen);
-}
-
-bool SocketAddress::nextAddress() {
- bool r = currentAddrInfo->ai_next != 0;
- if (r)
- currentAddrInfo = currentAddrInfo->ai_next;
- return r;
-}
-
-void SocketAddress::setAddrInfoPort(uint16_t port) {
- if (!currentAddrInfo) return;
-
- ::addrinfo& ai = *currentAddrInfo;
- switch (ai.ai_family) {
- case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return;
- case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ return host + ":" + port;
}
const ::addrinfo& getAddrInfo(const SocketAddress& sa)
@@ -123,8 +75,7 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa)
if (!sa.addrInfo) {
::addrinfo hints;
::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
- hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
+ hints.ai_family = AF_INET; // Change this to support IPv6
hints.ai_socktype = SOCK_STREAM;
const char* node = 0;
@@ -137,11 +88,10 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa)
int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
- sa.currentAddrInfo = sa.addrInfo;
+ throw Exception(QPID_MSG("Cannot resolve " << sa.host << ": " << ::gai_strerror(n)));
}
- return *sa.currentAddrInfo;
+ return *sa.addrInfo;
}
}}
diff --git a/cpp/src/qpid/sys/posix/Thread.cpp b/cpp/src/qpid/sys/posix/Thread.cpp
index a1d6396763..b466733260 100644
--- a/cpp/src/qpid/sys/posix/Thread.cpp
+++ b/cpp/src/qpid/sys/posix/Thread.cpp
@@ -37,8 +37,7 @@ void* runRunnable(void* p)
}
}
-class ThreadPrivate {
-public:
+struct ThreadPrivate {
pthread_t thread;
ThreadPrivate(Runnable* runnable) {
diff --git a/cpp/src/qpid/sys/posix/Time.cpp b/cpp/src/qpid/sys/posix/Time.cpp
index 9661f0c5e8..b3858279b4 100644
--- a/cpp/src/qpid/sys/posix/Time.cpp
+++ b/cpp/src/qpid/sys/posix/Time.cpp
@@ -27,7 +27,6 @@
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
-#include <iomanip>
namespace {
int64_t max_abstime() { return std::numeric_limits<int64_t>::max(); }
@@ -104,12 +103,6 @@ void outputFormattedNow(std::ostream& o) {
o << " ";
}
-void outputHiresNow(std::ostream& o) {
- ::timespec time;
- ::clock_gettime(CLOCK_REALTIME, &time);
- o << time.tv_sec << "." << std::setw(9) << std::setfill('0') << time.tv_nsec << "s ";
-}
-
void sleep(int secs) {
::sleep(secs);
}
diff --git a/cpp/src/qpid/sys/rdma/RdmaIO.cpp b/cpp/src/qpid/sys/rdma/RdmaIO.cpp
index 78bcdec68e..c80c94cba6 100644
--- a/cpp/src/qpid/sys/rdma/RdmaIO.cpp
+++ b/cpp/src/qpid/sys/rdma/RdmaIO.cpp
@@ -140,8 +140,8 @@ namespace Rdma {
// Prepost recv buffers before we go any further
qp->allocateRecvBuffers(recvBufferCount, bufferSize+FrameHeaderSize);
- // Create xmit buffers, reserve space for frame header.
- qp->createSendBuffers(xmitBufferCount, bufferSize, FrameHeaderSize);
+ // Create xmit buffers
+ qp->createSendBuffers(xmitBufferCount, bufferSize+FrameHeaderSize);
}
AsynchIO::~AsynchIO() {
@@ -210,14 +210,12 @@ namespace Rdma {
}
break;
case 1:
- if (!buff)
- buff = getSendBuffer();
+ Buffer* ob = buff ? buff : getSendBuffer();
// Add FrameHeader after frame data
FrameHeader header(credit);
- assert(buff->dataCount() <= buff->byteCount()); // ensure app data doesn't impinge on reserved space.
- ::memcpy(buff->bytes()+buff->dataCount(), &header, FrameHeaderSize);
- buff->dataCount(buff->dataCount()+FrameHeaderSize);
- qp->postSend(buff);
+ ::memcpy(ob->bytes()+ob->dataCount(), &header, FrameHeaderSize);
+ ob->dataCount(ob->dataCount()+FrameHeaderSize);
+ qp->postSend(ob);
break;
}
}
diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp b/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
index efe454c5be..6d38c42502 100644
--- a/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
+++ b/cpp/src/qpid/sys/rdma/rdma_wrap.cpp
@@ -50,9 +50,8 @@ namespace Rdma {
return count;
}
- Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount,
- const int32_t reserve) :
- bufferSize(byteCount + reserve), reserved(reserve)
+ Buffer::Buffer(uint32_t lkey, char* bytes, const int32_t byteCount) :
+ bufferSize(byteCount)
{
sge.addr = (uintptr_t) bytes;
sge.length = 0;
@@ -164,21 +163,21 @@ namespace Rdma {
}
// Create buffers to use for writing
- void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize, int reserved)
+ void QueuePair::createSendBuffers(int sendBufferCount, int bufferSize)
{
assert(!smr);
// Round up buffersize to cacheline (64 bytes)
- int dataLength = (bufferSize+reserved+63) & (~63);
+ bufferSize = (bufferSize+63) & (~63);
// Allocate memory block for all receive buffers
- char* mem = new char [sendBufferCount * dataLength];
- smr = regMr(pd.get(), mem, sendBufferCount * dataLength, ::IBV_ACCESS_LOCAL_WRITE);
+ char* mem = new char [sendBufferCount * bufferSize];
+ smr = regMr(pd.get(), mem, sendBufferCount * bufferSize, ::IBV_ACCESS_LOCAL_WRITE);
sendBuffers.reserve(sendBufferCount);
freeBuffers.reserve(sendBufferCount);
for (int i = 0; i<sendBufferCount; ++i) {
// Allocate xmit buffer
- sendBuffers.push_back(Buffer(smr->lkey, &mem[i*dataLength], bufferSize, reserved));
+ sendBuffers.push_back(Buffer(smr->lkey, &mem[i*bufferSize], bufferSize));
freeBuffers.push_back(i);
}
}
diff --git a/cpp/src/qpid/sys/rdma/rdma_wrap.h b/cpp/src/qpid/sys/rdma/rdma_wrap.h
index 8e3429027b..28bddd2165 100644
--- a/cpp/src/qpid/sys/rdma/rdma_wrap.h
+++ b/cpp/src/qpid/sys/rdma/rdma_wrap.h
@@ -57,9 +57,8 @@ namespace Rdma {
void dataCount(int32_t);
private:
- Buffer(uint32_t lkey, char* bytes, const int32_t byteCount, const int32_t reserve=0);
+ Buffer(uint32_t lkey, char* bytes, const int32_t byteCount);
int32_t bufferSize;
- int32_t reserved; // for framing header
::ibv_sge sge;
};
@@ -67,9 +66,8 @@ namespace Rdma {
return (char*) sge.addr;
}
- /** return the number of bytes available for application data */
inline int32_t Buffer::byteCount() const {
- return bufferSize - reserved;
+ return bufferSize;
}
inline int32_t Buffer::dataCount() const {
@@ -77,8 +75,6 @@ namespace Rdma {
}
inline void Buffer::dataCount(int32_t s) {
- // catch any attempt to overflow a buffer
- assert(s <= bufferSize + reserved);
sge.length = s;
}
@@ -140,7 +136,7 @@ namespace Rdma {
typedef boost::intrusive_ptr<QueuePair> intrusive_ptr;
// Create a buffers to use for writing
- void createSendBuffers(int sendBufferCount, int dataSize, int headerSize);
+ void createSendBuffers(int sendBufferCount, int bufferSize);
// Get a send buffer
Buffer* getSendBuffer();
diff --git a/cpp/src/qpid/sys/ssl/SslHandler.h b/cpp/src/qpid/sys/ssl/SslHandler.h
index 400fa317fd..a340109966 100644
--- a/cpp/src/qpid/sys/ssl/SslHandler.h
+++ b/cpp/src/qpid/sys/ssl/SslHandler.h
@@ -35,7 +35,7 @@ namespace sys {
namespace ssl {
class SslIO;
-struct SslIOBufferBase;
+class SslIOBufferBase;
class SslSocket;
class SslHandler : public OutputControl {
diff --git a/cpp/src/qpid/sys/ssl/SslIo.cpp b/cpp/src/qpid/sys/ssl/SslIo.cpp
index 734ebb483a..a58a137473 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.cpp
+++ b/cpp/src/qpid/sys/ssl/SslIo.cpp
@@ -117,7 +117,7 @@ void SslAcceptor::readable(DispatchHandle& h) {
SslConnector::SslConnector(const SslSocket& s,
Poller::shared_ptr poller,
std::string hostname,
- std::string port,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb) :
DispatchHandle(s,
diff --git a/cpp/src/qpid/sys/ssl/SslIo.h b/cpp/src/qpid/sys/ssl/SslIo.h
index 8785852c24..53ac69d8d6 100644
--- a/cpp/src/qpid/sys/ssl/SslIo.h
+++ b/cpp/src/qpid/sys/ssl/SslIo.h
@@ -73,7 +73,7 @@ public:
SslConnector(const SslSocket& socket,
Poller::shared_ptr poller,
std::string hostname,
- std::string port,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb = 0);
diff --git a/cpp/src/qpid/sys/ssl/SslSocket.cpp b/cpp/src/qpid/sys/ssl/SslSocket.cpp
index f7483a220c..01e2658877 100644
--- a/cpp/src/qpid/sys/ssl/SslSocket.cpp
+++ b/cpp/src/qpid/sys/ssl/SslSocket.cpp
@@ -158,7 +158,7 @@ void SslSocket::setNonblocking() const
PR_SetSocketOption(socket, &option);
}
-void SslSocket::connect(const std::string& host, const std::string& port) const
+void SslSocket::connect(const std::string& host, uint16_t port) const
{
std::stringstream namestream;
namestream << host << ":" << port;
@@ -180,7 +180,7 @@ void SslSocket::connect(const std::string& host, const std::string& port) const
PRHostEnt hostEntry;
PR_CHECK(PR_GetHostByName(host.data(), hostBuffer, PR_NETDB_BUF_SIZE, &hostEntry));
PRNetAddr address;
- int value = PR_EnumerateHostEnt(0, &hostEntry, boost::lexical_cast<PRUint16>(port), &address);
+ int value = PR_EnumerateHostEnt(0, &hostEntry, port, &address);
if (value < 0) {
throw Exception(QPID_MSG("Error getting address for host: " << ErrorString()));
} else if (value == 0) {
diff --git a/cpp/src/qpid/sys/ssl/SslSocket.h b/cpp/src/qpid/sys/ssl/SslSocket.h
index 993859495b..25712c98d5 100644
--- a/cpp/src/qpid/sys/ssl/SslSocket.h
+++ b/cpp/src/qpid/sys/ssl/SslSocket.h
@@ -53,7 +53,7 @@ public:
* NSSInit().*/
void setCertName(const std::string& certName);
- void connect(const std::string& host, const std::string& port) const;
+ void connect(const std::string& host, uint16_t port) const;
void close() const;
diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp
index 30378d4c5f..38d8842521 100644
--- a/cpp/src/qpid/sys/windows/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/windows/AsynchIO.cpp
@@ -30,7 +30,6 @@
#include "qpid/log/Statement.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/windows/mingw32_compat.h"
#include <boost/thread/once.hpp>
@@ -47,13 +46,16 @@ namespace {
/*
* The function pointers for AcceptEx and ConnectEx need to be looked up
- * at run time.
+ * at run time. Make sure this is done only once.
*/
-const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
- SOCKET h = toSocketHandle(s);
+boost::once_flag lookUpAcceptExOnce = BOOST_ONCE_INIT;
+LPFN_ACCEPTEX fnAcceptEx = 0;
+typedef void (*lookUpFunc)(const qpid::sys::Socket &);
+
+void lookUpAcceptEx() {
+ SOCKET h = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
GUID guidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
- LPFN_ACCEPTEX fnAcceptEx;
WSAIoctl(h,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidAcceptEx,
@@ -63,9 +65,9 @@ const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
&dwBytes,
NULL,
NULL);
+ closesocket(h);
if (fnAcceptEx == 0)
throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx"));
- return fnAcceptEx;
}
}
@@ -92,15 +94,18 @@ private:
AsynchAcceptor::Callback acceptedCallback;
const Socket& socket;
- const LPFN_ACCEPTEX fnAcceptEx;
};
AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback)
: acceptedCallback(callback),
- socket(s),
- fnAcceptEx(lookUpAcceptEx(s)) {
+ socket(s) {
s.setNonblocking();
+#if (BOOST_VERSION >= 103500) /* boost 1.35 or later reversed the args */
+ boost::call_once(lookUpAcceptExOnce, lookUpAcceptEx);
+#else
+ boost::call_once(lookUpAcceptEx, lookUpAcceptExOnce);
+#endif
}
AsynchAcceptor::~AsynchAcceptor()
@@ -109,8 +114,7 @@ AsynchAcceptor::~AsynchAcceptor()
}
void AsynchAcceptor::start(Poller::shared_ptr poller) {
- PollerHandle ph = PollerHandle(socket);
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
restart ();
}
@@ -118,26 +122,25 @@ void AsynchAcceptor::restart(void) {
DWORD bytesReceived = 0; // Not used, needed for AcceptEx API
AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback,
this,
- socket);
+ toSocketHandle(socket));
BOOL status;
- status = fnAcceptEx(toSocketHandle(socket),
- toSocketHandle(*result->newSocket),
- result->addressBuffer,
- 0,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- &bytesReceived,
- result->overlapped());
+ status = ::fnAcceptEx(toSocketHandle(socket),
+ toSocketHandle(*result->newSocket),
+ result->addressBuffer,
+ 0,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ &bytesReceived,
+ result->overlapped());
QPID_WINDOWS_CHECK_ASYNC_START(status);
}
AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const Socket& listener)
- : callback(cb), acceptor(acceptor),
- listener(toSocketHandle(listener)),
- newSocket(listener.createSameTypeSocket()) {
+ SOCKET listener)
+ : callback(cb), acceptor(acceptor), listener(listener) {
+ newSocket.reset (new Socket());
}
void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
@@ -151,7 +154,7 @@ void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
delete this;
}
-void AsynchAcceptResult::failure(int /*status*/) {
+void AsynchAcceptResult::failure(int status) {
//if (status != WSA_OPERATION_ABORTED)
// Can there be anything else? ;
delete this;
@@ -170,20 +173,20 @@ private:
FailedCallback failCallback;
const Socket& socket;
const std::string hostname;
- const std::string port;
+ const uint16_t port;
public:
AsynchConnector(const Socket& socket,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb = 0);
void start(Poller::shared_ptr poller);
};
AsynchConnector::AsynchConnector(const Socket& sock,
- const std::string& hname,
- const std::string& p,
+ std::string hname,
+ uint16_t p,
ConnectedCallback connCb,
FailedCallback failCb) :
connCallback(connCb), failCallback(failCb), socket(sock),
@@ -213,8 +216,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s,
}
AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb)
{
@@ -407,9 +410,8 @@ void AsynchIO::queueForDeletion() {
}
void AsynchIO::start(Poller::shared_ptr poller0) {
- PollerHandle ph = PollerHandle(socket);
poller = poller0;
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
if (writeQueue.size() > 0) // Already have data queued for write
notifyPendingWrite();
startReading();
@@ -582,6 +584,7 @@ void AsynchIO::notifyIdle(void) {
void AsynchIO::startWrite(AsynchIO::BufferBase* buff) {
writeInProgress = true;
InterlockedIncrement(&opsInProgress);
+ int writeCount = buff->byteCount-buff->dataCount;
AsynchWriteResult *result =
new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1),
buff,
diff --git a/cpp/src/qpid/sys/windows/AsynchIoResult.h b/cpp/src/qpid/sys/windows/AsynchIoResult.h
index 27e4c22138..66c89efc11 100755
--- a/cpp/src/qpid/sys/windows/AsynchIoResult.h
+++ b/cpp/src/qpid/sys/windows/AsynchIoResult.h
@@ -83,22 +83,22 @@ class AsynchAcceptResult : public AsynchResult {
public:
AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const qpid::sys::Socket& listener);
+ SOCKET listener);
virtual void success (size_t bytesTransferred);
virtual void failure (int error);
private:
virtual void complete(void) {} // No-op for this class.
+ std::auto_ptr<qpid::sys::Socket> newSocket;
qpid::sys::AsynchAcceptor::Callback callback;
AsynchAcceptor *acceptor;
SOCKET listener;
- std::auto_ptr<qpid::sys::Socket> newSocket;
// AcceptEx needs a place to write the local and remote addresses
// when accepting the connection. Place those here; get enough for
// IPv6 addresses, even if the socket is IPv4.
- enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16,
+ enum { SOCKADDRMAXLEN = sizeof sockaddr_in6 + 16,
SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN };
char addressBuffer[SOCKADDRBUFLEN];
};
diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp
index 1805dd2cd8..d326ab02ac 100755
--- a/cpp/src/qpid/sys/windows/IocpPoller.cpp
+++ b/cpp/src/qpid/sys/windows/IocpPoller.cpp
@@ -152,9 +152,9 @@ void Poller::monitorHandle(PollerHandle& handle, Direction dir) {
}
// All no-ops...
-void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {}
-void Poller::registerHandle(PollerHandle& /*handle*/) {}
-void Poller::unregisterHandle(PollerHandle& /*handle*/) {}
+void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) {}
+void Poller::registerHandle(PollerHandle& handle) {}
+void Poller::unregisterHandle(PollerHandle& handle) {}
Poller::Event Poller::wait(Duration timeout) {
DWORD timeoutMs = 0;
diff --git a/cpp/src/qpid/sys/windows/SCM.cpp b/cpp/src/qpid/sys/windows/SCM.cpp
deleted file mode 100644
index 4d2c74d4b9..0000000000
--- a/cpp/src/qpid/sys/windows/SCM.cpp
+++ /dev/null
@@ -1,332 +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 "qpid/log/Statement.h"
-#include "qpid/sys/windows/check.h"
-#include "SCM.h"
-
-#pragma comment(lib, "advapi32.lib")
-
-namespace {
-
-// Container that will close a SC_HANDLE upon destruction.
-class AutoServiceHandle {
-public:
- AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {}
- ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); }
- void release() { h = NULL; }
- void reset(SC_HANDLE newHandle)
- {
- if (h != NULL)
- ::CloseServiceHandle(h);
- h = newHandle;
- }
- operator SC_HANDLE() const { return h; }
-
-private:
- SC_HANDLE h;
-};
-
-}
-
-namespace qpid {
-namespace windows {
-
-SCM::SCM() : scmHandle(NULL)
-{
-}
-
-SCM::~SCM()
-{
- if (NULL != scmHandle)
- ::CloseServiceHandle(scmHandle);
-}
-
-/**
- * Install this executable as a service
- */
-void SCM::install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType,
- const string& account,
- const string& password,
- const string& depends)
-{
- // Handle dependent service name list; Windows wants a set of nul-separated
- // names ending with a double nul.
- string depends2 = depends;
- if (!depends2.empty()) {
- // CDL to null delimiter w/ trailing double null
- size_t p = 0;
- while ((p = depends2.find_first_of( ',', p)) != string::npos)
- depends2.replace(p, 1, 1, '\0');
- depends2.push_back('\0');
- depends2.push_back('\0');
- }
-
-#if 0
- // I'm nervous about adding a user/password check here. Is this a
- // potential attack vector, letting users check passwords without
- // control? -Steve Huston, Feb 24, 2011
-
- // Validate account, password
- HANDLE hToken = NULL;
- bool logStatus = false;
- if (!account.empty() && !password.empty() &&
- !(logStatus = ::LogonUserA(account.c_str(),
- "",
- password.c_str(),
- LOGON32_LOGON_NETWORK,
- LOGON32_PROVIDER_DEFAULT,
- &hToken ) != 0))
- std::cout << "warning: supplied account & password failed with LogonUser." << std::endl;
- if (logStatus)
- ::CloseHandle(hToken);
-#endif
-
- // Get fully qualified .exe name
- char myPath[MAX_PATH];
- DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH);
- QPID_WINDOWS_CHECK_NOT(myPathLength, 0);
- string imagePath(myPath, myPathLength);
- if (!args.empty())
- imagePath += " " + args;
-
- // Ensure there's a handle to the SCM database.
- openSvcManager();
-
- // Create the service
- SC_HANDLE svcHandle;
- svcHandle = ::CreateService(scmHandle, // SCM database
- serviceName.c_str(), // name of service
- serviceDesc.c_str(), // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS, // service type
- startType, // start type
- SERVICE_ERROR_NORMAL, // error cntrl type
- imagePath.c_str(), // path to service's binary w/ optional arguments
- NULL, // no load ordering group
- NULL, // no tag identifier
- depends2.empty() ? NULL : depends2.c_str(),
- account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem
- password.empty() ? NULL : password.c_str()); // password, or NULL for none
- QPID_WINDOWS_CHECK_NULL(svcHandle);
- ::CloseServiceHandle(svcHandle);
- QPID_LOG(info, "Service installed successfully");
-}
-
-/**
- *
- */
-void SCM::uninstall(const string& serviceName)
-{
- // Ensure there's a handle to the SCM database.
- openSvcManager();
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- DELETE));
- QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc);
- QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0);
- QPID_LOG(info, "Service deleted successfully.");
-}
-
-/**
- * Attempt to start the service.
- */
-void SCM::start(const string& serviceName)
-{
- // Ensure we have a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_ALL_ACCESS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Check the status in case the service is not stopped.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOP_PENDING)
- throw qpid::Exception("Timed out waiting for running service to stop.");
-
- // Attempt to start the service.
- QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0);
-
- QPID_LOG(info, "Service start pending...");
-
- // Check the status until the service is no longer start pending.
- state = waitForStateChangeFrom(svc, SERVICE_START_PENDING);
- // Determine whether the service is running.
- if (state == SERVICE_RUNNING) {
- QPID_LOG(info, "Service started successfully");
- }
- else {
- throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state));
- }
-}
-
-/**
- *
- */
-void SCM::stop(const string& serviceName)
-{
- // Ensure a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_STOP | SERVICE_QUERY_STATUS |
- SERVICE_ENUMERATE_DEPENDENTS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Make sure the service is not already stopped; if it's stop-pending,
- // wait for it to finalize.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED) {
- QPID_LOG(info, "Service is already stopped");
- return;
- }
-
- // If the service is running, dependencies must be stopped first.
- std::auto_ptr<ENUM_SERVICE_STATUS> deps;
- DWORD numDeps = getDependentServices(svc, deps);
- for (DWORD i = 0; i < numDeps; i++)
- stop(deps.get()[i].lpServiceName);
-
- // Dependents stopped; send a stop code to the service.
- SERVICE_STATUS_PROCESS ssp;
- if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
- throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " <<
- qpid::sys::strError(::GetLastError())));
-
- // Wait for the service to stop.
- state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED)
- QPID_LOG(info, QPID_MSG("Service " << serviceName <<
- " stopped successfully."));
-}
-
-/**
- *
- */
-void SCM::openSvcManager()
-{
- if (NULL != scmHandle)
- return;
-
- scmHandle = ::OpenSCManager(NULL, // local computer
- NULL, // ServicesActive database
- SC_MANAGER_ALL_ACCESS); // Rights
- QPID_WINDOWS_CHECK_NULL(scmHandle);
-}
-
-DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState)
-{
- SERVICE_STATUS_PROCESS ssStatus;
- DWORD bytesNeeded;
- DWORD waitTime;
- if (!::QueryServiceStatusEx(svc, // handle to service
- SC_STATUS_PROCESS_INFO, // information level
- (LPBYTE)&ssStatus, // address of structure
- sizeof(ssStatus), // size of structure
- &bytesNeeded)) // size needed if buffer is too small
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- // Save the tick count and initial checkpoint.
- DWORD startTickCount = ::GetTickCount();
- DWORD oldCheckPoint = ssStatus.dwCheckPoint;
-
- // Wait for the service to change out of the noted state.
- while (ssStatus.dwCurrentState == originalState) {
- // Do not wait longer than the wait hint. A good interval is
- // one-tenth of the wait hint but not less than 1 second
- // and not more than 10 seconds.
- waitTime = ssStatus.dwWaitHint / 10;
- if (waitTime < 1000)
- waitTime = 1000;
- else if (waitTime > 10000)
- waitTime = 10000;
-
- ::Sleep(waitTime);
-
- // Check the status until the service is no longer stop pending.
- if (!::QueryServiceStatusEx(svc,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE) &ssStatus,
- sizeof(ssStatus),
- &bytesNeeded))
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- if (ssStatus.dwCheckPoint > oldCheckPoint) {
- // Continue to wait and check.
- startTickCount = ::GetTickCount();
- oldCheckPoint = ssStatus.dwCheckPoint;
- } else {
- if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint)
- break;
- }
- }
- return ssStatus.dwCurrentState;
-}
-
-/**
- * Get the services that depend on @arg svc. All dependent service info
- * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps.
- *
- * @retval The number of dependent services.
- */
-DWORD SCM::getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps)
-{
- DWORD bytesNeeded;
- DWORD numEntries;
-
- // Pass a zero-length buffer to get the required buffer size.
- if (::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- 0,
- 0,
- &bytesNeeded,
- &numEntries)) {
- // If the Enum call succeeds, then there are no dependent
- // services, so do nothing.
- return 0;
- }
-
- if (::GetLastError() != ERROR_MORE_DATA)
- throw QPID_WINDOWS_ERROR((::GetLastError()));
-
- // Allocate a buffer for the dependencies.
- deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded]));
- // Enumerate the dependencies.
- if (!::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- deps.get(),
- bytesNeeded,
- &bytesNeeded,
- &numEntries))
- throw QPID_WINDOWS_ERROR((::GetLastError()));
- return numEntries;
-}
-
-} } // namespace qpid::windows
diff --git a/cpp/src/qpid/sys/windows/SCM.h b/cpp/src/qpid/sys/windows/SCM.h
deleted file mode 100644
index 8e94ef83c7..0000000000
--- a/cpp/src/qpid/sys/windows/SCM.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef WINDOWS_SCM_H
-#define WINDOWS_SCM_H
-
-/*
- *
- * 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 <memory>
-#include <string>
-using std::string;
-
-#ifdef UNICODE
-#undef UNICODE
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include <windows.h>
-
-#include "qpid/CommonImportExport.h"
-
-namespace qpid {
-namespace windows {
-
-/**
- * @class SCM
- *
- * Access the Windows Service Control Manager.
- */
-class SCM
-{
-public:
- QPID_COMMON_EXTERN SCM();
- QPID_COMMON_EXTERN ~SCM();
-
- /**
- * Install this executable as a service
- *
- * @param serviceName The name of the service
- * @param serviceDesc Description of the service's purpose
- * @param args The argument list to pass into the service
- * @param startType The start type: SERVICE_DEMAND_START,
- * SERVICE_AUTO_START, SERVICE_DISABLED
- * @param account If not empty, the account name to install this
- * service under
- * @param password If not empty, the account password to install this
- * service with
- * @param depends If not empty, a comma delimited list of services
- * that must start before this one
- */
- QPID_COMMON_EXTERN void install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType = SERVICE_DEMAND_START,
- const string& account = "NT AUTHORITY\\LocalSystem",
- const string& password = "",
- const string& depends = "");
-
- /**
- * Uninstall this executable as a service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void uninstall(const string& serviceName);
-
- /**
- * Start the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void start(const string& serviceName);
-
- /**
- * Stop the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void stop(const string &serviceName);
-
-private:
- SC_HANDLE scmHandle;
-
- void openSvcManager();
- DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState);
- DWORD getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps);
-
-};
-
-}} // namespace qpid::windows
-
-#endif /* #ifndef WINDOWS_SCM_H */
diff --git a/cpp/src/qpid/sys/windows/Shlib.cpp b/cpp/src/qpid/sys/windows/Shlib.cpp
index ba18747eb4..38027de93f 100644
--- a/cpp/src/qpid/sys/windows/Shlib.cpp
+++ b/cpp/src/qpid/sys/windows/Shlib.cpp
@@ -44,8 +44,7 @@ void Shlib::unload() {
}
void* Shlib::getSymbol(const char* name) {
- // Double cast avoids warning about casting function pointer to object
- void *sym = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), name)));
+ void* sym = GetProcAddress(static_cast<HMODULE>(handle), name);
if (sym == NULL)
throw QPID_WINDOWS_ERROR(GetLastError());
return sym;
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index 1fa4768329..11fb8b4133 100644..100755
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -20,18 +20,19 @@
*/
#include "qpid/sys/Socket.h"
-
#include "qpid/sys/SocketAddress.h"
-#include "qpid/sys/windows/check.h"
#include "qpid/sys/windows/IoHandlePrivate.h"
+#include "qpid/sys/windows/check.h"
+#include "qpid/sys/Time.h"
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include <cstdlib>
+#include <string.h>
#include <winsock2.h>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+
// Need to initialize WinSock. Ideally, this would be a singleton or embedded
// in some one-time initialization function. I tried boost singleton and could
// not get it to compile (and others located in google had the same problem).
@@ -83,30 +84,53 @@ namespace sys {
namespace {
-std::string getName(SOCKET fd, bool local)
+std::string getName(SOCKET fd, bool local, bool includeService = false)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
if (local) {
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
} else {
- QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
}
- return SocketAddress::asString(name, namelen);
+ char servName[NI_MAXSERV];
+ char dispName[NI_MAXHOST];
+ if (includeService) {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return std::string(dispName) + ":" + std::string(servName);
+ } else {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ 0, 0,
+ NI_NUMERICHOST) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return dispName;
+ }
}
-uint16_t getLocalPort(int fd)
+std::string getService(SOCKET fd, bool local)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
+
+ if (local) {
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
+ } else {
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
+ }
- return SocketAddress::getPort(name);
+ char servName[NI_MAXSERV];
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ 0, 0,
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return servName;
}
} // namespace
@@ -114,7 +138,13 @@ Socket::Socket() :
IOHandle(new IOHandlePrivate),
nonblocking(false),
nodelay(false)
-{}
+{
+ SOCKET& socket = impl->fd;
+ if (socket != INVALID_SOCKET) Socket::close();
+ SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
+ socket = s;
+}
Socket::Socket(IOHandlePrivate* h) :
IOHandle(h),
@@ -122,7 +152,8 @@ Socket::Socket(IOHandlePrivate* h) :
nodelay(false)
{}
-void Socket::createSocket(const SocketAddress& sa) const
+void
+Socket::createSocket(const SocketAddress& sa) const
{
SOCKET& socket = impl->fd;
if (socket != INVALID_SOCKET) Socket::close();
@@ -137,24 +168,24 @@ void Socket::createSocket(const SocketAddress& sa) const
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
} catch (std::exception&) {
- ::closesocket(s);
+ closesocket(s);
socket = INVALID_SOCKET;
throw;
}
}
-Socket* Socket::createSameTypeSocket() const {
- SOCKET& socket = impl->fd;
- // Socket currently has no actual socket attached
- if (socket == INVALID_SOCKET)
- return new Socket;
-
- ::sockaddr_storage sa;
- ::socklen_t salen = sizeof(sa);
- QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
- SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
- if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
- return new Socket(new IOHandlePrivate(s));
+void Socket::setTimeout(const Duration& interval) const
+{
+ const SOCKET& socket = impl->fd;
+ int64_t nanosecs = interval;
+ nanosecs /= (1000 * 1000); // nsecs -> usec -> msec
+ int msec = 0;
+ if (nanosecs > std::numeric_limits<int>::max())
+ msec = std::numeric_limits<int>::max();
+ else
+ msec = static_cast<int>(nanosecs);
+ setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec));
+ setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec));
}
void Socket::setNonblocking() const {
@@ -162,25 +193,30 @@ void Socket::setNonblocking() const {
QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock));
}
-void Socket::connect(const std::string& host, const std::string& port) const
+void Socket::connect(const std::string& host, uint16_t port) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
connect(sa);
}
void
Socket::connect(const SocketAddress& addr) const
{
- peername = addr.asString(false);
-
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
- int err;
+ const addrinfo *addrs = &(getAddrInfo(addr));
+ int error = 0;
WSASetLastError(0);
- if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) &&
- ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK))
- throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername));
+ while (addrs != 0) {
+ if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) ||
+ (WSAGetLastError() == WSAEWOULDBLOCK))
+ break;
+ // Error... save this error code and see if there are other address
+ // to try before throwing the exception.
+ error = WSAGetLastError();
+ addrs = addrs->ai_next;
+ }
+ if (error)
+ throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname));
}
void
@@ -211,26 +247,24 @@ int Socket::read(void *buf, size_t count) const
return received;
}
-int Socket::listen(const std::string& host, const std::string& port, int backlog) const
-{
- SocketAddress sa(host, port);
- return listen(sa, backlog);
-}
-
-int Socket::listen(const SocketAddress& addr, int backlog) const
+int Socket::listen(uint16_t port, int backlog) const
{
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
BOOL yes=1;
QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)));
-
- if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError())));
+ struct sockaddr_in name;
+ memset(&name, 0, sizeof(name));
+ name.sin_family = AF_INET;
+ name.sin_port = htons(port);
+ name.sin_addr.s_addr = 0;
+ if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) == SOCKET_ERROR)
+ throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError())));
if (::listen(socket, backlog) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError())));
-
- return getLocalPort(socket);
+ throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError())));
+
+ socklen_t namelen = sizeof(name);
+ QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen));
+ return ntohs(name.sin_port);
}
Socket* Socket::accept() const
@@ -243,20 +277,36 @@ Socket* Socket::accept() const
else throw QPID_WINDOWS_ERROR(WSAGetLastError());
}
+std::string Socket::getSockname() const
+{
+ return getName(impl->fd, true);
+}
+
+std::string Socket::getPeername() const
+{
+ return getName(impl->fd, false);
+}
+
std::string Socket::getPeerAddress() const
{
- if (peername.empty()) {
- peername = getName(impl->fd, false);
- }
- return peername;
+ if (!connectname.empty())
+ return std::string (connectname);
+ return getName(impl->fd, false, true);
}
std::string Socket::getLocalAddress() const
{
- if (localname.empty()) {
- localname = getName(impl->fd, true);
- }
- return localname;
+ return getName(impl->fd, true, true);
+}
+
+uint16_t Socket::getLocalPort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
+}
+
+uint16_t Socket::getRemotePort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
}
int Socket::getError() const
diff --git a/cpp/src/qpid/sys/windows/SocketAddress.cpp b/cpp/src/qpid/sys/windows/SocketAddress.cpp
index 77bbf85810..501cff1297 100644
--- a/cpp/src/qpid/sys/windows/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/windows/SocketAddress.cpp
@@ -21,13 +21,7 @@
#include "qpid/sys/SocketAddress.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
-
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include "qpid/sys/windows/check.h"
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -41,111 +35,37 @@ SocketAddress::SocketAddress(const std::string& host0, const std::string& port0)
port(port0),
addrInfo(0)
{
-}
-
-SocketAddress::SocketAddress(const SocketAddress& sa) :
- host(sa.host),
- port(sa.port),
- addrInfo(0)
-{
-}
-
-SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
-{
- SocketAddress temp(sa);
-
- std::swap(temp, *this);
- return *this;
-}
-
-SocketAddress::~SocketAddress()
-{
- if (addrInfo) {
- ::freeaddrinfo(addrInfo);
+ ::addrinfo hints;
+ ::memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well
+ hints.ai_socktype = SOCK_STREAM;
+
+ const char* node = 0;
+ if (host.empty()) {
+ hints.ai_flags |= AI_PASSIVE;
+ } else {
+ node = host.c_str();
}
-}
+ const char* service = port.empty() ? "0" : port.c_str();
-std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen)
-{
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (int rc=::getnameinfo(addr, addrlen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- std::string s;
- switch (addr->sa_family) {
- case AF_INET: s += dispName; break;
- case AF_INET6: s += "["; s += dispName; s+= "]"; break;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
- s += ":";
- s += servName;
- return s;
+ int n = ::getaddrinfo(node, service, &hints, &addrInfo);
+ if (n != 0)
+ throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
}
-uint16_t SocketAddress::getPort(::sockaddr const * const addr)
+SocketAddress::~SocketAddress()
{
- switch (addr->sa_family) {
- case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port);
- case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port);
- default:throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ ::freeaddrinfo(addrInfo);
}
-std::string SocketAddress::asString(bool numeric) const
+std::string SocketAddress::asString() const
{
- if (!numeric)
- return host + ":" + port;
- // Canonicalise into numeric id
- const ::addrinfo& ai = getAddrInfo(*this);
-
- return asString(ai.ai_addr, ai.ai_addrlen);
-}
-
-bool SocketAddress::nextAddress() {
- bool r = currentAddrInfo->ai_next != 0;
- if (r)
- currentAddrInfo = currentAddrInfo->ai_next;
- return r;
-}
-
-void SocketAddress::setAddrInfoPort(uint16_t port) {
- if (!currentAddrInfo) return;
-
- ::addrinfo& ai = *currentAddrInfo;
- switch (ai.ai_family) {
- case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return;
- case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ return host + ":" + port;
}
const ::addrinfo& getAddrInfo(const SocketAddress& sa)
{
- if (!sa.addrInfo) {
- ::addrinfo hints;
- ::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
- hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
- hints.ai_socktype = SOCK_STREAM;
-
- const char* node = 0;
- if (sa.host.empty()) {
- hints.ai_flags |= AI_PASSIVE;
- } else {
- node = sa.host.c_str();
- }
- const char* service = sa.port.empty() ? "0" : sa.port.c_str();
-
- int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
- if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
- sa.currentAddrInfo = sa.addrInfo;
- }
-
- return *sa.currentAddrInfo;
+ return *sa.addrInfo;
}
}}
diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.h b/cpp/src/qpid/sys/windows/SslAsynchIO.h
index edec081ced..3cdf2c8f08 100644
--- a/cpp/src/qpid/sys/windows/SslAsynchIO.h
+++ b/cpp/src/qpid/sys/windows/SslAsynchIO.h
@@ -39,6 +39,9 @@ namespace qpid {
namespace sys {
namespace windows {
+class Socket;
+class Poller;
+
/*
* SSL/Schannel shim between the frame-handling and AsynchIO layers.
* SslAsynchIO creates a regular AsynchIO object to handle I/O and this class
diff --git a/cpp/src/qpid/sys/windows/StrError.cpp b/cpp/src/qpid/sys/windows/StrError.cpp
index 546d399d16..9c1bfcd79c 100755
--- a/cpp/src/qpid/sys/windows/StrError.cpp
+++ b/cpp/src/qpid/sys/windows/StrError.cpp
@@ -30,7 +30,6 @@ namespace sys {
std::string strError(int err) {
const size_t bufsize = 512;
char buf[bufsize];
- buf[0] = 0;
if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK
| FORMAT_MESSAGE_FROM_SYSTEM,
0,
@@ -40,11 +39,7 @@ std::string strError(int err) {
bufsize,
0))
{
-#ifdef _MSC_VER
- strerror_s(buf, bufsize, err);
-#else
- return std::string(strerror(err));
-#endif
+ strerror_s (buf, bufsize, err);
}
return std::string(buf);
}
diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp
index 23b0033be4..583a9613a3 100755
--- a/cpp/src/qpid/sys/windows/Thread.cpp
+++ b/cpp/src/qpid/sys/windows/Thread.cpp
@@ -19,11 +19,6 @@
*
*/
-// Ensure definition of OpenThread in mingw
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-
#include "qpid/sys/Thread.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/windows/check.h"
@@ -31,204 +26,50 @@
#include <process.h>
#include <windows.h>
-/*
- * This implementation distinguishes between two types of thread: Qpid
- * threads (based on qpid::sys::Runnable) and the rest. It provides a
- * join() that will not deadlock against the Windows loader lock for
- * Qpid threads.
- *
- * System thread identifiers are unique per Windows thread; thread
- * handles are not. Thread identifiers can be recycled, but keeping a
- * handle open against the thread prevents recycling as long as
- * shared_ptr references to a ThreadPrivate structure remain.
- *
- * There is a 1-1 relationship between Qpid threads and their
- * ThreadPrivate structure. Non-Qpid threads do not need to find the
- * qpidThreadDone handle, so there may be a 1-many relationship for
- * them.
- *
- * TLS storage is used for a lockless solution for static library
- * builds. The special case of LoadLibrary/FreeLibrary requires
- * additional synchronization variables and resource cleanup in
- * DllMain. _DLL marks the dynamic case.
- */
+namespace {
+unsigned __stdcall runRunnable(void* p)
+{
+ static_cast<qpid::sys::Runnable*>(p)->run();
+ _endthreadex(0);
+ return 0;
+}
+}
namespace qpid {
namespace sys {
class ThreadPrivate {
-public:
friend class Thread;
- friend unsigned __stdcall runThreadPrivate(void*);
- typedef boost::shared_ptr<ThreadPrivate> shared_ptr;
- ~ThreadPrivate();
-private:
- unsigned threadId;
HANDLE threadHandle;
- HANDLE initCompleted;
- HANDLE qpidThreadDone;
- Runnable* runnable;
- shared_ptr keepAlive;
-
- ThreadPrivate() : threadId(GetCurrentThreadId()), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(NULL) {
- threadHandle = OpenThread (SYNCHRONIZE, FALSE, threadId);
- QPID_WINDOWS_CHECK_CRT_NZ(threadHandle);
- }
-
- ThreadPrivate(Runnable* r) : threadHandle(NULL), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(r) {}
-
- void start(shared_ptr& p);
- static shared_ptr createThread(Runnable* r);
-};
-
-}} // namespace qpid::sys
-
-
-namespace {
-using namespace qpid::sys;
-
-#ifdef _DLL
-class ScopedCriticalSection
-{
- public:
- ScopedCriticalSection(CRITICAL_SECTION& cs) : criticalSection(cs) { EnterCriticalSection(&criticalSection); }
- ~ScopedCriticalSection() { LeaveCriticalSection(&criticalSection); }
- private:
- CRITICAL_SECTION& criticalSection;
-};
-
-CRITICAL_SECTION threadLock;
-long runningThreads = 0;
-HANDLE threadsDone;
-bool terminating = false;
-#endif
-
-
-DWORD volatile tlsIndex = TLS_OUT_OF_INDEXES;
-
-DWORD getTlsIndex() {
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- return tlsIndex; // already set
-
- DWORD trialIndex = TlsAlloc();
- QPID_WINDOWS_CHECK_NOT(trialIndex, TLS_OUT_OF_INDEXES); // No OS resource
+ unsigned threadId;
- // only one thread gets to set the value
- DWORD actualIndex = (DWORD) InterlockedCompareExchange((LONG volatile *) &tlsIndex, (LONG) trialIndex, (LONG) TLS_OUT_OF_INDEXES);
- if (actualIndex == TLS_OUT_OF_INDEXES)
- return trialIndex; // we won the race
- else {
- TlsFree(trialIndex);
- return actualIndex;
+ ThreadPrivate(Runnable* runnable) {
+ uintptr_t h = _beginthreadex(0,
+ 0,
+ runRunnable,
+ runnable,
+ 0,
+ &threadId);
+ QPID_WINDOWS_CHECK_CRT_NZ(h);
+ threadHandle = reinterpret_cast<HANDLE>(h);
}
-}
-
-} // namespace
-
-namespace qpid {
-namespace sys {
-
-unsigned __stdcall runThreadPrivate(void* p)
-{
- ThreadPrivate* threadPrivate = static_cast<ThreadPrivate*>(p);
- TlsSetValue(getTlsIndex(), threadPrivate);
-
- WaitForSingleObject (threadPrivate->initCompleted, INFINITE);
- CloseHandle (threadPrivate->initCompleted);
- threadPrivate->initCompleted = NULL;
-
- try {
- threadPrivate->runnable->run();
- } catch (...) {
- // not our concern
- }
-
- SetEvent (threadPrivate->qpidThreadDone); // allow join()
- threadPrivate->keepAlive.reset(); // may run ThreadPrivate destructor
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
- return 0;
-}
-
-
-ThreadPrivate::shared_ptr ThreadPrivate::createThread(Runnable* runnable) {
- ThreadPrivate::shared_ptr tp(new ThreadPrivate(runnable));
- tp->start(tp);
- return tp;
-}
-
-void ThreadPrivate::start(ThreadPrivate::shared_ptr& tp) {
- getTlsIndex(); // fail here if OS problem, not in new thread
-
- initCompleted = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(initCompleted);
- qpidThreadDone = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(qpidThreadDone);
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (terminating)
- throw qpid::Exception(QPID_MSG("creating thread after exit/FreeLibrary"));
- runningThreads++;
- }
-#endif
-
- uintptr_t h = _beginthreadex(0,
- 0,
- runThreadPrivate,
- (void *)this,
- 0,
- &threadId);
-
-#ifdef _DLL
- if (h == NULL) {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
-
- QPID_WINDOWS_CHECK_CRT_NZ(h);
-
- // Success
- keepAlive = tp;
- threadHandle = reinterpret_cast<HANDLE>(h);
- SetEvent (initCompleted);
-}
-
-ThreadPrivate::~ThreadPrivate() {
- if (threadHandle)
- CloseHandle (threadHandle);
- if (initCompleted)
- CloseHandle (initCompleted);
- if (qpidThreadDone)
- CloseHandle (qpidThreadDone);
-}
-
+
+ ThreadPrivate()
+ : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {}
+};
Thread::Thread() {}
-Thread::Thread(Runnable* runnable) : impl(ThreadPrivate::createThread(runnable)) {}
+Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {}
-Thread::Thread(Runnable& runnable) : impl(ThreadPrivate::createThread(&runnable)) {}
+Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {}
Thread::operator bool() {
return impl;
}
bool Thread::operator==(const Thread& t) const {
- if (!impl || !t.impl)
- return false;
return impl->threadId == t.impl->threadId;
}
@@ -238,17 +79,10 @@ bool Thread::operator!=(const Thread& t) const {
void Thread::join() {
if (impl) {
- DWORD status;
- if (impl->runnable) {
- HANDLE handles[2] = {impl->qpidThreadDone, impl->threadHandle};
- // wait for either. threadHandle not signalled if loader
- // lock held (FreeLibrary). qpidThreadDone not signalled
- // if thread terminated by exit().
- status = WaitForMultipleObjects (2, handles, false, INFINITE);
- }
- else
- status = WaitForSingleObject (impl->threadHandle, INFINITE);
+ DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE);
QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED);
+ CloseHandle (impl->threadHandle);
+ impl->threadHandle = 0;
}
}
@@ -258,70 +92,9 @@ unsigned long Thread::logId() {
/* static */
Thread Thread::current() {
- ThreadPrivate* tlsValue = (ThreadPrivate *) TlsGetValue(getTlsIndex());
Thread t;
- if (tlsValue != NULL) {
- // called from within Runnable->run(), so keepAlive has positive use count
- t.impl = tlsValue->keepAlive;
- }
- else
- t.impl.reset(new ThreadPrivate());
+ t.impl.reset(new ThreadPrivate());
return t;
}
-}} // namespace qpid::sys
-
-
-#ifdef _DLL
-
-// DllMain: called possibly many times in a process lifetime if dll
-// loaded and freed repeatedly . Be mindful of Windows loader lock
-// and other DllMain restrictions.
-
-BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) {
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- InitializeCriticalSection(&threadLock);
- threadsDone = CreateEvent(NULL, TRUE, FALSE, NULL);
- break;
-
- case DLL_PROCESS_DETACH:
- terminating = true;
- if (reserved != NULL) {
- // process exit(): threads are stopped arbitrarily and
- // possibly in an inconsistent state. Not even threadLock
- // can be trusted. All static destructors have been
- // called at this point and any resources this unit knows
- // about will be released as part of process tear down by
- // the OS. Accordingly, do nothing.
- return TRUE;
- }
- else {
- // FreeLibrary(): threads are still running and we are
- // encouraged to clean up to avoid leaks. Mostly we just
- // want any straggler threads to finish and notify
- // threadsDone as the last thing they do.
- while (1) {
- {
- ScopedCriticalSection l(threadLock);
- if (runningThreads == 0)
- break;
- ResetEvent(threadsDone);
- }
- WaitForSingleObject(threadsDone, INFINITE);
- }
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- TlsFree(getTlsIndex());
- CloseHandle(threadsDone);
- DeleteCriticalSection(&threadLock);
- }
- break;
-
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return TRUE;
-}
-
-#endif
+}} /* qpid::sys */
diff --git a/cpp/src/qpid/sys/windows/Time.cpp b/cpp/src/qpid/sys/windows/Time.cpp
index 25c50819cd..16d09fcdc0 100644
--- a/cpp/src/qpid/sys/windows/Time.cpp
+++ b/cpp/src/qpid/sys/windows/Time.cpp
@@ -27,17 +27,6 @@
using namespace boost::posix_time;
-namespace {
-
-// High-res timing support. This will display times since program start,
-// more or less. Keep track of the start value and the conversion factor to
-// seconds.
-bool timeInitialized = false;
-LARGE_INTEGER start;
-double freq = 1.0;
-
-}
-
namespace qpid {
namespace sys {
@@ -102,35 +91,10 @@ void outputFormattedNow(std::ostream& o) {
char time_string[100];
::time( &rawtime );
-#ifdef _MSC_VER
::localtime_s(&timeinfo, &rawtime);
-#else
- timeinfo = *(::localtime(&rawtime));
-#endif
::strftime(time_string, 100,
"%Y-%m-%d %H:%M:%S",
&timeinfo);
o << time_string << " ";
}
-
-void outputHiresNow(std::ostream& o) {
- if (!timeInitialized) {
- start.QuadPart = 0;
- LARGE_INTEGER iFreq;
- iFreq.QuadPart = 1;
- QueryPerformanceCounter(&start);
- QueryPerformanceFrequency(&iFreq);
- freq = static_cast<double>(iFreq.QuadPart);
- timeInitialized = true;
- }
- LARGE_INTEGER iNow;
- iNow.QuadPart = 0;
- QueryPerformanceCounter(&iNow);
- iNow.QuadPart -= start.QuadPart;
- if (iNow.QuadPart < 0)
- iNow.QuadPart = 0;
- double now = static_cast<double>(iNow.QuadPart);
- now /= freq; // now is seconds after this
- o << std::fixed << std::setprecision(8) << std::setw(16) << std::setfill('0') << now << "s ";
-}
}}
diff --git a/cpp/src/qpid/sys/windows/mingw32_compat.h b/cpp/src/qpid/sys/windows/mingw32_compat.h
deleted file mode 100644
index 51f613cc25..0000000000
--- a/cpp/src/qpid/sys/windows/mingw32_compat.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _sys_windows_mingw32_compat
-#define _sys_windows_mingw32_compat
-/*
- *
- * 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.
- *
- */
-
-#ifdef WIN32
-#ifndef _MSC_VER
-
-//
-// The following definitions for extension function GUIDs and signatures are taken from
-// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of
-// mswsock.h, but are not included presently.
-//
-
-#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
-typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED);
-
-#endif
-#endif
-
-#endif
diff --git a/cpp/src/qpid/sys/windows/uuid.cpp b/cpp/src/qpid/sys/windows/uuid.cpp
index 3316ecbc00..b5360622dc 100644
--- a/cpp/src/qpid/sys/windows/uuid.cpp
+++ b/cpp/src/qpid/sys/windows/uuid.cpp
@@ -19,7 +19,7 @@
*
*/
-#include <rpc.h>
+#include <Rpc.h>
#ifdef uuid_t /* Done in rpcdce.h */
# undef uuid_t
#endif
@@ -52,11 +52,7 @@ int uuid_parse (const char *in, uuid_t uu) {
void uuid_unparse (const uuid_t uu, char *out) {
unsigned char *formatted;
if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) {
-#ifdef _MSC_VER
strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE);
-#else
- strncpy (out, (char*)formatted, 36+1);
-#endif
RpcStringFree(&formatted);
}
}
diff --git a/cpp/src/qpid/types/Uuid.cpp b/cpp/src/qpid/types/Uuid.cpp
index 9862fa8946..9face4e5d2 100644
--- a/cpp/src/qpid/types/Uuid.cpp
+++ b/cpp/src/qpid/types/Uuid.cpp
@@ -20,7 +20,6 @@
*/
#include "qpid/types/Uuid.h"
#include "qpid/sys/uuid.h"
-#include "qpid/sys/IntegerTypes.h"
#include <sstream>
#include <iostream>
#include <string.h>
@@ -72,8 +71,7 @@ void Uuid::clear()
// Force int 0/!0 to false/true; avoids compile warnings.
bool Uuid::isNull() const
{
- // This const cast is for Solaris which has non const arguments
- return !!uuid_is_null(const_cast<uint8_t*>(bytes));
+ return !!uuid_is_null(bytes);
}
Uuid::operator bool() const { return !isNull(); }
@@ -88,8 +86,7 @@ const unsigned char* Uuid::data() const
bool operator==(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) == 0;
+ return uuid_compare(a.bytes, b.bytes) == 0;
}
bool operator!=(const Uuid& a, const Uuid& b)
@@ -99,26 +96,22 @@ bool operator!=(const Uuid& a, const Uuid& b)
bool operator<(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) < 0;
+ return uuid_compare(a.bytes, b.bytes) < 0;
}
bool operator>(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) > 0;
+ return uuid_compare(a.bytes, b.bytes) > 0;
}
bool operator<=(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) <= 0;
+ return uuid_compare(a.bytes, b.bytes) <= 0;
}
bool operator>=(const Uuid& a, const Uuid& b)
{
- // This const cast is for Solaris which has non const arguments
- return uuid_compare(const_cast<uint8_t*>(a.bytes), const_cast<uint8_t*>(b.bytes)) >= 0;
+ return uuid_compare(a.bytes, b.bytes) >= 0;
}
ostream& operator<<(ostream& out, Uuid uuid)
diff --git a/cpp/src/qpid/types/Variant.cpp b/cpp/src/qpid/types/Variant.cpp
index f563d5de5b..5d8878bdac 100644
--- a/cpp/src/qpid/types/Variant.cpp
+++ b/cpp/src/qpid/types/Variant.cpp
@@ -19,6 +19,7 @@
*
*/
#include "qpid/types/Variant.h"
+#include "qpid/Msg.h"
#include "qpid/log/Statement.h"
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
@@ -107,27 +108,15 @@ class VariantImpl
} value;
std::string encoding;//optional encoding for variable length data
+ std::string getTypeName(VariantType type) const;
template<class T> T convertFromString() const
{
std::string* s = reinterpret_cast<std::string*>(value.v);
- if (std::numeric_limits<T>::is_signed || s->find('-') != 0) {
- //lexical_cast won't fail if string is a negative number and T is unsigned
- try {
- return boost::lexical_cast<T>(*s);
- } catch(const boost::bad_lexical_cast&) {
- //don't return, throw exception below
- }
- } else {
- //T is unsigned and number starts with '-'
- try {
- //handle special case of negative zero
- if (boost::lexical_cast<int>(*s) == 0) return 0;
- //else its a non-zero negative number so throw exception at end of function
- } catch(const boost::bad_lexical_cast&) {
- //wasn't a valid int, therefore not a valid uint
- }
+ try {
+ return boost::lexical_cast<T>(*s);
+ } catch(const boost::bad_lexical_cast&) {
+ throw InvalidConversion(QPID_MSG("Cannot convert " << *s));
}
- throw InvalidConversion(QPID_MSG("Cannot convert " << *s));
}
};
@@ -381,11 +370,11 @@ int8_t VariantImpl::asInt8() const
return int8_t(value.ui16);
break;
case VAR_UINT32:
- if (value.ui32 <= (uint32_t) std::numeric_limits<int8_t>::max())
+ if (value.ui32 <= (uint) std::numeric_limits<int8_t>::max())
return int8_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int8_t>::max())
+ if (value.ui64 <= (uint) std::numeric_limits<int8_t>::max())
return int8_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int8_t>();
@@ -412,11 +401,11 @@ int16_t VariantImpl::asInt16() const
return int16_t(value.ui16);
break;
case VAR_UINT32:
- if (value.ui32 <= (uint32_t) std::numeric_limits<int16_t>::max())
+ if (value.ui32 <= (uint) std::numeric_limits<int16_t>::max())
return int16_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int16_t>::max())
+ if (value.ui64 <= (uint) std::numeric_limits<int16_t>::max())
return int16_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int16_t>();
@@ -441,7 +430,7 @@ int32_t VariantImpl::asInt32() const
return int32_t(value.ui32);
break;
case VAR_UINT64:
- if (value.ui64 <= (uint64_t) std::numeric_limits<int32_t>::max())
+ if (value.ui64 <= (uint32_t) std::numeric_limits<int32_t>::max())
return int32_t(value.ui64);
break;
case VAR_STRING: return convertFromString<int32_t>();
@@ -593,7 +582,7 @@ const std::string& VariantImpl::getString() const
void VariantImpl::setEncoding(const std::string& s) { encoding = s; }
const std::string& VariantImpl::getEncoding() const { return encoding; }
-std::string getTypeName(VariantType type)
+std::string VariantImpl::getTypeName(VariantType type) const
{
switch (type) {
case VAR_VOID: return "void";
diff --git a/cpp/src/replication.mk b/cpp/src/replication.mk
index e5da32f88b..dbe071f405 100644
--- a/cpp/src/replication.mk
+++ b/cpp/src/replication.mk
@@ -19,14 +19,14 @@
# Make file for building two plugins for asynchronously replicating
# queues.
-dmoduleexec_LTLIBRARIES += replicating_listener.la replication_exchange.la
+dmodule_LTLIBRARIES += replicating_listener.la replication_exchange.la
# a queue event listener plugin that creates messages on a replication
# queue corresponding to enqueue and dequeue events:
replicating_listener_la_SOURCES = \
qpid/replication/constants.h \
qpid/replication/ReplicatingEventListener.cpp \
- qpid/replication/ReplicatingEventListener.h
+ qpid/replication/ReplicatingEventListener.h
replicating_listener_la_LIBADD = libqpidbroker.la
if SUNOS
@@ -41,7 +41,7 @@ replicating_listener_la_LDFLAGS = $(PLUGINLDFLAGS)
replication_exchange_la_SOURCES = \
qpid/replication/constants.h \
qpid/replication/ReplicationExchange.cpp \
- qpid/replication/ReplicationExchange.h
+ qpid/replication/ReplicationExchange.h
replication_exchange_la_LIBADD = libqpidbroker.la
diff --git a/cpp/src/ssl.mk b/cpp/src/ssl.mk
index 4dba9bb61c..5fbdd55438 100644
--- a/cpp/src/ssl.mk
+++ b/cpp/src/ssl.mk
@@ -18,7 +18,7 @@
#
#
# Makefile fragment, conditionally included in Makefile.am
-#
+#
libsslcommon_la_SOURCES = \
qpid/sys/ssl/check.h \
qpid/sys/ssl/check.cpp \
@@ -47,7 +47,7 @@ ssl_la_CXXFLAGS=$(AM_CXXFLAGS) $(SSL_CFLAGS)
ssl_la_LDFLAGS = $(PLUGINLDFLAGS)
-dmoduleexec_LTLIBRARIES += ssl.la
+dmodule_LTLIBRARIES += ssl.la
sslconnector_la_SOURCES = \
qpid/client/SslConnector.cpp
@@ -60,5 +60,5 @@ sslconnector_la_CXXFLAGS = $(AM_CXXFLAGS) -DQPIDC_CONF_FILE=\"$(confdir)/qpidc.c
sslconnector_la_LDFLAGS = $(PLUGINLDFLAGS)
-cmoduleexec_LTLIBRARIES += \
+cmodule_LTLIBRARIES += \
sslconnector.la
diff --git a/cpp/src/tests/.valgrind.supp b/cpp/src/tests/.valgrind.supp
index 2c6a1509ff..0e3e045437 100644
--- a/cpp/src/tests/.valgrind.supp
+++ b/cpp/src/tests/.valgrind.supp
@@ -73,6 +73,61 @@
}
{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:_Znwm
+ fun:_ZN5boost15program_options??options_description*
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:_Znwm
+ fun:_ZN5boost9unit_test9test_case*
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlopen@@GLIBC_2.2.5
+ fun:_ZN4qpid3sys5Shlib4loadEPKc
+ fun:_Z9testShlibv
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv
+ obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0
+ fun:_ZN5boost17execution_monitor7executeEbi
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:_ZN5boost9unit_test10test_suite6do_runEv
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:main
+}
+
+{
+ boost 103200 -- we think Boost is responsible for these leaks.
+ Memcheck:Leak
+ fun:calloc
+ fun:_dl_allocate_tls
+ fun:pthread_create@@GLIBC_2.2.5
+ fun:_ZN4qpid6broker5Timer5startEv
+ fun:_ZN4qpid6broker5TimerC1Ev
+ fun:_ZN4qpid6broker10DtxManagerC1Ev
+ fun:_ZN4qpid6broker6BrokerC1ERKNS1_7OptionsE
+ fun:_ZN4qpid6broker6Broker6createERKNS1_7OptionsE
+ fun:_ZN15SessionFixtureTI15ProxyConnectionEC2Ev
+ fun:_Z14testQueueQueryv
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor8functionEv
+ obj:/usr/lib64/libboost_unit_test_framework.so.1.32.0
+ fun:_ZN5boost17execution_monitor7executeEbi
+ fun:_ZN5boost9unit_test9ut_detail17unit_test_monitor21execute_and_translateEPNS0_9test_caseEMS3_FvvEi
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:_ZN5boost9unit_test10test_suite6do_runEv
+ fun:_ZN5boost9unit_test9test_case3runEv
+ fun:main
+}
+
+{
INVESTIGATE
Memcheck:Leak
fun:calloc
@@ -100,6 +155,25 @@
}
{
+ boost 103200 -- mgoulish -- fix this, sometime
+ Memcheck:Leak
+ fun:*
+ fun:*
+ obj:*
+ fun:*
+ fun:_ZN4qpid34options_description_less_easy_initclEPKcPKN5boost15program_options14value_semanticES2_
+}
+
+{
+ boost 103200 -- mgoulish -- fix this, sometime
+ Memcheck:Leak
+ fun:*
+ fun:*
+ fun:*
+ fun:_ZN4qpid34options_description_less_easy_initclEPKcPKN5boost15program_options14value_semanticES2_
+}
+
+{
INVESTIGATE
Memcheck:Param
socketcall.sendto(msg)
diff --git a/cpp/src/tests/Address.cpp b/cpp/src/tests/Address.cpp
index 0fd3585958..f41f27b6df 100644
--- a/cpp/src/tests/Address.cpp
+++ b/cpp/src/tests/Address.cpp
@@ -119,17 +119,6 @@ QPID_AUTO_TEST_CASE(testParseQuotedNameAndSubject)
BOOST_CHECK_EQUAL(std::string("my subject with ; in it"), address.getSubject());
}
-QPID_AUTO_TEST_CASE(testParseOptionsWithEmptyStringAsValue)
-{
- Address address("my-topic; {a:'', x:101}");
- BOOST_CHECK_EQUAL(std::string("my-topic"), address.getName());
- Variant a = address.getOptions()["a"];
- BOOST_CHECK_EQUAL(VAR_STRING, a.getType());
- std::string aVal = a;
- BOOST_CHECK(aVal.size() == 0);
- BOOST_CHECK_EQUAL((uint16_t) 101, address.getOptions()["x"].asInt64());
-}
-
QPID_AUTO_TEST_SUITE_END()
}}
diff --git a/cpp/src/tests/BrokerFixture.h b/cpp/src/tests/BrokerFixture.h
index 92c6d22b57..672d954572 100644
--- a/cpp/src/tests/BrokerFixture.h
+++ b/cpp/src/tests/BrokerFixture.h
@@ -22,6 +22,8 @@
*
*/
+#include "SocketProxy.h"
+
#include "qpid/broker/Broker.h"
#include "qpid/client/Connection.h"
#include "qpid/client/ConnectionImpl.h"
@@ -69,15 +71,16 @@ struct BrokerFixture : private boost::noncopyable {
brokerThread = qpid::sys::Thread(*broker);
};
- void shutdownBroker() {
- if (broker) {
- broker->shutdown();
- brokerThread.join();
- broker = BrokerPtr();
- }
+ void shutdownBroker()
+ {
+ broker->shutdown();
+ broker = BrokerPtr();
}
- ~BrokerFixture() { shutdownBroker(); }
+ ~BrokerFixture() {
+ if (broker) broker->shutdown();
+ brokerThread.join();
+ }
/** Open a connection to the broker. */
void open(qpid::client::Connection& c) {
@@ -94,6 +97,20 @@ struct LocalConnection : public qpid::client::Connection {
~LocalConnection() { close(); }
};
+/** A local client connection via a socket proxy. */
+struct ProxyConnection : public qpid::client::Connection {
+ SocketProxy proxy;
+ ProxyConnection(int brokerPort) : proxy(brokerPort) {
+ open("localhost", proxy.getPort());
+ }
+ ProxyConnection(const qpid::client::ConnectionSettings& s) : proxy(s.port) {
+ qpid::client::ConnectionSettings proxySettings(s);
+ proxySettings.port = proxy.getPort();
+ open(proxySettings);
+ }
+ ~ProxyConnection() { close(); }
+};
+
/** Convenience class to create and open a connection and session
* and some related useful objects.
*/
@@ -130,6 +147,7 @@ struct SessionFixtureT : BrokerFixture, ClientT<ConnectionType,SessionType> {
};
typedef SessionFixtureT<LocalConnection> SessionFixture;
+typedef SessionFixtureT<ProxyConnection> ProxySessionFixture;
}} // namespace qpid::tests
diff --git a/cpp/src/tests/BrokerMgmtAgent.cpp b/cpp/src/tests/BrokerMgmtAgent.cpp
index 1d5289dc90..d0c6668b72 100644
--- a/cpp/src/tests/BrokerMgmtAgent.cpp
+++ b/cpp/src/tests/BrokerMgmtAgent.cpp
@@ -599,12 +599,13 @@ namespace qpid {
// populate the agent with multiple test objects
const size_t objCount = 50;
std::vector<TestManageable *> tmv;
+ uint32_t objLen;
for (size_t i = 0; i < objCount; i++) {
std::stringstream key;
key << "testobj-" << i;
TestManageable *tm = new TestManageable(agent, key.str());
- (void) tm->GetManagementObject()->writePropertiesSize();
+ objLen = tm->GetManagementObject()->writePropertiesSize();
agent->addObject(tm->GetManagementObject(), key.str());
tmv.push_back(tm);
}
diff --git a/cpp/src/tests/BrokerOptions.cpp b/cpp/src/tests/BrokerOptions.cpp
deleted file mode 100644
index b36d96916a..0000000000
--- a/cpp/src/tests/BrokerOptions.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *
- * Copyright (c) 2006 The Apache Software Foundation
- *
- * 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.
- *
- */
-
-/** Unit tests for various broker configuration options **/
-
-#include "unit_test.h"
-#include "test_tools.h"
-#include "MessagingFixture.h"
-
-#include "qpid/messaging/Address.h"
-#include "qpid/messaging/Connection.h"
-#include "qpid/messaging/Message.h"
-#include "qpid/messaging/Receiver.h"
-#include "qpid/messaging/Sender.h"
-#include "qpid/messaging/Session.h"
-
-namespace qpid {
-namespace tests {
-
-QPID_AUTO_TEST_SUITE(BrokerOptionsTestSuite)
-
-using namespace qpid::broker;
-using namespace qpid::messaging;
-using namespace qpid::types;
-using namespace qpid;
-
-QPID_AUTO_TEST_CASE(testDisabledTimestamp)
-{
- // by default, there should be no timestamp added by the broker
- MessagingFixture fix;
-
- Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}");
- messaging::Message msg("hi");
- sender.send(msg);
-
- Receiver receiver = fix.session.createReceiver("test-q");
- messaging::Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE));
- Variant::Map props = in.getProperties();
- BOOST_CHECK(props.find("x-amqp-0-10.timestamp") == props.end());
-}
-
-QPID_AUTO_TEST_CASE(testEnabledTimestamp)
-{
- // when enabled, the 0.10 timestamp is added by the broker
- Broker::Options opts;
- opts.timestampRcvMsgs = true;
- MessagingFixture fix(opts, true);
-
- Sender sender = fix.session.createSender("test-q; {create:always, delete:sender}");
- messaging::Message msg("one");
- sender.send(msg);
-
- Receiver receiver = fix.session.createReceiver("test-q");
- messaging::Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::IMMEDIATE));
- Variant::Map props = in.getProperties();
- BOOST_CHECK(props.find("x-amqp-0-10.timestamp") != props.end());
- BOOST_CHECK(props["x-amqp-0-10.timestamp"]);
-}
-
-QPID_AUTO_TEST_SUITE_END()
-
-}}
diff --git a/cpp/src/tests/CMakeLists.txt b/cpp/src/tests/CMakeLists.txt
index 7d781e5eb3..3b3b232671 100644
--- a/cpp/src/tests/CMakeLists.txt
+++ b/cpp/src/tests/CMakeLists.txt
@@ -107,6 +107,7 @@ set(unit_tests_to_build
MessagingSessionTests
SequenceSet
StringUtils
+ IncompleteMessageList
RangeSet
AtomicValue
QueueTest
@@ -118,7 +119,6 @@ set(unit_tests_to_build
MessageTest
QueueRegistryTest
QueuePolicyTest
- QueueFlowLimitTest
FramingTest
HeaderTest
SequenceNumberTest
@@ -264,19 +264,6 @@ add_executable (qpid-send qpid-send.cpp Statistics.cpp ${platform_test_additions
target_link_libraries (qpid-send qpidmessaging)
remember_location(qpid-send)
-add_executable (qpid-ping qpid-ping.cpp ${platform_test_additions})
-target_link_libraries (qpid-ping qpidclient)
-remember_location(qpid-ping)
-
-add_executable (datagen datagen.cpp ${platform_test_additions})
-target_link_libraries (datagen qpidclient)
-remember_location(datagen)
-
-add_executable (msg_group_test msg_group_test.cpp ${platform_test_additions})
-target_link_libraries (msg_group_test qpidmessaging)
-remember_location(msg_group_test)
-
-
# qpid-perftest and qpid-latency-test are generally useful so install them
install (TARGETS qpid-perftest qpid-latency-test RUNTIME
DESTINATION ${QPID_INSTALL_BINDIR})
@@ -291,7 +278,7 @@ set(test_wrap ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_test${test_script_suffix}
add_test (unit_test ${test_wrap} ${unit_test_LOCATION})
add_test (start_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/start_broker${test_script_suffix})
-add_test (qpid-client-test ${test_wrap} ${qpid-client-test_LOCATION})
+add_test (qpid-client-test ${test_wrap} ${qpid-client_test_LOCATION})
add_test (quick_perftest ${test_wrap} ${qpid-perftest_LOCATION} --summary --count 100)
add_test (quick_topictest ${test_wrap} ${CMAKE_CURRENT_SOURCE_DIR}/quick_topictest${test_script_suffix})
add_test (quick_txtest ${test_wrap} ${qpid-txtest_LOCATION} --queues 4 --tx-count 10 --quiet)
@@ -301,7 +288,6 @@ if (PYTHON_EXECUTABLE)
endif (PYTHON_EXECUTABLE)
add_test (stop_broker ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/stop_broker${test_script_suffix})
if (PYTHON_EXECUTABLE)
- add_test (ipv6_test ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/ipv6_test${test_script_suffix})
add_test (federation_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_federation_tests${test_script_suffix})
if (BUILD_ACL)
add_test (acl_tests ${shell} ${CMAKE_CURRENT_SOURCE_DIR}/run_acl_tests${test_script_suffix})
diff --git a/cpp/src/tests/ClientSessionTest.cpp b/cpp/src/tests/ClientSessionTest.cpp
index 30441cd03c..939f8f2b88 100644
--- a/cpp/src/tests/ClientSessionTest.cpp
+++ b/cpp/src/tests/ClientSessionTest.cpp
@@ -102,9 +102,9 @@ struct SimpleListener : public MessageListener
}
};
-struct ClientSessionFixture : public SessionFixture
+struct ClientSessionFixture : public ProxySessionFixture
{
- ClientSessionFixture(Broker::Options opts = Broker::Options()) : SessionFixture(opts) {
+ ClientSessionFixture(Broker::Options opts = Broker::Options()) : ProxySessionFixture(opts) {
session.queueDeclare(arg::queue="my-queue");
}
};
@@ -150,6 +150,16 @@ QPID_AUTO_TEST_CASE(testDispatcherThread)
BOOST_CHECK_EQUAL(boost::lexical_cast<string>(i), listener.messages[i].getData());
}
+// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented.
+void testSuspend0Timeout() {
+ ClientSessionFixture fix;
+ fix.session.suspend(); // session has 0 timeout.
+ try {
+ fix.connection.resume(fix.session);
+ BOOST_FAIL("Expected InvalidArgumentException.");
+ } catch(const InternalErrorException&) {}
+}
+
QPID_AUTO_TEST_CASE(testUseSuspendedError)
{
ClientSessionFixture fix;
@@ -161,6 +171,18 @@ QPID_AUTO_TEST_CASE(testUseSuspendedError)
} catch(const NotAttachedException&) {}
}
+// FIXME aconway 2009-06-17: test for unimplemented feature, enable when implemented.
+void testSuspendResume() {
+ ClientSessionFixture fix;
+ fix.session.timeout(60);
+ fix.session.suspend();
+ // Make sure we are still subscribed after resume.
+ fix.connection.resume(fix.session);
+ fix.session.messageTransfer(arg::content=Message("my-message", "my-queue"));
+ BOOST_CHECK_EQUAL("my-message", fix.subs.get("my-queue", TIME_SEC).getData());
+}
+
+
QPID_AUTO_TEST_CASE(testSendToSelf) {
ClientSessionFixture fix;
SimpleListener mylistener;
@@ -249,12 +271,8 @@ QPID_AUTO_TEST_CASE(testOpenFailure) {
QPID_AUTO_TEST_CASE(testPeriodicExpiration) {
Broker::Options opts;
opts.queueCleanInterval = 1;
- opts.queueFlowStopRatio = 0;
- opts.queueFlowResumeRatio = 0;
ClientSessionFixture fix(opts);
- FieldTable args;
- args.setInt("qpid.max_count",10);
- fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
+ fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
for (uint i = 0; i < 10; i++) {
Message m((boost::format("Message_%1%") % (i+1)).str(), "my-queue");
@@ -265,7 +283,6 @@ QPID_AUTO_TEST_CASE(testPeriodicExpiration) {
BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 10u);
qpid::sys::sleep(2);
BOOST_CHECK_EQUAL(fix.session.queueQuery(string("my-queue")).getMessageCount(), 5u);
- fix.session.messageTransfer(arg::content=Message("Message_11", "my-queue"));//ensure policy is also updated
}
QPID_AUTO_TEST_CASE(testExpirationOnPop) {
diff --git a/cpp/src/tests/ExchangeTest.cpp b/cpp/src/tests/ExchangeTest.cpp
index fe72f42a46..88a1cd99c2 100644
--- a/cpp/src/tests/ExchangeTest.cpp
+++ b/cpp/src/tests/ExchangeTest.cpp
@@ -253,7 +253,7 @@ QPID_AUTO_TEST_CASE(testIVEOption)
TopicExchange topic ("topic1", false, args);
intrusive_ptr<Message> msg1 = cmessage("direct1", "abc");
- msg1->insertCustomProperty("a", "abc");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString("a", "abc");
DeliverableMessage dmsg1(msg1);
FieldTable args2;
diff --git a/cpp/src/tests/ForkedBroker.cpp b/cpp/src/tests/ForkedBroker.cpp
index 10674b5175..53eaa7e1ce 100644
--- a/cpp/src/tests/ForkedBroker.cpp
+++ b/cpp/src/tests/ForkedBroker.cpp
@@ -68,7 +68,8 @@ ForkedBroker::~ForkedBroker() {
}
if (!dataDir.empty())
{
- (void) ::system(("rm -rf "+dataDir).c_str());
+ int unused_ret; // Suppress warnings about ignoring return value.
+ unused_ret = ::system(("rm -rf "+dataDir).c_str());
}
}
diff --git a/cpp/src/tests/IncompleteMessageList.cpp b/cpp/src/tests/IncompleteMessageList.cpp
new file mode 100644
index 0000000000..10782572e5
--- /dev/null
+++ b/cpp/src/tests/IncompleteMessageList.cpp
@@ -0,0 +1,134 @@
+/*
+ *
+ * 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 <iostream>
+#include <sstream>
+#include "qpid/broker/Message.h"
+#include "qpid/broker/NullMessageStore.h"
+#include "qpid/broker/Queue.h"
+#include "qpid/broker/IncompleteMessageList.h"
+
+#include "unit_test.h"
+
+namespace qpid {
+namespace tests {
+
+QPID_AUTO_TEST_SUITE(IncompleteMessageListTestSuite)
+
+using namespace qpid::broker;
+using namespace qpid::framing;
+
+struct Checker
+{
+ std::list<SequenceNumber> ids;
+
+ Checker() { }
+
+ Checker(uint start, uint end) {
+ for (uint i = start; i <= end; i++) {
+ ids.push_back(i);
+ }
+ }
+
+ Checker& expect(const SequenceNumber& id) {
+ ids.push_back(id);
+ return *this;
+ }
+
+ void operator()(boost::intrusive_ptr<Message> msg) {
+ BOOST_CHECK(!ids.empty());
+ BOOST_CHECK_EQUAL(msg->getCommandId(), ids.front());
+ ids.pop_front();
+ }
+};
+
+QPID_AUTO_TEST_CASE(testProcessSimple)
+{
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ }
+ //process and ensure they are all passed to completion listener
+ list.process(Checker(1, 5), false);
+ //process again and ensure none are resent to listener
+ list.process(Checker(), false);
+}
+
+QPID_AUTO_TEST_CASE(testProcessWithIncomplete)
+{
+ Queue::shared_ptr queue;
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ boost::intrusive_ptr<Message> middle;
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ if (i == 2) {
+ //mark a message in the middle as incomplete
+ msg->enqueueAsync(queue, 0);
+ middle = msg;
+ }
+ }
+ //process and ensure only message upto incomplete message are passed to listener
+ list.process(Checker(1, 2), false);
+ //mark message complete and re-process to get remaining messages sent to listener
+ middle->enqueueComplete();
+ list.process(Checker(3, 5), false);
+}
+
+
+struct MockStore : public NullMessageStore
+{
+ Queue::shared_ptr queue;
+ boost::intrusive_ptr<Message> msg;
+
+ void flush(const qpid::broker::PersistableQueue& q) {
+ BOOST_CHECK_EQUAL(queue.get(), &q);
+ msg->enqueueComplete();
+ }
+};
+
+QPID_AUTO_TEST_CASE(testSyncProcessWithIncomplete)
+{
+ IncompleteMessageList list;
+ SequenceNumber counter(1);
+ MockStore store;
+ store.queue = Queue::shared_ptr(new Queue("mock-queue", false, &store));
+ //fill up list with messages
+ for (int i = 0; i < 5; i++) {
+ boost::intrusive_ptr<Message> msg(new Message(counter++));
+ list.add(msg);
+ if (i == 2) {
+ //mark a message in the middle as incomplete
+ msg->enqueueAsync(store.queue, &store);
+ store.msg = msg;
+ }
+ }
+ //process with sync bit specified and ensure that all messages are passed to listener
+ list.process(Checker(1, 5), true);
+}
+
+QPID_AUTO_TEST_SUITE_END()
+
+}} // namespace qpid::tests
diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am
index 3c9ca1b70f..07405bcd8f 100644
--- a/cpp/src/tests/Makefile.am
+++ b/cpp/src/tests/Makefile.am
@@ -75,7 +75,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
MessagingThreadTests.cpp \
MessagingFixture.h \
ClientSessionTest.cpp \
- BrokerFixture.h \
+ BrokerFixture.h SocketProxy.h \
exception_test.cpp \
RefCounted.cpp \
SessionState.cpp logging.cpp \
@@ -87,6 +87,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
InlineVector.cpp \
SequenceSet.cpp \
StringUtils.cpp \
+ IncompleteMessageList.cpp \
RangeSet.cpp \
AtomicValue.cpp \
QueueTest.cpp \
@@ -98,7 +99,6 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
MessageTest.cpp \
QueueRegistryTest.cpp \
QueuePolicyTest.cpp \
- QueueFlowLimitTest.cpp \
FramingTest.cpp \
HeaderTest.cpp \
SequenceNumberTest.cpp \
@@ -124,8 +124,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \
Variant.cpp \
Address.cpp \
ClientMessage.cpp \
- Qmf2.cpp \
- BrokerOptions.cpp
+ Qmf2.cpp
if HAVE_XML
unit_test_SOURCES+= XmlClientSessionTest.cpp
@@ -287,27 +286,31 @@ check_PROGRAMS+=datagen
datagen_SOURCES=datagen.cpp
datagen_LDADD=$(lib_common) $(lib_client)
+check_PROGRAMS+=qrsh_server
+qrsh_server_SOURCES=qrsh_server.cpp
+qrsh_server_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh_run
+qrsh_run_SOURCES=qrsh_run.cpp
+qrsh_run_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh
+qrsh_SOURCES=qrsh.cpp
+qrsh_LDADD=$(lib_client)
+
check_PROGRAMS+=qpid-stream
qpid_stream_INCLUDES=$(PUBLIC_INCLUDES)
qpid_stream_SOURCES=qpid-stream.cpp
qpid_stream_LDADD=$(lib_messaging)
-check_PROGRAMS+=msg_group_test
-msg_group_test_INCLUDES=$(PUBLIC_INCLUDES)
-msg_group_test_SOURCES=msg_group_test.cpp
-msg_group_test_LDADD=$(lib_messaging)
-
TESTS_ENVIRONMENT = \
VALGRIND=$(VALGRIND) \
LIBTOOL="$(LIBTOOL)" \
QPID_DATA_DIR= \
$(srcdir)/run_test
-system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest \
- run_msg_group_tests
-TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_federation_sys_tests \
- run_acl_tests run_cli_tests replication_test dynamic_log_level_test \
- run_queue_flow_limit_tests ipv6_test
+system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest
+TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_acl_tests run_cli_tests replication_test dynamic_log_level_test
EXTRA_DIST += \
run_test vg_check \
@@ -322,8 +325,6 @@ EXTRA_DIST += \
config.null \
ais_check \
run_federation_tests \
- run_federation_sys_tests \
- run_long_federation_sys_tests \
run_cli_tests \
run_acl_tests \
.valgrind.supp \
@@ -348,10 +349,7 @@ EXTRA_DIST += \
run_test.ps1 \
start_broker.ps1 \
stop_broker.ps1 \
- topictest.ps1 \
- run_queue_flow_limit_tests \
- run_msg_group_tests \
- ipv6_test
+ topictest.ps1
check_LTLIBRARIES += libdlclose_noop.la
libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
@@ -362,11 +360,7 @@ CLEANFILES+=valgrind.out *.log *.vglog* dummy_test qpidd.port $(unit_wrappers)
# Longer running stability tests, not run by default check: target.
# Not run under valgrind, too slow
-LONG_TESTS+=start_broker \
- fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test \
- run_msg_group_tests_soak \
- stop_broker \
- run_long_federation_sys_tests \
+LONG_TESTS+=start_broker fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test stop_broker \
run_failover_soak reliable_replication_test \
federated_cluster_test_with_node_failure
@@ -378,8 +372,7 @@ EXTRA_DIST+= \
run_failover_soak \
reliable_replication_test \
federated_cluster_test_with_node_failure \
- sasl_test_setup.sh \
- run_msg_group_tests_soak
+ sasl_test_setup.sh
check-long:
$(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND=
diff --git a/cpp/src/tests/MessageReplayTracker.cpp b/cpp/src/tests/MessageReplayTracker.cpp
index e35f673683..3d79ee53c2 100644
--- a/cpp/src/tests/MessageReplayTracker.cpp
+++ b/cpp/src/tests/MessageReplayTracker.cpp
@@ -51,7 +51,7 @@ class ReplayBufferChecker
QPID_AUTO_TEST_CASE(testReplay)
{
- SessionFixture fix;
+ ProxySessionFixture fix;
fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
MessageReplayTracker tracker(10);
@@ -77,7 +77,7 @@ QPID_AUTO_TEST_CASE(testReplay)
QPID_AUTO_TEST_CASE(testCheckCompletion)
{
- SessionFixture fix;
+ ProxySessionFixture fix;
fix.session.queueDeclare(arg::queue="my-queue", arg::exclusive=true, arg::autoDelete=true);
MessageReplayTracker tracker(10);
diff --git a/cpp/src/tests/MessagingFixture.h b/cpp/src/tests/MessagingFixture.h
index 2312a87e9d..715de09bad 100644
--- a/cpp/src/tests/MessagingFixture.h
+++ b/cpp/src/tests/MessagingFixture.h
@@ -27,19 +27,15 @@
#include "qpid/client/Connection.h"
#include "qpid/client/Session.h"
#include "qpid/framing/Uuid.h"
-#include "qpid/messaging/Address.h"
#include "qpid/messaging/Connection.h"
#include "qpid/messaging/Session.h"
#include "qpid/messaging/Sender.h"
#include "qpid/messaging/Receiver.h"
#include "qpid/messaging/Message.h"
-#include "qpid/types/Variant.h"
namespace qpid {
namespace tests {
-using qpid::types::Variant;
-
struct BrokerAdmin
{
qpid::client::Connection connection;
@@ -227,119 +223,6 @@ inline void receive(messaging::Receiver& receiver, uint count = 1, uint start =
}
}
-
-class MethodInvoker
-{
- public:
- MethodInvoker(messaging::Session& session) : replyTo("#; {create:always, node:{x-declare:{auto-delete:true}}}"),
- sender(session.createSender("qmf.default.direct/broker")),
- receiver(session.createReceiver(replyTo)) {}
-
- void createExchange(const std::string& name, const std::string& type, bool durable=false)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="exchange";
- params["properties"] = Variant::Map();
- params["properties"].asMap()["exchange-type"] = type;
- params["properties"].asMap()["durable"] = durable;
- methodRequest("create", params);
- }
-
- void deleteExchange(const std::string& name)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="exchange";
- methodRequest("delete", params);
- }
-
- void createQueue(const std::string& name, bool durable=false, bool autodelete=false,
- const Variant::Map& options=Variant::Map())
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="queue";
- params["properties"] = options;
- params["properties"].asMap()["durable"] = durable;
- params["properties"].asMap()["auto-delete"] = autodelete;
- methodRequest("create", params);
- }
-
- void deleteQueue(const std::string& name)
- {
- Variant::Map params;
- params["name"]=name;
- params["type"]="queue";
- methodRequest("delete", params);
- }
-
- void bind(const std::string& exchange, const std::string& queue, const std::string& key,
- const Variant::Map& options=Variant::Map())
- {
- Variant::Map params;
- params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str();
- params["type"]="binding";
- params["properties"] = options;
- methodRequest("create", params);
- }
-
- void unbind(const std::string& exchange, const std::string& queue, const std::string& key)
- {
- Variant::Map params;
- params["name"]=(boost::format("%1%/%2%/%3%") % (exchange) % (queue) % (key)).str();
- params["type"]="binding";
- methodRequest("delete", params);
- }
-
- void methodRequest(const std::string& method, const Variant::Map& inParams, Variant::Map* outParams = 0)
- {
- Variant::Map content;
- Variant::Map objectId;
- objectId["_object_name"] = "org.apache.qpid.broker:broker:amqp-broker";
- content["_object_id"] = objectId;
- content["_method_name"] = method;
- content["_arguments"] = inParams;
-
- messaging::Message request;
- request.setReplyTo(replyTo);
- request.getProperties()["x-amqp-0-10.app-id"] = "qmf2";
- request.getProperties()["qmf.opcode"] = "_method_request";
- encode(content, request);
-
- sender.send(request);
-
- messaging::Message response;
- if (receiver.fetch(response, messaging::Duration::SECOND*5)) {
- if (response.getProperties()["x-amqp-0-10.app-id"] == "qmf2") {
- std::string opcode = response.getProperties()["qmf.opcode"];
- if (opcode == "_method_response") {
- if (outParams) {
- Variant::Map m;
- decode(response, m);
- *outParams = m["_arguments"].asMap();
- }
- } else if (opcode == "_exception") {
- Variant::Map m;
- decode(response, m);
- throw Exception(QPID_MSG("Error: " << m["_values"]));
- } else {
- throw Exception(QPID_MSG("Invalid response received, unexpected opcode: " << opcode));
- }
- } else {
- throw Exception(QPID_MSG("Invalid response received, not a qmfv2 message: app-id="
- << response.getProperties()["x-amqp-0-10.app-id"]));
- }
- } else {
- throw Exception(QPID_MSG("No response received"));
- }
- }
- private:
- messaging::Address replyTo;
- messaging::Sender sender;
- messaging::Receiver receiver;
-};
-
}} // namespace qpid::tests
#endif /*!TESTS_MESSAGINGFIXTURE_H*/
diff --git a/cpp/src/tests/MessagingSessionTests.cpp b/cpp/src/tests/MessagingSessionTests.cpp
index 9d5db84bb4..991ec847bf 100644
--- a/cpp/src/tests/MessagingSessionTests.cpp
+++ b/cpp/src/tests/MessagingSessionTests.cpp
@@ -611,28 +611,6 @@ QPID_AUTO_TEST_CASE(testAssertPolicyQueue)
fix.admin.deleteQueue("q");
}
-QPID_AUTO_TEST_CASE(testAssertExchangeOption)
-{
- MessagingFixture fix;
- std::string a1 = "e; {create:always, assert:always, node:{type:topic, x-declare:{type:direct, arguments:{qpid.msg_sequence:True}}}}";
- Sender s1 = fix.session.createSender(a1);
- s1.close();
- Receiver r1 = fix.session.createReceiver(a1);
- r1.close();
-
- std::string a2 = "e; {assert:receiver, node:{type:topic, x-declare:{type:fanout, arguments:{qpid.msg_sequence:True}}}}";
- Sender s2 = fix.session.createSender(a2);
- s2.close();
- BOOST_CHECK_THROW(fix.session.createReceiver(a2), qpid::messaging::AssertionFailed);
-
- std::string a3 = "e; {assert:sender, node:{x-declare:{arguments:{qpid.msg_sequence:False}}}}";
- BOOST_CHECK_THROW(fix.session.createSender(a3), qpid::messaging::AssertionFailed);
- Receiver r3 = fix.session.createReceiver(a3);
- r3.close();
-
- fix.admin.deleteExchange("e");
-}
-
QPID_AUTO_TEST_CASE(testGetSender)
{
QueueFixture fix;
@@ -912,212 +890,6 @@ QPID_AUTO_TEST_CASE(testAcknowledge)
BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE));
}
-QPID_AUTO_TEST_CASE(testQmfCreateAndDelete)
-{
- MessagingFixture fix(Broker::Options(), true/*enable management*/);
- MethodInvoker control(fix.session);
- control.createQueue("my-queue");
- control.createExchange("my-exchange", "topic");
- control.bind("my-exchange", "my-queue", "subject1");
-
- Sender sender = fix.session.createSender("my-exchange");
- Receiver receiver = fix.session.createReceiver("my-queue");
- Message out;
- out.setSubject("subject1");
- out.setContent("one");
- sender.send(out);
- Message in;
- BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5));
- BOOST_CHECK_EQUAL(out.getContent(), in.getContent());
- control.unbind("my-exchange", "my-queue", "subject1");
- control.bind("my-exchange", "my-queue", "subject2");
-
- out.setContent("two");
- sender.send(out);//should be dropped
-
- out.setSubject("subject2");
- out.setContent("three");
- sender.send(out);//should not be dropped
-
- BOOST_CHECK(receiver.fetch(in, Duration::SECOND*5));
- BOOST_CHECK_EQUAL(out.getContent(), in.getContent());
- BOOST_CHECK(!receiver.fetch(in, Duration::IMMEDIATE));
- sender.close();
- receiver.close();
-
- control.deleteExchange("my-exchange");
- messaging::Session other = fix.connection.createSession();
- {
- ScopedSuppressLogging sl;
- BOOST_CHECK_THROW(other.createSender("my-exchange"), qpid::messaging::NotFound);
- }
- control.deleteQueue("my-queue");
- other = fix.connection.createSession();
- {
- ScopedSuppressLogging sl;
- BOOST_CHECK_THROW(other.createReceiver("my-queue"), qpid::messaging::NotFound);
- }
-}
-
-QPID_AUTO_TEST_CASE(testRejectAndCredit)
-{
- //Ensure credit is restored on completing rejected messages
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- Receiver receiver = fix.session.createReceiver(fix.queue);
-
- const uint count(10);
- receiver.setCapacity(count);
- for (uint i = 0; i < count; i++) {
- sender.send(Message((boost::format("Message_%1%") % (i+1)).str()));
- }
-
- Message in;
- for (uint i = 0; i < count; ++i) {
- if (receiver.fetch(in, Duration::SECOND)) {
- BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+1)).str());
- fix.session.reject(in);
- } else {
- BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+1)).str());
- break;
- }
- }
- //send another batch of messages
- for (uint i = 0; i < count; i++) {
- sender.send(Message((boost::format("Message_%1%") % (i+count)).str()));
- }
-
- for (uint i = 0; i < count; ++i) {
- if (receiver.fetch(in, Duration::SECOND)) {
- BOOST_CHECK_EQUAL(in.getContent(), (boost::format("Message_%1%") % (i+count)).str());
- } else {
- BOOST_FAIL((boost::format("Message_%1% not received as expected") % (i+count)).str());
- break;
- }
- }
- fix.session.acknowledge();
- receiver.close();
- sender.close();
-}
-
-QPID_AUTO_TEST_CASE(testTtlForever)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- Message out("I want to live forever!");
- out.setTtl(Duration::FOREVER);
- sender.send(out, true);
- Receiver receiver = fix.session.createReceiver(fix.queue);
- Message in = receiver.fetch(Duration::IMMEDIATE);
- fix.session.acknowledge();
- BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
- BOOST_CHECK(in.getTtl() == Duration::FOREVER);
-}
-
-QPID_AUTO_TEST_CASE(testExclusiveTopicSubscriber)
-{
- TopicFixture fix;
- std::string address = (boost::format("%1%; { link: { name: 'my-subscription', x-declare: { auto-delete: true, exclusive: true }}}") % fix.topic).str();
- Sender sender = fix.session.createSender(fix.topic);
- Receiver receiver1 = fix.session.createReceiver(address);
- {
- ScopedSuppressLogging sl;
- try {
- fix.session.createReceiver(address);
- fix.session.sync();
- BOOST_FAIL("Expected exception.");
- } catch (const MessagingException& /*e*/) {}
- }
-}
-
-QPID_AUTO_TEST_CASE(testNonExclusiveSubscriber)
-{
- TopicFixture fix;
- std::string address = (boost::format("%1%; {node:{type:topic}, link:{name:'my-subscription', x-declare:{auto-delete:true, exclusive:false}}}") % fix.topic).str();
- Receiver receiver1 = fix.session.createReceiver(address);
- Receiver receiver2 = fix.session.createReceiver(address);
- Sender sender = fix.session.createSender(fix.topic);
- sender.send(Message("one"), true);
- Message in = receiver1.fetch(Duration::IMMEDIATE);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("one"));
- sender.send(Message("two"), true);
- in = receiver2.fetch(Duration::IMMEDIATE);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("two"));
- fix.session.acknowledge();
-}
-
-QPID_AUTO_TEST_CASE(testAcknowledgeUpTo)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender(fix.queue);
- const uint count(20);
- for (uint i = 0; i < count; ++i) {
- sender.send(Message((boost::format("Message_%1%") % (i+1)).str()));
- }
-
- Session other = fix.connection.createSession();
- Receiver receiver = other.createReceiver(fix.queue);
- std::vector<Message> messages;
- for (uint i = 0; i < count; ++i) {
- Message msg = receiver.fetch();
- BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1)).str());
- messages.push_back(msg);
- }
- const uint batch = 10;
- other.acknowledgeUpTo(messages[batch-1]);//acknowledge first 10 messages only
-
- messages.clear();
- other.sync();
- other.close();
-
- other = fix.connection.createSession();
- receiver = other.createReceiver(fix.queue);
- Message msg;
- for (uint i = 0; i < (count-batch); ++i) {
- msg = receiver.fetch();
- BOOST_CHECK_EQUAL(msg.getContent(), (boost::format("Message_%1%") % (i+1+batch)).str());
- }
- other.acknowledgeUpTo(msg);
- other.sync();
- other.close();
-
- Message m;
- //check queue is empty
- BOOST_CHECK(!fix.session.createReceiver(fix.queue).fetch(m, Duration::IMMEDIATE));
-}
-
-QPID_AUTO_TEST_CASE(testCreateBindingsOnStandardExchange)
-{
- QueueFixture fix;
- Sender sender = fix.session.createSender((boost::format("amq.direct; {create:always, node:{type:topic, x-bindings:[{queue:%1%, key:my-subject}]}}") % fix.queue).str());
- Message out("test-message");
- out.setSubject("my-subject");
- sender.send(out);
- Receiver receiver = fix.session.createReceiver(fix.queue);
- Message in = receiver.fetch(Duration::SECOND * 5);
- fix.session.acknowledge();
- BOOST_CHECK_EQUAL(in.getContent(), out.getContent());
- BOOST_CHECK_EQUAL(in.getSubject(), out.getSubject());
-}
-
-QPID_AUTO_TEST_CASE(testUnsubscribeOnClose)
-{
- MessagingFixture fix;
- Sender sender = fix.session.createSender("my-exchange/my-subject; {create: always, delete:sender, node:{type:topic, x-declare:{alternate-exchange:amq.fanout}}}");
- Receiver receiver = fix.session.createReceiver("my-exchange/my-subject");
- Receiver deadletters = fix.session.createReceiver("amq.fanout");
-
- sender.send(Message("first"));
- Message in = receiver.fetch(Duration::SECOND);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("first"));
- fix.session.acknowledge();
- receiver.close();
- sender.send(Message("second"));
- in = deadletters.fetch(Duration::SECOND);
- BOOST_CHECK_EQUAL(in.getContent(), std::string("second"));
- fix.session.acknowledge();
-}
-
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/cpp/src/tests/Qmf2.cpp b/cpp/src/tests/Qmf2.cpp
index bc263d5c6d..66c774accd 100644
--- a/cpp/src/tests/Qmf2.cpp
+++ b/cpp/src/tests/Qmf2.cpp
@@ -23,36 +23,12 @@
#include "qmf/QueryImpl.h"
#include "qmf/SchemaImpl.h"
#include "qmf/exceptions.h"
-#include "qpid/messaging/Connection.h"
-#include "qmf/PosixEventNotifierImpl.h"
-#include "qmf/AgentSession.h"
-#include "qmf/AgentSessionImpl.h"
-#include "qmf/ConsoleSession.h"
-#include "qmf/ConsoleSessionImpl.h"
+
#include "unit_test.h"
-using namespace std;
using namespace qpid::types;
-using namespace qpid::messaging;
using namespace qmf;
-bool isReadable(int fd)
-{
- fd_set rfds;
- struct timeval tv;
- int nfds, result;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- nfds = fd + 1;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- result = select(nfds, &rfds, NULL, NULL, &tv);
-
- return result > 0;
-}
-
namespace qpid {
namespace tests {
@@ -339,84 +315,6 @@ QPID_AUTO_TEST_CASE(testSchema)
BOOST_CHECK_THROW(method.getArgument(3), QmfException);
}
-QPID_AUTO_TEST_CASE(testAgentSessionEventListener)
-{
- Connection connection("localhost");
- AgentSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- AgentSessionImpl& sessionImpl = AgentSessionImplAccess::get(session);
-
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
-}
-
-QPID_AUTO_TEST_CASE(testConsoleSessionEventListener)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session);
-
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
-}
-
-QPID_AUTO_TEST_CASE(testGetHandle)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
-
- BOOST_CHECK(notifier.getHandle() > 0);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadableToFalse)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- PosixEventNotifierImplAccess::get(notifier).setReadable(false);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(!readable);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadable)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- PosixEventNotifierImplAccess::get(notifier).setReadable(true);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(readable);
-}
-
-QPID_AUTO_TEST_CASE(testSetReadableMultiple)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- posix::EventNotifier notifier(session);
- for (int i = 0; i < 15; i++)
- PosixEventNotifierImplAccess::get(notifier).setReadable(true);
- PosixEventNotifierImplAccess::get(notifier).setReadable(false);
-
- bool readable(isReadable(notifier.getHandle()));
- BOOST_CHECK(!readable);
-}
-
-QPID_AUTO_TEST_CASE(testDeleteNotifier)
-{
- Connection connection("localhost");
- ConsoleSession session(connection, "");
- ConsoleSessionImpl& sessionImpl = ConsoleSessionImplAccess::get(session);
- {
- posix::EventNotifier notifier(session);
- BOOST_CHECK(sessionImpl.getEventNotifier() != 0);
- }
- BOOST_CHECK(sessionImpl.getEventNotifier() == 0);
-}
-
QPID_AUTO_TEST_SUITE_END()
}} // namespace qpid::tests
diff --git a/cpp/src/tests/QueueEvents.cpp b/cpp/src/tests/QueueEvents.cpp
index cea8bbf0db..bd18fa45fb 100644
--- a/cpp/src/tests/QueueEvents.cpp
+++ b/cpp/src/tests/QueueEvents.cpp
@@ -147,7 +147,7 @@ struct EventRecorder
QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing)
{
- SessionFixture fixture;
+ ProxySessionFixture fixture;
//register dummy event listener to broker
EventRecorder listener;
fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1));
@@ -194,7 +194,7 @@ QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing)
QPID_AUTO_TEST_CASE(testSystemLevelEventProcessing_enqueuesOnly)
{
- SessionFixture fixture;
+ ProxySessionFixture fixture;
//register dummy event listener to broker
EventRecorder listener;
fixture.broker->getQueueEvents().registerListener("recorder", boost::bind(&EventRecorder::handle, &listener, _1));
diff --git a/cpp/src/tests/QueueFlowLimitTest.cpp b/cpp/src/tests/QueueFlowLimitTest.cpp
deleted file mode 100644
index 8a6923fb09..0000000000
--- a/cpp/src/tests/QueueFlowLimitTest.cpp
+++ /dev/null
@@ -1,463 +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 <sstream>
-#include <deque>
-#include "unit_test.h"
-#include "test_tools.h"
-
-#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-#include "qpid/sys/Time.h"
-#include "qpid/framing/reply_exceptions.h"
-#include "MessageUtils.h"
-#include "BrokerFixture.h"
-
-using namespace qpid::broker;
-using namespace qpid::framing;
-
-namespace qpid {
-namespace tests {
-
-QPID_AUTO_TEST_SUITE(QueueFlowLimitTestSuite)
-
-namespace {
-
-class TestFlow : public QueueFlowLimit
-{
-public:
- TestFlow(uint32_t flowStopCount, uint32_t flowResumeCount,
- uint64_t flowStopSize, uint64_t flowResumeSize) :
- QueueFlowLimit(0, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize)
- {}
- virtual ~TestFlow() {}
-
- static TestFlow *createTestFlow(const qpid::framing::FieldTable& settings)
- {
- FieldTable::ValuePtr v;
-
- v = settings.get(flowStopCountKey);
- uint32_t flowStopCount = (v) ? (uint32_t)v->get<int64_t>() : 0;
- v = settings.get(flowResumeCountKey);
- uint32_t flowResumeCount = (v) ? (uint32_t)v->get<int64_t>() : 0;
- v = settings.get(flowStopSizeKey);
- uint64_t flowStopSize = (v) ? (uint64_t)v->get<int64_t>() : 0;
- v = settings.get(flowResumeSizeKey);
- uint64_t flowResumeSize = (v) ? (uint64_t)v->get<int64_t>() : 0;
-
- return new TestFlow(flowStopCount, flowResumeCount, flowStopSize, flowResumeSize);
- }
-
- static QueueFlowLimit *getQueueFlowLimit(const qpid::framing::FieldTable& settings)
- {
- return QueueFlowLimit::createLimit(0, settings);
- }
-};
-
-
-
-QueuedMessage createMessage(uint32_t size)
-{
- static uint32_t seqNum;
- QueuedMessage msg;
- msg.payload = MessageUtils::createMessage();
- msg.position = ++seqNum;
- MessageUtils::addContent(msg.payload, std::string (size, 'x'));
- return msg;
-}
-}
-
-QPID_AUTO_TEST_CASE(testFlowCount)
-{
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 7);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 5);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 7, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 5, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-
- std::deque<QueuedMessage> msgs;
- for (size_t i = 0; i < 6; i++) {
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- BOOST_CHECK(!flow->isFlowControlActive()); // 6 on queue
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive()); // 7 on queue
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue, ON
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 9 on queue, no change to flow control
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 8 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 7 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 6 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 5 on queue, no change
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 4 on queue, OFF
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowSize)
-{
- FieldTable args;
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, 70);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 50);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint32_t) 70, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 50, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-
- std::deque<QueuedMessage> msgs;
- for (size_t i = 0; i < 6; i++) {
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- BOOST_CHECK(!flow->isFlowControlActive()); // 60 on queue
- BOOST_CHECK_EQUAL(6u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(60u, flow->getFlowSize());
-
- QueuedMessage msg_9 = createMessage(9);
- flow->enqueued(msg_9);
- BOOST_CHECK(!flow->isFlowControlActive()); // 69 on queue
- QueuedMessage tinyMsg_1 = createMessage(1);
- flow->enqueued(tinyMsg_1);
- BOOST_CHECK(!flow->isFlowControlActive()); // 70 on queue
-
- QueuedMessage tinyMsg_2 = createMessage(1);
- flow->enqueued(tinyMsg_2);
- BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue, ON
- msgs.push_back(createMessage(10));
- flow->enqueued(msgs.back());
- BOOST_CHECK(flow->isFlowControlActive()); // 81 on queue
- BOOST_CHECK_EQUAL(10u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(81u, flow->getFlowSize());
-
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 71 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 61 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // 51 on queue
-
- flow->dequeued(tinyMsg_1);
- BOOST_CHECK(flow->isFlowControlActive()); // 50 on queue
- flow->dequeued(tinyMsg_2);
- BOOST_CHECK(!flow->isFlowControlActive()); // 49 on queue, OFF
-
- flow->dequeued(msg_9);
- BOOST_CHECK(!flow->isFlowControlActive()); // 40 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 30 on queue
- flow->dequeued(msgs.front());
- msgs.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive()); // 20 on queue
- BOOST_CHECK_EQUAL(2u, flow->getFlowCount());
- BOOST_CHECK_EQUAL(20u, flow->getFlowSize());
-}
-
-QPID_AUTO_TEST_CASE(testFlowArgs)
-{
- FieldTable args;
- const uint64_t stop(0x2FFFFFFFFull);
- const uint64_t resume(0x1FFFFFFFFull);
- args.setInt(QueueFlowLimit::flowStopCountKey, 30);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 21);
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, stop);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, resume);
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
-
- BOOST_CHECK_EQUAL((uint32_t) 30, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 21, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL(stop, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL(resume, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowCombo)
-{
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 10);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 5);
- args.setUInt64(QueueFlowLimit::flowStopSizeKey, 200);
- args.setUInt64(QueueFlowLimit::flowResumeSizeKey, 100);
-
- std::deque<QueuedMessage> msgs_1;
- std::deque<QueuedMessage> msgs_10;
- std::deque<QueuedMessage> msgs_50;
- std::deque<QueuedMessage> msgs_100;
-
- QueuedMessage msg;
-
- std::auto_ptr<TestFlow> flow(TestFlow::createTestFlow(args));
- BOOST_CHECK(!flow->isFlowControlActive()); // count:0 size:0
-
- // verify flow control comes ON when only count passes its stop point.
-
- for (size_t i = 0; i < 10; i++) {
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:10 size:100
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:11 size: 101 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- for (size_t i = 0; i < 6; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
- }
- // count:5 size: 41
-
- flow->dequeued(msgs_1.front()); // count: 4 size: 40 ->OFF
- msgs_1.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-
- for (size_t i = 0; i < 4; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:0 size:0
-
- // verify flow control comes ON when only size passes its stop point.
-
- msgs_100.push_back(createMessage(100));
- flow->enqueued(msgs_100.back()); // count:1 size: 100
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_50.push_back(createMessage(50));
- flow->enqueued(msgs_50.back()); // count:2 size: 150
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_50.push_back(createMessage(50));
- flow->enqueued(msgs_50.back()); // count:3 size: 200
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:4 size: 201 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_100.front()); // count:3 size:101
- msgs_100.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_1.front()); // count:2 size:100
- msgs_1.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- flow->dequeued(msgs_50.front()); // count:1 size:50 ->OFF
- msgs_50.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-
- // verify flow control remains ON until both thresholds drop below their
- // resume point.
-
- for (size_t i = 0; i < 8; i++) {
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back());
- BOOST_CHECK(!flow->isFlowControlActive());
- }
- // count:9 size:130
-
- msgs_10.push_back(createMessage(10));
- flow->enqueued(msgs_10.back()); // count:10 size: 140
- BOOST_CHECK(!flow->isFlowControlActive());
-
- msgs_1.push_back(createMessage(1));
- flow->enqueued(msgs_1.back()); // count:11 size: 141 ->ON
- BOOST_CHECK(flow->isFlowControlActive());
-
- msgs_100.push_back(createMessage(100));
- flow->enqueued(msgs_100.back()); // count:12 size: 241 (both thresholds crossed)
- BOOST_CHECK(flow->isFlowControlActive());
-
- // at this point: 9@10 + 1@50 + 1@100 + 1@1 == 12@241
-
- flow->dequeued(msgs_50.front()); // count:11 size:191
- msgs_50.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
-
- for (size_t i = 0; i < 9; i++) {
- flow->dequeued(msgs_10.front());
- msgs_10.pop_front();
- BOOST_CHECK(flow->isFlowControlActive());
- }
- // count:2 size:101
- flow->dequeued(msgs_1.front()); // count:1 size:100
- msgs_1.pop_front();
- BOOST_CHECK(flow->isFlowControlActive()); // still active due to size
-
- flow->dequeued(msgs_100.front()); // count:0 size:0 ->OFF
- msgs_100.pop_front();
- BOOST_CHECK(!flow->isFlowControlActive());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowDefaultArgs)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 80, // 80% stop threshold
- 70); // 70% resume threshold
- FieldTable args;
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
-
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
- BOOST_CHECK_EQUAL((uint64_t) 2360001, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 2065000, flow->getFlowResumeSize());
- BOOST_CHECK_EQUAL( 0u, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL( 0u, flow->getFlowResumeCount());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowOverrideArgs)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 80, // 80% stop threshold
- 70); // 70% resume threshold
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 35000);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 30000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 0, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopSizeKey, 350000);
- args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 0, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 35000);
- args.setInt(QueueFlowLimit::flowResumeCountKey, 30000);
- args.setInt(QueueFlowLimit::flowStopSizeKey, 350000);
- args.setInt(QueueFlowLimit::flowResumeSizeKey, 300000);
-
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 35000, flow->getFlowStopCount());
- BOOST_CHECK_EQUAL((uint32_t) 30000, flow->getFlowResumeCount());
- BOOST_CHECK_EQUAL((uint64_t) 350000, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint64_t) 300000, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
- }
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowOverrideDefaults)
-{
- QueueFlowLimit::setDefaults(2950001, // max queue byte count
- 97, // stop threshold
- 73); // resume threshold
- FieldTable args;
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(ptr);
- std::auto_ptr<QueueFlowLimit> flow(ptr);
-
- BOOST_CHECK_EQUAL((uint32_t) 2861501, flow->getFlowStopSize());
- BOOST_CHECK_EQUAL((uint32_t) 2153500, flow->getFlowResumeSize());
- BOOST_CHECK(!flow->isFlowControlActive());
- BOOST_CHECK(flow->monitorFlowControl());
-}
-
-
-QPID_AUTO_TEST_CASE(testFlowDisable)
-{
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(!ptr);
- }
- {
- FieldTable args;
- args.setInt(QueueFlowLimit::flowStopSizeKey, 0);
- QueueFlowLimit *ptr = TestFlow::getQueueFlowLimit(args);
- BOOST_CHECK(!ptr);
- }
-}
-
-
-QPID_AUTO_TEST_SUITE_END()
-
-}} // namespace qpid::tests
diff --git a/cpp/src/tests/QueuePolicyTest.cpp b/cpp/src/tests/QueuePolicyTest.cpp
index f735e09449..90af9c7dd9 100644
--- a/cpp/src/tests/QueuePolicyTest.cpp
+++ b/cpp/src/tests/QueuePolicyTest.cpp
@@ -23,7 +23,6 @@
#include "test_tools.h"
#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
#include "qpid/client/QueueOptions.h"
#include "qpid/sys/Time.h"
#include "qpid/framing/reply_exceptions.h"
@@ -39,7 +38,6 @@ namespace tests {
QPID_AUTO_TEST_SUITE(QueuePolicyTestSuite)
-namespace {
QueuedMessage createMessage(uint32_t size)
{
QueuedMessage msg;
@@ -47,7 +45,7 @@ QueuedMessage createMessage(uint32_t size)
MessageUtils::addContent(msg.payload, std::string (size, 'x'));
return msg;
}
-}
+
QPID_AUTO_TEST_CASE(testCount)
{
@@ -152,7 +150,7 @@ QPID_AUTO_TEST_CASE(testRingPolicyCount)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
for (int i = 0; i < 10; i++) {
@@ -187,7 +185,7 @@ QPID_AUTO_TEST_CASE(testRingPolicySize)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 0, 500, QueuePolicy::RING);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
@@ -259,7 +257,7 @@ QPID_AUTO_TEST_CASE(testStrictRingPolicy)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::RING_STRICT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-ring-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -285,7 +283,7 @@ QPID_AUTO_TEST_CASE(testPolicyWithDtx)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-policy-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -342,10 +340,8 @@ QPID_AUTO_TEST_CASE(testFlowToDiskWithNoStore)
//fallback to rejecting messages
QueueOptions args;
args.setSizePolicy(FLOW_TO_DISK, 0, 5);
- // Disable flow control, or else we'll never hit the max limit
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("my-queue");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
LocalQueue incoming;
@@ -371,7 +367,7 @@ QPID_AUTO_TEST_CASE(testPolicyFailureOnCommit)
std::auto_ptr<QueuePolicy> policy = QueuePolicy::createQueuePolicy("test", 5, 0, QueuePolicy::REJECT);
policy->update(args);
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("q");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
f.session.txSelect();
@@ -386,9 +382,8 @@ QPID_AUTO_TEST_CASE(testCapacityConversion)
{
FieldTable args;
args.setString("qpid.max_count", "5");
- args.setString("qpid.flow_stop_count", "0");
- SessionFixture f;
+ ProxySessionFixture f;
std::string q("q");
f.session.queueDeclare(arg::queue=q, arg::exclusive=true, arg::autoDelete=true, arg::arguments=args);
for (int i = 0; i < 5; i++) {
diff --git a/cpp/src/tests/QueueTest.cpp b/cpp/src/tests/QueueTest.cpp
index aaa2721021..80c69ac386 100644
--- a/cpp/src/tests/QueueTest.cpp
+++ b/cpp/src/tests/QueueTest.cpp
@@ -36,9 +36,6 @@
#include "qpid/framing/AMQFrame.h"
#include "qpid/framing/MessageTransferBody.h"
#include "qpid/framing/reply_exceptions.h"
-#include "qpid/broker/QueuePolicy.h"
-#include "qpid/broker/QueueFlowLimit.h"
-
#include <iostream>
#include "boost/format.hpp"
@@ -56,12 +53,12 @@ class TestConsumer : public virtual Consumer{
public:
typedef boost::shared_ptr<TestConsumer> shared_ptr;
- QueuedMessage last;
+ intrusive_ptr<Message> last;
bool received;
- TestConsumer(std::string name="test", bool acquire = true):Consumer(name, acquire), received(false) {};
+ TestConsumer(bool acquire = true):Consumer(acquire), received(false) {};
virtual bool deliver(QueuedMessage& msg){
- last = msg;
+ last = msg.payload;
received = true;
return true;
};
@@ -81,14 +78,13 @@ public:
Message& getMessage() { return *(msg.get()); }
};
-intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey, uint64_t ttl = 0) {
+intrusive_ptr<Message> create_message(std::string exchange, std::string routingKey) {
intrusive_ptr<Message> msg(new Message());
AMQFrame method((MessageTransferBody(ProtocolVersion(), exchange, 0, 0)));
AMQFrame header((AMQHeaderBody()));
msg->getFrames().append(method);
msg->getFrames().append(header);
msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setRoutingKey(routingKey);
- if (ttl) msg->getFrames().getHeaders()->get<DeliveryProperties>(true)->setTtl(ttl);
return msg;
}
@@ -149,16 +145,16 @@ QPID_AUTO_TEST_CASE(testConsumers){
queue->deliver(msg1);
BOOST_CHECK(queue->dispatch(c1));
- BOOST_CHECK_EQUAL(msg1.get(), c1->last.payload.get());
+ BOOST_CHECK_EQUAL(msg1.get(), c1->last.get());
queue->deliver(msg2);
BOOST_CHECK(queue->dispatch(c2));
- BOOST_CHECK_EQUAL(msg2.get(), c2->last.payload.get());
+ BOOST_CHECK_EQUAL(msg2.get(), c2->last.get());
c1->received = false;
queue->deliver(msg3);
BOOST_CHECK(queue->dispatch(c1));
- BOOST_CHECK_EQUAL(msg3.get(), c1->last.payload.get());
+ BOOST_CHECK_EQUAL(msg3.get(), c1->last.get());
//Test cancellation:
queue->cancel(c1);
@@ -214,7 +210,7 @@ QPID_AUTO_TEST_CASE(testDequeue){
if (!consumer->received)
sleep(2);
- BOOST_CHECK_EQUAL(msg3.get(), consumer->last.payload.get());
+ BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get());
BOOST_CHECK_EQUAL(uint32_t(0), queue->getMessageCount());
received = queue->get().payload;
@@ -248,7 +244,7 @@ QPID_AUTO_TEST_CASE(testBound){
exchange2.reset();
//unbind the queue from all exchanges it knows it has been bound to:
- queue->unbind(exchanges);
+ queue->unbind(exchanges, queue);
//ensure the remaining exchanges don't still have the queue bound to them:
FailOnDeliver deliverable;
@@ -258,26 +254,26 @@ QPID_AUTO_TEST_CASE(testBound){
QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
client::QueueOptions args;
- args.setPersistLastNode();
+ args.setPersistLastNode();
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
queue->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
- //change mode
- queue->setLastNodeFailure();
+ //change mode
+ queue->setLastNodeFailure();
- //enqueue 1 message
+ //enqueue 1 message
queue->deliver(msg3);
- //check all have persistent ids.
+ //check all have persistent ids.
BOOST_CHECK(msg1->isPersistent());
BOOST_CHECK(msg2->isPersistent());
BOOST_CHECK(msg3->isPersistent());
@@ -287,58 +283,54 @@ QPID_AUTO_TEST_CASE(testPersistLastNodeStanding){
QPID_AUTO_TEST_CASE(testSeek){
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
- TestConsumer::shared_ptr consumer(new TestConsumer("test", false));
+ TestConsumer::shared_ptr consumer(new TestConsumer(false));
SequenceNumber seq(2);
consumer->position = seq;
QueuedMessage qm;
queue->dispatch(consumer);
-
- BOOST_CHECK_EQUAL(msg3.get(), consumer->last.payload.get());
+
+ BOOST_CHECK_EQUAL(msg3.get(), consumer->last.get());
queue->dispatch(consumer);
queue->dispatch(consumer); // make sure over-run is safe
-
+
}
QPID_AUTO_TEST_CASE(testSearch){
- Queue::shared_ptr queue(new Queue("my-queue", true));
+ Queue::shared_ptr queue(new Queue("my-queue", true));
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
intrusive_ptr<Message> msg3 = create_message("e", "C");
- //enqueue 2 messages
+ //enqueue 2 messages
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
SequenceNumber seq(2);
- QueuedMessage qm;
- TestConsumer::shared_ptr c1(new TestConsumer());
-
- BOOST_CHECK(queue->find(seq, qm));
-
+ QueuedMessage qm = queue->find(seq);
+
BOOST_CHECK_EQUAL(seq.getValue(), qm.position.getValue());
-
- queue->acquire(qm, c1->getName());
+
+ queue->acquire(qm);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
SequenceNumber seq1(3);
- QueuedMessage qm1;
- BOOST_CHECK(queue->find(seq1, qm1));
+ QueuedMessage qm1 = queue->find(seq1);
BOOST_CHECK_EQUAL(seq1.getValue(), qm1.position.getValue());
-
+
}
const std::string nullxid = "";
@@ -424,10 +416,10 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
client::QueueOptions args;
// set queue mode
- args.setOrdering(client::LVQ);
+ args.setOrdering(client::LVQ);
- Queue::shared_ptr queue(new Queue("my-queue", true ));
- queue->configure(args);
+ Queue::shared_ptr queue(new Queue("my-queue", true ));
+ queue->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "B");
@@ -438,16 +430,16 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
//set deliever match for LVQ a,b,c,a
string key;
- args.getLVQKey(key);
+ args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"b");
- msg3->insertCustomProperty(key,"c");
- msg4->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
+ msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
- //enqueue 4 message
+ //enqueue 4 message
queue->deliver(msg1);
queue->deliver(msg2);
queue->deliver(msg3);
@@ -467,9 +459,9 @@ QPID_AUTO_TEST_CASE(testLVQOrdering){
intrusive_ptr<Message> msg5 = create_message("e", "A");
intrusive_ptr<Message> msg6 = create_message("e", "B");
intrusive_ptr<Message> msg7 = create_message("e", "C");
- msg5->insertCustomProperty(key,"a");
- msg6->insertCustomProperty(key,"b");
- msg7->insertCustomProperty(key,"c");
+ msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg7->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
queue->deliver(msg5);
queue->deliver(msg6);
queue->deliver(msg7);
@@ -504,7 +496,7 @@ QPID_AUTO_TEST_CASE(testLVQEmptyKey){
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
queue->deliver(msg1);
queue->deliver(msg2);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
@@ -516,8 +508,6 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
client::QueueOptions args;
// set queue mode
args.setOrdering(client::LVQ);
- // disable flow control, as this test violates the enqueue/dequeue sequence.
- args.setInt(QueueFlowLimit::flowStopCountKey, 0);
Queue::shared_ptr queue(new Queue("my-queue", true ));
queue->configure(args);
@@ -536,12 +526,12 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"b");
- msg3->insertCustomProperty(key,"c");
- msg4->insertCustomProperty(key,"a");
- msg5->insertCustomProperty(key,"b");
- msg6->insertCustomProperty(key,"c");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg3->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
+ msg4->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg5->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"b");
+ msg6->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"c");
//enqueue 4 message
queue->deliver(msg1);
@@ -556,13 +546,12 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
QueuedMessage qmsg2(queue.get(), msg2, ++sequence);
framing::SequenceNumber sequence1(10);
QueuedMessage qmsg3(queue.get(), 0, sequence1);
- TestConsumer::shared_ptr dummy(new TestConsumer());
- BOOST_CHECK(!queue->acquire(qmsg, dummy->getName()));
- BOOST_CHECK(queue->acquire(qmsg2, dummy->getName()));
+ BOOST_CHECK(!queue->acquire(qmsg));
+ BOOST_CHECK(queue->acquire(qmsg2));
// Acquire the massage again to test failure case.
- BOOST_CHECK(!queue->acquire(qmsg2, dummy->getName()));
- BOOST_CHECK(!queue->acquire(qmsg3, dummy->getName()));
+ BOOST_CHECK(!queue->acquire(qmsg2));
+ BOOST_CHECK(!queue->acquire(qmsg3));
BOOST_CHECK_EQUAL(queue->getMessageCount(), 2u);
@@ -572,7 +561,7 @@ QPID_AUTO_TEST_CASE(testLVQAcquire){
// set mode to no browse and check
args.setOrdering(client::LVQ_NO_BROWSE);
queue->configure(args);
- TestConsumer::shared_ptr c1(new TestConsumer("test", false));
+ TestConsumer::shared_ptr c1(new TestConsumer(false));
queue->dispatch(c1);
queue->dispatch(c1);
@@ -606,8 +595,8 @@ QPID_AUTO_TEST_CASE(testLVQMultiQueue){
args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"a");
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
queue1->deliver(msg1);
queue2->deliver(msg1);
@@ -641,7 +630,7 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore));
intrusive_ptr<Message> received;
- queue1->create(args);
+ queue1->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
intrusive_ptr<Message> msg2 = create_message("e", "A");
@@ -650,9 +639,9 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
args.getLVQKey(key);
BOOST_CHECK_EQUAL(key, "qpid.LVQ_key");
- msg1->insertCustomProperty(key,"a");
- msg2->insertCustomProperty(key,"a");
- // 3
+ msg1->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ msg2->getProperties<MessageProperties>()->getApplicationHeaders().setString(key,"a");
+ // 3
queue1->deliver(msg1);
// 4
queue1->setLastNodeFailure();
@@ -671,8 +660,13 @@ QPID_AUTO_TEST_CASE(testLVQRecover){
void addMessagesToQueue(uint count, Queue& queue, uint oddTtl = 200, uint evenTtl = 0)
{
for (uint i = 0; i < count; i++) {
- intrusive_ptr<Message> m = create_message("exchange", "key", i % 2 ? oddTtl : evenTtl);
- m->computeExpiration(new broker::ExpiryPolicy);
+ intrusive_ptr<Message> m = create_message("exchange", "key");
+ if (i % 2) {
+ if (oddTtl) m->getProperties<DeliveryProperties>()->setTtl(oddTtl);
+ } else {
+ if (evenTtl) m->getProperties<DeliveryProperties>()->setTtl(evenTtl);
+ }
+ m->setTimestamp(new broker::ExpiryPolicy);
queue.deliver(m);
}
}
@@ -682,7 +676,7 @@ QPID_AUTO_TEST_CASE(testPurgeExpired) {
addMessagesToQueue(10, queue);
BOOST_CHECK_EQUAL(queue.getMessageCount(), 10u);
::usleep(300*1000);
- queue.purgeExpired(0);
+ queue.purgeExpired();
BOOST_CHECK_EQUAL(queue.getMessageCount(), 5u);
}
@@ -693,7 +687,7 @@ QPID_AUTO_TEST_CASE(testQueueCleaner) {
addMessagesToQueue(10, *queue, 200, 400);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 10u);
- QueueCleaner cleaner(queues, &timer);
+ QueueCleaner cleaner(queues, timer);
cleaner.start(100 * qpid::sys::TIME_MSEC);
::usleep(300*1000);
BOOST_CHECK_EQUAL(queue->getMessageCount(), 5u);
@@ -701,280 +695,6 @@ QPID_AUTO_TEST_CASE(testQueueCleaner) {
BOOST_CHECK_EQUAL(queue->getMessageCount(), 0u);
}
-
-namespace {
- // helper for group tests
- void verifyAcquire( Queue::shared_ptr queue,
- TestConsumer::shared_ptr c,
- std::deque<QueuedMessage>& results,
- const std::string& expectedGroup,
- const int expectedId )
- {
- queue->dispatch(c);
- results.push_back(c->last);
- std::string group = c->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsString("GROUP-ID");
- int id = c->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( group, expectedGroup );
- BOOST_CHECK_EQUAL( id, expectedId );
- }
-}
-
-QPID_AUTO_TEST_CASE(testGroupsMultiConsumer) {
- //
- // Verify that consumers of grouped messages own the groups once a message is acquired,
- // and release the groups once all acquired messages have been dequeued or requeued
- //
- FieldTable args;
- Queue::shared_ptr queue(new Queue("my_queue", true));
- args.setString("qpid.group_header_key", "GROUP-ID");
- args.setInt("qpid.shared_msg_group", 1);
- queue->configure(args);
-
- std::string groups[] = { std::string("a"), std::string("a"), std::string("a"),
- std::string("b"), std::string("b"), std::string("b"),
- std::string("c"), std::string("c"), std::string("c") };
- for (int i = 0; i < 9; ++i) {
- intrusive_ptr<Message> msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", groups[i]);
- msg->insertCustomProperty("MY-ID", i);
- queue->deliver(msg);
- }
-
- // Queue = a-0, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ---, ---, ---, ---, ---, ---, ---, ---, ---,
-
- BOOST_CHECK_EQUAL(uint32_t(9), queue->getMessageCount());
-
- TestConsumer::shared_ptr c1(new TestConsumer("C1"));
- TestConsumer::shared_ptr c2(new TestConsumer("C2"));
-
- queue->consume(c1);
- queue->consume(c2);
-
- std::deque<QueuedMessage> dequeMeC1;
- std::deque<QueuedMessage> dequeMeC2;
-
-
- verifyAcquire(queue, c1, dequeMeC1, "a", 0 ); // c1 now owns group "a" (acquire a-0)
- verifyAcquire(queue, c2, dequeMeC2, "b", 3 ); // c2 should now own group "b" (acquire b-3)
-
- // now let c1 complete the 'a-0' message - this should free the 'a' group
- queue->dequeue( 0, dequeMeC1.front() );
- dequeMeC1.pop_front();
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ---, ---, ^C2, ^C2, ^C2, ---, ---, ---
-
- // now c2 should pick up the next 'a-1', since it is oldest free
- verifyAcquire(queue, c2, dequeMeC2, "a", 1 ); // c2 should now own groups "a" and "b"
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ---, ---, ---
-
- // c1 should only be able to snarf up the first "c" message now...
- verifyAcquire(queue, c1, dequeMeC1, "c", 6 ); // should skip to the first "c"
-
- // Queue = a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C2, ^C2, ^C2, ^C1, ^C1, ^C1
-
- // hmmm... what if c2 now dequeues "b-3"? (now only has a-1 acquired)
- queue->dequeue( 0, dequeMeC2.front() );
- dequeMeC2.pop_front();
-
- // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ---, ---, ^C1, ^C1, ^C1
-
- // b group is free, c is owned by c1 - c1's next get should grab 'b-4'
- verifyAcquire(queue, c1, dequeMeC1, "b", 4 );
-
- // Queue = a-1, a-2, b-4, b-5, c-6, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ^C1, ^C1, ^C1
-
- // c2 can now only grab a-2, and that's all
- verifyAcquire(queue, c2, dequeMeC2, "a", 2 );
-
- // now C2 can't get any more, since C1 owns "b" and "c" group...
- bool gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- // hmmm... what if c1 now dequeues "c-6"? (now only own's b-4)
- queue->dequeue( 0, dequeMeC1.front() );
- dequeMeC1.pop_front();
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ---, ---
-
- // c2 can now grab c-7
- verifyAcquire(queue, c2, dequeMeC2, "c", 7 );
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C2, ^C2, ^C1, ^C1, ^C2, ^C2
-
- // what happens if C-2 "requeues" a-1 and a-2?
- queue->requeue( dequeMeC2.front() );
- dequeMeC2.pop_front();
- queue->requeue( dequeMeC2.front() );
- dequeMeC2.pop_front(); // now just has c-7 acquired
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ---, ---, ^C1, ^C1, ^C2, ^C2
-
- // now c1 will grab a-1 and a-2...
- verifyAcquire(queue, c1, dequeMeC1, "a", 1 );
- verifyAcquire(queue, c1, dequeMeC1, "a", 2 );
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ^C1, ^C1, ^C1, ^C1, ^C2, ^C2
-
- // c2 can now acquire c-8 only
- verifyAcquire(queue, c2, dequeMeC2, "c", 8 );
-
- // and c1 can get b-5
- verifyAcquire(queue, c1, dequeMeC1, "b", 5 );
-
- // should be no more acquire-able for anyone now:
- gotOne = queue->dispatch(c1);
- BOOST_CHECK( !gotOne );
- gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- // requeue all of C1's acquired messages, then cancel C1
- while (!dequeMeC1.empty()) {
- queue->requeue(dequeMeC1.front());
- dequeMeC1.pop_front();
- }
- queue->cancel(c1);
-
- // Queue = a-1, a-2, b-4, b-5, c-7, c-8...
- // Owners= ---, ---, ---, ---, ^C2, ^C2
-
- // b-4, a-1, a-2, b-5 all should be available, right?
- verifyAcquire(queue, c2, dequeMeC2, "a", 1 );
-
- while (!dequeMeC2.empty()) {
- queue->dequeue(0, dequeMeC2.front());
- dequeMeC2.pop_front();
- }
-
- // Queue = a-2, b-4, b-5
- // Owners= ---, ---, ---
-
- TestConsumer::shared_ptr c3(new TestConsumer("C3"));
- std::deque<QueuedMessage> dequeMeC3;
-
- verifyAcquire(queue, c3, dequeMeC3, "a", 2 );
- verifyAcquire(queue, c2, dequeMeC2, "b", 4 );
-
- // Queue = a-2, b-4, b-5
- // Owners= ^C3, ^C2, ^C2
-
- gotOne = queue->dispatch(c3);
- BOOST_CHECK( !gotOne );
-
- verifyAcquire(queue, c2, dequeMeC2, "b", 5 );
-
- while (!dequeMeC2.empty()) {
- queue->dequeue(0, dequeMeC2.front());
- dequeMeC2.pop_front();
- }
-
- // Queue = a-2,
- // Owners= ^C3,
-
- intrusive_ptr<Message> msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", "a");
- msg->insertCustomProperty("MY-ID", 9);
- queue->deliver(msg);
-
- // Queue = a-2, a-9
- // Owners= ^C3, ^C3
-
- gotOne = queue->dispatch(c2);
- BOOST_CHECK( !gotOne );
-
- msg = create_message("e", "A");
- msg->insertCustomProperty("GROUP-ID", "b");
- msg->insertCustomProperty("MY-ID", 10);
- queue->deliver(msg);
-
- // Queue = a-2, a-9, b-10
- // Owners= ^C3, ^C3, ----
-
- verifyAcquire(queue, c2, dequeMeC2, "b", 10 );
- verifyAcquire(queue, c3, dequeMeC3, "a", 9 );
-
- gotOne = queue->dispatch(c3);
- BOOST_CHECK( !gotOne );
-
- queue->cancel(c2);
- queue->cancel(c3);
-}
-
-
-QPID_AUTO_TEST_CASE(testGroupsMultiConsumerDefaults) {
- //
- // Verify that the same default group name is automatically applied to messages that
- // do not specify a group name.
- //
- FieldTable args;
- Queue::shared_ptr queue(new Queue("my_queue", true));
- args.setString("qpid.group_header_key", "GROUP-ID");
- args.setInt("qpid.shared_msg_group", 1);
- queue->configure(args);
-
- for (int i = 0; i < 3; ++i) {
- intrusive_ptr<Message> msg = create_message("e", "A");
- // no "GROUP-ID" header
- msg->insertCustomProperty("MY-ID", i);
- queue->deliver(msg);
- }
-
- // Queue = 0, 1, 2
-
- BOOST_CHECK_EQUAL(uint32_t(3), queue->getMessageCount());
-
- TestConsumer::shared_ptr c1(new TestConsumer("C1"));
- TestConsumer::shared_ptr c2(new TestConsumer("C2"));
-
- queue->consume(c1);
- queue->consume(c2);
-
- std::deque<QueuedMessage> dequeMeC1;
- std::deque<QueuedMessage> dequeMeC2;
-
- queue->dispatch(c1); // c1 now owns default group (acquired 0)
- dequeMeC1.push_back(c1->last);
- int id = c1->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 0 );
-
- bool gotOne = queue->dispatch(c2); // c2 should get nothing
- BOOST_CHECK( !gotOne );
-
- queue->dispatch(c1); // c1 now acquires 1
- dequeMeC1.push_back(c1->last);
- id = c1->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 1 );
-
- gotOne = queue->dispatch(c2); // c2 should still get nothing
- BOOST_CHECK( !gotOne );
-
- while (!dequeMeC1.empty()) {
- queue->dequeue(0, dequeMeC1.front());
- dequeMeC1.pop_front();
- }
-
- // now default group should be available...
- queue->dispatch(c2); // c2 now owns default group (acquired 2)
- id = c2->last.payload->getProperties<MessageProperties>()->getApplicationHeaders().getAsInt("MY-ID");
- BOOST_CHECK_EQUAL( id, 2 );
-
- gotOne = queue->dispatch(c1); // c1 should get nothing
- BOOST_CHECK( !gotOne );
-
- queue->cancel(c1);
- queue->cancel(c2);
-}
-
QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
TestMessageStoreOC testStore;
@@ -982,9 +702,9 @@ QPID_AUTO_TEST_CASE(testMultiQueueLastNode){
args.setPersistLastNode();
Queue::shared_ptr queue1(new Queue("queue1", true, &testStore ));
- queue1->create(args);
+ queue1->configure(args);
Queue::shared_ptr queue2(new Queue("queue2", true, &testStore ));
- queue2->create(args);
+ queue2->configure(args);
intrusive_ptr<Message> msg1 = create_message("e", "A");
@@ -1070,7 +790,7 @@ not requeued to the store.
Queue::shared_ptr queue1(new Queue("my-queue", true, &testStore));
intrusive_ptr<Message> received;
- queue1->create(args);
+ queue1->configure(args);
// check requeue 1
intrusive_ptr<Message> msg1 = create_message("e", "C");
@@ -1150,40 +870,28 @@ QPID_AUTO_TEST_CASE(testFlowToDiskBlocking){
intrusive_ptr<Message> msg02 = mkMsg(testStore, std::string(5, 'X')); // transient w/ content
DeliverableMessage dmsg02(msg02);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg02, "", 0), ResourceLimitExceededException);
- }
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg02, "", 0), ResourceLimitExceededException);
msg02->tryReleaseContent();
BOOST_CHECK_EQUAL(msg02->isContentReleased(), false);
BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
intrusive_ptr<Message> msg03 = mkMsg(testStore, std::string(5, 'X'), true); // durable w/ content
DeliverableMessage dmsg03(msg03);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg03, "", 0), ResourceLimitExceededException);
- }
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg03, "", 0), ResourceLimitExceededException);
msg03->tryReleaseContent();
BOOST_CHECK_EQUAL(msg03->isContentReleased(), false);
BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
intrusive_ptr<Message> msg04 = mkMsg(testStore); // transient no content
DeliverableMessage dmsg04(msg04);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg04, "", 0), ResourceLimitExceededException);
- }
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg04, "", 0), ResourceLimitExceededException);
msg04->tryReleaseContent();
BOOST_CHECK_EQUAL(msg04->isContentReleased(), false);
BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
intrusive_ptr<Message> msg05 = mkMsg(testStore, "", true); // durable no content
DeliverableMessage dmsg05(msg05);
- {
- ScopedSuppressLogging sl; // suppress expected error messages.
- BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException);
- }
+ BOOST_CHECK_THROW(sbtFanout1.route(dmsg05, "", 0), ResourceLimitExceededException);
msg05->tryReleaseContent();
BOOST_CHECK_EQUAL(msg05->isContentReleased(), false);
BOOST_CHECK_EQUAL(1u, tq1->getMessageCount());
diff --git a/cpp/src/tests/ReplicationTest.cpp b/cpp/src/tests/ReplicationTest.cpp
index 1219a6b59e..7310a3fe20 100644
--- a/cpp/src/tests/ReplicationTest.cpp
+++ b/cpp/src/tests/ReplicationTest.cpp
@@ -74,7 +74,7 @@ QPID_AUTO_TEST_CASE(testReplicationExchange)
{
qpid::broker::Broker::Options brokerOpts(getBrokerOpts(list_of<string>("qpidd")
("--replication-exchange-name=qpid.replication")));
- SessionFixture f(brokerOpts);
+ ProxySessionFixture f(brokerOpts);
std::string dataQ("queue-1");
diff --git a/cpp/src/tests/SessionState.cpp b/cpp/src/tests/SessionState.cpp
index 3be9bb0cbc..157cabfb63 100644
--- a/cpp/src/tests/SessionState.cpp
+++ b/cpp/src/tests/SessionState.cpp
@@ -43,7 +43,7 @@ using namespace qpid::framing;
// Apply f to [begin, end) and accumulate the result
template <class Iter, class T, class F>
T applyAccumulate(Iter begin, Iter end, T seed, const F& f) {
- return std::accumulate(begin, end, seed, boost::bind(std::plus<T>(), _1, boost::bind(f, _2)));
+ return std::accumulate(begin, end, seed, bind(std::plus<T>(), _1, bind(f, _2)));
}
// Create a frame with a one-char string.
@@ -105,8 +105,8 @@ size_t transferN(qpid::SessionState& s, string content) {
char last = content[content.size()-1];
content.resize(content.size()-1);
size += applyAccumulate(content.begin(), content.end(), 0,
- boost::bind(&send, boost::ref(s),
- boost::bind(contentFrameChar, _1, false)));
+ bind(&send, ref(s),
+ bind(contentFrameChar, _1, false)));
size += send(s, contentFrameChar(last, true));
}
return size;
@@ -115,7 +115,7 @@ size_t transferN(qpid::SessionState& s, string content) {
// Send multiple transfers with single-byte content.
size_t transfers(qpid::SessionState& s, string content) {
return applyAccumulate(content.begin(), content.end(), 0,
- boost::bind(transfer1Char, boost::ref(s), _1));
+ bind(transfer1Char, ref(s), _1));
}
size_t contentFrameSize(size_t n=1) { return AMQFrame(( AMQContentBody())).encodedSize() + n; }
diff --git a/cpp/src/tests/SocketProxy.h b/cpp/src/tests/SocketProxy.h
new file mode 100644
index 0000000000..0c6f39d62e
--- /dev/null
+++ b/cpp/src/tests/SocketProxy.h
@@ -0,0 +1,181 @@
+#ifndef SOCKETPROXY_H
+#define SOCKETPROXY_H
+
+/*
+ * 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 "qpid/sys/IOHandle.h"
+#ifdef _WIN32
+# include "qpid/sys/windows/IoHandlePrivate.h"
+ typedef SOCKET FdType;
+#else
+# include "qpid/sys/posix/PrivatePosix.h"
+ typedef int FdType;
+#endif
+#include "qpid/sys/Socket.h"
+#include "qpid/sys/Runnable.h"
+#include "qpid/sys/Thread.h"
+#include "qpid/sys/Mutex.h"
+#include "qpid/log/Statement.h"
+
+namespace qpid {
+namespace tests {
+
+/**
+ * A simple socket proxy that forwards to another socket.
+ * Used between client & local broker to simulate network failures.
+ */
+class SocketProxy : private qpid::sys::Runnable
+{
+ // Need a Socket we can get the fd from
+ class LowSocket : public qpid::sys::Socket {
+ public:
+#ifdef _WIN32
+ FdType getFd() { return toSocketHandle(*this); }
+#else
+ FdType getFd() { return toFd(impl); }
+#endif
+ };
+
+ public:
+ /** Connect to connectPort on host, start a forwarding thread.
+ * Listen for connection on getPort().
+ */
+ SocketProxy(int connectPort, const std::string host="localhost")
+ : closed(false), joined(true),
+ port(listener.listen()), dropClient(), dropServer()
+ {
+ client.connect(host, connectPort);
+ joined = false;
+ thread = qpid::sys::Thread(static_cast<qpid::sys::Runnable*>(this));
+ }
+
+ ~SocketProxy() { close(); if (!joined) thread.join(); }
+
+ /** Simulate a network disconnect. */
+ void close() {
+ {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ if (closed) { return; }
+ closed=true;
+ }
+ if (thread && thread != qpid::sys::Thread::current()) {
+ thread.join();
+ joined = true;
+ }
+ client.close();
+ }
+
+ /** Simulate lost packets, drop data from client */
+ void dropClientData(bool drop=true) { dropClient=drop; }
+
+ /** Simulate lost packets, drop data from server */
+ void dropServerData(bool drop=true) { dropServer=drop; }
+
+ bool isClosed() const {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ return closed;
+ }
+
+ uint16_t getPort() const { return port; }
+
+ private:
+ static void throwErrno(const std::string& msg) {
+ throw qpid::Exception(msg+":"+qpid::sys::strError(errno));
+ }
+ static void throwIf(bool condition, const std::string& msg) {
+ if (condition) throw qpid::Exception(msg);
+ }
+
+ void run() {
+ std::auto_ptr<LowSocket> server;
+ try {
+ fd_set socks;
+ FdType maxFd = listener.getFd();
+ struct timeval tmo;
+ for (;;) {
+ FD_ZERO(&socks);
+ FD_SET(maxFd, &socks);
+ tmo.tv_sec = 0;
+ tmo.tv_usec = 500 * 1000;
+ if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ throwIf(closed, "SocketProxy: Closed by close()");
+ continue;
+ }
+ throwIf(!FD_ISSET(maxFd, &socks), "SocketProxy: Accept failed");
+ break; // Accept ready... go to next step
+ }
+ server.reset(reinterpret_cast<LowSocket *>(listener.accept()));
+ maxFd = server->getFd();
+ if (client.getFd() > maxFd)
+ maxFd = client.getFd();
+ char buffer[1024];
+ for (;;) {
+ FD_ZERO(&socks);
+ tmo.tv_sec = 0;
+ tmo.tv_usec = 500 * 1000;
+ FD_SET(client.getFd(), &socks);
+ FD_SET(server->getFd(), &socks);
+ if (select(maxFd+1, &socks, 0, 0, &tmo) == 0) {
+ qpid::sys::Mutex::ScopedLock l(lock);
+ throwIf(closed, "SocketProxy: Closed by close()");
+ continue;
+ }
+ // Something is set; relay data as needed until something closes
+ if (FD_ISSET(server->getFd(), &socks)) {
+ int n = server->read(buffer, sizeof(buffer));
+ throwIf(n <= 0, "SocketProxy: server disconnected");
+ if (!dropServer) client.write(buffer, n);
+ }
+ if (FD_ISSET(client.getFd(), &socks)) {
+ int n = client.read(buffer, sizeof(buffer));
+ throwIf(n <= 0, "SocketProxy: client disconnected");
+ if (!dropServer) server->write(buffer, n);
+ }
+ if (!FD_ISSET(client.getFd(), &socks) &&
+ !FD_ISSET(server->getFd(), &socks))
+ throwIf(true, "SocketProxy: No handle ready");
+ }
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(debug, "SocketProxy::run exception: " << e.what());
+ }
+ try {
+ if (server.get()) server->close();
+ close();
+ }
+ catch (const std::exception& e) {
+ QPID_LOG(debug, "SocketProxy::run exception in client/server close()" << e.what());
+ }
+ }
+
+ mutable qpid::sys::Mutex lock;
+ mutable bool closed;
+ bool joined;
+ LowSocket client, listener;
+ uint16_t port;
+ qpid::sys::Thread thread;
+ bool dropClient, dropServer;
+};
+
+}} // namespace qpid::tests
+
+#endif
diff --git a/cpp/src/tests/TimerTest.cpp b/cpp/src/tests/TimerTest.cpp
index 6a0a196f4e..7df94164e0 100644
--- a/cpp/src/tests/TimerTest.cpp
+++ b/cpp/src/tests/TimerTest.cpp
@@ -77,10 +77,8 @@ class TestTask : public TimerTask
BOOST_CHECK(fired);
BOOST_CHECK_EQUAL(expected_position, position);
Duration actual(start, end);
-#ifdef _MSC_VER
+#ifdef _WIN32
uint64_t difference = _abs64(expected - actual);
-#elif defined(_WIN32)
- uint64_t difference = labs(expected - actual);
#else
uint64_t difference = abs(expected - actual);
#endif
diff --git a/cpp/src/tests/TxPublishTest.cpp b/cpp/src/tests/TxPublishTest.cpp
index 152581e4ba..6b44d95baa 100644
--- a/cpp/src/tests/TxPublishTest.cpp
+++ b/cpp/src/tests/TxPublishTest.cpp
@@ -50,9 +50,10 @@ struct TxPublishTest
TxPublishTest() :
queue1(new Queue("queue1", false, &store, 0)),
queue2(new Queue("queue2", false, &store, 0)),
- msg(MessageUtils::createMessage("exchange", "routing_key", true)),
+ msg(MessageUtils::createMessage("exchange", "routing_key", false, "id")),
op(msg)
{
+ msg->getProperties<DeliveryProperties>()->setDeliveryMode(PERSISTENT);
op.deliverTo(queue1);
op.deliverTo(queue2);
}
@@ -73,7 +74,7 @@ QPID_AUTO_TEST_CASE(testPrepare)
BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[0].second);
BOOST_CHECK_EQUAL(string("queue2"), t.store.enqueued[1].first);
BOOST_CHECK_EQUAL(pmsg, t.store.enqueued[1].second);
- BOOST_CHECK_EQUAL( true, ( boost::static_pointer_cast<PersistableMessage>(t.msg))->isIngressComplete());
+ BOOST_CHECK_EQUAL( true, ( boost::static_pointer_cast<PersistableMessage>(t.msg))->isEnqueueComplete());
}
QPID_AUTO_TEST_CASE(testCommit)
@@ -86,7 +87,7 @@ QPID_AUTO_TEST_CASE(testCommit)
BOOST_CHECK_EQUAL((uint32_t) 1, t.queue1->getMessageCount());
intrusive_ptr<Message> msg_dequeue = t.queue1->get().payload;
- BOOST_CHECK_EQUAL( true, (boost::static_pointer_cast<PersistableMessage>(msg_dequeue))->isIngressComplete());
+ BOOST_CHECK_EQUAL( true, (boost::static_pointer_cast<PersistableMessage>(msg_dequeue))->isEnqueueComplete());
BOOST_CHECK_EQUAL(t.msg, msg_dequeue);
BOOST_CHECK_EQUAL((uint32_t) 1, t.queue2->getMessageCount());
diff --git a/cpp/src/tests/Url.cpp b/cpp/src/tests/Url.cpp
index b30de682bc..234a62ee91 100644
--- a/cpp/src/tests/Url.cpp
+++ b/cpp/src/tests/Url.cpp
@@ -60,32 +60,6 @@ QPID_AUTO_TEST_CASE(TestParseXyz) {
BOOST_CHECK_EQUAL(Url("xyz:host").str(), "amqp:xyz:host:5672");
}
-QPID_AUTO_TEST_CASE(TestParseTricky) {
- BOOST_CHECK_EQUAL(Url("amqp").str(), "amqp:tcp:amqp:5672");
- BOOST_CHECK_EQUAL(Url("amqp:tcp").str(), "amqp:tcp:tcp:5672");
- // These are ambiguous parses and arguably not the best result
- BOOST_CHECK_EQUAL(Url("amqp:876").str(), "amqp:tcp:876:5672");
- BOOST_CHECK_EQUAL(Url("tcp:567").str(), "amqp:tcp:567:5672");
-}
-
-QPID_AUTO_TEST_CASE(TestParseIPv6) {
- Url u1("[::]");
- BOOST_CHECK_EQUAL(u1[0].host, "::");
- BOOST_CHECK_EQUAL(u1[0].port, 5672);
- Url u2("[::1]");
- BOOST_CHECK_EQUAL(u2[0].host, "::1");
- BOOST_CHECK_EQUAL(u2[0].port, 5672);
- Url u3("[::127.0.0.1]");
- BOOST_CHECK_EQUAL(u3[0].host, "::127.0.0.1");
- BOOST_CHECK_EQUAL(u3[0].port, 5672);
- Url u4("[2002::222:68ff:fe0b:e61a]");
- BOOST_CHECK_EQUAL(u4[0].host, "2002::222:68ff:fe0b:e61a");
- BOOST_CHECK_EQUAL(u4[0].port, 5672);
- Url u5("[2002::222:68ff:fe0b:e61a]:123");
- BOOST_CHECK_EQUAL(u5[0].host, "2002::222:68ff:fe0b:e61a");
- BOOST_CHECK_EQUAL(u5[0].port, 123);
-}
-
QPID_AUTO_TEST_CASE(TestParseMultiAddress) {
Url::addProtocol("xyz");
URL_CHECK_STR("amqp:tcp:host:0,xyz:foo:123,tcp:foo:0,xyz:bar:1");
diff --git a/cpp/src/tests/Variant.cpp b/cpp/src/tests/Variant.cpp
index 40f1c0cf75..b4188f524b 100644
--- a/cpp/src/tests/Variant.cpp
+++ b/cpp/src/tests/Variant.cpp
@@ -86,64 +86,6 @@ QPID_AUTO_TEST_CASE(testConversions)
BOOST_CHECK_THROW(value.asBool(), InvalidConversion);
}
-QPID_AUTO_TEST_CASE(testConversionsFromString)
-{
- Variant value;
- value = "5";
- BOOST_CHECK_EQUAL(5, value.asInt16());
- BOOST_CHECK_EQUAL(5u, value.asUint16());
-
- value = "-5";
- BOOST_CHECK_EQUAL(-5, value.asInt16());
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
-
- value = "18446744073709551615";
- BOOST_CHECK_EQUAL(18446744073709551615ull, value.asUint64());
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "9223372036854775808";
- BOOST_CHECK_EQUAL(9223372036854775808ull, value.asUint64());
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "-9223372036854775809";
- BOOST_CHECK_THROW(value.asUint64(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt64(), InvalidConversion);
-
- value = "2147483648";
- BOOST_CHECK_EQUAL(2147483648ul, value.asUint32());
- BOOST_CHECK_THROW(value.asInt32(), InvalidConversion);
-
- value = "-2147483649";
- BOOST_CHECK_THROW(value.asUint32(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt32(), InvalidConversion);
-
- value = "32768";
- BOOST_CHECK_EQUAL(32768u, value.asUint16());
- BOOST_CHECK_THROW(value.asInt16(), InvalidConversion);
-
- value = "-32769";
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
- BOOST_CHECK_THROW(value.asInt16(), InvalidConversion);
-
- value = "-2.5";
- BOOST_CHECK_EQUAL(-2.5, value.asFloat());
-
- value = "-0.875432e10";
- BOOST_CHECK_EQUAL(-0.875432e10, value.asDouble());
-
- value = "-0";
- BOOST_CHECK_EQUAL(0, value.asInt16());
- BOOST_CHECK_EQUAL(0u, value.asUint16());
-
- value = "-000";
- BOOST_CHECK_EQUAL(0, value.asInt16());
- BOOST_CHECK_EQUAL(0u, value.asUint16());
-
- value = "-0010";
- BOOST_CHECK_EQUAL(-10, value.asInt16());
- BOOST_CHECK_THROW(value.asUint16(), InvalidConversion);
-}
-
QPID_AUTO_TEST_CASE(testSizeConversionsUint)
{
Variant value;
diff --git a/cpp/src/tests/XmlClientSessionTest.cpp b/cpp/src/tests/XmlClientSessionTest.cpp
index b94c35ece0..b3b7f12b53 100644
--- a/cpp/src/tests/XmlClientSessionTest.cpp
+++ b/cpp/src/tests/XmlClientSessionTest.cpp
@@ -90,7 +90,7 @@ struct SimpleListener : public MessageListener
}
};
-struct ClientSessionFixture : public SessionFixture
+struct ClientSessionFixture : public ProxySessionFixture
{
void declareSubscribe(const string& q="odd_blue",
const string& dest="xml")
diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py
index 65d5242e51..2d6a5b489d 100755
--- a/cpp/src/tests/acl.py
+++ b/cpp/src/tests/acl.py
@@ -26,11 +26,10 @@ from qpid.datatypes import uuid4
from qpid.testlib import TestBase010
from qmf.console import Session
from qpid.datatypes import Message
-import qpid.messaging
class ACLFile:
- def __init__(self, policy='data_dir/policy.acl'):
- self.f = open(policy,'w')
+ def __init__(self):
+ self.f = open('data_dir/policy.acl','w');
def write(self,line):
self.f.write(line)
@@ -51,24 +50,14 @@ class ACLTests(TestBase010):
acl = self.qmf.getObjects(_class="acl")[0]
return acl.reloadACLFile()
- def get_acl_file(self):
- return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl"))
-
def setUp(self):
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow all all\n')
aclf.close()
TestBase010.setUp(self)
self.startQmf()
self.reload_acl()
-
- def tearDown(self):
- aclf = self.get_acl_file()
- aclf.write('acl allow all all\n')
- aclf.close()
- self.reload_acl()
- TestBase010.tearDown(self)
-
+
#=====================================
# ACL general tests
#=====================================
@@ -77,7 +66,7 @@ class ACLTests(TestBase010):
"""
Test the deny all mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow anonymous all all\n')
aclf.write('acl allow bob@QPID create queue\n')
aclf.write('acl deny all all')
@@ -105,7 +94,7 @@ class ACLTests(TestBase010):
"""
Test the allow all mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID bind exchange\n')
aclf.write('acl allow all all')
aclf.close()
@@ -137,7 +126,7 @@ class ACLTests(TestBase010):
"""
Test empty groups
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl group\n')
aclf.write('acl group admins bob@QPID joe@QPID\n')
aclf.write('acl allow all all')
@@ -151,7 +140,7 @@ class ACLTests(TestBase010):
"""
Test illegal acl formats
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl group admins bob@QPID joe@QPID\n')
aclf.write('acl allow all all')
aclf.close()
@@ -165,7 +154,7 @@ class ACLTests(TestBase010):
Test illegal extension lines
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group admins bob@QPID \n')
aclf.write(' \ \n')
aclf.write('joe@QPID \n')
@@ -183,7 +172,7 @@ class ACLTests(TestBase010):
"""
Test proper extention lines
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe@EXAMPLE.com \\ \n') # should be allowed
aclf.write(' jack@EXAMPLE.com \\ \n') # should be allowed
aclf.write('jill@TEST.COM \\ \n') # should be allowed
@@ -200,7 +189,7 @@ class ACLTests(TestBase010):
Test a user defined without a realm
Ex. group admin rajith
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group admin bob\n') # shouldn't be allowed
aclf.write('acl deny admin bind exchange\n')
aclf.write('acl allow all all')
@@ -215,7 +204,7 @@ class ACLTests(TestBase010):
Test a user defined without a realm
Ex. group admin rajith
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe@EXAMPLE.com\n') # should be allowed
aclf.write('group test2 jack_123-jill@EXAMPLE.com\n') # should be allowed
aclf.write('group test4 host/somemachine.example.com@EXAMPLE.COM\n') # should be allowed
@@ -226,7 +215,7 @@ class ACLTests(TestBase010):
if (result.text.find("ACL format error",0,len(result.text)) != -1):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('group test1 joe$H@EXAMPLE.com\n') # shouldn't be allowed
aclf.write('acl allow all all')
aclf.close()
@@ -244,7 +233,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ding\n')
aclf.write('acl allow all all')
aclf.close()
@@ -260,7 +249,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=-1\n')
aclf.write('acl allow all all')
aclf.close()
@@ -271,7 +260,7 @@ class ACLTests(TestBase010):
if (result.text != expected):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=9223372036854775808\n')
aclf.write('acl allow all all')
aclf.close()
@@ -288,7 +277,7 @@ class ACLTests(TestBase010):
Test illegal queue policy
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=-1\n')
aclf.write('acl allow all all')
aclf.close()
@@ -299,7 +288,7 @@ class ACLTests(TestBase010):
if (result.text != expected):
self.fail(result)
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=9223372036854775808\n')
aclf.write('acl allow all all')
aclf.close()
@@ -319,7 +308,7 @@ class ACLTests(TestBase010):
"""
Test cases for queue acl in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create queue name=q1 durable=true passive=true\n')
aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ring\n')
aclf.write('acl deny bob@QPID access queue name=q3\n')
@@ -422,7 +411,7 @@ class ACLTests(TestBase010):
"""
Test cases for queue acl in deny mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID create queue name=q1 durable=true passive=true\n')
aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true policytype=ring\n')
aclf.write('acl allow bob@QPID access queue name=q3\n')
@@ -545,7 +534,7 @@ class ACLTests(TestBase010):
"""
Test cases for exchange acl in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID create exchange name=testEx durable=true passive=true\n')
aclf.write('acl deny bob@QPID create exchange name=ex1 type=direct\n')
aclf.write('acl deny bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n')
@@ -676,7 +665,7 @@ class ACLTests(TestBase010):
"""
Test cases for exchange acl in deny mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID create exchange name=myEx durable=true passive=false\n')
aclf.write('acl allow bob@QPID bind exchange name=amq.topic queuename=bar routingkey=foo.*\n')
aclf.write('acl allow bob@QPID unbind exchange name=amq.topic queuename=bar routingkey=foo.*\n')
@@ -783,52 +772,6 @@ class ACLTests(TestBase010):
if (403 == e.args[0].error_code):
self.fail("ACL should allow exchange delete request for myEx");
- def test_create_and_delete_exchange_via_qmf(self):
- """
- Test acl is enforced when creating/deleting via QMF
- methods. Note that in order to be able to send the QMF methods
- and receive the responses a significant amount of permissions
- need to be enabled (TODO: can the set below be narrowed down
- at all?)
- """
- aclf = self.get_acl_file()
- aclf.write('acl allow bob@QPID create exchange\n')
- aclf.write('acl allow admin@QPID delete exchange\n')
- aclf.write('acl allow all access exchange\n')
- aclf.write('acl allow all bind exchange\n')
- aclf.write('acl allow all create queue\n')
- aclf.write('acl allow all access queue\n')
- aclf.write('acl allow all delete queue\n')
- aclf.write('acl allow all consume queue\n')
- aclf.write('acl allow all access method\n')
- aclf.write('acl deny all all')
- aclf.close()
-
- result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
- self.fail(result)
-
- bob = BrokerAdmin(self.config.broker, "bob", "bob")
- bob.create_exchange("my-exchange") #should pass
- #cleanup by deleting exchange
- try:
- bob.delete_exchange("my-exchange") #should fail
- self.fail("ACL should deny exchange delete request for my-exchange");
- except Exception, e:
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- admin = BrokerAdmin(self.config.broker, "admin", "admin")
- admin.delete_exchange("my-exchange") #should pass
-
- anonymous = BrokerAdmin(self.config.broker)
- try:
- anonymous.create_exchange("another-exchange") #should fail
- self.fail("ACL should deny exchange create request for another-exchange");
- except Exception, e:
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
-
-
#=====================================
# ACL consume tests
#=====================================
@@ -837,7 +780,7 @@ class ACLTests(TestBase010):
"""
Test cases for consume in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID consume queue name=q1\n')
aclf.write('acl deny bob@QPID consume queue name=q2\n')
aclf.write('acl allow all all')
@@ -883,7 +826,7 @@ class ACLTests(TestBase010):
"""
Test cases for consume in allow mode
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID consume queue name=q1\n')
aclf.write('acl allow bob@QPID consume queue name=q2\n')
aclf.write('acl allow bob@QPID create queue\n')
@@ -929,7 +872,7 @@ class ACLTests(TestBase010):
"""
Test various publish acl
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl deny bob@QPID publish exchange name=amq.direct routingkey=rk1\n')
aclf.write('acl deny bob@QPID publish exchange name=amq.topic\n')
aclf.write('acl deny bob@QPID publish exchange name=myEx routingkey=rk2\n')
@@ -978,7 +921,7 @@ class ACLTests(TestBase010):
"""
Test various publish acl
"""
- aclf = self.get_acl_file()
+ aclf = ACLFile()
aclf.write('acl allow bob@QPID publish exchange name=amq.direct routingkey=rk1\n')
aclf.write('acl allow bob@QPID publish exchange name=amq.topic\n')
aclf.write('acl allow bob@QPID publish exchange name=myEx routingkey=rk2\n')
@@ -1029,113 +972,3 @@ class ACLTests(TestBase010):
except qpid.session.SessionException, e:
if (403 == e.args[0].error_code):
self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1");
-
- #=====================================
- # ACL broker configuration tests
- #=====================================
-
- def test_broker_timestamp_config(self):
- """
- Test ACL control of the broker timestamp configuration
- """
- aclf = self.get_acl_file()
- # enable lots of stuff to allow QMF to work
- aclf.write('acl allow all create exchange\n')
- aclf.write('acl allow all access exchange\n')
- aclf.write('acl allow all bind exchange\n')
- aclf.write('acl allow all publish exchange\n')
- aclf.write('acl allow all create queue\n')
- aclf.write('acl allow all access queue\n')
- aclf.write('acl allow all delete queue\n')
- aclf.write('acl allow all consume queue\n')
- aclf.write('acl allow all access method\n')
- # this should let bob access the timestamp configuration
- aclf.write('acl allow bob@QPID access broker\n')
- aclf.write('acl allow admin@QPID all all\n')
- aclf.write('acl deny all all')
- aclf.close()
-
- result = self.reload_acl()
- if (result.text.find("format error",0,len(result.text)) != -1):
- self.fail(result)
-
- ts = None
- bob = BrokerAdmin(self.config.broker, "bob", "bob")
- ts = bob.get_timestamp_cfg() #should work
- bob.set_timestamp_cfg(ts); #should work
-
- obo = BrokerAdmin(self.config.broker, "obo", "obo")
- try:
- ts = obo.get_timestamp_cfg() #should fail
- failed = False
- except Exception, e:
- failed = True
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- assert(failed)
-
- try:
- obo.set_timestamp_cfg(ts) #should fail
- failed = False
- except Exception, e:
- failed = True
- self.assertEqual(7,e.args[0]["error_code"])
- assert e.args[0]["error_text"].find("unauthorized-access") == 0
- assert(failed)
-
- admin = BrokerAdmin(self.config.broker, "admin", "admin")
- ts = admin.get_timestamp_cfg() #should pass
- admin.set_timestamp_cfg(ts) #should pass
-
-
-class BrokerAdmin:
- def __init__(self, broker, username=None, password=None):
- self.connection = qpid.messaging.Connection(broker)
- if username:
- self.connection.username = username
- self.connection.password = password
- self.connection.sasl_mechanisms = "PLAIN"
- self.connection.open()
- self.session = self.connection.session()
- self.sender = self.session.sender("qmf.default.direct/broker")
- self.reply_to = "responses-#; {create:always}"
- self.receiver = self.session.receiver(self.reply_to)
-
- def invoke(self, method, arguments):
- content = {
- "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"},
- "_method_name": method,
- "_arguments": arguments
- }
- request = qpid.messaging.Message(reply_to=self.reply_to, content=content)
- request.properties["x-amqp-0-10.app-id"] = "qmf2"
- request.properties["qmf.opcode"] = "_method_request"
- self.sender.send(request)
- response = self.receiver.fetch()
- self.session.acknowledge()
- if response.properties['x-amqp-0-10.app-id'] == 'qmf2':
- if response.properties['qmf.opcode'] == '_method_response':
- return response.content['_arguments']
- elif response.properties['qmf.opcode'] == '_exception':
- raise Exception(response.content['_values'])
- else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode'])
- else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id'])
- def create_exchange(self, name, exchange_type=None, options={}):
- properties = options
- if exchange_type: properties["exchange_type"] = exchange_type
- self.invoke("create", {"type": "exchange", "name":name, "properties":properties})
-
- def create_queue(self, name, properties={}):
- self.invoke("create", {"type": "queue", "name":name, "properties":properties})
-
- def delete_exchange(self, name):
- self.invoke("delete", {"type": "exchange", "name":name})
-
- def delete_queue(self, name):
- self.invoke("delete", {"type": "queue", "name":name})
-
- def get_timestamp_cfg(self):
- return self.invoke("getTimestampConfig", {})
-
- def set_timestamp_cfg(self, receive):
- return self.invoke("getTimestampConfig", {"receive":receive})
diff --git a/cpp/src/tests/allhosts b/cpp/src/tests/allhosts
index 4b4b943156..e43571aed4 100755
--- a/cpp/src/tests/allhosts
+++ b/cpp/src/tests/allhosts
@@ -29,12 +29,11 @@ Options:
-s SECONDS sleep between starting commands.
-q don't print banner lines for each host.
-o SUFFIX log output of each command to <host>.SUFFIX
- -X passed to ssh - forward X connection.
"
exit 1
}
-while getopts "tl:bs:dqo:X" opt; do
+while getopts "tl:bs:dqo:" opt; do
case $opt in
l) SSHOPTS="-l$OPTARG $SSHOPTS" ;;
t) SSHOPTS="-t $SSHOPTS" ;;
@@ -43,7 +42,6 @@ while getopts "tl:bs:dqo:X" opt; do
s) SLEEP="sleep $OPTARG" ;;
q) NOBANNER=1 ;;
o) SUFFIX=$OPTARG ;;
- X) SSHOPTS="-X $SSHOPTS" ;;
*) usage;;
esac
done
diff --git a/cpp/src/tests/brokertest.py b/cpp/src/tests/brokertest.py
index 16d7fb0b78..98f58ebfdd 100644
--- a/cpp/src/tests/brokertest.py
+++ b/cpp/src/tests/brokertest.py
@@ -29,7 +29,6 @@ from unittest import TestCase
from copy import copy
from threading import Thread, Lock, Condition
from logging import getLogger
-import qmf.console
log = getLogger("qpid.brokertest")
@@ -62,6 +61,24 @@ def is_running(pid):
class BadProcessStatus(Exception):
pass
+class ExceptionWrapper:
+ """Proxy object that adds a message to exceptions raised"""
+ def __init__(self, obj, msg):
+ self.obj = obj
+ self.msg = msg
+
+ def __getattr__(self, name):
+ func = getattr(self.obj, name)
+ if type(func) != callable:
+ return func
+ return lambda *args, **kwargs: self._wrap(func, args, kwargs)
+
+ def _wrap(self, func, args, kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception, e:
+ raise Exception("%s: %s" %(self.msg, str(e)))
+
def error_line(filename, n=1):
"""Get the last n line(s) of filename for error messages"""
result = []
@@ -71,8 +88,7 @@ def error_line(filename, n=1):
for l in f:
if len(result) == n: result.pop(0)
result.append(" "+l)
- finally:
- f.close()
+ finally: f.close()
except: return ""
return ":\n" + "".join(result)
@@ -80,90 +96,111 @@ def retry(function, timeout=10, delay=.01):
"""Call function until it returns True or timeout expires.
Double the delay for each retry. Return True if function
returns true, False if timeout expires."""
- deadline = time.time() + timeout
while not function():
- remaining = deadline - time.time()
- if remaining <= 0: return False
- delay = min(delay, remaining)
+ if delay > timeout: delay = timeout
time.sleep(delay)
+ timeout -= delay
+ if timeout <= 0: return False
delay *= 2
return True
-class AtomicCounter:
- def __init__(self):
- self.count = 0
- self.lock = Lock()
-
- def next(self):
- self.lock.acquire();
- ret = self.count
- self.count += 1
- self.lock.release();
- return ret
-
-_popen_id = AtomicCounter() # Popen identifier for use in output file names.
-
-# Constants for file descriptor arguments to Popen
-FILE = "FILE" # Write to file named after process
-PIPE = subprocess.PIPE
-
class Popen(subprocess.Popen):
"""
Can set and verify expectation of process status at end of test.
Dumps command line, stdout, stderr to data dir for debugging.
"""
- def __init__(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE):
- """Run cmd (should be a list of program and arguments)
+ class DrainThread(Thread):
+ """Thread to drain a file object and write the data to a file."""
+ def __init__(self, infile, outname):
+ Thread.__init__(self)
+ self.infile, self.outname = infile, outname
+ self.outfile = None
+
+ def run(self):
+ try:
+ for line in self.infile:
+ if self.outfile is None:
+ self.outfile = open(self.outname, "w")
+ self.outfile.write(line)
+ finally:
+ self.infile.close()
+ if self.outfile is not None: self.outfile.close()
+
+ class OutStream(ExceptionWrapper):
+ """Wrapper for output streams, handles exceptions & draining output"""
+ def __init__(self, infile, outfile, msg):
+ ExceptionWrapper.__init__(self, infile, msg)
+ self.infile, self.outfile = infile, outfile
+ self.thread = None
+
+ def drain(self):
+ if self.thread is None:
+ self.thread = Popen.DrainThread(self.infile, self.outfile)
+ self.thread.start()
+
+ def outfile(self, ext): return "%s.%s" % (self.pname, ext)
+
+ def __init__(self, cmd, expect=EXPECT_EXIT_OK, drain=True):
+ """Run cmd (should be a list of arguments)
expect - if set verify expectation at end of test.
- stdout, stderr - can have the same values as for subprocess.Popen as well as
- FILE (the default) which means write to a file named after the process.
- stdin - like subprocess.Popen but defauts to PIPE
+ drain - if true (default) drain stdout/stderr to files.
"""
self._clean = False
self._clean_lock = Lock()
assert find_exe(cmd[0]), "executable not found: "+cmd[0]
if type(cmd) is type(""): cmd = [cmd] # Make it a list.
self.cmd = [ str(x) for x in cmd ]
+ self.returncode = None
self.expect = expect
- self.id = _popen_id.next()
- self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.id)
- if stdout == FILE: stdout = open(self.outfile("out"), "w")
- if stderr == FILE: stderr = open(self.outfile("err"), "w")
try:
- subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None,
- stdin=stdin, stdout=stdout, stderr=stderr,
- close_fds=True)
- except ValueError: # Windows can't do close_fds
- subprocess.Popen.__init__(self, self.cmd, bufsize=0, executable=None,
- stdin=stdin, stdout=stdout, stderr=stderr)
-
+ subprocess.Popen.__init__(self, self.cmd, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE, close_fds=True)
+ except ValueError: # Windows can't do close_fds
+ subprocess.Popen.__init__(self, self.cmd, 0, None, subprocess.PIPE, subprocess.PIPE, subprocess.PIPE)
+ self.pname = "%s-%d" % (os.path.split(self.cmd[0])[1], self.pid)
+ msg = "Process %s" % self.pname
+ self.stdin = ExceptionWrapper(self.stdin, msg)
+ self.stdout = Popen.OutStream(self.stdout, self.outfile("out"), msg)
+ self.stderr = Popen.OutStream(self.stderr, self.outfile("err"), msg)
f = open(self.outfile("cmd"), "w")
- try: f.write("%s\n%d"%(self.cmd_str(), self.pid))
+ try: f.write(self.cmd_str())
finally: f.close()
log.debug("Started process %s: %s" % (self.pname, " ".join(self.cmd)))
+ if drain: self.drain()
- def __str__(self): return "Popen<%s>"%(self.pname)
+ def __str__(self): return "Popen<%s>"%(self.pname)
- def outfile(self, ext): return "%s.%s" % (self.pname, ext)
+ def drain(self):
+ """Start threads to drain stdout/err"""
+ self.stdout.drain()
+ self.stderr.drain()
+
+ def _cleanup(self):
+ """Close pipes to sub-process"""
+ self._clean_lock.acquire()
+ try:
+ if self._clean: return
+ self._clean = True
+ self.stdin.close()
+ self.drain() # Drain output pipes.
+ self.stdout.thread.join() # Drain thread closes pipe.
+ self.stderr.thread.join()
+ finally: self._clean_lock.release()
def unexpected(self,msg):
err = error_line(self.outfile("err")) or error_line(self.outfile("out"))
raise BadProcessStatus("%s %s%s" % (self.pname, msg, err))
-
+
def stop(self): # Clean up at end of test.
try:
if self.expect == EXPECT_UNKNOWN:
try: self.kill() # Just make sure its dead
except: pass
elif self.expect == EXPECT_RUNNING:
- if self.poll() != None:
- self.unexpected("expected running, exit code %d" % self.returncode)
- else:
- try:
- self.kill()
- except Exception,e:
- self.unexpected("exception from kill: %s" % str(e))
+ try:
+ self.kill()
+ except:
+ self.unexpected("expected running, exit code %d" % self.wait())
else:
retry(lambda: self.poll() is not None)
if self.returncode is None: # Still haven't stopped
@@ -175,21 +212,40 @@ class Popen(subprocess.Popen):
self.unexpected("expected error")
finally:
self.wait() # Clean up the process.
-
+
def communicate(self, input=None):
- ret = subprocess.Popen.communicate(self, input)
- self.cleanup()
- return ret
+ if input:
+ self.stdin.write(input)
+ self.stdin.close()
+ outerr = (self.stdout.read(), self.stderr.read())
+ self.wait()
+ return outerr
- def is_running(self): return self.poll() is None
+ def is_running(self):
+ return self.poll() is None
def assert_running(self):
if not self.is_running(): self.unexpected("Exit code %d" % self.returncode)
+ def poll(self, _deadstate=None): # _deadstate required by base class in python 2.4
+ if self.returncode is None:
+ # Pass _deadstate only if it has been set, there is no _deadstate
+ # parameter in Python 2.6
+ if _deadstate is None: ret = subprocess.Popen.poll(self)
+ else: ret = subprocess.Popen.poll(self, _deadstate)
+
+ if (ret != -1):
+ self.returncode = ret
+ self._cleanup()
+ return self.returncode
+
def wait(self):
- ret = subprocess.Popen.wait(self)
- self._cleanup()
- return ret
+ if self.returncode is None:
+ self.drain()
+ try: self.returncode = subprocess.Popen.wait(self)
+ except OSError,e: raise OSError("Wait failed %s: %s"%(self.pname, e))
+ self._cleanup()
+ return self.returncode
def terminate(self):
try: subprocess.Popen.terminate(self)
@@ -198,8 +254,7 @@ class Popen(subprocess.Popen):
os.kill( self.pid , signal.SIGTERM)
except AttributeError: # no os.kill, using taskkill.. (Windows only)
os.popen('TASKKILL /PID ' +str(self.pid) + ' /F')
- self._cleanup()
-
+
def kill(self):
try: subprocess.Popen.kill(self)
except AttributeError: # No terminate method
@@ -207,20 +262,6 @@ class Popen(subprocess.Popen):
os.kill( self.pid , signal.SIGKILL)
except AttributeError: # no os.kill, using taskkill.. (Windows only)
os.popen('TASKKILL /PID ' +str(self.pid) + ' /F')
- self._cleanup()
-
- def _cleanup(self):
- """Clean up after a dead process"""
- self._clean_lock.acquire()
- if not self._clean:
- self._clean = True
- try: self.stdin.close()
- except: pass
- try: self.stdout.close()
- except: pass
- try: self.stderr.close()
- except: pass
- self._clean_lock.release()
def cmd_str(self): return " ".join([str(s) for s in self.cmd])
@@ -247,11 +288,11 @@ class Broker(Popen):
while (os.path.exists(self.log)):
self.log = "%s-%d.log" % (self.name, i)
i += 1
-
+
def get_log(self):
return os.path.abspath(self.log)
- def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None, show_cmd=False):
+ def __init__(self, test, args=[], name=None, expect=EXPECT_RUNNING, port=0, log_level=None, wait=None):
"""Start a broker daemon. name determines the data-dir and log
file names."""
@@ -277,20 +318,15 @@ class Broker(Popen):
cmd += ["--log-to-file", self.log]
cmd += ["--log-to-stderr=no"]
if log_level != None:
- cmd += ["--log-enable=%s" % log_level]
+ cmd += ["--log-enable=%s" % log_level]
self.datadir = self.name
cmd += ["--data-dir", self.datadir]
- if show_cmd: print cmd
- Popen.__init__(self, cmd, expect, stdout=PIPE)
+ Popen.__init__(self, cmd, expect, drain=False)
test.cleanup_stop(self)
self._host = "127.0.0.1"
log.debug("Started broker %s (%s, %s)" % (self.name, self.pname, self.log))
self._log_ready = False
- def startQmf(self, handler=None):
- self.qmf_session = qmf.console.Session(handler)
- self.qmf_broker = self.qmf_session.addBroker("%s:%s" % (self.host(), self.port()))
-
def host(self): return self._host
def port(self):
@@ -321,7 +357,7 @@ class Broker(Popen):
s = c.session(str(qpid.datatypes.uuid4()))
s.queue_declare(queue=queue)
c.close()
-
+
def _prep_sender(self, queue, durable, xprops):
s = queue + "; {create:always, node:{durable:" + str(durable)
if xprops != None: s += ", x-declare:{" + xprops + "}"
@@ -365,14 +401,13 @@ class Broker(Popen):
def log_ready(self):
"""Return true if the log file exists and contains a broker ready message"""
- if not self._log_ready:
- self._log_ready = find_in_file("notice Broker running", self.log)
- return self._log_ready
+ if self._log_ready: return True
+ self._log_ready = find_in_file("notice Broker running", self.log)
def ready(self, **kwargs):
"""Wait till broker is ready to serve clients"""
# First make sure the broker is listening by checking the log.
- if not retry(self.log_ready, timeout=60):
+ if not retry(self.log_ready, timeout=30):
raise Exception(
"Timed out waiting for broker %s%s"%(self.name, error_line(self.log,5)))
# Create a connection and a session. For a cluster broker this will
@@ -381,27 +416,23 @@ class Broker(Popen):
c = self.connect(**kwargs)
try: c.session()
finally: c.close()
- except Exception,e: raise RethrownException(
- "Broker %s not responding: (%s)%s"%(self.name,e,error_line(self.log, 5)))
+ except: raise RethrownException(
+ "Broker %s failed ready test%s"%(self.name,error_line(self.log, 5)))
def store_state(self):
- f = open(os.path.join(self.datadir, "cluster", "store.status"))
- try: uuids = f.readlines()
- finally: f.close()
+ uuids = open(os.path.join(self.datadir, "cluster", "store.status")).readlines()
null_uuid="00000000-0000-0000-0000-000000000000\n"
if len(uuids) < 2: return "unknown" # we looked while the file was being updated.
if uuids[0] == null_uuid: return "empty"
if uuids[1] == null_uuid: return "dirty"
return "clean"
-
+
class Cluster:
"""A cluster of brokers in a test."""
- # Client connection options for use in failover tests.
- CONNECTION_OPTIONS = "reconnect:true,reconnect-timeout:10,reconnect-urls-replace:true"
_cluster_count = 0
- def __init__(self, test, count=0, args=[], expect=EXPECT_RUNNING, wait=True, show_cmd=False):
+ def __init__(self, test, count=0, args=[], expect=EXPECT_RUNNING, wait=True):
self.test = test
self._brokers=[]
self.name = "cluster%d" % Cluster._cluster_count
@@ -412,19 +443,16 @@ class Cluster:
self.args += [ "--log-enable=info+", "--log-enable=debug+:cluster"]
assert BrokerTest.cluster_lib, "Cannot locate cluster plug-in"
self.args += [ "--load-module", BrokerTest.cluster_lib ]
- self.start_n(count, expect=expect, wait=wait, show_cmd=show_cmd)
+ self.start_n(count, expect=expect, wait=wait)
- def start(self, name=None, expect=EXPECT_RUNNING, wait=True, args=[], port=0, show_cmd=False):
+ def start(self, name=None, expect=EXPECT_RUNNING, wait=True, args=[], port=0):
"""Add a broker to the cluster. Returns the index of the new broker."""
if not name: name="%s-%d" % (self.name, len(self._brokers))
- self._brokers.append(self.test.broker(self.args+args, name, expect, wait, port=port, show_cmd=show_cmd))
+ self._brokers.append(self.test.broker(self.args+args, name, expect, wait, port=port))
return self._brokers[-1]
- def ready(self):
- for b in self: b.ready()
-
- def start_n(self, count, expect=EXPECT_RUNNING, wait=True, args=[], show_cmd=False):
- for i in range(count): self.start(expect=expect, wait=wait, args=args, show_cmd=show_cmd)
+ def start_n(self, count, expect=EXPECT_RUNNING, wait=True, args=[]):
+ for i in range(count): self.start(expect=expect, wait=wait, args=args)
# Behave like a list of brokers.
def __len__(self): return len(self._brokers)
@@ -453,7 +481,7 @@ class BrokerTest(TestCase):
rootdir = os.getcwd()
def configure(self, config): self.config=config
-
+
def setUp(self):
outdir = self.config.defines.get("OUTDIR") or "brokertest.tmp"
self.dir = os.path.join(self.rootdir, outdir, self.id())
@@ -474,49 +502,40 @@ class BrokerTest(TestCase):
"""Call thing.stop at end of test"""
self.stopem.append(stopable)
- def popen(self, cmd, expect=EXPECT_EXIT_OK, stdin=None, stdout=FILE, stderr=FILE):
+ def popen(self, cmd, expect=EXPECT_EXIT_OK, drain=True):
"""Start a process that will be killed at end of test, in the test dir."""
os.chdir(self.dir)
- p = Popen(cmd, expect, stdin=stdin, stdout=stdout, stderr=stderr)
+ p = Popen(cmd, expect, drain)
self.cleanup_stop(p)
return p
- def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, log_level=None, show_cmd=False):
+ def broker(self, args=[], name=None, expect=EXPECT_RUNNING, wait=True, port=0, log_level=None):
"""Create and return a broker ready for use"""
- b = Broker(self, args=args, name=name, expect=expect, port=port, log_level=log_level, show_cmd=show_cmd)
+ b = Broker(self, args=args, name=name, expect=expect, port=port, log_level=log_level)
if (wait):
try: b.ready()
except Exception, e:
raise RethrownException("Failed to start broker %s(%s): %s" % (b.name, b.log, e))
return b
- def cluster(self, count=0, args=[], expect=EXPECT_RUNNING, wait=True, show_cmd=False):
+ def cluster(self, count=0, args=[], expect=EXPECT_RUNNING, wait=True):
"""Create and return a cluster ready for use"""
- cluster = Cluster(self, count, args, expect=expect, wait=wait, show_cmd=show_cmd)
+ cluster = Cluster(self, count, args, expect=expect, wait=wait)
return cluster
- def browse(self, session, queue, timeout=0):
- """Return a list with the contents of each message on queue."""
- r = session.receiver("%s;{mode:browse}"%(queue))
- r.capacity = 100
- try:
- contents = []
- try:
- while True: contents.append(r.fetch(timeout=timeout).content)
- except messaging.Empty: pass
- finally: r.close()
- return contents
-
def assert_browse(self, session, queue, expect_contents, timeout=0):
"""Assert that the contents of messages on queue (as retrieved
using session and timeout) exactly match the strings in
expect_contents"""
- actual_contents = self.browse(session, queue, timeout)
- self.assertEqual(expect_contents, actual_contents)
-def join(thread, timeout=10):
- thread.join(timeout)
- if thread.isAlive(): raise Exception("Timed out joining thread %s"%thread)
+ r = session.receiver("%s;{mode:browse}"%(queue))
+ actual_contents = []
+ try:
+ for c in expect_contents: actual_contents.append(r.fetch(timeout=timeout).content)
+ while True: actual_contents.append(r.fetch(timeout=0).content) # Check for extra messages.
+ except messaging.Empty: pass
+ r.close()
+ self.assertEqual(expect_contents, actual_contents)
class RethrownException(Exception):
"""Captures the stack trace of the current exception to be thrown later"""
@@ -535,16 +554,15 @@ class StoppableThread(Thread):
def stop(self):
self.stopped = True
- join(self)
+ self.join()
if self.error: raise self.error
-
+
class NumberedSender(Thread):
"""
Thread to run a sender client and send numbered messages until stopped.
"""
- def __init__(self, broker, max_depth=None, queue="test-queue",
- connection_options=Cluster.CONNECTION_OPTIONS):
+ def __init__(self, broker, max_depth=None, queue="test-queue"):
"""
max_depth: enable flow control, ensure sent - received <= max_depth.
Requires self.notify_received(n) to be called each time messages are received.
@@ -555,11 +573,9 @@ class NumberedSender(Thread):
"--broker", "localhost:%s"%broker.port(),
"--address", "%s;{create:always}"%queue,
"--failover-updates",
- "--connection-options", "{%s}"%(connection_options),
"--content-stdin"
],
- expect=EXPECT_RUNNING,
- stdin=PIPE)
+ expect=EXPECT_RUNNING)
self.condition = Condition()
self.max = max_depth
self.received = 0
@@ -574,7 +590,6 @@ class NumberedSender(Thread):
try:
self.sent = 0
while not self.stopped:
- self.sender.assert_running()
if self.max:
self.condition.acquire()
while not self.stopped and self.sent - self.received > self.max:
@@ -597,17 +612,16 @@ class NumberedSender(Thread):
self.stopped = True
self.condition.notify()
finally: self.condition.release()
- join(self)
+ self.join()
self.write_message(-1) # end-of-messages marker.
if self.error: raise self.error
-
+
class NumberedReceiver(Thread):
"""
Thread to run a receiver client and verify it receives
sequentially numbered messages.
"""
- def __init__(self, broker, sender = None, queue="test-queue",
- connection_options=Cluster.CONNECTION_OPTIONS):
+ def __init__(self, broker, sender = None, queue="test-queue"):
"""
sender: enable flow control. Call sender.received(n) for each message received.
"""
@@ -618,24 +632,22 @@ class NumberedReceiver(Thread):
"--broker", "localhost:%s"%broker.port(),
"--address", "%s;{create:always}"%queue,
"--failover-updates",
- "--connection-options", "{%s}"%(connection_options),
"--forever"
],
expect=EXPECT_RUNNING,
- stdout=PIPE)
+ drain=False)
self.lock = Lock()
self.error = None
self.sender = sender
- self.received = 0
def read_message(self):
return int(self.receiver.stdout.readline())
-
+
def run(self):
try:
+ self.received = 0
m = self.read_message()
while m != -1:
- self.receiver.assert_running()
assert(m <= self.received) # Check for missing messages
if (m == self.received): # Ignore duplicates
self.received += 1
@@ -647,7 +659,7 @@ class NumberedReceiver(Thread):
def stop(self):
"""Returns when termination message is received"""
- join(self)
+ self.join()
if self.error: raise self.error
class ErrorGenerator(StoppableThread):
@@ -662,7 +674,7 @@ class ErrorGenerator(StoppableThread):
self.broker=broker
broker.test.cleanup_stop(self)
self.start()
-
+
def run(self):
c = self.broker.connect_old()
try:
diff --git a/cpp/src/tests/cli_tests.py b/cpp/src/tests/cli_tests.py
index 6c75927461..deef03279d 100755
--- a/cpp/src/tests/cli_tests.py
+++ b/cpp/src/tests/cli_tests.py
@@ -365,26 +365,6 @@ class CliTests(TestBase010):
self.assertEqual(queue._altExchange_.name, altName)
self.assertEqual(found, True)
- def test_qpid_config_list_queues_arguments(self):
- """
- Test to verify that when the type of a policy limit is
- actually a string (though still a valid value), it does not
- upset qpid-config
- """
- self.startQmf();
- qmf = self.qmf
-
- names = ["queue_capacity%s" % (i) for i in range(1, 6)]
- for name in names:
- self.session.queue_declare(queue=name, exclusive=True,
- arguments={'qpid.max_count' : str(i), 'qpid.max_size': '100'})
-
- output = os.popen(self.qpid_config_command(" queues")).readlines()
- queues = [line.split()[0] for line in output[2:len(output)]] #ignore first two lines (header)
-
- for name in names:
- assert name in queues, "%s not in %s" % (name, queues)
-
def test_qpid_route(self):
self.startQmf();
qmf = self.qmf
@@ -425,7 +405,7 @@ class CliTests(TestBase010):
qmf = self.qmf
ret = self.qpid_route_api("dynamic add "
- + " --client-sasl-mechanism PLAIN "
+ + " --sasl-mechanism PLAIN "
+ "guest/guest@localhost:"+str(self.broker.port) + " "
+ str(self.remote_host())+":"+str(self.remote_port()) + " "
+"amq.direct")
@@ -444,7 +424,7 @@ class CliTests(TestBase010):
qmf = self.qmf
ret = self.qpid_route_api("dynamic add "
- + " --client-sasl-mechanism PLAIN "
+ + " --sasl-mechanism PLAIN "
+ "localhost:"+str(self.broker.port) + " "
+ str(self.remote_host())+":"+str(self.remote_port()) + " "
+"amq.direct")
diff --git a/cpp/src/tests/cluster_python_tests_failing.txt b/cpp/src/tests/cluster_python_tests_failing.txt
index f8639d7b59..7ba8089946 100644
--- a/cpp/src/tests/cluster_python_tests_failing.txt
+++ b/cpp/src/tests/cluster_python_tests_failing.txt
@@ -1,4 +1,32 @@
qpid_tests.broker_0_10.management.ManagementTest.test_purge_queue
qpid_tests.broker_0_10.management.ManagementTest.test_connection_close
+qpid_tests.broker_0_10.dtx.DtxTests.test_bad_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_commit_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_end
+qpid_tests.broker_0_10.dtx.DtxTests.test_end_suspend_and_fail
+qpid_tests.broker_0_10.dtx.DtxTests.test_end_unknown_xid
+qpid_tests.broker_0_10.dtx.DtxTests.test_forget_xid_on_completion
+qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout
+qpid_tests.broker_0_10.dtx.DtxTests.test_get_timeout_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_implicit_end
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_false
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_commit_one_phase_true
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_prepare_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_invalid_rollback_not_ended
+qpid_tests.broker_0_10.dtx.DtxTests.test_prepare_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_recover
+qpid_tests.broker_0_10.dtx.DtxTests.test_rollback_unknown
+qpid_tests.broker_0_10.dtx.DtxTests.test_select_required
+qpid_tests.broker_0_10.dtx.DtxTests.test_set_timeout
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_commit
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_prepare_rollback
+qpid_tests.broker_0_10.dtx.DtxTests.test_simple_rollback
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_already_known
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_join
+qpid_tests.broker_0_10.dtx.DtxTests.test_start_join_and_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_resume
+qpid_tests.broker_0_10.dtx.DtxTests.test_suspend_start_end_resume
qpid_tests.broker_0_10.message.MessageTests.test_ttl
qpid_tests.broker_0_10.management.ManagementTest.test_broker_connectivity_oldAPI
diff --git a/cpp/src/tests/cluster_test_logs.py b/cpp/src/tests/cluster_test_logs.py
index 3c7e8e8020..1fa9014d11 100755
--- a/cpp/src/tests/cluster_test_logs.py
+++ b/cpp/src/tests/cluster_test_logs.py
@@ -53,19 +53,16 @@ def filter_log(log):
'stall for update|unstall, ignore update|cancelled offer .* unstall',
'caught up',
'active for links|Passivating links|Activating links',
- 'info Connecting: .*', # UpdateClient connection
'info Connection.* connected to', # UpdateClient connection
- 'warning Connection \\[[-0-9.: ]+\\] closed', # UpdateClient connection
+ 'warning Connection [\d+ [0-9.:]+] closed', # UpdateClient connection
'warning Broker closed connection: 200, OK',
'task late',
'task overran',
'warning CLOSING .* unsent data',
'Inter-broker link ',
- 'Running in a cluster, marking store',
- 'debug Sending keepalive signal to watchdog', # Watchdog timer thread
- 'last broker standing joined by 1 replicas, updating queue policies.',
- 'Connection .* timed out: closing' # heartbeat connection close
+ 'Running in a cluster, marking store'
])
+ skip_re = re.compile(skip)
# Regex to match a UUID
uuid='\w\w\w\w\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w-\w\w\w\w\w\w\w\w\w\w\w\w'
# Substitutions to remove expected differences
@@ -83,13 +80,6 @@ def filter_log(log):
(r' map={.*_object_name:([^,}]*)[,}].*', r' \1'), # V2 map - just keep name
(r'\d+-\d+-\d+--\d+', 'X-X-X--X'), # V1 Object IDs
]
- # Substitutions to mask known issue: durable test shows inconsistent "changed stats for com.redhat.rhm.store:journal" messages.
- skip += '|Changed V[12] statistics com.redhat.rhm.store:journal'
- subs += [(r'to=console.obj.1.0.com.redhat.rhm.store.journal props=\d+ stats=\d+',
- 'to=console.obj.1.0.com.redhat.rhm.store.journal props=NN stats=NN')]
-
- skip_re = re.compile(skip)
- subs = [(re.compile(pattern), subst) for pattern, subst in subs]
for l in open(log):
if skip_re.search(l): continue
for pattern,subst in subs: l = re.sub(pattern,subst,l)
diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py
index 0e80e06d34..cbad4010b4 100755
--- a/cpp/src/tests/cluster_tests.py
+++ b/cpp/src/tests/cluster_tests.py
@@ -18,13 +18,12 @@
# under the License.
#
-import os, signal, sys, time, imp, re, subprocess, glob, random, logging
-import cluster_test_logs
+import os, signal, sys, time, imp, re, subprocess, glob, cluster_test_logs
from qpid import datatypes, messaging
from brokertest import *
from qpid.harness import Skipped
-from qpid.messaging import Message, Empty, Disposition, REJECTED, util
-from threading import Thread, Lock, Condition
+from qpid.messaging import Message, Empty
+from threading import Thread, Lock
from logging import getLogger
from itertools import chain
from tempfile import NamedTemporaryFile
@@ -97,15 +96,9 @@ class ShortTests(BrokerTest):
destination="amq.direct",
message=qpid.datatypes.Message(props, "content"))
- # Try message with TTL and differnet headers/properties
- cluster[0].send_message("q", Message(durable=True, ttl=100000))
- cluster[0].send_message("q", Message(durable=True, properties={}, ttl=100000))
- cluster[0].send_message("q", Message(durable=True, properties={"x":10}, ttl=100000))
-
# Now update a new member and compare their dumps.
cluster.start(args=["--test-store-dump", "updatee.dump"])
assert readfile("direct.dump") == readfile("updatee.dump")
-
os.remove("direct.dump")
os.remove("updatee.dump")
@@ -115,22 +108,19 @@ class ShortTests(BrokerTest):
acl=os.path.join(os.getcwd(), "policy.acl")
aclf=file(acl,"w")
aclf.write("""
-acl allow zig@QPID all all
-acl deny all all
+acl deny zag@QPID create queue
+acl allow all all
""")
aclf.close()
- cluster = self.cluster(1, args=["--auth", "yes",
+ cluster = self.cluster(2, args=["--auth", "yes",
"--sasl-config", sasl_config,
"--load-module", os.getenv("ACL_LIB"),
"--acl-file", acl])
# Valid user/password, ensure queue is created.
c = cluster[0].connect(username="zig", password="zig")
- c.session().sender("ziggy;{create:always,node:{x-declare:{exclusive:true}}}")
+ c.session().sender("ziggy;{create:always}")
c.close()
- cluster.start() # Start second node.
-
- # Check queue is created on second node.
c = cluster[1].connect(username="zig", password="zig")
c.session().receiver("ziggy;{assert:always}")
c.close()
@@ -159,7 +149,7 @@ acl deny all all
self.fail("Expected exception")
except messaging.exceptions.UnauthorizedAccess: pass
# make sure the queue was not created at the other node.
- c = cluster[1].connect(username="zig", password="zig")
+ c = cluster[0].connect(username="zag", password="zag")
try:
s = c.session()
s.sender("zaggy;{assert:always}")
@@ -167,35 +157,6 @@ acl deny all all
self.fail("Expected exception")
except messaging.exceptions.NotFound: pass
- def test_sasl_join(self):
- """Verify SASL authentication between brokers when joining a cluster."""
- sasl_config=os.path.join(self.rootdir, "sasl_config")
- # Test with a valid username/password
- cluster = self.cluster(1, args=["--auth", "yes",
- "--sasl-config", sasl_config,
- "--load-module", os.getenv("ACL_LIB"),
- "--cluster-username=zig",
- "--cluster-password=zig",
- "--cluster-mechanism=PLAIN"
- ])
- cluster.start()
- cluster.ready()
- c = cluster[1].connect(username="zag", password="zag")
-
- # Test with an invalid username/password
- cluster = self.cluster(1, args=["--auth", "yes",
- "--sasl-config", sasl_config,
- "--load-module", os.getenv("ACL_LIB"),
- "--cluster-username=x",
- "--cluster-password=y",
- "--cluster-mechanism=PLAIN"
- ])
- try:
- cluster.start(expect=EXPECT_EXIT_OK)
- cluster[1].ready()
- self.fail("Expected exception")
- except: pass
-
def test_user_id_update(self):
"""Ensure that user-id of an open session is updated to new cluster members"""
sasl_config=os.path.join(self.rootdir, "sasl_config")
@@ -285,6 +246,25 @@ acl deny all all
session1 = cluster[1].connect().session()
for q in queues: self.assert_browse(session1, "q1", ["foo"])
+ def test_dr_no_message(self):
+ """Regression test for https://bugzilla.redhat.com/show_bug.cgi?id=655141
+ Joining broker crashes with 'error deliveryRecord no update message'
+ """
+
+ cluster = self.cluster(1)
+ session0 = cluster[0].connect().session()
+ s = session0.sender("q1;{create:always}")
+ s.send(Message("a", ttl=0.05), sync=False)
+ s.send(Message("b", ttl=0.05), sync=False)
+ r1 = session0.receiver("q1")
+ self.assertEqual("a", r1.fetch(timeout=0).content)
+ r2 = session0.receiver("q1;{mode:browse}")
+ self.assertEqual("b", r2.fetch(timeout=0).content)
+ # Leave messages un-acknowledged, let the expire, then start new broker.
+ time.sleep(.1)
+ cluster.start()
+ self.assertRaises(Empty, cluster[1].connect().session().receiver("q1").fetch,0)
+
def test_route_update(self):
"""Regression test for https://issues.apache.org/jira/browse/QPID-2982
Links and bridges associated with routes were not replicated on update.
@@ -292,7 +272,6 @@ acl deny all all
client was attached.
"""
args=["--mgmt-pub-interval=1","--log-enable=trace+:management"]
- # First broker will be killed.
cluster0 = self.cluster(1, args=args)
cluster1 = self.cluster(1, args=args)
assert 0 == subprocess.call(
@@ -322,695 +301,9 @@ acl deny all all
qpid_tool.wait()
scanner.join()
assert scanner.found
- # Regression test for https://issues.apache.org/jira/browse/QPID-3235
- # Inconsistent stats when changing elder.
-
- # Force a change of elder
- cluster0.start()
- cluster0[0].expect=EXPECT_EXIT_FAIL # About to die.
- cluster0[0].kill()
- time.sleep(2) # Allow a management interval to pass.
# Verify logs are consistent
cluster_test_logs.verify_logs()
- def test_redelivered(self):
- """Verify that redelivered flag is set correctly on replayed messages"""
- cluster = self.cluster(2, expect=EXPECT_EXIT_FAIL)
- url = "amqp:tcp:%s,tcp:%s" % (cluster[0].host_port(), cluster[1].host_port())
- queue = "my-queue"
- cluster[0].declare_queue(queue)
- self.sender = self.popen(
- ["qpid-send",
- "--broker", url,
- "--address", queue,
- "--sequence=true",
- "--send-eos=1",
- "--messages=100000",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS)
- ])
- self.receiver = self.popen(
- ["qpid-receive",
- "--broker", url,
- "--address", queue,
- "--ignore-duplicates",
- "--check-redelivered",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--forever"
- ])
- time.sleep(1)#give sender enough time to have some messages to replay
- cluster[0].kill()
- self.sender.wait()
- self.receiver.wait()
- cluster[1].kill()
-
- class BlockedSend(Thread):
- """Send a message, send is expected to block.
- Verify that it does block (for a given timeout), then allow
- waiting till it unblocks when it is expected to do so."""
- def __init__(self, sender, msg):
- self.sender, self.msg = sender, msg
- self.blocked = True
- self.condition = Condition()
- self.timeout = 0.1 # Time to wait for expected results.
- Thread.__init__(self)
- def run(self):
- try:
- self.sender.send(self.msg, sync=True)
- self.condition.acquire()
- try:
- self.blocked = False
- self.condition.notify()
- finally: self.condition.release()
- except Exception,e: print "BlockedSend exception: %s"%e
- def start(self):
- Thread.start(self)
- time.sleep(self.timeout)
- assert self.blocked # Expected to block
- def assert_blocked(self): assert self.blocked
- def wait(self): # Now expecting to unblock
- self.condition.acquire()
- try:
- while self.blocked:
- self.condition.wait(self.timeout)
- if self.blocked: raise Exception("Timed out waiting for send to unblock")
- finally: self.condition.release()
- self.join()
-
- def queue_flowlimit_test(self, brokers):
- """Verify that the queue's flowlimit configuration and state are
- correctly replicated.
- The brokers argument allows this test to run on single broker,
- cluster of 2 pre-startd brokers or cluster where second broker
- starts after queue is in flow control.
- """
- # configure a queue with a specific flow limit on first broker
- ssn0 = brokers.first().connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}")
- brokers.first().startQmf()
- q1 = [q for q in brokers.first().qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- oid = q1.getObjectId()
- self.assertEqual(q1.name, "flq")
- self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert not q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 0)
-
- # fill the queue on one broker until flow control is active
- for x in range(5): s0.send(Message(str(x)))
- sender = ShortTests.BlockedSend(s0, Message(str(6)))
- sender.start() # Tests that sender does block
- # Verify the broker queue goes into a flowStopped state
- deadline = time.time() + 1
- while not q1.flowStopped and time.time() < deadline: q1.update()
- assert q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 1)
- sender.assert_blocked() # Still blocked
-
- # Now verify the both brokers in cluster have same configuration
- brokers.second().startQmf()
- qs = brokers.second().qmf_session.getObjects(_objectId=oid)
- self.assertEqual(len(qs), 1)
- q2 = qs[0]
- self.assertEqual(q2.name, "flq")
- self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert q2.flowStopped
- self.assertEqual(q2.flowStoppedCount, 1)
-
- # now drain the queue using a session to the other broker
- ssn1 = brokers.second().connect().session()
- r1 = ssn1.receiver("flq", capacity=6)
- for x in range(4):
- r1.fetch(timeout=0)
- ssn1.acknowledge()
- sender.wait() # Verify no longer blocked.
-
- # and re-verify state of queue on both brokers
- q1.update()
- assert not q1.flowStopped
- q2.update()
- assert not q2.flowStopped
-
- ssn0.connection.close()
- ssn1.connection.close()
- cluster_test_logs.verify_logs()
-
- def test_queue_flowlimit(self):
- """Test flow limits on a standalone broker"""
- broker = self.broker()
- class Brokers:
- def first(self): return broker
- def second(self): return broker
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_cluster(self):
- cluster = self.cluster(2)
- class Brokers:
- def first(self): return cluster[0]
- def second(self): return cluster[1]
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_cluster_join(self):
- cluster = self.cluster(1)
- class Brokers:
- def first(self): return cluster[0]
- def second(self):
- if len(cluster) == 1: cluster.start()
- return cluster[1]
- self.queue_flowlimit_test(Brokers())
-
- def test_queue_flowlimit_replicate(self):
- """ Verify that a queue which is in flow control BUT has drained BELOW
- the flow control 'stop' threshold, is correctly replicated when a new
- broker is added to the cluster.
- """
-
- class AsyncSender(Thread):
- """Send a fixed number of msgs from a sender in a separate thread
- so it may block without blocking the test.
- """
- def __init__(self, broker, address, count=1, size=4):
- Thread.__init__(self)
- self.daemon = True
- self.broker = broker
- self.queue = address
- self.count = count
- self.size = size
- self.done = False
-
- def run(self):
- self.sender = subprocess.Popen(["qpid-send",
- "--capacity=1",
- "--content-size=%s" % self.size,
- "--messages=%s" % self.count,
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--address=%s" % self.queue,
- "--broker=%s" % self.broker.host_port()])
- self.sender.wait()
- self.done = True
-
- cluster = self.cluster(2)
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':100, 'qpid.flow_resume_count':20}}}}")
-
- # fire off the sending thread to broker[0], and wait until the queue
- # hits flow control on broker[1]
- sender = AsyncSender(cluster[0], "flq", count=110);
- sender.start();
-
- cluster[1].startQmf()
- q_obj = [q for q in cluster[1].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- deadline = time.time() + 10
- while not q_obj.flowStopped and time.time() < deadline:
- q_obj.update()
- assert q_obj.flowStopped
- assert not sender.done
- assert q_obj.msgDepth < 110
-
- # Now drain enough messages on broker[1] to drop below the flow stop
- # threshold, but not relieve flow control...
- receiver = subprocess.Popen(["qpid-receive",
- "--messages=15",
- "--timeout=1",
- "--print-content=no",
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--ack-frequency=1",
- "--address=flq",
- "--broker=%s" % cluster[1].host_port()])
- receiver.wait()
- q_obj.update()
- assert q_obj.flowStopped
- assert not sender.done
- current_depth = q_obj.msgDepth
-
- # add a new broker to the cluster, and verify that the queue is in flow
- # control on that broker
- cluster.start()
- cluster[2].startQmf()
- q_obj = [q for q in cluster[2].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- assert q_obj.flowStopped
- assert q_obj.msgDepth == current_depth
-
- # now drain the queue on broker[2], and verify that the sender becomes
- # unblocked
- receiver = subprocess.Popen(["qpid-receive",
- "--messages=95",
- "--timeout=1",
- "--print-content=no",
- "--failover-updates",
- "--connection-options={%s}"%(Cluster.CONNECTION_OPTIONS),
- "--ack-frequency=1",
- "--address=flq",
- "--broker=%s" % cluster[2].host_port()])
- receiver.wait()
- q_obj.update()
- assert not q_obj.flowStopped
- self.assertEqual(q_obj.msgDepth, 0)
-
- # verify that the sender has become unblocked
- sender.join(timeout=5)
- assert not sender.isAlive()
- assert sender.done
-
- def test_blocked_queue_delete(self):
- """Verify that producers which are blocked on a queue due to flow
- control are unblocked when that queue is deleted.
- """
-
- cluster = self.cluster(2)
- cluster[0].startQmf()
- cluster[1].startQmf()
-
- # configure a queue with a specific flow limit on first broker
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("flq; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':5, 'qpid.flow_resume_count':3}}}}")
- q1 = [q for q in cluster[0].qmf_session.getObjects(_class="queue") if q.name == "flq"][0]
- oid = q1.getObjectId()
- self.assertEqual(q1.name, "flq")
- self.assertEqual(q1.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert not q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 0)
-
- # fill the queue on one broker until flow control is active
- for x in range(5): s0.send(Message(str(x)))
- sender = ShortTests.BlockedSend(s0, Message(str(6)))
- sender.start() # Tests that sender does block
- # Verify the broker queue goes into a flowStopped state
- deadline = time.time() + 1
- while not q1.flowStopped and time.time() < deadline: q1.update()
- assert q1.flowStopped
- self.assertEqual(q1.flowStoppedCount, 1)
- sender.assert_blocked() # Still blocked
-
- # Now verify the both brokers in cluster have same configuration
- qs = cluster[1].qmf_session.getObjects(_objectId=oid)
- self.assertEqual(len(qs), 1)
- q2 = qs[0]
- self.assertEqual(q2.name, "flq")
- self.assertEqual(q2.arguments, {u'qpid.flow_stop_count': 5L, u'qpid.flow_resume_count': 3L})
- assert q2.flowStopped
- self.assertEqual(q2.flowStoppedCount, 1)
-
- # now delete the blocked queue from other broker
- ssn1 = cluster[1].connect().session()
- self.evaluate_address(ssn1, "flq;{delete:always}")
- sender.wait() # Verify no longer blocked.
-
- ssn0.connection.close()
- ssn1.connection.close()
- cluster_test_logs.verify_logs()
-
-
- def test_alternate_exchange_update(self):
- """Verify that alternate-exchange on exchanges and queues is propagated to new members of a cluster. """
- cluster = self.cluster(1)
- s0 = cluster[0].connect().session()
- # create alt queue bound to amq.fanout exchange, will be destination for alternate exchanges
- self.evaluate_address(s0, "alt;{create:always,node:{x-bindings:[{exchange:'amq.fanout',queue:alt}]}}")
- # create direct exchange ex with alternate-exchange amq.fanout and no queues bound
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic, x-declare:{type:'direct', alternate-exchange:'amq.fanout'}}}")
- # create queue q with alternate-exchange amq.fanout
- self.evaluate_address(s0, "q;{create:always,node:{type:queue, x-declare:{alternate-exchange:'amq.fanout'}}}")
-
- def verify(broker):
- s = broker.connect().session()
- # Verify unmatched message goes to ex's alternate.
- s.sender("ex").send("foo")
- self.assertEqual("foo", s.receiver("alt").fetch(timeout=0).content)
- # Verify rejected message goes to q's alternate.
- s.sender("q").send("bar")
- msg = s.receiver("q").fetch(timeout=0)
- self.assertEqual("bar", msg.content)
- s.acknowledge(msg, Disposition(REJECTED)) # Reject the message
- self.assertEqual("bar", s.receiver("alt").fetch(timeout=0).content)
-
- verify(cluster[0])
- cluster.start()
- verify(cluster[1])
-
- def test_binding_order(self):
- """Regression test for binding order inconsistency in cluster"""
- cluster = self.cluster(1)
- c0 = cluster[0].connect()
- s0 = c0.session()
- # Declare multiple queues bound to same key on amq.topic
- def declare(q,max=0):
- if max: declare = 'x-declare:{arguments:{"qpid.max_count":%d, "qpid.flow_stop_count":0}}'%max
- else: declare = 'x-declare:{}'
- bind='x-bindings:[{queue:%s,key:key,exchange:"amq.topic"}]'%(q)
- s0.sender("%s;{create:always,node:{%s,%s}}" % (q,declare,bind))
- declare('d',max=4) # Only one with a limit
- for q in ['c', 'b','a']: declare(q)
- # Add a cluster member, send enough messages to exceed the max count
- cluster.start()
- try:
- s = s0.sender('amq.topic/key')
- for m in xrange(1,6): s.send(Message(str(m)))
- self.fail("Expected capacity exceeded exception")
- except messaging.exceptions.TargetCapacityExceeded: pass
- c1 = cluster[1].connect()
- s1 = c1.session()
- s0 = c0.session() # Old session s0 is broken by exception.
- # Verify queue contents are consistent.
- for q in ['a','b','c','d']:
- self.assertEqual(self.browse(s0, q), self.browse(s1, q))
- # Verify queue contents are "best effort"
- for q in ['a','b','c']: self.assert_browse(s1,q,[str(n) for n in xrange(1,6)])
- self.assert_browse(s1,'d',[str(n) for n in xrange(1,5)])
-
- def test_deleted_exchange(self):
- """QPID-3215: cached exchange reference can cause cluster inconsistencies
- if exchange is deleted/recreated
- Verify stand-alone case
- """
- cluster = self.cluster()
- # Verify we do not route message via an exchange that has been destroyed.
- cluster.start()
- s0 = cluster[0].connect().session()
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}")
- self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}")
- send0 = s0.sender("ex/foo")
- send0.send("foo")
- self.assert_browse(s0, "q", ["foo"])
- self.evaluate_address(s0, "ex;{delete:always}")
- try:
- send0.send("bar") # Should fail, exchange is deleted.
- self.fail("Expected not-found exception")
- except qpid.messaging.NotFound: pass
- self.assert_browse(cluster[0].connect().session(), "q", ["foo"])
-
- def test_deleted_exchange_inconsistent(self):
- """QPID-3215: cached exchange reference can cause cluster inconsistencies
- if exchange is deleted/recreated
-
- Verify cluster inconsistency.
- """
- cluster = self.cluster()
- cluster.start()
- s0 = cluster[0].connect().session()
- self.evaluate_address(s0, "ex;{create:always,node:{type:topic}}")
- self.evaluate_address(s0, "q;{create:always,node:{x-bindings:[{exchange:'ex',queue:q,key:foo}]}}")
- send0 = s0.sender("ex/foo")
- send0.send("foo")
- self.assert_browse(s0, "q", ["foo"])
-
- cluster.start()
- s1 = cluster[1].connect().session()
- self.evaluate_address(s0, "ex;{delete:always}")
- try:
- send0.send("bar")
- self.fail("Expected not-found exception")
- except qpid.messaging.NotFound: pass
-
- self.assert_browse(s1, "q", ["foo"])
-
-
- def test_ttl_consistent(self):
- """Ensure we don't get inconsistent errors with message that have TTL very close together"""
- messages = [ Message(str(i), ttl=i/1000.0) for i in xrange(0,1000)]
- messages.append(Message("x"))
- cluster = self.cluster(2)
- sender = cluster[0].connect().session().sender("q;{create:always}")
-
- def fetch(b):
- receiver = b.connect().session().receiver("q;{create:always}")
- while receiver.fetch().content != "x": pass
-
- for m in messages: sender.send(m, sync=False)
- for m in messages: sender.send(m, sync=False)
- fetch(cluster[0])
- fetch(cluster[1])
- for m in messages: sender.send(m, sync=False)
- cluster.start()
- fetch(cluster[2])
-
-# Some utility code for transaction tests
-XA_RBROLLBACK = 1
-XA_RBTIMEOUT = 2
-XA_OK = 0
-dtx_branch_counter = 0
-
-class DtxStatusException(Exception):
- def __init__(self, expect, actual):
- self.expect = expect
- self.actual = actual
-
- def str(self):
- return "DtxStatusException(expect=%s, actual=%s)"%(self.expect, self.actual)
-
-class DtxTestFixture:
- """Bundle together some common requirements for dtx tests."""
- def __init__(self, test, broker, name, exclusive=False):
- self.test = test
- self.broker = broker
- self.name = name
- # Use old API. DTX is not supported in messaging API.
- self.connection = broker.connect_old()
- self.session = self.connection.session(name, 1) # 1 second timeout
- self.queue = self.session.queue_declare(name, exclusive=exclusive)
- self.session.dtx_select()
- self.consumer = None
-
- def xid(self, id=None):
- if id is None: id = self.name
- return self.session.xid(format=0, global_id=id)
-
- def check_status(self, expect, actual):
- if expect != actual: raise DtxStatusException(expect, actual)
-
- def start(self, id=None, resume=False):
- self.check_status(XA_OK, self.session.dtx_start(xid=self.xid(id), resume=resume).status)
-
- def end(self, id=None, suspend=False):
- self.check_status(XA_OK, self.session.dtx_end(xid=self.xid(id), suspend=suspend).status)
-
- def prepare(self, id=None):
- self.check_status(XA_OK, self.session.dtx_prepare(xid=self.xid(id)).status)
-
- def commit(self, id=None, one_phase=True):
- self.check_status(
- XA_OK, self.session.dtx_commit(xid=self.xid(id), one_phase=one_phase).status)
-
- def rollback(self, id=None):
- self.check_status(XA_OK, self.session.dtx_rollback(xid=self.xid(id)).status)
-
- def set_timeout(self, timeout, id=None):
- self.session.dtx_set_timeout(xid=self.xid(id),timeout=timeout)
-
- def send(self, messages):
- for m in messages:
- dp=self.session.delivery_properties(routing_key=self.name)
- mp=self.session.message_properties()
- self.session.message_transfer(message=qpid.datatypes.Message(dp, mp, m))
-
- def accept(self):
- """Accept 1 message from queue"""
- consumer_tag="%s-consumer"%(self.name)
- self.session.message_subscribe(queue=self.name, destination=consumer_tag)
- self.session.message_flow(unit = self.session.credit_unit.message, value = 1, destination = consumer_tag)
- self.session.message_flow(unit = self.session.credit_unit.byte, value = 0xFFFFFFFFL, destination = consumer_tag)
- msg = self.session.incoming(consumer_tag).get(timeout=1)
- self.session.message_cancel(destination=consumer_tag)
- self.session.message_accept(qpid.datatypes.RangedSet(msg.id))
- return msg
-
-
- def verify(self, sessions, messages):
- for s in sessions:
- self.test.assert_browse(s, self.name, messages)
-
-class DtxTests(BrokerTest):
-
- def test_dtx_update(self):
- """Verify that DTX transaction state is updated to a new broker.
- Start a collection of transactions, then add a new cluster member,
- then verify they commit/rollback correctly on the new broker."""
-
- # Note: multiple test have been bundled into one to avoid the need to start/stop
- # multiple brokers per test.
-
- cluster=self.cluster(1)
- sessions = [cluster[0].connect().session()] # For verify
-
- # Transaction that will be open when new member joins, then committed.
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.start()
- t1.send(["1", "2"])
- t1.verify(sessions, []) # Not visible outside of transaction
-
- # Transaction that will be open when new member joins, then rolled back.
- t2 = DtxTestFixture(self, cluster[0], "t2")
- t2.start()
- t2.send(["1", "2"])
-
- # Transaction that will be prepared when new member joins, then committed.
- t3 = DtxTestFixture(self, cluster[0], "t3")
- t3.start()
- t3.send(["1", "2"])
- t3.end()
- t3.prepare()
- t1.verify(sessions, []) # Not visible outside of transaction
-
- # Transaction that will be prepared when new member joins, then rolled back.
- t4 = DtxTestFixture(self, cluster[0], "t4")
- t4.start()
- t4.send(["1", "2"])
- t4.end()
- t4.prepare()
-
- # Transaction using an exclusive queue
- t5 = DtxTestFixture(self, cluster[0], "t5", exclusive=True)
- t5.start()
- t5.send(["1", "2"])
-
- # Accept messages in a transaction before/after join then commit
- t6 = DtxTestFixture(self, cluster[0], "t6")
- t6.send(["a","b","c"])
- t6.start()
- self.assertEqual(t6.accept().body, "a");
-
- # Accept messages in a transaction before/after join then roll back
- t7 = DtxTestFixture(self, cluster[0], "t7")
- t7.send(["a","b","c"])
- t7.start()
- self.assertEqual(t7.accept().body, "a");
-
- # Ended, suspended transactions across join.
- t8 = DtxTestFixture(self, cluster[0], "t8")
- t8.start(id="1")
- t8.send(["x"])
- t8.end(id="1", suspend=True)
- t8.start(id="2")
- t8.send(["y"])
- t8.end(id="2")
- t8.start()
- t8.send("z")
-
-
- # Start new cluster member
- cluster.start()
- sessions.append(cluster[1].connect().session())
-
- # Commit t1
- t1.send(["3","4"])
- t1.verify(sessions, [])
- t1.end()
- t1.commit(one_phase=True)
- t1.verify(sessions, ["1","2","3","4"])
-
- # Rollback t2
- t2.send(["3","4"])
- t2.end()
- t2.rollback()
- t2.verify(sessions, [])
-
- # Commit t3
- t3.commit(one_phase=False)
- t3.verify(sessions, ["1","2"])
-
- # Rollback t4
- t4.rollback()
- t4.verify(sessions, [])
-
- # Commit t5
- t5.send(["3","4"])
- t5.verify(sessions, [])
- t5.end()
- t5.commit(one_phase=True)
- t5.verify(sessions, ["1","2","3","4"])
-
- # Commit t6
- self.assertEqual(t6.accept().body, "b");
- t6.verify(sessions, ["c"])
- t6.end()
- t6.commit(one_phase=True)
- t6.session.close() # Make sure they're not requeued by the session.
- t6.verify(sessions, ["c"])
-
- # Rollback t7
- self.assertEqual(t7.accept().body, "b");
- t7.end()
- t7.rollback()
- t7.verify(sessions, ["a", "b", "c"])
-
- # Resume t8
- t8.end()
- t8.commit(one_phase=True)
- t8.start("1", resume=True)
- t8.end("1")
- t8.commit("1", one_phase=True)
- t8.commit("2", one_phase=True)
- t8.verify(sessions, ["z", "x","y"])
-
-
- def test_dtx_failover_rollback(self):
- """Kill a broker during a transaction, verify we roll back correctly"""
- cluster=self.cluster(1, expect=EXPECT_EXIT_FAIL)
- cluster.start(expect=EXPECT_RUNNING)
-
- # Test unprepared at crash
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.send(["a"]) # Not in transaction
- t1.start()
- t1.send(["b"]) # In transaction
-
- # Test prepared at crash
- t2 = DtxTestFixture(self, cluster[0], "t2")
- t2.send(["a"]) # Not in transaction
- t2.start()
- t2.send(["b"]) # In transaction
- t2.end()
- t2.prepare()
-
- # Crash the broker
- cluster[0].kill()
-
- # Transactional changes should not appear
- s = cluster[1].connect().session();
- self.assert_browse(s, "t1", ["a"])
- self.assert_browse(s, "t2", ["a"])
-
- def test_dtx_timeout(self):
- """Verify that dtx timeout works"""
- cluster = self.cluster(1)
- t1 = DtxTestFixture(self, cluster[0], "t1")
- t1.start()
- t1.set_timeout(1)
- time.sleep(1.1)
- try:
- t1.end()
- self.fail("Expected rollback timeout.")
- except DtxStatusException, e:
- self.assertEqual(e.actual, XA_RBTIMEOUT)
-
-class TxTests(BrokerTest):
-
- def test_tx_update(self):
- """Verify that transaction state is updated to a new broker"""
-
- def make_message(session, body=None, key=None, id=None):
- dp=session.delivery_properties(routing_key=key)
- mp=session.message_properties(correlation_id=id)
- return qpid.datatypes.Message(dp, mp, body)
-
- cluster=self.cluster(1)
- # Use old API. TX is not supported in messaging API.
- c = cluster[0].connect_old()
- s = c.session("tx-session", 1)
- s.queue_declare(queue="q")
- # Start transaction
- s.tx_select()
- s.message_transfer(message=make_message(s, "1", "q"))
- # Start new member mid-transaction
- cluster.start()
- # Do more work
- s.message_transfer(message=make_message(s, "2", "q"))
- # Commit the transaction and verify the results.
- s.tx_commit()
- for b in cluster: self.assert_browse(b.connect().session(), "q", ["1","2"])
-
-
class LongTests(BrokerTest):
"""Tests that can run for a long time if -DDURATION=<minutes> is set"""
def duration(self):
@@ -1023,28 +316,22 @@ class LongTests(BrokerTest):
# Original cluster will all be killed so expect exit with failure
cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL)
- for b in cluster: b.ready() # Wait for brokers to be ready
for b in cluster: ErrorGenerator(b)
# Start sender and receiver threads
cluster[0].declare_queue("test-queue")
- sender = NumberedSender(cluster[0], 1000) # Max queue depth
- receiver = NumberedReceiver(cluster[0], sender)
+ sender = NumberedSender(cluster[1], 1000) # Max queue depth
+ receiver = NumberedReceiver(cluster[2], sender)
receiver.start()
sender.start()
- # Wait for sender & receiver to get up and running
- retry(lambda: receiver.received > 0)
# Kill original brokers, start new ones for the duration.
endtime = time.time() + self.duration()
i = 0
while time.time() < endtime:
- sender.sender.assert_running()
- receiver.receiver.assert_running()
cluster[i].kill()
i += 1
b = cluster.start(expect=EXPECT_EXIT_FAIL)
- for b in cluster[i:]: b.ready()
ErrorGenerator(b)
time.sleep(5)
sender.stop()
@@ -1075,24 +362,24 @@ class LongTests(BrokerTest):
if self.stopped: break
self.process = self.broker.test.popen(
self.cmd, expect=EXPECT_UNKNOWN)
- finally:
- self.lock.release()
- try:
- exit = self.process.wait()
+ finally: self.lock.release()
+ try: exit = self.process.wait()
except OSError, e:
- # Process may already have been killed by self.stop()
- break
+ # Seems to be a race in wait(), it throws
+ # "no such process" during test shutdown.
+ # Doesn't indicate a test error, ignore.
+ return
except Exception, e:
self.process.unexpected(
"client of %s: %s"%(self.broker.name, e))
self.lock.acquire()
try:
+ # Quit and ignore errors if stopped or expecting failure.
if self.stopped: break
if exit != 0:
self.process.unexpected(
"client of %s exit code %s"%(self.broker.name, exit))
- finally:
- self.lock.release()
+ finally: self.lock.release()
except Exception, e:
self.error = RethrownException("Error in ClientLoop.run")
@@ -1114,7 +401,7 @@ class LongTests(BrokerTest):
args += ["--log-enable=trace+:management"]
# Use store if present.
if BrokerTest.store_lib: args +=["--load-module", BrokerTest.store_lib]
- cluster = self.cluster(3, args, expect=EXPECT_EXIT_FAIL) # brokers will be killed
+ cluster = self.cluster(3, args)
clients = [] # Per-broker list of clients that only connect to one broker.
mclients = [] # Management clients that connect to every broker in the cluster.
@@ -1123,12 +410,10 @@ class LongTests(BrokerTest):
"""Start ordinary clients for a broker."""
cmds=[
["qpid-tool", "localhost:%s"%(broker.port())],
- ["qpid-perftest", "--count=5000", "--durable=yes",
+ ["qpid-perftest", "--count", 50000,
"--base-name", str(qpid.datatypes.uuid4()), "--port", broker.port()],
- ["qpid-txtest", "--queue-base-name", "tx-%s"%str(qpid.datatypes.uuid4()),
- "--port", broker.port()],
- ["qpid-queue-stats", "-a", "localhost:%s" %(broker.port())]
- ]
+ ["qpid-queue-stats", "-a", "localhost:%s" %(broker.port())],
+ ["testagent", "localhost", str(broker.port())] ]
clients.append([ClientLoop(broker, cmd) for cmd in cmds])
def start_mclients(broker):
@@ -1137,8 +422,7 @@ class LongTests(BrokerTest):
mclients.append(ClientLoop(broker, cmd))
endtime = time.time() + self.duration()
- # For long duration, first run is a quarter of the duration.
- runtime = min(5.0, self.duration() / 3.0)
+ runtime = self.duration() / 4 # First run is longer, use quarter of duration.
alive = 0 # First live cluster member
for i in range(len(cluster)): start_clients(cluster[i])
start_mclients(cluster[alive])
@@ -1149,7 +433,7 @@ class LongTests(BrokerTest):
for b in cluster[alive:]: b.ready() # Check if a broker crashed.
# Kill the first broker, expect the clients to fail.
b = cluster[alive]
- b.ready()
+ b.expect = EXPECT_EXIT_FAIL
b.kill()
# Stop the brokers clients and all the mclients.
for c in clients[alive] + mclients:
@@ -1159,251 +443,26 @@ class LongTests(BrokerTest):
mclients = []
# Start another broker and clients
alive += 1
- cluster.start(expect=EXPECT_EXIT_FAIL)
- cluster[-1].ready() # Wait till its ready
+ cluster.start()
start_clients(cluster[-1])
start_mclients(cluster[alive])
for c in chain(mclients, *clients):
c.stop()
- for b in cluster[alive:]:
- b.ready() # Verify still alive
- b.kill()
+
# Verify that logs are consistent
cluster_test_logs.verify_logs()
def test_management_qmf2(self):
self.test_management(args=["--mgmt-qmf2=yes"])
- def test_connect_consistent(self):
+ def test_connect_consistent(self): # FIXME aconway 2011-01-18:
args=["--mgmt-pub-interval=1","--log-enable=trace+:management"]
cluster = self.cluster(2, args=args)
end = time.time() + self.duration()
while (time.time() < end): # Get a management interval
for i in xrange(1000): cluster[0].connect().close()
- cluster_test_logs.verify_logs()
-
- def test_flowlimit_failover(self):
- """Test fail-over during continuous send-receive with flow control
- active.
- """
-
- # Original cluster will all be killed so expect exit with failure
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL)
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- s0 = ssn0.sender("test-queue; {create:always, node:{type:queue, x-declare:{arguments:{'qpid.flow_stop_count':2000, 'qpid.flow_resume_count':100}}}}")
-
- receiver = NumberedReceiver(cluster[0])
- receiver.start()
- senders = [NumberedSender(cluster[0]) for i in range(1,3)]
- for s in senders:
- s.start()
- # Wait for senders & receiver to get up and running
- retry(lambda: receiver.received > 2*senders)
-
- # Kill original brokers, start new ones for the duration.
- endtime = time.time() + self.duration();
- i = 0
- while time.time() < endtime:
- for s in senders: s.sender.assert_running()
- receiver.receiver.assert_running()
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- time.sleep(5)
- for s in senders:
- s.stop()
- receiver.stop()
- for i in range(i, len(cluster)): cluster[i].kill()
-
- def test_ttl_failover(self):
- """Test that messages with TTL don't cause problems in a cluster with failover"""
-
- class Client(StoppableThread):
-
- def __init__(self, broker):
- StoppableThread.__init__(self)
- self.connection = broker.connect(reconnect=True)
- self.auto_fetch_reconnect_urls(self.connection)
- self.session = self.connection.session()
-
- def auto_fetch_reconnect_urls(self, conn):
- """Replacment for qpid.messaging.util version which is noisy"""
- ssn = conn.session("auto-fetch-reconnect-urls")
- rcv = ssn.receiver("amq.failover")
- rcv.capacity = 10
-
- def main():
- while True:
- try:
- msg = rcv.fetch()
- qpid.messaging.util.set_reconnect_urls(conn, msg)
- ssn.acknowledge(msg, sync=False)
- except messaging.exceptions.LinkClosed: return
- except messaging.exceptions.ConnectionError: return
-
- thread = Thread(name="auto-fetch-reconnect-urls", target=main)
- thread.setDaemon(True)
- thread.start()
-
- def stop(self):
- StoppableThread.stop(self)
- self.connection.detach()
-
- class Sender(Client):
- def __init__(self, broker, address):
- Client.__init__(self, broker)
- self.sent = 0 # Number of messages _reliably_ sent.
- self.sender = self.session.sender(address, capacity=1000)
-
- def send_counted(self, ttl):
- self.sender.send(Message(str(self.sent), ttl=ttl))
- self.sent += 1
-
- def run(self):
- while not self.stopped:
- choice = random.randint(0,4)
- if choice == 0: self.send_counted(None) # No ttl
- elif choice == 1: self.send_counted(100000) # Large ttl
- else: # Small ttl, might expire
- self.sender.send(Message("", ttl=random.random()/10))
- self.sender.send(Message("z"), sync=True) # Chaser.
-
- class Receiver(Client):
-
- def __init__(self, broker, address):
- Client.__init__(self, broker)
- self.received = 0 # Number of non-empty (reliable) messages received.
- self.receiver = self.session.receiver(address, capacity=1000)
- def run(self):
- try:
- while True:
- m = self.receiver.fetch(1)
- if m.content == "z": break
- if m.content: # Ignore unreliable messages
- # Ignore duplicates
- if int(m.content) == self.received: self.received += 1
- except Exception,e: self.error = e
-
- # def test_ttl_failover
-
- # Original cluster will all be killed so expect exit with failure
- # Set small purge interval.
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL, args=["--queue-purge-interval=1"])
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # Python client failover produces noisy WARN logs, disable temporarily
- logger = logging.getLogger()
- log_level = logger.getEffectiveLevel()
- logger.setLevel(logging.ERROR)
- sender = None
- receiver = None
- try:
- # Start sender and receiver threads
- receiver = Receiver(cluster[0], "q;{create:always}")
- receiver.start()
- sender = Sender(cluster[0], "q;{create:always}")
- sender.start()
- # Wait for sender & receiver to get up and running
- retry(lambda: receiver.received > 0)
-
- # Kill brokers in a cycle.
- endtime = time.time() + self.duration()
- runtime = min(5.0, self.duration() / 4.0)
- i = 0
- while time.time() < endtime:
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- b.ready()
- time.sleep(runtime)
- sender.stop()
- receiver.stop()
- for b in cluster[i:]:
- b.ready() # Check it didn't crash
- b.kill()
- self.assertEqual(sender.sent, receiver.received)
cluster_test_logs.verify_logs()
- finally:
- # Detach to avoid slow reconnect attempts during shut-down if test fails.
- if sender: sender.connection.detach()
- if receiver: receiver.connection.detach()
- logger.setLevel(log_level)
-
- def test_msg_group_failover(self):
- """Test fail-over during continuous send-receive of grouped messages.
- """
-
- class GroupedTrafficGenerator(Thread):
- def __init__(self, url, queue, group_key):
- Thread.__init__(self)
- self.url = url
- self.queue = queue
- self.group_key = group_key
- self.status = -1
-
- def run(self):
- # generate traffic for approx 10 seconds (2011msgs / 200 per-sec)
- cmd = ["msg_group_test",
- "--broker=%s" % self.url,
- "--address=%s" % self.queue,
- "--connection-options={%s}" % (Cluster.CONNECTION_OPTIONS),
- "--group-key=%s" % self.group_key,
- "--receivers=2",
- "--senders=3",
- "--messages=2011",
- "--send-rate=200",
- "--capacity=11",
- "--ack-frequency=23",
- "--allow-duplicates",
- "--group-size=37",
- "--randomize-group-size",
- "--interleave=13"]
- # "--trace"]
- self.generator = Popen( cmd );
- self.status = self.generator.wait()
- return self.status
-
- def results(self):
- self.join(timeout=30) # 3x assumed duration
- if self.isAlive(): return -1
- return self.status
-
- # Original cluster will all be killed so expect exit with failure
- cluster = self.cluster(3, expect=EXPECT_EXIT_FAIL, args=["-t"])
- for b in cluster: b.ready() # Wait for brokers to be ready
-
- # create a queue with rather draconian flow control settings
- ssn0 = cluster[0].connect().session()
- q_args = "{'qpid.group_header_key':'group-id', 'qpid.shared_msg_group':1}"
- s0 = ssn0.sender("test-group-q; {create:always, node:{type:queue, x-declare:{arguments:%s}}}" % q_args)
-
- # Kill original brokers, start new ones for the duration.
- endtime = time.time() + self.duration();
- i = 0
- while time.time() < endtime:
- traffic = GroupedTrafficGenerator( cluster[i].host_port(),
- "test-group-q", "group-id" )
- traffic.start()
- time.sleep(1)
-
- for x in range(2):
- for b in cluster[i:]: b.ready() # Check if any broker crashed.
- cluster[i].kill()
- i += 1
- b = cluster.start(expect=EXPECT_EXIT_FAIL)
- time.sleep(1)
-
- # wait for traffic to finish, verify success
- self.assertEqual(0, traffic.results())
-
- for i in range(i, len(cluster)): cluster[i].kill()
-
class StoreTests(BrokerTest):
"""
diff --git a/cpp/src/tests/exception_test.cpp b/cpp/src/tests/exception_test.cpp
index 3e844b4e58..3536ffddbe 100644
--- a/cpp/src/tests/exception_test.cpp
+++ b/cpp/src/tests/exception_test.cpp
@@ -92,30 +92,32 @@ QPID_AUTO_TEST_CASE(TestSessionBusy) {
}
QPID_AUTO_TEST_CASE(DisconnectedPop) {
- SessionFixture fix;
+ ProxySessionFixture fix;
+ ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT));
fix.session.queueDeclare(arg::queue="q");
fix.subs.subscribe(fix.lq, "q");
Catcher<TransportFailure> pop(bind(&LocalQueue::pop, &fix.lq, sys::TIME_SEC));
- fix.shutdownBroker();
+ fix.connection.proxy.close();
BOOST_CHECK(pop.join());
}
QPID_AUTO_TEST_CASE(DisconnectedListen) {
- SessionFixture fix;
+ ProxySessionFixture fix;
struct NullListener : public MessageListener {
void received(Message&) { BOOST_FAIL("Unexpected message"); }
} l;
+ ProxyConnection c(fix.broker->getPort(Broker::TCP_TRANSPORT));
fix.session.queueDeclare(arg::queue="q");
fix.subs.subscribe(l, "q");
Catcher<TransportFailure> runner(bind(&SubscriptionManager::run, boost::ref(fix.subs)));
- fix.shutdownBroker();
- runner.join();
+ fix.connection.proxy.close();
+ runner.join();
BOOST_CHECK_THROW(fix.session.queueDeclare(arg::queue="x"), TransportFailure);
}
QPID_AUTO_TEST_CASE(NoSuchQueueTest) {
- SessionFixture fix;
+ ProxySessionFixture fix;
ScopedSuppressLogging sl; // Suppress messages for expected errors.
BOOST_CHECK_THROW(fix.subs.subscribe(fix.lq, "no such queue"), NotFoundException);
}
diff --git a/cpp/src/tests/federated_topic_test b/cpp/src/tests/federated_topic_test
index 2e55ddcfaa..b1063c7e8c 100755
--- a/cpp/src/tests/federated_topic_test
+++ b/cpp/src/tests/federated_topic_test
@@ -42,12 +42,13 @@ while getopts "s:m:b:" opt ; do
esac
done
+MY_DIR=$(dirname $(which $0))
source ./test_env.sh
trap stop_brokers EXIT
start_broker() {
- $QPIDD_EXEC --daemon --port 0 --no-module-dir --no-data-dir --auth no > qpidd.port
+ ${MY_DIR}/../qpidd --daemon --port 0 --no-module-dir --no-data-dir --auth no > qpidd.port
}
start_brokers() {
@@ -75,39 +76,39 @@ subscribe() {
echo Subscriber $1 connecting on $MY_PORT
LOG="subscriber_$1.log"
- ./qpid-topic-listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG
+ ${MY_DIR}/topic_listener -p $MY_PORT > $LOG 2>&1 && rm -f $LOG
}
publish() {
- ./qpid-topic-publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A
+ ${MY_DIR}/topic_publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS -p $PORT_A
}
setup_routes() {
- BROKER_A="daffodil:$PORT_A"
- BROKER_B="daffodil:$PORT_B"
- BROKER_C="daffodil:$PORT_C"
+ BROKER_A="localhost:$PORT_A"
+ BROKER_B="localhost:$PORT_B"
+ BROKER_C="localhost:$PORT_C"
if (($VERBOSE)); then
echo "Establishing routes for topic..."
fi
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_A amq.topic topic_control B B
- $QPID_ROUTE_EXEC route add $BROKER_C $BROKER_B amq.topic topic_control C C
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_A amq.topic topic_control B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_C $BROKER_B amq.topic topic_control C C
if (($VERBOSE)); then
echo "linked A->B->C"
fi
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_C amq.topic topic_control B B
- $QPID_ROUTE_EXEC route add $BROKER_A $BROKER_B amq.topic topic_control A A
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.topic topic_control B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.topic topic_control A A
if (($VERBOSE)); then
echo "linked C->B->A"
echo "Establishing routes for response queue..."
fi
- $QPID_ROUTE_EXEC route add $BROKER_B $BROKER_C amq.direct response B B
- $QPID_ROUTE_EXEC route add $BROKER_A $BROKER_B amq.direct response A A
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_B $BROKER_C amq.direct response B B
+ $PYTHON_COMMANDS/qpid-route route add $BROKER_A $BROKER_B amq.direct response A A
if (($VERBOSE)); then
echo "linked C->B->A"
for b in $BROKER_A $BROKER_B $BROKER_C; do
echo "Routes for $b"
- $QPID_ROUTE_EXEC route list $b
+ $PYTHON_COMMANDS/qpid-route route list $b
done
fi
}
diff --git a/cpp/src/tests/federation.py b/cpp/src/tests/federation.py
index 7d613b98ce..973a1d366c 100755
--- a/cpp/src/tests/federation.py
+++ b/cpp/src/tests/federation.py
@@ -23,7 +23,7 @@ from qpid.testlib import TestBase010
from qpid.datatypes import Message
from qpid.queue import Empty
from qpid.util import URL
-from time import sleep, time
+from time import sleep
class _FedBroker(object):
@@ -111,18 +111,18 @@ class FederationTests(TestBase010):
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.direct", "my-key", "", "", False, False, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -133,11 +133,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, False, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
@@ -165,9 +165,9 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -178,11 +178,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "amq.direct", "amq.fanout", "my-key", "", "", False, True, False, 0)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
@@ -209,9 +209,9 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
result = link.close()
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
self.verify_cleanup()
@@ -236,11 +236,11 @@ class FederationTests(TestBase010):
qmf = self.qmf
broker = qmf.getObjects(_class="broker")[0]
result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
link = qmf.getObjects(_class="link")[0]
result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1)
- self.assertEqual(result.status, 0, result)
+ self.assertEqual(result.status, 0)
bridge = qmf.getObjects(_class="bridge")[0]
sleep(3)
@@ -262,63 +262,6 @@ class FederationTests(TestBase010):
except Empty: None
result = bridge.close()
- self.assertEqual(result.status, 0, result)
- result = link.close()
- self.assertEqual(result.status, 0, result)
-
- self.verify_cleanup()
-
- def test_pull_from_queue_recovery(self):
- session = self.session
-
- #setup queue on remote broker and add some messages
- r_conn = self.connect(host=self.remote_host(), port=self.remote_port())
- r_session = r_conn.session("test_pull_from_queue_recovery")
- r_session.queue_declare(queue="my-bridge-queue", auto_delete=True)
- for i in range(1, 6):
- dp = r_session.delivery_properties(routing_key="my-bridge-queue")
- r_session.message_transfer(message=Message(dp, "Message %d" % i))
-
- #setup queue to receive messages from local broker
- session.queue_declare(queue="fed1", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="fed1", exchange="amq.fanout")
- self.subscribe(queue="fed1", destination="f1")
- queue = session.incoming("f1")
-
- self.startQmf()
- qmf = self.qmf
- broker = qmf.getObjects(_class="broker")[0]
- result = broker.connect(self.remote_host(), self.remote_port(), False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0, result)
-
- link = qmf.getObjects(_class="link")[0]
- result = link.bridge(False, "my-bridge-queue", "amq.fanout", "my-key", "", "", True, False, False, 1)
- self.assertEqual(result.status, 0, result)
-
- bridge = qmf.getObjects(_class="bridge")[0]
- sleep(5)
-
- #recreate the remote bridge queue to invalidate the bridge session
- r_session.queue_delete (queue="my-bridge-queue", if_empty=False, if_unused=False)
- r_session.queue_declare(queue="my-bridge-queue", auto_delete=True)
-
- #add some more messages (i.e. after bridge was created)
- for i in range(6, 11):
- dp = r_session.delivery_properties(routing_key="my-bridge-queue")
- r_session.message_transfer(message=Message(dp, "Message %d" % i))
-
- for i in range(1, 11):
- try:
- msg = queue.get(timeout=5)
- self.assertEqual("Message %d" % i, msg.body)
- except Empty:
- self.fail("Failed to find expected message containing 'Message %d'" % i)
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message in queue: " + extra.body)
- except Empty: None
-
- result = bridge.close()
self.assertEqual(result.status, 0)
result = link.close()
self.assertEqual(result.status, 0)
@@ -706,17 +649,10 @@ class FederationTests(TestBase010):
self.verify_cleanup()
- def test_dynamic_headers_any(self):
- self.do_test_dynamic_headers('any')
-
- def test_dynamic_headers_all(self):
- self.do_test_dynamic_headers('all')
-
-
- def do_test_dynamic_headers(self, match_mode):
+ def test_dynamic_headers(self):
session = self.session
r_conn = self.connect(host=self.remote_host(), port=self.remote_port())
- r_session = r_conn.session("test_dynamic_headers_%s" % match_mode)
+ r_session = r_conn.session("test_dynamic_headers")
session.exchange_declare(exchange="fed.headers", type="headers")
r_session.exchange_declare(exchange="fed.headers", type="headers")
@@ -735,7 +671,7 @@ class FederationTests(TestBase010):
sleep(5)
session.queue_declare(queue="fed1", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':match_mode, 'class':'first'})
+ session.exchange_bind(queue="fed1", exchange="fed.headers", binding_key="key1", arguments={'x-match':'any', 'class':'first'})
self.subscribe(queue="fed1", destination="f1")
queue = session.incoming("f1")
@@ -1855,301 +1791,3 @@ class FederationTests(TestBase010):
if headers:
return headers[name]
return None
-
- def test_dynamic_topic_bounce(self):
- """ Bounce the connection between federated Topic Exchanges.
- """
- class Params:
- def exchange_type(self): return "topic"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename,
- binding_key="spud.*")
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud.*")
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud.boy")
-
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_direct_bounce(self):
- """ Bounce the connection between federated Direct Exchanges.
- """
- class Params:
- def exchange_type(self): return "direct"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename, binding_key="spud")
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud")
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud")
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_fanout_bounce(self):
- """ Bounce the connection between federated Fanout Exchanges.
- """
- class Params:
- def exchange_type(self): return "fanout"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename)
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename)
- def delivery_properties(self, ssn):
- return ssn.delivery_properties(routing_key="spud")
- self.generic_dynamic_bounce_test(Params())
-
- def test_dynamic_headers_bounce(self):
- """ Bounce the connection between federated Headers Exchanges.
- """
- class Params:
- def exchange_type(self): return "headers"
- def bind_queue(self, ssn, qname, ename):
- ssn.exchange_bind(queue=qname, exchange=ename,
- binding_key="spud", arguments={'x-match':'any', 'class':'first'})
- def unbind_queue(self, ssn, qname, ename):
- ssn.exchange_unbind(queue=qname, exchange=ename, binding_key="spud")
- def delivery_properties(self, ssn):
- return ssn.message_properties(application_headers={'class':'first'})
- ## @todo KAG - re-enable once federation bugs with headers exchanges
- ## are fixed.
- #self.generic_dynamic_bounce_test(Params())
- return
-
-
- def generic_dynamic_bounce_test(self, params):
- """ Verify that a federated broker can maintain a binding to a local
- queue using the same key as a remote binding. Destroy and reconnect
- the federation link, and verify routes are restored correctly.
- See QPID-3170.
- Topology:
-
- Queue1 <---"Key"---B0<==[Federated Exchange]==>B1---"Key"--->Queue2
- """
- session = self.session
-
- # create the federation
-
- self.startQmf()
- qmf = self.qmf
-
- self._setup_brokers()
-
- # create exchange on each broker, and retrieve the corresponding
- # management object for that exchange
-
- exchanges=[]
- for _b in self._brokers[0:2]:
- _b.client_session.exchange_declare(exchange="fedX", type=params.exchange_type())
- self.assertEqual(_b.client_session.exchange_query(name="fedX").type,
- params.exchange_type(), "exchange_declare failed!")
- # pull the exchange out of qmf...
- retries = 0
- my_exchange = None
- timeout = time() + 10
- while my_exchange is None and time() <= timeout:
- objs = qmf.getObjects(_broker=_b.qmf_broker, _class="exchange")
- for ooo in objs:
- if ooo.name == "fedX":
- my_exchange = ooo
- break
- if my_exchange is None:
- self.fail("QMF failed to find new exchange!")
- exchanges.append(my_exchange)
-
- #
- # on each broker, create a local queue bound to the exchange with the
- # same key value.
- #
-
- self._brokers[0].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True)
- params.bind_queue(self._brokers[0].client_session, "fedX1", "fedX")
- self.subscribe(self._brokers[0].client_session, queue="fedX1", destination="f1")
- queue_0 = self._brokers[0].client_session.incoming("f1")
-
- self._brokers[1].client_session.queue_declare(queue="fedX1", exclusive=True, auto_delete=True)
- params.bind_queue(self._brokers[1].client_session, "fedX1", "fedX")
- self.subscribe(self._brokers[1].client_session, queue="fedX1", destination="f1")
- queue_1 = self._brokers[1].client_session.incoming("f1")
-
- # now federate the two brokers
-
- # connect B0 --> B1
- result = self._brokers[1].qmf_object.connect(self._brokers[0].host,
- self._brokers[0].port,
- False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0)
-
- # connect B1 --> B0
- result = self._brokers[0].qmf_object.connect(self._brokers[1].host,
- self._brokers[1].port,
- False, "PLAIN", "guest", "guest", "tcp")
- self.assertEqual(result.status, 0)
-
- # for each link, bridge the "fedX" exchanges:
-
- for _l in qmf.getObjects(_class="link"):
- # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker())))
- result = _l.bridge(False, # durable
- "fedX", # src
- "fedX", # dst
- "", # key
- "", # tag
- "", # excludes
- False, # srcIsQueue
- False, # srcIsLocal
- True, # dynamic
- 0) # sync
- self.assertEqual(result.status, 0)
-
- # wait for all the inter-broker links to become operational
- operational = False
- timeout = time() + 10
- while not operational and time() <= timeout:
- operational = True
- for _l in qmf.getObjects(_class="link"):
- #print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.state)))
- if _l.state != "Operational":
- operational = False
- self.failUnless(operational, "inter-broker links failed to become operational.")
-
- # @todo - There is no way to determine when the bridge objects become
- # active.
-
- # wait until the binding key has propagated to each broker - each
- # broker should see 2 bindings (1 local, 1 remote)
-
- binding_counts = [2, 2]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount < binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- # send 10 msgs to B0
- for i in range(1, 11):
- # dp = self._brokers[0].client_session.delivery_properties(routing_key=params.routing_key())
- dp = params.delivery_properties(self._brokers[0].client_session)
- self._brokers[0].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i))
-
- # get exactly 10 msgs on B0's local queue and B1's queue
- for i in range(1, 11):
- try:
- msg = queue_0.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- msg = queue_1.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- except Empty:
- self.fail("Only got %d msgs - expected 10" % i)
- try:
- extra = queue_0.get(timeout=1)
- self.fail("Got unexpected message in queue_0: " + extra.body)
- except Empty: None
-
- try:
- extra = queue_1.get(timeout=1)
- self.fail("Got unexpected message in queue_1: " + extra.body)
- except Empty: None
-
- #
- # Tear down the bridges between the two exchanges, then wait
- # for the bindings to be cleaned up
- #
-
- for _b in qmf.getObjects(_class="bridge"):
- result = _b.close()
- self.assertEqual(result.status, 0)
-
- binding_counts = [1, 1]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- #
- # restore the bridges between the two exchanges, and wait for the
- # bindings to propagate.
- #
-
- for _l in qmf.getObjects(_class="link"):
- # print("Link=%s:%s %s" % (_l.host, _l.port, str(_l.getBroker())))
- result = _l.bridge(False, # durable
- "fedX", # src
- "fedX", # dst
- "", # key
- "", # tag
- "", # excludes
- False, # srcIsQueue
- False, # srcIsLocal
- True, # dynamic
- 0) # sync
- self.assertEqual(result.status, 0)
-
- binding_counts = [2, 2]
- self.assertEqual(len(binding_counts), len(exchanges), "Update Test!")
- for i in range(2):
- exchanges[i].update()
- timeout = time() + 10
- while exchanges[i].bindingCount != binding_counts[i] and time() <= timeout:
- exchanges[i].update()
- self.failUnless(exchanges[i].bindingCount == binding_counts[i])
-
- #
- # verify traffic flows correctly
- #
-
- for i in range(1, 11):
- #dp = self._brokers[1].client_session.delivery_properties(routing_key=params.routing_key())
- dp = params.delivery_properties(self._brokers[1].client_session)
- self._brokers[1].client_session.message_transfer(destination="fedX", message=Message(dp, "Message_trp %d" % i))
-
- # get exactly 10 msgs on B0's queue and B1's queue
- for i in range(1, 11):
- try:
- msg = queue_0.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- msg = queue_1.get(timeout=5)
- self.assertEqual("Message_trp %d" % i, msg.body)
- except Empty:
- self.fail("Only got %d msgs - expected 10" % i)
- try:
- extra = queue_0.get(timeout=1)
- self.fail("Got unexpected message in queue_0: " + extra.body)
- except Empty: None
-
- try:
- extra = queue_1.get(timeout=1)
- self.fail("Got unexpected message in queue_1: " + extra.body)
- except Empty: None
-
-
- #
- # cleanup
- #
- params.unbind_queue(self._brokers[0].client_session, "fedX1", "fedX")
- self._brokers[0].client_session.message_cancel(destination="f1")
- self._brokers[0].client_session.queue_delete(queue="fedX1")
-
- params.unbind_queue(self._brokers[1].client_session, "fedX1", "fedX")
- self._brokers[1].client_session.message_cancel(destination="f1")
- self._brokers[1].client_session.queue_delete(queue="fedX1")
-
- for _b in qmf.getObjects(_class="bridge"):
- result = _b.close()
- self.assertEqual(result.status, 0)
-
- for _l in qmf.getObjects(_class="link"):
- result = _l.close()
- self.assertEqual(result.status, 0)
-
- for _b in self._brokers[0:2]:
- _b.client_session.exchange_delete(exchange="fedX")
-
- self._teardown_brokers()
-
- self.verify_cleanup()
-
-
diff --git a/cpp/src/tests/federation_sys.py b/cpp/src/tests/federation_sys.py
deleted file mode 100755
index 11590f684e..0000000000
--- a/cpp/src/tests/federation_sys.py
+++ /dev/null
@@ -1,1900 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-from inspect import stack
-from qpid import messaging
-from qpid.messaging import Message
-from qpid.messaging.exceptions import Empty
-from qpid.testlib import TestBase010
-from random import randint
-from sys import stdout
-from time import sleep
-
-
-class Enum(object):
- def __init__(self, **entries):
- self.__dict__.update(entries)
- def __repr__(self):
- args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()]
- return 'Enum(%s)' % ', '.join(args)
-
-
-class QmfTestBase010(TestBase010):
-
- _brokers = []
- _links = []
- _bridges = []
- _alt_exch_ops = Enum(none=0, create=1, delete=2)
-
- class _Broker(object):
- """
- This broker proxy object holds the Qmf proxy to a broker of known address as well as the QMF broker
- object, connection and sessions to the broker.
- """
- def __init__(self, url):
- self.url = url # format: "host:port"
- url_parts = url.split(':')
- self.host = url_parts[0]
- self.port = int(url_parts[1])
- self.qmf_broker = None
- self.connection = messaging.Connection.establish(self.url)
- self.sessions = []
- def __str__(self):
- return "_Broker %s:%s (%d open sessions)" % (self.host, self.port, len(self.sessions))
- def destroy(self, qmf = None):
- if qmf is not None:
- qmf.delBroker(self.qmf_broker.getBroker())
- for session in self.sessions:
- try: # Session may have been closed by broker error
- session.close()
- except Exception, e: print "WARNING: %s: Unable to close session %s (%s): %s %s" % (self, session, hex(id(session)), type(e), e)
- try: # Connection may have been closed by broker error
- self.connection.close()
- except Exception, e: print "WARNING: %s: Unable to close connection %s (%s): %s %s" % (self, self.connection, hex(id(self.connection)), type(e), e)
- def session(self, name, transactional_flag = False):
- session = self.connection.session(name, transactional_flag)
- self.sessions.append(session)
- return session
-
- def setUp(self):
- """
- Called one before each test starts
- """
- TestBase010.setUp(self)
- self.startQmf();
-
- def tearDown(self):
- """
- Called once after each test competes. Close all Qmf objects (bridges, links and brokers)
- """
- while len(self._bridges):
- self._bridges.pop().close()
- while len(self._links):
- self._links.pop().close()
- while len(self._brokers):
- b = self._brokers.pop()
- if len(self._brokers) <= 1:
- b.destroy(None)
- else:
- b.destroy(self.qmf)
- TestBase010.tearDown(self)
- self.qmf.close()
-
- #--- General test utility functions
-
- def _get_name(self):
- """
- Return the name of method which called this method stripped of "test_" prefix. Used for naming
- queues and exchanges on a per-test basis.
- """
- return stack()[1][3][5:]
-
- def _get_broker_port(self, key):
- """
- Get the port of a broker defined in the environment using -D<key>=portno
- """
- return int(self.defines[key])
-
- def _get_cluster_ports(self, key):
- """
- Get the cluster ports from the parameters of the test which place it in the environment using
- -D<key>="port0 port1 ... portN" (space-separated)
- """
- ports = []
- ports_str = self.defines[key]
- if ports_str:
- for p in ports_str.split():
- ports.append(int(p))
- return ports
-
- def _get_send_address(self, exch_name, queue_name):
- """
- Get an address to which to send messages based on the exchange name and queue name, but taking into account
- that the exchange name may be "" (the default exchange), in whcih case the format changes slightly.
- """
- if len(exch_name) == 0: # Default exchange
- return queue_name
- return "%s/%s" % (exch_name, queue_name)
-
- def _get_broker(self, cluster_flag, broker_port_key, cluster_ports_key):
- """
- Read the port numbers for pre-started brokers from the environment using keys, then find or create and return
- the Qmf broker proxy for the appropriate broker
- """
- if cluster_flag:
- port = self._get_cluster_ports(cluster_ports_key)[0] # Always use the first node in the cluster
- else:
- port = self._get_broker_port(broker_port_key)
- return self._find_create_broker("localhost:%s" % port)
-
- def _get_msg_subject(self, topic_key):
- """
- Return an appropriate subject for sending a message to a known topic. Return None if there is no topic.
- """
- if len(topic_key) == 0: return None
- if "*" in topic_key: return topic_key.replace("*", "test")
- if "#" in topic_key: return topic_key.replace("#", "multipart.test")
- return topic_key
-
- def _send_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", topic_key = "",
- msg_durable_flag = False, enq_txn_size = 0):
- """
- Send messages to a broker using address addr
- """
- send_session = broker.session(session_name, transactional_flag = enq_txn_size > 0)
- sender = send_session.sender(addr)
- txn_cnt = 0
- for i in range(0, msg_count):
- sender.send(Message(msg_content % (i + 1), subject = self._get_msg_subject(topic_key), durable = msg_durable_flag))
- if enq_txn_size > 0:
- txn_cnt += 1
- if txn_cnt >= enq_txn_size:
- send_session.commit()
- txn_cnt = 0
- if enq_txn_size > 0 and txn_cnt > 0:
- send_session.commit()
- sender.close()
- send_session.close()
-
- def _receive_msgs(self, session_name, broker, addr, msg_count, msg_content = "Message_%03d", deq_txn_size = 0,
- timeout = 0):
- """
- Receive messages from a broker
- """
- receive_session = broker.session(session_name, transactional_flag = deq_txn_size > 0)
- receiver = receive_session.receiver(addr)
- txn_cnt = 0
- for i in range(0, msg_count):
- try:
- msg = receiver.fetch(timeout = timeout)
- if deq_txn_size > 0:
- txn_cnt += 1
- if txn_cnt >= deq_txn_size:
- receive_session.commit()
- txn_cnt = 0
- receive_session.acknowledge()
- except Empty:
- if deq_txn_size > 0: receive_session.rollback()
- receiver.close()
- receive_session.close()
- if i == 0:
- self.fail("Broker %s queue \"%s\" is empty" % (broker.qmf_broker.getBroker().getUrl(), addr))
- else:
- self.fail("Unable to receive message %d from broker %s queue \"%s\"" % (i, broker.qmf_broker.getBroker().getUrl(), addr))
- if msg.content != msg_content % (i + 1):
- receiver.close()
- receive_session.close()
- self.fail("Unexpected message \"%s\", was expecting \"%s\"." % (msg.content, msg_content % (i + 1)))
- try:
- msg = receiver.fetch(timeout = 0)
- if deq_txn_size > 0: receive_session.rollback()
- receiver.close()
- receive_session.close()
- self.fail("Extra message \"%s\" found on broker %s address \"%s\"" % (msg.content, broker.qmf_broker.getBroker().getUrl(), addr))
- except Empty:
- pass
- if deq_txn_size > 0 and txn_cnt > 0:
- receive_session.commit()
- receiver.close()
- receive_session.close()
-
- #--- QMF-specific utility functions
-
- def _get_qmf_property(self, props, key):
- """
- Get the value of a named property key kj from a property list [(k0, v0), (k1, v1), ... (kn, vn)].
- """
- for k,v in props:
- if k.name == key:
- return v
- return None
-
- def _check_qmf_return(self, method_result):
- """
- Check the result of a Qmf-defined method call
- """
- self.assertTrue(method_result.status == 0, method_result.text)
-
- def _check_optional_qmf_property(self, qmf_broker, type, qmf_object, key, expected_val, obj_ref_flag):
- """
- Optional Qmf properties don't show up in the properties list when they are not specified. Checks for
- these property types involve searching the properties list and making sure it is present or not as
- expected.
- """
- val = self._get_qmf_property(qmf_object.getProperties(), key)
- if val is None:
- if len(expected_val) > 0:
- self.fail("%s %s exists, but has does not have %s property. Expected value: \"%s\"" %
- (type, qmf_object.name, key, expected_val))
- else:
- if len(expected_val) > 0:
- if obj_ref_flag:
- obj = self.qmf.getObjects(_objectId = val, _broker = qmf_broker.getBroker())
- self.assertEqual(len(obj), 1, "More than one object with the same objectId: %s" % obj)
- val = obj[0].name
- self.assertEqual(val, expected_val, "%s %s exists, but has incorrect %s property. Found \"%s\", expected \"%s\"" %
- (type, qmf_object.name, key, val, expected_val))
- else:
- self.fail("%s %s exists, but has an unexpected %s property \"%s\" set." % (type, qmf_object.name, key, val))
-
- #--- Find/create Qmf broker objects
-
- def _find_qmf_broker(self, url):
- """
- Find the Qmf broker object for the given broker URL. The broker must have been previously added to Qmf through
- addBroker()
- """
- for b in self.qmf.getObjects(_class="broker"):
- if b.getBroker().getUrl() == url:
- return b
- return None
-
- def _find_create_broker(self, url):
- """
- Find a running broker through Qmf. If it does not exist, add it (assuming the broker is already running).
- """
- broker = self._Broker(url)
- self._brokers.append(broker)
- if self.qmf is not None:
- qmf_broker = self._find_qmf_broker(broker.url)
- if qmf_broker is None:
- self.qmf.addBroker(broker.url)
- broker.qmf_broker = self._find_qmf_broker(broker.url)
- else:
- broker.qmf_broker = qmf_broker
- return broker
-
- #--- Find/create/delete exchanges
-
- def _find_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete):
- """
- Find Qmf exchange object
- """
- for e in self.qmf.getObjects(_class="exchange", _broker = qmf_broker.getBroker()):
- if e.name == name:
- if len(name) == 0 or (len(name) >= 4 and name[:4] == "amq."): return e # skip checks for special exchanges
- self.assertEqual(e.type, type,
- "Exchange \"%s\" exists, but is of unexpected type %s; expected type %s." %
- (name, e.type, type))
- self._check_optional_qmf_property(qmf_broker, "Exchange", e, "altExchange", alternate, True)
- self.assertEqual(e.durable, durable,
- "Exchange \"%s\" exists, but has incorrect durability. Found durable=%s, expected durable=%s" %
- (name, e.durable, durable))
- self.assertEqual(e.autoDelete, auto_delete,
- "Exchange \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" %
- (name, e.autoDelete, auto_delete))
- return e
- return None
-
- def _find_create_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete, args):
- """
- Find Qmf exchange object if exchange exists, create exchange and return its Qmf object if not
- """
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- if e is not None: return e
- # Does not exist, so create it
- props = dict({"exchange-type": type, "type": type, "durable": durable, "auto-delete": auto_delete, "alternate-exchange": alternate}, **args)
- self._check_qmf_return(qmf_broker.create(type="exchange", name=name, properties=props, strict=True))
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- self.assertNotEqual(e, None, "Creation of exchange %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl()))
- return e
-
- def _find_delete_qmf_exchange(self, qmf_broker, name, type, alternate, durable, auto_delete):
- """
- Find and delete Qmf exchange object if it exists
- """
- e = self._find_qmf_exchange(qmf_broker, name, type, alternate, durable, auto_delete)
- if e is not None and not auto_delete:
- self._check_qmf_return(qmf_broker.delete(type="exchange", name=name, options={}))
-
- #--- Find/create/delete queues
-
- def _find_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete):
- """
- Find a Qmf queue object
- """
- for q in self.qmf.getObjects(_class="queue", _broker = qmf_broker.getBroker()):
- if q.name == name:
- self._check_optional_qmf_property(qmf_broker, "Queue", q, "altExchange", alternate_exchange, True)
- self.assertEqual(q.durable, durable,
- "Queue \"%s\" exists, but has incorrect durable property. Found %s, expected %s" %
- (name, q.durable, durable))
- self.assertEqual(q.exclusive, exclusive,
- "Queue \"%s\" exists, but has incorrect exclusive property. Found %s, expected %s" %
- (name, q.exclusive, exclusive))
- self.assertEqual(q.autoDelete, auto_delete,
- "Queue \"%s\" exists, but has incorrect auto-delete property. Found %s, expected %s" %
- (name, q.autoDelete, auto_delete))
- return q
- return None
-
- def _find_create_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args):
- """
- Find Qmf queue object if queue exists, create queue and return its Qmf object if not
- """
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- if q is not None: return q
- # Queue does not exist, so create it
- props = dict({"durable": durable, "auto-delete": auto_delete, "exclusive": exclusive, "alternate-exchange": alternate_exchange}, **args)
- self._check_qmf_return(qmf_broker.create(type="queue", name=name, properties=props, strict=True))
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- self.assertNotEqual(q, None, "Creation of queue %s on broker %s failed" % (name, qmf_broker.getBroker().getUrl()))
- return q
-
- def _find_delete_qmf_queue(self, qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete, args):
- """
- Find and delete Qmf queue object if it exists
- """
- q = self._find_qmf_queue(qmf_broker, name, alternate_exchange, durable, exclusive, auto_delete)
- if q is not None and not auto_delete:
- self._check_qmf_return(qmf_broker.delete(type="queue", name=name, options={}))
-
- #--- Find/create/delete bindings (between an exchange and a queue)
-
- def _find_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find a Qmf binding object
- """
- for b in self.qmf.getObjects(_class="binding", _broker = qmf_broker.getBroker()):
- if b.exchangeRef == qmf_exchange.getObjectId() and b.queueRef == qmf_queue.getObjectId():
- if qmf_exchange.type != "fanout": # Fanout ignores the binding key, and always returns "" as the key
- self.assertEqual(b.bindingKey, binding_key,
- "Binding between exchange %s and queue %s exists, but has mismatching binding key: Found %s, expected %s." %
- (qmf_exchange.name, qmf_queue.name, b.bindingKey, binding_key))
- self.assertEqual(b.arguments, binding_args,
- "Binding between exchange %s and queue %s exists, but has mismatching arguments: Found %s, expected %s" %
- (qmf_exchange.name, qmf_queue.name, b.arguments, binding_args))
- return b
- return None
-
- def _find_create_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find Qmf binding object if it exists, create binding and return its Qmf object if not
- """
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- if b is not None: return b
- # Does not exist, so create it
- self._check_qmf_return(qmf_broker.create(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), properties=binding_args, strict=True))
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- self.assertNotEqual(b, None, "Creation of binding between exchange %s and queue %s with key %s failed" %
- (qmf_exchange.name, qmf_queue.name, binding_key))
- return b
-
- def _find_delete_qmf_binding(self, qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args):
- """
- Find and delete Qmf binding object if it exists
- """
- b = self._find_qmf_binding(qmf_broker, qmf_exchange, qmf_queue, binding_key, binding_args)
- if b is not None:
- if len(qmf_exchange.name) > 0: # not default exchange
- self._check_qmf_return(qmf_broker.delete(type="binding", name="%s/%s/%s" % (qmf_exchange.name, qmf_queue.name, binding_key), options={}))
-
- #--- Find/create a link
-
- def _find_qmf_link(self, qmf_from_broker_proxy, host, port):
- """
- Find a Qmf link object
- """
- for l in self.qmf.getObjects(_class="link", _broker=qmf_from_broker_proxy):
- if l.host == host and l.port == port:
- return l
- return None
-
- def _find_create_qmf_link(self, qmf_from_broker, qmf_to_broker_proxy, link_durable_flag, auth_mechanism, user_id,
- password, transport, pause_interval, link_ready_timeout):
- """
- Find a Qmf link object if it exists, create it and return its Qmf link object if not
- """
- to_broker_host = qmf_to_broker_proxy.host
- to_broker_port = qmf_to_broker_proxy.port
- l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port)
- if l is not None: return l
- # Does not exist, so create it
- self._check_qmf_return(qmf_from_broker.connect(to_broker_host, to_broker_port, link_durable_flag, auth_mechanism, user_id, password, transport))
- l = self._find_qmf_link(qmf_from_broker.getBroker(), to_broker_host, to_broker_port)
- self.assertNotEqual(l, None, "Creation of link from broker %s to broker %s failed" %
- (qmf_from_broker.getBroker().getUrl(), qmf_to_broker_proxy.getUrl()))
- self._wait_for_link(l, pause_interval, link_ready_timeout)
- return l
-
- def _wait_for_link(self, link, pause_interval, link_ready_timeout):
- """
- Wait for link to become active (state=Operational)
- """
- tot_time = 0
- link.update()
- if link.state == "":
- # Link mgmt updates for the c++ link object are disabled when in a cluster because of inconsistent state:
- # one is "Operational", the other "Passive". In this case, wait a bit and hope for the best...
- sleep(2*pause_interval)
- else:
- while link.state != "Operational" and tot_time < link_ready_timeout:
- sleep(pause_interval)
- tot_time += pause_interval
- link.update()
- self.assertEqual(link.state, "Operational", "Timeout: Link not operational, state=%s" % link.state)
-
- #--- Find/create a bridge
-
- def _find_qmf_bridge(self, qmf_broker_proxy, qmf_link, source, destination, key):
- """
- Find a Qmf link object
- """
- for b in self.qmf.getObjects(_class="bridge", _broker=qmf_broker_proxy):
- if b.linkRef == qmf_link.getObjectId() and b.src == source and b.dest == destination and b.key == key:
- return b
- return None
-
- def _find_create_qmf_bridge(self, qmf_broker_proxy, qmf_link, queue_name, exch_name, topic_key,
- queue_route_type_flag, bridge_durable_flag):
- """
- Find a Qmf bridge object if it exists, create it and return its Qmf object if not
- """
- if queue_route_type_flag:
- src = queue_name
- dest = exch_name
- key = ""
- else:
- src = exch_name
- dest = exch_name
- if len(topic_key) > 0:
- key = topic_key
- else:
- key = queue_name
- b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key)
- if b is not None:
- return b
- # Does not exist, so create it
- self._check_qmf_return(qmf_link.bridge(bridge_durable_flag, src, dest, key, "", "", queue_route_type_flag, False, False, 1))
- b = self._find_qmf_bridge(qmf_broker_proxy, qmf_link, src, dest, key)
- self.assertNotEqual(b, None, "Bridge creation failed: src=%s dest=%s key=%s" % (src, dest, key))
- return b
-
- def _wait_for_bridge(self, bridge, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval,
- bridge_ready_timeout):
- """
- Wait for bridge to become active by sending messages over the bridge at 1 sec intervals until they are
- observed at the destination.
- """
- tot_time = 0
- active = False
- send_session = src_broker.session("tx")
- sender = send_session.sender(self._get_send_address(exch_name, queue_name))
- src_receive_session = src_broker.session("src_rx")
- src_receiver = src_receive_session.receiver(queue_name)
- dest_receive_session = dest_broker.session("dest_rx")
- dest_receiver = dest_receive_session.receiver(queue_name)
- while not active and tot_time < bridge_ready_timeout:
- sender.send(Message("xyz123", subject = self._get_msg_subject(topic_key)))
- try:
- src_receiver.fetch(timeout = 0)
- src_receive_session.acknowledge()
- # Keep receiving msgs, as several may have accumulated
- while True:
- dest_receiver.fetch(timeout = 0)
- dest_receive_session.acknowledge()
- sleep(1)
- active = True
- except Empty:
- sleep(pause_interval)
- tot_time += pause_interval
- dest_receiver.close()
- dest_receive_session.close()
- src_receiver.close()
- src_receive_session.close()
- sender.close()
- send_session.close()
- self.assertTrue(active, "Bridge failed to become active after %ds: %s" % (bridge_ready_timeout, bridge))
-
- #--- Find/create/delete utility functions
-
- def _create_and_bind(self, qmf_broker, exchange_args, queue_args, binding_args):
- """
- Create a binding between a named exchange and queue on a broker
- """
- e = self._find_create_qmf_exchange(qmf_broker, **exchange_args)
- q = self._find_create_qmf_queue(qmf_broker, **queue_args)
- return self._find_create_qmf_binding(qmf_broker, e, q, **binding_args)
-
- def _check_alt_exchange(self, qmf_broker, alt_exch_name, alt_exch_type, alt_exch_op):
- """
- Check for existence of alternate exchange. Return the Qmf exchange proxy object for the alternate exchange
- """
- if len(alt_exch_name) == 0: return None
- if alt_exch_op == _alt_exch_ops.create:
- return self._find_create_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type,
- alternate="", durable=False, auto_delete=False, args={})
- if alt_exch_op == _alt_exch_ops.delete:
- return self._find_delete_qmf_exchange(qmf_broker=qmf_broker, name=alt_exch_name, type=alt_exch_type,
- alternate="", durable=False, auto_delete=False)
- return self._find_qmf_exchange(qmf_broker=qmf_broker, name=alt_exchange_name, type=alt_exchange_type,
- alternate="", durable=False, auto_delete=False)
-
- def _delete_queue_binding(self, qmf_broker, exchange_args, queue_args, binding_args):
- """
- Delete a queue and the binding between it and the exchange
- """
- e = self._find_qmf_exchange(qmf_broker, exchange_args["name"], exchange_args["type"], exchange_args["alternate"], exchange_args["durable"], exchange_args["auto_delete"])
- q = self._find_qmf_queue(qmf_broker, queue_args["name"], queue_args["alternate_exchange"], queue_args["durable"], queue_args["exclusive"], queue_args["auto_delete"])
- self._find_delete_qmf_binding(qmf_broker, e, q, **binding_args)
- self._find_delete_qmf_queue(qmf_broker, **queue_args)
-
- def _create_route(self, queue_route_type_flag, src_broker, dest_broker, exch_name, queue_name, topic_key,
- link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport,
- pause_interval = 1, link_ready_timeout = 20, bridge_ready_timeout = 20):
- """
- Create a route from a source broker to a destination broker
- """
- l = self._find_create_qmf_link(dest_broker.qmf_broker, src_broker.qmf_broker.getBroker(), link_durable_flag,
- auth_mechanism, user_id, password, transport, pause_interval, link_ready_timeout)
- self._links.append(l)
- b = self._find_create_qmf_bridge(dest_broker.qmf_broker.getBroker(), l, queue_name, exch_name, topic_key,
- queue_route_type_flag, bridge_durable_flag)
- self._bridges.append(b)
- self._wait_for_bridge(b, src_broker, dest_broker, exch_name, queue_name, topic_key, pause_interval, bridge_ready_timeout)
-
- # Parameterized test - entry point for tests
-
- def _do_test(self,
- test_name, # Name of test
- exch_name = "amq.direct", # Remote exchange name
- exch_type = "direct", # Remote exchange type
- exch_alt_exch = "", # Remote exchange alternate exchange
- exch_alt_exch_type = "direct", # Remote exchange alternate exchange type
- exch_durable_flag = False, # Remote exchange durability
- exch_auto_delete_flag = False, # Remote exchange auto-delete property
- exch_x_args = {}, # Remote exchange args
- queue_alt_exch = "", # Remote queue alternate exchange
- queue_alt_exch_type = "direct", # Remote queue alternate exchange type
- queue_durable_flag = False, # Remote queue durability
- queue_exclusive_flag = False, # Remote queue exclusive property
- queue_auto_delete_flag = False, # Remote queue auto-delete property
- queue_x_args = {}, # Remote queue args
- binding_durable_flag = False, # Remote binding durability
- binding_x_args = {}, # Remote binding args
- topic_key = "", # Binding key For remote topic exchanges only
- msg_count = 10, # Number of messages to send
- msg_durable_flag = False, # Message durability
- link_durable_flag = False, # Route link durability
- bridge_durable_flag = False, # Route bridge durability
- queue_route_type_flag = False, # Route type: false = bridge route, true = queue route
- enq_txn_size = 0, # Enqueue transaction size, 0 = no transactions
- deq_txn_size = 0, # Dequeue transaction size, 0 = no transactions
- local_cluster_flag = False, # Use a node from the local cluster, otherwise use single local broker
- remote_cluster_flag = False, # Use a node from the remote cluster, otherwise use single remote broker
- alt_exch_op = _alt_exch_ops.create,# Op on alt exch [create (ensure present), delete (ensure not present), none (neither create nor delete)]
- auth_mechanism = "", # Authorization mechanism for linked broker
- user_id = "", # User ID for authorization on linked broker
- password = "", # Password for authorization on linked broker
- transport = "tcp" # Transport for route to linked broker
- ):
- """
- Parameterized federation test. Sets up a federated link between a source broker and a destination broker and
- checks that messages correctly pass over the link to the destination. Where appropriate (non-queue-routes), also
- checks for the presence of messages on the source broker.
-
- In these tests, the concept is to create a LOCAL broker, then create a link to a REMOTE broker using federation.
- In other words, the messages sent to the LOCAL broker will be replicated on the REMOTE broker, and tests are
- performed on the REMOTE broker to check that the required messages are present. In the case of regular routes,
- the LOCAL broker will also retain the messages, and a similar test is performed on this broker.
-
- TODO: There are several items to improve here:
- 1. _do_test() is rather general. Rather create a version for each exchange type and test the exchange/queue
- interaction in more detail based on the exchange type
- 2. Add a headers and an xml exchange type
- 3. Restructure the tests to start and stop brokers and clusters directly rather than relying on previously
- started brokers. Then persistence can be checked by stopping and restarting the brokers/clusters. In particular,
- test the persistence of links and bridges, both of which take a persistence flag.
- 4. Test the behavior of the alternate exchanges when messages are sourced through a link. Also check behavior
- when the alternate exchange is not present or is deleted after the reference is made.
- 5. Test special queue types (eg LVQ)
- """
- local_broker = self._get_broker(local_cluster_flag, "local-port", "local-cluster-ports")
- remote_broker = self._get_broker(remote_cluster_flag, "remote-port", "remote-cluster-ports")
-
- # Check alternate exchanges exist (and create them if not) on both local and remote brokers
- self._check_alt_exchange(local_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(local_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(remote_broker.qmf_broker, exch_alt_exch, exch_alt_exch_type, alt_exch_op)
- self._check_alt_exchange(remote_broker.qmf_broker, queue_alt_exch, queue_alt_exch_type, alt_exch_op)
-
- queue_name = "queue_%s" % test_name
- exchange_args = {"name": exch_name, "type": exch_type, "alternate": exch_alt_exch,
- "durable": exch_durable_flag, "auto_delete": exch_auto_delete_flag, "args": exch_x_args}
- queue_args = {"name": queue_name, "alternate_exchange": queue_alt_exch, "durable": queue_durable_flag,
- "exclusive": queue_exclusive_flag, "auto_delete": queue_auto_delete_flag, "args": queue_x_args}
- binding_args = {"binding_args": binding_x_args}
- if exch_type == "topic":
- self.assertTrue(len(topic_key) > 0, "Topic exchange selected, but no topic key was set.")
- binding_args["binding_key"] = topic_key
- elif exch_type == "direct":
- binding_args["binding_key"] = queue_name
- else:
- binding_args["binding_key"] = ""
- self._create_and_bind(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._create_and_bind(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._create_route(queue_route_type_flag, local_broker, remote_broker, exch_name, queue_name, topic_key,
- link_durable_flag, bridge_durable_flag, auth_mechanism, user_id, password, transport)
-
- self._send_msgs("send_session", local_broker, addr = self._get_send_address(exch_name, queue_name),
- msg_count = msg_count, topic_key = topic_key, msg_durable_flag = msg_durable_flag, enq_txn_size = enq_txn_size)
- if not queue_route_type_flag:
- self._receive_msgs("local_receive_session", local_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size)
- self._receive_msgs("remote_receive_session", remote_broker, addr = queue_name, msg_count = msg_count, deq_txn_size = deq_txn_size, timeout = 5)
-
- # Clean up
- self._delete_queue_binding(qmf_broker=local_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
- self._delete_queue_binding(qmf_broker=remote_broker.qmf_broker, exchange_args=exchange_args, queue_args=queue_args, binding_args=binding_args)
-
-class A_ShortTests(QmfTestBase010):
-
- def test_route_defaultExch(self):
- self._do_test(self._get_name())
-
- def test_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True)
-
-
-class A_LongTests(QmfTestBase010):
-
- def test_route_amqDirectExch(self):
- self._do_test(self._get_name(), exch_name="amq.direct")
-
- def test_queueRoute_amqDirectExch(self):
- self._do_test(self._get_name(), exch_name="amq.direct", queue_route_type_flag=True)
-
-
- def test_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange")
-
- def test_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True)
-
-
- def test_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout")
-
- def test_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True)
-
-
- def test_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#")
-
- def test_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True)
-
-
-class B_ShortTransactionTests(QmfTestBase010):
-
- def test_txEnq01_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1)
-
- def test_txEnq01_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class B_LongTransactionTests(QmfTestBase010):
-
- def test_txEnq10_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
-
-
-
- def test_txEnq01_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1)
-
- def test_txEnq01_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class C_ShortClusterTests(QmfTestBase010):
-
- def test_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), local_cluster_flag=True)
-
- def test_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class C_LongClusterTests(QmfTestBase010):
-
- def test_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", local_cluster_flag=True)
-
- def test_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class D_ShortClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq01_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class D_LongClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq10_locCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_defaultExch(self):
- self._do_test(self._get_name(), enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_defaultExch(self):
- self._do_test(self._get_name(), queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class E_ShortPersistenceTests(QmfTestBase010):
-
- def test_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
-class E_LongPersistenceTests(QmfTestBase010):
-
-
- def test_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
- def test_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
- def test_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True)
-
- def test_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True)
-
- def test_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True)
-
- def test_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True)
-
-
-class F_ShortPersistenceTransactionTests(QmfTestBase010):
-
- def test_txEnq01_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class F_LongPersistenceTransactionTests(QmfTestBase010):
-
- def test_txEnq10_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
-
-
-
- def test_txEnq01_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
- def test_txEnq01_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq01_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1)
-
- def test_txEnq10_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq10_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103)
-
- def test_txEnq01_txDeq01_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
- def test_txEnq01_txDeq01_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1)
-
-
-class G_ShortPersistenceClusterTests(QmfTestBase010):
-
- def test_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class G_LongPersistenceClusterTests(QmfTestBase010):
-
-
-
- def test_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True)
-
- def test_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class H_ShortPersistenceClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq01_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-class H_LongPersistenceClusterTransactionTests(QmfTestBase010):
-
- def test_txEnq10_locCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_defaultExch(self):
- self._do_test(self._get_name(), queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_defaultExch(self):
- self._do_test(self._get_name(), msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
-
-
-
- def test_txEnq01_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_directExch(self):
- self._do_test(self._get_name(), exch_name="testDirectExchange", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_fanoutExch(self):
- self._do_test(self._get_name(), exch_name="testFanoutExchange", exch_type="fanout", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
-
- def test_txEnq01_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq10_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq10_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq10_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=10, msg_count = 103, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_route_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
- def test_txEnq01_txDeq01_locCluster_remCluster_queueRoute_durMsg_durQueue_topicExch(self):
- self._do_test(self._get_name(), exch_name="testTopicExchange", exch_type="topic", topic_key=self._get_name()+".#", msg_durable_flag=True, queue_durable_flag=True, queue_route_type_flag=True, enq_txn_size=1, deq_txn_size=1, local_cluster_flag=True, remote_cluster_flag=True)
-
diff --git a/cpp/src/tests/ipv6_test b/cpp/src/tests/ipv6_test
deleted file mode 100755
index d75d50fd0a..0000000000
--- a/cpp/src/tests/ipv6_test
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run a simple test over IPv6
-source ./test_env.sh
-
-CONFIG=$(dirname $0)/config.null
-TEST_HOSTNAME=::1
-COUNT=10
-
-trap cleanup EXIT
-
-error() { echo $*; exit 1; }
-
-# Don't need --no-module-dir or --no-data-dir as they are set as env vars in test_env.sh
-COMMON_OPTS="--daemon --auth no --config $CONFIG"
-
-# Record all broker ports started
-unset PORTS
-declare -a PORTS
-
-# Start new brokers:
-# $1 must be integer
-# $2 = extra opts
-# Append used ports to PORTS variable
-start_brokers() {
- local -a ports
- for (( i=0; $i<$1; i++)) do
- ports[$i]=$($QPIDD_EXEC --port 0 $COMMON_OPTS $2)
- done
- PORTS=( ${PORTS[@]} ${ports[@]} )
-}
-
-stop_brokers() {
- for port in "${PORTS[@]}";
- do
- $QPIDD_EXEC -qp $port
- done
- PORTS=()
-}
-
-cleanup() {
- stop_brokers
-}
-
-start_brokers 1
-PORT=${PORTS[0]}
-echo "Started IPv6 smoke perftest on broker port $PORT"
-
-## Test connection via connection settings
-./qpid-perftest --count ${COUNT} --port ${PORT} -b $TEST_HOSTNAME --summary
-
-## Test connection with a URL
-URL="amqp:[$TEST_HOSTNAME]:$PORT"
-
-./qpid-send -b $URL --content-string=hello -a "foo;{create:always}"
-MSG=`./qpid-receive -b $URL -a "foo;{create:always}" --messages 1`
-test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; }
-
-stop_brokers
-
-# Federation smoke test follows
-
-# Start 2 brokers
-
-# In a distribution, the python tools will be absent.
-if [ ! -f $QPID_CONFIG_EXEC ] || [ ! -f $QPID_ROUTE_EXEC ] ; then
- echo "python tools absent - skipping federation test."
-else
-
- start_brokers 2
- echo "Started Federated brokers on ports ${PORTS[*]}"
- # Make broker urls
- BROKER0="[::1]:${PORTS[0]}"
- BROKER1="[::1]:${PORTS[1]}"
- TEST_QUEUE=ipv6-fed-test
-
- $QPID_CONFIG_EXEC -a $BROKER0 add queue $TEST_QUEUE
- $QPID_CONFIG_EXEC -a $BROKER1 add queue $TEST_QUEUE
- $QPID_ROUTE_EXEC dynamic add $BROKER1 $BROKER0 amq.direct
- $QPID_CONFIG_EXEC -a $BROKER1 bind amq.direct $TEST_QUEUE $TEST_QUEUE
- $QPID_ROUTE_EXEC route map $BROKER1
-
- ./datagen --count 100 | tee rdata-in |
- ./qpid-send -b amqp:$BROKER0 -a amq.direct/$TEST_QUEUE --content-stdin
- ./qpid-receive -b amqp:$BROKER1 -a $TEST_QUEUE --print-content yes -m 0 > rdata-out
-
- cmp rdata-in rdata-out || { echo "Federated data over IPv6 does not compare"; exit 1; }
-
- stop_brokers
- rm rdata-in rdata-out
-fi
-
-# Cluster smoke test follows
-test -z $CLUSTER_LIB && exit 0 # Exit if cluster not supported.
-
-## Test failover in a cluster using IPv6 only
-. $srcdir/ais_check # Will exit if clustering not enabled.
-
-pick_port() {
- # We need a fixed port to set --cluster-url. Use qpidd to pick a free port.
- # Note this method is racy
- PICK=$($QPIDD_EXEC -dp0)
- $QPIDD_EXEC -qp $PICK
- echo $PICK
-}
-
-ssl_cluster_broker() { # $1 = port
- $QPIDD_EXEC $COMMON_OPTS --load-module $CLUSTER_LIB --cluster-name ipv6_test.$HOSTNAME.$$ --cluster-url amqp:[$TEST_HOSTNAME]:$1 --port $1
- # Wait for broker to be ready
- ./qpid-ping -b $TEST_HOSTNAME -qp $1 || { echo "Cannot connect to broker on $1"; exit 1; }
- echo "Running IPv6 cluster broker on port $1"
-}
-
-PORT1=`pick_port`; ssl_cluster_broker $PORT1
-PORT2=`pick_port`; ssl_cluster_broker $PORT2
-
-# Pipe receive output to uniq to remove duplicates
-./qpid-receive --connection-options "{reconnect:true, reconnect-timeout:5}" --failover-updates -b amqp:[$TEST_HOSTNAME]:$PORT1 -a "foo;{create:always}" -f | uniq > ssl_test_receive.tmp &
-
-./qpid-send -b amqp:[$TEST_HOSTNAME]:$PORT2 --content-string=one -a "foo;{create:always}"
-
-$QPIDD_EXEC -qp $PORT1 # Kill broker 1 receiver should fail-over.
-./qpid-send -b amqp:[$TEST_HOSTNAME]:$PORT2 --content-string=two -a "foo;{create:always}" --send-eos 1
-wait # Wait for qpid-receive
-{ echo one; echo two; } > ssl_test_receive.cmp
-diff ssl_test_receive.tmp ssl_test_receive.cmp || { echo "Failover failed"; exit 1; }
-
-$QPIDD_EXEC -qp $PORT2
-
-rm -f ssl_test_receive.*
-
diff --git a/cpp/src/tests/msg_group_test.cpp b/cpp/src/tests/msg_group_test.cpp
deleted file mode 100644
index 6b9d09b89a..0000000000
--- a/cpp/src/tests/msg_group_test.cpp
+++ /dev/null
@@ -1,618 +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 <qpid/messaging/Address.h>
-#include <qpid/messaging/Connection.h>
-#include <qpid/messaging/Receiver.h>
-#include <qpid/messaging/Sender.h>
-#include <qpid/messaging/Session.h>
-#include <qpid/messaging/Message.h>
-#include <qpid/messaging/FailoverUpdates.h>
-#include <qpid/Options.h>
-#include <qpid/log/Logger.h>
-#include <qpid/log/Options.h>
-#include "qpid/log/Statement.h"
-#include "qpid/sys/Time.h"
-#include "qpid/sys/Runnable.h"
-#include "qpid/sys/Thread.h"
-#include "qpid/sys/SystemInfo.h"
-
-#include <iostream>
-#include <memory>
-#include <stdlib.h>
-
-using namespace qpid::messaging;
-using namespace qpid::types;
-using namespace std;
-
-namespace qpid {
-namespace tests {
-
-struct Options : public qpid::Options
-{
- bool help;
- std::string url;
- std::string address;
- std::string connectionOptions;
- uint messages;
- uint capacity;
- uint ackFrequency;
- bool failoverUpdates;
- qpid::log::Options log;
- uint senders;
- uint receivers;
- uint groupSize;
- bool printReport;
- std::string groupKey;
- bool durable;
- bool allowDuplicates;
- bool randomizeSize;
- bool stickyConsumer;
- uint timeout;
- uint interleave;
- std::string prefix;
- uint sendRate;
-
- Options(const std::string& argv0=std::string())
- : qpid::Options("Options"),
- help(false),
- url("amqp:tcp:127.0.0.1"),
- messages(10000),
- capacity(1000),
- ackFrequency(100),
- failoverUpdates(false),
- log(argv0),
- senders(2),
- receivers(2),
- groupSize(10),
- printReport(false),
- groupKey("qpid.no_group"),
- durable(false),
- allowDuplicates(false),
- randomizeSize(false),
- stickyConsumer(false),
- timeout(10),
- interleave(1),
- sendRate(0)
- {
- addOptions()
- ("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)")
- ("address,a", qpid::optValue(address, "ADDRESS"), "address to send and receive from")
- ("allow-duplicates", qpid::optValue(allowDuplicates), "Ignore the delivery of duplicated messages")
- ("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
- ("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)")
- ("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
- ("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.")
- ("failover-updates", qpid::optValue(failoverUpdates), "Listen for membership updates distributed via amq.failover")
- ("group-key", qpid::optValue(groupKey, "KEY"), "Key of the message header containing the group identifier.")
- ("group-prefix", qpid::optValue(prefix, "STRING"), "Add 'prefix' to the start of all generated group identifiers.")
- ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group.")
- ("interleave", qpid::optValue(interleave, "N"), "Simultaineously interleave messages from N different groups.")
- ("messages,m", qpid::optValue(messages, "N"), "Number of messages to send per each sender.")
- ("receivers,r", qpid::optValue(receivers, "N"), "Number of message consumers.")
- ("randomize-group-size", qpid::optValue(randomizeSize), "Randomize the number of messages per group to [1...group-size].")
- ("send-rate", qpid::optValue(sendRate,"N"), "Send at rate of N messages/second. 0 means send as fast as possible.")
- ("senders,s", qpid::optValue(senders, "N"), "Number of message producers.")
- ("sticky-consumers", qpid::optValue(stickyConsumer), "If set, verify that all messages in a group are consumed by the same client [TBD].")
- ("timeout", qpid::optValue(timeout, "N"), "Fail with a stall error should all consumers remain idle for timeout seconds.")
- ("print-report", qpid::optValue(printReport), "Dump message group statistics to stdout.")
- ("help", qpid::optValue(help), "print this usage statement");
- add(log);
- //("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)")
- //("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)")
- //("rollback-frequency", qpid::optValue(rollbackFrequency, "N"), "rollback frequency (0 implies no transaction will be rolledback)")
- }
-
- bool parse(int argc, char** argv)
- {
- try {
- qpid::Options::parse(argc, argv);
- if (address.empty()) throw qpid::Exception("Address must be specified!");
- qpid::log::Logger::instance().configure(log);
- if (help) {
- std::ostringstream msg;
- std::cout << msg << *this << std::endl << std::endl
- << "Verifies the behavior of grouped messages." << std::endl;
- return false;
- } else {
- return true;
- }
- } catch (const std::exception& e) {
- std::cerr << *this << std::endl << std::endl << e.what() << std::endl;
- return false;
- }
- }
-};
-
-const string EOS("eos");
-const string SN("sn");
-
-
-// class that monitors group state across all publishers and consumers. tracks the next
-// expected sequence for each group, and total messages consumed.
-class GroupChecker
-{
- qpid::sys::Mutex lock;
-
- const uint totalMsgs;
- uint totalMsgsConsumed;
- uint totalMsgsPublished;
- bool allowDuplicates;
- uint duplicateMsgs;
-
- typedef std::map<std::string, uint> SequenceMap;
- SequenceMap sequenceMap;
-
- // Statistics - for each group, store the names of all clients that consumed messages
- // from that group, and the number of messages consumed per client.
- typedef std::map<std::string, uint> ClientCounter;
- typedef std::map<std::string, ClientCounter> GroupStatistics;
- GroupStatistics statistics;
-
-public:
-
- GroupChecker( uint t, bool d ) :
- totalMsgs(t), totalMsgsConsumed(0), totalMsgsPublished(0), allowDuplicates(d),
- duplicateMsgs(0) {}
-
- bool checkSequence( const std::string& groupId,
- uint sequence, const std::string& client )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
-
- QPID_LOG(debug, "Client " << client << " has received " << groupId << ":" << sequence);
-
- GroupStatistics::iterator gs = statistics.find(groupId);
- if (gs == statistics.end()) {
- statistics[groupId][client] = 1;
- } else {
- gs->second[client]++;
- }
- // now verify
- SequenceMap::iterator s = sequenceMap.find(groupId);
- if (s == sequenceMap.end()) {
- QPID_LOG(debug, "Client " << client << " thinks this is the first message from group " << groupId << ":" << sequence);
- // if duplication allowed, it is possible that the last msg(s) of an old sequence are redelivered on reconnect.
- // in this case, set the sequence from the first msg.
- sequenceMap[groupId] = (allowDuplicates) ? sequence : 0;
- s = sequenceMap.find(groupId);
- } else if (sequence < s->second) {
- duplicateMsgs++;
- QPID_LOG(debug, "Client " << client << " thinks this message is a duplicate! " << groupId << ":" << sequence);
- return allowDuplicates;
- }
- totalMsgsConsumed++;
- return sequence == s->second++;
- }
-
- void sendingSequence( const std::string& groupId,
- uint sequence, bool eos,
- const std::string& client )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- ++totalMsgsPublished;
-
- QPID_LOG(debug, "Client " << client << " sending " << groupId << ":" << sequence <<
- ((eos) ? " (last)" : ""));
- }
-
- bool eraseGroup( const std::string& groupId, const std::string& name )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- QPID_LOG(debug, "Deleting group " << groupId << " (by client " << name << ")");
- return sequenceMap.erase( groupId ) == 1;
- }
-
- uint getNextExpectedSequence( const std::string& groupId )
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return sequenceMap[groupId];
- }
-
- bool allMsgsConsumed() // true when done processing msgs
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return (totalMsgsPublished >= totalMsgs) &&
- (totalMsgsConsumed >= totalMsgsPublished) &&
- sequenceMap.size() == 0;
- }
-
- uint getConsumedTotal()
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return totalMsgsConsumed;
- }
-
- uint getPublishedTotal()
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- return totalMsgsPublished;
- }
-
- ostream& print(ostream& out)
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- out << "Total Published: " << totalMsgsPublished << ", Total Consumed: " << totalMsgsConsumed <<
- ", Duplicates detected: " << duplicateMsgs << std::endl;
- out << "Total Groups: " << statistics.size() << std::endl;
- unsigned long consumers = 0;
- for (GroupStatistics::iterator gs = statistics.begin(); gs != statistics.end(); ++gs) {
- out << " GroupId: " << gs->first;
- consumers += gs->second.size(); // # of consumers that processed this group
- if (gs->second.size() == 1)
- out << " completely consumed by a single client." << std::endl;
- else
- out << " consumed by " << gs->second.size() << " different clients." << std::endl;
-
- for (ClientCounter::iterator cc = gs->second.begin(); cc != gs->second.end(); ++cc) {
- out << " Client: " << cc->first << " consumed " << cc->second << " messages from the group." << std::endl;
- }
- }
- out << "Average # of consumers per group: " << ((statistics.size() != 0) ? (double(consumers)/statistics.size()) : 0) << std::endl;
- return out;
- }
-};
-
-
-namespace {
- // rand() is not thread safe. Create a singleton obj to hold a lock while calling
- // rand() so it can be called safely by multiple concurrent clients.
- class Randomizer {
- qpid::sys::Mutex lock;
- public:
- uint operator()(uint max) {
- qpid::sys::Mutex::ScopedLock l(lock);
- return (rand() % max) + 1;
- }
- };
-
- static Randomizer randomizer;
-}
-
-
-// tag each generated message with a group identifer
-//
-class GroupGenerator {
-
- const std::string groupPrefix;
- const uint groupSize;
- const bool randomizeSize;
- const uint interleave;
-
- uint groupSuffix;
- uint total;
-
- struct GroupState {
- std::string id;
- const uint size;
- uint count;
- GroupState( const std::string& i, const uint s )
- : id(i), size(s), count(0) {}
- };
- typedef std::list<GroupState> GroupList;
- GroupList groups;
- GroupList::iterator current;
-
- // add a new group identifier to the list
- void newGroup() {
- std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate);
- groupId << std::string(":") << groupSuffix++;
- uint size = (randomizeSize) ? randomizer(groupSize) : groupSize;
- QPID_LOG(trace, "New group: GROUPID=[" << groupId.str() << "] size=" << size << " this=" << this);
- GroupState group( groupId.str(), size );
- groups.push_back( group );
- }
-
-public:
- GroupGenerator( const std::string& prefix,
- const uint t,
- const uint size,
- const bool randomize,
- const uint i)
- : groupPrefix(prefix), groupSize(size),
- randomizeSize(randomize), interleave(i), groupSuffix(0), total(t)
- {
- QPID_LOG(trace, "New group generator: PREFIX=[" << prefix << "] total=" << total << " size=" << size << " rand=" << randomize << " interleave=" << interleave << " this=" << this);
- for (uint i = 0; i < 1 || i < interleave; ++i) {
- newGroup();
- }
- current = groups.begin();
- }
-
- bool genGroup(std::string& groupId, uint& seq, bool& eos)
- {
- if (!total) return false;
- --total;
- if (current == groups.end())
- current = groups.begin();
- groupId = current->id;
- seq = current->count++;
- if (current->count == current->size) {
- QPID_LOG(trace, "Last msg for " << current->id << ", " << current->count << " this=" << this);
- eos = true;
- if (total >= interleave) { // need a new group to replace this one
- newGroup();
- groups.erase(current++);
- } else ++current;
- } else {
- ++current;
- eos = total < interleave; // mark eos on the last message of each group
- }
- QPID_LOG(trace, "SENDING GROUPID=[" << groupId << "] seq=" << seq << " eos=" << eos << " this=" << this);
- return true;
- }
-};
-
-
-
-class Client : public qpid::sys::Runnable
-{
-public:
- typedef boost::shared_ptr<Client> shared_ptr;
- enum State {ACTIVE, DONE, FAILURE};
- Client( const std::string& n, const Options& o ) : name(n), opts(o), state(ACTIVE), stopped(false) {}
- virtual ~Client() {}
- State getState() { return state; }
- void testFailed( const std::string& reason ) { state = FAILURE; error << "Client '" << name << "' failed: " << reason; }
- void clientDone() { if (state == ACTIVE) state = DONE; }
- qpid::sys::Thread& getThread() { return thread; }
- const std::string getErrorMsg() { return error.str(); }
- void stop() {stopped = true;}
- const std::string& getName() { return name; }
-
-protected:
- const std::string name;
- const Options& opts;
- qpid::sys::Thread thread;
- ostringstream error;
- State state;
- bool stopped;
-};
-
-
-class Consumer : public Client
-{
- GroupChecker& checker;
-
-public:
- Consumer(const std::string& n, const Options& o, GroupChecker& c ) : Client(n, o), checker(c) {};
- virtual ~Consumer() {};
-
- void run()
- {
- Connection connection;
- try {
- connection = Connection(opts.url, opts.connectionOptions);
- connection.open();
- std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0);
- Session session = connection.createSession();
- Receiver receiver = session.createReceiver(opts.address);
- receiver.setCapacity(opts.capacity);
- Message msg;
- uint count = 0;
-
- while (!stopped) {
- if (receiver.fetch(msg, Duration::SECOND)) { // msg retrieved
- qpid::types::Variant::Map& properties = msg.getProperties();
- std::string groupId = properties[opts.groupKey];
- uint groupSeq = properties[SN];
- bool eof = properties[EOS];
-
- QPID_LOG(trace, "RECVING GROUPID=[" << groupId << "] seq=" << groupSeq << " eos=" << eof << " name=" << name);
-
- qpid::sys::usleep(10);
-
- if (!checker.checkSequence( groupId, groupSeq, name )) {
- ostringstream msg;
- msg << "Check sequence failed. Group=" << groupId << " rcvd seq=" << groupSeq << " expected=" << checker.getNextExpectedSequence( groupId );
- testFailed( msg.str() );
- break;
- } else if (eof) {
- if (!checker.eraseGroup( groupId, name )) {
- ostringstream msg;
- msg << "Erase group failed. Group=" << groupId << " rcvd seq=" << groupSeq;
- testFailed( msg.str() );
- break;
- }
- }
-
- ++count;
- if (opts.ackFrequency && (count % opts.ackFrequency == 0)) {
- session.acknowledge();
- }
- // Clear out message properties & content for next iteration.
- msg = Message(); // TODO aconway 2010-12-01: should be done by fetch
- } else if (checker.allMsgsConsumed()) // timed out, nothing else to do?
- break;
- }
- session.acknowledge();
- session.close();
- connection.close();
- } catch(const std::exception& error) {
- ostringstream msg;
- msg << "consumer error: " << error.what();
- testFailed( msg.str() );
- connection.close();
- }
- clientDone();
- QPID_LOG(trace, "Consuming client " << name << " completed.");
- }
-};
-
-
-
-class Producer : public Client
-{
- GroupChecker& checker;
- GroupGenerator generator;
-
-public:
- Producer(const std::string& n, const Options& o, GroupChecker& c)
- : Client(n, o), checker(c),
- generator( n, o.messages, o.groupSize, o.randomizeSize, o.interleave )
- {};
- virtual ~Producer() {};
-
- void run()
- {
- Connection connection;
- try {
- connection = Connection(opts.url, opts.connectionOptions);
- connection.open();
- std::auto_ptr<FailoverUpdates> updates(opts.failoverUpdates ? new FailoverUpdates(connection) : 0);
- Session session = connection.createSession();
- Sender sender = session.createSender(opts.address);
- if (opts.capacity) sender.setCapacity(opts.capacity);
- Message msg;
- msg.setDurable(opts.durable);
- std::string groupId;
- uint seq;
- bool eos;
- uint sent = 0;
-
- qpid::sys::AbsTime start = qpid::sys::now();
- int64_t interval = 0;
- if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate;
-
- while (!stopped && generator.genGroup(groupId, seq, eos)) {
- msg.getProperties()[opts.groupKey] = groupId;
- msg.getProperties()[SN] = seq;
- msg.getProperties()[EOS] = eos;
- checker.sendingSequence( groupId, seq, eos, name );
-
- sender.send(msg);
- ++sent;
-
- if (opts.sendRate) {
- qpid::sys::AbsTime waitTill(start, sent*interval);
- int64_t delay = qpid::sys::Duration(qpid::sys::now(), waitTill);
- if (delay > 0) qpid::sys::usleep(delay/qpid::sys::TIME_USEC);
- }
- }
- session.sync();
- session.close();
- connection.close();
- } catch(const std::exception& error) {
- ostringstream msg;
- msg << "producer '" << name << "' error: " << error.what();
- testFailed(msg.str());
- connection.close();
- }
- clientDone();
- QPID_LOG(trace, "Producing client " << name << " completed.");
- }
-};
-
-
-}} // namespace qpid::tests
-
-using namespace qpid::tests;
-
-int main(int argc, char ** argv)
-{
- int status = 0;
- try {
- Options opts;
- if (opts.parse(argc, argv)) {
-
- GroupChecker state( opts.senders * opts.messages,
- opts.allowDuplicates);
- std::vector<Client::shared_ptr> clients;
-
- if (opts.randomizeSize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId());
-
- // fire off the producers && consumers
- for (size_t j = 0; j < opts.senders; ++j) {
- ostringstream name;
- name << opts.prefix << "P_" << j;
- clients.push_back(Client::shared_ptr(new Producer( name.str(), opts, state )));
- clients.back()->getThread() = qpid::sys::Thread(*clients.back());
- }
- for (size_t j = 0; j < opts.receivers; ++j) {
- ostringstream name;
- name << opts.prefix << "C_" << j;
- clients.push_back(Client::shared_ptr(new Consumer( name.str(), opts, state )));
- clients.back()->getThread() = qpid::sys::Thread(*clients.back());
- }
-
- // wait for all pubs/subs to finish.... or for consumers to fail or stall.
- uint stalledTime = 0;
- bool done;
- bool clientFailed = false;
- do {
- uint lastCount = state.getConsumedTotal();
- qpid::sys::usleep( 1000000 );
-
- // check each client for status
- done = true;
- for (std::vector<Client::shared_ptr>::iterator i = clients.begin();
- i != clients.end(); ++i) {
- QPID_LOG(debug, "Client " << (*i)->getName() << " state=" << (*i)->getState());
- if ((*i)->getState() == Client::FAILURE) {
- QPID_LOG(error, argv[0] << ": test failed with client error: " << (*i)->getErrorMsg());
- clientFailed = true;
- done = true;
- break; // exit test.
- } else if ((*i)->getState() != Client::DONE) {
- done = false;
- }
- }
-
- if (!done) {
- // check that consumers are still receiving messages
- if (lastCount == state.getConsumedTotal())
- stalledTime++;
- else {
- lastCount = state.getConsumedTotal();
- stalledTime = 0;
- }
- }
-
- QPID_LOG(debug, "Consumed to date = " << state.getConsumedTotal() <<
- " Published to date = " << state.getPublishedTotal() <<
- " total=" << opts.senders * opts.messages );
-
- } while (!done && stalledTime < opts.timeout);
-
- if (clientFailed) {
- status = 1;
- } else if (stalledTime >= opts.timeout) {
- QPID_LOG(error, argv[0] << ": test failed due to stalled consumer." );
- status = 2;
- }
-
- // Wait for started threads.
- for (std::vector<Client::shared_ptr>::iterator i = clients.begin();
- i != clients.end(); ++i) {
- (*i)->stop();
- (*i)->getThread().join();
- }
-
- if (opts.printReport && !status) state.print(std::cout);
- } else status = 4;
- } catch(const std::exception& error) {
- QPID_LOG(error, argv[0] << ": " << error.what());
- status = 3;
- }
- QPID_LOG(trace, "TEST DONE [" << status << "]");
-
- return status;
-}
diff --git a/cpp/src/tests/python_tests b/cpp/src/tests/python_tests
index 0216b5ca7b..e367004a71 100755
--- a/cpp/src/tests/python_tests
+++ b/cpp/src/tests/python_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/qpid-cluster-benchmark b/cpp/src/tests/qpid-cluster-benchmark
index ff787a46dd..4408e63866 100755
--- a/cpp/src/tests/qpid-cluster-benchmark
+++ b/cpp/src/tests/qpid-cluster-benchmark
@@ -7,9 +7,9 @@
# 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
@@ -19,40 +19,21 @@
#
# Benchmark script for comparing cluster performance.
+#PORT=":5555"
+BROKER=`echo $HOSTS | awk '{print $1}'` # Single broker
+BROKERS=`echo $HOSTS | sed "s/\>/$PORT/g;s/ /,/g"` # Broker URL list
+COUNT=100000
+RATE=20000 # Rate to throttle senders for latency results
+run_test() { echo $*; "$@"; echo; echo; echo; }
-# Default values
-PORT="5672"
-COUNT=10000
-FLOW=100 # Flow control limit on queue depth for latency.
-REPEAT=10
-QUEUES=4
-CLIENTS=3
-
-while getopts "p:c:f:r:t:b:q:c" opt; do
- case $opt in
- p) PORT=$OPTARG;;
- c) COUNT=$OPTARG;;
- f) FLOW=$OPTARG;;
- r) REPEAT=$OPTARG;;
- s) SCALE=$OPTARG;;
- b) BROKERS=$OPTARG;;
- q) QUEUES=$OPTARG;;
- c) CLIENTS=$OPTARG;;
- *) echo "Unknown option"; exit 1;;
- esac
-done
-
-BROKERS=${BROKERS:-$(echo $HOSTS | sed "s/\>/:$PORT/g;s/ /,/g")} # Broker URL list
-BROKER=`echo $BROKERS | awk -F, '{print $1}'` # First broker
+# Thruput, unshared queue
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --no-timestamp -m $COUNT
-run_test() { echo $*; shift; "$@"; echo; echo; echo; }
+# Latency
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --connection-options '{tcp-nodelay:true}' -m `expr $COUNT / 2` --send-rate $RATE
# Multiple pubs/subs connect via multiple brokers (active-active)
-run_test "multi-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKERS --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKERS --no-timestamp --summarize -s10 -r10 -m `expr $COUNT / 10`
# Multiple pubs/subs connect via single broker (active-passive)
-run_test "single-host-thruput" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --no-timestamp --summarize -q$QUEUES -s$CLIENTS -r$CLIENTS -m $COUNT
-
-# Latency
-run_test "latency" qpid-cpp-benchmark --repeat $REPEAT -b $BROKER --connection-options '{tcp-nodelay:true}' -m $COUNT --flow-control $FLOW
-
+run_test qpid-cpp-benchmark --repeat 10 -b $BROKER --no-timestamp --summarize -s10 -r10 -m `expr $COUNT / 10`
diff --git a/cpp/src/tests/qpid-cpp-benchmark b/cpp/src/tests/qpid-cpp-benchmark
index 300d34774f..1f77226b4d 100755
--- a/cpp/src/tests/qpid-cpp-benchmark
+++ b/cpp/src/tests/qpid-cpp-benchmark
@@ -77,20 +77,6 @@ def ssh_command(host, command):
"""Convert command into an ssh command on host with quoting"""
return ["ssh", host] + [posix_quote(arg) for arg in command]
-class Clients:
- def __init__(self): self.clients=[]
-
- def add(self, client):
- self.clients.append(client)
- return client
-
- def kill(self):
- for c in self.clients:
- try: c.kill()
- except: pass
-
-clients = Clients()
-
def start_receive(queue, index, opts, ready_queue, broker, host):
address_opts=["create:receiver"] + opts.receive_option
if opts.durable: address_opts += ["node:{durable:true}"]
@@ -115,7 +101,7 @@ def start_receive(queue, index, opts, ready_queue, broker, host):
if opts.connection_options:
command += ["--connection-options",opts.connection_options]
if host: command = ssh_command(host, command)
- return clients.add(Popen(command, stdout=PIPE))
+ return Popen(command, stdout=PIPE)
def start_send(queue, opts, broker, host):
address="%s;{%s}"%(queue,",".join(opts.send_option))
@@ -136,7 +122,7 @@ def start_send(queue, opts, broker, host):
if opts.connection_options:
command += ["--connection-options",opts.connection_options]
if host: command = ssh_command(host, command)
- return clients.add(Popen(command, stdout=PIPE))
+ return Popen(command, stdout=PIPE)
def first_line(p):
out,err=p.communicate()
@@ -147,11 +133,7 @@ def delete_queues(queues, broker):
c = qpid.messaging.Connection(broker)
c.open()
for q in queues:
- try:
- s = c.session()
- snd = s.sender("%s;{delete:always}"%(q))
- snd.close()
- s.sync()
+ try: s = c.session().sender("%s;{delete:always}"%(q))
except qpid.messaging.exceptions.NotFound: pass # Ignore "no such queue"
c.close()
@@ -163,6 +145,7 @@ def print_header(timestamp):
def parse(parser, lines): # Parse sender/receiver output
for l in lines:
fn_val = zip(parser, l)
+
return [map(lambda p: p[0](p[1]), zip(parser,line.split())) for line in lines]
def parse_senders(senders):
@@ -173,12 +156,11 @@ def parse_receivers(receivers):
def print_data(send_stats, recv_stats):
for send,recv in map(None, send_stats, recv_stats):
- line=""
- if send: line += "%d"%send[0]
+ if send: print send[0],
if recv:
- line += "\t\t%d"%recv[0]
- if len(recv) == 4: line += "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:])
- print line
+ print "\t\t%d"%recv[0],
+ if len(recv) == 4: print "\t%.2f\t%.2f\t%.2f"%tuple(recv[1:]),
+ print
def print_summary(send_stats, recv_stats):
def avg(s): sum(s) / len(s)
@@ -202,11 +184,11 @@ class ReadyReceiver:
self.receiver = self.connection.session().receiver(
"%s;{create:receiver,delete:receiver,node:{durable:false}}"%(queue))
self.receiver.session.sync()
- self.timeout=10
+ self.timeout=2
def wait(self, receivers):
try:
- for i in receivers: self.receiver.fetch(self.timeout)
+ for i in xrange(len(receivers)): self.receiver.fetch(self.timeout)
self.connection.close()
except qpid.messaging.Empty:
for r in receivers:
@@ -215,8 +197,7 @@ class ReadyReceiver:
raise Exception("Receiver error: %s"%(out))
raise Exception("Timed out waiting for receivers to be ready")
-def flatten(l):
- return sum(map(lambda s: re.split(re.compile("\s*,\s*|\s+"), s), l), [])
+def flatten(l): return sum(map(lambda s: s.split(","), l),[])
class RoundRobin:
def __init__(self,items):
@@ -240,22 +221,20 @@ def main():
receive_out = ""
ready_queue="%s-ready"%(opts.queue_name)
queues = ["%s-%s"%(opts.queue_name, i) for i in xrange(opts.queues)]
- try:
- for i in xrange(opts.repeat):
- delete_queues(queues, opts.broker[0])
- ready_receiver = ReadyReceiver(ready_queue, opts.broker[0])
- receivers = [start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next())
- for q in queues for j in xrange(opts.receivers)]
- ready_receiver.wait(filter(None, receivers)) # Wait for receivers to be ready.
- senders = [start_send(q, opts,brokers.next(), client_hosts.next())
- for q in queues for j in xrange(opts.senders)]
- if opts.report_header and i == 0: print_header(opts.timestamp)
- send_stats=parse_senders(senders)
- recv_stats=parse_receivers(receivers)
- if opts.summarize: print_summary(send_stats, recv_stats)
- else: print_data(send_stats, recv_stats)
- delete_queues(queues, opts.broker[0])
- finally: clients.kill() # No strays
+ for i in xrange(opts.repeat):
+ delete_queues(queues, opts.broker[0])
+ ready_receiver = ReadyReceiver(ready_queue, opts.broker[0])
+ receivers = [start_receive(q, j, opts, ready_queue, brokers.next(), client_hosts.next())
+ for q in queues for j in xrange(opts.receivers)]
+ ready_receiver.wait(filter(None, receivers)) # Wait for receivers to be ready.
+ senders = [start_send(q, opts,brokers.next(), client_hosts.next())
+ for q in queues for j in xrange(opts.senders)]
+ if opts.report_header and i == 0: print_header(opts.timestamp)
+ send_stats=parse_senders(senders)
+ recv_stats=parse_receivers(receivers)
+ if opts.summarize: print_summary(send_stats, recv_stats)
+ else: print_data(send_stats, recv_stats)
+ delete_queues(queues, opts.broker[0])
if __name__ == "__main__": main()
diff --git a/cpp/src/tests/qpid-ctrl b/cpp/src/tests/qpid-ctrl
index 4246c57898..7b46c190fb 100755
--- a/cpp/src/tests/qpid-ctrl
+++ b/cpp/src/tests/qpid-ctrl
@@ -92,10 +92,7 @@ try:
arguments = {}
for a in args:
name, val = nameval(a)
- if val[0] == '{' or val[0] == '[':
- arguments[name] = eval(val)
- else:
- arguments[name] = val
+ arguments[name] = val
content = {
"_object_id": {"_object_name": object_name},
"_method_name": method_name,
diff --git a/cpp/src/tests/qpid-perftest.cpp b/cpp/src/tests/qpid-perftest.cpp
index dd81354adb..4d7b563c8c 100644
--- a/cpp/src/tests/qpid-perftest.cpp
+++ b/cpp/src/tests/qpid-perftest.cpp
@@ -396,7 +396,7 @@ struct Controller : public Client {
void run() { // Controller
try {
// Wait for subscribers to be ready.
- process(opts.totalSubs, fqn("sub_ready"), boost::bind(expect, _1, "ready"));
+ process(opts.totalSubs, fqn("sub_ready"), bind(expect, _1, "ready"));
LocalQueue pubDone;
LocalQueue subDone;
@@ -423,10 +423,8 @@ struct Controller : public Client {
process(opts.totalSubs, subDone, fqn("sub_done"), boost::ref(subRates));
AbsTime end=now();
+
double time=secs(start, end);
- if (time <= 0.0) {
- throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count.");
- }
double txrate=opts.transfers/time;
double mbytes=(txrate*opts.size)/(1024*1024);
@@ -510,11 +508,10 @@ struct PublishThread : public Client {
}
SubscriptionManager subs(session);
LocalQueue lq;
- subs.setFlowControl(0, SubscriptionManager::UNLIMITED, false);
- Subscription cs = subs.subscribe(lq, fqn("pub_start"));
+ subs.setFlowControl(1, SubscriptionManager::UNLIMITED, true);
+ subs.subscribe(lq, fqn("pub_start"));
for (size_t j = 0; j < opts.iterations; ++j) {
- cs.grantMessageCredit(1);
expect(lq.pop().getData(), "start");
AbsTime start=now();
for (size_t i=0; i<opts.count; i++) {
@@ -546,9 +543,6 @@ struct PublishThread : public Client {
if (opts.confirm) session.sync();
AbsTime end=now();
double time=secs(start,end);
- if (time <= 0.0) {
- throw Exception("ERROR: Test completed in zero seconds. Try again with a larger message count.");
- }
// Send result to controller.
Message report(lexical_cast<string>(opts.count/time), fqn("pub_done"));
@@ -644,9 +638,7 @@ struct SubscribeThread : public Client {
//
// For now verify order only for a single publisher.
size_t offset = opts.uniqueData ? 5 /*marker is 'data:'*/ : 0;
- size_t n;
- memcpy (&n, reinterpret_cast<const char*>(msg.getData().data() + offset),
- sizeof(n));
+ size_t n = *reinterpret_cast<const size_t*>(msg.getData().data() + offset);
if (opts.pubs == 1) {
if (opts.subs == 1 || opts.mode == FANOUT) verify(n==expect, "==", expect, n);
else verify(n>=expect, ">=", expect, n);
diff --git a/cpp/src/tests/qpid-receive.cpp b/cpp/src/tests/qpid-receive.cpp
index 9c713e872a..012d544a2e 100644
--- a/cpp/src/tests/qpid-receive.cpp
+++ b/cpp/src/tests/qpid-receive.cpp
@@ -53,7 +53,6 @@ struct Options : public qpid::Options
bool forever;
uint messages;
bool ignoreDuplicates;
- bool checkRedelivered;
uint capacity;
uint ackFrequency;
uint tx;
@@ -76,7 +75,6 @@ struct Options : public qpid::Options
forever(false),
messages(0),
ignoreDuplicates(false),
- checkRedelivered(false),
capacity(1000),
ackFrequency(100),
tx(0),
@@ -94,11 +92,10 @@ struct Options : public qpid::Options
("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
("address,a", qpid::optValue(address, "ADDRESS"), "address to receive from")
("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
- ("timeout", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting")
+ ("timeout,t", qpid::optValue(timeout, "TIMEOUT"), "timeout in seconds to wait before exiting")
("forever,f", qpid::optValue(forever), "ignore timeout and wait forever")
("messages,m", qpid::optValue(messages, "N"), "Number of messages to receive; 0 means receive indefinitely")
("ignore-duplicates", qpid::optValue(ignoreDuplicates), "Detect and ignore duplicates (by checking 'sn' header)")
- ("check-redelivered", qpid::optValue(checkRedelivered), "Fails with exception if a duplicate is not marked as redelivered (only relevant when ignore-duplicates is selected)")
("capacity", qpid::optValue(capacity, "N"), "Pre-fetch window (0 implies no pre-fetch)")
("ack-frequency", qpid::optValue(ackFrequency, "N"), "Ack frequency (0 implies none of the messages will get accepted)")
("tx", qpid::optValue(tx, "N"), "batch size for transactions (0 implies transaction are not used)")
@@ -219,8 +216,6 @@ int main(int argc, char ** argv)
std::cout << msg.getContent() << std::endl;//TODO: handle map or list messages
if (opts.messages && count >= opts.messages) done = true;
}
- } else if (opts.checkRedelivered && !msg.getRedelivered()) {
- throw qpid::Exception("duplicate sequence number received, message not marked as redelivered!");
}
if (opts.tx && (count % opts.tx == 0)) {
if (opts.rollbackFrequency && (++txCount % opts.rollbackFrequency == 0)) {
@@ -262,7 +257,7 @@ int main(int argc, char ** argv)
return 0;
}
} catch(const std::exception& error) {
- std::cerr << "qpid-receive: " << error.what() << std::endl;
+ std::cerr << "Failure: " << error.what() << std::endl;
connection.close();
return 1;
}
diff --git a/cpp/src/tests/qpid-send.cpp b/cpp/src/tests/qpid-send.cpp
index b1213a484f..6a7e7838ce 100644
--- a/cpp/src/tests/qpid-send.cpp
+++ b/cpp/src/tests/qpid-send.cpp
@@ -28,7 +28,6 @@
#include <qpid/messaging/FailoverUpdates.h>
#include <qpid/sys/Time.h>
#include <qpid/sys/Monitor.h>
-#include <qpid/sys/SystemInfo.h>
#include "TestOptions.h"
#include "Statistics.h"
@@ -77,11 +76,6 @@ struct Options : public qpid::Options
uint flowControl;
bool sequence;
bool timestamp;
- std::string groupKey;
- std::string groupPrefix;
- uint groupSize;
- bool groupRandSize;
- uint groupInterleave;
Options(const std::string& argv0=std::string())
: qpid::Options("Options"),
@@ -106,23 +100,19 @@ struct Options : public qpid::Options
sendRate(0),
flowControl(0),
sequence(true),
- timestamp(true),
- groupPrefix("GROUP-"),
- groupSize(10),
- groupRandSize(false),
- groupInterleave(1)
+ timestamp(true)
{
addOptions()
("broker,b", qpid::optValue(url, "URL"), "url of broker to connect to")
- ("address,a", qpid::optValue(address, "ADDRESS"), "address to send to")
+ ("address,a", qpid::optValue(address, "ADDRESS"), "address to drain from")
("connection-options", qpid::optValue(connectionOptions, "OPTIONS"), "options for the connection")
("messages,m", qpid::optValue(messages, "N"), "stop after N messages have been sent, 0 means no limit")
("id,i", qpid::optValue(id, "ID"), "use the supplied id instead of generating one")
("reply-to", qpid::optValue(replyto, "REPLY-TO"), "specify reply-to address")
("send-eos", qpid::optValue(sendEos, "N"), "Send N EOS messages to mark end of input")
("durable", qpid::optValue(durable, "yes|no"), "Mark messages as durable.")
- ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds")
- ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)")
+ ("ttl", qpid::optValue(ttl, "msecs"), "Time-to-live for messages, in milliseconds")
+ ("priority", qpid::optValue(priority, "PRIORITY"), "Priority for messages (higher value implies higher priority)")
("property,P", qpid::optValue(properties, "NAME=VALUE"), "specify message property")
("correlation-id", qpid::optValue(correlationid, "ID"), "correlation-id for message")
("user-id", qpid::optValue(userid, "USERID"), "userid for message")
@@ -141,11 +131,6 @@ struct Options : public qpid::Options
("flow-control", qpid::optValue(flowControl,"N"), "Do end to end flow control to limit queue depth to 2*N. 0 means no flow control.")
("sequence", qpid::optValue(sequence, "yes|no"), "Add a sequence number messages property (required for duplicate/lost message detection)")
("timestamp", qpid::optValue(timestamp, "yes|no"), "Add a time stamp messages property (required for latency measurement)")
- ("group-key", qpid::optValue(groupKey, "KEY"), "Generate groups of messages using message header 'KEY' to hold the group identifier")
- ("group-prefix", qpid::optValue(groupPrefix, "STRING"), "Generate group identifers with 'STRING' prefix (if group-key specified)")
- ("group-size", qpid::optValue(groupSize, "N"), "Number of messages per a group (if group-key specified)")
- ("group-randomize-size", qpid::optValue(groupRandSize), "Randomize the number of messages per group to [1...group-size] (if group-key specified)")
- ("group-interleave", qpid::optValue(groupInterleave, "N"), "Simultaineously interleave messages from N different groups (if group-key specified)")
("help", qpid::optValue(help), "print this usage statement");
add(log);
}
@@ -267,68 +252,6 @@ class MapContentGenerator : public ContentGenerator {
const Options& opts;
};
-// tag each generated message with a group identifer
-//
-class GroupGenerator {
-public:
- GroupGenerator(const std::string& key,
- const std::string& prefix,
- const uint size,
- const bool randomize,
- const uint interleave)
- : groupKey(key), groupPrefix(prefix), groupSize(size),
- randomizeSize(randomize), groupSuffix(0)
- {
- if (randomize) srand((unsigned int)qpid::sys::SystemInfo::getProcessId());
-
- for (uint i = 0; i < 1 || i < interleave; ++i) {
- newGroup();
- }
- current = groups.begin();
- }
-
- void setGroupInfo(Message &msg)
- {
- if (current == groups.end())
- current = groups.begin();
- msg.getProperties()[groupKey] = current->id;
- // std::cout << "SENDING GROUPID=[" << current->id << "]" << std::endl;
- if (++(current->count) == current->size) {
- newGroup();
- groups.erase(current++);
- } else
- ++current;
- }
-
- private:
- const std::string& groupKey;
- const std::string& groupPrefix;
- const uint groupSize;
- const bool randomizeSize;
-
- uint groupSuffix;
-
- struct GroupState {
- std::string id;
- const uint size;
- uint count;
- GroupState( const std::string& i, const uint s )
- : id(i), size(s), count(0) {}
- };
- typedef std::list<GroupState> GroupList;
- GroupList groups;
- GroupList::iterator current;
-
- void newGroup() {
- std::ostringstream groupId(groupPrefix, ios_base::out|ios_base::ate);
- groupId << groupSuffix++;
- uint size = (randomizeSize) ? (rand() % groupSize) + 1 : groupSize;
- // std::cout << "New group: GROUPID=[" << groupId.str() << "] size=" << size << std::endl;
- GroupState group( groupId.str(), size );
- groups.push_back( group );
- }
-};
-
int main(int argc, char ** argv)
{
Connection connection;
@@ -373,14 +296,6 @@ int main(int argc, char ** argv)
else
contentGen.reset(new FixedContentGenerator(opts.contentString));
- std::auto_ptr<GroupGenerator> groupGen;
- if (!opts.groupKey.empty())
- groupGen.reset(new GroupGenerator(opts.groupKey,
- opts.groupPrefix,
- opts.groupSize,
- opts.groupRandSize,
- opts.groupInterleave));
-
qpid::sys::AbsTime start = qpid::sys::now();
int64_t interval = 0;
if (opts.sendRate) interval = qpid::sys::TIME_SEC/opts.sendRate;
@@ -397,6 +312,9 @@ int main(int argc, char ** argv)
++sent;
if (opts.sequence)
msg.getProperties()[SN] = sent;
+ if (opts.timestamp)
+ msg.getProperties()[TS] = int64_t(
+ qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()));
if (opts.flowControl) {
if ((sent % opts.flowControl) == 0) {
msg.setReplyTo(flowControlAddress);
@@ -405,12 +323,6 @@ int main(int argc, char ** argv)
else
msg.setReplyTo(Address()); // Clear the reply address.
}
- if (groupGen.get())
- groupGen->setGroupInfo(msg);
-
- if (opts.timestamp)
- msg.getProperties()[TS] = int64_t(
- qpid::sys::Duration(qpid::sys::EPOCH, qpid::sys::now()));
sender.send(msg);
reporter.message(msg);
@@ -456,7 +368,7 @@ int main(int argc, char ** argv)
return 0;
}
} catch(const std::exception& error) {
- std::cerr << "qpid-send: " << error.what() << std::endl;
+ std::cout << "Failed: " << error.what() << std::endl;
connection.close();
return 1;
}
diff --git a/cpp/src/tests/qrsh.cpp b/cpp/src/tests/qrsh.cpp
new file mode 100644
index 0000000000..0cb52b6b05
--- /dev/null
+++ b/cpp/src/tests/qrsh.cpp
@@ -0,0 +1,169 @@
+/*
+ *
+ * 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 <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+#include <stdio.h>
+#include <cstdlib>
+#include <iostream>
+
+#include <sstream>
+
+using namespace qpid::client;
+using namespace qpid::framing;
+
+using namespace std;
+
+namespace qpid {
+namespace tests {
+
+class ResponseListener : public MessageListener
+{
+ public :
+
+ int exitCode;
+
+ ResponseListener ( SubscriptionManager & subscriptions )
+ : exitCode(-1),
+ subscriptions ( subscriptions )
+ {
+ }
+
+ virtual void
+ received ( Message & message )
+ {
+ char first_word[1000];
+ sscanf ( message.getData().c_str(), "%s", first_word );
+
+ if ( ! strcmp ( first_word, "wait_response" ) )
+ {
+ // If we receive a message here, parse out the exit code.
+ sscanf ( message.getData().c_str(), "%*s%d", & exitCode );
+ subscriptions.cancel(message.getDestination());
+ }
+ else
+ if ( ! strcmp ( first_word, "get_response" ) )
+ {
+ // The remainder of the message is the file we requested.
+ fprintf ( stdout,
+ "%s",
+ message.getData().c_str() + strlen("get_response" )
+ );
+ subscriptions.cancel(message.getDestination());
+ }
+ }
+
+
+ private :
+
+ SubscriptionManager & subscriptions;
+};
+
+}} // namespace qpid::tests
+
+using namespace qpid::tests;
+
+/*
+ * argv[1] host
+ * argv[2] port
+ * argv[3] server name
+ * argv[4] command name
+ * argv[5..N] args to the command
+ */
+int
+main ( int argc, char ** argv )
+{
+ const char* host = argv[1];
+ int port = atoi(argv[2]);
+
+
+ Connection connection;
+
+ try
+ {
+ connection.open ( host, port );
+ Session session = connection.newSession ( );
+
+ // Make a queue and bind it to fanout.
+ string myQueue = session.getId().getName();
+
+ session.queueDeclare ( arg::queue=myQueue,
+ arg::exclusive=true,
+ arg::autoDelete=true
+ );
+
+ session.exchangeBind ( arg::exchange="amq.fanout",
+ arg::queue=myQueue,
+ arg::bindingKey="my-key"
+ );
+
+ // Get ready to listen for the wait-response.
+ // or maybe a get-response.
+ // ( Although this may not be one of those types
+ // of command, get ready anyway.
+ SubscriptionManager subscriptions ( session );
+ ResponseListener responseListener ( subscriptions );
+ subscriptions.subscribe ( responseListener, myQueue );
+
+ bool response_command = false;
+ if(! strcmp("exec_wait", argv[4] ))
+ response_command = true;
+ else
+ if(! strcmp("exited", argv[4] ))
+ response_command = true;
+ else
+ if(! strcmp("get", argv[4] ))
+ response_command = true;
+
+ // Send the payload message.
+ // Skip "qrsh host_name port"
+ Message message;
+ stringstream ss;
+ for ( int i = 3; i < argc; ++ i )
+ ss << argv[i] << ' ';
+
+ message.setData ( ss.str() );
+
+ session.messageTransfer(arg::content=message,
+ arg::destination="amq.fanout");
+
+ if ( response_command )
+ subscriptions.run();
+
+ session.close();
+ connection.close();
+ return responseListener.exitCode;
+ }
+ catch ( exception const & e)
+ {
+ cerr << e.what() << endl;
+ }
+
+ return 1;
+}
+
+
+
diff --git a/cpp/src/tests/qrsh_run.cpp b/cpp/src/tests/qrsh_run.cpp
new file mode 100644
index 0000000000..cfdd0cef80
--- /dev/null
+++ b/cpp/src/tests/qrsh_run.cpp
@@ -0,0 +1,321 @@
+/*
+ *
+ * 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 <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+using namespace std;
+
+
+
+int
+main ( int argc, char ** argv )
+{
+ int exit_code = -1;
+ int fd[2];
+ int my_pid = getpid();
+ int child_pid;
+
+ pipe(fd);
+
+ char const * root_dir = argv[1]; // This arg is prepended by qrsh_server.
+ char const * child_name = argv[2]; // This arg comes from qrsh.
+ char const * child_path = argv[3]; // This arg comes from qrsh.
+
+ // This is the problem..
+ fprintf ( stderr, "MDEBUG qrsh_run: root_dir: |%s|\n", root_dir );
+ fprintf ( stderr, "MDEBUG qrsh_run: child_name: |%s|\n", child_name );
+ fprintf ( stderr, "MDEBUG qrsh_run: child_path: |%s|\n", child_path );
+
+ /*
+ * A named child is one for whom we will create a directory and
+ * store information. There are some magic names that are not
+ * real symbolic names -- but are instead the names of actions.
+ */
+
+ bool named_child = true;
+
+ if ( ! strcmp ( child_name, "exec" ) )
+ named_child = false;
+ else
+ if ( ! strcmp ( child_name, "exec_wait" ) )
+ named_child = false;
+ else
+ if ( ! strcmp ( child_name, "exited" ) )
+ named_child = false;
+ else
+ named_child = true;
+
+ stringstream child_dir_name;
+
+ if ( named_child )
+ {
+ child_dir_name << root_dir
+ << '/'
+ << child_name;
+
+ /*
+ * Make the child directory before forking, or there is
+ * a race in which the child might be trying to make its
+ * stdout and stderr files while we are tring to make
+ * the directory.
+ */
+ if ( -1 == mkdir ( child_dir_name.str().c_str(), 0777 ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run error: Can't mkdir |%s|\n",
+ child_dir_name.str().c_str()
+ );
+ exit ( 1 );
+ }
+
+ }
+ else
+ /*
+ * If this is an 'exited' command that means we are
+ * waiting for a pre-existing child.
+ */
+ if ( ! strcmp ( child_name, "exited" ) )
+ {
+ int wait_pid = atoi(child_path);
+
+ // Find the child's symbolic name.
+ stringstream pid_to_name_file_name;
+ pid_to_name_file_name << root_dir
+ << '/'
+ << wait_pid;
+ FILE * fp = fopen ( pid_to_name_file_name.str().c_str(), "r" );
+ if (! fp)
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open pid2name file |%s|.\n",
+ my_pid,
+ pid_to_name_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ char symbolic_name[1000];
+ strcpy ( symbolic_name, "qrsh_no_name" );
+ fscanf ( fp, "%s", symbolic_name );
+ fclose ( fp );
+
+ // Make the name of the child's exit code file.
+ stringstream exit_code_file_name;
+ exit_code_file_name << root_dir
+ << '/'
+ << symbolic_name
+ << "/exit_code";
+
+ struct stat stat_buf;
+ int file_does_not_exist = stat ( exit_code_file_name.str().c_str(), & stat_buf );
+
+ /*
+ * If the result of stat is zero, the file exists, which means that
+ * the command has exited. The question we are being asked here is
+ * "has it exited yet?"
+ */
+ if ( ! file_does_not_exist )
+ return 1;
+ else
+ if ( errno == ENOENT )
+ return 0;
+ else
+ return 2 ;
+ }
+
+
+ // We are not waiting on a pre-wxiting child: we have a
+ // new child to create.
+
+ child_pid = fork();
+
+ if ( child_pid == 0 )
+ {
+ // This code is executed in the child process.
+
+ // If it's a *named* child, then redirect its stdout and stderr.
+ if ( named_child )
+ {
+ stringstream stdout_path,
+ stderr_path;
+
+ // Redirect the child's stdout. -----------------
+ stdout_path << root_dir
+ << '/'
+ << child_name
+ << '/'
+ << "stdout";
+
+ int redirected_stdout = open ( stdout_path.str().c_str(),
+ O_WRONLY|O_CREAT|O_TRUNC,
+ S_IRWXU|S_IRWXG|S_IRWXO
+ );
+ if ( redirected_stdout < 0 )
+ {
+ perror ( "qrsh_run: error opening redirected_stdout: " );
+ fprintf ( stderr, "stdout path: |%s|\n", stdout_path.str().c_str() );
+ exit ( 1 );
+ }
+ if ( -1 == dup2 ( redirected_stdout, 1 ) )
+ {
+ perror ( "qrsh_run: dup2 (stdout) error: " );
+ exit(1);
+ }
+
+ // Redirect the child's stderr. -----------------
+ stderr_path << root_dir
+ << '/'
+ << child_name
+ << '/'
+ << "stderr";
+
+ int redirected_stderr = open ( stderr_path.str().c_str(),
+ O_WRONLY|O_CREAT|O_TRUNC,
+ S_IRWXU|S_IRWXG|S_IRWXO
+ );
+ if ( redirected_stderr < 0 )
+ {
+ perror ( "qrsh_run: error opening redirected_stderr: " );
+ fprintf ( stderr, "stderr path: |%s|\n", stderr_path.str().c_str() );
+ exit ( 1 );
+ }
+ if(-1 == dup2 ( redirected_stderr, 2 ) )
+ {
+ perror ( "qrsh_run: dup2 (stderr) error: " );
+ exit(1);
+ }
+ }
+
+ fprintf ( stderr, "MDEBUG ------------- qrsh_run argv -------------\n" );
+ for ( int i = 0; i < argc; ++ i )
+ fprintf ( stderr, "MDEBUG argv[%d] : |%s|\n", i, argv[i] );
+
+ execv ( child_path, argv + 2 );
+ perror ( "qrsh_run: execv error: " );
+ fprintf ( stderr, "on path |%s|\n", child_path );
+ exit ( 1 );
+ }
+ else
+ {
+ // This code is executed in the parent process.
+
+ if ( named_child )
+ {
+ // Write the name-to-pid mapping.
+ stringstream pid_file_name;
+ pid_file_name << child_dir_name.str()
+ << "/pid";
+
+ FILE * fp;
+ if ( ! (fp = fopen ( pid_file_name.str().c_str(), "w") ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open file |%s|\n",
+ my_pid,
+ pid_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%d\n", child_pid );
+ fclose ( fp );
+
+
+ // Write the pid-to-name mapping.
+ stringstream name_to_pid_file_name;
+ name_to_pid_file_name << root_dir
+ << '/'
+ << child_pid;
+ if(! (fp = fopen ( name_to_pid_file_name.str().c_str(), "w")))
+ {
+ fprintf ( stderr,
+ "qrsh_run %d error: Can't open file |%s|\n",
+ my_pid,
+ name_to_pid_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%s\n", child_name );
+ fclose(fp);
+ }
+
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr,
+ "qrsh_run %d info: parent: waiting for child %d...\n",
+ my_pid,
+ child_pid
+ );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_run error awaiting child!\n" );
+ exit ( 1 );
+ }
+
+ /*
+ * Write the exit code.
+ */
+ exit_code >>= 8;
+
+ if ( named_child )
+ {
+ if ( child_pid == awaited_pid )
+ {
+ stringstream exit_code_file_name;
+ exit_code_file_name << child_dir_name.str()
+ << "/exit_code";
+
+ FILE * fp;
+ if ( ! (fp = fopen ( exit_code_file_name.str().c_str(), "w") ) )
+ {
+ fprintf ( stderr,
+ "qrsh_run error: Can't open file |%s|\n",
+ exit_code_file_name.str().c_str()
+ );
+ exit(1);
+ }
+ fprintf ( fp, "%d\n", exit_code );
+ fclose ( fp );
+ }
+ }
+ }
+
+ fprintf ( stderr, "MDEBUG qrsh_run returning exit code %d\n", exit_code );
+ return exit_code;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_server.cpp b/cpp/src/tests/qrsh_server.cpp
new file mode 100644
index 0000000000..782f1e6c7c
--- /dev/null
+++ b/cpp/src/tests/qrsh_server.cpp
@@ -0,0 +1,1068 @@
+/*
+ *
+ * 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 <stdio.h>
+#include <set>
+#include <string>
+#include <sstream>
+#include <unistd.h>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+
+using namespace qpid::client;
+using namespace qpid::framing;
+using namespace std;
+
+
+namespace qpid {
+namespace tests {
+
+int
+mrand ( int max_desired_val )
+{
+ double zero_to_one = (double) rand() / (double) RAND_MAX;
+ return (int) (zero_to_one * (double) max_desired_val);
+}
+
+
+
+char *
+file2str ( char const * file_name )
+{
+ FILE * fp = fopen ( file_name, "r" );
+ if(! fp)
+ {
+ fprintf ( stderr, "file2str error: can't open file |%s|.\n", file_name );
+ return 0;
+ }
+
+ fseek ( fp, 0, SEEK_END );
+ size_t file_len = (size_t) ftell ( fp );
+ rewind ( fp );
+ char * content = (char *) malloc ( file_len + 1 );
+
+ if ( ! content )
+ {
+ fprintf ( stderr,
+ "file2str error: can't malloc %d bytes.\n",
+ (int)file_len
+ );
+ return 0;
+ }
+
+ size_t items_read = fread ( content, file_len, 1, fp );
+
+ if ( 1 != items_read )
+ {
+ fprintf ( stderr, "file2str error: read failed.\n" );
+ free ( content );
+ return 0;
+ }
+
+ fclose ( fp );
+ content[file_len] = 0;
+
+ return content;
+}
+
+
+
+
+
+class QrshServer : public MessageListener
+{
+ public:
+
+ QrshServer ( SubscriptionManager & subscriptions,
+ char const * name,
+ char const * qrsh_run_path,
+ char const * host,
+ int port
+ );
+
+ virtual void received ( Message & message);
+
+
+ private:
+
+ set<string> all_server_names;
+
+ stringstream data_dir;
+
+ SubscriptionManager & subscriptions;
+
+ // Is this message addressed to me?
+ bool myMessage ( Message const & message );
+
+ /* ----------------------------------------------
+ * Special Commands
+ * These are commands that the qrsh_server executes
+ * directly, rather than through a child process
+ * instance of qrsh_run.
+ */
+ void runCommand ( Message const & message );
+ void execute ( Message const & message );
+ void wait ( Message const & message );
+ void exited ( Message const & message );
+ void get ( Message const & message );
+ void rememberIntroduction ( Message const & message );
+ void getStraw ( Message const & message );
+ void addAlias ( Message const & message );
+
+ void start ( );
+ void sayHello ( );
+ void sayName ( );
+ // end Special Commands ------------------------
+
+
+ void saveCommand ( Message const & message );
+
+ void send ( string const & content );
+
+ void drawStraws ( );
+ void getNames ( );
+ void runSavedCommand ( );
+
+ char ** getArgs ( char const * s );
+ bool isProcessName ( char const * s );
+ int string_countWords ( char const * s );
+ char const * skipWord ( char const * s );
+
+
+ void string_replaceAll ( string & str,
+ string & target,
+ string & replacement
+ );
+
+
+ string name,
+ qrsh_run_path,
+ host;
+
+ vector<string *> aliases;
+
+ int port;
+
+ map < char *, int > abstract_name_map;
+
+ set < string > myFellowBrokers;
+
+ bool saidHello;
+
+ Message savedCommand;
+
+ vector < int > straws;
+ int myStraw;
+
+};
+
+
+
+QrshServer::QrshServer ( SubscriptionManager & subs,
+ char const * name,
+ char const * qrsh_run_path,
+ char const * host,
+ int port
+ )
+ : subscriptions ( subs ),
+ name ( name ),
+ qrsh_run_path ( qrsh_run_path ),
+ host ( host ),
+ port ( port ),
+ saidHello ( false ),
+ myStraw ( 0 )
+{
+ data_dir << "/tmp/qrsh_"
+ << getpid();
+
+ if(mkdir ( data_dir.str().c_str(), 0777 ) )
+ {
+ fprintf ( stderr,
+ "QrshServer::QrshServer error: can't mkdir |%s|\n",
+ data_dir.str().c_str()
+ );
+ exit ( 1 );
+ }
+}
+
+
+
+void
+QrshServer::saveCommand ( Message const & message )
+{
+ savedCommand = message;
+}
+
+
+
+void
+QrshServer::runSavedCommand ( )
+{
+ runCommand ( savedCommand );
+}
+
+
+
+void
+QrshServer::start ( )
+{
+ stringstream announcement_data;
+ announcement_data << "hello_my_name_is "
+ << name;
+
+ send ( announcement_data.str() );
+
+ saidHello = true;
+}
+
+
+
+
+void
+QrshServer::send ( string const & content )
+{
+ try
+ {
+ Message message;
+ message.setData ( content );
+
+ Connection connection;
+ connection.open ( host, port );
+ Session session = connection.newSession ( );
+ session.messageTransfer ( arg::content = message,
+ arg::destination = "amq.fanout"
+ );
+ session.close();
+ connection.close();
+ }
+ catch ( exception const & e )
+ {
+ fprintf ( stderr, "QrshServer::send error: |%s|\n", e.what() );
+ }
+}
+
+
+
+
+void
+QrshServer::sayHello ( )
+{
+ if ( saidHello )
+ return;
+
+ stringstream ss;
+
+ ss << "hello_my_name_is "
+ << name;
+
+ send ( ss.str() );
+ saidHello = true;
+}
+
+
+
+void
+QrshServer::sayName ( )
+{
+ fprintf ( stderr, "My name is: |%s|\n", name.c_str() );
+}
+
+
+
+
+void
+QrshServer::drawStraws ( )
+{
+ myStraw = mrand ( 1000000000 );
+ stringstream ss;
+ ss << "straw "
+ << name
+ << ' '
+ << myStraw;
+ send ( ss.str() );
+}
+
+
+
+void
+QrshServer::getStraw ( Message const & message )
+{
+ int straw;
+
+ char brokerName[1000];
+ sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+ if ( ! strcmp ( brokerName, name.c_str() ) )
+ return;
+
+ sscanf ( message.getData().c_str(), "%*s%*s%d", & straw );
+ straws.push_back ( straw );
+
+ bool i_win = true;
+ int ties = 0;
+
+ if ( straws.size() >= myFellowBrokers.size() )
+ {
+ // All votes are in! Let's see if I win!
+ for ( unsigned int i = 0; i < straws.size(); ++ i )
+ {
+ if ( straws[i] == myStraw )
+ ++ ties;
+ else
+ if ( straws[i] > myStraw )
+ {
+ i_win = false;
+ break;
+ }
+ }
+
+ if ( i_win && (ties <= 0) )
+ {
+ myStraw = 0;
+ straws.clear();
+ runSavedCommand ( );
+ }
+ else
+ if ( i_win && (ties > 0) )
+ {
+ fprintf ( stderr, "MDEBUG oh no! drawStraws error: server %s tied with straw %d!\n", name.c_str(), straw );
+ }
+ }
+}
+
+
+
+
+/*
+ * "APB" command (all-points-bullitens (commands that are not addressed
+ * specifically to any server)) are handled directly, here.
+ * Because if I return simply "true", the normal command processing code
+ * will misinterpret the command.
+ */
+bool
+QrshServer::myMessage ( Message const & message )
+{
+ int const maxlen = 100;
+ char head[maxlen];
+ char first_word [ maxlen + 1 ];
+ strncpy ( head, message.getData().c_str(), maxlen );
+ sscanf ( head, "%s", first_word );
+
+ if ( ! strcmp ( name.c_str(), first_word ) )
+ {
+ return true;
+ }
+ else
+ {
+ // Is the given name one of my aliases?
+ char possibleAlias[1000];
+ if(1 == sscanf ( message.getData().c_str(), "%s", possibleAlias ))
+ {
+ for ( unsigned int i = 0; i < aliases.size(); ++ i )
+ {
+
+ if ( ! strcmp ( possibleAlias, aliases[i]->c_str() ))
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ if ( ! strcmp ( first_word, "hello_my_name_is" ) )
+ {
+ rememberIntroduction ( message );
+ sayHello ( );
+ return false;
+ }
+ else
+ if ( ! strcmp ( first_word, "straw" ) )
+ {
+ getStraw ( message );
+ return false;
+ }
+ else
+ if ( ! strcmp ( first_word, "all" ) )
+ {
+ return true;
+ }
+ else
+ if ( ! strcmp ( first_word, "any" ) )
+ {
+ straws.clear();
+ usleep ( 200000 );
+ saveCommand ( message );
+ drawStraws ( );
+ return false;
+ }
+ else
+ return false;
+}
+
+
+
+
+void
+QrshServer::rememberIntroduction ( Message const & message )
+{
+ char brokerName [ 1000 ];
+ sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+ if ( strcmp ( brokerName, name.c_str() ) )
+ myFellowBrokers.insert ( string ( brokerName ) );
+}
+
+
+
+
+void
+QrshServer::addAlias ( Message const & message )
+{
+ char alias[1000];
+ sscanf ( message.getData().c_str(), "%*s%*s%s", alias );
+ aliases.push_back ( new string(alias) );
+}
+
+
+
+
+void
+QrshServer::getNames ( )
+{
+ abstract_name_map.clear();
+
+ DIR * dir = opendir ( data_dir.str().c_str() );
+
+ if ( ! dir )
+ {
+ fprintf ( stderr,
+ "QrshServer::getNames error: could not open dir |%s|.\n",
+ data_dir.str().c_str()
+ );
+ return;
+ }
+
+ struct dirent * file;
+ while ( (file = readdir ( dir ) ) )
+ {
+ if ( '.' != file->d_name[0] )
+ {
+ stringstream pid_file_name;
+ pid_file_name << data_dir.str()
+ << '/'
+ << file->d_name
+ << "/pid";
+
+ int pid = 0;
+ FILE * fp;
+ if ( (fp = fopen ( pid_file_name.str().c_str(), "r" ) ) )
+ {
+ fscanf ( fp, "%d", & pid );
+ fclose ( fp );
+ abstract_name_map.insert(pair<char*, int>(strdup(file->d_name), pid));
+ }
+ else
+ {
+ /*
+ * Fail silently. The non-existence of this file
+ * is not necessarily an error.
+ */
+ }
+ }
+ }
+ closedir ( dir );
+}
+
+
+
+void
+QrshServer::string_replaceAll ( string & str,
+ string & target,
+ string & replacement
+ )
+{
+ int target_size = target.size();
+ int found_pos = 0;
+
+ while ( 0 <= (found_pos = str.find ( target ) ) )
+ str.replace ( found_pos, target_size, replacement );
+}
+
+
+
+
+bool
+QrshServer::isProcessName ( char const * str )
+{
+ getNames();
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ if ( ! strcmp ( str, it->first ) )
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+
+int
+QrshServer::string_countWords ( char const * s1 )
+{
+ int count = 0;
+ char const * s2 = s1 + 1;
+
+ if ( ! isspace(* s1) )
+ {
+ ++ count;
+ }
+
+ for ( ; * s2; ++ s1, ++ s2 )
+ {
+ // count space-to-word transitions.
+ if ( isspace(*s1) && (! isspace(*s2)) )
+ ++ count;
+ }
+
+ return count;
+}
+
+
+
+
+void
+QrshServer::execute ( Message const & message )
+{
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string command ( message.getData() );
+
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( command, target, replacement );
+ }
+
+
+ char const * truncated_command = skipWord(skipWord(command.c_str()));
+
+ if ( truncated_command )
+ system ( truncated_command );
+}
+
+
+
+
+
+void
+QrshServer::get ( Message const & request_message )
+{
+ char * file_content;
+
+ /*
+ * Get the contents of the requested file.
+ */
+ char file_or_process_name[1000];
+ sscanf ( request_message.getData().c_str(), "%*s%*s%s", file_or_process_name );
+
+ if ( isProcessName ( file_or_process_name ) )
+ {
+ stringstream desired_file_name;
+ desired_file_name << data_dir.str()
+ << '/'
+ << file_or_process_name
+ << '/';
+ char requested_output_stream[1000];
+ if(1 != sscanf ( request_message.getData().c_str(),
+ "%*s%*s%*s%s",
+ requested_output_stream
+ )
+ )
+ {
+ fprintf ( stderr,
+ "QrshServer::get error: Can't read requested data file name from this message: |%s|\n",
+ request_message.getData().c_str()
+ );
+ return;
+ }
+ desired_file_name << requested_output_stream;
+ file_content = file2str ( desired_file_name.str().c_str() );
+ }
+ else
+ {
+ file_content = file2str ( file_or_process_name );
+ }
+
+ stringstream reply_data ;
+ reply_data << "get_response "
+ << file_content;
+ /*
+ * Send a response-message to the server who is waiting.
+ */
+ send ( reply_data.str() );
+}
+
+
+
+
+
+
+void
+QrshServer::exited ( Message const & message )
+{
+ int exit_code = -1;
+
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string edited_command ( message.getData() );
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( edited_command, target, replacement );
+ }
+
+ // Skip the service name. That is not used by the child.
+ char const * truncated_command = skipWord(edited_command.c_str());
+
+ if ( truncated_command )
+ {
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << truncated_command;
+
+ int child_pid;
+ if ( ! (child_pid = fork() ) )
+ {
+ // This is the child.
+
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+
+ perror ( "qrsh_server: execv error: " );
+ exit ( 1 );
+ }
+ else
+ {
+ // This is the parent.
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+ exit ( 1 );
+ }
+
+ exit_code >>= 8;
+
+ stringstream data;
+ data << "wait_response "
+ << exit_code;
+
+ send ( data.str() );
+ }
+ }
+}
+
+
+
+
+void
+QrshServer::wait ( Message const & message )
+{
+ bool pre_existing = false;
+ if ( 3 == string_countWords ( message.getData().c_str() ) )
+ {
+ // The first word is the name of this service.
+ // The second word is "exec_wait".
+ // The third word is the symbolic name of the command to wait for.
+ // The fact that there are exactly three words means that this
+ // must be a command that has already been named and started --
+ // we just need to find its pid and wait on it.
+ pre_existing = true;
+ }
+
+
+ int exit_code = -1;
+
+ // First, gather all the symbolic names we know.
+ getNames();
+
+ // Now make a copy of the command, that I can alter.
+ string edited_command ( message.getData() );
+
+ // Replace each occurrence of every abstract name with its pid.
+ char pid_str[100];
+ map<char *, int>::iterator it;
+ for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+ {
+ sprintf ( pid_str, "%d", it->second );
+ string target ( it->first ),
+ replacement ( pid_str );
+ string_replaceAll ( edited_command, target, replacement );
+ }
+
+ // Skip the service name. That is not used by the child.
+ char const * truncated_command = skipWord(edited_command.c_str());
+
+ if ( truncated_command )
+ {
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << truncated_command;
+
+ int child_pid;
+ if ( ! (child_pid = fork() ) )
+ {
+ // This is the child.
+
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+
+ perror ( "qrsh_server: execv error: " );
+ exit ( 1 );
+ }
+ else
+ {
+ // This is the parent.
+ pid_t awaited_pid;
+ while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+ {
+ fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+ sleep(1);
+ }
+
+ if ( -1 == awaited_pid )
+ {
+ fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+ exit ( 1 );
+ }
+ }
+
+ exit_code >>= 8;
+
+ stringstream data;
+ data << "wait_response "
+ << exit_code;
+
+ send ( data.str() );
+ }
+}
+
+
+
+
+
+char const *
+QrshServer::skipWord ( char const * s )
+{
+ if(! (s && *s) )
+ return 0;
+
+ // skip past initial white space
+ while ( isspace(*s) )
+ {
+ ++ s;
+ if(! *s)
+ return 0;
+ }
+
+ // skip past first word
+ while ( ! isspace(*s) )
+ {
+ ++ s;
+ if(! *s)
+ return 0;
+ }
+
+ return s;
+}
+
+
+
+
+
+char **
+QrshServer::getArgs ( char const * str )
+{
+ char const * s = str;
+
+ char ** argv = 0;
+ vector<int> start_positions,
+ lengths;
+
+ int pos = 0;
+ int arg_len = 0;
+
+ int n_args = 0;
+ while ( 1 )
+ {
+ // advance over whitespace.
+ while ( isspace ( *s ) )
+ {
+ ++ s; ++ pos;
+ if(! *s)
+ {
+ goto done;
+ }
+ }
+
+ ++ n_args;
+ start_positions.push_back ( pos );
+ arg_len = 0;
+
+ // advance over non-whitespace.
+ while ( ! isspace ( *s ) )
+ {
+ ++ s; ++ pos; ++ arg_len;
+ if(! *s)
+ {
+ lengths.push_back ( arg_len );
+ arg_len = 0;
+ goto done;
+ }
+ }
+
+ lengths.push_back ( arg_len );
+ arg_len = 0;
+ }
+
+ done:
+
+ if ( arg_len > 0 )
+ lengths.push_back ( arg_len );
+
+ // Alloc the array.
+ argv = (char **) malloc ( sizeof(char *) * ( n_args + 1 ) );
+ argv[n_args] = 0; // mull-term the array.
+
+ for ( int i = 0; i < n_args; ++ i )
+ {
+ argv[i] = ( char *) malloc ( lengths[i] + 1 );
+ strncpy ( argv[i],
+ str + start_positions[i],
+ lengths[i]
+ );
+ argv[i][lengths[i]] = 0;
+ }
+
+ return argv;
+}
+
+
+
+void
+QrshServer::runCommand ( Message const & message )
+{
+ char const * s = message.getData().c_str();
+
+ /*
+ * Skip the first word, which is this server's name.
+ */
+ while ( isspace(*s) ) // go to start of first word.
+ ++ s;
+
+ while ( ! isspace(*s) ) // go to end of first word.
+ ++ s;
+
+ while ( isspace(*s) ) // go to start of second word.
+ ++ s;
+
+ char command_name[1000];
+ sscanf ( s, "%s", command_name );
+
+ if ( ! strcmp ( "get", command_name ) )
+ {
+ get ( message );
+ }
+ else
+ if ( ! strcmp ( "exited", command_name ) )
+ {
+ exited ( message );
+ }
+ else
+ if ( ! strcmp ( "exec_wait", command_name ) )
+ {
+ wait ( message );
+ }
+ else
+ if ( ! strcmp ( "exec", command_name ) )
+ {
+ execute ( message );
+ }
+ else
+ if ( ! strcmp ( "start", command_name ) )
+ {
+ start ( );
+ }
+ else
+ if ( ! strcmp ( "alias", command_name ) )
+ {
+ addAlias ( message );
+ }
+ else
+ if ( ! strcmp ( "sayName", command_name ) )
+ {
+ sayName ( );
+ }
+ else
+ {
+ /*
+ * If the command is not any of the "special" commands
+ * above, then it's a "normal" command.
+ * That means we run it with a child process instance of
+ * qrsh_run, which will save all its data in the qrsh dir.
+ */
+ stringstream ss;
+ ss << qrsh_run_path
+ << ' '
+ << data_dir.str()
+ << ' '
+ << s;
+
+ if ( ! fork() )
+ {
+ char ** argv = getArgs ( ss.str().c_str() );
+ execv ( qrsh_run_path.c_str(), argv );
+ perror ( "qrsh_server: execv error: " );
+ }
+ }
+}
+
+
+
+void
+QrshServer::received ( Message & message )
+{
+ if ( myMessage ( message ) )
+ runCommand ( message );
+}
+
+
+
+}} // namespace qpid::tests
+
+using namespace qpid::tests;
+
+/*
+ * fixme mick Mon Aug 3 10:29:26 EDT 2009
+ * argv[1] server name
+ * argv[2] qrsh exe path
+ * argv[3] host
+ * argv[4] port
+ */
+int
+main ( int /*argc*/, char** argv )
+{
+ const char* host = argv[3];
+ int port = atoi(argv[4]);
+ Connection connection;
+ Message msg;
+
+ srand ( getpid() );
+
+ try
+ {
+ connection.open ( host, port );
+ Session session = connection.newSession();
+
+
+ // Declare queues.
+ string myQueue = session.getId().getName();
+ session.queueDeclare ( arg::queue=myQueue,
+ arg::exclusive=true,
+ arg::autoDelete=true);
+
+ session.exchangeBind ( arg::exchange="amq.fanout",
+ arg::queue=myQueue,
+ arg::bindingKey="my-key");
+
+ // Create a server and subscribe it to my queue.
+ SubscriptionManager subscriptions ( session );
+ QrshServer server ( subscriptions,
+ argv[1], // server name
+ argv[2], // qrsh exe path
+ host,
+ port
+ );
+ subscriptions.subscribe ( server, myQueue );
+
+ // Receive messages until the subscription is cancelled
+ // by QrshServer::received()
+ subscriptions.run();
+
+ connection.close();
+ }
+ catch(const exception& error)
+ {
+ cout << error.what() << endl;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/10_all b/cpp/src/tests/qrsh_utils/10_all
new file mode 100755
index 0000000000..7b486ea672
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/10_all
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "Asking all servers to say their names... "
+qrsh 127.0.0.1 5813 \
+ all sayName
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/1_remote_run b/cpp/src/tests/qrsh_utils/1_remote_run
new file mode 100755
index 0000000000..5b9b307bba
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/1_remote_run
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_1 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
diff --git a/cpp/src/tests/qrsh_utils/2_forever b/cpp/src/tests/qrsh_utils/2_forever
new file mode 100755
index 0000000000..5528b0e4d8
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/2_forever
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_2 /home/mick/redhat/qrsh/qrsh_run/forever foo bar baz
diff --git a/cpp/src/tests/qrsh_utils/3_kill_it b/cpp/src/tests/qrsh_utils/3_kill_it
new file mode 100755
index 0000000000..afc7a03c9d
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/3_kill_it
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+echo "Killing command 2... "
+./qrsh 127.0.0.1 5813 \
+ mrg23 exec kill -9 command_2
+
diff --git a/cpp/src/tests/qrsh_utils/4_wait_for_it b/cpp/src/tests/qrsh_utils/4_wait_for_it
new file mode 100755
index 0000000000..a4dc0da1ce
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/4_wait_for_it
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exec_wait /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+echo "my_command returned an exit code of $?"
diff --git a/cpp/src/tests/qrsh_utils/5_exited b/cpp/src/tests/qrsh_utils/5_exited
new file mode 100755
index 0000000000..4fec1dcc79
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/5_exited
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+path=/home/mick/redhat/qrsh/qrsh_run
+
+echo "Running command_3 ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_3 $path/my_command foo bar baz
+
+echo "Now I do some other stuff..."
+sleep 1
+echo "And then some more stuff..."
+sleep 1
+echo "and so on..."
+sleep 1
+
+echo "Now I'm waiting for command_3 ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+ mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/6_get b/cpp/src/tests/qrsh_utils/6_get
new file mode 100755
index 0000000000..4b35ca98e6
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/6_get
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+echo "getting /tmp/foo ..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 get /tmp/foo
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/7_get_output b/cpp/src/tests/qrsh_utils/7_get_output
new file mode 100755
index 0000000000..59911089ec
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/7_get_output
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#! /bin/bash
+
+echo "Run a command..."
+./qrsh 127.0.0.1 5813 \
+ mrg23 command_4 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+
+echo "Wait for a while..."
+sleep 20
+
+echo "Get stderr output:"
+echo "------------- begin stderr ---------------"
+./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stderr
+echo "------------- end stderr ---------------"
+echo " "
+echo " "
+echo " "
+echo "Get stdout output:"
+echo "------------- begin stdout ---------------"
+./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stdout
+echo "------------- end stdout ---------------"
+
diff --git a/cpp/src/tests/qrsh_utils/8_any b/cpp/src/tests/qrsh_utils/8_any
new file mode 100755
index 0000000000..2a922ea0e0
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/8_any
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#! /bin/bash
+
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+ any sayName
+sleep 1
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/9_alias b/cpp/src/tests/qrsh_utils/9_alias
new file mode 100755
index 0000000000..a4cfdfdf9a
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/9_alias
@@ -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.
+ *
+ */
+
+#! /bin/bash
+
+# Make a group of two of the servers, using "alias",
+# and send the group a command.
+
+qrsh 127.0.0.1 5813 \
+ mrg22 alias group_1
+qrsh 127.0.0.1 5813 \
+ mrg23 alias group_1
+
+echo "Asking group_1 to say their names... "
+qrsh 127.0.0.1 5813 \
+ group_1 sayName
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp b/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
new file mode 100644
index 0000000000..386e2f73f0
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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 <stdio.h>
+#include <unistd.h>
+
+
+
+main ( int argc, char ** argv )
+{
+ fprintf ( stderr, "Hello, I am the Example Child!\n");
+ fprintf ( stderr, "my arguments %d are:\n", argc - 1 );
+ fprintf ( stdout, "And hello to stdout, too!\n");
+
+ int i;
+ for ( i = 1; i < argc; ++ i )
+ {
+ fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+ }
+
+ for ( i = 0; i < 15; ++ i )
+ {
+ fprintf ( stderr, "child sleeping...\n" );
+ sleep ( 1 );
+ }
+
+ fprintf ( stderr, "child exiting with code 13.\n" );
+
+ return 13;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/qrsh_forever.cpp b/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
new file mode 100644
index 0000000000..191a9bca11
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 <stdio.h>
+#include <unistd.h>
+
+
+
+main ( int argc, char ** argv )
+{
+ fprintf ( stderr, "Hello, I am the Forever Example Child!\n");
+ fprintf ( stderr, "my %d arguments are:\n", argc - 1 );
+
+ int i;
+ for ( i = 1; i < argc; ++ i )
+ fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+
+ for ( i = 0; i >= 0; ++ i )
+ {
+ fprintf ( stderr, "child sleeping forever %d ...\n" , i);
+ sleep ( 1 );
+ }
+
+ fprintf ( stderr, "child exiting with code 12.\n" );
+
+ return 12;
+}
+
+
+
+
diff --git a/cpp/src/tests/qrsh_utils/qsh_doc.txt b/cpp/src/tests/qrsh_utils/qsh_doc.txt
new file mode 100644
index 0000000000..ad5990b38b
--- /dev/null
+++ b/cpp/src/tests/qrsh_utils/qsh_doc.txt
@@ -0,0 +1,309 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+##############################################
+ qrsh: a Qpid-based remote shell utility
+
+ Last updated: 3 Aug 09 Mick Goulish
+##############################################
+
+
+
+=============================
+Overview
+=============================
+
+ You're writing a multi-box test, and you want to write a
+ shell script in which you start processes on other boxes
+ and kill them (or send arbitrary signals to them).
+
+ But ssh doesn't let you signal them, and bash isn't the
+ greatest language in the world for creating data structures
+ (like you need to associate the PIDs with box names and
+ executable names.)
+
+ Qsh is a utility implemented on Qpid that you can use from
+ within your bash script, or any other scripting language.
+ With it, you can:
+
+ 1. run any executable on any box in your cluster.
+
+ 2. don't worry about PIDs and box-names. You associate
+ your own abstract names with the executable instances,
+ and then use those names in the rest of your script.
+ I.e. "broker_1" "sender_3" etc.
+
+ 3. Launch the executable and wait until it returns, and
+ get its exit code.
+
+ 4. Launch your executable and do other stuff, then come
+ back later and see if it has exited.
+
+ 5. Get whatever it sent to stdout or stderr.
+
+ 6. Get the contents of any other file.
+
+ 7. send a command to all your boxes at once
+
+ 8. send a command to a randomly selected box.
+
+ 9. define groups of boxes, and send a command simultaneously
+ to all boxes in a given group.
+
+
+
+
+=============================
+Using It
+=============================
+
+ 1. You need to run a Qpid broker.
+
+ 2. You start a Qpid client ( which is called a qrsh_server )
+ on all the boxes you care about. And you give them all
+ names like "mrg13", "mrg14" etc. The names can be anything
+ you want, but I've always used one qrsh_server per box,
+ and given it the box name. ( However, you can run two on
+ one box, they won't collide. )
+
+ 3. After you start all servers, send a "start" command to any
+ one of them:
+
+ 4. The qrsh_servers use the fanout exchange to talk to each
+ other.
+
+ 5. In your script, you run an executable called "qrsh". It knows
+ how to talk to the servers, do what you want, and retrieve
+ the data you want.
+
+
+ example start script: (this does 4 servers on the same box)
+ -------------------------------------------------------------
+
+ echo "Starting server mrg22 ..."
+ ./qrsh_server mrg22 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg23 ..."
+ ./qrsh_server mrg23 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg24 ..."
+ ./qrsh_server mrg24 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Starting server mrg25 ..."
+ ./qrsh_server mrg25 ./qrsh_run 127.0.0.1 5813 &
+
+ echo "Issuing start command..."
+ sleep 2
+ ./qrsh 127.0.0.1 5813 mrg22 start
+ sleep 1
+
+ echo "Ready."
+
+ # end of script.
+
+
+
+
+
+
+=============================
+Qrsh Syntax
+=============================
+
+ qrsh host port server_name command_name arg*
+
+
+ "host" and "port" specify the Qpid server to connect to.
+
+ "server_name" can be anything you want. I always use the name
+ of the box that the server is running on.
+
+ "command_name" is the name that you choose to assign to
+ the process you are running. Each process that you decide
+ to name must have a unique name within this script.
+
+ Or it could be a reserved command name, that Qsh
+ interprets in a special way.
+
+ Reserved command names are:
+
+ exec
+ exec_wait
+ exited
+ get
+
+ "exec" means "interpret the rest of the command line as a
+ command to be executed by the designated server.
+
+ "exec_wait" means same as "exec", but wait for the command
+ to terminate, and return its exit code.
+
+ "exited" -- you provide 1 arg, which is an abstract
+ process name. qrsh returns 1 if that process has exited,
+ else 0.
+
+ "get" -- you provide one arg which is a path. qrsh returns
+ (by printing to stdout) the contents of that file.
+
+ "arg*" is zero or more arguments. They are interpreted
+ differently depending on whether you are using one of
+ the above reserved command names, or making up your own
+ abstract name for a command.
+
+
+
+
+=============================
+Examples
+=============================
+
+ 1. Run a process on a remote box.
+
+ qrsh mrg23 command_1 /usr/sbin/whatever foo bar baz
+
+ Returns immediately.
+
+
+
+ 2. Kill a process that you started earlier:
+
+ qrsh mrg23 exec kill -9 command_1
+
+ After the word "exec" put any command line you want.
+ The server you're sending this to will replace all abstract
+ names in the command with process IDs. ( In this example,
+ just the word "command_1" will be replaced. ) Then it will
+ execute the command.
+
+
+
+ 3. Execute a command, and wait for it to finish
+
+ qrsh mrg23 exec_wait command_name args
+
+
+
+ 4. Check on whether a command you issude earlier has exited.
+
+ ./qrsh mrg23 exited command_3
+
+ Returns 1 if it has exited, else 0.
+
+
+
+ 5. Get the contents of a file from the remote system:
+
+ ./qrsh mrg23 get /tmp/foo
+
+ Prints the contents to stdout.
+
+
+
+ 6. Send a command to all servers at once:
+
+ # This example causes them all to print thir names to stderr.
+ ./qrsh all sayName
+
+
+ 7. Define a group of servers and send a command to that group.
+
+ #! /bin/bash
+
+ # Make a group of two of the servers, using "alias",
+ # and send the group a command.
+
+ qrsh 127.0.0.1 5813 \
+ mrg22 alias group_1
+
+ qrsh 127.0.0.1 5813 \
+ mrg23 alias group_1
+
+ echo "Asking group_1 to say their names... "
+ qrsh 127.0.0.1 5813 \
+ group_1 sayName
+
+ # end of script.
+
+
+
+
+ 8. Execute a command and get its stdout and stderr contents.
+
+ #! /bin/bash
+
+ echo "Run a command..."
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 command_4 my_command foo bar baz
+
+ echo "Wait for a while..."
+ sleep 10
+
+ echo "Get stderr output:"
+ echo "------------- begin stderr ---------------"
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stderr
+ echo "------------- end stderr ---------------"
+ echo " "
+
+ echo " "
+ echo "Get stdout output:"
+ echo "------------- begin stdout ---------------"
+ ./qrsh 127.0.0.1 5813 \
+ mrg23 get command_4 stdout
+ echo "------------- end stdout ---------------"
+
+ # end of script.
+
+
+
+
+ 9. Send a command to one of your servers, selected
+ at random.
+
+ #! /bin/bash
+
+ # I do it multiple times here, so I can see
+ # that it really is selecting randomly.
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+ sleep 1
+
+ echo "asking any server to say his name ..."
+ ./qrsh 127.0.0.1 5813 \
+ any sayName
+
+ # end of script.
+
+
+
+
diff --git a/cpp/src/tests/queue_flow_limit_tests.py b/cpp/src/tests/queue_flow_limit_tests.py
deleted file mode 100644
index dec7cfb3af..0000000000
--- a/cpp/src/tests/queue_flow_limit_tests.py
+++ /dev/null
@@ -1,371 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-import sys
-from qpid.testlib import TestBase010
-from qpid import datatypes, messaging
-from qpid.messaging import Message, Empty
-from threading import Thread, Lock
-from logging import getLogger
-from time import sleep, time
-from os import environ, popen
-
-class QueueFlowLimitTests(TestBase010):
-
- def __getattr__(self, name):
- if name == "assertGreater":
- return lambda a, b: self.failUnless(a > b)
- else:
- raise AttributeError
-
- def _create_queue(self, name,
- stop_count=None, resume_count=None,
- stop_size=None, resume_size=None,
- max_size=None, max_count=None):
- """ Create a queue with the given flow settings via the queue.declare
- command.
- """
- args={}
- if (stop_count is not None):
- args["qpid.flow_stop_count"] = stop_count;
- if (resume_count is not None):
- args["qpid.flow_resume_count"] = resume_count;
- if (stop_size is not None):
- args["qpid.flow_stop_size"] = stop_size;
- if (resume_size is not None):
- args["qpid.flow_resume_size"] = resume_size;
- if (max_size is not None):
- args["qpid.max_size"] = max_size;
- if (max_count is not None):
- args["qpid.max_count"] = max_count;
-
-
- self.session.queue_declare(queue=name, arguments=args)
-
- qs = self.qmf.getObjects(_class="queue")
- for i in qs:
- if i.name == name:
- # verify flow settings
- if (stop_count is not None):
- self.assertEqual(i.arguments.get("qpid.flow_stop_count"), stop_count)
- if (resume_count is not None):
- self.assertEqual(i.arguments.get("qpid.flow_resume_count"), resume_count)
- if (stop_size is not None):
- self.assertEqual(i.arguments.get("qpid.flow_stop_size"), stop_size)
- if (resume_size is not None):
- self.assertEqual(i.arguments.get("qpid.flow_resume_size"), resume_size)
- if (max_size is not None):
- self.assertEqual(i.arguments.get("qpid.max_size"), max_size)
- if (max_count is not None):
- self.assertEqual(i.arguments.get("qpid.max_count"), max_count)
- self.failIf(i.flowStopped)
- return i.getObjectId()
- self.fail("Unable to create queue '%s'" % name)
- return None
-
-
- def _delete_queue(self, name):
- """ Delete a named queue
- """
- self.session.queue_delete(queue=name)
-
-
- def _start_qpid_send(self, queue, count, content="X", capacity=100):
- """ Use the qpid-send client to generate traffic to a queue.
- """
- command = "qpid-send" + \
- " -b" + " %s:%s" % (self.broker.host, self.broker.port) \
- + " -a " + str(queue) \
- + " --messages " + str(count) \
- + " --content-string " + str(content) \
- + " --capacity " + str(capacity)
- return popen(command)
-
- def _start_qpid_receive(self, queue, count, timeout=5):
- """ Use the qpid-receive client to consume from a queue.
- Note well: prints one line of text to stdout for each consumed msg.
- """
- command = "qpid-receive" + \
- " -b " + "%s:%s" % (self.broker.host, self.broker.port) \
- + " -a " + str(queue) \
- + " --messages " + str(count) \
- + " --timeout " + str(timeout) \
- + " --print-content yes"
- return popen(command)
-
- def test_qpid_config_cmd(self):
- """ Test the qpid-config command's ability to configure a queue's flow
- control thresholds.
- """
- tool = environ.get("QPID_CONFIG_EXEC")
- if tool:
- command = tool + \
- " --broker-addr=%s:%s " % (self.broker.host, self.broker.port) \
- + "add queue test01 --flow-stop-count=999" \
- + " --flow-resume-count=55 --flow-stop-size=5000000" \
- + " --flow-resume-size=100000"
- cmd = popen(command)
- rc = cmd.close()
- self.assertEqual(rc, None)
-
- # now verify the settings
- self.startQmf();
- qs = self.qmf.getObjects(_class="queue")
- for i in qs:
- if i.name == "test01":
- self.assertEqual(i.arguments.get("qpid.flow_stop_count"), 999)
- self.assertEqual(i.arguments.get("qpid.flow_resume_count"), 55)
- self.assertEqual(i.arguments.get("qpid.flow_stop_size"), 5000000)
- self.assertEqual(i.arguments.get("qpid.flow_resume_size"), 100000)
- self.failIf(i.flowStopped)
- break;
- self.assertEqual(i.name, "test01")
- self._delete_queue("test01")
-
-
- def test_flow_count(self):
- """ Create a queue with count-based flow limit. Spawn several
- producers which will exceed the limit. Verify limit exceeded. Consume
- all messages. Verify flow control released.
- """
- self.startQmf();
- oid = self._create_queue("test-q", stop_count=373, resume_count=229)
- self.assertEqual(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount, 0)
-
- sndr1 = self._start_qpid_send("test-q", count=1213, content="XXX", capacity=50);
- sndr2 = self._start_qpid_send("test-q", count=797, content="Y", capacity=13);
- sndr3 = self._start_qpid_send("test-q", count=331, content="ZZZZZ", capacity=149);
- totalMsgs = 1213 + 797 + 331
-
- # wait until flow control is active
- deadline = time() + 10
- while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
- time() < deadline:
- pass
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(depth, 373)
-
- # now wait until the enqueues stop happening - ensure that
- # not all msgs have been sent (senders are blocked)
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- while depth != newDepth:
- depth = newDepth;
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(totalMsgs, depth)
-
- # drain the queue
- rcvr = self._start_qpid_receive("test-q",
- count=totalMsgs)
- count = 0;
- x = rcvr.readline() # prints a line for each received msg
- while x:
- count += 1;
- x = rcvr.readline()
-
- sndr1.close();
- sndr2.close();
- sndr3.close();
- rcvr.close();
-
- self.assertEqual(count, totalMsgs)
- self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStoppedCount)
-
- self._delete_queue("test-q")
-
-
- def test_flow_size(self):
- """ Create a queue with size-based flow limit. Spawn several
- producers which will exceed the limit. Verify limit exceeded. Consume
- all messages. Verify flow control released.
- """
- self.startQmf();
- oid = self._create_queue("test-q", stop_size=351133, resume_size=251143)
-
- sndr1 = self._start_qpid_send("test-q", count=1699, content="X"*439, capacity=53);
- sndr2 = self._start_qpid_send("test-q", count=1129, content="Y"*631, capacity=13);
- sndr3 = self._start_qpid_send("test-q", count=881, content="Z"*823, capacity=149);
- totalMsgs = 1699 + 1129 + 881
-
- # wait until flow control is active
- deadline = time() + 10
- while (not self.qmf.getObjects(_objectId=oid)[0].flowStopped) and \
- time() < deadline:
- pass
- self.failUnless(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
- self.assertGreater(self.qmf.getObjects(_objectId=oid)[0].byteDepth, 351133)
-
- # now wait until the enqueues stop happening - ensure that
- # not all msgs have been sent (senders are blocked)
- depth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- while depth != newDepth:
- depth = newDepth;
- sleep(1)
- newDepth = self.qmf.getObjects(_objectId=oid)[0].msgDepth
- self.assertGreater(totalMsgs, depth)
-
- # drain the queue
- rcvr = self._start_qpid_receive("test-q",
- count=totalMsgs)
- count = 0;
- x = rcvr.readline() # prints a line for each received msg
- while x:
- count += 1;
- x = rcvr.readline()
-
- sndr1.close();
- sndr2.close();
- sndr3.close();
- rcvr.close();
-
- self.assertEqual(count, totalMsgs)
- self.failIf(self.qmf.getObjects(_objectId=oid)[0].flowStopped)
-
- self._delete_queue("test-q")
-
-
- def verify_limit(self, testq):
- """ run a limit check against the testq object
- """
-
- testq.mgmt = self.qmf.getObjects(_objectId=testq.oid)[0]
-
- # fill up the queue, waiting until flow control is active
- sndr1 = self._start_qpid_send(testq.mgmt.name, count=testq.sendCount, content=testq.content)
- deadline = time() + 10
- while (not testq.mgmt.flowStopped) and time() < deadline:
- testq.mgmt.update()
-
- self.failUnless(testq.verifyStopped())
-
- # now consume enough messages to drop below the flow resume point, and
- # verify flow control is released.
- rcvr = self._start_qpid_receive(testq.mgmt.name, count=testq.consumeCount)
- rcvr.readlines() # prints a line for each received msg
- rcvr.close();
-
- # we should now be below the resume threshold
- self.failUnless(testq.verifyResumed())
-
- self._delete_queue(testq.mgmt.name)
- sndr1.close();
-
-
- def test_default_flow_count(self):
- """ Create a queue with count-based size limit, and verify the computed
- thresholds using the broker's default ratios.
- """
- class TestQ:
- def __init__(self, oid):
- # Use the broker-wide default flow thresholds of 80%/70% (see
- # run_queue_flow_limit_tests) to base the thresholds off the
- # queue's max_count configuration parameter
- # max_count == 1000 -> stop == 800, resume == 700
- self.oid = oid
- self.sendCount = 1000
- self.consumeCount = 301 # (send - resume) + 1 to reenable flow
- self.content = "X"
- def verifyStopped(self):
- self.mgmt.update()
- return self.mgmt.flowStopped and (self.mgmt.msgDepth > 800)
- def verifyResumed(self):
- self.mgmt.update()
- return (not self.mgmt.flowStopped) and (self.mgmt.msgDepth < 700)
-
- self.startQmf();
- oid = self._create_queue("test-X", max_count=1000)
- self.verify_limit(TestQ(oid))
-
-
- def test_default_flow_size(self):
- """ Create a queue with byte-based size limit, and verify the computed
- thresholds using the broker's default ratios.
- """
- class TestQ:
- def __init__(self, oid):
- # Use the broker-wide default flow thresholds of 80%/70% (see
- # run_queue_flow_limit_tests) to base the thresholds off the
- # queue's max_count configuration parameter
- # max_size == 10000 -> stop == 8000 bytes, resume == 7000 bytes
- self.oid = oid
- self.sendCount = 2000
- self.consumeCount = 601 # (send - resume) + 1 to reenable flow
- self.content = "XXXXX" # 5 bytes per message sent.
- def verifyStopped(self):
- self.mgmt.update()
- return self.mgmt.flowStopped and (self.mgmt.byteDepth > 8000)
- def verifyResumed(self):
- self.mgmt.update()
- return (not self.mgmt.flowStopped) and (self.mgmt.byteDepth < 7000)
-
- self.startQmf();
- oid = self._create_queue("test-Y", max_size=10000)
- self.verify_limit(TestQ(oid))
-
-
- def test_blocked_queue_delete(self):
- """ Verify that blocked senders are unblocked when a queue that is flow
- controlled is deleted.
- """
-
- class BlockedSender(Thread):
- def __init__(self, tester, queue, count, capacity=10):
- self.tester = tester
- self.queue = queue
- self.count = count
- self.capacity = capacity
- Thread.__init__(self)
- self.done = False
- self.start()
- def run(self):
- # spawn qpid-send
- p = self.tester._start_qpid_send(self.queue,
- self.count,
- self.capacity)
- p.close() # waits for qpid-send to complete
- self.done = True
-
- self.startQmf();
- oid = self._create_queue("kill-q", stop_size=10, resume_size=2)
- q = self.qmf.getObjects(_objectId=oid)[0]
- self.failIf(q.flowStopped)
-
- sender = BlockedSender(self, "kill-q", count=100)
- # wait for flow control
- deadline = time() + 10
- while (not q.flowStopped) and time() < deadline:
- q.update()
-
- self.failUnless(q.flowStopped)
- self.failIf(sender.done) # sender blocked
-
- self._delete_queue("kill-q")
- sender.join(5)
- self.failIf(sender.isAlive())
- self.failUnless(sender.done)
-
-
-
-
diff --git a/cpp/src/tests/replication_test b/cpp/src/tests/replication_test
index 8c37568875..691fd20b0c 100755
--- a/cpp/src/tests/replication_test
+++ b/cpp/src/tests/replication_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_acl_tests b/cpp/src/tests/run_acl_tests
index 41f41e20e1..aff13408ed 100755
--- a/cpp/src/tests/run_acl_tests
+++ b/cpp/src/tests/run_acl_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_cli_tests b/cpp/src/tests/run_cli_tests
index ec5c71b646..3f1388b9f5 100755
--- a/cpp/src/tests/run_cli_tests
+++ b/cpp/src/tests/run_cli_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -70,8 +70,7 @@ stop_brokers() {
if test -d ${PYTHON_DIR} ; then
start_brokers
echo "Running CLI tests using brokers on ports $LOCAL_PORT $REMOTE_PORT"
- PYTHON_TESTS=${PYTHON_TESTS:-$*}
- $QPID_PYTHON_TEST -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $targs $PYTHON_TESTS $@
+ $QPID_PYTHON_TEST -m cli_tests -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dcli-dir=$CLI_DIR $targs $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/cpp/src/tests/run_federation_sys_tests b/cpp/src/tests/run_federation_sys_tests
deleted file mode 100755
index f5f772d72e..0000000000
--- a/cpp/src/tests/run_federation_sys_tests
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run the federation system tests.
-
-source ./test_env.sh
-
-MODULENAME=federation_sys
-
-# Test for clustering
-ps -u root | grep 'aisexec\|corosync' > /dev/null
-if (( $? == 0 )); then
- CLUSTERING_ENABLED=1
-else
- echo "WARNING: No clustering detected; tests using it will be ignored."
-fi
-
-# Test for long test
-if [[ "$1" == "LONG_TEST" ]]; then
- USE_LONG_TEST=1
- shift # get rid of this param so it is not treated as a test name
-fi
-
-trap stop_brokers INT TERM QUIT
-
-SKIPTESTS="-i federation_sys.E_* -i federation_sys.F_* -i federation_sys.G_* -i federation_sys.H_*"
-if [ -z ${USE_LONG_TEST} ]; then
- SKIPTESTS="-i federation_sys.A_Long* -i federation_sys.B_Long* ${SKIPTESTS}"
-fi
-echo "WARNING: Tests using persistence will be ignored."
-if [ -z ${CLUSTERING_ENABLED} ]; then
- SKIPTESTS="${SKIPTESTS} -i federation_sys.C_* -i federation_sys.D_*"
-elif [ -z ${USE_LONG_TEST} ]; then
- SKIPTESTS="${SKIPTESTS} -i federation_sys.C_Long* -i federation_sys.D_Long*"
-fi
-
-start_brokers() {
- start_broker() {
- ${QPIDD_EXEC} --daemon --port 0 --auth no --no-data-dir $1 > qpidd.port
- PORT=`cat qpidd.port`
- eval "$2=${PORT}"
- }
- start_broker "" LOCAL_PORT
- start_broker "" REMOTE_PORT
- if [ -n "${CLUSTERING_ENABLED}" ]; then
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-1" CLUSTER_C1_1
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-1" CLUSTER_C1_2
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-2" CLUSTER_C2_1
- start_broker "--load-module ${CLUSTER_LIB} --cluster-name test-cluster-2" CLUSTER_C2_2
- fi
- rm qpidd.port
-}
-
-stop_brokers() {
- ${QPIDD_EXEC} -q --port ${LOCAL_PORT}
- ${QPIDD_EXEC} -q --port ${REMOTE_PORT}
- if [ -n "${CLUSTERING_ENABLED}" ]; then
- ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C1_1}
- ${QPID_CLUSTER_EXEC} --all-stop --force localhost:${CLUSTER_C2_1}
- fi
-}
-
-if test -d ${PYTHON_DIR} ; then
- start_brokers
- if [ -z ${CLUSTERING_ENABLED} ]; then
- echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT} (NOTE: clustering is DISABLED)"
- else
- echo "Running federation tests using brokers on local port ${LOCAL_PORT}, remote port ${REMOTE_PORT}, local cluster nodes ${CLUSTER_C1_1} ${CLUSTER_C1_2}, remote cluster nodes ${CLUSTER_C2_1} ${CLUSTER_C2_2}"
- fi
- if [ -z ${USE_LONG_TEST} ]; then
- echo "NOTE: To run a full set of federation system tests, use \"make check-long\". To test with persistence, run the store version of this script."
- fi
- ${QPID_PYTHON_TEST} -m ${MODULENAME} ${SKIPTESTS} -b localhost:${REMOTE_PORT} -Dlocal-port=${LOCAL_PORT} -Dremote-port=${REMOTE_PORT} -Dlocal-cluster-ports="${CLUSTER_C1_1} ${CLUSTER_C1_2}" -Dremote-cluster-ports="${CLUSTER_C2_1} ${CLUSTER_C2_2}" $@
- RETCODE=$?
- stop_brokers
- if test x${RETCODE} != x0; then
- echo "FAIL federation tests"; exit 1;
- fi
-fi
diff --git a/cpp/src/tests/run_federation_tests b/cpp/src/tests/run_federation_tests
index 14af4807ba..4be27a2e85 100755
--- a/cpp/src/tests/run_federation_tests
+++ b/cpp/src/tests/run_federation_tests
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -55,7 +55,7 @@ stop_brokers() {
if test -d ${PYTHON_DIR} ; then
start_brokers
echo "Running federation tests using brokers on ports $LOCAL_PORT $REMOTE_PORT $REMOTE_B1 $REMOTE_B2"
- $QPID_PYTHON_TEST -m federation "$SKIPTESTS" -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dextra-brokers="$REMOTE_B1 $REMOTE_B2" $@
+ $QPID_PYTHON_TEST -m federation $SKIPTESTS -b localhost:$LOCAL_PORT -Dremote-port=$REMOTE_PORT -Dextra-brokers="$REMOTE_B1 $REMOTE_B2" $@
RETCODE=$?
stop_brokers
if test x$RETCODE != x0; then
diff --git a/cpp/src/tests/run_header_test b/cpp/src/tests/run_header_test
index 34008132cc..07658343e7 100755
--- a/cpp/src/tests/run_header_test
+++ b/cpp/src/tests/run_header_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
diff --git a/cpp/src/tests/run_long_federation_sys_tests b/cpp/src/tests/run_long_federation_sys_tests
deleted file mode 100644
index 69dc08d11c..0000000000
--- a/cpp/src/tests/run_long_federation_sys_tests
+++ /dev/null
@@ -1,24 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run the federation system tests (long version).
-
-./run_federation_sys_tests LONG_TEST $@
diff --git a/cpp/src/tests/run_msg_group_tests b/cpp/src/tests/run_msg_group_tests
deleted file mode 100755
index 8423022521..0000000000
--- a/cpp/src/tests/run_msg_group_tests
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-#script to run a sequence of message group queue tests via make
-
-#setup path to find qpid-config and msg_group_test progs
-source ./test_env.sh
-
-export PATH=$PWD:$srcdir:$PYTHON_COMMANDS:$PATH
-
-#set port to connect to via env var
-test -s qpidd.port && QPID_PORT=`cat qpidd.port`
-
-#trap cleanup INT TERM QUIT
-
-QUEUE_NAME="group-queue"
-GROUP_KEY="My-Group-Id"
-
-BROKER_URL="${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
-
-run_test() {
- $@
-}
-
-##set -x
-
-declare -i i=0
-declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 3"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 7 --randomize-group-size"
- "qpid-config -a $BROKER_URL add queue ${QUEUE_NAME}-two --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 7 --ack-frequency 3 --randomize-group-size"
- "msg_group_test -b $BROKER_URL -a ${QUEUE_NAME}-two --group-key $GROUP_KEY --messages 103 --group-size 13 --receivers 2 --senders 3 --capacity 3 --ack-frequency 7 --randomize-group-size --interleave 5"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 5 --receivers 2 --senders 3 --capacity 1 --ack-frequency 3 --randomize-group-size"
- "qpid-config -a $BROKER_URL del queue ${QUEUE_NAME}-two --force"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 59 --group-size 3 --receivers 2 --senders 3 --capacity 1 --ack-frequency 1 --randomize-group-size"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 211 --group-size 13 --receivers 2 --senders 3 --capacity 47 --ack-frequency 79 --interleave 53"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
-
-while [ -n "${tests[i]}" ]; do
- run_test ${tests[i]}
- RETCODE=$?
- if test x$RETCODE != x0; then
- echo "FAILED message group test. Failed command: \"${tests[i]}\"";
- exit 1;
- fi
- i+=1
-done
diff --git a/cpp/src/tests/run_msg_group_tests_soak b/cpp/src/tests/run_msg_group_tests_soak
deleted file mode 100755
index 5231f74755..0000000000
--- a/cpp/src/tests/run_msg_group_tests_soak
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-#script to run a sequence of long-running message group tests via make
-
-#setup path to find qpid-config and msg_group_test test progs
-source ./test_env.sh
-
-export PATH=$PWD:$srcdir:$PYTHON_COMMANDS:$PATH
-
-#set port to connect to via env var
-test -s qpidd.port && QPID_PORT=`cat qpidd.port`
-
-#trap cleanup INT TERM QUIT
-
-QUEUE_NAME="group-queue"
-GROUP_KEY="My-Group-Id"
-
-BROKER_URL="${QPID_BROKER:-localhost}:${QPID_PORT:-5672}"
-
-run_test() {
- $@
-}
-
-##set -x
-
-declare -i i=0
-declare -a tests
-tests=("qpid-config -a $BROKER_URL add queue $QUEUE_NAME --group-header=${GROUP_KEY} --shared-groups"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 47 --ack-frequency 97"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 79 --ack-frequency 79"
- "msg_group_test -b $BROKER_URL -a $QUEUE_NAME --group-key $GROUP_KEY --messages 10007 --receivers 3 --senders 5 --group-size 211 --randomize-group-size --capacity 97 --ack-frequency 47"
- "qpid-config -a $BROKER_URL del queue $QUEUE_NAME --force")
-
-while [ -n "${tests[i]}" ]; do
- run_test ${tests[i]}
- RETCODE=$?
- if test x$RETCODE != x0; then
- echo "FAILED message group test. Failed command: \"${tests[i]}\"";
- exit 1;
- fi
- i+=1
-done
diff --git a/cpp/src/tests/run_queue_flow_limit_tests b/cpp/src/tests/run_queue_flow_limit_tests
deleted file mode 100755
index f921cf5e7e..0000000000
--- a/cpp/src/tests/run_queue_flow_limit_tests
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Run tests against Queue producer flow control.
-
-source ./test_env.sh
-test -d $PYTHON_DIR || { echo "Skipping queue flow control tests, no python dir."; exit 0; }
-
-LOG_FILE=queue_flow_limit_test.log
-PORT=""
-
-trap stop_broker INT TERM QUIT
-
-error() {
- echo $*
- exit 1;
-}
-
-start_broker() {
- # Note: if you change the DEFAULT_THRESHOLDS, you will need to update queue_flow_limit_tests.py
- DEFAULT_THRESHOLDS="--default-flow-stop-threshold=80 --default-flow-resume-threshold=70"
- rm -rf $LOG_FILE
- PORT=$($QPIDD_EXEC $DEFAULT_THRESHOLDS --auth=no --no-module-dir --daemon --port=0 -t --log-to-file $LOG_FILE) || error "Could not start broker"
-}
-
-stop_broker() {
- test -n "$PORT" && $QPIDD_EXEC --no-module-dir --quit --port $PORT
-}
-
-start_broker
-echo "Running Queue flow limit tests using broker on port $PORT"
-$QPID_PYTHON_TEST -m queue_flow_limit_tests $SKIPTESTS -b localhost:$PORT $@
-RETCODE=$?
-stop_broker
-if test x$RETCODE != x0; then
- echo "FAIL queue flow limit tests"; exit 1;
-fi
-rm -rf $LOG_FILE
-
diff --git a/cpp/src/tests/run_store_tests.ps1 b/cpp/src/tests/run_store_tests.ps1
index b2f0b1ccd8..76b46737f0 100644
--- a/cpp/src/tests/run_store_tests.ps1
+++ b/cpp/src/tests/run_store_tests.ps1
@@ -111,7 +111,7 @@ Invoke-Expression "$prog --quit --port $env:QPID_PORT" | Write-Output
# Test 2... store.py starts/stops/restarts its own brokers
$tests = "*"
-$env:PYTHONPATH="$PYTHON_DIR;$QMF_LIB;$srcdir"
+$env:PYTHONPATH="$PYTHON_DIR;$srcdir"
$env:QPIDD_EXEC="$prog"
$env:STORE_LIB="$store_dir\store$suffix.dll"
if ($test_store -eq "MSSQL") {
diff --git a/cpp/src/tests/run_test b/cpp/src/tests/run_test
index 6ec1fd892b..4b227621bc 100755
--- a/cpp/src/tests/run_test
+++ b/cpp/src/tests/run_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
diff --git a/cpp/src/tests/sasl.mk b/cpp/src/tests/sasl.mk
index 69b24c3f8a..5b8419f604 100644
--- a/cpp/src/tests/sasl.mk
+++ b/cpp/src/tests/sasl.mk
@@ -30,21 +30,9 @@ check_PROGRAMS+=sasl_version
sasl_version_SOURCES=sasl_version.cpp
sasl_version_LDADD=$(lib_client)
-TESTS += run_cluster_authentication_test sasl_fed sasl_fed_ex_dynamic sasl_fed_ex_link sasl_fed_ex_queue sasl_fed_ex_route sasl_fed_ex_route_cluster sasl_fed_ex_link_cluster sasl_fed_ex_queue_cluster sasl_fed_ex_dynamic_cluster sasl_no_dir
+TESTS += run_cluster_authentication_test sasl_fed sasl_fed_ex
LONG_TESTS += run_cluster_authentication_soak
-EXTRA_DIST += run_cluster_authentication_test \
- sasl_fed \
- sasl_fed_ex \
- run_cluster_authentication_soak \
- sasl_fed_ex_dynamic \
- sasl_fed_ex_link \
- sasl_fed_ex_queue \
- sasl_fed_ex_route \
- sasl_fed_ex_dynamic_cluster \
- sasl_fed_ex_link_cluster \
- sasl_fed_ex_queue_cluster \
- sasl_fed_ex_route_cluster \
- sasl_no_dir
+EXTRA_DIST += run_cluster_authentication_test sasl_fed sasl_fed_ex run_cluster_authentication_soak
endif # HAVE_SASL
diff --git a/cpp/src/tests/sasl_fed b/cpp/src/tests/sasl_fed
index 884c44177c..9845a20838 100755
--- a/cpp/src/tests/sasl_fed
+++ b/cpp/src/tests/sasl_fed
@@ -123,7 +123,7 @@ n_messages=100
#--------------------------------------------------
#echo " Sending 100 messages to $broker_1_port "
#--------------------------------------------------
-$builddir/datagen --count $n_messages | $SENDER_EXEC --mechanism DIGEST-MD5 --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port
+$builddir/datagen --count $n_messages | $SENDER_EXEC --username zag --password zag --exchange $EXCHANGE_NAME --routing-key $ROUTING_KEY --port $broker_1_port
sleep 5
diff --git a/cpp/src/tests/sasl_fed_ex b/cpp/src/tests/sasl_fed_ex
index 716a806874..0740650d6c 100755
--- a/cpp/src/tests/sasl_fed_ex
+++ b/cpp/src/tests/sasl_fed_ex
@@ -19,52 +19,22 @@
# under the License.
#
+
#===============================================================================
-# These tests create federated links between two brokers using SASL security.
+# This test creates a federated link between two brokers using SASL security.
# The SASL mechanism used is EXTERNAL, which is satisfied by SSL
# transport-layer security.
#===============================================================================
source ./test_env.sh
-script_name=`basename $0`
-
-if [ $# -lt 1 ] || [ $# -gt 2 ]
-then
- echo
- # These are the four different ways of creating links ( or routes+links )
- # that the qpid-route command provides.
- echo "Usage: ${script_name} dynamic|link|queue|route [cluster]"
- echo
- exit 1
-fi
-
-# Has the user told us to do clustering ? -----------
-clustering_flag=
-if [ $# -eq "2" ] && [ "$2" == "cluster" ]; then
- clustering_flag=true
-fi
-
-qpid_route_method=$1
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-print "=========== start sasl_fed_ex $* ============"
-
-
# This minimum value corresponds to sasl version 2.1.22
minimum_sasl_version=131350
sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-# This test is necessary because this sasl version is the first one that permits
+# This test is necessary becasue this sasl version is the first one that permits
# redirection of the sasl config file path.
if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
@@ -90,7 +60,6 @@ create_certs() {
delete_certs() {
if [[ -e ${CERT_DIR} ]] ; then
- print "removing cert dir ${CERT_DIR}"
rm -rf ${CERT_DIR}
fi
}
@@ -103,40 +72,22 @@ if [[ !(-x $CERTUTIL) ]] ; then
fi
delete_certs
-create_certs 2> /dev/null
-if [ ! $? ]; then
- error "Could not create test certificate"
- exit 1
-fi
+create_certs || error "Could not create test certificate"
-sasl_config_dir=$builddir/sasl_config
-tmp_root=${builddir}/sasl_fed_ex_temp
-print "results dir is ${tmp_root}"
-rm -rf ${tmp_root}
+sasl_config_file=$builddir/sasl_config
+
+my_random_number=$RANDOM
+tmp_root=/tmp/sasl_fed_$my_random_number
mkdir -p $tmp_root
SRC_SSL_PORT=6667
DST_SSL_PORT=6666
-SRC_SSL_PORT_2=6668
-DST_SSL_PORT_2=6669
-
SRC_TCP_PORT=5801
DST_TCP_PORT=5807
-SRC_TCP_PORT_2=5802
-DST_TCP_PORT_2=5803
-
-CLUSTER_NAME_SUFFIX=`hostname | tr '.' ' ' | awk '{print $1}'`
-CLUSTER_1_NAME=sasl_fed_ex_cluster_1_${CLUSTER_NAME_SUFFIX}
-CLUSTER_2_NAME=sasl_fed_ex_cluster_2_${CLUSTER_NAME_SUFFIX}
-
-print "CLUSTER_1_NAME == ${CLUSTER_1_NAME}"
-print "CLUSTER_2_NAME == ${CLUSTER_2_NAME}"
-
-SSL_LIB=${moduledir}/ssl.so
-CLUSTER_LIB=${moduledir}/cluster.so
+SSL_LIB=../.libs/ssl.so
export QPID_SSL_CERT_NAME=${TEST_HOSTNAME}
@@ -165,112 +116,52 @@ export QPID_SSL_CERT_NAME=${TEST_HOSTNAME}
# 5. DST pulls messages off the temp queue on SRC to itself.
#
-COMMON_BROKER_OPTIONS=" \
- --ssl-sasl-no-dict \
- --sasl-config=$sasl_config_dir \
- --ssl-require-client-authentication \
- --auth yes \
- --ssl-cert-db $CERT_DIR \
- --ssl-cert-password-file $CERT_PW_FILE \
- --ssl-cert-name $TEST_HOSTNAME \
- --no-data-dir \
- --no-module-dir \
- --load-module ${SSL_LIB} \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --daemon "
-
-
-function start_brokers {
- if [ $1 ]; then
- # clustered ----------------------------------------
- print "Starting SRC cluster"
-
- print " src broker 1"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT} \
- --ssl-port ${SRC_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_1_NAME} \
- --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
-
- broker_ports[0]=${SRC_TCP_PORT}
-
- print " src broker 2"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT_2} \
- --ssl-port ${SRC_SSL_PORT_2} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_1_NAME} \
- --log-to-file $tmp_root/qpidd_src_2.log 2> /dev/null
-
- broker_ports[1]=${SRC_TCP_PORT_2}
-
-
- print "Starting DST cluster"
-
- print " dst broker 1"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT} \
- --ssl-port ${DST_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_2_NAME} \
- --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
-
- broker_ports[2]=${DST_TCP_PORT}
-
- print " dst broker 2"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT_2} \
- --ssl-port ${DST_SSL_PORT_2} \
- ${COMMON_BROKER_OPTIONS} \
- --load-module ${CLUSTER_LIB} \
- --cluster-name ${CLUSTER_2_NAME} \
- --log-to-file $tmp_root/qpidd_dst_2.log 2> /dev/null
-
- broker_ports[3]=${DST_TCP_PORT_2}
-
- else
- # vanilla brokers --------------------------------
- print "Starting SRC broker"
- $QPIDD_EXEC \
- --port=${SRC_TCP_PORT} \
- --ssl-port ${SRC_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
-
- broker_ports[0]=${SRC_TCP_PORT}
-
- print "Starting DST broker"
- $QPIDD_EXEC \
- --port=${DST_TCP_PORT} \
- --ssl-port ${DST_SSL_PORT} \
- ${COMMON_BROKER_OPTIONS} \
- --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
-
- broker_ports[1]=${DST_TCP_PORT}
- fi
-}
-
-function halt_brokers {
- n_brokers=${#broker_ports[@]}
- print "Halting ${n_brokers} brokers."
- for i in $(seq 0 $((${n_brokers} - 1)))
- do
- halt_port=${broker_ports[$i]}
- print "Halting broker $i on port ${halt_port}"
- $QPIDD_EXEC --port ${halt_port} --quit
- done
-
-}
-
-start_brokers $clustering_flag
+#echo "-----------------------"
+#echo "Starting SRC broker"
+#echo "-----------------------"
+$QPIDD_EXEC \
+ --port=${SRC_TCP_PORT} \
+ --ssl-port ${SRC_SSL_PORT} \
+ --ssl-sasl-no-dict \
+ --sasl-config=$sasl_config_file \
+ --ssl-require-client-authentication \
+ --auth yes \
+ --ssl-cert-db $CERT_DIR \
+ --ssl-cert-password-file $CERT_PW_FILE \
+ --ssl-cert-name $TEST_HOSTNAME \
+ --no-data-dir \
+ --no-module-dir \
+ --load-module ${SSL_LIB} \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --daemon \
+ --log-to-file $tmp_root/qpidd_src.log 2> /dev/null
+
+
+#echo "-----------------------"
+#echo "Starting DST broker"
+#echo "-----------------------"
+$QPIDD_EXEC \
+ --port=${DST_TCP_PORT} \
+ --ssl-port ${DST_SSL_PORT} \
+ --ssl-cert-db $CERT_DIR \
+ --ssl-cert-password-file $CERT_PW_FILE \
+ --ssl-cert-name $TEST_HOSTNAME \
+ --ssl-sasl-no-dict \
+ --ssl-require-client-authentication \
+ --sasl-config=$sasl_config_file \
+ --no-data-dir \
+ --no-module-dir \
+ --load-module ${SSL_LIB} \
+ --mgmt-enable=yes \
+ --log-enable info+ \
+ --log-source yes \
+ --daemon \
+ $COMMON_BROKER_OPTIONS \
+ --log-to-file $tmp_root/qpidd_dst.log 2> /dev/null
# I am not randomizing these names, because this test creates its own brokers.
@@ -279,83 +170,76 @@ ROUTING_KEY=sasl_fed_queue
EXCHANGE_NAME=sasl_fedex
-print "add exchanges"
+#echo "-----------------------"
+#echo "add exchanges"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add exchange direct $EXCHANGE_NAME
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add exchange direct $EXCHANGE_NAME
-print "add queues"
+#echo "-----------------------"
+#echo "add queues"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} add queue $QUEUE_NAME
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} add queue $QUEUE_NAME
-print "create bindings"
+#echo "-----------------------"
+#echo "create bindings"
+#echo "-----------------------"
$QPID_CONFIG_EXEC -a localhost:${SRC_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
$QPID_CONFIG_EXEC -a localhost:${DST_TCP_PORT} bind $EXCHANGE_NAME $QUEUE_NAME $ROUTING_KEY
-#
+#echo "-----------------------"
+#echo "qpid-route route add"
+#echo "-----------------------"
# NOTE: The SRC broker *must* be referred to as $TEST_HOSTNAME, and not as "localhost".
# It must be referred to by the exact string given as the Common Name (CN) in the cert,
# which was created in the function create_certs, above.
+$QPID_ROUTE_EXEC route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} -t ssl $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL
+#echo "-----------------------"
+#echo "view the route :"
+#echo "-----------------------"
+#$PYTHON_COMMANDS/qpid-route route list localhost:${DST_TCP_PORT}
+# I don't know how to avoid this sleep yet. It has to come after route-creation.
+sleep 5
-#----------------------------------------------------------------
-# Use qpid-route to create the link, or the link+route, depending
-# on which of its several methods was requested.
-#----------------------------------------------------------------
-if [ ${qpid_route_method} == "dynamic" ]; then
- print "dynamic add"
- $QPID_ROUTE_EXEC -t ssl dynamic add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME "" "" EXTERNAL
-elif [ ${qpid_route_method} == "link" ]; then
- print "link add"
- $QPID_ROUTE_EXEC -t ssl link add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} EXTERNAL
-elif [ ${qpid_route_method} == "queue" ]; then
- print "queue add"
- $QPID_ROUTE_EXEC -t ssl queue add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY EXTERNAL
-elif [ ${qpid_route_method} == "route" ]; then
- print "route add"
- $QPID_ROUTE_EXEC -t ssl route add localhost:${DST_TCP_PORT} $TEST_HOSTNAME:${SRC_SSL_PORT} $EXCHANGE_NAME $ROUTING_KEY "" "" EXTERNAL
-else
- echo "unknown method: |${qpid_route_method}|"
- echo " choices are: dynamic|link|queue|route "
- halt_brokers
- exit 1
-fi
+n_messages=100
+./datagen --count ${n_messages} | ./sender --broker localhost --port ${SRC_TCP_PORT} --exchange ${EXCHANGE_NAME} --routing-key ${ROUTING_KEY} --mechanism ANONYMOUS
-# I don't know how to avoid this sleep yet. It has to come after route-creation
-# to avoid false negatives.
-sleep 5
-# This should work the same whether or not we are running a clustered test.
-# In the case of clustered tests, the status is not printed by qpid_route.
-# So in either case, I will look only at the transport field, which should be "ssl".
-print "check the link"
-link_status=$($QPID_ROUTE_EXEC link list localhost:${DST_TCP_PORT} | tail -1 | awk '{print $3}')
+#echo "-----------------------"
+#echo "Examine DST Broker"
+#echo "-----------------------"
+dst_message_count=`qpid-stat -q localhost:${DST_TCP_PORT} | grep sasl_fed_queue | awk '{print $2}'`
-halt_brokers
-sleep 1
+#echo "-----------------------"
+#echo "Asking brokers to quit."
+#echo "-----------------------"
+$QPIDD_EXEC --port ${SRC_TCP_PORT} --quit
+$QPIDD_EXEC --port ${DST_TCP_PORT} --quit
-if [ ! ${link_status} ]; then
- print "link_status is empty"
- print "result: fail"
- exit 2
-fi
-if [ ${link_status} == "ssl" ]; then
- print "result: good"
- # Only remove the tmp_root on success, to permit debugging.
- print "Removing temporary directory $tmp_root"
- rm -rf $tmp_root
+#echo "-----------------------"
+#echo "Removing temporary directory $tmp_root"
+#echo "-----------------------"
+rm -rf $tmp_root
+
+if [ "$dst_message_count" -eq "$n_messages" ]; then
+ #echo "good: |$dst_message_count| == |$n_messages|"
exit 0
+else
+ #echo "not ideal: |$dst_message_count| != |$n_messages|"
+ exit 1
fi
-print "link_status has a bad value: ${link_status}"
-print "result: fail"
-exit 3
+
+
diff --git a/cpp/src/tests/sasl_fed_ex_dynamic b/cpp/src/tests/sasl_fed_ex_dynamic
deleted file mode 100755
index c20b8d69a0..0000000000
--- a/cpp/src/tests/sasl_fed_ex_dynamic
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex dynamic
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_dynamic_cluster b/cpp/src/tests/sasl_fed_ex_dynamic_cluster
deleted file mode 100755
index b0cceccecb..0000000000
--- a/cpp/src/tests/sasl_fed_ex_dynamic_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source $srcdir/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex dynamic cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_link b/cpp/src/tests/sasl_fed_ex_link
deleted file mode 100755
index 7b232d4874..0000000000
--- a/cpp/src/tests/sasl_fed_ex_link
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex link
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_link_cluster b/cpp/src/tests/sasl_fed_ex_link_cluster
deleted file mode 100755
index 4139300b12..0000000000
--- a/cpp/src/tests/sasl_fed_ex_link_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source $srcdir/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex link cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_queue b/cpp/src/tests/sasl_fed_ex_queue
deleted file mode 100755
index be0c10cf63..0000000000
--- a/cpp/src/tests/sasl_fed_ex_queue
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex queue
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_queue_cluster b/cpp/src/tests/sasl_fed_ex_queue_cluster
deleted file mode 100755
index f251420e08..0000000000
--- a/cpp/src/tests/sasl_fed_ex_queue_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source ${srcdir}/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex queue cluster
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_route b/cpp/src/tests/sasl_fed_ex_route
deleted file mode 100755
index dd5c4f3cac..0000000000
--- a/cpp/src/tests/sasl_fed_ex_route
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-
-${srcdir}/sasl_fed_ex route
-
-
diff --git a/cpp/src/tests/sasl_fed_ex_route_cluster b/cpp/src/tests/sasl_fed_ex_route_cluster
deleted file mode 100755
index a5d1542def..0000000000
--- a/cpp/src/tests/sasl_fed_ex_route_cluster
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-
-source ./test_env.sh
-source ${srcdir}/ais_check
-
-with_ais_group ${srcdir}/sasl_fed_ex route cluster
-
-
diff --git a/cpp/src/tests/sasl_no_dir b/cpp/src/tests/sasl_no_dir
deleted file mode 100755
index 15a36014bb..0000000000
--- a/cpp/src/tests/sasl_no_dir
+++ /dev/null
@@ -1,218 +0,0 @@
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-source ./test_env.sh
-
-script_name=`basename $0`
-
-# This minimum value corresponds to sasl version 2.1.22
-minimum_sasl_version=131350
-
-sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-
-# This test is necessary because this sasl version is the first one that permits
-# redirection of the sasl config file path.
-if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
- echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
- exit 0
-fi
-
-
-sasl_config_dir=$builddir/sasl_config
-
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-
-my_random_number=$RANDOM
-tmp_root=/tmp/sasl_fed_$my_random_number
-mkdir -p $tmp_root
-
-
-LOG_FILE=$tmp_root/qpidd.log
-
-# If you want to see this test fail, just comment out this 'mv' command.
-print "Moving sasl configuration dir."
-mv ${sasl_config_dir} ${sasl_config_dir}-
-
-
-#--------------------------------------------------
-print " Starting broker"
-#--------------------------------------------------
-$QPIDD_EXEC \
- -p 0 \
- --no-data-dir \
- --auth=yes \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --log-to-file ${LOG_FILE} \
- --sasl-config=$sasl_config_dir \
- -d 2> /dev/null 1> $tmp_root/broker_port
-
-
-
-# If it works right, the output will look something like this: ( two lines long )
-# Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-# 2011-10-13 14:07:00 critical qpidd.cpp:83: Unexpected error: Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-
-result=`cat ${LOG_FILE} | grep "sasl_set_path failed: no such directory" | wc -l `
-
-#--------------------------------------------------
-print "Restore the Sasl config dir to its original place."
-#--------------------------------------------------
-mv ${sasl_config_dir}- ${sasl_config_dir}
-
-if [ "2" -eq ${result} ]; then
- print "result: success"
- rm -rf $tmp_root
- exit 0
-fi
-
-
-# If this test fails, the broker is still alive.
-# Kill it.
-broker_port=`cat $tmp_root/broker_port`
-#--------------------------------------------------
-print "Asking broker to quit."
-#--------------------------------------------------
-$QPIDD_EXEC --port $broker_port --quit
-
-rm -rf $tmp_root
-
-print "result: fail"
-exit 1
-
-#! /bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-source ./test_env.sh
-
-script_name=`basename $0`
-
-# This minimum value corresponds to sasl version 2.1.22
-minimum_sasl_version=131350
-
-sasl_version=`$QPID_TEST_EXEC_DIR/sasl_version`
-
-# This test is necessary because this sasl version is the first one that permits
-# redirection of the sasl config file path.
-if [ "$sasl_version" -lt "$minimum_sasl_version" ]; then
- echo "sasl_fed: must have sasl version 2.1.22 or greater. ( Integer value: $minimum_sasl_version ) Version is: $sasl_version"
- exit 0
-fi
-
-
-sasl_config_dir=$builddir/sasl_config
-
-
-# Debugging print. --------------------------
-debug=
-function print {
- if [ "$debug" ]; then
- echo "${script_name}: $1"
- fi
-}
-
-
-my_random_number=$RANDOM
-tmp_root=/tmp/sasl_fed_$my_random_number
-mkdir -p $tmp_root
-
-
-LOG_FILE=$tmp_root/qpidd.log
-
-# If you want to see this test fail, just comment out this 'mv' command.
-print "Moving sasl configuration dir."
-mv ${sasl_config_dir} ${sasl_config_dir}-
-
-
-#--------------------------------------------------
-print " Starting broker"
-#--------------------------------------------------
-$QPIDD_EXEC \
- -p 0 \
- --no-data-dir \
- --auth=yes \
- --mgmt-enable=yes \
- --log-enable info+ \
- --log-source yes \
- --log-to-file ${LOG_FILE} \
- --sasl-config=$sasl_config_dir \
- -d 2> /dev/null 1> $tmp_root/broker_port
-
-
-
-# If it works right, the output will look something like this: ( two lines long )
-# Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-# 2011-10-13 14:07:00 critical qpidd.cpp:83: Unexpected error: Daemon startup failed: SASL: sasl_set_path failed: no such directory: /home/mick/trunk/qpid/cpp/src/tests/sasl_config (qpid/broker/SaslAuthenticator.cpp:112)
-
-result=`cat ${LOG_FILE} | grep "sasl_set_path failed: no such directory" | wc -l `
-
-#--------------------------------------------------
-print "Restore the Sasl config dir to its original place."
-#--------------------------------------------------
-mv ${sasl_config_dir}- ${sasl_config_dir}
-
-if [ "2" -eq ${result} ]; then
- print "result: success"
- rm -rf $tmp_root
- exit 0
-fi
-
-
-# If this test fails, the broker is still alive.
-# Kill it.
-broker_port=`cat $tmp_root/broker_port`
-#--------------------------------------------------
-print "Asking broker to quit."
-#--------------------------------------------------
-$QPIDD_EXEC --port $broker_port --quit
-
-rm -rf $tmp_root
-
-print "result: fail"
-exit 1
-
diff --git a/cpp/src/tests/sasl_test_setup.sh b/cpp/src/tests/sasl_test_setup.sh
index 3e69c0f02b..6395ba6ec3 100755
--- a/cpp/src/tests/sasl_test_setup.sh
+++ b/cpp/src/tests/sasl_test_setup.sh
@@ -30,7 +30,6 @@ pwcheck_method: auxprop
auxprop_plugin: sasldb
sasldb_path: $PWD/sasl_config/qpidd.sasldb
sql_select: dummy select
-mech_list: ANONYMOUS PLAIN DIGEST-MD5 EXTERNAL
EOF
# Populate temporary sasl db.
diff --git a/cpp/src/tests/sender.cpp b/cpp/src/tests/sender.cpp
index 063b5e87dc..9850e851da 100644
--- a/cpp/src/tests/sender.cpp
+++ b/cpp/src/tests/sender.cpp
@@ -120,7 +120,7 @@ void Sender::execute(AsyncSession& session, bool isRetry)
string data;
while (getline(std::cin, data)) {
message.setData(data);
- //message.getHeaders().setInt("SN", ++sent);
+ message.getHeaders().setInt("SN", ++sent);
string matchKey;
if (lvqMatchValues && getline(lvqMatchValues, matchKey)) {
message.getHeaders().setString(QueueOptions::strLVQMatchProperty, matchKey);
diff --git a/cpp/src/tests/ssl_test b/cpp/src/tests/ssl_test
index 2a56c0b80e..04584f169d 100755
--- a/cpp/src/tests/ssl_test
+++ b/cpp/src/tests/ssl_test
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -47,13 +47,9 @@ delete_certs() {
fi
}
-COMMON_OPTS="--daemon --no-data-dir --no-module-dir --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption"
+COMMON_OPTS="--daemon --no-data-dir --no-module-dir --auth no --config $CONFIG --load-module $SSL_LIB --ssl-cert-db $CERT_DIR --ssl-cert-password-file $CERT_PW_FILE --ssl-cert-name $TEST_HOSTNAME --require-encryption"
start_broker() { # $1 = extra opts
- ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS --auth no $1;
-}
-
-start_authenticating_broker() {
- ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS --ssl-sasl-no-dict --ssl-require-client-authentication --auth yes;
+ ../qpidd --transport ssl --port 0 --ssl-port 0 $COMMON_OPTS $1;
}
stop_brokers() {
@@ -97,7 +93,7 @@ test "$MSG" = "hello" || { echo "receive failed '$MSG' != 'hello'"; exit 1; }
#### Client Authentication tests
-PORT2=`start_authenticating_broker` || error "Could not start broker"
+PORT2=`start_broker --ssl-require-client-authentication` || error "Could not start broker"
echo "Running SSL client authentication test on port $PORT2"
URL=amqp:ssl:$TEST_HOSTNAME:$PORT2
@@ -125,7 +121,7 @@ pick_port() {
echo $PICK
}
ssl_cluster_broker() { # $1 = port
- ../qpidd $COMMON_OPTS --auth no --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1 --port 0 --ssl-port $1 --transport ssl > /dev/null
+ ../qpidd $COMMON_OPTS --load-module $CLUSTER_LIB --cluster-name ssl_test.$HOSTNAME.$$ --cluster-url amqp:ssl:$TEST_HOSTNAME:$1 --port 0 --ssl-port $1 --transport ssl > /dev/null
# Wait for broker to be ready
qpid-ping -Pssl -b $TEST_HOSTNAME -qp $1 || { echo "Cannot connect to broker on $1"; exit 1; }
echo "Running SSL cluster broker on port $1"
diff --git a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp b/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
index 024f20b147..a0b665db73 100644
--- a/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
+++ b/cpp/src/tests/windows/DisableWin32ErrorWindows.cpp
@@ -26,9 +26,7 @@
// include this file with the executable being built. If the default
// behaviors are desired, don't include this file in the build.
-#if defined(_MSC_VER)
#include <crtdbg.h>
-#endif
#include <windows.h>
#include <iostream>
@@ -55,14 +53,12 @@ static redirect_errors_to_stderr block;
redirect_errors_to_stderr::redirect_errors_to_stderr()
{
-#if defined(_MSC_VER)
_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
-#endif
// Prevent the system from displaying the critical-error-handler
// and can't-open-file message boxes.
diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp
index 60a31901bd..884cdc366b 100644
--- a/cpp/src/windows/QpiddBroker.cpp
+++ b/cpp/src/windows/QpiddBroker.cpp
@@ -21,12 +21,12 @@
#include "config.h"
#include "qpidd.h"
+#include "SCM.h"
#include "qpid/Exception.h"
#include "qpid/Options.h"
#include "qpid/Plugin.h"
#include "qpid/sys/IntegerTypes.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/windows/SCM.h"
#include "qpid/broker/Broker.h"
#include <iostream>
@@ -147,7 +147,7 @@ NamedSharedMemory<T>::NamedSharedMemory(const std::string& n) :
name(n),
memory(NULL),
data(0)
-{}
+{};
template <typename T>
NamedSharedMemory<T>::~NamedSharedMemory() {
@@ -155,7 +155,7 @@ NamedSharedMemory<T>::~NamedSharedMemory() {
::UnmapViewOfFile(data);
if (memory != NULL)
::CloseHandle(memory);
-}
+};
template <typename T>
T& NamedSharedMemory<T>::create() {
@@ -291,12 +291,12 @@ struct ServiceOptions : public qpid::Options {
depends("")
{
addOptions()
- ("install", qpid::optValue(install), "Install as service.")
- ("start-type", qpid::optValue(startType, "auto|demand|disabled"), "Service start type.\nApplied at install time only.")
+ ("install", qpid::optValue(install), "Install as service")
+ ("start-type", qpid::optValue(startType, "auto|demand|disabled"), "Service start type\nApplied at install time only.")
("arguments", qpid::optValue(startArgs, "COMMAND LINE ARGS"), "Arguments to pass when service auto-starts")
- ("account", qpid::optValue(account, "ACCOUNT"), "Account to run as.\nApplied at install time only.")
- ("password", qpid::optValue(password, "PASSWORD"), "Account password, if needed.\nApplied at install time only.")
- ("depends", qpid::optValue(depends, "(comma delimited list)"), "Names of services that must start before this service.\nApplied at install time only.")
+ ("account", qpid::optValue(account, "(LocalService)"), "Account to run as, default is LocalService\nApplied at install time only.")
+ ("password", qpid::optValue(password, "PASSWORD"), "Account password, if needed\nApplied at install time only.")
+ ("depends", qpid::optValue(depends, "(comma delimited list)"), "Names of services that must start before this service\nApplied at install time only.")
("start", qpid::optValue(start), "Start the service.")
("stop", qpid::optValue(stop), "Stop the service.")
("uninstall", qpid::optValue(uninstall), "Uninstall the service.");
diff --git a/cpp/src/windows/SCM.cpp b/cpp/src/windows/SCM.cpp
new file mode 100644
index 0000000000..232bb04c17
--- /dev/null
+++ b/cpp/src/windows/SCM.cpp
@@ -0,0 +1,332 @@
+/*
+ *
+ * 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 "qpid/log/Statement.h"
+#include "qpid/sys/windows/check.h"
+#include "SCM.h"
+
+#pragma comment(lib, "advapi32.lib")
+
+namespace {
+
+// Container that will close a SC_HANDLE upon destruction.
+class AutoServiceHandle {
+public:
+ AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {}
+ ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); }
+ void release() { h = NULL; }
+ void reset(SC_HANDLE newHandle)
+ {
+ if (h != NULL)
+ ::CloseServiceHandle(h);
+ h = newHandle;
+ }
+ operator SC_HANDLE() const { return h; }
+
+private:
+ SC_HANDLE h;
+};
+
+}
+
+namespace qpid {
+namespace windows {
+
+SCM::SCM() : scmHandle(NULL)
+{
+}
+
+SCM::~SCM()
+{
+ if (NULL != scmHandle)
+ ::CloseServiceHandle(scmHandle);
+}
+
+/**
+ * Install this executable as a service
+ */
+void SCM::install(const string& serviceName,
+ const string& serviceDesc,
+ const string& args,
+ DWORD startType,
+ const string& account,
+ const string& password,
+ const string& depends)
+{
+ // Handle dependent service name list; Windows wants a set of nul-separated
+ // names ending with a double nul.
+ string depends2 = depends;
+ if (!depends2.empty()) {
+ // CDL to null delimiter w/ trailing double null
+ size_t p = 0;
+ while ((p = depends2.find_first_of( ',', p)) != string::npos)
+ depends2.replace(p, 1, 1, '\0');
+ depends2.push_back('\0');
+ depends2.push_back('\0');
+ }
+
+#if 0
+ // I'm nervous about adding a user/password check here. Is this a
+ // potential attack vector, letting users check passwords without
+ // control? -Steve Huston, Feb 24, 2011
+
+ // Validate account, password
+ HANDLE hToken = NULL;
+ bool logStatus = false;
+ if (!account.empty() && !password.empty() &&
+ !(logStatus = ::LogonUserA(account.c_str(),
+ "",
+ password.c_str(),
+ LOGON32_LOGON_NETWORK,
+ LOGON32_PROVIDER_DEFAULT,
+ &hToken ) != 0))
+ std::cout << "warning: supplied account & password failed with LogonUser." << std::endl;
+ if (logStatus)
+ ::CloseHandle(hToken);
+#endif
+
+ // Get fully qualified .exe name
+ char myPath[MAX_PATH];
+ DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH);
+ QPID_WINDOWS_CHECK_NOT(myPathLength, 0);
+ string imagePath(myPath, myPathLength);
+ if (!args.empty())
+ imagePath += " " + args;
+
+ // Ensure there's a handle to the SCM database.
+ openSvcManager();
+
+ // Create the service
+ SC_HANDLE svcHandle;
+ svcHandle = ::CreateService(scmHandle, // SCM database
+ serviceName.c_str(), // name of service
+ serviceDesc.c_str(), // name to display
+ SERVICE_ALL_ACCESS, // desired access
+ SERVICE_WIN32_OWN_PROCESS, // service type
+ startType, // start type
+ SERVICE_ERROR_NORMAL, // error cntrl type
+ imagePath.c_str(), // path to service's binary w/ optional arguments
+ NULL, // no load ordering group
+ NULL, // no tag identifier
+ depends2.empty() ? NULL : depends2.c_str(),
+ account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem
+ password.empty() ? NULL : password.c_str()); // password, or NULL for none
+ QPID_WINDOWS_CHECK_NULL(svcHandle);
+ ::CloseServiceHandle(svcHandle);
+ QPID_LOG(info, "Service installed successfully");
+}
+
+/**
+ *
+ */
+void SCM::uninstall(const string& serviceName)
+{
+ // Ensure there's a handle to the SCM database.
+ openSvcManager();
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ DELETE));
+ QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc);
+ QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0);
+ QPID_LOG(info, "Service deleted successfully.");
+}
+
+/**
+ * Attempt to start the service.
+ */
+void SCM::start(const string& serviceName)
+{
+ // Ensure we have a handle to the SCM database.
+ openSvcManager();
+
+ // Get a handle to the service.
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ SERVICE_ALL_ACCESS));
+ QPID_WINDOWS_CHECK_NULL(svc);
+
+ // Check the status in case the service is not stopped.
+ DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOP_PENDING)
+ throw qpid::Exception("Timed out waiting for running service to stop.");
+
+ // Attempt to start the service.
+ QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0);
+
+ QPID_LOG(info, "Service start pending...");
+
+ // Check the status until the service is no longer start pending.
+ state = waitForStateChangeFrom(svc, SERVICE_START_PENDING);
+ // Determine whether the service is running.
+ if (state == SERVICE_RUNNING) {
+ QPID_LOG(info, "Service started successfully");
+ }
+ else {
+ throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state));
+ }
+}
+
+/**
+ *
+ */
+void SCM::stop(const string& serviceName)
+{
+ // Ensure a handle to the SCM database.
+ openSvcManager();
+
+ // Get a handle to the service.
+ AutoServiceHandle svc(::OpenService(scmHandle,
+ serviceName.c_str(),
+ SERVICE_STOP | SERVICE_QUERY_STATUS |
+ SERVICE_ENUMERATE_DEPENDENTS));
+ QPID_WINDOWS_CHECK_NULL(svc);
+
+ // Make sure the service is not already stopped; if it's stop-pending,
+ // wait for it to finalize.
+ DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOPPED) {
+ QPID_LOG(info, "Service is already stopped");
+ return;
+ }
+
+ // If the service is running, dependencies must be stopped first.
+ std::auto_ptr<ENUM_SERVICE_STATUS> deps;
+ DWORD numDeps = getDependentServices(svc, deps);
+ for (DWORD i = 0; i < numDeps; i++)
+ stop(deps.get()[i].lpServiceName);
+
+ // Dependents stopped; send a stop code to the service.
+ SERVICE_STATUS_PROCESS ssp;
+ if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
+ throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " <<
+ qpid::sys::strError(::GetLastError())));
+
+ // Wait for the service to stop.
+ state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
+ if (state == SERVICE_STOPPED)
+ QPID_LOG(info, QPID_MSG("Service " << serviceName <<
+ " stopped successfully."));
+}
+
+/**
+ *
+ */
+void SCM::openSvcManager()
+{
+ if (NULL != scmHandle)
+ return;
+
+ scmHandle = ::OpenSCManager(NULL, // local computer
+ NULL, // ServicesActive database
+ SC_MANAGER_ALL_ACCESS); // Rights
+ QPID_WINDOWS_CHECK_NULL(scmHandle);
+}
+
+DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState)
+{
+ SERVICE_STATUS_PROCESS ssStatus;
+ DWORD bytesNeeded;
+ DWORD waitTime;
+ if (!::QueryServiceStatusEx(svc, // handle to service
+ SC_STATUS_PROCESS_INFO, // information level
+ (LPBYTE)&ssStatus, // address of structure
+ sizeof(ssStatus), // size of structure
+ &bytesNeeded)) // size needed if buffer is too small
+ throw QPID_WINDOWS_ERROR(::GetLastError());
+
+ // Save the tick count and initial checkpoint.
+ DWORD startTickCount = ::GetTickCount();
+ DWORD oldCheckPoint = ssStatus.dwCheckPoint;
+
+ // Wait for the service to change out of the noted state.
+ while (ssStatus.dwCurrentState == originalState) {
+ // Do not wait longer than the wait hint. A good interval is
+ // one-tenth of the wait hint but not less than 1 second
+ // and not more than 10 seconds.
+ waitTime = ssStatus.dwWaitHint / 10;
+ if (waitTime < 1000)
+ waitTime = 1000;
+ else if (waitTime > 10000)
+ waitTime = 10000;
+
+ ::Sleep(waitTime);
+
+ // Check the status until the service is no longer stop pending.
+ if (!::QueryServiceStatusEx(svc,
+ SC_STATUS_PROCESS_INFO,
+ (LPBYTE) &ssStatus,
+ sizeof(ssStatus),
+ &bytesNeeded))
+ throw QPID_WINDOWS_ERROR(::GetLastError());
+
+ if (ssStatus.dwCheckPoint > oldCheckPoint) {
+ // Continue to wait and check.
+ startTickCount = ::GetTickCount();
+ oldCheckPoint = ssStatus.dwCheckPoint;
+ } else {
+ if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint)
+ break;
+ }
+ }
+ return ssStatus.dwCurrentState;
+}
+
+/**
+ * Get the services that depend on @arg svc. All dependent service info
+ * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps.
+ *
+ * @retval The number of dependent services.
+ */
+DWORD SCM::getDependentServices(SC_HANDLE svc,
+ std::auto_ptr<ENUM_SERVICE_STATUS>& deps)
+{
+ DWORD bytesNeeded;
+ DWORD numEntries;
+
+ // Pass a zero-length buffer to get the required buffer size.
+ if (::EnumDependentServices(svc,
+ SERVICE_ACTIVE,
+ 0,
+ 0,
+ &bytesNeeded,
+ &numEntries)) {
+ // If the Enum call succeeds, then there are no dependent
+ // services, so do nothing.
+ return 0;
+ }
+
+ if (::GetLastError() != ERROR_MORE_DATA)
+ throw QPID_WINDOWS_ERROR((::GetLastError()));
+
+ // Allocate a buffer for the dependencies.
+ deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded]));
+ // Enumerate the dependencies.
+ if (!::EnumDependentServices(svc,
+ SERVICE_ACTIVE,
+ deps.get(),
+ bytesNeeded,
+ &bytesNeeded,
+ &numEntries))
+ throw QPID_WINDOWS_ERROR((::GetLastError()));
+ return numEntries;
+}
+
+} } // namespace qpid::windows
diff --git a/cpp/src/windows/SCM.h b/cpp/src/windows/SCM.h
new file mode 100644
index 0000000000..bdc73bc210
--- /dev/null
+++ b/cpp/src/windows/SCM.h
@@ -0,0 +1,109 @@
+#ifndef WINDOWS_SCM_H
+#define WINDOWS_SCM_H
+
+/*
+ *
+ * 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 <memory>
+#include <string>
+using std::string;
+
+#ifdef UNICODE
+#undef UNICODE
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+namespace qpid {
+namespace windows {
+
+/**
+ * @class SCM
+ *
+ * Access the Windows Service Control Manager.
+ */
+class SCM
+{
+public:
+ SCM();
+ ~SCM();
+
+ /**
+ * Install this executable as a service
+ *
+ * @param serviceName The name of the service
+ * @param serviceDesc Description of the service's purpose
+ * @param args The argument list to pass into the service
+ * @param startType The start type: SERVICE_DEMAND_START,
+ * SERVICE_AUTO_START, SERVICE_DISABLED
+ * @param account If not empty, the account name to install this
+ * service under
+ * @param password If not empty, the account password to install this
+ * service with
+ * @param depends If not empty, a comma delimited list of services
+ * that must start before this one
+ */
+ void install(const string& serviceName,
+ const string& serviceDesc,
+ const string& args,
+ DWORD startType = SERVICE_DEMAND_START,
+ const string& account = "NT AUTHORITY\\LocalSystem",
+ const string& password = "",
+ const string& depends = "");
+
+ /**
+ * Uninstall this executable as a service
+ *
+ * @param serviceName the name of the service
+ */
+ void uninstall(const string& serviceName);
+
+ /**
+ * Start the specified service
+ *
+ * @param serviceName the name of the service
+ */
+ void start(const string& serviceName);
+
+ /**
+ * Stop the specified service
+ *
+ * @param serviceName the name of the service
+ */
+ void stop(const string &serviceName);
+
+private:
+ SC_HANDLE scmHandle;
+
+ void openSvcManager();
+ DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState);
+ DWORD getDependentServices(SC_HANDLE svc,
+ std::auto_ptr<ENUM_SERVICE_STATUS>& deps);
+
+};
+
+}} // namespace qpid::windows
+
+#endif /* #ifndef WINDOWS_SCM_H */
diff --git a/cpp/src/windows/resources/template-resource.rc b/cpp/src/windows/resources/template-resource.rc
index 8ca0a90890..725d1c9391 100644
--- a/cpp/src/windows/resources/template-resource.rc
+++ b/cpp/src/windows/resources/template-resource.rc
@@ -24,7 +24,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
-#include "windows.h"
+#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
diff --git a/cpp/src/xml.mk b/cpp/src/xml.mk
index baf3803647..0d700fcc03 100644
--- a/cpp/src/xml.mk
+++ b/cpp/src/xml.mk
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-dmoduleexec_LTLIBRARIES += xml.la
+dmodule_LTLIBRARIES += xml.la
xml_la_SOURCES = \
qpid/xml/XmlExchange.cpp \
diff --git a/cpp/xml/cluster.xml b/cpp/xml/cluster.xml
index 899625f5ec..be1c1f868c 100644
--- a/cpp/xml/cluster.xml
+++ b/cpp/xml/cluster.xml
@@ -8,9 +8,9 @@
- 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
@@ -78,6 +78,10 @@
<field name="left" type="vbin16"/> <!-- packed member-id array -->
</control>
+ <control name="message-expired" code="0x12">
+ <field name="id" type="uint64"/>
+ </control>
+
<domain name="error-type" type="uint8" label="Types of error">
<enum>
<choice name="none" value="0"/>
@@ -85,7 +89,7 @@
<choice name="connection" value="2"/>
</enum>
</domain>
-
+
<!-- Check for error consistency across the cluster -->
<control name="error-check" code="0x14">
<field name="type" type="error-type"/>
@@ -112,11 +116,6 @@
<field name="message" type="vbin32"/>
</control>
- <!-- Update the cluster time -->
- <control name="clock" code="0x22">
- <field name="time" type="uint64"/>
- </control>
-
</class>
<!-- Controls associated with a specific connection. -->
@@ -150,7 +149,7 @@
<!-- Abort a connection that is sending invalid data. -->
<control name="abort" code="0x4"/>
-
+
<!-- Update controls. Sent to a new broker in joining mode.
A connection is updated as followed:
- send the shadow's management ID in shadow-perpare on the update connection
@@ -184,7 +183,7 @@
<field name="position" type="sequence-no"/>
<field name="tag" type="str8"/>
<field name="id" type="sequence-no"/>
- <field name="acquired" type="bit"/> <!--If not set, message is on update queue. -->
+ <field name="acquired" type="bit"/> <!--If not set, message follows. -->
<field name="accepted" type="bit"/>
<field name="cancelled" type="bit"/>
<field name="completed" type="bit"/>
@@ -193,9 +192,9 @@
<field name="enqueued" type="bit"/>
<field name="credit" type="uint32"/>
</control>
-
+
<!-- Tx transaction state. -->
- <control name="tx-start" code="0x12"/>
+ <control name="tx-start" code="0x12"/>
<control name="tx-accept" code="0x13"> <field name="commands" type="sequence-set"/> </control>
<control name="tx-dequeue" code="0x14"> <field name="queue" type="str8"/> </control>
<control name="tx-enqueue" code="0x15"> <field name="queue" type="str8"/> </control>
@@ -205,37 +204,13 @@
</control>
<control name="tx-end" code="0x17"/>
<control name="accumulated-ack" code="0x18"> <field name="commands" type="sequence-set"/> </control>
-
+
<!-- Consumers in the connection's output task -->
<control name="output-task" code="0x19">
<field name="channel" type="uint16"/>
<field name="name" type="str8"/>
</control>
- <!-- Dtx transaction state. -->
- <control name="dtx-start" code="0x1A">
- <field name="xid" type="str16"/>
- <field name="ended" type="bit"/>
- <field name="suspended" type="bit"/>
- <field name="failed" type="bit"/>
- <field name="expired" type="bit"/>
- </control>
- <control name="dtx-end" code="0x1B"/>
-
- <control name="dtx-ack" code="0x1C"/>
-
- <control name="dtx-buffer-ref" code="0x1D">
- <field name="xid" type="str16"/>
- <field name="index" type="uint32"/>
- <field name="suspended" type="bit"/>
- </control>
-
- <control name="dtx-work-record" code="0x1E">
- <field name="xid" type="str16"/>
- <field name="prepared" type="bit"/>
- <field name="timeout" type="uint32"/>
- </control>
-
<!-- Complete a session state update. -->
<control name="session-state" code="0x1F">
<!-- Target session deduced from channel number. -->
@@ -247,7 +222,6 @@
<field name="received" type="sequence-no"/> <!-- Received up to here (>= expected) -->
<field name="unknown-completed" type="sequence-set"/> <!-- Completed but not known to peer. -->
<field name="received-incomplete" type="sequence-set"/> <!-- Received and incomplete -->
- <field name="dtx-selected" type="bit"/>
</control>
<!-- Complete a shadow connection update. -->
@@ -278,6 +252,10 @@
<!-- Replicate encoded exchanges/queues. -->
<control name="exchange" code="0x31"><field name="encoded" type="str32"/></control>
+ <control name="queue" code="0x32"><field name="encoded" type="str32"/></control>
+
+ <!-- Set expiry-id for subsequent messages. -->
+ <control name="expiry-id" code="0x33"><field name="expiry-id" type="uint64"/></control>
<!-- Add a listener to a queue -->
<control name="add-queue-listener" code="0x34">
@@ -304,26 +282,6 @@
<field name="position" type="uint8"/>
<field name="count" type="uint8"/>
</control>
-
- <!-- Replicate a QueueObserver for a given queue. -->
- <control name="queue-observer-state" code="0x39">
- <field name="queue" type="str8"/>
- <field name="observer-id" type="str8"/>
- <field name="state" type="map"/> <!-- "name"=value -->
- </control>
-
- <!-- Update the cluster time -->
- <control name="clock" code="0x40">
- <field name="time" type="uint64"/>
- </control>
-
- <!-- Update a queue's dequeue rate -->
- <control name="queue-dequeue-since-purge-state" code="0x41">
- <field name="queue" type="str8"/>
- <field name="dequeueSincePurge" type="uint32"/>
- </control>
-
-
</class>
</amqp>
diff --git a/doc/book/build-book.sh b/doc/book/build-book.sh
index 46192907e6..74a2ec963d 100755
--- a/doc/book/build-book.sh
+++ b/doc/book/build-book.sh
@@ -29,12 +29,6 @@
#
########################################################################
-# DOCBOOK XSL STYLESHEET LOCATION
-# Fedora, RHEL:
-DOCBOOK_XSL=/usr/share/sgml/docbook/xsl-stylesheets
-# Ubuntu:
-# DOCBOOK_XSL=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh
-
rm -rf build/$1
mkdir -p build/$1
mkdir -p build/$1/html-single
@@ -44,16 +38,16 @@ cp -r src/images build/$1/html-single
cp -r src/images build/$1/html
# Create single-page .html
-xsltproc --xinclude --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 ${DOCBOOK_XSL}/html/docbook.xsl src/$1.xml >build/$1/html-single/$1.html
+xsltproc --xinclude --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 /usr/share/sgml/docbook/xsl-stylesheets/html/docbook.xsl src/$1.xml >build/$1/html-single/$1.html
# Create chunked .html
INFILE=$(readlink -f src/$1.xml)
pushd build/$1/html
-xsltproc --xinclude --stringparam chunk.section.depth 1 --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 ${DOCBOOK_XSL}/html/chunk.xsl $INFILE
+xsltproc --xinclude --stringparam chunk.section.depth 1 --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 /usr/share/sgml/docbook/xsl-stylesheets/html/chunk.xsl $INFILE
popd
# Create the .fo
-xsltproc --xinclude --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 ${DOCBOOK_XSL}/fo/docbook.xsl src/$1.xml >build/$1/pdf/$1.fo
+xsltproc --xinclude --stringparam section.autolabel 1 --stringparam callout.graphics 0 --stringparam callout.unicode 0 --stringparam section.label.includes.component.label 1 /usr/share/sgml/docbook/xsl-stylesheets/fo/docbook.xsl src/$1.xml >build/$1/pdf/$1.fo
# Use Apache FOP to create the PDF
fop build/$1/pdf/$1.fo build/$1/pdf/$1.pdf
diff --git a/doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml b/doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml
index 10d83ec887..309492262d 100644
--- a/doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml
+++ b/doc/book/src/AMQP-Messaging-Broker-CPP-Book.xml
@@ -56,10 +56,8 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="LVQ.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="queue-state-replication.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Starting-a-cluster.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="producer-flow-control.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="AMQP-Compatibility.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Qpid-Interoperability-Documentation.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Using-message-groups.xml"/>
</chapter>
diff --git a/doc/book/src/AMQP-Messaging-Broker-CPP.xml b/doc/book/src/AMQP-Messaging-Broker-CPP.xml
index 92b474b0c0..b9c513e511 100644
--- a/doc/book/src/AMQP-Messaging-Broker-CPP.xml
+++ b/doc/book/src/AMQP-Messaging-Broker-CPP.xml
@@ -50,9 +50,7 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="LVQ.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="queue-state-replication.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Starting-a-cluster.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ACL.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="producer-flow-control.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Using-message-groups.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ACL.xml"/>
</chapter>
diff --git a/doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml b/doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml
index d50948e0cc..60f1a4103d 100644
--- a/doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml
+++ b/doc/book/src/Cheat-Sheet-for-configuring-Queue-Options.xml
@@ -65,16 +65,6 @@
</itemizedlist>
</para></listitem>
</itemizedlist>
-
- <para>
- The 0.10 C++ Broker supports the following additional Queue configuration options:
- </para>
- <itemizedlist>
- <listitem><para>
- <xref linkend="producer-flow-control"/>
- </para></listitem>
- </itemizedlist>
-
<section role="h3" id="CheatSheetforconfiguringQueueOptions-ApplyingQueueSizingConstraints"><title>
Applying Queue Sizing Constraints
</title>
diff --git a/doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml b/doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml
index 1ffd4b4050..c09923711d 100644
--- a/doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml
+++ b/doc/book/src/Configure-Java-Qpid-to-use-a-SSL-connection.xml
@@ -51,8 +51,8 @@
&lt;ssl&gt;
&lt;enabled&gt;true&lt;/enabled&gt;
&lt;sslOnly&gt;true&lt;/sslOnly&gt;
- &lt;keyStorePath&gt;/path/to/keystore.ks&lt;/keyStorePath&gt;
- &lt;keyStorePassword&gt;keystorepass&lt;/keyStorePassword&gt;
+ &lt;keystorePath&gt;/path/to/keystore.ks&lt;/keystorePath&gt;
+ &lt;keystorePassword&gt;keystorepass&lt;/keystorePassword&gt;
&lt;/ssl&gt;
</programlisting>
diff --git a/doc/book/src/Programming-In-Apache-Qpid.xml b/doc/book/src/Programming-In-Apache-Qpid.xml
index 4d72864cb1..3950b375da 100644
--- a/doc/book/src/Programming-In-Apache-Qpid.xml
+++ b/doc/book/src/Programming-In-Apache-Qpid.xml
@@ -1722,7 +1722,7 @@ try {
<row>
<entry>
- <literal>username</literal>
+ username
</entry>
<entry>
string
@@ -1733,7 +1733,7 @@ try {
</row>
<row>
<entry>
- <literal>password</literal>
+ password
</entry>
<entry>
string
@@ -1744,22 +1744,35 @@ try {
</row>
<row>
<entry>
- <literal>sasl_mechanisms</literal>
+ sasl-mechanism
</entry>
<entry>
string
</entry>
<entry>
- The specific SASL mechanisms to use with the python
+ The specific SASL mechanism to use with the c++
+ client when authenticating to the broker. Only a
+ single value can be specified at present. [C++ only].
+ </entry>
+ </row>
+ <row>
+ <entry>
+ sasl_mechanisms
+ </entry>
+ <entry>
+ string
+ </entry>
+ <entry>
+ The specific SASL mechanism to use with the python
client when authenticating to the broker. The value
- is a space separated list.
+ is a space separated list in order of preference. [Python only].
</entry>
</row>
<row>
<entry>
- <literal>reconnect</literal>
+ reconnect
</entry>
<entry>
boolean
@@ -1770,7 +1783,7 @@ try {
</row>
<row>
<entry>
- <literal>reconnect_timeout</literal>
+ <literal>reconnect_timeout&nbsp;[Python]</literal> <literal>reconnect-timeout&nbsp;[C++]</literal>
</entry>
<entry>
integer
@@ -1781,7 +1794,7 @@ try {
</row>
<row>
<entry>
- <literal>reconnect_limit</literal>
+ <literal>reconnect_limit&nbsp;[Python]</literal> <literal>reconnect-limit&nbsp;[C++]</literal>
</entry>
<entry>
integer
@@ -1792,7 +1805,7 @@ try {
</row>
<row>
<entry>
- <literal>reconnect_interval_min</literal>
+ <literal>reconnect_interval_min&nbsp;[Python]</literal> <literal>reconnect-interval-min&nbsp;[C++]</literal>
</entry>
<entry>
integer representing time in seconds
@@ -1803,7 +1816,7 @@ try {
</row>
<row>
<entry>
- <literal>reconnect_interval_max</literal>
+ <literal>reconnect_interval_max&nbsp;[Python]</literal> <literal>reconnect-interval-max&nbsp;[C++]</literal>
</entry>
<entry>
integer representing time in seconds
@@ -1814,7 +1827,7 @@ try {
</row>
<row>
<entry>
- <literal>reconnect_interval</literal>
+ <literal>reconnect_interval&nbsp;[Python]</literal> <literal>reconnect-interval&nbsp;[C++]</literal>
</entry>
<entry>
integer representing time in seconds
@@ -1826,7 +1839,7 @@ try {
<row>
<entry>
- <literal>heartbeat</literal>
+ heartbeat
</entry>
<entry>
integer representing time in seconds
@@ -1839,7 +1852,7 @@ try {
</row>
<row>
<entry>
- <literal>protocol</literal>
+ protocol
</entry>
<entry>
string
@@ -1850,7 +1863,7 @@ try {
</row>
<row>
<entry>
- <literal>tcp-nodelay</literal>
+ tcp-nodelay
</entry>
<entry>
boolean
@@ -3443,8 +3456,9 @@ log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
<entry>qpid.amqp.version</entry>
<entry>string</entry>
<entry>0-10</entry>
- <entry><para>Sets the AMQP version to be used - currently supports one of {0-8,0-9,0-91,0-10}.</para><para>The client will begin negotiation at the specified version and only negotiate downwards if the Broker does not support the specified version.</para></entry>
- </row>
+ <entry>Sets the AMQP version to be used - currently supports one of {0-8,0-9,0-91,0-10}</entry>
+ </row>
+
<row>
<entry>qpid.heartbeat</entry>
<entry>int</entry>
@@ -3609,20 +3623,15 @@ log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
<entry>qpid.transport</entry>
<entry>string</entry>
<entry>org.apache.qpid.transport.network.io.IoNetworkTransport</entry>
- <entry><para>The transport implementation to be used.</para><para>A user could specify an alternative transport mechanism that implements the <varname>org.apache.qpid.transport.network.NetworkTransport</varname> interface.</para></entry>
- </row>
- <row>
- <entry>qpid.sync_op_timeout</entry>
- <entry>long</entry>
- <entry>60000</entry>
- <entry><para>The length of time (in milliseconds) to wait for a synchronous operation to complete.</para><para>For compatibility with older clients, the synonym <varname>amqj.default_syncwrite_timeout</varname> is supported.</para></entry>
- </row>
+ <entry><para>The transport implementation to be used.</para><para>A user could specify an alternative transport mechanism that implements the <varname>org.apache.qpid.transport.network.NetworkTransport</varname> interface.</para></entry>
+ </row>
+
<row>
<entry>amqj.tcp_nodelay</entry>
<entry>boolean</entry>
<entry>false</entry>
- <entry><para>Sets the TCP_NODELAY property of the underlying socket.</para><para>This could also be set per connection as well (see connection paramters).</para></entry>
- </row>
+ <entry><para>Sets the TCP_NODELAY property of the underlying socket.</para><para>This could also be set per connection as well (see connection paramters).</para></entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/doc/book/src/Qpid-Java-FAQ.xml b/doc/book/src/Qpid-Java-FAQ.xml
index 2144d3a533..7a28703774 100644
--- a/doc/book/src/Qpid-Java-FAQ.xml
+++ b/doc/book/src/Qpid-Java-FAQ.xml
@@ -736,6 +736,35 @@ amqj.logging.level
</para>
<!--h3--></section>
+ <section role="h3" id="QpidJavaFAQ-HowdoIuseanInVMBrokerformyowntests-3F"><title>
+ How do I
+ use an InVM Broker for my own tests?
+ </title>
+
+ <para>
+ I would take a look at the testPassiveTTL in
+ <ulink url="https://svn.apache.org/repos/asf/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java">TimeToLiveTest.java</ulink>
+ </para><para>
+ The setUp and tearDown methods show how to correctly start up a
+ broker for InVM testing. If you write your tests using a file for
+ the JNDI you can then very easily swap between running your tests
+ InVM and against a real broker.
+ </para><para>
+ See our <xref linkend="How-to-Use-JNDI"/> on how to confgure it
+ </para><para>
+ Basically though you just need to set two System Properites:
+ </para><para>
+ java.naming.factory.initial =
+ org.apache.qpid.jndi.PropertiesFileInitialContextFactory
+ java.naming.provider.url = &lt;your JNDI file&gt;
+ </para><para>
+ and call getInitialContext() in your code.
+ </para><para>
+ You will of course need to have the broker libraries on your
+ class path for this to run.
+ </para>
+<!--h3--></section>
+
<section role="h3" id="QpidJavaFAQ-HowcanIinspectthecontentsofmyMessageStore-3F"><title>
How
can I inspect the contents of my MessageStore?
@@ -878,6 +907,31 @@ java.lang.NullPointerException
</para>
<!--h3--></section>
+ <section role="h3" id="QpidJavaFAQ-Clientkeepsthrowing-27Serverdidnotrespondinatimelyfashion-27-5Cerrorcode408-3ARequestTimeout-5C."><title>
+ Client keeps throwing 'Server did not respond in a timely
+ fashion' [error code 408: Request Timeout].
+ </title>
+
+ <para>
+ Certain operations wait for a response from the Server. One such
+ operations is commit. If the server does not respond to the
+ commit request within a set time a Request Timeout [error code:
+ 408] exception is thrown (Server did not respond in a timely
+ fashion). This is to ensure that a server that has hung does not
+ cause the client process to be come unresponsive.
+ </para><para>
+ However, it is possible that the server just needs a long time to
+ process a give request. For example, sending a large persistent
+ message when using a persistent store will take some time to a)
+ Transfer accross the network and b) to be fully written to disk.
+ </para><para>
+ These situations require that the default timeout value be
+ increased. A cilent <xref linkend="qpid_System-Properties"/> 'amqj.default_syncwrite_timeout' can be set
+ on the client to increase the wait time. The default in 0.5 is
+ 30000 (30s).
+ </para>
+<!--h3--></section>
+
<section role="h3" id="QpidJavaFAQ-CanauseTCPKEEPALIVEorAMQPheartbeatingtokeepmyconnectionopen-3F"><title>
Can a use TCP_KEEPALIVE or AMQP heartbeating to keep my
connection open?
diff --git a/doc/book/src/Security.xml b/doc/book/src/Security.xml
index 49abfbebca..77d10abf8c 100644
--- a/doc/book/src/Security.xml
+++ b/doc/book/src/Security.xml
@@ -1,25 +1,5 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<!--
-
- 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.
-
--->
<section id="chap-Messaging_User_Guide-Security">
<title>Security</title>
<para>
diff --git a/doc/book/src/System-Properties.xml b/doc/book/src/System-Properties.xml
index 40b823185f..d61673f234 100644
--- a/doc/book/src/System-Properties.xml
+++ b/doc/book/src/System-Properties.xml
@@ -135,7 +135,7 @@
<varlistentry>
- <term>qpid.sync_op_timeout</term>
+ <term>amqj.default_syncwrite_timeout</term>
<listitem>
<variablelist>
<varlistentry>
@@ -144,11 +144,12 @@
</varlistentry>
<varlistentry>
<term>Default</term>
- <listitem><para>60000</para></listitem>
+ <listitem><para>30000</para></listitem>
</varlistentry>
</variablelist>
- <para>The length of time (in milliseconds) to wait for a synchronous operation to complete.
- For compatibility with older clients, the synonym amqj.default_syncwrite_timeout is supported.</para>
+ <para> The number length of time in millisecond to wait
+ for a synchronous write to complete.
+ </para>
</listitem>
</varlistentry>
@@ -192,7 +193,7 @@
<varlistentry>
- <term>amqj.tcp_nodelay</term>
+ <term>amqj.tcpNoDelay</term>
<listitem>
<variablelist>
<varlistentry>
@@ -210,6 +211,65 @@
</varlistentry>
<varlistentry>
+ <term>amqj.sendBufferSize</term>
+ <listitem>
+ <variablelist>
+ <varlistentry>
+ <term>integer</term>
+ <listitem><para>Boolean</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Default</term>
+ <listitem><para>32768</para></listitem>
+ </varlistentry>
+ </variablelist>
+ <para>This is the default buffer sized created by Mina.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>amqj.receiveBufferSize</term>
+ <listitem>
+ <variablelist>
+ <varlistentry>
+ <term>Type</term>
+ <listitem><para>integer</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Default</term>
+ <listitem><para>32768</para></listitem>
+ </varlistentry>
+ </variablelist>
+ <para>This is the default buffer sized created by Mina.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>amqj.protocolprovider.class</term>
+ <listitem>
+ <variablelist>
+ <varlistentry>
+ <term>Type</term>
+ <listitem><para>String</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Default</term>
+ <listitem><para>org.apache.qpid.server.protocol.AMQPFastProtocolHandler</para></listitem>
+ </varlistentry>
+ </variablelist>
+ <para> This specifies the default IoHandlerAdapter that
+ represents the InVM broker. The IoHandlerAdapter must have
+ a constructor that takes a single Integer that represents
+ the InVM port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
<term>amqj.protocol.logging.level</term>
<listitem>
<variablelist>
diff --git a/doc/book/src/Using-message-groups.xml b/doc/book/src/Using-message-groups.xml
deleted file mode 100644
index 7de7fbb995..0000000000
--- a/doc/book/src/Using-message-groups.xml
+++ /dev/null
@@ -1,261 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-
--->
-
-<section id="Using-message-groups">
- <title>
- Using Message Groups
- </title>
-
- <section role="h2" id="usingmessagegroups-Overview">
- <title>
- Overview
- </title>
- <para>
- The broker allows messaging applications to classify a set of related messages as
- belonging to a group. This allows a message producer to indicate to the consumer
- that a group of messages should be considered a single logical operation with
- respect to the application.
- </para>
- <para>
- The broker can use this group identification to enforce policies controlling how
- messages from a given group can be distributed to consumers. For instance, the
- broker can be configured to guarantee all the messages from a particular group are
- processed in order across multiple consumers.
- </para>
- <para>
- For example, assume we have a shopping application that manages items in a virtual
- shopping cart. A user may add an item to their shopping cart, then change their
- mind and remove it. If the application sends an <emphasis>add</emphasis> message to the broker,
- immediately followed by a <emphasis>remove</emphasis> message, they will be queued in the proper
- order - <emphasis>add</emphasis>, followed by <emphasis>remove</emphasis>.
- </para>
- <para>
- However, if there are multiple consumers, it is possible that once a consumer
- acquires the <emphasis>add</emphasis> message, a different consumer may acquire the
- <emphasis>remove</emphasis> message. This allows both messages to be processed in parallel,
- which could result in a "race" where the <emphasis>remove</emphasis> operation is incorrectly
- performed before the <emphasis>add</emphasis> operation.
- </para>
- </section>
- <!--h2-->
- <section role="h2" id="usingmessagegroups-GroupingMessages">
- <title>
- Grouping Messages
- </title>
- <para>
- In order to group messages, the application would designate a particular
- application header as containing a message's <emphasis>group identifier</emphasis>. The group
- identifier stored in that header field would be a string value set by the message
- producer. Messages from the same group would have the same group identifier
- value. The key that identifies the header must also be known to the message
- consumers. This allows the consumers to determine a message's assigned group.
- </para>
- <para>
- The header that is used to hold the group identifier, as well as the values used
- as group identifiers, are totally under control of the application.
- </para>
- </section>
- <section role="h2" id="usingmessagegroups-BrokerRole">
- <title>
- The Role of the Broker
- </title>
- <para>
- The broker will apply the following processing on each grouped message:
- <itemizedlist>
- <listitem>Enqueue a received message on the destination queue.</listitem>
- <listitem>Determine the message's group by examining the message's group identifier header.</listitem>
- <listitem>Enforce <emphasis>consumption ordering</emphasis> among messages belonging to the same group.</listitem>
- </itemizedlist>
- <emphasis>Consumption ordering</emphasis> means that the broker will not allow outstanding
- unacknowledged messages to <emphasis>more than one consumer for a given group</emphasis>.
- </para>
- <para>
- This means that only one consumer can be processing messages from a particular
- group at a given time. When the consumer acknowledges all of its acquired
- messages, then the broker <emphasis>may</emphasis> pass the next message from that group to
- another consumer.
- </para>
- <para>
- Specifically, for any given group, the broker allows only the first N messages in
- the group to be available for delivery to a particular consumer. The value of N
- would be determined by the selected consumer's configured prefetch capacity. The
- broker blocks access to the remaining messages in that group by any other
- consumer. Once the selected consumer has acknowledged that first set of delivered
- messages, the broker allows the next messages in the group to be available for
- delivery. The next set of messages may be delivered to a different consumer.
- </para>
- <para>
- Note well that distinct message groups would not block each other from delivery.
- For example, assume a queue contains messages from two different message groups -
- say group "A" and group "B" - and they are enqueued such that "A"'s messages are
- in front of "B". If the first message of group "A" is in the process of being
- consumed by a client, then the remaining "A" messages are blocked, but the
- messages of the "B" group are available for consumption by other consumers - even
- though it is "behind" group "A" in the queue.
- </para>
- </section>
- <section role="h2" id="usingmessagegroups-ConsumerGuide">
- <title>
- Well Behaved Consumers
- </title>
- <para>
- In order to guarantee the ordering policy, the consuming application has to ensure
- that it has completely processed the data in a received message before accepting
- that message, as described in Section 2.6.2. Transfer of Responsibility, of the
- AMQP-0.10 specification.
- </para>
- <para>
- The term <emphasis>processed</emphasis> means that the application has finished updating all
- state related to the message that has been received.
- </para>
- <note>
- <title>Be Advised</title>
- <para>
- It is possible for a consumer to affect the ordering of grouped messages even
- when the broker is enforcing consumption order. This can be done by selectively
- acknowledging and releasing messages from the same group.
- </para>
- <para>
- Assume a consumer has received two messages from group "A", "A-1" and "A-2", in
- that order. If the consumer releases "A-1" then acknowledges "A-2", "A-1" will
- be put back onto the queue and "A-2" will be removed from the queue. This
- allows another consumer to acquire and process "A-1" <emphasis>after</emphasis> "A-2" has been
- processed.
- </para>
- <para>
- Under some application-defined circumstances, this may be acceptable behavior.
- However, if order must be preserved, the client should either release <emphasis>all</emphasis>
- currently held messages, or discard the target message using reject.
- </para>
- </note>
- </section>
- <!--h2-->
- <section role="h2" id="usingmessagegroups-BrokerConfig">
- <title>
- Broker Configuration
- </title>
- <para>
- In order for the broker to determine a message's group, the key for the header
- that contains the group identifier must be provided to the broker via
- configuration. This is done on a per-queue basis, when the queue is first
- configured.
- </para>
- <para>
- This means that message group classification is determined by the message's destination
- queue.
- </para>
- <para>
- Specifically, the queue "holds" the header key that is used to find the message's
- group identifier. All messages arriving at the queue are expected to use the same
- header key for holding the identifer. Once the message is enqueued, the broker
- looks up the group identifier in the message's header, and classifies the message
- by its group.
- </para>
- <para>
- Message group support can be enabled on a queue using the
- <command>qpid-config</command> command line tool. The following options should be
- provided when adding a new queue:
- <programlisting>
- --group-header=<replaceable>header-name</replaceable> Enable message group support for this queue. Specify name of application header that holds the group identifier.
- --shared-groups Enforce ordered message group consumption across multiple consumers.
- </programlisting>
- </para>
- <para>
- Message group support may also be specified in the
- <command>queue.declare</command> method via the <command>arguments</command>
- parameter map, or using the messaging address syntax. The following keys must be
- provided in the arguments map to enable message group support on a queue:
- </para>
- <table>
- <title>Queue Declare/Addres Syntax Message Group Configuration Arguments</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Key</entry>
- <entry>Value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>qpid.group_header_key</entry>
- <entry>string - key for message header that holds the group identifier value</entry>
- </row>
- <row>
- <entry>qpid.shared_msg_group</entry>
- <entry>1 - enforce ordering across multiple consumers</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- It is important to note that there is no need to provide the actual group
- identifer values that will be used. The broker learns this values as messages are
- recieved. Also, there is no practical limit - aside from resource limitations -
- to the number of different groups that the broker can track at run time.
- </para>
- <note>
- <title>Restrictions</title>
- <para>
- Message grouping is not supported on LVQ or Priority queues.
- </para>
- </note>
- <example>
- <title>Creating a message group queue via qpid-config</title>
- <para>
- This example uses the qpid-config tool to create a message group queue called
- "MyMsgQueue". The message header that contains the group identifier will use
- the key "GROUP_KEY".
- </para>
- <programlisting>
- qpid-config add queue MyMsgQueue --group-header="GROUP_KEY" --shared-groups"
- </programlisting>
- </example>
- <example>
- <title>Creating a message group queue using address syntax (C++)</title>
- <para>
- This example uses the messaging address syntax to create a message group queue
- with the same configuration as the previous example.
- </para>
- <programlisting>
- sender = session.createSender("MyMsgQueue; {create:always, delete:receiver, node: {x-declare: {arguments:"
- " {'qpid.group_header_key':'GROUP_KEY', 'qpid.shared_msg_group':1}}}}")
- </programlisting>
- </example>
- <section role="h3" id="usingmessagegroups-DefaultGroup">
- <title>
- Default Group
- </title>
- <para>
- Should a message without a group identifier arrive at a queue configured for message grouping, the broker assigns the message to the default group. Therefore, all such "unidentified" messages are considered by the broker as part of the same group. The name of the default group is <command>"qpid.no-group"</command>. This default can be overridden by suppling a different value to the broker configuration item <command>"default-message-group"</command>:
- <example>
- <title>Overriding the default message group identifier for the broker</title>
- <programlisting>
- qpidd --default-msg-group "EMPTY-GROUP"
- </programlisting>
- </example>
- </para>
- </section>
- </section>
- </section>
-
-
-
diff --git a/doc/book/src/producer-flow-control.xml b/doc/book/src/producer-flow-control.xml
deleted file mode 100644
index fd44f51e81..0000000000
--- a/doc/book/src/producer-flow-control.xml
+++ /dev/null
@@ -1,351 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-
--->
-
-<section id="producer-flow-control">
- <title>
- Producer Flow Control
- </title>
-
- <section role="h2" id="producerflowcontrol-Overview">
- <title>
- Overview
- </title>
- <para>
- As of release 0.10, the C++ broker supports the use of flow control to
- throttle back message producers that are at risk of overflowing a
- destination queue.
- </para>
-
- <para>
- Each queue in the C++ broker has two threshold values associated with it:
- </para>
-
- <para>
- Flow Stop Threshold: this is the level of queue resource
- utilization above which flow control will be enabled. Once this
- threshold is crossed, the queue is considered in danger of overflow.
- </para>
-
- <para>
- Flow Resume Threshold - this is the level of queue resource utilization
- below which flow control will be disabled. Once this threshold is
- crossed, the queue is no longer considered in danger of overflow.
- </para>
-
- <para>
- In the above description, queue resource utilization may be
- defined as the total count of messages currently enqueued, or the total
- sum of all message content in bytes.
- </para>
-
- <para>
- The value for a queue's Flow Stop Threshold must be greater than or
- equal to the value of the queue's Flow Resume Threshold.
- </para>
-
- <section role="h3" id="producerflowcontrol-QueueThresholdsExample">
- <title>
- Example
- </title>
-
- <para>
- Let's consider a queue with a maximum limit set on the total number of
- messages that may be enqueued to that queue. Assume this maximum
- message limit is 1000 messages. Assume also that the user configures a
- Flow Stop Threshold of 900 messages, and a Flow Resume Threshold of 500
- messages. Then the following holds:
- </para>
-
- <para>
- The queue's initial flow control state is "OFF".
- </para>
-
- <para>
- While the total number of enqueued messages is less than or equal to
- 900, the queue's flow control state remains "OFF".
- </para>
-
- <para>
- When the total number of enqueued messages is greater than 900, the
- queue's flow control state transitions to "ON".
- </para>
-
- <para>
- When the queue's flow control state is "ON", it remains "ON" until the
- total number of enqueued messages is less than 500. At that point, the queue's
- flow control state transitions to "OFF".
- </para>
-
- <para>
- A similar example using total enqueued content bytes as the threshold
- units are permitted.
- </para>
- </section>
-
- <para>
- Thresholds may be set using both total message counts and total byte
- counts. In this case, the following rules apply:
- </para>
-
- <para>
- 1) Flow control is "ON" when either stop threshold value is crossed.
- </para>
- <para>
- 2) Flow control remains "ON" until both resume thresholds are satisfied.
- </para>
-
- <section role="h3" id="producerflowcontro-MultiThresholdExample">
- <title>
- Example
- </title>
-
- <para>
- Let's consider a queue with a maximum size limit of 10K bytes, and 5000
- messages. A user may assign a Flow Stop Threshold based on a total
- message count of 4000 messages. They may also assigne a Flow Stop
- Threshold of 8K bytes. The queue's flow control state transitions to
- "ON" if either threshold is crossed: (total-msgs greater-than 4000 OR total-bytes
- greater-than 8K).
- </para>
-
- <para>
- Assume the user has assigned Flow Resume threshold's of 3000 messages and
- 6K bytes. Then the queue's flow control will remain active until both
- thresholds are satified: (total-msg less-than 3000 AND total-bytes less-than 6K).
- </para>
- </section>
-
- <para>
- The Broker enforces flow control by delaying the completion of the
- Message.Transfer command that causes a message to be delivered to a queue
- with active flow control. The completion of the Message.Transfer command
- is held off until flow control state transitions to "OFF" for all queues
- that are a destination for that command.
- </para>
-
- <para>
- A message producing client is permitted to have a finite number of
- commands pending completion. When the total number of these outstanding
- commands reaches the limit, the client must not issue further commands
- until one or more of the outstanding commands have completed. This
- window of outstanding commands is considered the sender's "capacity".
- This allows any given producer to have a "capacity's" worth of messages
- blocked due to flow control before the sender must stop sending further
- messages.
- </para>
-
- <para>
- This capacity window must be considered when determining a suitable
- flow stop threshold for a given queue, as a producer may send its
- capacity worth of messages _after_ a queue has reached the flow stop
- threshold. Therefore, a flow stop threshould should be set such that
- the queue can accomodate more messages without overflowing.
- </para>
-
- <para>
- For example, assume two clients, C1 and C2, are producing messages to
- one particular destination queue. Assume client C1 has a configured
- capacity of 50 messages, and client C2's capacity is 15 messages. In
- this example, assume C1 and C2 are the only clients queuing messages to
- a given queue. If this queue has a Flow Stop Threshold of 100
- messages, then, worst-case, the queue may receive up to 165 messages
- before clients C1 and C2 are blocked from sending further messages.
- This is due to the fact that the queue will enable flow control on
- receipt of its 101'st message - preventing the completion of the
- Message.Transfer command that carried the 101'st message. However, C1
- and C2 are allowed to have a total of 65 (50 for C1 and 15 for C2)
- messages pending completion of Message.Transfer before they will stop
- producing messages. Thus, up to 65 messages may be enqueued beyond the
- flow stop threshold before the producers will be blocked.
- </para>
- </section>
-
- <section role="h2" id="producerflowcontrol-UserInterface">
- <title>
- User Interface
- </title>
-
- <para>
- By default, the C++ broker assigns a queue's flow stop and flow resume
- thresholds when the queue is created. The C++ broker also allows the
- user to manually specify the flow control thresholds on a per queue
- basis.
- </para>
-
- <para>
- However, queues that have been configured with a Limit Policy of type
- RING or RING-STRICT do NOT have queue flow thresholds enabled by
- default. The nature of a RING queue defines its behavior when its
- capacity is reach: replace the oldest message.
- </para>
-
- <para>
- The flow control state of a queue can be determined by the "flowState"
- boolean in the queue's QMF management object. The queue's management
- object also contains a counter that increments each time flow control
- becomes active for the queue.
- </para>
-
- <para>
- The broker applies a threshold ratio to compute a queue's default flow
- control configuration. These thresholds are expressed as a percentage
- of a queue's maximum capacity. There is one value for determining the
- stop threshold, and another for determining the resume threshold. The
- user may configure these percentages using the following broker
- configuration options:
- </para>
-
- <programlisting>
- --default-flow-stop-threshold ("Queue capacity level at which flow control is activated.")
- --default-flow-resume-threshold ("Queue capacity level at which flow control is de-activated.")
- </programlisting>
-
- <para>
- For example:
- </para>
-
- <programlisting>
- qpidd --default-flow-stop-threshold=90 --default-flow-resume-threshold=75
- </programlisting>
-
- <para>
- Sets the default flow stop threshold to 90% of a queue's maximum
- capacity and the flow resume threshold to 75% of the maximum capacity.
- If a queue is created with a default-queue-limit of 10000 bytes, then
- the default flow stop threshold would be 90% of 10000 = 9000 bytes and
- the flow resume threshold would be 75% of 10000 = 7500. The same
- computation is performed should a queue be created with a maximum size
- expressed as a message count instead of a byte count.
- </para>
-
- <para>
- If not overridden by the user, the value of the
- default-flow-stop-threshold is 80% and the value of the
- default-flow-resume-threshold is 70%.
- </para>
-
- <para>
- The user may disable default queue flow control broker-wide by
- specifying the value 0 for both of these configuration options. Note
- that flow control may still be applied manually on a per-queue basis in
- this case.
- </para>
-
- <para>
- The user may manually set the flow thresholds when creating a queue.
- The following options may be provided when adding a queue using the
- <command>qpid-config</command> command line tool:
- </para>
-
- <programlisting>
- --flow-stop-size=<replaceable>N</replaceable> Sets the queue's flow stop threshold to <replaceable>N</replaceable> total bytes.
- --flow-resume-size=<replaceable>N</replaceable> Sets the queue's flow resume threshold to <replaceable>N</replaceable> total bytes.
- --flow-stop-count=<replaceable>N</replaceable> Sets the queue's flow stop threshold to <replaceable>N</replaceable> total messages.
- --flow-resume-count=<replaceable>N</replaceable> Sets the queue's flow resume threshold to <replaceable>N</replaceable> total messages.
- </programlisting>
-
- <para>
- Flow thresholds may also be specified in the
- <command>queue.declare</command> method, via the
- <command>arguments</command> parameter map. The following keys can be
- provided in the arguments map for setting flow thresholds:
- </para>
-
- <table>
- <title>Queue Declare Method Flow Control Arguments</title>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Key</entry>
- <entry>Value</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>qpid.flow_stop_size</entry>
- <entry>integer - queue's flow stop threshold value in bytes</entry>
- </row>
- <row>
- <entry>qpid.flow_resume_size</entry>
- <entry>integer - queue's flow resume threshold value in bytes</entry>
- </row>
- <row>
- <entry>qpid.flow_stop_count</entry>
- <entry>integer - queue's flow stop threshold value as a message count</entry>
- </row>
- <row>
- <entry>qpid.flow_resume_count</entry>
- <entry>integer - queue's flow resume threshold value as a message count</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- The user may disable flow control on a per queue basis by setting
- the flow-stop-size and flow-stop-count to zero for the queue.
- </para>
-
- <para>
- The current state of flow control for a given queue can be
- determined by the "flowStopped" statistic. This statistic is
- available in the queue's QMF management object. The value of
- flowStopped is True when the queue's capacity has exceeded the
- flow stop threshold. The value of flowStopped is False when the
- queue is no longer blocking due to flow control.
- </para>
-
- <para>
- A queue will also track the number of times flow control has been
- activated. The "flowStoppedCount" statistic is incremented each time
- the queue's capacity exceeds a flow stop threshold. This statistic can
- be used to monitor the activity of flow control for any given queue
- over time.
- </para>
-
- <table>
- <title>Flow Control Statistics available in Queue's QMF Class</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Statistic Name</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>flowStopped</entry>
- <entry>Boolean</entry>
- <entry>If true, producers are blocked by flow control.</entry>
- </row>
- <row>
- <entry>flowStoppedCount</entry>
- <entry>count32</entry>
- <entry>Number of times flow control was activated for this queue</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- <!--h2-->
- </section>
diff --git a/doc/dev-readme/QPID-0.8-Component-README.odg b/doc/dev-readme/QPID-0.8-Component-README.odg
new file mode 100644
index 0000000000..4a5024c330
--- /dev/null
+++ b/doc/dev-readme/QPID-0.8-Component-README.odg
Binary files differ
diff --git a/doc/dev-readme/QPID-0.8-Component-README.pdf b/doc/dev-readme/QPID-0.8-Component-README.pdf
new file mode 100644
index 0000000000..4b3c810081
--- /dev/null
+++ b/doc/dev-readme/QPID-0.8-Component-README.pdf
Binary files differ
diff --git a/doc/dev-readme/QPID-Component-README.odg b/doc/dev-readme/QPID-Component-README.odg
deleted file mode 100644
index 217a6d68d8..0000000000
--- a/doc/dev-readme/QPID-Component-README.odg
+++ /dev/null
Binary files differ
diff --git a/doc/dev-readme/QPID-Component-README.pdf b/doc/dev-readme/QPID-Component-README.pdf
deleted file mode 100644
index 3012372889..0000000000
--- a/doc/dev-readme/QPID-Component-README.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/website/README.txt b/doc/website/README.txt
index dcb3b423e5..6a0c2876ab 100644
--- a/doc/website/README.txt
+++ b/doc/website/README.txt
@@ -1,10 +1,26 @@
-To edit the website, check out the /site repo area:
+This is the source directory for creating web pages for the Qpid web
+site.
- svn co https://svn.apache.org/repos/asf/qpid/site
+The template used for all pages (template.html), stylesheet
+(style.css), and images are in the ./template directory.
-The HTML files for the site reside in the docs directory, where a README
-can be found to describe the process of adding new content.
+The tools directory contains a very simple Python script (wrap) that
+combines a template and content to create static html pages. Content
+should be written in XHTML, with one <div/> element at the root - see
+./content/home.html for an example.
-It is no longer necessary to generate the main website pages, the live files
-are now edited directly, and are deployed to the web server after check in.
+Use wrap like this:
+$ tools/wrap template/template.html content/<filename> build/<filename>
+
+Content for the main pages should be check into the content
+directory. Content for documentation is created in the ../book
+directory.
+
+To publish generated content, check out the website repo:
+
+$ svn co https://svn.apache.org/repos/asf/qpid/site/docs
+
+Copy generated content (NOT the source!) into the website repo, add it
+using $ svn add, and commit it. When it is committed, it appears on
+the website.
diff --git a/doc/website/build.sh b/doc/website/build.sh
new file mode 100755
index 0000000000..25162b4de0
--- /dev/null
+++ b/doc/website/build.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+TEMPLATE_DIR=template
+TEMPLATE=template.html
+CONTENT_DIR=content
+BUILD_DIR=build
+WRAP="tools/wrap"
+
+# Gather the *.html filenames to wrap
+pushd $CONTENT_DIR >/dev/null
+HTML_FILES=`ls *.html`
+popd >/dev/null
+
+# Clear the existing artefacts, or create the build dir
+if [ -d $BUILD_DIR ];
+then
+ rm -rf $BUILD_DIR/*;
+else
+ mkdir $BUILD_DIR
+fi
+
+# Wrap the html files
+for FILE in $HTML_FILES;
+do
+ ./$WRAP "$TEMPLATE_DIR/$TEMPLATE" "$CONTENT_DIR/$FILE" "$BUILD_DIR/$FILE"
+done
+
+# Copy the .htaccess, style.css, images, and any specifically required non-html content
+cp $CONTENT_DIR/.htaccess $BUILD_DIR/
+cp $TEMPLATE_DIR/style.css $BUILD_DIR/
+cp -R $TEMPLATE_DIR/images $BUILD_DIR/
+cp -R $CONTENT_DIR/images $BUILD_DIR/
+cp $CONTENT_DIR/download.cgi $BUILD_DIR/
+
+
diff --git a/doc/website/content/.htaccess b/doc/website/content/.htaccess
new file mode 100644
index 0000000000..a6ab32531b
--- /dev/null
+++ b/doc/website/content/.htaccess
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+Redirect /download.html http://qpid.apache.org/download.cgi
+Redirect /licence.html http://www.apache.org/licenses/
diff --git a/doc/website/content/acknowledgements.html b/doc/website/content/acknowledgements.html
new file mode 100644
index 0000000000..daeb21c172
--- /dev/null
+++ b/doc/website/content/acknowledgements.html
@@ -0,0 +1,39 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Acknowledgements</h1>
+ <div>
+ <table>
+ <tbody>
+ <tr>
+ <td><a href="http://www.ej-technologies.com/products/jprofiler/overview.html">
+ <img src="images/jprofiler.png" /></a>
+ </td>
+ <td><p>We acknowledge <a href="http://www.ej-technologies.com">ej-technologies</a> for giving us a free team license for profiling Qpid Java code.</p></td>
+
+ </tr>
+ <tr>
+ <td><a href="http://www.headwaysoftware.com/products/structure101"><img src="images/structure101.jpg"/></a> </td>
+ <td><p>We acknowledge <a href="http://www.headwaysoftware.com">Headway Software</a> for giving us free licenses of Structure101 for analyzing and managing the architecture of Qpid Java code.</p></td>
+ </tr>
+ </tbody></table>
+ </div>
+</div>
diff --git a/doc/website/content/amqp.html b/doc/website/content/amqp.html
new file mode 100644
index 0000000000..a251164d07
--- /dev/null
+++ b/doc/website/content/amqp.html
@@ -0,0 +1,71 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>What is AMQP?</h1>
+
+ <p>AMQP <a href="http://www.amqp.org">Advanced Message Queuing Protocol</a> is an open standard designed to support reliable, high-performance messaging over the Internet. AMQP can be used for any distributed or business application, and supports common messaging paradigms like point-to-point, fanout, publish-subscribe, and request-response.</p>
+
+ <p>Apache Qpid implements AMQP, including transaction management, queuing, clustering, federation, security, management and multi-platform support.</p>
+
+
+ <p>Apache Qpid implements the latest AMQP specification, providing transaction management, queuing, distribution, security, management, clustering, federation and heterogeneous multi-platform support and a lot more. </p>
+
+ <p>Apache Qpid is highly optimized, and <a href="compatibility.html" title="AMQP compatibility">aims to be 100% AMQP Compliant</a>.</p>
+
+ <h2><a name="AMQP%28AdvancedMessageQueueingProtocol%29-DownloadtheAMQPSpecifications"></a>Download the AMQP Specifications</h2>
+
+ <h3><a name="AMQP%28AdvancedMessageQueueingProtocol%29-AMQPversion010"></a>AMQP version 0-10</h3>
+
+
+ <ul>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp.0-10.pdf?version=1">AMQP 0-10 Specification (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp.0-10.xml?version=1">AMQP 0-10 Protocol Definition XML </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp.0-10.dfd?version=1">AMQP 0-10 Protocol Definition DTD </a></li>
+
+ </ul>
+
+
+ <h3><a name="AMQP%28AdvancedMessageQueueingProtocol%29-AMQPversion091"></a>AMQP version 0-9-1</h3>
+
+ <ul>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9-1.pdf?version=1">AMQP 0-9-1 Specification (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9-1.xml?version=1">AMQP 0-9-1 Protocol Documentation (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9-1.dtd?version=1">AMQP 0-9-1 Protocol Definitions (XML) </a></li>
+ </ul>
+
+
+ <h3><a name="AMQP%28AdvancedMessageQueueingProtocol%29-AMQPversion09"></a>AMQP version 0-9</h3>
+
+ <ul>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9.pdf?version=1">AMQP 0-9 Specification (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9.xml?version=1">AMQP 0-9 Protocol Documentation (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-9.dtd?version=1">AMQP 0-9 Protocol Definitions (XML) </a></li>
+ </ul>
+
+ <h3><a name="AMQP%28AdvancedMessageQueueingProtocol%29-AMQPversion08"></a>AMQP version 0-8</h3>
+
+ <ul>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.pdf?version=1">AMQP 0-8 Specification (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.dtd?version=1">AMQP 0-8 Protocol Documentation (PDF) </a></li>
+ <li><a href="https://jira.amqp.org/confluence/download/attachments/720900/amqp0-8.xml?version=1">AMQP 0-8 Protocol Definitions (XML) </a></li>
+ </ul>
+</div>
+
diff --git a/doc/website/content/compatibility.html b/doc/website/content/compatibility.html
new file mode 100644
index 0000000000..af99670da9
--- /dev/null
+++ b/doc/website/content/compatibility.html
@@ -0,0 +1,386 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <p><b>Qpid provides the most complete and compatible implementation of AMQP. And is the most aggressive in implementing the latest version of the specification. Qpid can be</b> <b><a href="./download.cgi" title="Download"><b>downloaded here</b></a></b></p>
+
+ <p>There are two brokers:</p>
+
+ <p>C+&#43; with support for AMQP 0-10<br/>
+ Java with support for AMQP 0-8, 0-9, and 0-10.</p>
+
+ <p>There are client libraries for C++, Java (JMS), .Net (written in C#), python and ruby.</p>
+
+ <ul>
+ <li>All clients support 0-10 and interoperate with both brokers as of 0.6.</li>
+ </ul>
+
+
+ <ul>
+ <li>The JMS client supports 0-8, 0-9 and 0-10 and interoperates with both brokers.</li>
+ </ul>
+
+
+ <ul>
+ <li>The python and ruby clients will also support all versions, but the API is dynamically driven by the specification used and so differs between versions. To work with the C+&#43; broker you must use 0-10. To work with the Java broker you can use any version as of 0.6, or prior to 0.6 you can use 0-8 or 0-9.</li>
+
+ </ul>
+
+
+ <ul>
+ <li>There are two separate C# clients, one for 0-8 that interoperates only with the Java broker, and one for 0-10.</li>
+ </ul>
+
+
+ <ul>
+ <li>There is also a WCF channel, which wraps the 0-10 native C++ client library.</li>
+ </ul>
+
+
+ <p>QMF Management is supported in Ruby, Python, C++, and can be translated to Java JMX &amp; WS-DM via the QMan management tool.</p>
+
+ <h3><a name="AMQPcompatibility-AMQPCompatibilityofQpidreleases%3A"></a>AMQP Compatibility of Qpid releases:</h3>
+
+ <p>Qpid implements the AMQP Specification, and as the specification has progressed Qpid is keeping up with the updates. This means that different Qpid versions support different versions of AMQP. Here is a simple guide on what use.</p>
+
+ <p>Here is a matrix that describes the different versions supported by each release<br/>
+ Y = supported<br/>
+ N = unsupported<br/>
+
+ IP = in progress<br/>
+ P = planned</p>
+ <div >
+ <table ><tbody>
+ <tr>
+ <th > Component </th>
+ <th > Spec </th>
+ <th >&nbsp;</th>
+ <th >&nbsp;</th>
+ <th >&nbsp;</th>
+ <th >&nbsp;</th>
+ <th >&nbsp;</th>
+ <th >&nbsp;</th>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <th > M2.1 </th>
+ <th > M3 </th>
+ <th > M4 </th>
+ <th > 0.5 </th>
+ <th > 0.6 </th>
+ <th > 0.8 </th>
+ </tr>
+ <tr>
+ <th > Java client </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-9 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-8 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <th > Java broker </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-9 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-8 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+
+ <th > C+&#43; client/broker </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-9 </td>
+ <td > Y </td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ </tr>
+
+ <tr>
+ <th > Python client </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-9 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-8 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <th > Ruby client </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-8 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+
+ <th > C# client </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td >&nbsp;</td>
+ <td > 0-8 </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <th > WCF channel </th>
+ <td > 0-10 </td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td >&nbsp;</td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <h3><a name="AMQPcompatibility-InteroptablebyAMQPspecificationversion"></a>Interop table by AMQP specification version</h3>
+
+ <p>Above table represented in another format.</p>
+ <div >
+ <table ><tbody>
+ <tr>
+ <th >Component</th>
+ <th >Release </th>
+
+ <th > 0-8 </th>
+ <th > 0-9 </th>
+ <th > 0-10 </th>
+ </tr>
+ <tr>
+ <td > Java client </td>
+ <td > M3, M4, 0.5, 0.6, 0.8</td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td > Java client </td>
+ <td > M2.1 </td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > Java broker </td>
+ <td > 0.6, 0.8</td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td > Java broker </td>
+ <td > M3, M4, 0.5 </td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > Java broker </td>
+ <td > M2.1 </td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > C+&#43; client/broker </td>
+ <td > M3, M4, 0.5, 0.6, 0.8</td>
+
+ <td > N </td>
+ <td > N </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td > C+&#43; client/broker </td>
+ <td > M2.1 </td>
+
+ <td > N </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > Python client </td>
+ <td > M3, M4, 0.5, 0.6, 0.8</td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td > Python client </td>
+ <td > M2.1 </td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > Ruby client </td>
+ <td > M4, 0.5, 0.6, 0.8</td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > Y </td>
+ </tr>
+ <tr>
+ <td > Ruby client </td>
+ <td > M3 </td>
+
+ <td > Y </td>
+ <td > Y </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > C# client 0-10 </td>
+ <td > M4, 0.5, 0.6, 0.8</td>
+
+ <td > N </td>
+ <td > N </td>
+ <td > Y</td>
+ </tr>
+ <tr>
+ <td > C# client 0-8 </td>
+ <td > M3, M4, 0.5, 0.6, 0.8</td>
+
+ <td > Y </td>
+ <td > N </td>
+ <td > N </td>
+ </tr>
+ <tr>
+ <td > WCF channel </td>
+ <td > 0.6, 0.8</td>
+
+ <td > N </td>
+ <td > N </td>
+ <td > Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+</div>
+
diff --git a/doc/website/content/documentation.html b/doc/website/content/documentation.html
new file mode 100644
index 0000000000..0a49a7c50b
--- /dev/null
+++ b/doc/website/content/documentation.html
@@ -0,0 +1,92 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Qpid Documentation</h1>
+
+ <h2 id="doc-release">Documentation for Qpid 0.8 release</h2>
+
+ <p>This documentation was converted from the Wiki and organized into
+ book form. <a href="#doc-archives">The archives</a> contain the
+ original content of the Wiki.</p>
+
+ <ul>
+ <li><a href="getting_started.html">Getting Started</a></li>
+ <li><p>AMQP Messaging Broker (C++ implementation for Linux, Windows, Solaris)</p>
+ <p>
+ <a href="books/0.8/AMQP-Messaging-Broker-CPP-Book/pdf/AMQP-Messaging-Broker-CPP-Book.pdf"
+ name="AMQP Messaging Broker (C++ implemementation)">PDF</a> |
+ <a href="books/0.8/AMQP-Messaging-Broker-CPP-Book/html/index.html">HTML</a></p></li>
+ <li><p>AMQP Messaging Broker (Java implemementation)</p>
+ <p><a href="books/0.8/AMQP-Messaging-Broker-Java-Book/pdf/AMQP-Messaging-Broker-Java-Book.pdf"
+ name="AMQP Messaging Broker (Java implemementation)">PDF</a> |
+ <a href="books/0.8/AMQP-Messaging-Broker-Java-Book/html/index.html">HTML</a></p></li>
+ <li><p>Programming in Apache Qpid: Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python</p>
+ <p>
+ <a href="books/0.8/Programming-In-Apache-Qpid/pdf/Programming-In-Apache-Qpid.pdf"
+ name="Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python">PDF</a> |
+ <a href="books/0.8/Programming-In-Apache-Qpid/html/index.html"
+ name="Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python">HTML</a></p></li>
+ <li><p>For programming examples and documentation for Qpid,
+ see the <a href="getting_started.html">Getting Started</a>
+ page.</p></li>
+ <li><p>API Reference Documentation</p>
+ <p>C++: <a href="apis/0.8/cpp/html/index.html">HTML</a> | <a href="apis/0.8/cpp/qpid-cpp-doxygen-0.8.html.tar.gz">qpid-cpp-doxygen-0.8.html.tar.gz</a></p>
+ <p>Python: <a href="apis/0.8/python/html/index.html">HTML</a> | <a href="apis/0.8/python/qpid-python-epydoc-0.8.html.tar.gz">qpid-python-epydoc-0.8.html.tar.gz</a></p></li>
+ </ul>
+
+
+ <h2 id="doc-trunk">Documentation for Qpid development trunk</h2>
+ <ul>
+ <li><a href="getting_started.html">Getting Started</a></li>
+ <li><p>AMQP Messaging Broker (C++ implementation for Linux, Windows, Solaris)</p>
+ <p>
+ <a href="books/trunk/AMQP-Messaging-Broker-CPP-Book/pdf/AMQP-Messaging-Broker-CPP-Book.pdf"
+ name="AMQP Messaging Broker (C++ implemementation)">PDF</a> |
+ <a href="books/trunk/AMQP-Messaging-Broker-CPP-Book/html/index.html">HTML</a></p></li>
+ <li><p>AMQP Messaging Broker (Java implemementation)</p>
+ <p><a href="books/trunk/AMQP-Messaging-Broker-Java-Book/pdf/AMQP-Messaging-Broker-Java-Book.pdf"
+ name="AMQP Messaging Broker (Java implemementation)">PDF</a> |
+ <a href="books/trunk/AMQP-Messaging-Broker-Java-Book/html/index.html">HTML</a></p></li>
+ <li><p>Programming in Apache Qpid: Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python</p>
+ <p>
+ <a href="books/trunk/Programming-In-Apache-Qpid/pdf/Programming-In-Apache-Qpid.pdf"
+ name="Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python">PDF</a> |
+ <a href="books/trunk/Programming-In-Apache-Qpid/html/index.html"
+ name="Cross-Platform AMQP Messaging in Java JMS, .NET, C++, and Python">HTML</a></p></li>
+ </ul>
+
+
+
+ <h2 id="doc-archives">Documentation Archives</h2>
+
+ <ul>
+ <li><p>Qpid Wiki converted to PDF format on 26 May 2010</p>
+ <a href="archives/qpid-2010-05-26.html.zip">HTML</a> |
+ <a href="archives/qpid-2010-05-26.pdf">PDF</a></li>
+ </ul>
+
+ <h2 id="qpid-wiki">Qpid Wiki</h2>
+
+ <ul>
+ <li><p><a href="https://cwiki.apache.org/qpid/">Qpid Wiki</a></p></li>
+ </ul>
+
+</div>
diff --git a/doc/website/content/download.cgi b/doc/website/content/download.cgi
new file mode 100644
index 0000000000..c4e25082c8
--- /dev/null
+++ b/doc/website/content/download.cgi
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Wrapper script around mirrors.cgi script
+# (we must change to that directory in order for python to pick up the
+# python includes correctly)
+cd /www/www.apache.org/dyn/mirrors
+/www/www.apache.org/dyn/mirrors/mirrors.cgi $*
+
diff --git a/doc/website/content/download.html b/doc/website/content/download.html
new file mode 100644
index 0000000000..b8d1013cfc
--- /dev/null
+++ b/doc/website/content/download.html
@@ -0,0 +1,466 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Downloads</h1>
+
+ <h2>Production Releases</h2>
+
+ <p>These releases are well tested and appropriate for production use, use the links below to download them from one of our mirrors. Older versions can be found in the <a href="http://archive.apache.org/dist/qpid/">archive</a></p>
+
+ <p>Qpid supports the latest version of AMQP 0-10, and some components also the earlier AMQP 0-8 and 0-9 versions. The Java Broker and Client provide protocol negotiation. For details on cross component compatibility among releases, see: <a href="./compatibility.html">AMQP Release Compatibility for Qpid</a></p>
+
+ <p>If you have any questions about these releases, please email the <a href="mailto:users@qpid.apache.org">user list</a></p>
+
+ <h2>Mirrors</h2>
+
+ <p>[if-any logo]
+<a href="[link]"><img align="right" src="[logo]" border="0" /></a>[end]
+The currently selected mirror is <b>[preferred]</b>. If you encounter a problem with this mirror, please select another. If all mirrors are failing, there are <i>backup</i> mirrors (at the end of the list) that should be available, or you may also consult the <a href="http://www.apache.org/mirrors/">complete list</a> of mirrors.</p>
+
+<form action="[location]" method="get" id="SelectMirror">
+<p>
+Other mirrors: <select name="Preferred">
+[if-any http]
+ [for http]<option value="[http]">[http]</option>[end]
+[end]
+[if-any ftp]
+ [for ftp]<option value="[ftp]">[ftp]</option>[end]
+[end]
+[if-any backup]
+ [for backup]<option value="[backup]">[backup] (backup)</option>[end]
+[end]
+</select>
+<input type="submit" value="Change" />
+</p>
+</form>
+
+ <p> It is good practice to <a href="#Download-Verify">verify</a> the integrity of the downloaded files using signatures downloaded from our <a href="http://www.apache.org/dist/qpid/">main distribution directory</a>.</p>
+
+
+ <h2>Latest Release: 0.8</h2>
+
+ <p>Individual PGP signatures are provided below, and the sha1sum output for each artefact is listed here: <a href="http://www.apache.org/dist/qpid/0.8/SHA1SUM">SHA1SUM</a>.</p>
+
+ <h3>Multiple Component Packages</h3>
+
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Full source release</td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-0.8.tar.gz">qpid-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-0.8.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C+&#43; broker &amp; client </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-cpp-0.8.tar.gz">qpid-cpp-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-cpp-0.8.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java broker, client &amp; tools </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-java-0.8.tar.gz">qpid-java-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-java-0.8.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> All released artefacts</td>
+ <td> <a href="[preferred]/qpid/0.8/">/qpid/0.8/</a> </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <h3><a name="Download-SingleComponentPackage"></a>Single Component Packages</h3>
+
+ <p><b>Broker</b></p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Language </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-java-broker-0.8.tar.gz">qpid-java-broker-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-java-broker-0.8.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <p><b>Client</b></p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Language </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET, WCF) WCF channel (C+&#43; Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-wcf-0.8.zip">qpid-wcf-0.8.zip</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-wcf-0.8.zip.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET, WCF, Excel) 0-10 client (C+&#43; Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-dotnet-0-10-0.8.zip">qpid-dotnet-0-10-0.8.zip</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-dotnet-0-10-0.8.zip.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET) 0-8 client (Java Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-dotnet-0-8-0.8.zip">qpid-dotnet-0-8-0.8.zip</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-dotnet-0-8-0.8.zip.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java </td>
+
+ <td> <a href="[preferred]/qpid/0.8/qpid-java-client-0.8.tar.gz">qpid-java-client-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-java-client-0.8.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Python </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-python-0.8.tar.gz">qpid-python-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-python-0.8.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Ruby </td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-ruby-0.8.tar.gz">qpid-ruby-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-ruby-0.8.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <p><b>Management tools</b></p>
+
+ <p>C+&#43; broker management</p>
+ <div>
+ <table class="download_table"><tbody>
+
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Cmd line tools <br /> (packaged in full-release)</td>
+ <td> <a href="[preferred]/qpid/0.8/qpid-0.8.tar.gz">qpid-0.8.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-0.8.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ </tbody></table>
+
+ </div>
+
+
+ <p>Java broker management</p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+ <th> Download </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> JMX Management Console <br /> </td>
+
+ <td> <a href="[preferred]/qpid/0.8/qpid-jmx-management-console-0.8-linux-gtk-x86.tar.gz">Linux x86</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-jmx-management-console-0.8-linux-gtk-x86.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.8/qpid-jmx-management-console-0.8-linux-gtk-x86_64.tar.gz">Linux x86_64</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-jmx-management-console-0.8-linux-gtk-x86_64.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.8/qpid-jmx-management-console-0.8-macosx.zip">Mac OS X</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-jmx-management-console-0.8-macosx.zip.asc">PGP</a>] | <a href="[preferred]/qpid/0.8/qpid-jmx-management-console-0.8-solaris-gtk-sparc.tar.gz">Solaris 10 Sparc</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-jmx-management-console-0.8-solaris-gtk-sparc.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.8/qpid-jmx-management-console-0.8-win32-win32-x86.zip">Windows x86</a> [<a href="http://www.apache.org/dist/qpid/0.8/qpid-jmx-management-console-0.8-win32-win32-x86.zip.asc">PGP</a>] </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+
+ <h2><a name="Download-PreviousRelease"></a>Previous Release: 0.6</h2>
+
+ <p>Individual PGP signatures are provided below, and the sha1sum output for each artefact is listed here: <a href="http://www.apache.org/dist/qpid/0.6/SHA1SUM">SHA1SUM</a>.</p>
+
+ <h3>Multiple Component Packages</h3>
+
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> All released artefacts</td>
+ <td> <a href="[preferred]/qpid/0.6/">/qpid/0.6/</a> </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C+&#43; broker &amp; client </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-cpp-0.6.tar.gz">qpid-cpp-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-cpp-0.6.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java broker, client &amp; tools </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-java-0.6.tar.gz">qpid-java-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-java-0.6.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <h3><a name="Download-SingleComponentPackage"></a>Single Component Packages</h3>
+
+ <p><b>Broker</b></p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Language </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-java-broker-0.6.tar.gz">qpid-java-broker-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-java-broker-0.6.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <p><b>Client</b></p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Language </th>
+
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET, WCF) WCF channel (C+&#43; Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-wcf-0.6.zip">qpid-wcf-0.6.zip</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-wcf-0.6.zip.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET, WCF, Excel) 0-10 client (C+&#43; Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-dotnet-0-10-0.6.zip">qpid-dotnet-0-10-0.6.zip</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-dotnet-0-10-0.6.zip.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> C# (.NET) 0-8 client (Java Broker Compatible) </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-dotnet-0-8-0.6.zip">qpid-dotnet-0-8-0.6.zip</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-dotnet-0-8-0.6.zip.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Java </td>
+
+ <td> <a href="[preferred]/qpid/0.6/qpid-java-client-0.6.tar.gz">qpid-java-client-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-java-client-0.6.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Python </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-python-0.6.tar.gz">qpid-python-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-python-0.6.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> Ruby </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-ruby-0.6.tar.gz">qpid-ruby-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-ruby-0.6.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <p><b>Management tools</b></p>
+
+ <p>C+&#43; broker management</p>
+ <div>
+ <table class="download_table"><tbody>
+
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+ <th> Download </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-10 </th>
+ <th class="download_table_amqp_col"> AMQP<br />0-8/0-9 </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> cmd line (packaged with python) </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-python-0.6.tar.gz">qpid-python-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-python-0.6.tar.gz.asc">PGP</a>] </td>
+
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> QMan JMX bridge, WS-DM </td>
+ <td> <a href="[preferred]/qpid/0.6/qpid-management-client-0.6.tar.gz">qpid-management-client-0.6.tar.gz</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-management-client-0.6.tar.gz.asc">PGP</a>] </td>
+ <td class="download_table_amqp_col"> Y </td>
+ <td class="download_table_amqp_col">&nbsp;</td>
+ </tr>
+ </tbody></table>
+
+ </div>
+
+
+ <p>Java broker management</p>
+ <div>
+ <table class="download_table"><tbody>
+ <tr>
+ <th class="download_table_col_1"> Component </th>
+ <th> Download </th>
+ </tr>
+ <tr>
+ <td class="download_table_col_1"> JMX Management Console <br /> </td>
+
+ <td> <a href="[preferred]/qpid/0.6/qpid-jmx-management-console-0.6-linux-gtk-x86.tar.gz">Linux x86</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-jmx-management-console-0.6-linux-gtk-x86.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.6/qpid-jmx-management-console-0.6-linux-gtk-x86_64.tar.gz">Linux x86_64</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-jmx-management-console-0.6-linux-gtk-x86_64.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.6/qpid-jmx-management-console-0.6-macosx.zip">Mac OS X</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-jmx-management-console-0.6-macosx.zip.asc">PGP</a>] | <a href="[preferred]/qpid/0.6/qpid-jmx-management-console-0.6-solaris-gtk-sparc.tar.gz">Solaris 10 Sparc</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-jmx-management-console-0.6-solaris-gtk-sparc.tar.gz.asc">PGP</a>] | <a href="[preferred]/qpid/0.6/qpid-jmx-management-console-0.6-win32-win32-x86.zip">Windows x86</a> [<a href="http://www.apache.org/dist/qpid/0.6/qpid-jmx-management-console-0.6-win32-win32-x86.zip.asc">PGP</a>] </td>
+ </tr>
+ </tbody></table>
+ </div>
+
+
+ <h2><a name="Download-QpidComponents.org"></a>QpidComponents.org </h2>
+
+ <p><a href="http://QpidComponents.org">QpidComponents.org</a> provides further components for Apache Qpid, including both persistence and management tools. These components are open source, but are not developed as part of the Apache Qpid project due to licensing or other restrictions.</p>
+
+ <h2><a name="Download-ContributedC%5CPackages"></a>Contributed C+&#43; Packages</h2>
+
+ <h3><a name="Download-WindowsInstaller"></a>Windows Installer</h3>
+
+ <p>The Windows installer is available from <a href="http://www.riverace.com/qpid/downloads.htm">http://www.riverace.com/qpid/downloads.htm</a>. It is built from the C+&#43; broker &amp; client and C# WCF Channel source distributions listed above. It has been tested for Windows XP SP3 and above.</p>
+
+ <h3><a name="Download-PrebuiltLinuxPackages"></a>Pre-built Linux Packages</h3>
+
+ <h4><a name="Download-Fedora"></a>Fedora </h4>
+
+ <p>On Fedora, Qpid can be installed using yum. Because Java RPMs are not yet available in Fedora repos, the Java client is not in these distributions.</p>
+
+ <p>To install the server:</p>
+ <div><div>
+ <pre>
+# yum install qpidd
+ </pre>
+ </div></div>
+
+ <p>To install C+&#43; and Python clients:</p>
+ <div><div>
+ <pre>
+# yum install qpidc-devel
+ </pre>
+ </div></div>
+ <div><div>
+ <pre>
+# yum install amqp python-qpid
+ </pre>
+ </div></div>
+ <p>To install documentation:</p>
+ <div><div>
+
+ <pre>
+# yum install rhm-docs
+ </pre>
+ </div></div>
+ <p>To install persistence using an external store module:</p>
+ <div><div>
+ <pre>
+# yum install rhm
+ </pre>
+ </div></div>
+
+ <h2><a name="Download-SourceCodeRepository"></a>Source Code Repository</h2>
+
+ <p>The latest version of the code is always available in the <a href="source_repository.html" title="Source Repository">Source Repository</a>.</p>
+
+
+ <h2><a name="Download-Verify"></a>Verify the integrity of the files</h2>
+
+ <p>It is essential that you verify the integrity of the downloaded files using the PGP signatures or SHA1 checksums.</p>
+
+ <p>The PGP signatures can be verified using PGP or GPG. First download the <a href="http://www.apache.org/dist/qpid/KEYS">KEYS</a> file as well as the <code>.asc</code> PGP signature file for the relevant artefact. Make sure you get these files from the relevant subdirectory of the <a href="http://www.apache.org/dist/qpid/">main distribution directory</a>, rather than from a mirror. Then verify the signatures using:</p>
+
+ <p>
+ <code>
+% pgpk -a KEYS<br />
+% pgpv qpid-0.8.tar.gz.asc<br />
+ </code>
+ <em>or</em><br />
+ <code>
+% pgp -ka KEYS<br />
+% pgp qpid-0.8.tar.gz.asc<br />
+ </code>
+ <em>or</em><br />
+ <code>
+% gpg --import KEYS<br />
+% gpg --verify qpid-0.8.tar.gz.asc
+ </code>
+ </p>
+
+<p>Alternatively, you can verify the SHA1 checksum of the files. A unix program called <code>sha1</code> or <code>sha1sum</code> is included in many unix distributions. It is also available as part of <a href="http://www.gnu.org/software/textutils/textutils.html">GNU Textutils</a>. For windows users, <a href="http://www.slavasoft.com/fsum/">fsum</a> supports SHA1. Ensure your generated checksum string matches the string published in the SHA1SUM file included with each release. Again, make sure you get this file from the relevant subdirectory of the <a href="http://www.apache.org/dist/qpid/">main distribution directory</a>, rather than from a mirror</p>
+
+</div>
diff --git a/doc/website/content/getting_involved.html b/doc/website/content/getting_involved.html
new file mode 100644
index 0000000000..033abdc443
--- /dev/null
+++ b/doc/website/content/getting_involved.html
@@ -0,0 +1,69 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+
+<h1>Getting Involved</h1>
+
+<h2><a name="GettingInvolved-TherearemanywaysyoucangetinvolvedinQpid%3A"></a>Join in</h2>
+
+<ol>
+ <li>Participate on the <a href="mailing_lists.html" title="Mailing Lists">Mailing Lists</a>.</li>
+ <li>Contibute via <a href="http://issues.apache.org/jira/browse/qpid">JIRA issues</a>. Remember that all patches must be attached to a JIRA with the ASL usage granted or we can't use it!</li>
+ <li>Review the current code.</li>
+ <li>Help write user documentation.</li>
+ <li>Help write user examples.</li>
+ <li>Most definitely add more tests.</li>
+</ol>
+
+<p>Please be sure to take a look at the coding guidelines for the section of the project that you contribute to:</p>
+
+<ul>
+ <li><a href="https://cwiki.apache.org/qpid/java-coding-standards.html">Java Coding Standards</a></li>
+ <li><a href="https://cwiki.apache.org/qpid/cppstyleguide.html">C++ Coding Standards</a></li>
+
+ <li><a href="https://cwiki.apache.org/qpid/cpptips.html">C++ Tips</a></li>
+ <li><a href="https://cwiki.apache.org/qpid/osvc.html">OS version considerations</a></li>
+</ul>
+
+<h2><a name="GettingInvolved-ProjectEtiquette"></a>Project Etiquette</h2>
+
+<p>Please read and digest our <a href="qpid_project_etiquette_guide.html" title="Qpid Project Etiquette Guide">Qpid Project Etiquette Guide</a>. This is a key guide for new contributers and required reading.</p>
+
+<h2><a name="GettingInvolved-Becomingacommitter%3A"></a>Becoming a Committer</h2>
+
+<p>Qpid uses the following guidelines for voting in new committers. First off we would like new committers to have provided meaningful contribution to the project. By contributions we include development (tests, features, examples) or documentation through patches and interactions with the project through lists and JIRA. It should be noted that as we send our JIRA to the dev list, thus some people filter the JIRA's to limit traffic. It is thus good to cross post something to the dev list every now and again, if the discussion is being held primarily on JIRA.</p>
+
+<p>The key question is what does the Qpid project consider to be a meaningful contribution to be come a committer. As this bar is set for all new commiters Qpid will be conservative in general with adding new committers.</p>
+
+<p>The Qpid project will look to see if someone consistently provides quality contributions and interactions with the project over a period of several weeks. Based on that the PMC will vote the new committers onto the project. </p>
+
+<p>If you have any question please mail <a href="mailto:dev@qpid.apache.org">dev@qpid.apache.org</a> or <a href="mailto:private@qpid.apache.org">private@qpid.apache.org</a> </p>
+
+<p>Many thanks for you interest,<br />
+
+The Qpid Team.</p>
+
+<h2><a name="GettingInvolved-JoiningthePMC"></a>Joining the PMC</h2>
+
+<p>Nominations for Qpid PMC membership will be voted on by the Qpid PMC.</p>
+
+</div>
+
diff --git a/doc/website/content/getting_started.html b/doc/website/content/getting_started.html
new file mode 100644
index 0000000000..5a3a8cb602
--- /dev/null
+++ b/doc/website/content/getting_started.html
@@ -0,0 +1,85 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+-->
+<div class="main_text_area_body" >
+ <h1>Getting Started with Apache Qpid</h1>
+ <p>To get started with Apache Qpid, follow the steps below.</p>
+
+ <ol>
+ <li>Download the software <a href="download.cgi" title="Download">Download</a></li>
+ <li>Start a broker.
+ <ul>
+ <li>Instructions for <a href="https://cwiki.apache.org/qpid/getting-started-guide.html" title="Getting Started Guide">running a Qpid Java broker (AMQP 0-8, 0-9) </a></li>
+ <li>Instructions for <a href="http://qpid.apache.org/books/trunk/AMQP-Messaging-Broker-CPP-Book/html/ch01.html#section-Running-a-Qpid-CPP-Broker" title="RASC">running a Qpid C++ broker (AMQP 0-10) </a></li>
+
+ <li><a href="https://cwiki.apache.org/qpid/mgmtc.html" title="MgmtC++">Management tools </a> (AMQP 0-10, works with the Qpid C++ broker)</li>
+ </ul>
+ </li>
+ <li>Run an example program from the downloaded software, or from the following URLs (these are svn URLs, which you can use to browse the examples or check them out):
+ <ul>
+ <li>C++ (AMQP 0-10):
+ <ul>
+ <li>Examples: <a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/examples/">https://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/examples/ </a></li>
+
+ <li><a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/cpp/examples/README.txt">Running the C++ Examples </a></li>
+ </ul>
+ </li>
+ <li>Java JMS (AMQP 0-10):
+ <ul>
+ <li>Examples: <a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/java/client/example/">https://svn.apache.org/repos/asf/qpid/trunk/qpid/java/client/example/ </a></li>
+ <li><a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/java/client/example/src/main/java/runSample.sh">Script for Running the Java JMS Examples </a></li>
+
+ </ul>
+ </li>
+ <li>Python (AMQP 0-10):
+ <ul>
+ <li>Examples: <a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/">https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/ </a></li>
+ <li><a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/python/examples/README">Running the Python Examples </a></li>
+ </ul>
+ </li>
+
+ <li>Ruby (AMQP 0-10):
+ <ul>
+ <li>Examples: <a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid/ruby/examples/">https://svn.apache.org/repos/asf/qpid/trunk/qpid/ruby/examples/ </a></li>
+ </ul>
+ </li>
+ <li>.NET (AMQP 0-10):
+ <ul>
+ <li>Examples: <a href="http://svn.apache.org/viewvc/qpid/trunk/qpid/dotnet/client-010/examples/">http://svn.apache.org/viewvc/qpid/trunk/qpid/dotnet/client-010/examples/ </a></li>
+
+ <li><a href="https://cwiki.apache.org/qpid/net-user-guide.html">.NET Tutorial </a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>Read the API Guides and Documentation
+ <ul>
+ <li><p><a href="documentation.html">API Guides and Documentation</a></li>
+ </ul>
+ </li>
+ <li>Get your Questions Answered
+ <ul>
+ <li>Read the <a href="https://cwiki.apache.org/qpid/faq.html" title="FAQ">FAQ</a></li>
+
+ <li>Ask a question on the user list <a href="mailto:users-subscribe@qpid.apache.org">users-subscribe@qpid.apache.org</a></li>
+ </ul>
+ </li>
+ </ol>
+</div>
diff --git a/doc/website/content/images/README.txt b/doc/website/content/images/README.txt
new file mode 100644
index 0000000000..c53909bfd2
--- /dev/null
+++ b/doc/website/content/images/README.txt
@@ -0,0 +1 @@
+This directory is for images associated with content, not the images used in page templates.
diff --git a/doc/website/content/images/jprofiler.png b/doc/website/content/images/jprofiler.png
new file mode 100644
index 0000000000..7c5da2cf94
--- /dev/null
+++ b/doc/website/content/images/jprofiler.png
Binary files differ
diff --git a/doc/website/content/images/structure101.jpg b/doc/website/content/images/structure101.jpg
new file mode 100644
index 0000000000..9242ea9176
--- /dev/null
+++ b/doc/website/content/images/structure101.jpg
Binary files differ
diff --git a/doc/website/content/index.html b/doc/website/content/index.html
new file mode 100644
index 0000000000..16e96ebc7a
--- /dev/null
+++ b/doc/website/content/index.html
@@ -0,0 +1,91 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Introduction</h1>
+
+ <p>Apache Qpid&#8482; is a cross-platform Enterprise
+ Messaging system which implements the Advanced Message Queuing Protocol
+ (AMQP), providing message brokers written in C++ and
+ Java, along with clients for C++, Java JMS, .Net, Python, and Ruby.</p>
+
+ <p>Enterprise Messaging systems let programs communicate by
+ exchanging messages, much as people communicate by
+ exchanging email. Unlike email, enterprise messaging systems
+ provide guaranteed delivery, speed, security, and freedom
+ from spam. Until recently, there was no open standard for
+ Enterprise Messaging systems, so programmers either wrote
+ their own, or used expensive proprietary systems.</p>
+
+ <p><a href="http://www.amqp.org/">AMQP</a> is the first open standard for
+ Enterprise Messaging. It is designed to support messaging
+ for just about any distributed or business
+ application. Routing can be configured flexibly, easily
+ supporting common messaging paradigms like point-to-point,
+ fanout, publish-subscribe, and request-response.</p>
+
+ <p>Apache Qpid implements the latest AMQP specification, providing
+ transaction management, queuing, distribution, security,
+ management, clustering, federation and heterogeneous
+ multi-platform support and a lot more. And Apache Qpid is
+ extremely fast. Apache Qpid <a href="compatibility.html"
+ title="AMQP compatibility">aims to be 100% AMQP Compliant</a>.</p>
+
+ <p>This is a project of the <a href="http://www.apache.org/">Apache Software Foundation.</a></p>
+
+ <div class="feature_box">
+ <div class="feature_box_column1">
+ <h3>AMQP Brokers</h3>
+ <ul>
+ <li><p>Java Implementation</p>
+ </li>
+ <li><p>C++ Implementation</p>
+ </li>
+ </ul>
+ <br/>
+ <br/>
+ </div> <!-- end of feature_box_column -->
+
+ <div class="feature_box_column2">
+ <h3>AMQP Client APIs</h3>
+ <ul>
+ <li>Java (JMS 1.1 compliant)</li>
+ <li>C++ (Linux/Windows)</li>
+ <li>C# .NET</li>
+ <li>WCF Adapter (Windows Only)</li>
+ <li>Python</li>
+ <li>Ruby</li>
+ </ul>
+ </div> <!-- end of feature_box_column -->
+
+ <div class="feature_box_column3">
+ <h3>Qpid Management</h3>
+ <ul>
+ <li>QMF Python API</li>
+ <li>QMF C++ API </li>
+ <li>Python tools</li>
+ <li>JMX</li>
+ </ul>
+ </div> <!-- end of feature_box_column -->
+
+ </div> <!-- end of feature_box -->
+
+</div> <!-- end of main_text_area_body -->
+
diff --git a/doc/website/content/mailing_lists.html b/doc/website/content/mailing_lists.html
new file mode 100644
index 0000000000..b1c5266e40
--- /dev/null
+++ b/doc/website/content/mailing_lists.html
@@ -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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Qpid Mailing lists</h1>
+
+ <p>There are a number of lists listed below. Note when sening subscription emails it is best to have a value in the subjsct and body even if it is only 'subscribe'. This will help the ensure the email get past the spam filters.</p>
+
+ <h2>Qpid User List</h2>
+
+ <p>The user's list is for discussions that relate to use or questions
+ on Qpid. If you have questions about how a feature works, suggestions
+ on additional requirements, or general questions about Qpid please use
+ this list.</p>
+
+ <ul>
+ <li>To subscribe to the user's list send an e-mail with subject 'subscribe' to:<br />
+ <a href="mailto:users-subscribe@qpid.apache.org">users-subscribe@qpid.apache.org</a></li>
+
+ <li>To remove yourself from the user's list send an e-mail with subject 'unsubscribe' to:<br />
+ <a href="mailto:users-unsubscribe@qpid.apache.org">users-unsubscribe@qpid.apache.org</a></li>
+ <li>The user's mailing list is archived. You can view the archive at:
+ <ul>
+ <li>Apache archive: <a href="http://mail-archives.apache.org/mod_mbox/qpid-users/">http://mail-archives.apache.org/mod_mbox/qpid-users/</a><br/></li>
+ <li>Nabble archive: <a href="http://n2.nabble.com/Apache-Qpid-users-f2158936.html">http://n2.nabble.com/Apache-Qpid-users-f2158936.html</a></li>
+ </ul>
+ </li>
+ </ul>
+
+
+ <h2><a name="MailingLists-QpidDeveloperList"></a>Qpid Developer List</h2>
+
+ <p>The developer's list is for discussions that relate to the on going development of Qpid. If you have questions about how a feature is being developed, suggestions on how to implement a new feature, or requests for a new feature this is the list to use.</p>
+
+ <ul>
+ <li>To subscribe to the developer's list send an e-mail with subject 'subscribe' to:<br />
+ <a href="mailto:dev-subscribe@qpid.apache.org">dev-subscribe@qpid.apache.org</a></li>
+ <li>To remove yourself from the developer's list send an e-mail with subject 'unsubscribe' to:
+ <a href="mailto:dev-unsubscribe@qpid.apache.org">dev-unsubscribe@qpid.apache.org</a></li>
+ <li>The developer's mailing list is archived. You can view the archive at:
+ <ul>
+ <li>Apache archive: <a href="http://mail-archives.apache.org/mod_mbox/qpid-dev/">http://mail-archives.apache.org/mod_mbox/qpid-dev/</a></li>
+ <li>Nabble archive: <a href="http://www.nabble.com/Qpid-Developers-f16694.html">http://www.nabble.com/Qpid-Developers-f16694.html</a><br/>
+ and <a href="http://n2.nabble.com/Apache-Qpid-developers-f2158895.html">http://n2.nabble.com/Apache-Qpid-developers-f2158895.html</a></li>
+ </ul>
+ </li>
+ </ul>
+
+
+ <h2><a name="MailingLists-QpidCommitsList"></a>Qpid Commits List</h2>
+
+ <p>The commits list is for recieving notifications about code being committed to the Qpid repository. The trafic on this list is automatically generated by Subversion. You should not post messages to this list.</p>
+
+ <ul>
+ <li>To subscribe to the commits list send an e-mail with subject 'subscribe' to:<br />
+ <a href="mailto:commits-subscribe@qpid.apache.org">commits-subscribe@qpid.apache.org</a></li>
+ <li>To remove yourself from the commits list send an e-mail with subject 'unsubscribe' to:<br />
+ <a href="mailto:commits-unsubscribe@qpid.apache.org">commits-unsubscribe@qpid.apache.org</a></li>
+ <li>The commits mailing list is archived. You can view the archive at:
+ <ul>
+ <li>Apache archive: <a href="http://mail-archives.apache.org/mod_mbox/qpid-commits/">http://mail-archives.apache.org/mod_mbox/qpid-commits/</a></li>
+ </ul>
+ </li>
+ </ul>
+</div>
diff --git a/doc/website/content/people.html b/doc/website/content/people.html
new file mode 100644
index 0000000000..4b78a0a255
--- /dev/null
+++ b/doc/website/content/people.html
@@ -0,0 +1,98 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>People</h1>
+
+ <p>This page lists some of the people who have contributed to Qpid.</p>
+
+ <h2>Committers</h2>
+ <p>The people listed below have made significant contributions to
+ Qpid by working long and hard to make quality software for the rest
+ of the world to use.</p>
+
+ <p>In addition to providing us contribuions, or being commmitters
+ some of the following people are also members of the Project
+ Management Committee (PMC). Refer to the How the ASF works for
+ details on meritocracy.</p>
+
+ <p>If you would like to contribute to Qpid please look at the Get
+ Involved page to see how you can contribute.</p>
+
+ <ul>
+ <li>Aidan Skinner</li>
+ <li>Alan Conway</li>
+ <li>Andrea Gazzarini</li>
+ <li>Andrew Kennedy</li>
+ <li>Andrew Stitcher</li>
+ <li>Arnaud Simon</li>
+ <li>Carl Trieloff</li>
+ <li>Chuck Rolke</li>
+ <li>Cliff Jansen</li>
+ <li>Gordon Sim</li>
+ <li>Jim Meyering</li>
+ <li>John O'Hara</li>
+ <li>Jonathan Robie</li>
+ <li>Ken Giusti</li>
+ <li>Kim van der Riet</li>
+ <li>Lahiru Gunathilake</li>
+ <li>Manuel Teira</li>
+ <li>Marnie McCormack</li>
+ <li>Martin Ritchie</li>
+ <li>Michael Goulish</li>
+ <li>Nuno Santos</li>
+ <li>Paul Fremantle</li>
+ <li>Rafael Schloming</li>
+ <li>Rajith Attapattu</li>
+ <li>Robbie Gemmell</li>
+ <li>Robert Godfrey</li>
+ <li>Robert Greig</li>
+ <li>Rupert Smith</li>
+ <li>Steve Huston</li>
+ <li>Ted Ross</li>
+ <li>Yoav Shapira</li>
+ </ul>
+
+ <h2>Contributors</h2>
+
+
+ <p>Many thanks to the following people for providing contributions:</p>
+
+ <ul>
+ <li>Colin Crist</li>
+ <li>Bhupendra Bhardwaj</li>
+ <li>Kevin Smith</li>
+ <li>Steve Vinoski</li>
+ <li>Steven Shaw</li>
+ <li>Tomas Restrepo</li>
+ </ul>
+
+ <h2>Mentors</h2>
+
+ <p>And many thanks to our project's mentors:</p>
+
+ <ul>
+ <li>Cliff Schmidt</li>
+ <li>Craig Russell</li>
+ <li>Paul Fremantle</li>
+ <li>Yoav Shapira</li>
+ <li>Scott Deboy</li>
+ </ul>
+</div>
diff --git a/doc/website/content/qpid_integrated_with.html b/doc/website/content/qpid_integrated_with.html
new file mode 100644
index 0000000000..a2b53209c7
--- /dev/null
+++ b/doc/website/content/qpid_integrated_with.html
@@ -0,0 +1,40 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+
+ <h1><a name="QpidIntegrations-AMQPintegrations"></a>AMQP integrations </h1>
+
+ <ul>
+ <li><a href="http://qpid.apache.org/archives/wiki/hermesjms.html" title="HermesJMS">HermesJMS</a> - The integration of Hermes JMS with Qpid</li>
+ <li>Twisted AMQP - <a href="https://launchpad.net/txamqp" class="external-link" rel="nofollow">https://launchpad.net/txamqp</a></li>
+ <li>Apache Camel - <a href="http://activemq.apache.org/camel/amqp.html" class="external-link" rel="nofollow">http://activemq.apache.org/camel/amqp.html</a></li>
+ <li>Apache Axis2 Java - <a href="http://wso2.org/library/3663" class="external-link" rel="nofollow">http://wso2.org/library/3663</a></li>
+
+ <li>Apache Axis2 C - <a href="http://ws.apache.org/axis2/c/docs/axis2c_manual.html#amqptrans" class="external-link" rel="nofollow">http://ws.apache.org/axis2/c/docs/axis2c_manual.html#amqptrans</a></li>
+ <li>Apache Synapse</li>
+ <li>libvirt - <a href="http://libvirt.org/" class="external-link" rel="nofollow">http://libvirt.org/</a> Provides QMF access to visualization</li>
+ <li>Ovirt - <a href="http://ovirt.org/" class="external-link" rel="nofollow">http://ovirt.org/</a> QMFC - used to build management tools</li>
+
+ <li>Python web plugin - Plug-in for AMQP support from web browser</li>
+ <li>Red Hat MRG - <a href="http://redhat.com/mrg" class="external-link" rel="nofollow">http://redhat.com/mrg</a> Distro of Qpid with added management console and persistence</li>
+ <li>Condor - <a href="http://www.cs.wisc.edu/condor/" class="external-link" rel="nofollow">http://www.cs.wisc.edu/condor/</a> QMF Agents and AMQP job routing</li>
+ </ul>
+</div>
diff --git a/doc/website/content/qpid_project_etiquette_guide.html b/doc/website/content/qpid_project_etiquette_guide.html
new file mode 100644
index 0000000000..7ce69c327a
--- /dev/null
+++ b/doc/website/content/qpid_project_etiquette_guide.html
@@ -0,0 +1,104 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+
+<h1>Qpid Project Etiquette Guide</h1>
+
+<h2><a name="QpidProjectEtiquetteGuide-Purpose"></a>Purpose</h2>
+
+<p>This guide, written by Rafael Schloming, gives both Qpid committers and submitters a useful introduction to project etiquette, shedding light on how we do things &amp; why. Following this etiquette makes the path to righteousness less long and winding !</p>
+
+<h2><a name="QpidProjectEtiquetteGuide-Maintainers"></a>Maintainers</h2>
+
+<p>The Qpid project consists of a number of major components spread across almost as many different languages. Thus it is rare for qpid committers to be experts in every single area of the project.</p>
+
+<p>As such it is expected that qpid committers make some effort to reach out to their teammates before directly modifying components that are outside their chosen areas. </p>
+
+<p>You should use the dev list to reach out to Qpid developers and comment on any JIRAs you're progressing.</p>
+
+<h2><a name="QpidProjectEtiquetteGuide-PatchSubmission"></a>Patch Submission</h2>
+
+<p>As a committer it can be difficult to decide whether/how to provide feedback when someone submits a patch. Often it is tempting to just fix up the patch and avoid the slower and sometimes awkward process of telling someone that they got some part of it wrong. </p>
+
+<p>However, it is necessary to ensure that those who submit patches get to learn what they need to know in order to become a valued qpid committer.</p>
+
+<p>In that spirit, here are a few guidelines for contributing patch submissions and how we handle them:</p>
+
+<ul>
+ <li>Submitters should produce the final patch(s) as applied to the tree. Producing a patch that needs little or no rework is a key skill for a qpid committer.</li>
+
+ <li>Maintainers may make requests for 'trivial' updates to the patch. Such requests are vital to ensuring that contributers get familiar with subtle yet important aspects of the code, stylistic conventions, etc.</li>
+
+ <li>Make sure the submitter is familiar with project etiquette so they understand why we make seemingly trivial requests. We'll ask new contributers to read this etiquette info for that reason !</li>
+
+ <li>A one-time patch from someone passing through may need nothing more than a polite thank you regardless of the content. If a submitter does aim for committership, best to make it plain you're planning to stay around on the project.</li>
+
+ <li>Break up unrelated changes. It wouldn't be considered correct for a committer to glom together too many unrelated changes within a single commit, and so we won't commit this kind of patch from submitters.</li>
+
+ <li>You need a JIRA for any patch to be attached to, which should accurately describe the change.</li>
+</ul>
+
+
+<h2><a name="QpidProjectEtiquetteGuide-BigIdeas"></a>Big Ideas</h2>
+
+<p>Every so often someone has a Big Idea that they get excited about and want to go do. They generally mail the list about it to give people the opportunity to comment, and then when nobody says anything they go off and do it.</p>
+
+<p>Fast forward six months later they commit/merge/enable/publish the result of their Big Idea, and suddenly everyone understands the full implications, and not everyone is happy. </p>
+
+<h3><a name="QpidProjectEtiquetteGuide-Guidelines"></a>Guidelines</h3>
+
+<p>So, here are a few guidelines for making sure this doesn't happen, starting with how to write a good proposal for a Big Idea:</p>
+
+<ul>
+ <li>Make sure your proposal is recognizable as a proposal. An easy way to avoid ambiguity is to start a new thread for your proposal and stick &quot;proposal&quot; somewhere in the subject.</li>
+
+ <li>Understand who and what your proposal effects, and make this clear. If you think X's implementation of Y doesn't deserve to live and you're going to rewrite the whole thing from scratch then make this very clear so X can object sooner rather than later.</li>
+
+ <li>Make sure you call out loudly that you intend to kill feature A, even if you think no-one on earth should care.</li>
+
+ <li>Even if you're going to write an Atari emulator, and you're 100% sure that it won't overlap with anything in the rest of the project, make sure you understand how and why it relates to the rest of the project in general, and make that clear.</li>
+
+ <li>Be concrete. Often a proposal of the form &quot;hey, I did a little of this, here is a proof-of-concept, I'd like to do it for real now&quot; is far more effective than a proposal of the form &quot;hey, I have this vague idea about this, I'm going to vaguely suggest it would be good if someone did it&quot;.</li>
+
+ <li>Talk about the long term implications of your proposal. If it's code then someone needs to maintain it, and committers will expect this to be you. Make clear your intentions.</li>
+
+ <li>Never assume silence implies complicity, more likely it means people didn't understand the implications of your proposal, or didn't have time to figure out why they didn't like it. Ask again !</li>
+
+ <li>The bigger your idea is, the more time and effort you should spend on the proposal, and ensuring that you get positive responses and deal with the comments and feedback provided in your actual implementation.</li>
+</ul>
+
+
+<h3><a name="QpidProjectEtiquetteGuide-Talkearly%2Ctalkoften"></a>Talk early, talk often</h3>
+
+<p>No matter how incredibly excellent your proposal is, there is going to need to be some discussion before the result of your Big Idea is blessed. Here are some things you can do to help that discussion go smoothly:</p>
+
+<ul>
+ <li>Make frequent progress reports. Every hour/day/week/month you spend working without telling people what you're doing is an hour/day/week/month of your time that you risk wasting.</li>
+
+ <li>Define milestones and make them visible to the rest of the project. Just like a concrete proof-of-concept can help a proposal, it helps to give people a concrete look at what you're doing while it's in progress. This can go a long way towards avoiding surprises.</li>
+</ul>
+
+<h3><a name="QpidProjectEtiquetteGuide-Andfinally....."></a>And finally .....</h3>
+
+<p>When the time does come to commit/merge/enable/publish your Big Idea, it really shouldn't be a surprise to anyone if you've followed the steps up until now, but make sure you let people know in advance by making note in your final few progress reports of when you expect to be finished, and sending a note to the dev list a day or so before you flip the big switch.</p>
+
+</div>
+
diff --git a/doc/website/content/release_notes_0.8.html b/doc/website/content/release_notes_0.8.html
new file mode 100644
index 0000000000..2e0bb1fd7a
--- /dev/null
+++ b/doc/website/content/release_notes_0.8.html
@@ -0,0 +1,437 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>0.8 Release Notes</h1>
+
+<p>The full list of changes in the Qpid 0.8 release incorporates both the issues worked on during the 0.7 development stream and any final touches made during the 0.8 release process. A list of these JIRA issues can be found below.</p>
+
+<h3>JIRA Issues</h3>
+
+<h4>New Feature</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-664'>QPID-664</a>] - High-level C++ client API.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1403'>QPID-1403</a>] - Add SSL support for C++ Windows broker/client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1940'>QPID-1940</a>] - QMF Feature Request - Structured exceptions for method failure</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2321'>QPID-2321</a>] - [Java Broker] Add "conflation queue" to Java Broker</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2363'>QPID-2363</a>] - JMS Map Message Should Support AMQP 0-10 Encoded Map As Message Body</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2365'>QPID-2365</a>] - Reroute messages on a queue - remove messages from a queue and send them to an exchange</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2412'>QPID-2412</a>] - Support for SASL EXTERNAL when using SSL</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2500'>QPID-2500</a>] - Transport security for the WCF channel</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2555'>QPID-2555</a>] - Qpid Info OSGI plugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2581'>QPID-2581</a>] - Create a ConfigurationManager to allow plugins to provide configuration handling classes</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2589'>QPID-2589</a>] - Add a .NET binding to QPID Messaging API</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2614'>QPID-2614</a>] - QueueConfiguration requires to configurations to be provided on construction</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2646'>QPID-2646</a>] - Qpid Messaging address support for WCF Channel</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2700'>QPID-2700</a>] - Ability to remove queue binding in QPID</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2807'>QPID-2807</a>] - More flexible acknowledgement</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2867'>QPID-2867</a>] - enable the JMX management console to remove bindings from direct/topic exchanges</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2909'>QPID-2909</a>] - Hybrid SQL-CLFS persistence store for C++ broker on Windows</li>
+</ul>
+
+<h4>Bug</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1662'>QPID-1662</a>] - TimeToLiveTest.testPassive occasionally receives more messages.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1879'>QPID-1879</a>] - The client library uses a new thread for every connection</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1904'>QPID-1904</a>] - Timestamps are incorrect</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2137'>QPID-2137</a>] - StringIndexOutOfBounds when formating Connection Message during failed systest run.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2165'>QPID-2165</a>] - MINANetworkDriverTest fails to socket already in use</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2173'>QPID-2173</a>] - Java client should set the process ID in the client properties during Connection open</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2174'>QPID-2174</a>] - When kerberos auth is used, Java client should use the kerberos userid &amp; domain when setting the userid in messages</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2186'>QPID-2186</a>] - Windows - "vector iterator not dereferencable"</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2262'>QPID-2262</a>] - Random test failures in SimpleACLTest</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2265'>QPID-2265</a>] - Ruby Rakfile References an old file</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2297'>QPID-2297</a>] - ACL policy won't allow "." in the realm for users added to a group</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2298'>QPID-2298</a>] - CMake-based install based on released sources tries to include generated headers from build tree</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2299'>QPID-2299</a>] - C++ Messaging drain and spout examples need vcproj files</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2300'>QPID-2300</a>] - C++ packaging directory not included in release</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2301'>QPID-2301</a>] - C++ examples changed at r880718; obsolete vcproj files not removed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2302'>QPID-2302</a>] - Missing header.html, footer.html in C++ docs/api distribution</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2306'>QPID-2306</a>] - C++ uninstaller does not uninstall some header files.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2318'>QPID-2318</a>] - qpid-tool does not seem to issue session acknowledgements </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2320'>QPID-2320</a>] - Failed acquire on LVQ causes broker crash</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2323'>QPID-2323</a>] - Add uuid to variant</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2325'>QPID-2325</a>] - [Java Broker] SASL PLAIN authentication does not work when both an authentication and authorization id are supplied</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2328'>QPID-2328</a>] - Querying for 500 objects causes C++ based ruby console to hang</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2336'>QPID-2336</a>] - Cannot disable heatbeats in JMS client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2338'>QPID-2338</a>] - [C++ Broker] Ring queue does not properly implement byte size limits</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2339'>QPID-2339</a>] - JMS (0-10 client) does not verify if it supports the SASL mechanisms sent by the broker.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2340'>QPID-2340</a>] - [Java] ProducerFlowControlTest failing due to race condition in test</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2344'>QPID-2344</a>] - qpid/messaging/uuid.h r899657 breaks Windows build...</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2347'>QPID-2347</a>] - Subscribers are never notified if queue is deleted from under them</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2355'>QPID-2355</a>] - QMF bindings build conflicts with installed qmf headers</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2360'>QPID-2360</a>] - declaring virtualhost level firewall configuration in virtualhosts.xml leads to NPE on startup</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2361'>QPID-2361</a>] - exchange configuration attributes are ignored when configuration is placed in virtualhosts.xml</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2366'>QPID-2366</a>] - Windows C++ broker port written to stdout at startup is wrong</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2370'>QPID-2370</a>] - TTR-Qpid-07-NA failed due to channel error 504 during tear down</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2372'>QPID-2372</a>] - PeriodicTimerImpl addition broker Windows build</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2374'>QPID-2374</a>] - qpidd: --require-encryption with "--auth no" will reject SSL connections as being "un-encrypted" </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2376'>QPID-2376</a>] - C++ broker build broken at 20:00 Thurs Jan 28, 2010</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2378'>QPID-2378</a>] - WCF/C++ Client subtree lacks Apache licensing files</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2387'>QPID-2387</a>] - qpidd does not replicate management agent lists, causes brokers to exit. </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2388'>QPID-2388</a>] - user-defined signals can cause process terminate</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2392'>QPID-2392</a>] - Powershell scripts not included in release source kits</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2395'>QPID-2395</a>] - fd leak in Connection</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2398'>QPID-2398</a>] - C++ examples' Visual Studio projects need BOOST_ALL_DYN_LINK to build against installed kit</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2406'>QPID-2406</a>] - Consistent approach to durations in qpid::messaging api</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2407'>QPID-2407</a>] - C++ SSL session can get bad buffer management</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2413'>QPID-2413</a>] - ACL - error handling/bounds checking</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2418'>QPID-2418</a>] - Existing durable subscription with selector is not unsubscribed during change to new subscription</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2420'>QPID-2420</a>] - Windows SQL-based persistence loses prepared two-phase transactions on broker restart</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2422'>QPID-2422</a>] - DerbyStore does not persist queue exclusivity or arguments</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2426'>QPID-2426</a>] - Better error message and logging when receving/sending from/to empty address</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2427'>QPID-2427</a>] - Modify browse option in-line with path chosen for python client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2428'>QPID-2428</a>] - qpid.subject should be set on outgoing messages if the address specifies a suject</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2429'>QPID-2429</a>] - headers exchange does not match correctly on a map entry with a null value</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2430'>QPID-2430</a>] - Java broker emits NPE following qpid-tool being connected</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2431'>QPID-2431</a>] - .NET csproj files missing Apache license text</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2433'>QPID-2433</a>] - qpid-server.bat fails if the path contains a space character</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2434'>QPID-2434</a>] - make clean in qpid/cpp/src/tests/testagent breaks build</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2435'>QPID-2435</a>] - Deadlock can occur during the registration of a qmf agent</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2437'>QPID-2437</a>] - Define exceptions for messaging API</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2438'>QPID-2438</a>] - Performance tests do not correctly populate the message with the given MessageSize</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2439'>QPID-2439</a>] - CMake builds broken 08-Mar-2010</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2441'>QPID-2441</a>] - make check fails because of wrong sorting</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2444'>QPID-2444</a>] - JMS client does not verify that the hostname connected to matches that specified in the servers certificate</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2445'>QPID-2445</a>] - JMS Client needs to extract the user ID from the external auth mechanism when SASL EXTERNAL is used</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2452'>QPID-2452</a>] - Inconsistent handling on strings between C++ and Python messaging APIs</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2463'>QPID-2463</a>] - C++ install step puts api docs in wrong place on Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2465'>QPID-2465</a>] - Ant 1.8.x javac task prints warning message during builds</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2467'>QPID-2467</a>] - Windows install doesn't include qpidxarm.dll or broker plugins</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2468'>QPID-2468</a>] - WCF client samples can't resolve the DLLs when installed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2471'>QPID-2471</a>] - Java client releases messages in an unpredictable order on recover</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2472'>QPID-2472</a>] - QpidCompositeRollingAppender log4j configuration is misleading</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2474'>QPID-2474</a>] - ACL file reader can trip vector iter validity checking</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2475'>QPID-2475</a>] - qpid/messaging/Session.h r928855 breaks Windows build - macro conflict</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2481'>QPID-2481</a>] - Deadlock in Qpid 0.6</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2482'>QPID-2482</a>] - Topic Exchange can duplicate messages.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2484'>QPID-2484</a>] - Interoperability tests fail due to attempts to print out contents of JMS Message objects, and do not parse command line properies</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2487'>QPID-2487</a>] - Tearing down one dynamic route may delete other independent routes in the federation.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2488'>QPID-2488</a>] - ACL - error handling/bounds checking</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2493'>QPID-2493</a>] - AMQPEncodedMapMessage does not support nested maps and lists</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2497'>QPID-2497</a>] - messaging api silently ignores unrecognised/invalid address options</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2502'>QPID-2502</a>] - securityTracker open() call is made on exchangeTracker instance instead</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2503'>QPID-2503</a>] - CommandLineParser does not print '-' when showing options</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2506'>QPID-2506</a>] - QMF: fix encoding/decoding of map and list method call arguments</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2507'>QPID-2507</a>] - C++ broker can deadlock when processing a bind.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2511'>QPID-2511</a>] - ConnectionImpl instance may be deleted before IO threads are finished with the underllying DispatchHandle</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2515'>QPID-2515</a>] - Need to be able to set flow control in Java on a per destination level</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2520'>QPID-2520</a>] - Broken POM generation on Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2521'>QPID-2521</a>] - ACL module core dumps if management is disabled</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2523'>QPID-2523</a>] - When reloading a large acl file while acl lookup is in progress, the broker core dumps</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2526'>QPID-2526</a>] - Ant build fails if the path contains a space character</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2553'>QPID-2553</a>] - CMakeLists wrong file name </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2558'>QPID-2558</a>] - client connection.open to a non-broker on qpid 0.6 windows segfaults with: access violation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2561'>QPID-2561</a>] - Download page does not follow ASF standards</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2562'>QPID-2562</a>] - website does not have any links to the Issue tracker</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2563'>QPID-2563</a>] - Website does not have required ASF elements</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2564'>QPID-2564</a>] - Wcf functional test source file is absent</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2570'>QPID-2570</a>] - Broker uses NotAllowedException for ACL violations, should use UnauthorisedAccessException</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2587'>QPID-2587</a>] - PollableCondition test fails on Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2600'>QPID-2600</a>] - ACL policy doesn't permit certain characters in usernames added to groups</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2605'>QPID-2605</a>] - Recovered messages larger than 65523 bytes result in framing violation ()</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2607'>QPID-2607</a>] - Package name typo for CRAMMD5HexInitialiserTest.java</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2608'>QPID-2608</a>] - AMQPException messages contain duplicate AMQConstant text</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2609'>QPID-2609</a>] - MockAMQQueue does not implement getName</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2610'>QPID-2610</a>] - AMQConstant Map usage is not correct</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2611'>QPID-2611</a>] - AMQConnectionFailureException does not record reason for underlying cause if it is an AMQPException</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2612'>QPID-2612</a>] - Recent DLL qpidtypes breaks the build on Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2613'>QPID-2613</a>] - message data is not commited to the persistent store on 0-8/0-9 codepath</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2615'>QPID-2615</a>] - JMX Management Console fails to connect to 0.5 and below brokers if run in a Java5 VM</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2626'>QPID-2626</a>] - Typo in ServerConnectionDelegate</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2631'>QPID-2631</a>] - Race in qpid::client::Bounds causes (rare) deadlock</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2634'>QPID-2634</a>] - CRLF line endings in the shell scripts</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2635'>QPID-2635</a>] - Ant tests fail with OutOfMemoryError due to PermGen space exhaustion</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2636'>QPID-2636</a>] - disconnect() callback on broker results in leaked connections</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2637'>QPID-2637</a>] - connection.start() hangs if the connection is not accepted</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2640'>QPID-2640</a>] - options string for connection does not work for some types</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2641'>QPID-2641</a>] - The bitwise AND operator used instead of logical AND in QpidLog4JConfigurator.java</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2642'>QPID-2642</a>] - The bitwise AND operator used instead of logical AND in QpidLog4JConfigurator.java</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2644'>QPID-2644</a>] - Console examples sometimes fail due to not waiting for the broker connection to complete</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2647'>QPID-2647</a>] - Typo in str8-latin type definition for 0-10</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2649'>QPID-2649</a>] - Segfault on shutting down qpidd</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2650'>QPID-2650</a>] - DerbyStore only ever uses auto-commit connections</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2653'>QPID-2653</a>] - Double checked locking in org.apache.qpid.server.transport.ThreadPoolFilter</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2654'>QPID-2654</a>] - Access control plugin should use Actor logging</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2657'>QPID-2657</a>] - Verify/correct error handling on client 0-10 codepath</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2658'>QPID-2658</a>] - Update Java 0-10 profile excludes</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2661'>QPID-2661</a>] - The 0-8 BasicGetMethodHandler should return NOT_IMPLEMENTED for 0-10 messages</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2662'>QPID-2662</a>] - The FirewallPlugin should accept a ServerSocket, not the string representation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2665'>QPID-2665</a>] - Remove BROKER from object types for plugins</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2668'>QPID-2668</a>] - PlainPasswordPrincipalDatabase - code improvement </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2670'>QPID-2670</a>] - Concurrent tagging of message with trace id while message is delivered from another queue causes segfault</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2673'>QPID-2673</a>] - retained 0-10 ImplicitAcceptDispositionChangeListener objects can lead to connection closure timeout and broker OOM</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2674'>QPID-2674</a>] - heartbeats can cause seg faults under tcp on linux</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2677'>QPID-2677</a>] - QMF: console.py sends agent locate request before it has enabled receiving data indications.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2686'>QPID-2686</a>] - Update Ant doc task with better configuration</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2687'>QPID-2687</a>] - The PluginManager does not auto-deploy bundles properly</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2688'>QPID-2688</a>] - Exclusive queues deleted before unacked messages are requeued; unacked messages not routed to alternate-exchange as a result.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2691'>QPID-2691</a>] - ttl is lost for federation routes where trace id is added</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2694'>QPID-2694</a>] - Memory leak in 0-8/0-9 AMQSessions on channel close</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2695'>QPID-2695</a>] - VirtualHostConfigRecoveryHandler can NPE or bind to the wrong exchange on binding recovery</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2696'>QPID-2696</a>] - Addressing strings in the jndi properties file is interpreted as binding urls</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2697'>QPID-2697</a>] - AMQConnectionURL options do not appear in the toString representation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2698'>QPID-2698</a>] - Certain amqp 0-10 message properties are not exposed through messaging apis message class</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2702'>QPID-2702</a>] - --max-connections not work when using cluster</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2704'>QPID-2704</a>] - Provide scavenge() for SimpleQueueEntryList - TRUNK MERGE</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2706'>QPID-2706</a>] - Visual Basic example includes a directory whose name contains a space</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2707'>QPID-2707</a>] - Cmake build doesn't output all needed settings to build a valid shared library name for loading</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2716'>QPID-2716</a>] - QMF: c++ agent does not set the agent name attribute in an object id during addObject() call.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2718'>QPID-2718</a>] - Update the common.bnd to match client.bnd, release version</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2719'>QPID-2719</a>] - Some SSL errors do not get reported up the stack or in the log file.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2722'>QPID-2722</a>] - The JMS 0-10 client does not make use of the subject specified via "qpid.subject" in the application properties.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2723'>QPID-2723</a>] - NullPointerException thrown when you pass an address based destination to the setJMSReplyTo() in a Message.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2724'>QPID-2724</a>] - Docbook generation is fixed on xsl-stylesheets-1.75.2 </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2727'>QPID-2727</a>] - ./src/qpidd --load-module ./src/.libs/cluster.so --cluster-name blah --known-hosts-url amqpx:blah segfaults</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2728'>QPID-2728</a>] - Windows icon/version additions broke nightly builds</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2734'>QPID-2734</a>] - testAuthenticatedUsername fails on cmake builds</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2735'>QPID-2735</a>] - If no subject is specified and if the exchange type is topic, "#" should be used as the default. </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2741'>QPID-2741</a>] - DerbyMessageStore is not shut down when told to close</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2742'>QPID-2742</a>] - DerbyMessageStore createExchange() method does not function</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2744'>QPID-2744</a>] - FieldTable throws a NullPointerException in setObjectProperty rather than expected AMQPInvalidClassException</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2749'>QPID-2749</a>] - [Java Broker] Add -XX:+ExplicitGCInvokesConcurrent to qpid-server[.bat]</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2752'>QPID-2752</a>] - Cannot create LVQ's using the JMS client.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2754'>QPID-2754</a>] - C++ broker crashes due to management object database corruption</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2755'>QPID-2755</a>] - Windows SDK has no README</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2757'>QPID-2757</a>] - Remove double-checked-locking in ThreadPoolFilter</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2758'>QPID-2758</a>] - Remove call to Thread.run() in FirewallPlugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2760'>QPID-2760</a>] - Only client 0-10 session sync should throw any exceptions</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2764'>QPID-2764</a>] - WinSdk cpp examples do not compile</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2766'>QPID-2766</a>] - string to double conversion results in questionable precision</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2769'>QPID-2769</a>] - UnexpectedMethodException is serializable but does not implement serialVersionUID</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2774'>QPID-2774</a>] - Incorrect logic when querying for existance of an exchange while parsing an address string.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2781'>QPID-2781</a>] - QPBRKR process name tag should be declared in qpid-server script, not qpid-run</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2785'>QPID-2785</a>] - QpidTypes.pdb is not installed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2786'>QPID-2786</a>] - Cannot create a durable subscription using a destination created with an addressing string</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2788'>QPID-2788</a>] - jmx management console can throw ConcurrentModificationException whilst connected to (older) brokers with MBeans actively (un)registering</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2791'>QPID-2791</a>] - QMF: c++ agent publishes all data object updates in a single message.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2797'>QPID-2797</a>] - Add an extra boolean to 0-10 session to indicate closing</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2798'>QPID-2798</a>] - C++ Messaging Client .NET binding fails to clone managed objects correctly</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2799'>QPID-2799</a>] - Temporary queue names should be more meaningful</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2805'>QPID-2805</a>] - The windows resource version for qmfengine dll is hard coded to an unusable value</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2806'>QPID-2806</a>] - QMF: python console will incorrectly delete agents if the session is configured with rcvHeartbeats=False</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2810'>QPID-2810</a>] - QMF: python console does not properly shutdown broker thread in some error cases.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2817'>QPID-2817</a>] - Connection::close() may hang if broker is suspended</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2828'>QPID-2828</a>] - jmx management console can NPE when adding a queue to the navigation tree after its MBean has just been unregistered but before the view is refreshed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2842'>QPID-2842</a>] - references to other objects in qpid-tool use id that doesn't match anything else</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2844'>QPID-2844</a>] - JMS client should use the exchange given in the address if the exchange name is not explicitly given in x-bindings </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2845'>QPID-2845</a>] - JMS client should allow arbitary arguments map in the x-bindings section</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2846'>QPID-2846</a>] - QMF: python console crashes on race condition when deleting an agent.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2851'>QPID-2851</a>] - Programming with Apache Qpid doc confusing over confirmations</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2854'>QPID-2854</a>] - [Java Broker] 0-10 Queue Exclusive behaviour not correctly implemented</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2855'>QPID-2855</a>] - [Java Broker] 0-10 Transport should not block on awaiting for close confirmation from client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2856'>QPID-2856</a>] - [Java Broker] Should send 530 not-allowed exception onattempt to delete a defautl exchange (e.g. amq.direct, amq.topic)</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2857'>QPID-2857</a>] - [Java] Running FindBugs against Java codebase reveals room for improvement</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2860'>QPID-2860</a>] - C++ hello_xml example receives all message content, not just what's wanted</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2861'>QPID-2861</a>] - JMS client needs to handle duplicate commands replayed after failover</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2868'>QPID-2868</a>] - throw exception users when attempt is made to move/copy messages to a non-existent queue</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2869'>QPID-2869</a>] - prevent specifying the souce queue as destination when moving/copying messages</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2870'>QPID-2870</a>] - an unauthorised attempt to delete a queue will prevent all further deletion attempts</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2872'>QPID-2872</a>] - Java broker incorrectly indicates it supports sending 0-10 heartbeats when it currently does not</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2875'>QPID-2875</a>] - Federation route propagation tests fail occassionally.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2876'>QPID-2876</a>] - Design issues in Java client failover</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2877'>QPID-2877</a>] - QPID_JAVA_MEM usage in windows qpid-server.bat fails and prevents startup</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2879'>QPID-2879</a>] - The 0-10 Java Client is sending null arguments on messageSubscribe</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2880'>QPID-2880</a>] - QMF: C++ agent does not accept method calls with map/list arguments that contain booleans</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2883'>QPID-2883</a>] - QMF: python console does not pass V2-style events to the console callback</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2885'>QPID-2885</a>] - C++ qmf console shows memory leaks under valgrind.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2886'>QPID-2886</a>] - Address the issues outlined by findbugs on 0.5.x-dev branch</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2888'>QPID-2888</a>] - QMF: C++ agent does not re-publish all management data on reconnect to the broker.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2892'>QPID-2892</a>] - IBM JVM throws different exception when signal handler fails, stopping broker execution</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2896'>QPID-2896</a>] - Incorrect detection of data types in address parameters - C++ client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2898'>QPID-2898</a>] - broker is unable to evaulate "JMSMessageID IS NULL" correctly when using 0-10</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2910'>QPID-2910</a>] - Small fix for python timeout tests</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2914'>QPID-2914</a>] - address parser doesn't recognize None</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2915'>QPID-2915</a>] - Qpid Cpp Messaging .NET Binding does not properly handle Qpid type VAR_VOID</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2916'>QPID-2916</a>] - C++ broker &amp; Python client will silently truncate strings whose length is greater than the max length supported by the type.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2918'>QPID-2918</a>] - Assembly mis-named in csharp.example.declare_queues</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2919'>QPID-2919</a>] - hello_world, hello_xml examples left out of CMakeLists.txt</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2922'>QPID-2922</a>] - Qpid Cpp Messaging .NET Binding does not implement FailoverUpdate class</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2923'>QPID-2923</a>] - Qpid Messaging .NET Binding fails to translate exceptions from C++ to .NET</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2925'>QPID-2925</a>] - MSSQL-based message store throws uncaught exception if db recovery throws an error</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2926'>QPID-2926</a>] - Simple example code does not link under Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2927'>QPID-2927</a>] - JMX Shutdown plugin throws InstanceNotFoundException during broker shutdown</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2928'>QPID-2928</a>] - Java client always create exclusive lock for the queue when use with the new addressing scheme</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2929'>QPID-2929</a>] - the broker-plugins jars are not incorporated into the broker release binary when using 'ant release-bin'</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2931'>QPID-2931</a>] - nulling the MessageReference handle on the Message during QueueEntry disposal can result in NPE</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2940'>QPID-2940</a>] - message-accept records are not cleaned up unless getUnsettledAcks() is called</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2941'>QPID-2941</a>] - CLFS store recovery can encounter invalid C++ iterator</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2948'>QPID-2948</a>] - Generated API docs have extraneous macro names in method signatures</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2950'>QPID-2950</a>] - DerbyMessageStore incorrectly logs an error for an expected exception indicating successfull database shutdown</li>
+</ul>
+
+<h4>Improvement</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1308'>QPID-1308</a>] - JMS Temprory Queue naming</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1447'>QPID-1447</a>] - Broker does not handle with slow consumers effectively</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1825'>QPID-1825</a>] - Improve TimeToLiveTest.testActive to prevent spurious failures</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1831'>QPID-1831</a>] - Improve JMS Destination abstraction to better support AMQP and Qpid specific features</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2213'>QPID-2213</a>] - qpid/framing/BodyHolder.* still needed?</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2251'>QPID-2251</a>] - Provide portable signal mechanism for the C++ QMF agent API</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2283'>QPID-2283</a>] - java Testkit scripts should have sensible defaults when setting up the environment</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2313'>QPID-2313</a>] - Release notes for the WCF/C++ client </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2322'>QPID-2322</a>] - remove redundant "version" key property from the ObjectName of the JMX MBeans</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2327'>QPID-2327</a>] - Enhance qpid-config to deal with xml and headers brokers</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2348'>QPID-2348</a>] - [C++] The HeadersExchange does not support federation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2351'>QPID-2351</a>] - Allow the following config properties to be set in the ConnectionURL</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2371'>QPID-2371</a>] - Missing includes for MSVC 2005 compiler</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2380'>QPID-2380</a>] - define and implement reliability options for senders and receivers</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2415'>QPID-2415</a>] - Update doc for new SSL support in Windows broker and client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2421'>QPID-2421</a>] - Augment performance tests to allow pre-filling broker, fill and consume only runs.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2423'>QPID-2423</a>] - Add Constructors to set initial value of content for MapContent and ListContent</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2424'>QPID-2424</a>] - Augment CPU/GC processing scripts to provide additional stats.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2425'>QPID-2425</a>] - Augment TKTestRunner to provide latency data for throughput tests.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2446'>QPID-2446</a>] - JMS Client should allow a trust/key store per connection rather than one per JVM</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2447'>QPID-2447</a>] - JMS Client should allow multiple connections, each with it's own SSL certificate from the same JVM</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2466'>QPID-2466</a>] - Replace WeakReference use with SoftReference for enhanced message caching</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2477'>QPID-2477</a>] - std::cout in agent not used anymore</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2479'>QPID-2479</a>] - Log in debug aevery time the housekeeping thread runs</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2483'>QPID-2483</a>] - Can't build samples from Windows installer</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2489'>QPID-2489</a>] - Remove references to boost:: and qpid::framing:: from QMF-generated cpp files</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2492'>QPID-2492</a>] - Changes to brokertest.py to better manage Windows brokers</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2496'>QPID-2496</a>] - The following changes needs to be done for JMS Client to support the changes made in addressing</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2501'>QPID-2501</a>] - WCF Binding Configuration parameters</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2508'>QPID-2508</a>] - Replace org.apache.qpid.util.concurrent.Condition with a CountDownLatch</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2512'>QPID-2512</a>] - Change Default Destination Syntax to ADDR (addressing)</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2513'>QPID-2513</a>] - Expose the ServerConfiguration as an OSGI service for use in plugins</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2516'>QPID-2516</a>] - New sample to show how to specify WCF bindings in config files</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2522'>QPID-2522</a>] - Remove the dependency on Commons Lang for the Java client</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2525'>QPID-2525</a>] - Update QueueInformation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2529'>QPID-2529</a>] - Update the Felix OSGI framework to a recent release</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2530'>QPID-2530</a>] - Refactor the broker-plugins directory setup to allow adding new modules </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2533'>QPID-2533</a>] - Modify config.xml to have ${QPID_HOME}/lib/plugins as the standard OSGI plugin directory</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2534'>QPID-2534</a>] - Add org.apache.qpid.protocol and org.apache.junit.extensions.util to the packages exported by the PluginManager </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2547'>QPID-2547</a>] - Improve PluginTest.java in order to test new OSGI plugins</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2557'>QPID-2557</a>] - Hello World example</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2569'>QPID-2569</a>] - Implement the SimpleXML as an OSGI plugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2573'>QPID-2573</a>] - Implement the Firewall functionality as an OSGI plugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2575'>QPID-2575</a>] - Create a Connection and Session model to abstract protocol versions</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2579'>QPID-2579</a>] - InternalBrokerBaseCase can fail to test tearDown</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2580'>QPID-2580</a>] - Update build path to allow plugins to use systests</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2582'>QPID-2582</a>] - Update QTC to print stack traces from AppRegistry during InVM startup</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2585'>QPID-2585</a>] - Upgrade Felix to 2.0.5</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2590'>QPID-2590</a>] - Update install notes for transactions</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2594'>QPID-2594</a>] - Exception chaining for JMSExceptions</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2595'>QPID-2595</a>] - WCF programming guide documentation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2599'>QPID-2599</a>] - Allow Qpid users to configure the Java client logging using an sl4j binding of their choice, instead of Qpid shipping a defualt binding.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2618'>QPID-2618</a>] - Add org.apache.common to the PluginManager exported packages</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2619'>QPID-2619</a>] - Capture the PID for the qpid broker on unix platforms</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2628'>QPID-2628</a>] - c++ messaging API dotnet binding needs received message callback</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2629'>QPID-2629</a>] - Remove Java client dependency on commons-collection.jar</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2651'>QPID-2651</a>] - replace the deprecated Derby 10.3.2.1 (data corruption bug) with a newer version</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2663'>QPID-2663</a>] - QMF: Improvement the behavior of the python console implementation based on scale testing. </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2667'>QPID-2667</a>] - Cpp INSTALL-WINDOWS build instructions are out of date</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2669'>QPID-2669</a>] - Base64MD5PasswordFilePrincipalDatabase - code improvement</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2671'>QPID-2671</a>] - Doc Book Programming-In-Apache-Qpid needs update for Messaging .NET binding</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2678'>QPID-2678</a>] - Qpid Shutdown OSGI plugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2689'>QPID-2689</a>] - Cpp build on Windows does not produce debug symbol PDB file</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2710'>QPID-2710</a>] - C++ Messaging Client .NET binding is not compiled in SDK</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2711'>QPID-2711</a>] - Add version and icon resources to Windows C++ exe/dll files</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2717'>QPID-2717</a>] - Update the bnd tool to version 0.0.384</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2731'>QPID-2731</a>] - enable getting/setting queue exclusivity property via the JMX management interface</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2736'>QPID-2736</a>] - Allow session.createQueue and session.createTopic methods to accept an address string</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2737'>QPID-2737</a>] - Add support in the JMS client for x-subscribe props defined in the new addressing format</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2738'>QPID-2738</a>] - Add support in the JMS client for "mode" option defined in the new addressing format</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2761'>QPID-2761</a>] - Add tests 4 and 5 to the .NET client (0.8)</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2765'>QPID-2765</a>] - WinSdk does not .NET Binding examples</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2771'>QPID-2771</a>] - Use plugins rather than plugin in package naming</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2772'>QPID-2772</a>] - Add fully qualified path to Regex class on default.build</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2775'>QPID-2775</a>] - use JMX to reload the security configuration for FirewallConfigTest</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2780'>QPID-2780</a>] - Improve the operational logging for 0-10 code path</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2782'>QPID-2782</a>] - QMF: improve the console api for selective filtering of unsolicited V2 indications.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2783'>QPID-2783</a>] - Eliminate the UnknownMessageTypeException from o.a.q.server.protocol package</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2801'>QPID-2801</a>] - Implement LogSubject Interface in 0-10 Subscription/ServerConnection/ServerSession Objects</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2802'>QPID-2802</a>] - Implement selective operational logging via log4j.xml configuration</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2803'>QPID-2803</a>] - Abbreviate the log messages and optimize the log string operations for speed and size</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2809'>QPID-2809</a>] - Once an AMQDestination object resolves an address, it should not try to resolve it again when used in subsequent operations. </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2820'>QPID-2820</a>] - Remove the ManagedChannel interface from broker code</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2822'>QPID-2822</a>] - Move the documentation from o.a.q.server.logging.messages.*_logmessages.properties into qpid docbook documentation</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2824'>QPID-2824</a>] - Use toLogString rather than toString on LogSubject(s)</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2825'>QPID-2825</a>] - The class o.a.q.transport.Sink is not used and can be safely removed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2826'>QPID-2826</a>] - The class o.a.q.transport.Result is not used and can be safely removed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2827'>QPID-2827</a>] - QPID Cpp WinSDK does not contain 64-bit libraries</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2829'>QPID-2829</a>] - The o.a.q.transport.Echo class is not used and can be safely removed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2831'>QPID-2831</a>] - Use slf4j as the logging mechanism across all code paths</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2832'>QPID-2832</a>] - Collate all the LogSubject formatting strings in a static class</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2833'>QPID-2833</a>] - Add a Generic Actor for 0-10 Logging</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2834'>QPID-2834</a>] - Implement subscriptions (SUB) operational logging on 0-10 </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2835'>QPID-2835</a>] - Implement connections (CON) operational logging on 0-10</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2837'>QPID-2837</a>] - The o.a.q.server.transport.ThreadPoolFilter class is not used and can be safely removed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2838'>QPID-2838</a>] - reduce code duplication in logging tests</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2839'>QPID-2839</a>] - Implement Channel (CHN) operational logging on 0-10 protocol </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2840'>QPID-2840</a>] - Use a configurable message prefix on the AbstractActor class</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2841'>QPID-2841</a>] - QMF: set TTL on agent heartbeat messages</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2843'>QPID-2843</a>] - remove redundant/duplicated logging</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2853'>QPID-2853</a>] - ReadMe for WinSDK is unclear about Visual Studio version support.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2858'>QPID-2858</a>] - Implement FilterManager for 0-10 subscriptions</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2859'>QPID-2859</a>] - QMF: C++ agent should store its configured name in the config file if available.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2862'>QPID-2862</a>] - QMF: python console should abort any pending transactions when the broker is deleted.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2863'>QPID-2863</a>] - Propagate WinSDK Build Version numbers to the Messaging .NET Binding</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2865'>QPID-2865</a>] - Cpp messaging examples compile problems for x64</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2866'>QPID-2866</a>] - Remove unneeded build files and directory</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2884'>QPID-2884</a>] - Add the method arguments to Subscription_0_10 </li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2887'>QPID-2887</a>] - Remove the System.out.println statements from SlowConsumerDetectionConfiguration</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2897'>QPID-2897</a>] - C++ broker: improve scale and speed of route matching algorithm for topic exchanges.</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2906'>QPID-2906</a>] - Qpid WinSDK .NET Binding does not support Release configuration</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2907'>QPID-2907</a>] - Developing Qpid Cpp Messaging .NET Binding requires setup help</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2911'>QPID-2911</a>] - Remove the class printing from the log4j layout as the (%F:%L) provides sufficient debug information</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2913'>QPID-2913</a>] - QPID Cpp Messaging Libraries for WinSDK Are Not Signed</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2924'>QPID-2924</a>] - Refactor WinSDK to create separate debug and release /bin directories</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2942'>QPID-2942</a>] - enable the Java broker convenience binary release package to be run out-of-the-box</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2943'>QPID-2943</a>] - add the examples to the Java client binary convenience release package</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2947'>QPID-2947</a>] - use a newer sl4j-api release to allow the Java client binary convenience package to be used out-of-the-box</li>
+</ul>
+
+<h4>Test</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2359'>QPID-2359</a>] - Need functional tests for the transactional AMQP WCF channel</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2419'>QPID-2419</a>] - DurableSubscriptionTest is not thorough enough</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2510'>QPID-2510</a>] - Python messaging SetupTests.testConnectError false fail on Windows</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2532'>QPID-2532</a>] - stale lock file</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2787'>QPID-2787</a>] - enhance the MessageStoreTest</li>
+</ul>
+
+<h4>Sub-task</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-1811'>QPID-1811</a>] - Unable to compile qpid on FreeBSD</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2284'>QPID-2284</a>] - Add new qpidxarm dll to the Windows installer build</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2539'>QPID-2539</a>] - Update ACL file syntax to be clearer and add extra operations</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2540'>QPID-2540</a>] - Create parser and implementation of C++ style ACL files for Java broker</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2542'>QPID-2542</a>] - Implement ACL checking as OSGi plugin</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2659'>QPID-2659</a>] - Change message stores to throw exceptions with internal error code 541</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2660'>QPID-2660</a>] - FieldTable does not throw AMQFrameDecodingException</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2675'>QPID-2675</a>] - Remove obsolete QpidException</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2679'>QPID-2679</a>] - Cache Queues during bind and remove from cache on queue.close()</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2680'>QPID-2680</a>] - Provide user documentation for configuring SCD</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2681'>QPID-2681</a>] - Process topic configuration section</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2682'>QPID-2682</a>] - Move SCD Plugin to part of the Core Broker</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2715'>QPID-2715</a>] - Document new SecurityPlugin design and implementation</li>
+</ul>
+
+<h4>Task</h4>
+<ul>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2315'>QPID-2315</a>] - remove unused client package jar dependencies</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2417'>QPID-2417</a>] - Enhance topic test coverage</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2527'>QPID-2527</a>] - Remove Thread::id() dependency</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2709'>QPID-2709</a>] - Replace the remaining references to the incubator</li>
+<li>[<a href='https://issues.apache.org/jira/browse/QPID-2946'>QPID-2946</a>] - remove QMan binary convenience package from the 0.8 release</li>
+</ul>
+
+</div>
diff --git a/doc/website/content/source_repository.html b/doc/website/content/source_repository.html
new file mode 100644
index 0000000000..147669991e
--- /dev/null
+++ b/doc/website/content/source_repository.html
@@ -0,0 +1,74 @@
+<!--
+ -
+ - 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.
+ -
+-->
+<div class="main_text_area_body">
+ <h1>Source Code Repositories</h1>
+ <h2>Web Browsing of SVN</h2>
+
+ <p>To browse via the web use the ViewVC interface:</p>
+
+ <p><a href="http://svn.apache.org/viewvc/qpid/trunk/qpid">http://svn.apache.org/viewvc/qpid/trunk/qpid</a></p>
+
+ <p>Or to browse the source tree directly:</p>
+
+ <p><a href="https://svn.apache.org/repos/asf/qpid/trunk/qpid">https://svn.apache.org/repos/asf/qpid/trunk/qpid</a></p>
+
+ <h2>Checking out from SVN</h2>
+
+ <p>The source code can be checked out anonymous over HTTP:</p>
+
+ <pre>
+svn co http://svn.apache.org/repos/asf/qpid/trunk
+ </pre>
+
+
+ <p>Committers can check out the code using HTTPS:</p>
+
+ <pre>
+svn co https://svn.apache.org/repos/asf/qpid/trunk
+ </pre>
+
+ <h2>Read only GIT repo</h2>
+
+ <p>A read only GIT repo is available:</p>
+
+ <p>It can be cloned with</p>
+ <pre>
+git clone git://git.apache.org/qpid.git qpid
+ </pre>
+
+ <p>or</p>
+
+<pre>
+git clone http://git.apache.org/qpid.git qpid
+</pre>
+
+ <p>and then git pull will fetch updates.</p>
+
+ <p>If you have commit access it is also possible to commit back with git svn dcommit by following the instructions on the <a href="http://wiki.apache.org/general/GitAtApache">GitAtApache</a> page.</p>
+
+ <h2>Setting up your subversion client</h2>
+
+ <p>When adding files to subversion, it's important that your subversion client is properly setup to the appropriate subversion properties are set. The client can do it automatically by modifying the auto-props section of the subversion config file. Use the contents of:</p>
+
+<pre>
+http://svn.apache.org/repos/asf/qpid/trunk/etc/svn-auto-props
+</pre>
+</div>
diff --git a/doc/website/example/images/asf-logo.png b/doc/website/example/images/asf-logo.png
new file mode 100644
index 0000000000..d824fab768
--- /dev/null
+++ b/doc/website/example/images/asf-logo.png
Binary files differ
diff --git a/doc/website/example/images/asf_logo.gif b/doc/website/example/images/asf_logo.gif
new file mode 100644
index 0000000000..22eb9d7358
--- /dev/null
+++ b/doc/website/example/images/asf_logo.gif
Binary files differ
diff --git a/doc/website/example/images/header.png b/doc/website/example/images/header.png
new file mode 100644
index 0000000000..9cd149fb29
--- /dev/null
+++ b/doc/website/example/images/header.png
Binary files differ
diff --git a/doc/website/example/images/main_body.png b/doc/website/example/images/main_body.png
new file mode 100644
index 0000000000..a29bdeecd6
--- /dev/null
+++ b/doc/website/example/images/main_body.png
Binary files differ
diff --git a/doc/website/example/images/main_bottom.png b/doc/website/example/images/main_bottom.png
new file mode 100644
index 0000000000..319288a717
--- /dev/null
+++ b/doc/website/example/images/main_bottom.png
Binary files differ
diff --git a/doc/website/example/images/main_top.png b/doc/website/example/images/main_top.png
new file mode 100644
index 0000000000..ffefe05a8d
--- /dev/null
+++ b/doc/website/example/images/main_top.png
Binary files differ
diff --git a/doc/website/example/images/menu_body.png b/doc/website/example/images/menu_body.png
new file mode 100644
index 0000000000..39b2e22205
--- /dev/null
+++ b/doc/website/example/images/menu_body.png
Binary files differ
diff --git a/doc/website/example/images/menu_bottom.png b/doc/website/example/images/menu_bottom.png
new file mode 100644
index 0000000000..21bd16aeba
--- /dev/null
+++ b/doc/website/example/images/menu_bottom.png
Binary files differ
diff --git a/doc/website/example/images/menu_top.png b/doc/website/example/images/menu_top.png
new file mode 100644
index 0000000000..dea7164ef0
--- /dev/null
+++ b/doc/website/example/images/menu_top.png
Binary files differ
diff --git a/doc/website/example/images/qpid-logo-900x480.png b/doc/website/example/images/qpid-logo-900x480.png
new file mode 100644
index 0000000000..3e12816142
--- /dev/null
+++ b/doc/website/example/images/qpid-logo-900x480.png
Binary files differ
diff --git a/doc/website/example/images/qpid-logo.png b/doc/website/example/images/qpid-logo.png
new file mode 100644
index 0000000000..f6d4bfdbad
--- /dev/null
+++ b/doc/website/example/images/qpid-logo.png
Binary files differ
diff --git a/doc/website/example/index.html b/doc/website/example/index.html
new file mode 100644
index 0000000000..308ac94765
--- /dev/null
+++ b/doc/website/example/index.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Apache Qpid: Open Source AMQP Messaging</title>
+ <link href="style.css" rel="stylesheet" type="text/css"/>
+ </head>
+
+ <body>
+ <div id="container">
+ <div id="header">
+ <div id="logo">
+ <h1>Apache Qpid</h1>
+ <h2>Open Source AMQP Messaging</h2>
+ </div>
+ </div> <!-- end of header -->
+
+ <div id="menu_box">
+ <div id="menu_box_top"></div>
+ <div id="menu_box_body">
+ <h3>Apache Qpid</h3>
+ <ul>
+ <li><a href="#">Home</a></li>
+ <li><a href="#">Download</a></li>
+ <li><a href="#">Getting Started</a></li>
+ <li><a href="#">Roadmap</a></li>
+ <li><a href="#">License</a></li>
+ <li><a href="#">FAQ</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div id="menu_box_bottom"></div>
+
+ <div id="menu_box_top"></div>
+ <div id="menu_box_body">
+ <h3>Documentation</h3>
+ <ul>
+ <li><a href="#">Version 0.6</a></li>
+ <li><a href="#">Version 0.5</a></li>
+ <li><a href="#">Archive</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div id="menu_box_bottom"></div>
+
+ <div id="menu_box_top"></div>
+ <div id="menu_box_body">
+ <h3>Community</h3>
+ <ul>
+ <li><a href="#">Getting Involved</a></li>
+ <li><a href="#">Source Repository</a></li>
+ <li><a href="#">Mailing Lists</a></li>
+ <li><a href="#">Wiki</a></li>
+ <li><a href="#">Issue Reporting</a></li>
+ <li><a href="#">People</a></li>
+ <li><a href="#">Project Status</a></li>
+ <li><a href="#">Acknowledgements</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div id="menu_box_bottom"></div>
+
+ <div id="menu_box_top"></div>
+ <div id="menu_box_body">
+ <h3>Developers</h3>
+ <ul>
+ <li><a href="#">Building Qpid</a></li>
+ <li><a href="#">Developer Pages</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div id="menu_box_bottom"></div>
+
+ <div id="menu_box_top"></div>
+ <div id="menu_box_body">
+ <h3>About AMQP</h3>
+ <ul>
+ <li><a href="#">What is AMQP?</a></li>
+ <li><a href="#">Specification</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div id="menu_box_bottom"></div>
+
+ </div> <!-- end of menu_box -->
+
+ <div id="main_text_area">
+ <div id="main_text_area_top"></div>
+
+<div id="main_text_area_body" xmlns="http://www.w3.org/1999/xhtml">
+ <h1>Introduction</h1>
+ <p>Enterprise Messaging systems let programs communicate by
+ exchanging messages, much as people communicate by
+ exchanging email. Unlike email, enterprise messaging systems
+ provide guaranteed delivery, speed, security, and freedom
+ from spam. Until recently, there was no open standard for
+ Enterprise Messaging systems, so programmers either wrote
+ their own, or used expensive proprietary systems.</p>
+
+ <p>AMQP <a href="http://www.amqp.org/">Advanced Message
+ Queuing Protocol</a> is the first open standard for
+ Enterprise Messaging. It is designed to support messaging
+ for just about any distributed or business
+ application. Routing can be configured flexibly, easily
+ supporting common messaging paradigms like point-to-point,
+ fanout, publish-subscribe, and request-response.</p>
+
+ <p>Apache Qpid implements the latest AMQP specification, providing
+ transaction management, queuing, distribution, security,
+ management, clustering, federation and heterogeneous
+ multi-platform support and a lot more. And Apache Qpid is
+ extremely fast. Apache Qpid <a href="amqp-compatibility.html"
+ title="AMQP compatibility">aims to be 100% AMQP Compliant</a>.</p>
+
+ <div id="feature_box">
+ <div id="feature_box_column1">
+ <h3>AMQP Brokers</h3>
+ <ul>
+ <li><a href="#">Java Broker</a>
+ <ul>
+ <li><a href="#">Feature Guide</a></li>
+ </ul>
+ </li>
+ <li><a href="#">C++ Broker (Linux/Windows)</a>
+ <ul>
+ <li><a href="#">Feature Guide</a></li>
+ </ul>
+ </li>
+ </ul>
+ <br/>
+ <br/>
+ </div> <!-- end of feature_box_column -->
+
+ <div id="feature_box_column2">
+ <h3>AMQP Client APIs</h3>
+ <ul>
+ <li><a href="#">Java (JMS 1.1 compliant)</a></li>
+ <li><a href="#">C++ (Linux/Windows)</a></li>
+ <li><a href="#">C# .NET</a></li>
+ <li><a href="#">WCF Adapter (Windows Only)</a></li>
+ <li><a href="#">Python</a></li>
+ <li><a href="#">Ruby</a></li>
+ </ul>
+ </div> <!-- end of feature_box_column -->
+
+ <div id="feature_box_column3">
+ <h3>Qpid Management</h3>
+ <ul>
+ <li><a href="#">QMF Python API</a></li>
+ <li><a href="#">QMF C++ API</a> </li>
+ <li><a href="#">Python tools</a></li>
+ <li><a href="#">QMan (QMF&lt;=>JMX)</a></li>
+ </ul>
+ </div> <!-- end of feature_box_column -->
+
+ </div> <!-- end of feature_box -->
+
+</div> <!-- end of main_text_area_body -->
+
+
+ <div id="main_text_area_bottom"></div>
+ </div> <!-- end of main_text_area -->
+
+ <div id="footer">
+ Apache Qpid, Enterprise AMQP Messaging &#xA9; 2004-2010 The Apache Software Foundation.
+ </div>
+
+ </div>
+ </body>
+</html>
diff --git a/doc/website/example/style.css b/doc/website/example/style.css
new file mode 100644
index 0000000000..1e05052a03
--- /dev/null
+++ b/doc/website/example/style.css
@@ -0,0 +1,263 @@
+/*
+ *
+ * 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.
+ *
+ */
+ul {
+ list-style-type:square;
+}
+
+th {
+ text-align: left;
+ font-weight: bold;
+}
+
+
+#body {
+ margin:0;
+ background:#FFFFFF;
+ font-family:"Verdana", sans-serif;
+}
+
+#container {
+ width:950px;
+ margin:0 auto;
+}
+
+#header {
+ height:100px;
+ width:950px;
+ background:url(images/header.png)
+}
+
+#logo {
+ text-align:center;
+ font-weight:600;
+ padding:0 0 0 0;
+ font-size:14px;
+ font-family:"Verdana", cursive;
+}
+
+#logo a {
+ color:#000000;
+ text-decoration:none;
+}
+
+#main_text_area {
+ margin-left:200px;
+}
+
+#main_text_area_top {
+ height:14px;
+ font-size:1px;
+}
+
+#main_text_area_bottom {
+ height:14px;
+ font-size:1px;
+ margin-bottom:4px;
+}
+
+#main_text_area_body {
+ padding:5px 24px;
+}
+
+#main_text_area_body p {
+ text-align:justify;
+}
+
+#main_text_area br {
+ line-height:10px;
+}
+
+#main_text_area h1 {
+ font-size:28px;
+ font-weight:600;
+ margin:0 0 24px 0;
+ color:#0c3b82;
+ font-family:"Verdana", Times, serif;
+}
+
+#main_text_area h2 {
+ font-size:24px;
+ font-weight:600;
+ margin:24px 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana",Times, serif;
+}
+
+#main_text_area ol, #main_text_area ul {
+ padding:0;
+ margin:10px 0;
+ margin-left:20px;
+}
+
+#main_text_area li {
+/* margin-left:40px; */
+}
+
+#main_text_area, #menu_box {
+ font-size:13px;
+ line-height:17px;
+ color:#000000;
+}
+
+#main_text_area {
+ font-size:15px;
+}
+
+#main_text_area a {
+ color:#000000;
+}
+
+#main_text_area a:hover {
+ color:#000000;
+}
+
+#menu_box {
+ width:196px;
+ float:left;
+ margin-left:4px;
+}
+
+#menu_box_top {
+ background:url(images/menu_top.png) no-repeat;
+ height:14px;
+ font-size:1px;
+}
+
+#menu_box_body {
+ background:url(images/menu_body.png) repeat-y;
+ padding:5px 24px 5px 24px;
+}
+
+#menu_box_bottom {
+ background:url(images/menu_bottom.png) no-repeat;
+ height:14px;
+ font-size:1px;
+ margin-bottom:1px;
+}
+
+#menu_box h3 {
+ font-size:20px;
+ font-weight:500;
+ margin:0 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana",Times, serif;
+}
+
+#menu_box ul {
+ margin:12px;
+ padding:0px;
+}
+
+#menu_box li {
+ list-style:square;
+}
+
+#menu_box a {
+ color:#000000;
+ text-decoration:none;
+}
+
+#menu_box a:hover {
+ color:#000000;
+ text-decoration:underline;
+}
+
+#feature_box {
+ width:698px;
+ overflow:hidden;
+}
+
+#feature_box h3 {
+ font-size:18px;
+ font-weight:600;
+ margin:0 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana", Times, serif;
+}
+
+#feature_box_column1 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+#feature_box_column2 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+#feature_box_column3 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+#feature_box ul {
+ margin:.8em .4em;
+ padding-left:1.2em;
+ padding:0;
+ list-style-type: square;
+}
+
+#feature_box ul li {
+ font-family:"Verdana",sans-serif;
+ font-size:14px;
+ color:#000;
+ margin:.4em 0;
+}
+
+#feature_box ul li ul {
+ padding-left:1.2em;
+ margin-left:2em;
+}
+
+#feature_box a {
+ color:#000000;
+ text-decoration:none;
+}
+
+#feature_box a:hover {
+ color:#000000;
+ text-decoration:underline;
+}
+
+#footer {
+ color:#000000;
+ clear:both;
+ text-align:center;
+ font-size:11px;
+ line-height:17px;
+ height:45px;
+ padding-top:18px;
+}
+
+#footer a {
+ color:#000000;
+}
+
+#footer a:hover {
+ color:#000000;
+}
+
diff --git a/doc/website/template/images/asf-logo.png b/doc/website/template/images/asf-logo.png
new file mode 100644
index 0000000000..d824fab768
--- /dev/null
+++ b/doc/website/template/images/asf-logo.png
Binary files differ
diff --git a/doc/website/template/images/asf_logo.gif b/doc/website/template/images/asf_logo.gif
new file mode 100644
index 0000000000..22eb9d7358
--- /dev/null
+++ b/doc/website/template/images/asf_logo.gif
Binary files differ
diff --git a/doc/website/template/images/header.png b/doc/website/template/images/header.png
new file mode 100644
index 0000000000..66e35d7e37
--- /dev/null
+++ b/doc/website/template/images/header.png
Binary files differ
diff --git a/doc/website/template/images/main_body.png b/doc/website/template/images/main_body.png
new file mode 100644
index 0000000000..a29bdeecd6
--- /dev/null
+++ b/doc/website/template/images/main_body.png
Binary files differ
diff --git a/doc/website/template/images/main_bottom.png b/doc/website/template/images/main_bottom.png
new file mode 100644
index 0000000000..319288a717
--- /dev/null
+++ b/doc/website/template/images/main_bottom.png
Binary files differ
diff --git a/doc/website/template/images/main_top.png b/doc/website/template/images/main_top.png
new file mode 100644
index 0000000000..ffefe05a8d
--- /dev/null
+++ b/doc/website/template/images/main_top.png
Binary files differ
diff --git a/doc/website/template/images/menu_body.png b/doc/website/template/images/menu_body.png
new file mode 100644
index 0000000000..39b2e22205
--- /dev/null
+++ b/doc/website/template/images/menu_body.png
Binary files differ
diff --git a/doc/website/template/images/menu_bottom.png b/doc/website/template/images/menu_bottom.png
new file mode 100644
index 0000000000..21bd16aeba
--- /dev/null
+++ b/doc/website/template/images/menu_bottom.png
Binary files differ
diff --git a/doc/website/template/images/menu_top.png b/doc/website/template/images/menu_top.png
new file mode 100644
index 0000000000..dea7164ef0
--- /dev/null
+++ b/doc/website/template/images/menu_top.png
Binary files differ
diff --git a/doc/website/template/images/qpid-logo-900x480.png b/doc/website/template/images/qpid-logo-900x480.png
new file mode 100644
index 0000000000..3e12816142
--- /dev/null
+++ b/doc/website/template/images/qpid-logo-900x480.png
Binary files differ
diff --git a/doc/website/template/images/qpid-logo.png b/doc/website/template/images/qpid-logo.png
new file mode 100644
index 0000000000..95d49ea469
--- /dev/null
+++ b/doc/website/template/images/qpid-logo.png
Binary files differ
diff --git a/doc/website/template/style.css b/doc/website/template/style.css
new file mode 100644
index 0000000000..57dc571425
--- /dev/null
+++ b/doc/website/template/style.css
@@ -0,0 +1,276 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+ul {
+ list-style-type:square;
+}
+
+th {
+ text-align: left;
+ font-weight: bold;
+}
+
+body {
+ margin:0;
+ background:#FFFFFF;
+ font-family:"Verdana", sans-serif;
+}
+
+.container {
+ width:950px;
+ margin:0 auto;
+}
+
+.header {
+ height:100px;
+ width:950px;
+ background:url(images/header.png)
+}
+
+.logo {
+ text-align:center;
+ font-weight:600;
+ padding:0 0 0 0;
+ font-size:14px;
+ font-family:"Verdana", cursive;
+}
+
+.logo a {
+ color:#000000;
+ text-decoration:none;
+}
+
+.main_text_area {
+ margin-left:200px;
+}
+
+.main_text_area_top {
+ height:14px;
+ font-size:1px;
+}
+
+.main_text_area_bottom {
+ height:14px;
+ font-size:1px;
+ margin-bottom:4px;
+}
+
+.main_text_area_body {
+ padding:5px 24px;
+}
+
+.main_text_area_body p {
+ text-align:justify;
+}
+
+.main_text_area br {
+ line-height:10px;
+}
+
+.main_text_area h1 {
+ font-size:28px;
+ font-weight:600;
+ margin:0 0 24px 0;
+ color:#0c3b82;
+ font-family:"Verdana", Times, serif;
+}
+
+.main_text_area h2 {
+ font-size:24px;
+ font-weight:600;
+ margin:24px 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana",Times, serif;
+}
+
+.main_text_area ol, .main_text_area ul {
+ padding:0;
+ margin:10px 0;
+ margin-left:20px;
+}
+
+.main_text_area li {
+/* margin-left:40px; */
+}
+
+.main_text_area, .menu_box {
+ font-size:13px;
+ line-height:17px;
+ color:#000000;
+}
+
+.main_text_area {
+ font-size:15px;
+}
+
+.main_text_area a {
+ color:#000000;
+}
+
+.main_text_area a:hover {
+ color:#000000;
+}
+
+.menu_box {
+ width:196px;
+ float:left;
+ margin-left:4px;
+}
+
+.menu_box_top {
+ background:url(images/menu_top.png) no-repeat;
+ height:14px;
+ font-size:1px;
+}
+
+.menu_box_body {
+ background:url(images/menu_body.png) repeat-y;
+ padding:5px 24px 5px 24px;
+}
+
+.menu_box_bottom {
+ background:url(images/menu_bottom.png) no-repeat;
+ height:14px;
+ font-size:1px;
+ margin-bottom:1px;
+}
+
+.menu_box h3 {
+ font-size:20px;
+ font-weight:500;
+ margin:0 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana",Times, serif;
+}
+
+.menu_box ul {
+ margin:12px;
+ padding:0px;
+}
+
+.menu_box li {
+ list-style:square;
+}
+
+.menu_box a {
+ color:#000000;
+ text-decoration:none;
+}
+
+.menu_box a:hover {
+ color:#000000;
+ text-decoration:underline;
+}
+
+.feature_box {
+ width:698px;
+ overflow:hidden;
+}
+
+.feature_box h3 {
+ font-size:18px;
+ font-weight:600;
+ margin:0 0 8px 0;
+ color:#0c3b82;
+ font-family:"Verdana", Times, serif;
+}
+
+.feature_box_column1 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+.feature_box_column2 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+.feature_box_column3 {
+ width:196px;
+ float:left;
+ padding:10px 15px 10px 15px;
+ margin-left:0px;
+}
+
+
+.feature_box ul {
+ margin:.8em .4em;
+ padding-left:1.2em;
+ padding:0;
+ list-style-type: square;
+}
+
+.feature_box ul li {
+ font-family:"Verdana",sans-serif;
+ font-size:14px;
+ color:#000;
+ margin:.4em 0;
+}
+
+.feature_box ul li ul {
+ padding-left:1.2em;
+ margin-left:2em;
+}
+
+.feature_box a {
+ color:#000000;
+ text-decoration:none;
+}
+
+.feature_box a:hover {
+ color:#000000;
+ text-decoration:underline;
+}
+
+.footer {
+ color:#000000;
+ clear:both;
+ text-align:center;
+ font-size:11px;
+ line-height:17px;
+ height:45px;
+ padding-top:18px;
+}
+
+.footer a {
+ color:#000000;
+}
+
+.footer a:hover {
+ color:#000000;
+}
+
+.download_table {
+ width:100%;
+}
+
+.download_table_col_1 {
+ width:240px;
+}
+
+.download_table_amqp_col {
+ text-align:center;
+ width:80px;
+}
+
diff --git a/doc/website/template/template.html b/doc/website/template/template.html
new file mode 100644
index 0000000000..2738085e00
--- /dev/null
+++ b/doc/website/template/template.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>Apache Qpid&#8482;: Open Source AMQP Messaging</title>
+ <link href="style.css" rel="stylesheet" type="text/css"/>
+ </head>
+
+ <body>
+ <div class="container">
+ <div class="header">
+ <div class="logo">
+ <h1>Apache Qpid&#8482;</h1>
+ <h2>Open Source AMQP Messaging</h2>
+ </div>
+ </div> <!-- end of header -->
+
+ <div class="menu_box">
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>Apache Qpid</h3>
+ <ul>
+ <li><a href="index.html">Home</a></li>
+ <li><a href="download.cgi">Download</a></li>
+ <li><a href="getting_started.html">Getting Started</a></li>
+ <li><a href="http://www.apache.org/licenses/">License</a></li>
+ <li><a href="https://cwiki.apache.org/qpid/faq.html">FAQ</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>Documentation</h3>
+ <ul>
+ <li><a href="documentation.html#doc-release">0.8 Release</a></li>
+ <li><a href="documentation.html#doc-trunk">Trunk</a></li>
+ <li><a href="documentation.html#doc-archives">Archive</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>Community</h3>
+ <ul>
+ <li><a href="getting_involved.html">Getting Involved</a></li>
+ <li><a href="source_repository.html">Source Repository</a></li>
+ <li><a href="mailing_lists.html">Mailing Lists</a></li>
+ <li><a href="https://cwiki.apache.org/qpid/">Wiki</a></li>
+ <li><a href="https://issues.apache.org/jira/browse/qpid">Issue Reporting</a></li>
+ <li><a href="people.html">People</a></li>
+ <li><a href="acknowledgements.html">Acknowledgements</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>Developers</h3>
+ <ul>
+ <li><a href="https://cwiki.apache.org/qpid/building.html">Building Qpid</a></li>
+ <li><a href="https://cwiki.apache.org/qpid/developer-pages.html">Developer Pages</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>About AMQP</h3>
+ <ul>
+ <li><a href="amqp.html">What is AMQP?</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+
+ <div class="menu_box_top"></div>
+ <div class="menu_box_body">
+ <h3>About Apache</h3>
+ <ul>
+ <li><a href="http://www.apache.org">Home</a></li>
+ <li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
+ <li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
+ <li><a href="http://www.apache.org/security/">Security</a></li>
+ </ul>
+ </div> <!-- end of menu_box_body -->
+ <div class="menu_box_bottom"></div>
+ </div> <!-- end of menu_box -->
+
+ <div class="main_text_area">
+ <div class="main_text_area_top"></div>
+{.}
+ </div>
+
+ <div class="footer">
+ <p>
+ &#xA9; 2004-2010 The Apache Software Foundation.<br />
+ Apache Qpid, Qpid, Apache, the Apache feather logo, and the Apache Qpid project logo are trademarks of The Apache Software Foundation.<br />
+ All other marks mentioned may be trademarks or registered trademarks of their respective owners.
+ </p>
+ </div>
+
+ </div>
+ </body>
+</html>
diff --git a/doc/website/tools/generate b/doc/website/tools/generate
new file mode 100755
index 0000000000..a45e803793
--- /dev/null
+++ b/doc/website/tools/generate
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import os
+import sys
+
+if len(sys.argv) != 4:
+ print "Usage: $ generate template/template.html contentDir outputDir"
+ exit()
+
+else:
+ try:
+ srcDir = os.path.abspath(sys.argv[2])
+ srcFiles = os.listdir(srcDir)
+ targetDir = os.path.abspath(sys.argv[3])
+ template = open(sys.argv[1], "r")
+
+ for srcFile in srcFiles:
+ if os.path.splitext(srcFile)[1] == ".html":
+ content = open(os.path.join(srcDir,srcFile), "r")
+ output = open(os.path.join(targetDir,srcFile),"w")
+
+ template.seek(0)
+
+ for t in template:
+ if t.rstrip() == "{.}":
+ for c in content:
+ output.write( c )
+ else:
+ output.write( t )
+
+ output.close()
+ content.close()
+
+ except:
+ print "Ooops!"
+ exit()
+
+template.close()
diff --git a/doc/website/tools/wrap b/doc/website/tools/wrap
new file mode 100755
index 0000000000..d756da7335
--- /dev/null
+++ b/doc/website/tools/wrap
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import sys
+
+if len(sys.argv) != 4:
+ print "Usage: $ wrap template.html content.html output.html"
+ exit()
+
+try:
+ template = open(sys.argv[1], "r")
+ content = open(sys.argv[2], "r")
+ output = open(sys.argv[3], "w")
+
+ for t in template:
+ if t.rstrip() == "{.}":
+ for c in content:
+ output.write( c )
+ else:
+ output.write( t )
+except:
+ print "Ooops!"
+ exit()
+
+template.close()
+content.close()
+output.close()
diff --git a/dotnet/LICENSE.txt b/dotnet/LICENSE.txt
new file mode 100644
index 0000000000..981d2f83c3
--- /dev/null
+++ b/dotnet/LICENSE.txt
@@ -0,0 +1,757 @@
+
+ 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.
+
+
+=========================================================================
+== Saxon XSLT License ==
+=========================================================================
+
+Mozilla Public License Version 1.0
+
+1. Definitions.
+
+ 1.1. "Contributor" means each entity that creates or contributes
+ to the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the
+ Original Code, prior Modifications used by a Contributor, and the
+ Modifications made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications
+ or the combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism
+ generally accepted in the software development community for the
+ electronic transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than
+ Source Code.
+
+ 1.6. "Initial Developer" means the individual or entity
+ identified as the Initial Developer in the Source Code notice required by
+ Exhibit A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code
+ or portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.9. "Modifications" means any addition to or deletion from
+ the substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original
+ Code or previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software
+ code which is described in the Source Code notice required by Exhibit
+ A as Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.11. "Source Code" means the preferred form of the Covered
+ Code for making modifications to it, including all modules it contains,
+ plus any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or a list of source code
+ differential comparisons against either the Original Code or another well
+ known, available Covered Code of the Contributor's choice. The Source
+ Code can be in a compressed or archival form, provided the appropriate
+ decompression or de-archiving software is widely available for no charge.
+
+ 1.12. "You" means an individual or a legal entity exercising
+ rights under, and complying with all of the terms of, this License or a
+ future version of this License issued under Section 6.1. For legal
+ entities, "You" includes any entity which controls, is controlled by,
+ or is under common control with You. For purposes of this definition,
+ "control" means (a) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or otherwise,
+ or (b) ownership of fifty percent (50%) or more of the outstanding shares
+ or beneficial ownership of such entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+
+
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+
+ (a) to use, reproduce, modify, display, perform, sublicense
+ and distribute the Original Code (or portions thereof) with or
+ without Modifications, or as part of a Larger Work; and
+
+ (b) under patents now or hereafter owned or controlled by
+ Initial Developer, to make, have made, use and sell ("Utilize") the
+ Original Code (or portions thereof), but solely to the extent that
+ any such patent is reasonably necessary to enable You to Utilize the
+ Original Code (or portions thereof) and not to any greater extent
+ that may be necessary to Utilize further Modifications or
+ combinations.
+
+ 2.2. Contributor Grant.
+
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+
+ (a) to use, reproduce, modify, display, perform, sublicense and
+ distribute the Modifications created by such Contributor (or portions
+ thereof) either on an unmodified basis, with other Modifications, as
+ Covered Code or as part of a Larger Work; and
+
+ (b) under patents now or hereafter owned or controlled by
+ Contributor, to Utilize the Contributor Version (or portions thereof),
+ but solely to the extent that any such patent is reasonably necessary to
+ enable You to Utilize the Contributor Version (or portions thereof), and
+ not to any greater extent that may be necessary to Utilize further
+ Modifications or combinations.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+
+
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version of
+ this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this License
+ or the recipients' rights hereunder. However, You may include an
+ additional document offering the additional rights described in Section
+ 3.5.
+
+ 3.2. Availability of Source Code.
+
+
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License either
+ on the same media as an Executable version or via an accepted Electronic
+ Distribution Mechanism to anyone to whom you made an Executable version
+ available; and if made available via Electronic Distribution Mechanism,
+ must remain available for at least twelve (12) months after the date it
+ initially became available, or at least six (6) months after a subsequent
+ version of that particular Modification has been made available to such
+ recipients. You are responsible for ensuring that the Source Code version
+ remains available even if the Electronic Distribution Mechanism is
+ maintained by a third party.
+
+ 3.3. Description of Modifications.
+
+
+ You must cause all Covered Code to which you contribute to contain a
+ file documenting the changes You made to create that Covered Code and the
+ date of any change. You must include a prominent statement that the
+ Modification is derived, directly or indirectly, from Original Code
+ provided by the Initial Developer and including the name of the Initial
+ Developer in (a) the Source Code, and (b) in any notice in an Executable
+ version or related documentation in which You describe the origin or
+ ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+
+ (a) Third Party Claims.
+
+
+ If You have knowledge that a party claims an intellectual
+ property right in particular functionality or code (or its
+ utilization under this License), you must include a text file with
+ the source code distribution titled "LEGAL" which describes the
+ claim and the party making the claim in sufficient detail that a
+ recipient will know whom to contact. If you obtain such knowledge
+ after You make Your Modification available as described in Section
+ 3.2, You shall promptly modify the LEGAL file in all copies
+ You make available thereafter and shall take other steps (such as
+ notifying appropriate mailing lists or newsgroups) reasonably
+ calculated to inform those who received the Covered Code that new
+ knowledge has been obtained.
+
+ (b) Contributor APIs.
+
+
+ If Your Modification is an application programming interface and
+ You own or control patents which are reasonably necessary to
+ implement that API, you must also include this information in the
+ LEGAL file.
+
+ 3.5. Required Notices.
+
+
+ You must duplicate the notice in Exhibit A in each file of the
+ Source Code, and this License in any documentation for the Source Code,
+ where You describe recipients' rights relating to Covered Code. If You
+ created one or more Modification(s), You may add your name as a
+ Contributor to the notice described in Exhibit A. If it is not
+ possible to put such notice in a particular Source Code file due to its
+ structure, then you must include such notice in a location (such as a
+ relevant directory file) where a user would be likely to look for such a
+ notice. You may choose to offer, and to charge a fee for, warranty,
+ support, indemnity or liability obligations to one or more recipients of
+ Covered Code. However, You may do so only on Your own behalf, and not on
+ behalf of the Initial Developer or any Contributor. You must make it
+ absolutely clear than any such warranty, support, indemnity or liability
+ obligation is offered by You alone, and You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+
+
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered
+ Code, and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License, including
+ a description of how and where You have fulfilled the obligations of
+ Section 3.2. The notice must be conspicuously included in any
+ notice in an Executable version, related documentation or collateral in
+ which You describe recipients' rights relating to the Covered Code. You
+ may distribute the Executable version of Covered Code under a license of
+ Your choice, which may contain terms different from this License,
+ provided that You are in compliance with the terms of this License and
+ that the license for the Executable version does not attempt to limit or
+ alter the recipient's rights in the Source Code version from the rights
+ set forth in this License. If You distribute the Executable version under
+ a different license You must make it absolutely clear that any terms
+ which differ from this License are offered by You alone, not by the
+ Initial Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of any such terms You
+ offer.
+
+ 3.7. Larger Works.
+
+
+ You may create a Larger Work by combining Covered Code with other
+ code not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to statute or
+ regulation then You must: (a) comply with the terms of this License to
+ the maximum extent possible; and (b) describe the limitations and the
+ code they affect. Such description must be included in the LEGAL file
+ described in Section 3.4 and must be included with all
+ distributions of the Source Code. Except to the extent prohibited by
+ statute or regulation, such description must be sufficiently detailed for
+ a recipient of ordinary skill
+ to be able to understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has attached
+ the notice in Exhibit A, and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+
+
+ Netscape Communications Corporation ("Netscape") may publish
+ revised and/or new versions of the License from time to time. Each
+ version will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+
+
+ Once Covered Code has been published under a particular version of
+ the License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms of
+ any subsequent version of the License published by Netscape. No one other
+ than Netscape has the right to modify the terms applicable to Covered
+ Code created under this License.
+
+ 6.3. Derivative Works.
+
+
+ If you create or use a modified version of this License (which you
+ may only do in order to apply it to code which is not already Covered
+ Code governed by this License), you must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "NPL"
+ or any confusingly similar phrase do not appear anywhere in your license
+ and (b) otherwise make it clear that your version of the license contains
+ terms which differ from the Mozilla Public License and Netscape Public
+ License. (Filling in the name of the Initial Developer, Original Code or
+ Contributor in the notice described in Exhibit A shall not of
+ themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS,
+ MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE
+ RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH
+ YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+ INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+ NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
+ CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE
+ IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall survive
+ any termination of this License. Provisions which, by their nature, must
+ remain in effect beyond the termination of this License shall survive.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING
+ NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY
+ OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF
+ ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
+ INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER
+ INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+ STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED
+ OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL
+ NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+ PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+ LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION
+ OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION
+ MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in 48
+ C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software"
+ and "commercial computer software documentation," as such terms are
+ used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212
+ and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+ U.S. Government End Users acquire Covered Code with only those rights set
+ forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject matter
+ hereof. If any provision of this License is held to be unenforceable,
+ such provision shall be reformed only to the extent necessary to make it
+ enforceable. This License shall be governed by California law provisions
+ (except to the extent applicable law, if any, provides otherwise),
+ excluding its conflict-of-law provisions. With respect to disputes in
+ which at least one party is a citizen of, or an entity chartered or
+ registered to do business in, the United States of America: (a) unless
+ otherwise agreed in writing, all disputes relating to this License
+ (excepting any dispute relating to intellectual property rights) shall be
+ subject to final and binding arbitration, with the losing party paying
+ all costs of arbitration; (b) any arbitration relating to this Agreement
+ shall be held in Santa Clara County, California, under the auspices of
+ JAMS/EndDispute; and (c) any litigation relating to this Agreement shall
+ be subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys fees and
+ expenses. The application of the United Nations Convention on Contracts
+ for the International Sale of Goods is expressly excluded. Any law or
+ regulation which provides that the language of a contract shall be
+ construed against the drafter shall not apply to this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ Except in cases where another Contributor has failed to comply with
+ Section 3.4, You are responsible for damages arising, directly or
+ indirectly, out of Your utilization of rights under this License, based
+ on the number of copies of Covered Code you made available, the revenues
+ you received from utilizing such rights, and other relevant factors. You
+ agree to work with affected parties to distribute responsibility on an
+ equitable basis.
+
+EXHIBIT A.
+
+ "The contents of this file are subject to the Mozilla Public License
+ Version 1.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.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations under
+ the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is
+ ________________________. Portions created by ______________________ are
+ Copyright (C) ______ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________."
+
+
+=========================================================================
+== Nunit License ==
+=========================================================================
+Copyright (c) 2002 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
+Copyright (c) 2000-2002 Philip A. Craig
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
+=========================================================================
+== Mentalis Security LibraryLicense ==
+=========================================================================
+
+Source Code License
+
+Copyright © 2002-2007, The Mentalis.org Team
+All rights reserved.
+http://www.mentalis.org/
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+- Neither the name of the Mentalis.org Team, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================
+== AMQP License ==
+=========================================================================
+
+ Copyright Notice
+ ================
+ (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc.,
+ iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc.,
+ TWIST Process Innovations, and 29West Inc. 2006. All rights reserved.
+
+ License
+ =======
+ JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix
+ Corporation, IONA\ufffd Technologies, Red Hat, Inc., TWIST Process Innovations, and
+ 29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide,
+ perpetual, royalty-free, nontransferable, nonexclusive license to
+ (i) copy, display, and implement the Advanced Messaging Queue Protocol
+ ("AMQP") Specification and (ii) the Licensed Claims that are held by
+ the Authors, all for the purpose of implementing the Advanced Messaging
+ Queue Protocol Specification. Your license and any rights under this
+ Agreement will terminate immediately without notice from
+ any Author if you bring any claim, suit, demand, or action related to
+ the Advanced Messaging Queue Protocol Specification against any Author.
+ Upon termination, you shall destroy all copies of the Advanced Messaging
+ Queue Protocol Specification in your possession or control.
+
+ As used hereunder, "Licensed Claims" means those claims of a patent or
+ patent application, throughout the world, excluding design patents and
+ design registrations, owned or controlled, or that can be sublicensed
+ without fee and in compliance with the requirements of this
+ Agreement, by an Author or its affiliates now or at any
+ future time and which would necessarily be infringed by implementation
+ of the Advanced Messaging Queue Protocol Specification. A claim is
+ necessarily infringed hereunder only when it is not possible to avoid
+ infringing it because there is no plausible non-infringing alternative
+ for implementing the required portions of the Advanced Messaging Queue
+ Protocol Specification. Notwithstanding the foregoing, Licensed Claims
+ shall not include any claims other than as set forth above even if
+ contained in the same patent as Licensed Claims; or that read solely
+ on any implementations of any portion of the Advanced Messaging Queue
+ Protocol Specification that are not required by the Advanced Messaging
+ Queue Protocol Specification, or that, if licensed, would require a
+ payment of royalties by the licensor to unaffiliated third parties.
+ Moreover, Licensed Claims shall not include (i) any enabling technologies
+ that may be necessary to make or use any Licensed Product but are not
+ themselves expressly set forth in the Advanced Messaging Queue Protocol
+ Specification (e.g., semiconductor manufacturing technology, compiler
+ technology, object oriented technology, networking technology, operating
+ system technology, and the like); or (ii) the implementation of other
+ published standards developed elsewhere and merely referred to in the
+ body of the Advanced Messaging Queue Protocol Specification, or
+ (iii) any Licensed Product and any combinations thereof the purpose or
+ function of which is not required for compliance with the Advanced
+ Messaging Queue Protocol Specification. For purposes of this definition,
+ the Advanced Messaging Queue Protocol Specification shall be deemed to
+ include both architectural and interconnection requirements essential
+ for interoperability and may also include supporting source code artifacts
+ where such architectural, interconnection requirements and source code
+ artifacts are expressly identified as being required or documentation to
+ achieve compliance with the Advanced Messaging Queue Protocol Specification.
+
+ As used hereunder, "Licensed Products" means only those specific portions
+ of products (hardware, software or combinations thereof) that implement
+ and are compliant with all relevant portions of the Advanced Messaging
+ Queue Protocol Specification.
+
+ The following disclaimers, which you hereby also acknowledge as to any
+ use you may make of the Advanced Messaging Queue Protocol Specification:
+
+ THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS,"
+ AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+ IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE
+ CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE
+ SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED
+ MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
+ USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE
+ PROTOCOL SPECIFICATION.
+
+ The name and trademarks of the Authors may NOT be used in any manner,
+ including advertising or publicity pertaining to the Advanced Messaging
+ Queue Protocol Specification or its contents without specific, written
+ prior permission. Title to copyright in the Advanced Messaging Queue
+ Protocol Specification will at all times remain with the Authors.
+
+ No other rights are granted by implication, estoppel or otherwise.
+
+ Upon termination of your license or rights under this Agreement, you
+ shall destroy all copies of the Advanced Messaging Queue Protocol
+ Specification in your possession or control.
+
+ Trademarks
+ ==========
+ "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the
+ Octagon Symbol are trademarks of JPMorgan Chase & Co.
+
+ IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
+
+ IONA, IONA Technologies, and the IONA logos are trademarks of IONA
+ Technologies PLC and/or its subsidiaries.
+
+ LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered
+ trademarks of Red Hat, Inc. in the US and other countries.
+
+ Java, all Java-based trademarks and OpenOffice.org are trademarks of
+ Sun Microsystems, Inc. in the United States, other countries, or both.
+
+ Other company, product, or service names may be trademarks or service
+ marks of others.
+
+ Links to full AMQP specification:
+ =================================
+ http://www.envoytech.org/spec/amq/
+ http://www.iona.com/opensource/amqp/
+ http://www.redhat.com/solutions/specifications/amqp/
+ http://www.twiststandards.org/tiki-index.php?page=AMQ
+ http://www.imatix.com/amqp
diff --git a/dotnet/NOTICE.txt b/dotnet/NOTICE.txt
new file mode 100644
index 0000000000..0b22ed3ab2
--- /dev/null
+++ b/dotnet/NOTICE.txt
@@ -0,0 +1,32 @@
+=========================================================================
+== NOTICE file corresponding to the section 4 d of ==
+== the Apache License, Version 2.0, ==
+== in this case for the Apache Ant distribution. ==
+=========================================================================
+
+Apache Qpid.NET
+Copyright 2006 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+This product also includes software developed by:
+
+ - The SAXON XSLT Processor from Michael Kay distributed under the Mozilla
+ Public License v1.0, which is available for download at
+ http://saxon.sourceforge.net/
+
+ - The nunit library, Copyright © 2002 James W. Newkirk, Michael C. Two,
+ Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig. Available
+ under terms based on the zlib/libpng licence. Available from
+ http://www.nunit.org/
+
+ - The Mentalis Security Library, Copyright © 2002-2006, , The Mentalis.org Team
+ under tterms based on the BSD license (http://www.mentalis.org/site/license.qpx).
+ Available from http://www.mentalis.org/soft/projects/seclib/
+
+This product includes software, Apache Log4Net
+(http://logging.apache.org/log4net)
+License: Apache 2.0 License (http://www.apache.org/licenses/LICENSE-2.0)
+
+
diff --git a/dotnet/Qpid.Buffer.Tests/Properties/AssemblyInfo.cs b/dotnet/Qpid.Buffer.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..2f49033c2d
--- /dev/null
+++ b/dotnet/Qpid.Buffer.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+ using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Buffer.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Buffer.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("9d967d0b-9454-4f00-8f53-fa86fd62b696")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Buffer.Tests/Qpid.Buffer.Tests.csproj b/dotnet/Qpid.Buffer.Tests/Qpid.Buffer.Tests.csproj
new file mode 100644
index 0000000000..72d3ccc82f
--- /dev/null
+++ b/dotnet/Qpid.Buffer.Tests/Qpid.Buffer.Tests.csproj
@@ -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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{74640962-99D0-4D06-B57A-9CD66517CF52}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Buffer.Tests</RootNamespace>
+ <AssemblyName>Apache.Qpid.Buffer.Tests</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Client.Tests\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Buffer.Tests/SimpleByteBufferTests.cs b/dotnet/Qpid.Buffer.Tests/SimpleByteBufferTests.cs
new file mode 100644
index 0000000000..b028bdb1ee
--- /dev/null
+++ b/dotnet/Qpid.Buffer.Tests/SimpleByteBufferTests.cs
@@ -0,0 +1,333 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using NUnit.Framework;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Buffer.Tests
+{
+ /// <summary>
+ /// Tests for the SimpleByteBuffer class
+ /// </summary>
+ [TestFixture]
+ public class SimpleByteBufferTests
+ {
+ [Test]
+ public void CanCreateNewBuffer()
+ {
+ const int size = 10;
+ ByteBuffer buffer = ByteBuffer.Allocate(size);
+ Assert.AreEqual(size, buffer.Capacity);
+ Assert.AreEqual(0, buffer.Position);
+ Assert.AreEqual(size, buffer.Remaining);
+ Assert.AreEqual(true, buffer.HasRemaining);
+ }
+
+ [Test]
+ public void CanWrapArray()
+ {
+ byte[] array = new byte[10];
+ for ( int i=0; i < array.Length; i++ )
+ {
+ array[i] = (byte) i;
+ }
+ ByteBuffer buffer = ByteBuffer.Wrap(array);
+ // the buffer should be the same size,
+ // and positioned at the end
+ Assert.AreEqual(array.Length, buffer.Capacity);
+ Assert.AreEqual(array.Length, buffer.Position);
+ Assert.AreEqual(array.Length, buffer.Limit);
+ }
+
+ #region Base Read/Write tests
+ //
+ // Base Read/Write tests
+ //
+ [Test]
+ public void CanReadWriteBytes()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Rewind();
+ Assert.AreEqual(0x01, buffer.GetByte());
+ Assert.AreEqual(0x02, buffer.GetByte());
+ Assert.AreEqual(0x03, buffer.GetByte());
+ }
+
+ [Test]
+ [ExpectedException(typeof(BufferUnderflowException))]
+ public void ThrowOnReadByteWithNoSpace()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(1);
+ buffer.Put((byte)0x01);
+ buffer.GetByte();
+ }
+
+ [Test]
+ [ExpectedException(typeof(BufferOverflowException))]
+ public void ThrowOnWriteByteWithNoSpace()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(1);
+ buffer.Put((byte)0x01).Put((byte)0x02);
+ }
+
+ #endregion Base Read/Write tests
+
+ #region Other Buffer Operations
+ //
+ // Other Buffer Operations
+ //
+
+ [Test]
+ public void CanFlipBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Flip();
+ Assert.AreEqual(10, buffer.Capacity);
+ Assert.AreEqual(3, buffer.Limit);
+ Assert.AreEqual(0, buffer.Position);
+ Assert.AreEqual(3, buffer.Remaining);
+ }
+
+ [Test]
+ public void CanCompactBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Flip();
+ buffer.Position = 1;
+ buffer.Compact();
+ Assert.AreEqual(10, buffer.Capacity);
+ Assert.AreEqual(10, buffer.Limit);
+ Assert.AreEqual(2, buffer.Position);
+ Assert.AreEqual(8, buffer.Remaining);
+ buffer.Rewind();
+ Assert.AreEqual((byte)0x02, buffer.GetByte());
+ Assert.AreEqual((byte)0x03, buffer.GetByte());
+ }
+
+ [Test]
+ public void CanClearBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Flip();
+ buffer.Position = 2;
+ buffer.Clear();
+ Assert.AreEqual(10, buffer.Capacity);
+ Assert.AreEqual(10, buffer.Limit);
+ Assert.AreEqual(0, buffer.Position);
+ Assert.AreEqual(10, buffer.Remaining);
+ }
+
+ [Test]
+ public void CanExpandBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Flip();
+ buffer.Position = 2;
+ int pos = buffer.Position;
+ buffer.Expand(20);
+
+ Assert.AreEqual(pos, buffer.Position);
+ Assert.IsTrue(buffer.Remaining >= 20);
+ buffer.Rewind();
+ Assert.AreEqual(0x01, buffer.GetByte());
+ }
+
+ [Test]
+ public void CanAutoExpand()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(2);
+ buffer.IsAutoExpand = true;
+ // should cause autoexpand
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ Assert.IsTrue(buffer.Capacity > 2);
+ }
+
+ [Test]
+ public void CanGetArray()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer.Flip();
+
+ byte[] array = buffer.Array;
+ for ( int i=0; i < buffer.Limit; i++ )
+ {
+ Assert.AreEqual(buffer.GetByte(), array[i]);
+ }
+ }
+
+ [Test]
+ public void CanSkip()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Skip(4);
+ Assert.AreEqual(4, buffer.Position);
+ }
+
+ #endregion // Base Read/Write tests
+
+ #region Typed Accessors
+ //
+ // Typed Accessors
+ //
+ [Test]
+ public void CanReadWriteSByte()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ sbyte value = -12;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetSByte());
+ }
+ [Test]
+ public void CanReadWriteUInt16()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ ushort value = 41233;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetUInt16());
+ }
+ [Test]
+ public void CanReadWriteInt16()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ short value = -21233;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetInt16());
+ }
+ [Test]
+ public void CanReadWriteUInt32()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ uint value = 41233211;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetUInt32());
+ }
+ [Test]
+ public void CanReadWriteInt32()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ int value = -22221233;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetInt32());
+ }
+ [Test]
+ public void CanReadWriteUInt64()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ ulong value = 41233218871;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetUInt64());
+ }
+ [Test]
+ public void CanReadWriteInt64()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ long value = -9887335411;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetInt64());
+ }
+ [Test]
+ public void CanReadWriteFloat()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ float value = -1.2331f;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetFloat());
+ }
+
+ [Test]
+ public void CanReadWriteDouble()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ double value = -1.2331E12;
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetDouble());
+ }
+
+ [Test]
+ public void CanReadWriteChar()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ char value = 'H';
+ buffer.Put(value);
+ buffer.Flip();
+ Assert.AreEqual(value, buffer.GetChar());
+ }
+
+ [Test]
+ public void CanReadWriteByteArray()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put(new byte[] { 0x01, 0x02, 0x03});
+ buffer.Flip();
+ byte[] data = new byte[3];
+ buffer.GetBytes(data);
+ Assert.AreEqual(0x01, data[0]);
+ Assert.AreEqual(0x02, data[1]);
+ Assert.AreEqual(0x03, data[2]);
+ }
+
+ [Test]
+ public void CanReadWriteByteArrayWithOffset()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(10);
+ buffer.Put(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }, 1, 4);
+ buffer.Flip();
+ byte[] data = new byte[3];
+ buffer.GetBytes(data, 2, 1);
+ Assert.AreEqual(0x00, data[0]);
+ Assert.AreEqual(0x00, data[1]);
+ Assert.AreEqual(0x02, data[2]);
+ }
+
+ [Test]
+ public void CanWriteByteBuffer()
+ {
+ ByteBuffer buffer1 = ByteBuffer.Allocate(10);
+ buffer1.Put((byte)0x01).Put((byte)0x02).Put((byte)0x03);
+ buffer1.Flip();
+
+ ByteBuffer buffer2 = ByteBuffer.Allocate(10);
+ buffer2.Put(buffer1);
+ buffer2.Flip();
+ Assert.AreEqual(buffer1.Limit, buffer2.Limit);
+ Assert.AreEqual(0x01, buffer2.GetByte());
+ }
+ #endregion // Typed Accessors
+
+ } // class SimpleByteBufferTests
+}
+
+
diff --git a/dotnet/Qpid.Buffer.Tests/SlicedByteBufferTests.cs b/dotnet/Qpid.Buffer.Tests/SlicedByteBufferTests.cs
new file mode 100644
index 0000000000..7dec7c390f
--- /dev/null
+++ b/dotnet/Qpid.Buffer.Tests/SlicedByteBufferTests.cs
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using NUnit.Framework;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Buffer.Tests
+{
+ /// <summary>
+ /// Tests for the SlicedByteBuffer class
+ /// </summary>
+ [TestFixture]
+ public class SlicedByteBufferTests
+ {
+ private ByteBuffer _baseBuffer;
+
+ [SetUp]
+ public void Setup()
+ {
+ const int size = 50;
+ _baseBuffer = ByteBuffer.Allocate(size);
+ for ( byte b = 0; b < 10; b++ )
+ {
+ _baseBuffer.Put(b);
+ }
+ _baseBuffer.Flip();
+ }
+
+ [Test]
+ public void CanSliceBuffer()
+ {
+ _baseBuffer.Position = 5;
+
+ ByteBuffer slice = _baseBuffer.Slice();
+ Assert.AreEqual(5, slice.Capacity);
+ Assert.AreEqual(0, slice.Position);
+ Assert.AreEqual(5, slice.Remaining);
+ Assert.AreEqual(5, slice.Limit);
+ }
+
+ [Test]
+ public void CanReadWriteSlice()
+ {
+ _baseBuffer.Position = 5;
+
+ ByteBuffer slice = _baseBuffer.Slice();
+ slice.Put((byte) 0xFF).Put((byte) 0xF0).Put((byte) 0xA0);
+ slice.Flip();
+
+ Assert.AreEqual(3, slice.Limit);
+ Assert.AreEqual(0xFF, slice.GetByte());
+ Assert.AreEqual(0xF0, slice.GetByte());
+ Assert.AreEqual(0xA0, slice.GetByte());
+ }
+
+ [Test]
+ public void WriteModifiesBaseBufferOnCorrectPosition()
+ {
+ _baseBuffer.Position = 5;
+
+ ByteBuffer slice = _baseBuffer.Slice();
+ slice.Put((byte) 0xFF);
+ slice.Flip();
+ // reading the _baseBuffer at position 5 should yield 0xFF
+ _baseBuffer.Position = 5;
+ Assert.AreEqual(0xFF, _baseBuffer.GetByte());
+
+ }
+
+ [Test]
+ public void CanReadWriteByteArray()
+ {
+ _baseBuffer.Position = 5;
+
+ ByteBuffer slice = _baseBuffer.Slice();
+ byte[] data = {0xFF, 0xF0, 0xF2, 0xEE, 0x23};
+ slice.Put(data, 2, 2);
+ slice.Flip();
+
+ Assert.AreEqual(2, slice.Limit);
+ Assert.AreEqual(0xF2, slice.GetByte());
+ Assert.AreEqual(0xEE, slice.GetByte());
+ }
+
+ [Test]
+ [ExpectedException(typeof(BufferOverflowException))]
+ public void ThrowWhenWritePastLimit()
+ {
+ _baseBuffer.Position = 5;
+
+ ByteBuffer slice = _baseBuffer.Slice();
+ slice.Put(0x01).Put(0x02);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void ThrowOnCompact()
+ {
+ // we don't support compacting
+ ByteBuffer slice = _baseBuffer.Slice();
+ slice.Compact();
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotSupportedException))]
+ public void ThrowOnResize()
+ {
+ // we don't support resizing
+ ByteBuffer slice = _baseBuffer.Slice();
+ slice.Expand(50);
+ }
+ } // class SlicedByteBufferTests
+}
diff --git a/dotnet/Qpid.Buffer.Tests/default.build b/dotnet/Qpid.Buffer.Tests/default.build
new file mode 100644
index 0000000000..77e95fb9d9
--- /dev/null
+++ b/dotnet/Qpid.Buffer.Tests/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Buffer" default="test">
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="true" debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.Tests.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/${project::get-name()}.dll" />
+ </references>
+
+ </csc>
+ </target>
+ <target name="test" depends="build">
+ <nunit2>
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test assemblyname="${build.dir}/${project::get-name()}.Tests.dll" />
+ </nunit2>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Buffer/BufferOverflowException.cs b/dotnet/Qpid.Buffer/BufferOverflowException.cs
new file mode 100644
index 0000000000..5a2fff74a7
--- /dev/null
+++ b/dotnet/Qpid.Buffer/BufferOverflowException.cs
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Buffer
+{
+ [Serializable]
+ public class BufferOverflowException : Exception
+ {
+ public BufferOverflowException(string message) : base(message)
+ {
+ }
+
+ protected BufferOverflowException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Buffer/BufferUnderflowException.cs b/dotnet/Qpid.Buffer/BufferUnderflowException.cs
new file mode 100644
index 0000000000..13939b77a8
--- /dev/null
+++ b/dotnet/Qpid.Buffer/BufferUnderflowException.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Buffer
+{
+ [Serializable]
+ public class BufferUnderflowException : Exception
+ {
+ public BufferUnderflowException(string message)
+ : base(message)
+ {
+ }
+
+ protected BufferUnderflowException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Buffer/ByteBuffer.cs b/dotnet/Qpid.Buffer/ByteBuffer.cs
new file mode 100644
index 0000000000..67f0edd440
--- /dev/null
+++ b/dotnet/Qpid.Buffer/ByteBuffer.cs
@@ -0,0 +1,982 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Buffer
+{
+ /// <summary>
+ /// Abstract class implementing a byte buffer
+ /// </summary>
+ public abstract class ByteBuffer
+ {
+ private int _position;
+ private int _limit;
+ private bool _isAutoExpand;
+ private static IByteBufferAllocator _allocator =
+ new SimpleByteBufferAllocator();
+
+ #region Properties
+ //
+ // Properties
+ //
+
+ /// <summary>
+ /// The maximum number of bytes the buffer can hold
+ /// </summary>
+ public abstract int Capacity
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Return the backing array of this buffer
+ /// </summary>
+ public abstract byte[] Array
+ {
+ get;
+ }
+
+ /// <summary>
+ /// The current position inside this buffer
+ /// </summary>
+ public int Position
+ {
+ get { return _position; }
+ set { Seek(value); }
+ }
+
+ /// <summary>
+ /// Index of the first element that should not be read or written.
+ /// A buffer's limit is never negative and is never greater than the its capacity.
+ /// </summary>
+ public int Limit
+ {
+ get { return _limit; }
+ set { SetLimit(value); }
+ }
+
+ /// <summary>
+ /// Number of bytes remaining in the buffer from the current position
+ /// </summary>
+ public int Remaining
+ {
+ get { return Limit - Position; }
+ }
+
+ /// <summary>
+ /// True if there are bytes remaining in the buffer
+ /// </summary>
+ public bool HasRemaining
+ {
+ get { return Remaining > 0; }
+ }
+
+ /// <summary>
+ /// If true, the buffer will be resized as necessary
+ /// to allow space for writing. By default is false.
+ /// </summary>
+ public bool IsAutoExpand
+ {
+ get { return _isAutoExpand; }
+ set { _isAutoExpand = value; }
+ }
+
+ #endregion // Properties
+
+ #region Buffer Manipulation
+ //
+ // Buffer Manipulation
+ //
+
+ /// <summary>
+ /// Move the buffer to Position 0
+ /// </summary>
+ /// <returns>This instance</returns>
+ public ByteBuffer Rewind()
+ {
+ Seek(0);
+ return this;
+ }
+
+ /// <summary>
+ /// Prepare the buffer to read back what's been written
+ /// </summary>
+ /// <returns>This instance</returns>
+ public ByteBuffer Flip()
+ {
+ Limit = Position;
+ Position = 0;
+ return this;
+ }
+
+ /// <summary>
+ /// Compact this buffer.
+ /// </summary>
+ /// <returns>This instance</returns>
+ /// <remarks>
+ /// The bytes between the buffer's current position and its limit, if any,
+ /// are copied to the beginning of the buffer.
+ /// </remarks>
+ public ByteBuffer Compact()
+ {
+ DoCompact();
+ return this;
+ }
+
+ /// <summary>
+ /// Clears this buffer. The position is set to zero, the limit is set to the capacity
+ /// </summary>
+ /// <returns>This instance</returns>
+ public ByteBuffer Clear()
+ {
+ Limit = Capacity;
+ Position = 0;
+ return this;
+ }
+
+ /// <summary>
+ /// Expands this buffer's capacity so that
+ /// Remaining == expectedRemaining
+ /// </summary>
+ /// <param name="expectedRemaining">Number of bytes that should be accessable after resizing</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Expand(int expectedRemaining)
+ {
+ return Expand(Position, expectedRemaining);
+ }
+
+ /// <summary>
+ /// Expands this buffer's capacity so that
+ /// Remaining == expectedRemaining
+ /// </summary>
+ /// <param name="position">Position from which to start the resize</param>
+ /// <param name="expectedRemaining">Number of bytes that should be accessable after resizing</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Expand(int position, int expectedRemaining)
+ {
+ if ( expectedRemaining <= 0 )
+ throw new ArgumentException("expectedRemaining must be greater than 0");
+
+ int end = position + expectedRemaining;
+ if ( end > Capacity )
+ {
+ DoResize(end);
+ }
+ if ( end > Limit )
+ Limit = end;
+ return this;
+ }
+
+ /// <summary>
+ /// Creates a new byte buffer whose content is a shared
+ /// subsequence of this buffer's content.
+ /// </summary>
+ /// <remarks>
+ /// The content of the new buffer will start at this buffer's current position.
+ /// Changes to this buffer's content will be visible in the new buffer,
+ /// and vice versa; the two buffers' position and limit values will be independent.
+ /// <para>
+ /// The new buffer's position will be zero, its capacity and its limit will
+ /// be the number of bytes remaining in this buffer.
+ /// </para>
+ /// </remarks>
+ /// <returns>A view on top of this instance</returns>
+ public ByteBuffer Slice()
+ {
+ return new SlicedByteBuffer(this);
+ }
+
+ /// <summary>
+ /// Skip the specified number of bytes
+ /// </summary>
+ /// <param name="numBytes">Number of bytes to move forward by</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Skip(int numBytes)
+ {
+ Position += numBytes;
+ return this;
+ }
+
+ /// <summary>
+ /// Acquire this buffer to keep it alive.
+ /// </summary>
+ public virtual void Acquire()
+ {
+ // override in subclass if supported
+ }
+
+ /// <summary>
+ /// Release this buffer instance
+ /// </summary>
+ public virtual void Release()
+ {
+ // override in subclass if supported
+ }
+
+ /// <summary>
+ /// Return a string with a Hex Dump of this buffer's contents
+ /// </summary>
+ /// <returns>The hex dump</returns>
+ public string GetHexDump()
+ {
+ return ByteBufferHexDumper.GetHexDump(this);
+ }
+
+ public override string ToString()
+ {
+ return GetHexDump();
+ }
+ #endregion // Buffer Manipulation
+
+ #region Static Operations
+ //
+ // Static Operations
+ //
+ /// <summary>
+ /// Replaces the default allocator with your own implementation
+ /// </summary>
+ /// <param name="allocator">New allocator</param>
+ public static void SetAllocator(IByteBufferAllocator allocator)
+ {
+ if ( allocator == null )
+ throw new ArgumentNullException("allocator");
+ _allocator = allocator;
+ }
+
+ /// <summary>
+ /// Allocate a new buffer with the specified capacity
+ /// using the default allocator
+ /// </summary>
+ /// <param name="capacity">Desired capacity</param>
+ /// <returns>The new buffer</returns>
+ public static ByteBuffer Allocate(int capacity)
+ {
+ return _allocator.Allocate(capacity);
+ }
+
+ /// <summary>
+ /// Wraps the specified arrat into a new buffer
+ /// </summary>
+ /// <param name="buffer"></param>
+ /// <returns></returns>
+ public static ByteBuffer Wrap(byte[] buffer)
+ {
+ return _allocator.Wrap(buffer);
+ }
+ #endregion // Static Operations
+
+ #region Data Accessors
+ //
+ // Data Accessors
+ //
+
+ // Byte Stuff
+
+ /// <summary>
+ /// Read the next byte in the buffer
+ /// </summary>
+ /// <returns>The next byte available</returns>
+ public byte GetByte()
+ {
+ byte value = GetByte(Position);
+ Position += 1;
+ return value;
+ }
+ /// <summary>
+ /// Read the byte at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public byte GetByte(int position)
+ {
+ CheckSpaceForReading(position, 1);
+ return ReadByte(position);
+ }
+ /// <summary>
+ /// Write a byte at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(byte value)
+ {
+ Put(Position, value);
+ Position++;
+ return this;
+ }
+ /// <summary>
+ /// Write a byte at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, byte value)
+ {
+ CheckSpaceForWriting(position, 1);
+ Write(position, value);
+ return this;
+ }
+
+ // SByte Stuff
+
+ /// <summary>
+ /// Read the next signed byte in the buffer
+ /// </summary>
+ /// <returns>The next signed byte available</returns>
+ public sbyte GetSByte()
+ {
+ sbyte value = GetSByte(Position);
+ Position += 1;
+ return value;
+ }
+ /// <summary>
+ /// Read the signed byte at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public sbyte GetSByte(int position)
+ {
+ CheckSpaceForReading(position, 1);
+ return (sbyte)ReadByte(position);
+ }
+
+ /// <summary>
+ /// Write a signed byte at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(sbyte value)
+ {
+ Put(Position, value);
+ Position += 1;
+ return this;
+ }
+
+ /// <summary>
+ /// Write a signed byte at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, sbyte value)
+ {
+ CheckSpaceForWriting(position, 1);
+ Write(position, (byte)value);
+ return this;
+ }
+
+ // UInt16 Stuff
+
+ /// <summary>
+ /// Read the next uint16 in the buffer
+ /// </summary>
+ /// <returns>The next uint16 available</returns>
+ public ushort GetUInt16()
+ {
+ ushort value = GetUInt16(Position);
+ Position += 2;
+ return value;
+ }
+ /// <summary>
+ /// Read the uint16 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public ushort GetUInt16(int position)
+ {
+ CheckSpaceForReading(position, 2);
+ byte upper = ReadByte(position);
+ byte lower = ReadByte(position+1);
+ return (ushort)(((ushort)upper << 8) + lower);
+ }
+
+ /// <summary>
+ /// Write a uint16 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(ushort value)
+ {
+ Put(Position, value);
+ Position += 2;
+ return this;
+ }
+
+ /// <summary>
+ /// Write a uint16 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, ushort value)
+ {
+ CheckSpaceForWriting(position, 2);
+ Write(position, (byte)(value >> 8));
+ Write(position+1, (byte)(value));
+ return this;
+ }
+
+ // Int16 Stuff
+
+ /// <summary>
+ /// Read the next int16 in the buffer
+ /// </summary>
+ /// <returns>The next int16 available</returns>
+ public short GetInt16()
+ {
+ return (short) GetUInt16();
+ }
+ /// <summary>
+ /// Read the int16 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public short GetInt16(int position)
+ {
+ return (short)GetUInt16(position);
+ }
+
+ /// <summary>
+ /// Write a int16 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(short value)
+ {
+ return Put((ushort) value);
+ }
+
+ /// <summary>
+ /// Write a int16 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, short value)
+ {
+ return Put(position, (ushort)value);
+ }
+
+
+ // UInt32 Stuff
+
+ /// <summary>
+ /// Read the next uint32 in the buffer
+ /// </summary>
+ /// <returns>The next uint32 available</returns>
+ public uint GetUInt32()
+ {
+ uint value = GetUInt32(Position);
+ Position += 4;
+ return value;
+ }
+ /// <summary>
+ /// Read the uint32 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public uint GetUInt32(int position)
+ {
+ CheckSpaceForReading(position, 4);
+ byte b1 = ReadByte(position);
+ byte b2 = ReadByte(position + 1);
+ byte b3 = ReadByte(position + 2);
+ byte b4 = ReadByte(position + 3);
+ return (uint)((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
+ }
+
+ /// <summary>
+ /// Write a uint32 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(uint value)
+ {
+ Put(Position, value);
+ Position += 4;
+ return this;
+ }
+
+ /// <summary>
+ /// Write a uint32 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, uint value)
+ {
+ CheckSpaceForWriting(position, 4);
+ Write(position, (byte)(value >> 24));
+ Write(position + 1, (byte)(value >> 16));
+ Write(position + 2, (byte)(value >> 8));
+ Write(position + 3, (byte)(value));
+ return this;
+ }
+
+ // Int32 Stuff
+
+ /// <summary>
+ /// Read the next int32 in the buffer
+ /// </summary>
+ /// <returns>The next int32 available</returns>
+ public int GetInt32()
+ {
+ return (int)GetUInt32();
+ }
+ /// <summary>
+ /// Read the int32 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public int GetInt32(int position)
+ {
+ return (int)GetUInt32(position);
+ }
+
+ /// <summary>
+ /// Write a int32 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int value)
+ {
+ return Put((uint)value);
+ }
+
+ /// <summary>
+ /// Write a int32 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, int value)
+ {
+ return Put(position, (uint)value);
+ }
+
+ // UInt64 Stuff
+
+ /// <summary>
+ /// Read the next uint64 in the buffer
+ /// </summary>
+ /// <returns>The next uint64 available</returns>
+ public ulong GetUInt64()
+ {
+ ulong value = GetUInt64(Position);
+ Position += 8;
+ return value;
+ }
+ /// <summary>
+ /// Read the uint64 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public ulong GetUInt64(int position)
+ {
+ CheckSpaceForReading(position, 8);
+ byte b1 = ReadByte(position);
+ byte b2 = ReadByte(position + 1);
+ byte b3 = ReadByte(position + 2);
+ byte b4 = ReadByte(position + 3);
+ byte b5 = ReadByte(position + 4);
+ byte b6 = ReadByte(position + 5);
+ byte b7 = ReadByte(position + 6);
+ byte b8 = ReadByte(position + 7);
+ // all the casts necessary because otherwise each subexpression
+ // only gets promoted to uint and cause incorrect results
+ return (((ulong)b1 << 56) + ((ulong)b2 << 48) + ((ulong)b3 << 40) +
+ ((ulong)b4 << 32) + ((ulong)b5 << 24) +
+ ((ulong)b6 << 16) + ((ulong)b7 << 8) + b8);
+ }
+
+ /// <summary>
+ /// Write a uint64 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(ulong value)
+ {
+ Put(Position, value);
+ Position += 8;
+ return this;
+ }
+
+ /// <summary>
+ /// Write a uint64 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, ulong value)
+ {
+ CheckSpaceForWriting(position, 8);
+ Write(position, (byte)(value >> 56));
+ Write(position + 1, (byte)(value >> 48));
+ Write(position + 2, (byte)(value >> 40));
+ Write(position + 3, (byte)(value >> 32));
+ Write(position + 4, (byte)(value >> 24));
+ Write(position + 5, (byte)(value >> 16));
+ Write(position + 6, (byte)(value >> 8));
+ Write(position + 7, (byte)(value));
+ return this;
+ }
+
+ // Int64 Stuff
+
+ /// <summary>
+ /// Read the next int64 in the buffer
+ /// </summary>
+ /// <returns>The next int64 available</returns>
+ public long GetInt64()
+ {
+ return (long)GetUInt64();
+ }
+ /// <summary>
+ /// Read the int64 at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public long GetInt64(int position)
+ {
+ return (long)GetUInt64(position);
+ }
+
+ /// <summary>
+ /// Write a int64 at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(long value)
+ {
+ return Put((ulong)value);
+ }
+
+ /// <summary>
+ /// Write a int64 at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, long value)
+ {
+ return Put(position, (ulong)value);
+ }
+
+
+ // Float Stuff
+
+ /// <summary>
+ /// Read the next float in the buffer
+ /// </summary>
+ /// <returns>The next float available</returns>
+ public float GetFloat()
+ {
+ unsafe
+ {
+ uint val = GetUInt32();
+ return *((float*)&val);
+ }
+ }
+ /// <summary>
+ /// Read the float at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public float GetFloat(int position)
+ {
+ unsafe
+ {
+ uint val = GetUInt32(position);
+ return *((float*)&val);
+ }
+ }
+
+ /// <summary>
+ /// Write a float at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(float value)
+ {
+ unsafe
+ {
+ uint val = *((uint*)&value);
+ return Put(val);
+ }
+ }
+
+ /// <summary>
+ /// Write a float at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, float value)
+ {
+ unsafe
+ {
+ uint val = *((uint*)&value);
+ return Put(position, val);
+ }
+ }
+
+ // Double Stuff
+
+ /// <summary>
+ /// Read the next double in the buffer
+ /// </summary>
+ /// <returns>The next double available</returns>
+ public double GetDouble()
+ {
+ unsafe
+ {
+ ulong val = GetUInt64();
+ return *((double*)&val);
+ }
+ }
+ /// <summary>
+ /// Read the double at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public double GetDouble(int position)
+ {
+ unsafe
+ {
+ ulong val = GetUInt64(position);
+ return *((double*)&val);
+ }
+ }
+
+ /// <summary>
+ /// Write a double at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(double value)
+ {
+ unsafe
+ {
+ ulong val = *((ulong*)&value);
+ return Put(val);
+ }
+ }
+
+ /// <summary>
+ /// Write a double at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, double value)
+ {
+ unsafe
+ {
+ ulong val = *((ulong*)&value);
+ return Put(position, val);
+ }
+ }
+
+ // Char Stuff
+
+ /// <summary>
+ /// Read the next char in the buffer
+ /// </summary>
+ /// <returns>The next char available</returns>
+ public char GetChar()
+ {
+ return (char)GetUInt16();
+ }
+ /// <summary>
+ /// Read the char at the specified position
+ /// </summary>
+ /// <param name="position">Position to read from</param>
+ /// <returns>The value at the position</returns>
+ public char GetChar(int position)
+ {
+ return (char)GetUInt16(position);
+ }
+
+ /// <summary>
+ /// Write a char at the current position
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(char value)
+ {
+ return Put((ushort) value);
+ }
+
+ /// <summary>
+ /// Write a char at the specified position
+ /// </summary>
+ /// <param name="position">Position to write to</param>
+ /// <param name="value">Value to write</param>
+ /// <returns>This instance</returns>
+ public ByteBuffer Put(int position, char value)
+ {
+ return Put(position, (ushort)value);
+ }
+
+ // Byte[] stuff
+
+ public void GetBytes(byte[] buffer)
+ {
+ GetBytes(buffer, 0, buffer.Length);
+ }
+
+ public void GetBytes(byte[] buffer, int offset, int length)
+ {
+ GetBytes(Position, buffer, offset, length);
+ Position += length;
+ }
+ public void GetBytes(int position, byte[] buffer, int offset, int length)
+ {
+ CheckSpaceForReading(position, length);
+ if ( offset + length > buffer.Length )
+ throw new ArgumentException("Invalid offset + length");
+ ReadBytes(position, buffer, offset, length);
+ }
+
+ public ByteBuffer Put(byte[] buffer)
+ {
+ return Put(buffer, 0, buffer.Length);
+ }
+
+ public ByteBuffer Put(byte[] buffer, int offset, int length)
+ {
+ Put(Position, buffer, offset, length);
+ Position += length;
+ return this;
+ }
+
+ public ByteBuffer Put(int position, byte[] buffer, int offset, int length)
+ {
+ CheckSpaceForWriting(position, length);
+ if ( offset + length > buffer.Length )
+ throw new ArgumentException("Invalid offset + length");
+
+ Write(position, buffer, offset, length);
+ return this;
+ }
+
+ public ByteBuffer Put(ByteBuffer data)
+ {
+ Put(Position, data);
+ Position += data.Remaining;
+ return this;
+ }
+
+ public ByteBuffer Put(int position, ByteBuffer data)
+ {
+ CheckSpaceForWriting(position, data.Remaining);
+ Write(position, data.Array, data.Position, data.Remaining);
+ return this;
+ }
+
+ #endregion // Data Accessors
+
+ #region Core Overrides
+ //
+ // Core Overrides
+ //
+
+ protected abstract void DoWrite(int position, byte value);
+ protected abstract void DoWrite(int position, byte[] src, int offset, int length);
+ protected abstract byte DoReadByte(int position);
+ protected abstract void DoReadBytes(int position, byte[] dest, int offset, int length);
+ protected abstract void DoCompact();
+ protected abstract void DoResize(int newSize);
+
+ #endregion // Core Overrides
+
+ #region Private Methods
+ //
+ // Private Methods
+ //
+
+ private void Seek(int offset)
+ {
+ if ( offset > Capacity )
+ throw new ArgumentException("Cannot position beyond end of buffer");
+ _position = offset;
+ AdjustLimit();
+ }
+
+ private void SetLimit(int newLimit)
+ {
+ if ( newLimit < 0 )
+ throw new ArgumentOutOfRangeException("The new limit must be a positive value");
+ if ( newLimit > Capacity )
+ throw new ArgumentOutOfRangeException("The new limit must not be greater than the capacity");
+ _limit = newLimit;
+ if ( _position > newLimit )
+ _position = newLimit;
+ }
+
+ private void AdjustLimit()
+ {
+ if ( _limit < _position )
+ _limit = _position;
+ }
+
+ private void CheckSpaceForReading(int position, int length)
+ {
+ if ( position + length > Limit )
+ {
+ throw new BufferUnderflowException("Attempt to read " + length + " byte(s) to buffer where position is " + position +
+ " and limit is " + Limit);
+ }
+ }
+
+ private void CheckSpaceForWriting(int position, int length)
+ {
+ if ( IsAutoExpand )
+ {
+ Expand(position, length);
+ }
+ if ( position + length > Limit )
+ {
+ throw new BufferOverflowException("Attempt to write " + length + " byte(s) to buffer where position is " + position +
+ " and limit is " + Limit);
+ }
+ }
+
+ private void Write(int position, byte value)
+ {
+ DoWrite(position, value);
+ }
+ private void Write(int position, byte[] src, int offset, int length)
+ {
+ DoWrite(position, src, offset, length);
+ }
+ private byte ReadByte(int position)
+ {
+ return DoReadByte(position);
+ }
+ private void ReadBytes(int position, byte[] dest, int offset, int length)
+ {
+ DoReadBytes(position, dest, offset, length);
+ }
+
+ #endregion // Private Methods
+
+ } // class ByteBuffer
+}
diff --git a/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs b/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs
new file mode 100644
index 0000000000..4c2856c333
--- /dev/null
+++ b/dotnet/Qpid.Buffer/ByteBufferHexDumper.cs
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Text;
+
+namespace Apache.Qpid.Buffer
+{
+ public class ByteBufferHexDumper
+ {
+ private static byte[] highDigits;
+
+ private static byte[] lowDigits;
+
+ static ByteBufferHexDumper()
+ {
+ byte[] digits = { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+ (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D',
+ (byte)'E', (byte)'F' };
+ int i;
+ byte[] high = new byte[256];
+ byte[] low = new byte[256];
+
+ for (i = 0; i < 256; i++)
+ {
+ high[i] = digits[i >> 4];
+ low[i] = digits[i & 0x0F];
+ }
+
+ highDigits = high;
+ lowDigits = low;
+ }
+
+ public static string GetHexDump(ByteBuffer input)
+ {
+ int size = input.Remaining;
+ if (size == 0)
+ {
+ return "empty";
+ }
+
+ StringBuilder output = new StringBuilder(size * 3 - 1);
+
+ byte[] data = input.Array;
+ int byteValue = data[0] & 0xFF;
+ output.Append((char) highDigits[byteValue]);
+ output.Append((char) lowDigits[byteValue]);
+
+ for (int i = 1 ; i < size; i++)
+ {
+ output.Append(' ');
+ byteValue = data[i] & 0xFF;
+ output.Append((char) highDigits[byteValue]);
+ output.Append((char) lowDigits[byteValue]);
+ }
+
+ return output.ToString();
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Buffer/IByteBufferAllocator.cs b/dotnet/Qpid.Buffer/IByteBufferAllocator.cs
new file mode 100644
index 0000000000..74944f7e69
--- /dev/null
+++ b/dotnet/Qpid.Buffer/IByteBufferAllocator.cs
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+
+namespace Apache.Qpid.Buffer
+{
+ /// <summary>
+ /// Allocates <see cref="ByteBuffer"/>'s and manages them. Please
+ /// implement this interface if you need more advanced memory management scheme
+ /// </summary>
+ public interface IByteBufferAllocator : IDisposable
+ {
+ /// <summary>
+ /// Returns the buffer which is capable of the specified size.
+ /// </summary>
+ /// <param name="capacity">The capacity of the buffer</param>
+ /// <returns>A new buffer</returns>
+ ByteBuffer Allocate(int capacity);
+
+ /// <summary>
+ /// Wrap the specified byte array in a new buffer
+ /// </summary>
+ /// <param name="src">Source array</param>
+ /// <returns>A new buffer</returns>
+ ByteBuffer Wrap(byte[] src);
+
+ } // interface IByteBufferAllocator
+}
+
+
+
diff --git a/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs b/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..b692af7ce5
--- /dev/null
+++ b/dotnet/Qpid.Buffer/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.ByteBuffer")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.ByteBuffer")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2b3333e5-03b5-4f00-9215-66009f8a5c47")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Buffer/Qpid.Buffer.csproj b/dotnet/Qpid.Buffer/Qpid.Buffer.csproj
new file mode 100644
index 0000000000..d13f399196
--- /dev/null
+++ b/dotnet/Qpid.Buffer/Qpid.Buffer.csproj
@@ -0,0 +1,77 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Buffer</RootNamespace>
+ <AssemblyName>Apache.Qpid.Buffer</AssemblyName>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Buffer/SimpleByteBuffer.cs b/dotnet/Qpid.Buffer/SimpleByteBuffer.cs
new file mode 100644
index 0000000000..956c59aa45
--- /dev/null
+++ b/dotnet/Qpid.Buffer/SimpleByteBuffer.cs
@@ -0,0 +1,120 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Buffer
+{
+ internal sealed class SimpleByteBuffer : ByteBuffer
+ {
+ private byte[] _buffer;
+
+ public override int Capacity
+ {
+ get { return _buffer.Length; }
+ }
+
+ public override byte[] Array
+ {
+ get { return _buffer; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance with the desired size
+ /// </summary>
+ /// <param name="desiredSize">Initial Length of the array</param>
+ internal SimpleByteBuffer(int desiredSize)
+ {
+ _buffer = new byte[desiredSize];
+ Position = 0;
+ Limit = Capacity;
+ }
+
+ /// <summary>
+ /// Initialize a new instance with the data from
+ /// an underlying array
+ /// </summary>
+ /// <param name="buffer">Initial data</param>
+ /// <remarks>The original array is copied during construction and is not modified</remarks>
+ internal SimpleByteBuffer(byte[] buffer)
+ {
+ _buffer = (byte[])buffer.Clone();
+ // position at end
+ Position = Limit = Capacity;
+ }
+
+ protected override void DoWrite(int position, byte value)
+ {
+ // available space is already handled by base class
+ _buffer[position] = value;
+ }
+
+ protected override void DoWrite(int position, byte[] src, int offset, int length)
+ {
+ // available space is already handled by base class
+ for ( int i = 0; i < length; i++ )
+ {
+ _buffer[position+i] = src[offset+i];
+ }
+ }
+
+ protected override byte DoReadByte(int position)
+ {
+ return _buffer[position];
+ }
+
+ protected override void DoReadBytes(int position, byte[] dest, int offset, int length)
+ {
+ System.Array.Copy(_buffer, position, dest, offset, length);
+ }
+
+ protected override void DoCompact()
+ {
+ if ( Remaining > 0 )
+ {
+ if ( Position > 0 )
+ {
+ System.Array.Copy(_buffer, Position, _buffer, 0, Remaining);
+ }
+ Position = Remaining;
+ } else
+ {
+ Position = 0;
+ }
+ Limit = Capacity;
+ }
+
+ protected override void DoResize(int newSize)
+ {
+ if ( newSize < Capacity )
+ throw new NotSupportedException("Cannot resize a buffer to make it smaller");
+
+ int newCapacity = 1;
+ while ( newCapacity < newSize )
+ {
+ newCapacity <<= 1;
+ }
+
+ byte[] newBuffer = new byte[newCapacity];
+ System.Array.Copy(_buffer, newBuffer, _buffer.Length);
+ _buffer = newBuffer;
+ }
+ } // class SimpleByteBuffer
+}
diff --git a/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs b/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs
new file mode 100644
index 0000000000..e772e59ae3
--- /dev/null
+++ b/dotnet/Qpid.Buffer/SimpleByteBufferAllocator.cs
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+namespace Apache.Qpid.Buffer
+{
+ /// <summary>
+ /// Allocates <see cref="ByteBuffer"/>'s and manages them.
+ /// This is a simple implementation that just returns buffers
+ /// as they are. Buffers are not reused or refcounted
+ /// </summary>
+ public class SimpleByteBufferAllocator : IByteBufferAllocator
+ {
+ #region IByteBufferAllocator Members
+
+ public ByteBuffer Allocate(int capacity)
+ {
+ return new SimpleByteBuffer(capacity);
+ }
+
+ public ByteBuffer Wrap(byte[] src)
+ {
+ return new SimpleByteBuffer(src);
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ // no need to do anaything
+ }
+
+ #endregion
+
+ } // class SimpleByteBufferAllocator
+}
+
+
+
diff --git a/dotnet/Qpid.Buffer/SlicedByteBuffer.cs b/dotnet/Qpid.Buffer/SlicedByteBuffer.cs
new file mode 100644
index 0000000000..890e2a3c7a
--- /dev/null
+++ b/dotnet/Qpid.Buffer/SlicedByteBuffer.cs
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Buffer
+{
+ internal sealed class SlicedByteBuffer : ByteBuffer
+ {
+ private ByteBuffer _buffer;
+ private int _capacity;
+ private int _startPos;
+
+ public override int Capacity
+ {
+ get { return _capacity; }
+ }
+
+ public override byte[] Array
+ {
+ get { return _buffer.Array; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance
+ /// </summary>
+ /// <param name="buffer">Underlying byte buffer</param>
+ internal SlicedByteBuffer(ByteBuffer buffer)
+ {
+ _buffer = buffer;
+ _startPos = buffer.Position;
+ Position = 0;
+ _capacity = buffer.Remaining;
+ Limit = Capacity;
+ // cannot autoexpand
+ IsAutoExpand = false;
+ }
+
+ protected override void DoWrite(int position, byte value)
+ {
+ _buffer.Put(_startPos + position, value);
+ }
+
+ protected override void DoWrite(int position, byte[] src, int offset, int length)
+ {
+ _buffer.Put(_startPos + position, src, offset, length);
+ }
+
+ protected override byte DoReadByte(int position)
+ {
+ return _buffer.GetByte(_startPos + position);
+ }
+
+ protected override void DoReadBytes(int position, byte[] dest, int offset, int length)
+ {
+ _buffer.GetBytes(_startPos + position, dest, offset, length);
+ }
+
+ protected override void DoCompact()
+ {
+ throw new NotSupportedException();
+ }
+
+ protected override void DoResize(int newSize)
+ {
+ throw new NotSupportedException();
+ }
+ } // class SlicedByteBuffer
+}
diff --git a/dotnet/Qpid.Buffer/default.build b/dotnet/Qpid.Buffer/default.build
new file mode 100644
index 0000000000..efb5a8fc89
--- /dev/null
+++ b/dotnet/Qpid.Buffer/default.build
@@ -0,0 +1,46 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Buffer" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ unsafe="true"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Client.Tests/App.config b/dotnet/Qpid.Client.Tests/App.config
new file mode 100644
index 0000000000..e71a468a3a
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/App.config
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <configSections>
+ <sectionGroup name="qpid.client">
+ <section name="authentication" type="Apache.Qpid.Client.Configuration.AuthenticationConfigurationSectionHandler, Apache.Qpid.Client"/>
+ </sectionGroup>
+ </configSections>
+ <qpid.client>
+ <authentication>
+ <add key="TEST" value="Apache.Qpid.Client.Tests.Security.TestCallbackHandler, Apache.Qpid.Client.Tests"/>
+ </authentication>
+ </qpid.client>
+</configuration>
diff --git a/dotnet/Qpid.Client.Tests/BrokerDetails/BrokerDetailsTest.cs b/dotnet/Qpid.Client.Tests/BrokerDetails/BrokerDetailsTest.cs
new file mode 100644
index 0000000000..56269c0f9d
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/BrokerDetails/BrokerDetailsTest.cs
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Net;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Tests.BrokerDetails
+{
+ [TestFixture]
+ public class BrokerDetailsTest
+ {
+
+ [Test]
+ public void ValidateBrokerInfoEqualsMethod()
+ {
+ AmqBrokerInfo broker = new AmqBrokerInfo("amqp", "localhost", 5672, true);
+ AmqBrokerInfo broker1 = new AmqBrokerInfo("Amqp", "localhost", 5672, true);
+
+ Assert.IsTrue(broker.Equals(broker1),"The two AmqBrokerInfo objects are not equals");
+ Console.WriteLine(string.Format("The object broker: {0} and broker1: {1} are equals", broker, broker1));
+ }
+
+ [Test]
+ public void ValidateBrokerInfoWithDifferentSSL()
+ {
+ AmqBrokerInfo broker = new AmqBrokerInfo("amqp", "localhost", 5672, true);
+ AmqBrokerInfo broker1 = new AmqBrokerInfo("amqp", "localhost", 5672, false);
+
+ Assert.IsFalse(broker.Equals(broker1), "The two AmqBrokerInfo objects are equals");
+ Console.WriteLine(string.Format("The object broker: {0} and broker1: {1} are not equals", broker, broker1));
+ }
+
+ [Test]
+ public void ValidateBrokerInfoFromToString()
+ {
+ String url = "tcp://localhost:5672?timeout='200',immediatedelivery='true'";
+
+ AmqBrokerInfo broker = new AmqBrokerInfo(url);
+ AmqBrokerInfo broker1 = new AmqBrokerInfo(broker.ToString());
+
+ Assert.AreEqual(broker.GetOption("timeout"), broker1.GetOption("timeout"));
+ Assert.AreEqual(broker.GetOption("immediatedelivery"), broker1.GetOption("immediatedelivery"));
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client.Tests/Channel/ChannelMessageCreationTests.cs b/dotnet/Qpid.Client.Tests/Channel/ChannelMessageCreationTests.cs
new file mode 100644
index 0000000000..f4f217c2a0
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/Channel/ChannelMessageCreationTests.cs
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Client;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client.Tests.Channel
+{
+ /// <summary>
+ /// Test that channels can create messages correctly
+ /// </summary>
+ [TestFixture]
+ public class ChannelMessageCreationTests
+ {
+ [Test]
+ public void CanCreateTextMessage()
+ {
+ IChannel channel = AmqChannel.CreateDisconnectedChannel();
+ ITextMessage msg = channel.CreateTextMessage();
+ Assert.IsNotNull(msg);
+ }
+ [Test]
+ public void CanCreateTextMessageWithContent()
+ {
+ IChannel channel = AmqChannel.CreateDisconnectedChannel();
+ const string CONTENT = "1234567890";
+ ITextMessage msg = channel.CreateTextMessage(CONTENT);
+ Assert.IsNotNull(msg);
+ Assert.AreEqual(CONTENT, msg.Text);
+ }
+ [Test]
+ public void CanCreateBytesMessage()
+ {
+ IChannel channel = AmqChannel.CreateDisconnectedChannel();
+ IBytesMessage msg = channel.CreateBytesMessage();
+ Assert.IsNotNull(msg);
+ }
+ [Test]
+ public void CanCreateMessage()
+ {
+ IChannel channel = AmqChannel.CreateDisconnectedChannel();
+ IMessage msg = channel.CreateMessage();
+ Assert.IsNotNull(msg);
+ }
+ [Test]
+ public void CanCreateMessageFromMimeType()
+ {
+ IChannel channel = AmqChannel.CreateDisconnectedChannel();
+ IMessage msg = channel.CreateMessage("text/xml");
+ Assert.IsNotNull(msg);
+ Assert.IsInstanceOfType(typeof(ITextMessage), msg);
+ }
+ }
+} // namespace Apache.Qpid.Client.Tests.Channel
+
+
diff --git a/dotnet/Qpid.Client.Tests/Messages/MessageFactoryRegistryTests.cs b/dotnet/Qpid.Client.Tests/Messages/MessageFactoryRegistryTests.cs
new file mode 100644
index 0000000000..4db3c91cb5
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/Messages/MessageFactoryRegistryTests.cs
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Message;
+
+namespace Apache.Qpid.Client.Tests.Messages
+{
+ /// <summary>
+ /// Ensure a factory creates messages correctly
+ /// </summary>
+ [TestFixture]
+ public class MessageFactoryRegistryTests
+ {
+ const string TEXT_PLAIN = "text/plain";
+ const string TEXT_XML = "text/xml";
+ const string OCTET_STREAM = "application/octet-stream";
+
+ /// <summary>
+ /// Check default registry can create text/plain messages
+ /// </summary>
+ [Test]
+ public void CanCreateTextPlain()
+ {
+ MessageFactoryRegistry registry =
+ MessageFactoryRegistry.NewDefaultRegistry();
+
+ IMessage message = registry.CreateMessage(TEXT_PLAIN);
+ Assert.IsNotNull(message);
+ Assert.AreEqual(TEXT_PLAIN, message.ContentType);
+ Assert.IsInstanceOfType(typeof(QpidTextMessage), message);
+ }
+ /// <summary>
+ /// Check default registry can create text/xml messages
+ /// </summary>
+ [Test]
+ public void CanCreateTextXml()
+ {
+ MessageFactoryRegistry registry =
+ MessageFactoryRegistry.NewDefaultRegistry();
+
+ IMessage message = registry.CreateMessage(TEXT_XML);
+ Assert.IsNotNull(message);
+ Assert.AreEqual(TEXT_XML, message.ContentType);
+ Assert.IsInstanceOfType(typeof(QpidTextMessage), message);
+ }
+ /// <summary>
+ /// Check default registry can create application/octet-stream messages
+ /// </summary>
+ [Test]
+ public void CanCreateBinary()
+ {
+ MessageFactoryRegistry registry =
+ MessageFactoryRegistry.NewDefaultRegistry();
+
+ IMessage message = registry.CreateMessage(OCTET_STREAM);
+ Assert.IsNotNull(message);
+ Assert.AreEqual(OCTET_STREAM, message.ContentType);
+ Assert.IsInstanceOfType(typeof(QpidBytesMessage), message);
+ }
+ /// <summary>
+ /// Check default registry can create messages for unknown types
+ /// </summary>
+ [Test]
+ public void CanCreateUnknownType()
+ {
+ MessageFactoryRegistry registry =
+ MessageFactoryRegistry.NewDefaultRegistry();
+
+ const string OTHER = "application/unknown";
+ IMessage message = registry.CreateMessage(OTHER);
+ Assert.IsNotNull(message);
+ Assert.AreEqual(OTHER, message.ContentType);
+ Assert.IsInstanceOfType(typeof(QpidBytesMessage), message);
+ }
+ /// <summary>
+ /// Check that text messages default to UTF-8 encoding
+ /// </summary>
+ [Test]
+ public void TextMessagesDefaultToUTF8Encoding()
+ {
+ MessageFactoryRegistry registry =
+ MessageFactoryRegistry.NewDefaultRegistry();
+
+ IMessage message = registry.CreateMessage(TEXT_PLAIN);
+ Assert.AreEqual("utf-8", message.ContentEncoding.ToLower());
+ }
+
+ }
+} // namespace Apache.Qpid.Client.Tests.Messages
+
+
diff --git a/dotnet/Qpid.Client.Tests/Properties/AssemblyInfo.cs b/dotnet/Qpid.Client.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..c710818053
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+using log4net.Config;
+[assembly: XmlConfigurator(ConfigFile="log4net.config")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Client.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Client.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7ebdea21-1352-4673-b66e-fdc0beff461f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
diff --git a/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj b/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
new file mode 100644
index 0000000000..73eabfa1f8
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/Qpid.Client.Tests.csproj
@@ -0,0 +1,158 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Client.Tests</RootNamespace>
+ <AssemblyName>Apache.Qpid.Client.Tests</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <PublishUrl>http://localhost/Apache.Qpid.Client.Tests/</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Web</InstallFrom>
+ <UpdateEnabled>true</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>true</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Common\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.2.6.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="log4net.config">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="interop\TestCases\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Client.Tests/Security/CallbackHandlerRegistryTests.cs b/dotnet/Qpid.Client.Tests/Security/CallbackHandlerRegistryTests.cs
new file mode 100644
index 0000000000..f1446a9aa6
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/Security/CallbackHandlerRegistryTests.cs
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using NUnit.Framework;
+using Apache.Qpid.Client.Security;
+
+
+namespace Apache.Qpid.Client.Tests.Security
+{
+ [TestFixture]
+ public class CallbackRegistryHandlerTests
+ {
+ [Test]
+ public void ParsesConfiguration()
+ {
+ CallbackHandlerRegistry registry = CallbackHandlerRegistry.Instance;
+ Assert.AreEqual(4, registry.Mechanisms.Length);
+ Assert.Contains("TEST", registry.Mechanisms);
+
+ Type handlerType = registry.GetCallbackHandler("TEST");
+ Assert.IsNotNull(handlerType);
+ Assert.AreEqual(typeof(TestCallbackHandler), handlerType);
+ }
+
+ [Test]
+ public void MechanimsInOrder()
+ {
+ CallbackHandlerRegistry registry = CallbackHandlerRegistry.Instance;
+ Assert.AreEqual(4, registry.Mechanisms.Length);
+ Assert.AreEqual("TEST", registry.Mechanisms[0]);
+ Assert.AreEqual("EXTERNAL", registry.Mechanisms[1]);
+ Assert.AreEqual("CRAM-MD5", registry.Mechanisms[2]);
+ Assert.AreEqual("PLAIN", registry.Mechanisms[3]);
+ }
+ } // class CallbackRegistryHandlerTests
+
+ public class TestCallbackHandler : IAMQCallbackHandler
+ {
+ public void Initialize(Qpid.Client.Protocol.AMQProtocolSession session)
+ {
+ }
+ public void Handle(Qpid.Sasl.ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class TestCallbackHandler
+
+} // namespace Apache.Qpid.Client.Tests.Connection
diff --git a/dotnet/Qpid.Client.Tests/default.build b/dotnet/Qpid.Client.Tests/default.build
new file mode 100644
index 0000000000..5116e651e1
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/default.build
@@ -0,0 +1,64 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Client" default="test">
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="false" debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.Tests.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/${project::get-name()}.dll" />
+ <include name="${build.dir}/Apache.Qpid.Common.dll" />
+ <include name="${build.dir}/Apache.Qpid.Messaging.dll" />
+ <include name="${build.dir}/Apache.Qpid.Sasl.dll" />
+ </references>
+ </csc>
+ <copy tofile="${build.dir}/${project::get-name()}.Tests.dll.config" file="App.config" />
+ <copy todir="${build.dir}" file="log4net.config"/>
+ </target>
+
+ <target name="test" depends="build">
+ <nunit2 verbose="true">
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test>
+ <assemblies>
+ <include name="${build.dir}/${project::get-name()}.tests.dll"/>
+ </assemblies>
+ <categories>
+ <!-- The fail-over tests are interactive so should not be run as part of the build. -->
+ <exclude name="Integration"/>
+ <exclude name="SSL" if="${framework::get-target-framework() == 'mono-2.0'}"/>
+ </categories>
+ </test>
+ </nunit2>
+ </target>
+
+</project>
+
diff --git a/dotnet/Qpid.Client.Tests/interop/TopicListener.cs b/dotnet/Qpid.Client.Tests/interop/TopicListener.cs
new file mode 100644
index 0000000000..b355abb28d
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/interop/TopicListener.cs
@@ -0,0 +1,211 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Tests.interop
+{
+ public class TopicListener
+ {
+ private static ILog log = LogManager.GetLogger(typeof(TopicListener));
+
+ /// <summary> The default AMQ connection URL to use for tests. </summary>
+ const string DEFAULT_URI = "amqp://guest:guest@default/test?brokerlist='tcp://localhost:5672'";
+
+ /// <summary> Holds the routing key for the topic to receive test messages on. </summary>
+ public static string CONTROL_ROUTING_KEY = "topic_control";
+
+ /// <summary> Holds the routing key for the queue to send reports to. </summary>
+ public static string RESPONSE_ROUTING_KEY = "response";
+
+ /// <summary> Holds the connection to listen on. </summary>
+ private IConnection connection;
+
+ /// <summary> Holds the channel for all test messages.</summary>
+ private IChannel channel;
+
+ /// <summary> Holds the producer to send report messages on. </summary>
+ private IMessagePublisher publisher;
+
+ /// <summary> Holds a flag to indicate that a timer has begun on the first message. Reset when report is sent. </summary> */
+ private bool init;
+
+ /// <summary> Holds the count of messages received by this listener. </summary> */
+ private int count;
+
+ /// <summary> Creates a topic listener using the specified broker URL. </summary>
+ ///
+ /// <param name="connectionUri">The broker URL to listen on.</param>
+ TopicListener(string connectionUri)
+ {
+ log.Debug("TopicListener(string connectionUri = " + connectionUri + "): called");
+
+ // Create a connection to the broker.
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(connectionUri);
+ connection = new AMQConnection(connectionInfo);
+
+ // Establish a session on the broker.
+ channel = connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge, 1);
+
+ // Set up a queue to listen for test messages on.
+ string topicQueueName = channel.GenerateUniqueName();
+ channel.DeclareQueue(topicQueueName, false, true, true);
+
+ // Set this listener up to listen for incoming messages on the test topic queue.
+ channel.Bind(topicQueueName, ExchangeNameDefaults.TOPIC, CONTROL_ROUTING_KEY);
+ IMessageConsumer consumer = channel.CreateConsumerBuilder(topicQueueName)
+ .Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ // Set up this listener with a producer to send the reports on.
+ publisher = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.DIRECT)
+ .WithRoutingKey(RESPONSE_ROUTING_KEY)
+ .Create();
+
+ connection.Start();
+ Console.WriteLine("Waiting for messages...");
+ }
+
+ public static void Main(String[] argv)
+ {
+ // Create an instance of this listener with the command line parameters.
+ new TopicListener(DEFAULT_URI);
+ }
+
+ /// <summary>
+ /// Handles all message received by this listener. Test messages are counted, report messages result in a report being sent and
+ /// shutdown messages result in this listener being terminated.
+ /// </summary>
+ ///
+ /// <param name="message">The received message.</param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void onMessage(Message message = " + message + "): called");
+
+ // Take the start time of the first message if this is the first message.
+ if (!init)
+ {
+ count = 0;
+ init = true;
+ }
+
+ // Check if the message is a control message telling this listener to shut down.
+ if (IsShutdown(message))
+ {
+ log.Debug("Got a shutdown message.");
+ Shutdown();
+ }
+ // Check if the message is a report request message asking this listener to respond with the message count.
+ else if (IsReport(message))
+ {
+ log.Debug("Got a report request message.");
+
+ // Send the message count report.
+ SendReport();
+
+ // Reset the initialization flag so that the next message is considered to be the first.
+ init = false;
+ }
+ // Otherwise it is an ordinary test message, so increment the message count.
+ else
+ {
+ count++;
+ }
+ }
+
+ /// <summary> Checks a message to see if it is a shutdown control message. </summary>
+ ///
+ /// <param name="m">The message to check.</param>
+ ///
+ /// <returns><tt>true</tt> if it is a shutdown control message, <tt>false</tt> otherwise.</returns>
+ private bool IsShutdown(IMessage m)
+ {
+ bool result = CheckTextField(m, "TYPE", "TERMINATION_REQUEST");
+
+ //log.Debug("isShutdown = " + result);
+
+ return result;
+ }
+
+ /// <summary> Checks a message to see if it is a report request control message. </summary>
+ ///
+ /// <param name="m">The message to check.</param>
+ ///
+ /// <returns><tt>true</tt> if it is a report request control message, <tt>false</tt> otherwise.</returns>
+ private bool IsReport(IMessage m)
+ {
+ bool result = CheckTextField(m, "TYPE", "REPORT_REQUEST");
+
+ //log.Debug("isReport = " + result);
+
+ return result;
+ }
+
+ /// <summary> Checks whether or not a text field on a message has the specified value. </summary>
+ ///
+ /// <param name="e">The message to check.</param>
+ /// <param name="e">The name of the field to check.</param>
+ /// <param name="e">The expected value of the field to compare with.</param>
+ ///
+ /// <returns> <tt>true</tt>If the specified field has the specified value, <tt>fals</tt> otherwise. </returns>
+ private static bool CheckTextField(IMessage m, string fieldName, string value)
+ {
+ /*log.Debug("private static boolean checkTextField(Message m = " + m + ", String fieldName = " + fieldName
+ + ", String value = " + value + "): called");*/
+
+ string comp = m.Headers.GetString(fieldName);
+
+ return (comp != null) && comp == value;
+ }
+
+ /// <summary> Stops the message consumer and closes the connection. </summary>
+ private void Shutdown()
+ {
+ connection.Stop();
+ channel.Dispose();
+ connection.Dispose();
+ }
+
+ /// <summary> Sends the report message to the response location. </summary>
+ private void SendReport()
+ {
+ string report = "Received " + count + ".";
+
+ IMessage reportMessage = channel.CreateTextMessage(report);
+
+ reportMessage.Headers.SetBoolean("BOOLEAN", false);
+ //reportMessage.Headers.SetByte("BYTE", 5);
+ reportMessage.Headers.SetDouble("DOUBLE", 3.141);
+ reportMessage.Headers.SetFloat("FLOAT", 1.0f);
+ reportMessage.Headers.SetInt("INT", 1);
+ reportMessage.Headers.SetLong("LONG", 1);
+ reportMessage.Headers.SetString("STRING", "hello");
+ reportMessage.Headers.SetShort("SHORT", 2);
+
+ publisher.Send(reportMessage);
+
+ Console.WriteLine("Sent report: " + report);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client.Tests/interop/TopicPublisher.cs b/dotnet/Qpid.Client.Tests/interop/TopicPublisher.cs
new file mode 100644
index 0000000000..4fd0419e9c
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/interop/TopicPublisher.cs
@@ -0,0 +1,208 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Tests.interop
+{
+ public class TopicPublisher
+ {
+ private static ILog log = LogManager.GetLogger(typeof(TopicPublisher));
+
+ /// <summary> The default AMQ connection URL to use for tests. </summary>
+ const string DEFAULT_URI = "amqp://guest:guest@default/test?brokerlist='tcp://localhost:5672'";
+
+ /// <summary> Holds the default test timeout for broker communications before tests give up. </summary>
+ const int TIMEOUT = 10000;
+
+ /// <summary> Holds the routing key for the topic to receive test messages on. </summary>
+ const string CONTROL_ROUTING_KEY = "topic_control";
+
+ /// <summary> Holds the routing key for the queue to send reports to. </summary>
+ const string RESPONSE_ROUTING_KEY = "response";
+
+ /// <summary> Holds the number of messages to send in each test run. </summary>
+ private int numMessages;
+
+ /// <summary> Holds the number of subscribers listening to the messsages. </summary>
+ private int numSubscribers;
+
+ /// <summary> A monitor used to wait for all reports to arrive back from consumers on. </summary>
+ private AutoResetEvent allReportsReceivedEvt = new AutoResetEvent(false);
+
+ /// <summary> Holds the connection to listen on. </summary>
+ private IConnection connection;
+
+ /// <summary> Holds the channel for all test messages.</summary>
+ private IChannel channel;
+
+ /// <summary> Holds the producer to send test messages on. </summary>
+ private IMessagePublisher publisher;
+
+ /// <summary>
+ /// Creates a topic publisher that will send the specifed number of messages and expect the specifed number of report back from test
+ /// subscribers.
+ /// </summary>
+ ///
+ /// <param name="connectionUri">The broker URL.</param>
+ /// <param name="numMessages">The number of messages to send in each test.</param>
+ /// <param name="numSubscribers">The number of subscribes that are expected to reply with a report.</param>
+ TopicPublisher(string connectionUri, int numMessages, int numSubscribers)
+ {
+ log.Debug("TopicPublisher(string connectionUri = " + connectionUri + ", int numMessages = "+ numMessages +
+ ", int numSubscribers = " + numSubscribers + "): called");
+
+ // Create a connection to the broker.
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(connectionUri);
+ connection = new AMQConnection(connectionInfo);
+
+ // Establish a session on the broker.
+ channel = connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge, 1);
+
+ // Set up a queue to listen for reports on.
+ string responseQueueName = channel.GenerateUniqueName();
+ channel.DeclareQueue(responseQueueName, false, true, true);
+
+ // Set this listener up to listen for reports on the response queue.
+ channel.Bind(responseQueueName, ExchangeNameDefaults.DIRECT, RESPONSE_ROUTING_KEY);
+ //channel.Bind(responseQueueName, "<<default>>", RESPONSE_ROUTING_KEY);
+ IMessageConsumer consumer = channel.CreateConsumerBuilder(responseQueueName)
+ .Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ // Set up this listener with a producer to send the test messages and report requests on.
+ publisher = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(CONTROL_ROUTING_KEY)
+ .Create();
+
+ // Keep the test parameters.
+ this.numMessages = numMessages;
+ this.numSubscribers = numSubscribers;
+
+ connection.Start();
+ Console.WriteLine("Sending messages and waiting for reports...");
+ }
+
+ /// <summary>
+ /// Start a test subscriber. The broker URL must be specified as the first command line argument.
+ /// </summary>
+ ///
+ /// <param name="argv">The command line arguments, broker URL first.</param>
+ public static void Main(String[] argv)
+ {
+ // Create an instance of this publisher with the command line parameters.
+ TopicPublisher publisher = new TopicPublisher(DEFAULT_URI, 1, 1);
+
+ // Publish the test messages.
+ publisher.DoTest();
+ }
+
+ /// <summary>
+ /// Sends the test messages and waits for all subscribers to reply with a report.
+ /// </summary>
+ public void DoTest()
+ {
+ log.Debug("public void DoTest(): called");
+
+ // Create a test message to send.
+ IMessage testMessage = channel.CreateTextMessage("test");
+
+ // Send the desired number of test messages.
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+ }
+
+ log.Debug("Sent " + numMessages + " test messages.");
+
+ // Send the report request.
+ IMessage reportRequestMessage = channel.CreateTextMessage("Report request message.");
+ reportRequestMessage.Headers["TYPE"] = "REPORT_REQUEST";
+
+ reportRequestMessage.Headers.SetBoolean("BOOLEAN", false);
+ //reportRequestMessage.Headers.SetByte("BYTE", 5);
+ reportRequestMessage.Headers.SetDouble("DOUBLE", 3.141);
+ reportRequestMessage.Headers.SetFloat("FLOAT", 1.0f);
+ reportRequestMessage.Headers.SetInt("INT", 1);
+ reportRequestMessage.Headers.SetLong("LONG", 1);
+ reportRequestMessage.Headers.SetString("STRING", "hello");
+ reportRequestMessage.Headers.SetShort("SHORT", 2);
+
+ publisher.Send(reportRequestMessage);
+
+ log.Debug("Sent the report request message, waiting for all replies...");
+
+ // Wait until all the reports come in.
+ allReportsReceivedEvt.WaitOne(TIMEOUT, true);
+
+ // Check if all reports were really received or if the timeout occurred.
+ if (numSubscribers == 0)
+ {
+ log.Debug("Got all reports.");
+ }
+ else
+ {
+ log.Debug("Waiting for reports timed out, still waiting for " + numSubscribers + ".");
+ }
+
+ // Send the termination request.
+ IMessage terminationRequestMessage = channel.CreateTextMessage("Termination request message.");
+ terminationRequestMessage.Headers["TYPE"] = "TERMINATION_REQUEST";
+ publisher.Send(terminationRequestMessage);
+
+ log.Debug("Sent the termination request message.");
+
+ // Close all message producers and consumers and the connection to the broker.
+ Shutdown();
+ }
+
+ /// <summary>
+ /// Handles all report messages from subscribers. This decrements the count of subscribers that are still to reply, until this becomes
+ /// zero, at which time waiting threads are notified of this event.
+ /// </summary>
+ ///
+ /// <param name="message">The received report message.</param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void OnMessage(IMessage message = " + message + "): called");
+
+ // Decrement the count of expected messages and release the wait monitor when this becomes zero.
+ if (--numSubscribers == 0)
+ {
+ log.Debug("Got reports from all subscribers.");
+ allReportsReceivedEvt.Set();
+ }
+ }
+
+ /// <summary> Stops the message consumers and closes the connection. </summary>
+ private void Shutdown()
+ {
+ connection.Stop();
+ publisher.Dispose();
+ channel.Dispose();
+ connection.Dispose();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client.Tests/lib/nunit/nunit-licence.txt b/dotnet/Qpid.Client.Tests/lib/nunit/nunit-licence.txt
new file mode 100644
index 0000000000..b2316295d3
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/lib/nunit/nunit-licence.txt
@@ -0,0 +1,23 @@
+Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov,
+ Charlie Poole
+Copyright © 2000-2004 Philip A. Craig
+
+This software is provided 'as-is', without any express or implied warranty. In
+no event will the authors be held liable for any damages arising from the use
+of this software.
+
+Permission is granted to anyone to use this software for any purpose, including
+commercial applications, and to alter it and redistribute it freely, subject to
+the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a product, an
+ acknowledgment (see the following) in the product documentation is required.
+
+ Portions Copyright © 2002 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
+ or Copyright © 2000-2002 Philip A. Craig
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/dotnet/Qpid.Client.Tests/lib/nunit/nunit.framework.dll b/dotnet/Qpid.Client.Tests/lib/nunit/nunit.framework.dll
new file mode 100644
index 0000000000..53666e74c9
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/lib/nunit/nunit.framework.dll
Binary files differ
diff --git a/dotnet/Qpid.Client.Tests/log4net.config b/dotnet/Qpid.Client.Tests/log4net.config
new file mode 100644
index 0000000000..0ad25c4185
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/log4net.config
@@ -0,0 +1,68 @@
+<!--
+
+ 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.
+
+-->
+<log4net>
+
+ <!-- ============================== -->
+ <!-- Append messages to the console -->
+ <!-- ============================== -->
+
+ <appender name="console" type="log4net.Appender.ConsoleAppender" >
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%m%n"/>
+ </layout>
+ <threshold value="info"/>
+ </appender>
+
+ <!-- ====================================== -->
+ <!-- Append messages to the socket appender -->
+ <!-- ====================================== -->
+
+ <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
+ <remoteAddress value="127.0.0.1"/>
+ <remotePort value="4445"/>
+ <layout type="log4net.Layout.XmlLayoutSchemaLog4j">
+ <locationInfo value="true"/>
+ </layout>
+ <threshold value="debug"/>
+ </appender>
+
+ <!-- ================ -->
+ <!-- Limit categories -->
+ <!-- ================ -->
+
+ <logger name="Qpid">
+ <level value="debug"/>
+ </logger>
+
+ <logger name="CONSOLE">
+ <level value="info"/>
+ <appender-ref ref="console"/>
+ </logger>
+
+ <!-- ======================= -->
+ <!-- Setup the Root category -->
+ <!-- ======================= -->
+
+ <root>
+ <appender-ref ref="UdpAppender"/>
+ </root>
+
+</log4net>
diff --git a/dotnet/Qpid.Client.Tests/url/ConnectionUrlTest.cs b/dotnet/Qpid.Client.Tests/url/ConnectionUrlTest.cs
new file mode 100644
index 0000000000..3c9f8dd4e2
--- /dev/null
+++ b/dotnet/Qpid.Client.Tests/url/ConnectionUrlTest.cs
@@ -0,0 +1,446 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Net;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Tests.url
+{
+ [TestFixture]
+ public class connectionUrlTests
+ {
+ [Test]
+ public void FailoverURL()
+ {
+ //String url = "amqp://ritchiem:bob@/temp?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
+ String url = "amqp://ritchiem:bob@default/temp?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.AreEqual("roundrobin", connectionurl.FailoverMethod);
+ Assert.IsTrue(connectionurl.Username.Equals("ritchiem"));
+ Assert.IsTrue(connectionurl.Password.Equals("bob"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 2);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+
+ service = connectionurl.GetBrokerInfo(1);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("fancyserver"));
+ Assert.IsTrue(service.Port == 3000);
+
+ }
+
+ [Test]
+ public void SingleTransportUsernamePasswordURL()
+ {
+ String url = "amqp://ritchiem:bob@default/temp?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("ritchiem"));
+ Assert.IsTrue(connectionurl.Password.Equals("bob"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ }
+
+ [Test]
+ public void SingleTransportUsernameBlankPasswordURL()
+ {
+ String url = "amqp://ritchiem:@default/temp?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("ritchiem"));
+ Assert.IsTrue(connectionurl.Password.Equals(""));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ }
+
+ [Test]
+ public void FailedURLNullPassword()
+ {
+ String url = "amqp://ritchiem@default/temp?brokerlist='tcp://localhost:5672'";
+
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ Assert.Fail("URL has null password");
+ }
+ catch (UrlSyntaxException e)
+ {
+ Assert.AreEqual("Null password in user information not allowed.", e.Message);
+ Assert.IsTrue(e.GetIndex() == 7);
+ }
+ }
+
+ [Test]
+ public void SingleTransportURL()
+ {
+ String url = "amqp://guest:guest@default/test?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/test"));
+
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ }
+
+ [Test]
+ public void SingleTransportWithClientURLURL()
+ {
+ String url = "amqp://guest:guest@clientname/temp?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+ Assert.IsTrue(connectionurl.ClientName.Equals("clientname"));
+
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ }
+
+ [Test]
+ public void SingleTransport1OptionURL()
+ {
+ String url = "amqp://guest:guest@default/temp?brokerlist='tcp://localhost:5672',routingkey='jim'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ Assert.IsTrue(connectionurl.GetOption("routingkey").Equals("jim"));
+ }
+
+ [Test]
+ public void SingleTransportDefaultedBroker()
+ {
+ String url = "amqp://guest:guest@default/temp?brokerlist='localhost:'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+ }
+
+ [Test]
+ public void SingleTransportMultiOptionURL()
+ {
+ String url = "amqp://guest:guest@default/temp?brokerlist='tcp://localhost:5672',routingkey='jim',timeout='200',immediatedelivery='true'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("tcp"));
+
+ Assert.IsTrue(service.Host.Equals("localhost"));
+ Assert.IsTrue(service.Port == 5672);
+
+ Assert.IsTrue(connectionurl.GetOption("routingkey").Equals("jim"));
+ Assert.IsTrue(connectionurl.GetOption("timeout").Equals("200"));
+ Assert.IsTrue(connectionurl.GetOption("immediatedelivery").Equals("true"));
+ }
+
+ [Test]
+ public void SinglevmURL()
+ {
+ String url = "amqp://guest:guest@default/messages?brokerlist='vm://default:2'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod == null);
+ Assert.IsTrue(connectionurl.Username.Equals("guest"));
+ Assert.IsTrue(connectionurl.Password.Equals("guest"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/messages"));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("vm"));
+ Assert.AreEqual("localhost", service.Host);
+ Assert.AreEqual(2, service.Port);
+ }
+
+ [Test]
+ public void FailoverVMURL()
+ {
+ String url = "amqp://ritchiem:bob@default/temp?brokerlist='vm://default:2;vm://default:3',failover='roundrobin'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.FailoverMethod.Equals("roundrobin"));
+ Assert.IsTrue(connectionurl.Username.Equals("ritchiem"));
+ Assert.IsTrue(connectionurl.Password.Equals("bob"));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/temp"));
+
+ Assert.AreEqual(2, connectionurl.BrokerCount);
+
+ IBrokerInfo service = connectionurl.GetBrokerInfo(0);
+
+ Assert.IsTrue(service.Transport.Equals("vm"));
+ Assert.AreEqual("localhost", service.Host);
+ Assert.IsTrue(service.Port == 2);
+
+ service = connectionurl.GetBrokerInfo(1);
+ Assert.IsTrue(service.Transport.Equals("vm"));
+ Assert.AreEqual("localhost", service.Host);
+ Assert.IsTrue(service.Port == 3);
+ }
+
+ [Test]
+ public void NoVirtualHostURL()
+ {
+ String url = "amqp://user@default?brokerlist='tcp://localhost:5672'";
+
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ Assert.Fail("URL has no virtual host should not parse");
+ }
+ catch (UrlSyntaxException)
+ {
+ // This should occur.
+ }
+ }
+
+ [Test]
+ public void NoClientID()
+ {
+ String url = "amqp://user:@default/test?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connectionurl = QpidConnectionInfo.FromUrl(url);
+
+ Assert.IsTrue(connectionurl.Username.Equals("user"));
+ Assert.IsTrue(connectionurl.Password.Equals(""));
+ Assert.IsTrue(connectionurl.VirtualHost.Equals("/test"));
+ Assert.IsTrue(connectionurl.ClientName.StartsWith(Dns.GetHostName()));
+
+ Assert.IsTrue(connectionurl.BrokerCount == 1);
+ }
+
+ [Test]
+ public void WrongOptionSeparatorInOptions()
+ {
+ String url = "amqp://guest:guest@default/test?brokerlist='tcp://localhost:5672;tcp://localhost:5673'+failover='roundrobin'";
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ Assert.Fail("URL Should not parse");
+ }
+ catch (UrlSyntaxException urise)
+ {
+ Assert.IsTrue(urise.Message.Equals("Unterminated option. Possible illegal option separator:'+'"));
+ }
+
+ }
+
+ [Test]
+ public void NoUserDetailsProvidedWithClientID()
+
+ {
+ String url = "amqp://clientID/test?brokerlist='tcp://localhost:5672;tcp://localhost:5673'";
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ Assert.Fail("URL Should not parse");
+ }
+ catch (UrlSyntaxException urise)
+ {
+ Assert.IsTrue(urise.Message.StartsWith("User information not found on url"));
+ }
+
+ }
+
+ [Test]
+ public void NoUserDetailsProvidedNOClientID()
+
+ {
+ String url = "amqp:///test@default?brokerlist='tcp://localhost:5672;tcp://localhost:5673'";
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ Assert.Fail("URL Should not parse");
+ }
+ catch (UrlSyntaxException urise)
+ {
+
+ Assert.IsTrue(urise.Message.StartsWith("User information not found on url"));
+ }
+
+ }
+
+ [Test]
+ public void CheckVirtualHostFormat()
+ {
+ String url = "amqp://guest:guest@default/t.-_+!=:?brokerlist='tcp://localhost:5672'";
+
+ IConnectionInfo connection = QpidConnectionInfo.FromUrl(url);
+ Assert.IsTrue(connection.VirtualHost.Equals("/t.-_+!=:"));
+ }
+
+ [Test]
+ public void CheckDefaultPort()
+ {
+ String url = "amqp://guest:guest@default/test=:?brokerlist='tcp://localhost'";
+
+ IConnectionInfo connection = QpidConnectionInfo.FromUrl(url);
+
+ IBrokerInfo broker = connection.GetBrokerInfo(0);
+ Assert.IsTrue(broker.Port == BrokerInfoConstants.DEFAULT_PORT);
+
+ }
+
+ [Test]
+ public void CheckMissingFinalQuote()
+ {
+ String url = "amqp://guest:guest@id/test" + "?brokerlist='tcp://localhost:5672";
+
+ try
+ {
+ QpidConnectionInfo.FromUrl(url);
+ }
+ catch (UrlSyntaxException e)
+ {
+// Assert.AreEqual("Unterminated option at index 32: brokerlist='tcp://localhost:5672",
+// e.Message);
+ Assert.AreEqual("Unterminated option", e.Message);
+ }
+ }
+
+ [Test]
+ public void ValidateQpidConnectionInfoFromToString()
+ {
+ String url = "amqp://ritchiem:bob@default/temp?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
+
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(url);
+ IConnectionInfo connectionInfo1 = QpidConnectionInfo.FromUrl(connectionInfo.ToString());
+
+ Console.WriteLine(connectionInfo.ToString());
+ Console.WriteLine(connectionInfo1.ToString());
+
+ Assert.AreEqual(connectionInfo.Username, connectionInfo1.Username);
+ Assert.AreEqual(connectionInfo.Password, connectionInfo1.Password);
+ Assert.AreEqual(connectionInfo.VirtualHost, connectionInfo1.VirtualHost);
+
+ Assert.IsTrue((connectionInfo1.GetAllBrokerInfos().Count == 2));
+ Assert.IsTrue(connectionInfo.GetBrokerInfo(0).Equals(connectionInfo1.GetBrokerInfo(0)));
+ Assert.IsTrue(connectionInfo.GetBrokerInfo(1).Equals(connectionInfo1.GetBrokerInfo(1)));
+
+ }
+
+ [Test]
+ public void EnsureVirtualHostStartsWithSlash()
+ {
+ IConnectionInfo connection = new QpidConnectionInfo();
+ connection.VirtualHost = "test";
+ Assert.AreEqual("/test", connection.VirtualHost);
+
+ connection.VirtualHost = "/mytest";
+ Assert.AreEqual("/mytest", connection.VirtualHost);
+
+ connection.VirtualHost = "";
+ Assert.AreEqual("/", connection.VirtualHost);
+
+ connection.VirtualHost = null;
+ Assert.AreEqual("/", connection.VirtualHost);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketProcessor.cs b/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketProcessor.cs
new file mode 100644
index 0000000000..b62b11a3db
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketProcessor.cs
@@ -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.
+ *
+ */
+using System;
+using System.Net;
+using System.Net.Sockets;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Client.Protocol;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ class BlockingSocketProcessor : IConnectionCloser
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(BlockingSocketProcessor));
+
+ string _host;
+ int _port;
+ System.Net.Sockets.Socket _socket;
+ private NetworkStream _networkStream;
+ IByteChannel _byteChannel;
+ IProtocolListener _protocolListener;
+
+ public BlockingSocketProcessor(string host, int port, IProtocolListener protocolListener)
+ {
+ _host = host;
+ _port = port;
+ _protocolListener = protocolListener;
+ _byteChannel = new ByteChannel(this);
+ }
+
+ /// <summary>
+ /// Synchronous blocking connect.
+ /// </summary>
+ public void Connect()
+ {
+ _socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ /// For future note TCP Set NoDelay options may help, though with the blocking io not sure
+ /// The Don't linger may help with detecting disconnect but that hasn't been the case in testing.
+ /// _socket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.NoDelay, 0);
+ /// _socket.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.DontLinger, 0);
+
+ IPHostEntry ipHostInfo = Dns.Resolve(_host); // Note: don't fix this warning. We do this for .NET 1.1 compatibility.
+ IPAddress ipAddress = ipHostInfo.AddressList[0];
+
+ IPEndPoint ipe = new IPEndPoint(ipAddress, _port);
+
+ _socket.Connect(ipe);
+ _networkStream = new NetworkStream(_socket, true);
+ }
+
+ public string getLocalEndPoint()
+ {
+ return _socket.LocalEndPoint.ToString();
+ }
+
+ public void Write(ByteBuffer byteBuffer)
+ {
+ try
+ {
+ _networkStream.Write(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit()); // FIXME
+ }
+ catch (Exception e)
+ {
+ _log.Error("Write caused exception", e);
+ _protocolListener.OnException(e);
+ // We should provide the error synchronously as we are doing blocking io.
+ throw e;
+ }
+ }
+
+ public ByteBuffer Read()
+ {
+ const int bufferSize = 4 * 1024; // TODO: Prevent constant allocation of buffers.
+ byte[] bytes = new byte[bufferSize];
+
+ int numOctets = _networkStream.Read(bytes, 0, bytes.Length);
+
+ /// Read only returns 0 if the socket has been gracefully shutdown.
+ /// http://msdn2.microsoft.com/en-us/library/system.net.sockets.networkstream.read(VS.71).aspx
+ /// We can use this to block Send so the next Read will force an exception forcing failover.
+ /// Otherwise we need to wait ~20 seconds for the NetworkStream/Socket code to realise that
+ /// the socket has been closed.
+ if (numOctets == 0)
+ {
+ _socket.Shutdown(SocketShutdown.Send);
+ _socket.Close();
+ }
+
+ ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+ byteBuffer.limit(numOctets);
+
+ byteBuffer.flip();
+
+ return byteBuffer;
+ }
+
+ public void Disconnect()
+ {
+ _networkStream.Flush();
+ _networkStream.Close();
+ _socket.Close();
+ }
+
+ public void Close()
+ {
+ Disconnect();
+ }
+
+ public IByteChannel ByteChannel
+ {
+ get { return _byteChannel; }
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketTransport.cs b/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketTransport.cs
new file mode 100644
index 0000000000..17f911fb6d
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/BlockingSocketTransport.cs
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Framing;
+
+namespace Qpid.Client.Transport.Socket.Blocking
+{
+ public class BlockingSocketTransport : ITransport
+ {
+// static readonly ILog _log = LogManager.GetLogger(typeof(BlockingSocketTransport));
+
+ // Configuration variables.
+ string _host;
+ int _port;
+ IProtocolListener _protocolListener;
+
+ // Runtime variables.
+ private BlockingSocketProcessor _socketProcessor;
+ private AmqpChannel _amqpChannel;
+
+ private ReaderRunner _readerRunner;
+ private Thread _readerThread;
+
+ public BlockingSocketTransport(string host, int port, AMQConnection connection)
+ {
+ _host = host;
+ _port = port;
+ _protocolListener = connection.ProtocolListener;
+ }
+
+ public void Open()
+ {
+ _socketProcessor = new BlockingSocketProcessor(_host, _port, _protocolListener);
+ _socketProcessor.Connect();
+ _amqpChannel = new AmqpChannel(_socketProcessor.ByteChannel);
+ _readerRunner = new ReaderRunner(this);
+ _readerThread = new Thread(new ThreadStart(_readerRunner.Run));
+ _readerThread.Start();
+ }
+
+ public string getLocalEndPoint()
+ {
+ return _socketProcessor.getLocalEndPoint();
+ }
+
+ public void Close()
+ {
+ StopReaderThread();
+ _socketProcessor.Disconnect();
+ }
+
+ public IProtocolChannel ProtocolChannel { get { return _amqpChannel; } }
+ public IProtocolWriter ProtocolWriter { get { return _amqpChannel; } }
+
+ public void StopReaderThread()
+ {
+ _readerRunner.Stop();
+ }
+
+ class ReaderRunner
+ {
+ BlockingSocketTransport _transport;
+ bool _running = true;
+
+ public ReaderRunner(BlockingSocketTransport transport)
+ {
+ _transport = transport;
+ }
+
+ public void Run()
+ {
+ try
+ {
+ while (_running)
+ {
+ Queue frames = _transport.ProtocolChannel.Read();
+
+ foreach (IDataBlock dataBlock in frames)
+ {
+ _transport._protocolListener.OnMessage(dataBlock);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _transport._protocolListener.OnException(e);
+ }
+ }
+
+ public void Stop()
+ {
+ // TODO: Check if this is thread safe. running is not volitile....
+ _running = false;
+ }
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/ByteChannel.cs b/dotnet/Qpid.Client.Transport.Socket.Blocking/ByteChannel.cs
new file mode 100644
index 0000000000..5f67e99838
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/ByteChannel.cs
@@ -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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ class ByteChannel : IByteChannel
+ {
+ // Warning: don't use this log for regular logging.
+ private static readonly ILog _ioTraceLog = LogManager.GetLogger("TRACE.Qpid.Client.ByteChannel");
+
+ BlockingSocketProcessor processor;
+
+ public ByteChannel(BlockingSocketProcessor processor)
+ {
+ this.processor = processor;
+ }
+
+ public ByteBuffer Read()
+ {
+ ByteBuffer result = processor.Read();
+
+ // TODO: Move into decorator.
+ if (_ioTraceLog.IsDebugEnabled)
+ {
+ _ioTraceLog.Debug(String.Format("READ {0}", result));
+ }
+
+ return result;
+ }
+
+ public void Write(ByteBuffer buffer)
+ {
+ // TODO: Move into decorator.
+ if (_ioTraceLog.IsDebugEnabled)
+ {
+ _ioTraceLog.Debug(String.Format("WRITE {0}", buffer));
+ }
+
+ processor.Write(buffer);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/Properties/AssemblyInfo.cs b/dotnet/Qpid.Client.Transport.Socket.Blocking/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..19599b0833
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Transport.Blocking")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Transport.Blocking")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ca23e89c-f5b9-4f7a-929a-4fae00ef055b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.csproj b/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.csproj
new file mode 100644
index 0000000000..6a0b1cd8e6
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.csproj
@@ -0,0 +1,92 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{52AC4940-2077-4104-A753-29A9C8C16957}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Client.Transport.Socket.Blocking</RootNamespace>
+ <AssemblyName>Apache.Qpid.Client.Transport.Socket.Blocking</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.0.30714, Culture=neutral, PublicKeyToken=500ffcafb14f92df">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Common\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BlockingSocketProcessor.cs" />
+ <Compile Include="BlockingSocketTransport.cs" />
+ <Compile Include="ByteChannel.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.mdp b/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.mdp
new file mode 100644
index 0000000000..54c3be76e5
--- /dev/null
+++ b/dotnet/Qpid.Client.Transport.Socket.Blocking/Qpid.Client.Transport.Socket.Blocking.mdp
@@ -0,0 +1,50 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<Project name="Qpid.Client.Transport.Socket.Blocking" fileversion="2.0" language="C#" clr-version="Net_1_1" ctype="DotNetProject">
+ <Configurations active="Debug">
+ <Configuration name="Debug" ctype="DotNetProjectConfiguration">
+ <Output directory="./bin/Debug" assembly="Qpid.Client.Transport.Socket.Blocking" />
+ <Build debugmode="True" target="Library" />
+ <Execution runwithwarnings="True" consolepause="False" runtime="MsNet" clr-version="Net_1_1" />
+ <CodeGeneration compiler="Csc" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+ </Configuration>
+ <Configuration name="Release" ctype="DotNetProjectConfiguration">
+ <Output directory="./bin/Release" assembly="Qpid.Client.Transport.Socket.Blocking" />
+ <Build debugmode="False" target="Library" />
+ <Execution runwithwarnings="True" consolepause="False" runtime="MsNet" clr-version="Net_1_1" />
+ <CodeGeneration compiler="Csc" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+ </Configuration>
+ </Configurations>
+ <DeployTargets />
+ <Contents>
+ <File name="./Properties/AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
+ <File name="./BlockingSocketProcessor.cs" subtype="Code" buildaction="Compile" />
+ <File name="./BlockingSocketTransport.cs" subtype="Code" buildaction="Compile" />
+ <File name="./ByteChannel.cs" subtype="Code" buildaction="Compile" />
+ </Contents>
+ <References>
+ <ProjectReference type="Gac" localcopy="True" refto="System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <ProjectReference type="Assembly" localcopy="True" refto="../Qpid.Common/lib/log4net/log4net.dll" />
+ <ProjectReference type="Project" localcopy="True" refto="Qpid.Buffer" />
+ <ProjectReference type="Project" localcopy="True" refto="Qpid.Client" />
+ <ProjectReference type="Project" localcopy="True" refto="Qpid.Common" />
+ </References>
+</Project> \ No newline at end of file
diff --git a/dotnet/Qpid.Client/Client/AMQAuthenticationException.cs b/dotnet/Qpid.Client/Client/AMQAuthenticationException.cs
new file mode 100644
index 0000000000..7bb64e3fff
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQAuthenticationException.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Client
+{
+ [Serializable]
+ public class AMQAuthenticationException : AMQException
+ {
+ public AMQAuthenticationException(int error, String message)
+ : base(error, message)
+ {
+ }
+
+ protected AMQAuthenticationException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AMQConnection.cs b/dotnet/Qpid.Client/Client/AMQConnection.cs
new file mode 100644
index 0000000000..41d4e089b6
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQConnection.cs
@@ -0,0 +1,873 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Failover;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Client.Transport;
+using Apache.Qpid.Client.Transport.Socket.Blocking;
+using Apache.Qpid.Collections;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client
+{
+ public class AMQConnection : Closeable, IConnection
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(AMQConnection));
+
+ IConnectionInfo _connectionInfo;
+ private int _nextChannelId = 0;
+
+ // _Connected should be refactored with a suitable wait object.
+ private bool _connected;
+
+ Thread _heartBeatThread;
+ HeartBeatThread _heartBeatRunner;
+
+ // The last error code that occured on the connection. Used to return the correct exception to the client
+ private AMQException _lastAMQException = null;
+
+ /**
+ * This is the "root" mutex that must be held when doing anything that could be impacted by failover.
+ * This must be held by any child objects of this connection such as the session, producers and consumers.
+ */
+ private readonly Object _failoverMutex = new Object();
+ public object FailoverMutex
+ {
+ get { return _failoverMutex; }
+ }
+
+ /**
+ * Policy dictating how to failover
+ */
+ private FailoverPolicy _failoverPolicy;
+
+ internal bool IsFailoverAllowed
+ {
+ get { if(!_connected) return false; else return _failoverPolicy.FailoverAllowed(); }
+ }
+
+ /// <summary>
+ /// A channel is roughly analogous to a session. The server can negotiate the maximum number of channels
+ /// per session and we must prevent the client from opening too many. Zero means unlimited.
+ /// </summary>
+ private ushort _maximumChannelCount;
+
+ /// <summary>
+ /// The maximum size of frame supported by the server
+ /// </summary>
+ private uint _maximumFrameSize;
+
+ private AMQStateManager _stateManager;
+
+ private AMQProtocolSession _protocolSession;
+ public AMQProtocolSession ProtocolSession { get { return _protocolSession; } }
+
+ /// <summary>
+ /// Maps from session id (Integer) to AmqChannel instance
+ /// </summary>
+ private readonly IDictionary _sessions = new LinkedHashtable();
+
+ private ExceptionListenerDelegate _exceptionListener;
+
+ private IConnectionListener _connectionListener;
+
+ private ITransport _transport;
+ public ITransport Transport { get { return _transport; } }
+
+ /// <summary>
+ /// Whether this connection is started, i.e. whether messages are flowing to consumers. It has no meaning for
+ /// message publication.
+ /// </summary>
+ private bool _started;
+
+ private AMQProtocolListener _protocolListener;
+ public AMQProtocolListener ProtocolListener { get { return _protocolListener; } }
+
+ public IProtocolWriter ProtocolWriter
+ {
+ get { return _transport.ProtocolWriter; }
+ }
+
+ ProtocolWriter _protocolWriter;
+
+ public ProtocolWriter ConvenientProtocolWriter
+ {
+ get { return _protocolWriter; }
+ }
+
+ public AMQConnection(IConnectionInfo connectionInfo)
+ {
+ if (connectionInfo == null)
+ {
+ throw new ArgumentException("ConnectionInfo must be specified");
+ }
+ _log.Debug("ConnectionInfo: " + connectionInfo);
+ _connectionInfo = connectionInfo;
+ _log.Debug("password = " + _connectionInfo.Password);
+ _failoverPolicy = new FailoverPolicy(connectionInfo);
+
+ // We are not currently connected.
+ _connected = false;
+
+ Exception lastException = null;
+ do
+ {
+ try
+ {
+ IBrokerInfo brokerInfo = _failoverPolicy.GetNextBrokerInfo();
+ _log.Debug("Connecting to " + brokerInfo);
+ MakeBrokerConnection(brokerInfo);
+ break;
+ }
+ catch (Exception e)
+ {
+ lastException = e;
+ _log.Error("Unable to connect to broker " + _failoverPolicy.GetCurrentBrokerInfo(), e);
+ // XXX: Should perhaps break out of the do/while here if not a SocketException...
+ }
+ } while (!_connected && _failoverPolicy.FailoverAllowed());
+
+ _log.Debug("Are we connected:" + _connected);
+
+ if (!_connected)
+ {
+ if ( lastException is AMQException )
+ {
+ throw lastException;
+ }
+ else
+ {
+ throw new AMQConnectionException("Unable to connect", lastException);
+ }
+ }
+
+ }
+
+ /*private ITransport LoadTransportFromAssembly(string host, int port, String assemblyName, String transportType)
+ {
+ //Assembly assembly = Assembly.LoadFrom(assemblyName);
+ Assembly assembly = Assembly.Load(assemblyName);
+
+ foreach (Type type in assembly.GetTypes())
+ {
+ _log.Debug(String.Format("type = {0}", type));
+ }
+
+ Type transport = assembly.GetType(transportType);
+
+ if (transport == null)
+ {
+ throw new ArgumentException(
+ String.Format("Type is not found in assembly. Type={0} Assembly={1}", transportType, assemblyName));
+
+ }
+
+ _log.Debug("transport = " + transport);
+ _log.Debug("ctors = " + transport.GetConstructors());
+
+ ConstructorInfo info = transport.GetConstructors()[0];
+ ITransport result = (ITransport)info.Invoke(new object[] { host, port, this });
+
+ _log.Debug("transport = " + result);
+
+ return result;
+ }*/
+
+ public void Disconnect()
+ {
+ _transport.Close();
+ }
+
+ #region IConnection Members
+
+ public string ClientID
+ {
+ get
+ {
+ CheckNotClosed();
+ return _connectionInfo.ClientName;
+ }
+ set
+ {
+ CheckNotClosed();
+ _connectionInfo.ClientName = value;
+ }
+ }
+
+ public override void Close()
+ {
+ lock (FailoverMutex)
+ {
+ // atomically set to closed and check the _previous value was NOT CLOSED
+ if (Interlocked.Exchange(ref _closed, CLOSED) == NOT_CLOSED)
+ {
+ try
+ {
+ CloseAllSessions(null);
+ CloseConnection();
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Error closing connection: " + e);
+ }
+ }
+ }
+ }
+
+ private void CloseConnection()
+ {
+ _stateManager.ChangeState(AMQState.CONNECTION_CLOSING);
+
+ AMQFrame frame = ConnectionCloseBody.CreateAMQFrame(
+ 0, 200, "Qpid.NET client is closing the connection.", 0, 0);
+
+ ProtocolWriter.Write(frame);
+
+ _log.Debug("Blocking for connection close ok frame");
+
+ Disconnect();
+ }
+
+ class CreateChannelFailoverSupport : FailoverSupport
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(CreateChannelFailoverSupport));
+
+ private bool _transacted;
+ private AcknowledgeMode _acknowledgeMode;
+ int _prefetchHigh;
+ int _prefetchLow;
+ AMQConnection _connection;
+
+ public CreateChannelFailoverSupport(AMQConnection connection, bool transacted, AcknowledgeMode acknowledgeMode, int prefetchHigh, int prefetchLow)
+ {
+ _connection = connection;
+ _transacted = transacted;
+ _acknowledgeMode = acknowledgeMode;
+ _prefetchHigh = prefetchHigh;
+ _prefetchLow = prefetchLow;
+ }
+
+ protected override object operation()
+ {
+ ushort channelId = _connection.NextChannelId();
+
+ if (_log.IsDebugEnabled)
+ {
+ _log.Debug("Write channel open frame for channel id " + channelId);
+ }
+
+ // We must create the channel and register it before actually sending the frame to the server to
+ // open it, so that there is no window where we could receive data on the channel and not be set
+ // up to handle it appropriately.
+ AmqChannel channel = new AmqChannel(_connection,
+ channelId, _transacted, _acknowledgeMode, _prefetchHigh, _prefetchLow);
+ _connection.ProtocolSession.AddSessionByChannel(channelId, channel);
+ _connection.RegisterSession(channelId, channel);
+
+ bool success = false;
+ try
+ {
+ _connection.CreateChannelOverWire(channelId, _prefetchHigh, _prefetchLow, _transacted);
+ success = true;
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Error creating channel: " + e, e);
+ }
+ finally
+ {
+ if (!success) {
+ _connection.ProtocolSession.RemoveSessionByChannel(channelId);
+ _connection.DeregisterSession(channelId);
+ }
+ }
+
+ if (_connection._started)
+ {
+ channel.Start();
+ }
+ return channel;
+ }
+ }
+
+ internal ushort NextChannelId()
+ {
+ return (ushort) Interlocked.Increment(ref _nextChannelId);
+ }
+
+ public IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode)
+ {
+ return CreateChannel(transacted, acknowledgeMode, AmqChannel.DEFAULT_PREFETCH_HIGH_MARK);
+ }
+
+ public IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode, int prefetch)
+ {
+ return CreateChannel(transacted, acknowledgeMode, prefetch, prefetch);
+ }
+
+ public IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode, int prefetchHigh, int prefetchLow)
+ {
+ CheckNotClosed();
+ if (ChannelLimitReached())
+ {
+ throw new ChannelLimitReachedException(_maximumChannelCount);
+ }
+ else
+ {
+ CreateChannelFailoverSupport operation =
+ new CreateChannelFailoverSupport(this, transacted, acknowledgeMode, prefetchHigh, prefetchLow);
+ return (IChannel)operation.execute(this);
+ }
+ }
+
+ public void CloseSession(AmqChannel channel)
+ {
+ // FIXME: Don't we need FailoverSupport here (as we have SyncWrite).
+ _protocolSession.CloseSession(channel);
+
+ AMQFrame frame = ChannelCloseBody.CreateAMQFrame(
+ channel.ChannelId, 200, "JMS client closing channel", 0, 0);
+
+ _log.Debug("Blocking for channel close frame for channel " + channel.ChannelId);
+ _protocolWriter.SyncWrite(frame, typeof(ChannelCloseOkBody));
+ _log.Debug("Received channel close frame");
+ // When control resumes at this point, a reply will have been received that
+ // indicates the broker has closed the channel successfully
+ }
+
+ public ExceptionListenerDelegate ExceptionListener
+ {
+ get
+ {
+ CheckNotClosed();
+ return _exceptionListener;
+ }
+ set
+ {
+ CheckNotClosed();
+ _exceptionListener = value;
+ }
+ }
+
+ /// <summary>
+ /// Start the connection, i.e. start flowing messages. Note that this method must be called only from a single thread
+ /// and is not thread safe (which is legal according to the JMS specification).
+ /// @throws JMSException
+ /// </summary>
+ public void Start()
+ {
+ CheckNotClosed();
+
+ if (!_started)
+ {
+ foreach (DictionaryEntry lde in _sessions)
+ {
+ AmqChannel s = (AmqChannel)lde.Value;
+ s.Start();
+ }
+ _started = true;
+ }
+ }
+
+ public void Stop()
+ {
+ CheckNotClosed();
+
+ if (_started)
+ {
+ foreach (DictionaryEntry lde in _sessions)
+ {
+ AmqChannel s = (AmqChannel) lde.Value;
+ s.Stop();
+ }
+ _started = false;
+ }
+ }
+
+ public IConnectionListener ConnectionListener
+ {
+ get { return _connectionListener; }
+ set { _connectionListener = value; }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+
+ private bool ChannelLimitReached()
+ {
+ return _maximumChannelCount != 0 && _sessions.Count == _maximumChannelCount;
+ }
+
+ /// <summary>
+ /// Close all the sessions, either due to normal connection closure or due to an error occurring.
+ /// @param cause if not null, the error that is causing this shutdown
+ /// </summary>
+ private void CloseAllSessions(Exception cause)
+ {
+ _log.Debug("Closing all session in connection " + this);
+ ICollection sessions = new ArrayList(_sessions.Values);
+ foreach (AmqChannel channel in sessions)
+ {
+ _log.Debug("Closing channel " + channel);
+ if (cause != null)
+ {
+ channel.ClosedWithException(cause);
+ }
+ else
+ {
+ try
+ {
+ channel.Close();
+ }
+ catch (QpidException e)
+ {
+ _log.Error("Error closing channel: " + e);
+ }
+ }
+ }
+ _log.Debug("Done closing all sessions in connection " + this);
+ }
+
+ public int MaximumChannelCount
+ {
+ get
+ {
+ CheckNotClosed();
+ return _maximumChannelCount;
+ }
+ }
+
+ internal void SetMaximumChannelCount(ushort maximumChannelCount)
+ {
+ CheckNotClosed();
+ _maximumChannelCount = maximumChannelCount;
+ }
+
+ public uint MaximumFrameSize
+ {
+ get
+ {
+ return _maximumFrameSize;
+ }
+
+ set
+ {
+ _maximumFrameSize = value;
+ }
+ }
+
+ public IDictionary Sessions
+ {
+ get
+ {
+ return _sessions;
+ }
+ }
+
+ public string Host
+ {
+ get
+ {
+ return _failoverPolicy.GetCurrentBrokerInfo().Host;
+ }
+ }
+
+ public int Port
+ {
+ get
+ {
+ return _failoverPolicy.GetCurrentBrokerInfo().Port;
+ }
+ }
+
+ public string Username
+ {
+ get
+ {
+ return _connectionInfo.Username;
+ }
+ }
+
+ public string Password
+ {
+ get
+ {
+ return _connectionInfo.Password;
+ }
+ }
+
+ public string VirtualHost
+ {
+ get
+ {
+ return _connectionInfo.VirtualHost;
+ }
+ }
+
+ /// <summary>
+ /// Invoked by the AMQProtocolSession when a protocol session exception has occurred.
+ /// This method sends the exception to a JMS exception listener, if configured, and
+ /// propagates the exception to sessions, which in turn will propagate to consumers.
+ /// This allows synchronous consumers to have exceptions thrown to them.
+ /// </summary>
+ /// <param name="cause">the exception</param>
+ public void ExceptionReceived(Exception cause)
+ {
+ if (_exceptionListener != null)
+ {
+ // Listener expects one of these...
+ QpidException xe;
+
+ if (cause is QpidException)
+ {
+ xe = (QpidException) cause;
+ }
+ else
+ {
+ xe = new QpidException("Exception thrown against " + ToString() + ": " + cause, cause);
+ }
+ // in the case of an IOException, MINA has closed the protocol session so we set _closed to true
+ // so that any generic client code that tries to close the connection will not mess up this error
+ // handling sequence
+ if (cause is IOException)
+ {
+ Interlocked.Exchange(ref _closed, CLOSED);
+ }
+#if __MonoCS__
+ _exceptionListener(xe);
+#else
+ _exceptionListener.Invoke(xe);
+#endif
+ }
+ else
+ {
+ _log.Error("Connection exception: " + cause);
+ }
+
+ // An undelivered is not fatal to the connections usability.
+ if (!(cause is AMQUndeliveredException))
+ {
+ Interlocked.Exchange(ref _closed, CLOSED);
+ CloseAllSessions(cause);
+ }
+ else
+ {
+ ;
+ }
+ }
+
+ internal void RegisterSession(int channelId, AmqChannel channel)
+ {
+ _sessions[channelId] = channel;
+ }
+
+ internal void DeregisterSession(int channelId)
+ {
+ _sessions.Remove(channelId);
+ }
+
+ /**
+ * Fire the preFailover event to the registered connection listener (if any)
+ *
+ * @param redirect true if this is the result of a redirect request rather than a connection error
+ * @return true if no listener or listener does not veto change
+ */
+ public bool FirePreFailover(bool redirect)
+ {
+ bool proceed = true;
+ if (_connectionListener != null)
+ {
+ proceed = _connectionListener.PreFailover(redirect);
+ }
+ return proceed;
+ }
+
+ /**
+ * Fire the preResubscribe event to the registered connection listener (if any). If the listener
+ * vetoes resubscription then all the sessions are closed.
+ *
+ * @return true if no listener or listener does not veto resubscription.
+ * @throws JMSException
+ */
+ public bool FirePreResubscribe()
+ {
+ if (_connectionListener != null)
+ {
+ bool resubscribe = _connectionListener.PreResubscribe();
+ if (!resubscribe)
+ {
+ MarkAllSessionsClosed();
+ }
+ return resubscribe;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ /**
+ * Marks all sessions and their children as closed without sending any protocol messages. Useful when
+ * you need to mark objects "visible" in userland as closed after failover or other significant event that
+ * impacts the connection.
+ * <p/>
+ * The caller must hold the failover mutex before calling this method.
+ */
+ private void MarkAllSessionsClosed()
+ {
+ //LinkedList sessionCopy = new LinkedList(_sessions.values());
+ ArrayList sessionCopy = new ArrayList(_sessions.Values);
+ foreach (AmqChannel session in sessionCopy)
+ {
+ session.MarkClosed();
+ }
+ _sessions.Clear();
+ }
+
+ /**
+ * Fires a failover complete event to the registered connection listener (if any).
+ */
+ public void FireFailoverComplete()
+ {
+ if (_connectionListener != null)
+ {
+ _connectionListener.FailoverComplete();
+ }
+ }
+
+ public bool AttemptReconnection(String host, int port, SslOptions sslConfig)
+ {
+ IBrokerInfo bd = new AmqBrokerInfo("amqp", host, port, sslConfig);
+
+ _failoverPolicy.setBroker(bd);
+
+ try
+ {
+ MakeBrokerConnection(bd);
+ return true;
+ }
+ catch (Exception e)
+ {
+ _log.Debug("Unable to connect to broker at " + bd, e);
+ AttemptReconnection();
+ }
+ return false;
+ }
+
+ private void MakeBrokerConnection(IBrokerInfo brokerDetail)
+ {
+ try
+ {
+ _stateManager = new AMQStateManager();
+ _protocolListener = new AMQProtocolListener(this, _stateManager);
+ _protocolListener.AddFrameListener(_stateManager);
+
+ /*
+ // Currently there is only one transport option - BlockingSocket.
+ String assemblyName = "Apache.Qpid.Client.Transport.Socket.Blocking.dll";
+ String transportType = "Apache.Qpid.Client.Transport.Socket.Blocking.BlockingSocketTransport";
+
+ // Load the transport assembly dynamically.
+ _transport = LoadTransportFromAssembly(brokerDetail.getHost(), brokerDetail.getPort(), assemblyName, transportType);
+ */
+
+ _transport = new BlockingSocketTransport();
+
+ // Connect.
+ _transport.Connect(brokerDetail, this);
+ _protocolWriter = new ProtocolWriter(_transport.ProtocolWriter, _protocolListener);
+ _protocolSession = new AMQProtocolSession(_transport.ProtocolWriter, _transport, this);
+ _protocolListener.ProtocolSession = _protocolSession;
+
+ // Now start the connection "handshake".
+ _transport.ProtocolWriter.Write(new ProtocolInitiation());
+
+ // Blocks until the connection has been opened.
+ _stateManager.AttainState(AMQState.CONNECTION_OPEN);
+
+ _failoverPolicy.attainedConnection();
+
+ // XXX: Again this should be changed to a suitable notify.
+ _connected = true;
+ }
+ catch (AMQException e)
+ {
+ _lastAMQException = e;
+ throw; // rethrow
+ }
+ }
+
+ public bool AttemptReconnection()
+ {
+ while (_failoverPolicy.FailoverAllowed())
+ {
+ try
+ {
+ MakeBrokerConnection(_failoverPolicy.GetNextBrokerInfo());
+ return true;
+ }
+ catch (Exception e)
+ {
+ if (!(e is AMQException))
+ {
+ _log.Debug("Unable to connect to broker at " + _failoverPolicy.GetCurrentBrokerInfo(), e);
+ }
+ else
+ {
+ _log.Debug(e.Message + ":Unable to connect to broker at " + _failoverPolicy.GetCurrentBrokerInfo());
+ }
+ }
+ }
+
+ // Connection unsuccessful.
+ return false;
+ }
+
+ /**
+ * For all channels, and for all consumers in those sessions, resubscribe. This is called during failover handling.
+ * The caller must hold the failover mutex before calling this method.
+ */
+ public void ResubscribeChannels()
+ {
+ ArrayList channels = new ArrayList(_sessions.Values);
+ _log.Debug(String.Format("Resubscribing sessions = {0} sessions.size={1}", channels, channels.Count));
+ foreach (AmqChannel channel in channels)
+ {
+ _protocolSession.AddSessionByChannel(channel.ChannelId, channel);
+ ReopenChannel(
+ channel.ChannelId,
+ channel.DefaultPrefetchHigh,
+ channel.DefaultPrefetchLow,
+ channel.Transacted
+ );
+ channel.ReplayOnFailOver();
+ }
+ }
+
+ private void ReopenChannel(ushort channelId, int prefetchHigh, int prefetchLow, bool transacted)
+ {
+ _log.Debug(string.Format("Reopening channel id={0} prefetchHigh={1} prefetchLow={2} transacted={3}",
+ channelId, prefetchHigh, prefetchLow, transacted));
+ try
+ {
+ CreateChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted);
+ }
+ catch (AMQException e)
+ {
+ _protocolSession.RemoveSessionByChannel(channelId);
+ DeregisterSession(channelId);
+ throw new AMQException("Error reopening channel " + channelId + " after failover: " + e);
+ }
+ }
+
+ void CreateChannelOverWire(ushort channelId, int prefetchHigh, int prefetchLow, bool transacted)
+ {
+ _protocolWriter.SyncWrite(ChannelOpenBody.CreateAMQFrame(channelId, null), typeof (ChannelOpenOkBody));
+
+ // Don't use the BasicQos frame if connecting to OpenAMQ (at it is not support). We
+ // know this when we connection using AMQP 0.7
+ if (ProtocolInitiation.CURRENT_PROTOCOL_VERSION_MAJOR != 7)
+ {
+ // Basic.Qos frame appears to not be supported by OpenAMQ 1.0d.
+ _protocolWriter.SyncWrite(BasicQosBody.CreateAMQFrame(channelId, 0, (ushort)prefetchHigh, false), typeof (BasicQosOkBody));
+ }
+
+ if (transacted)
+ {
+ if (_log.IsDebugEnabled)
+ {
+ _log.Debug("Issuing TxSelect for " + channelId);
+ }
+ _protocolWriter.SyncWrite(TxSelectBody.CreateAMQFrame(channelId), typeof(TxSelectOkBody));
+ }
+ }
+
+ public String toURL()
+ {
+ return _connectionInfo.AsUrl();
+ }
+
+ class HeartBeatThread
+ {
+ int _heartbeatMillis;
+ IProtocolWriter _protocolWriter;
+ bool _run = true;
+
+ public HeartBeatThread(IProtocolWriter protocolWriter, int heartbeatMillis)
+ {
+ _protocolWriter = protocolWriter;
+ _heartbeatMillis = heartbeatMillis;
+ }
+
+ public void Run()
+ {
+ while (_run)
+ {
+ Thread.Sleep(_heartbeatMillis);
+ if (!_run) break;
+ _log.Debug("Sending heartbeat");
+ // TODO: Can we optimise this so that heartbeats are only written when we haven't sent anything recently to the broker?
+ _protocolWriter.Write(HeartbeatBody.FRAME);
+ }
+ _log.Debug("Heatbeat thread stopped");
+ }
+
+ public void Stop()
+ {
+ _run = false;
+ }
+ }
+
+ public void StartHeartBeatThread(int heartbeatSeconds)
+ {
+ _log.Debug("Starting new heartbeat thread");
+ _heartBeatRunner = new HeartBeatThread(ProtocolWriter, heartbeatSeconds * 1000);
+ _heartBeatThread = new Thread(new ThreadStart(_heartBeatRunner.Run));
+ _heartBeatThread.Name = "HeartBeat";
+ _heartBeatThread.Start();
+ }
+
+ public void StopHeartBeatThread()
+ {
+ if (_heartBeatRunner != null)
+ {
+ _log.Debug("Stopping old heartbeat thread");
+ _heartBeatRunner.Stop();
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AMQConnectionException.cs b/dotnet/Qpid.Client/Client/AMQConnectionException.cs
new file mode 100644
index 0000000000..c8a48814bb
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQConnectionException.cs
@@ -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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Client
+{
+ [Serializable]
+ public class AMQConnectionException : AMQException
+ {
+ public AMQConnectionException(String message, Exception e) : base(message, e)
+ {
+ }
+
+ protected AMQConnectionException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AMQDestination.cs b/dotnet/Qpid.Client/Client/AMQDestination.cs
new file mode 100644
index 0000000000..07ce3c2354
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQDestination.cs
@@ -0,0 +1,234 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client
+{
+ public abstract class AMQDestination
+ {
+ protected readonly string _exchangeName;
+ protected readonly string _exchangeClass;
+ protected readonly string _destinationName;
+ protected readonly bool _isExclusive;
+ protected readonly bool _isAutoDelete;
+ protected bool _isDurable;
+
+ public bool IsDurable
+ {
+
+ get { return _isDurable; }
+ }
+
+ protected string _queueName;
+
+ protected AMQDestination(String exchangeName, String exchangeClass, String destinationName, bool isExclusive,
+ bool isAutoDelete, String queueName)
+ {
+ // XXX: This is ugly - OnlyRequired because of ReplyToDestination.
+// if (destinationName == null)
+// {
+// throw new ArgumentNullException("destinationName");
+// }
+
+ // XXX: This is ugly - OnlyRequired because of SendingDestinationAdapter.
+// if (exchangeName == null)
+// {
+// throw new ArgumentNullException("exchangeName");
+// }
+
+ // XXX: This is ugly - OnlyRequired because of SendingDestinationAdapter.
+// if (exchangeClass == null)
+// {
+// throw new ArgumentNullException("exchangeClass");
+// }
+
+ _exchangeName = exchangeName;
+ _exchangeClass = exchangeClass;
+ _destinationName = destinationName;
+ _isExclusive = isExclusive;
+ _isAutoDelete = isAutoDelete;
+ _queueName = queueName;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return _destinationName;
+ }
+ }
+
+ public abstract string RoutingKey
+ {
+ get;
+ }
+
+ public abstract string EncodedName
+ {
+ get;
+ }
+
+ public bool AutoDelete
+ {
+ get
+ {
+ return _isAutoDelete;
+ }
+ }
+
+ public string QueueName
+ {
+ get
+ {
+ return _queueName;
+ }
+ set
+ {
+ _queueName = value;
+ }
+ }
+
+ public string ExchangeName
+ {
+ get
+ {
+ return _exchangeName;
+ }
+ }
+
+ public string ExchangeClass
+ {
+ get
+ {
+ return _exchangeClass;
+ }
+ }
+
+ public bool IsExclusive
+ {
+ get
+ {
+ return _isExclusive;
+ }
+ }
+
+ public bool IsAutoDelete
+ {
+ get
+ {
+ return _isAutoDelete;
+ }
+ }
+
+ public override string ToString()
+ {
+ return "Destination: " + _destinationName + ", " +
+ "Queue Name: " + _queueName + ", Exchange: " + _exchangeName +
+ ", Exchange class: " + _exchangeClass + ", Exclusive: " + _isExclusive +
+ ", AutoDelete: " + _isAutoDelete; // +", Routing Key: " + RoutingKey;
+ }
+
+ public override bool Equals(object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || GetType() != o.GetType())
+ {
+ return false;
+ }
+
+ AMQDestination that = (AMQDestination) o;
+
+ if (!StringsNotEqualNullSafe(_destinationName, that._destinationName))
+ {
+ return false;
+ }
+ if (!StringsNotEqualNullSafe(_exchangeClass, that._exchangeClass))
+ {
+ return false;
+ }
+ if (!StringsNotEqualNullSafe(_exchangeName, that._exchangeName))
+ {
+ return false;
+ }
+ if (!StringsNotEqualNullSafe(_queueName, that._queueName))
+ {
+ return false;
+ }
+ if (_isExclusive != that._isExclusive)
+ {
+ return false;
+ }
+ if (_isAutoDelete != that._isAutoDelete)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private bool StringsNotEqualNullSafe(string one, string two)
+ {
+ if ((one == null && two != null) ||
+ (one != null && !one.Equals(two)))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ int result;
+ if (_exchangeName == null)
+ {
+ result = "".GetHashCode();
+ }
+ else
+ {
+ result = _exchangeName.GetHashCode();
+ }
+ if (_exchangeClass != null)
+ {
+ result = 29 * result + _exchangeClass.GetHashCode();
+ }
+ if (_destinationName != null)
+ {
+ result = 29 * result + _destinationName.GetHashCode();
+ }
+ if (_queueName != null)
+ {
+ result = 29 * result + _queueName.GetHashCode();
+ }
+ result = result * (_isExclusive ? 13 : 7);
+ result = result * (_isAutoDelete ? 13 : 7);
+
+ Console.WriteLine("FIXME HashCode for " + this + " = " + result);
+ return result;
+ }
+
+ public abstract bool IsNameRequired { get; }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AMQNoConsumersException.cs b/dotnet/Qpid.Client/Client/AMQNoConsumersException.cs
new file mode 100644
index 0000000000..5c9dd86c53
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQNoConsumersException.cs
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using Apache.Qpid.Common;
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid.Client
+{
+ [Serializable]
+ public class AMQNoConsumersException : AMQUndeliveredException
+ {
+ public AMQNoConsumersException(string message)
+ : this(message, null)
+ {
+ }
+
+ public AMQNoConsumersException(string message, object bounced)
+ : base(AMQConstant.NO_CONSUMERS.Code, message, bounced)
+ {
+ }
+ protected AMQNoConsumersException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AMQNoRouteException.cs b/dotnet/Qpid.Client/Client/AMQNoRouteException.cs
new file mode 100644
index 0000000000..5868d78f32
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AMQNoRouteException.cs
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using Apache.Qpid.Common;
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid.Client
+{
+ [Serializable]
+ public class AMQNoRouteException : AMQUndeliveredException
+ {
+ public AMQNoRouteException(string message)
+ : this(message, null)
+ {
+ }
+
+ public AMQNoRouteException(string message, object bounced)
+ : base(AMQConstant.NO_ROUTE.Code, message, bounced)
+ {
+ }
+
+ protected AMQNoRouteException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AmqBrokerInfo.cs b/dotnet/Qpid.Client/Client/AmqBrokerInfo.cs
new file mode 100644
index 0000000000..591c5b941f
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AmqBrokerInfo.cs
@@ -0,0 +1,322 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client
+{
+ public class AmqBrokerInfo : IBrokerInfo
+ {
+ public readonly string URL_FORMAT_EXAMPLE =
+ "<transport>://<hostname>[:<port Default=\""+BrokerInfoConstants.DEFAULT_PORT+"\">][?<option>='<value>'[,<option>='<value>']]";
+
+ public const long DEFAULT_CONNECT_TIMEOUT = 30000L;
+
+ private string _host = "localhost";
+ private int _port = 5672;
+ private string _transport = "amqp";
+ private Hashtable _options = new Hashtable();
+ private SslOptions _sslOptions;
+
+ public AmqBrokerInfo()
+ {
+ }
+
+ public AmqBrokerInfo(string url)
+ {
+ // URL should be of format tcp://host:port?option='value',option='value'
+ try
+ {
+ Uri connection = new Uri(url);
+
+ String transport = connection.Scheme;
+
+ // Handles some defaults to minimise changes to existing broker URLS e.g. localhost
+ if (transport != null)
+ {
+ transport = transport.ToLower();
+ //todo this list of valid transports should be enumerated somewhere
+ if ((!(transport.Equals("vm") || transport.Equals("tcp"))))
+ {
+ if (transport.Equals("localhost"))
+ {
+ connection = new Uri(BrokerInfoConstants.DEFAULT_TRANSPORT + "://" + url);
+ transport = connection.Scheme;
+ }
+ else
+ {
+ if (url[transport.Length] == ':' && url[transport.Length + 1] != '/')
+ {
+ //Then most likely we have a host:port value
+ connection = new Uri(BrokerInfoConstants.DEFAULT_TRANSPORT + "://" + url);
+ transport = connection.Scheme;
+ }
+ else
+ {
+ URLHelper.parseError(0, transport.Length, "Unknown transport", url);
+ }
+ }
+ }
+ }
+ else
+ {
+ //Default the transport
+ connection = new Uri(BrokerInfoConstants.DEFAULT_TRANSPORT + "://" + url);
+ transport = connection.Scheme;
+ }
+
+ if (transport == null)
+ {
+ URLHelper.parseError(-1, "Unknown transport:'" + transport + "'" +
+ " In broker URL:'" + url + "' Format: " + URL_FORMAT_EXAMPLE, "");
+ }
+
+ Transport = transport;
+
+ String host = connection.Host;
+ if (!host.Equals("default")) Host = host;
+
+ int port = connection.Port;
+
+ if (port == -1)
+ {
+ // Fix for when there is port data but it is not automatically parseable by getPort().
+ String auth = connection.Authority;
+
+ if (auth != null && auth.IndexOf(':') != -1)
+ {
+ int start = auth.IndexOf(":") + 1;
+ int end = start;
+ bool looking = true;
+ bool found = false;
+ //Walk the authority looking for a port value.
+ while (looking)
+ {
+ try
+ {
+ end++;
+ int.Parse(auth.Substring(start, end-start+1));
+
+ if (end >= auth.Length)
+ {
+ looking = false;
+ found = true;
+ }
+ }
+ catch (FormatException)
+ {
+ looking = false;
+ }
+
+ }
+ if (found)
+ {
+ Port = int.Parse(auth.Substring(start, end-start+1));
+ }
+ else
+ {
+ URLHelper.parseError(connection.ToString().IndexOf(connection.Authority) + end - 1,
+ "Illegal character in port number", connection.ToString());
+ }
+ }
+ else
+ {
+ Port = BrokerInfoConstants.DEFAULT_PORT;
+ }
+ }
+ else
+ {
+ Port = port;
+ }
+
+ String queryString = connection.Query;
+ if (queryString.Length > 0 && queryString[0] == '?')
+ {
+ queryString = queryString.Substring(1);
+ }
+
+ URLHelper.parseOptions(_options, queryString);
+
+ //Fragment is #string (not used)
+ }
+ catch (UriFormatException uris)
+ {
+ throw uris;
+// if (uris is UrlSyntaxException)
+// {
+// throw uris;
+// }
+//
+// URLHelper.parseError(uris.getIndex(), uris.getReason(), uris.getInput());
+ }
+ }
+
+ public AmqBrokerInfo(string transport, string host, int port, bool useSSL) : this()
+ {
+ _transport = transport;
+ _host = host;
+ _port = port;
+
+ if (useSSL)
+ {
+ SetOption(BrokerInfoConstants.OPTIONS_SSL, "true");
+ }
+ }
+
+ public AmqBrokerInfo(string transport, string host, int port, SslOptions sslConfig)
+ : this()
+ {
+ _transport = transport;
+ _host = host;
+ _port = port;
+
+ if ( sslConfig != null )
+ {
+ SetOption(BrokerInfoConstants.OPTIONS_SSL, "true");
+ _sslOptions = sslConfig;
+ }
+ }
+
+
+ public string Host
+ {
+ get { return _host; }
+ set { _host = value; }
+ }
+
+ public int Port
+ {
+ get { return _port; }
+ set { _port = value; }
+ }
+
+ public string Transport
+ {
+ get { return _transport; }
+ set { _transport = value; }
+ }
+
+ public SslOptions SslOptions
+ {
+ get { return _sslOptions; }
+ }
+
+ public string GetOption(string key)
+ {
+ return (string)_options[key];
+ }
+
+ public void SetOption(string key, string value)
+ {
+ _options[key] = value;
+ }
+
+ public long Timeout
+ {
+ get
+ {
+ if ( _options.ContainsKey(BrokerInfoConstants.OPTIONS_CONNECT_TIMEOUT) )
+ {
+ try
+ {
+ return long.Parse(GetOption(BrokerInfoConstants.OPTIONS_CONNECT_TIMEOUT));
+ } catch ( FormatException )
+ {
+ //Do nothing as we will use the default below.
+ }
+ }
+ return BrokerInfoConstants.DEFAULT_CONNECT_TIMEOUT;
+ }
+ set
+ {
+ SetOption(BrokerInfoConstants.OPTIONS_CONNECT_TIMEOUT, value.ToString());
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append(_transport);
+ sb.Append("://");
+
+ if (!(StringEqualsIgnoreCase(_transport, "vm")))
+ {
+ sb.Append(_host);
+ }
+
+ sb.Append(':');
+ sb.Append(_port);
+
+ sb.Append(URLHelper.printOptions(_options));
+
+ return sb.ToString();
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is IBrokerInfo))
+ {
+ return false;
+ }
+
+ IBrokerInfo bd = (IBrokerInfo) obj;
+ return StringEqualsIgnoreCase(_host, bd.Host) &&
+ _port == bd.Port &&
+ StringEqualsIgnoreCase(_transport, bd.Transport) &&
+ UseSSL == bd.UseSSL;
+ }
+
+ public override int GetHashCode()
+ {
+ return _host.ToLower().GetHashCode() ^ _port.GetHashCode();
+ }
+
+ // TODO: move to util class.
+ private bool StringEqualsIgnoreCase(string one, string two)
+ {
+ return one.ToLower().Equals(two.ToLower());
+ }
+
+ public bool UseSSL
+ {
+ get
+ {
+ // To be friendly to users we should be case insensitive.
+ // or simply force users to conform to OPTIONS_SSL
+ // todo make case insensitive by trying ssl Ssl sSl ssL SSl SsL sSL SSL
+
+ if ( _options.ContainsKey(BrokerInfoConstants.OPTIONS_SSL) )
+ {
+ return StringEqualsIgnoreCase(GetOption(BrokerInfoConstants.OPTIONS_SSL), "true");
+ }
+
+ return false;
+ }
+ set
+ {
+ SetOption(BrokerInfoConstants.OPTIONS_SSL, value.ToString());
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/AmqChannel.cs b/dotnet/Qpid.Client/Client/AmqChannel.cs
new file mode 100644
index 0000000000..84c7c06fe1
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/AmqChannel.cs
@@ -0,0 +1,1241 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text.RegularExpressions;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Util;
+using Apache.Qpid.Collections;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid.Client
+{
+ /// <summary>
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Declare queues.
+ /// <tr><td> Declare exchanges.
+ /// <tr><td> Bind queues to exchanges.
+ /// <tr><td> Create messages.
+ /// <tr><td> Set up message consumers on the channel.
+ /// <tr><td> Set up message producers on the channel.
+ /// <tr><td> Commit the current transaction.
+ /// <tr><td> Roll-back the current transaction.
+ /// <tr><td> Close the channel.
+ /// </table>
+ /// </summary>
+ public class AmqChannel : Closeable, IChannel
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(AmqChannel));
+
+ internal const int BASIC_CONTENT_TYPE = 60;
+
+ public const int DEFAULT_PREFETCH_HIGH_MARK = 5000;
+
+ public const int DEFAULT_PREFETCH_LOW_MARK = 2500;
+
+ private static int _nextSessionNumber = 0;
+
+ private AMQConnection _connection;
+
+ private int _sessionNumber;
+
+ private bool _suspended;
+
+ private object _suspensionLock = new object();
+
+ // Used in the consume method. We generate the consume tag on the client so that we can use the nowait feature.
+ private int _nextConsumerNumber = 1;
+
+ private bool _transacted;
+
+ private AcknowledgeMode _acknowledgeMode;
+
+ private ushort _channelId;
+
+ private int _defaultPrefetchHighMark = DEFAULT_PREFETCH_HIGH_MARK;
+
+ private int _defaultPrefetchLowMark = DEFAULT_PREFETCH_LOW_MARK;
+
+ private FlowControlQueue _queue;
+
+ private Dispatcher _dispatcher;
+
+ private MessageFactoryRegistry _messageFactoryRegistry;
+
+ /// <summary> Holds all of the producers created by this channel. </summary>
+ private Hashtable _producers = Hashtable.Synchronized(new Hashtable());
+
+ /// <summary> Holds all of the consumers created by this channel. </summary>
+ private Hashtable _consumers = Hashtable.Synchronized(new Hashtable());
+
+ private ArrayList _replayFrames = new ArrayList();
+
+ /// <summary>
+ /// The counter of the _next producer id. This id is generated by the session and used only to allow the
+ /// producer to identify itself to the session when deregistering itself.
+ ///
+ /// Access to this id does not require to be synchronized since according to the JMS specification only one
+ /// thread of control is allowed to create producers for any given session instance.
+ /// </summary>
+ private long _nextProducerId;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AmqChannel"/> class.
+ /// </summary>
+ /// <param name="con">The connection.</param>
+ /// <param name="channelId">The channel id.</param>
+ /// <param name="transacted">if set to <c>true</c> [transacted].</param>
+ /// <param name="acknowledgeMode">The acknowledge mode.</param>
+ /// <param name="defaultPrefetchHigh">Default prefetch high value</param>
+ /// <param name="defaultPrefetchLow">Default prefetch low value</param>
+ internal AmqChannel(AMQConnection con, ushort channelId, bool transacted, AcknowledgeMode acknowledgeMode,
+ int defaultPrefetchHigh, int defaultPrefetchLow)
+ : this()
+ {
+ _sessionNumber = Interlocked.Increment(ref _nextSessionNumber);
+ _connection = con;
+ _transacted = transacted;
+
+ if ( transacted )
+ {
+ _acknowledgeMode = AcknowledgeMode.SessionTransacted;
+ }
+ else
+ {
+ _acknowledgeMode = acknowledgeMode;
+ }
+
+ _channelId = channelId;
+ _defaultPrefetchHighMark = defaultPrefetchHigh;
+ _defaultPrefetchLowMark = defaultPrefetchLow;
+
+ if ( _acknowledgeMode == AcknowledgeMode.NoAcknowledge )
+ {
+ _queue = new FlowControlQueue(_defaultPrefetchLowMark, _defaultPrefetchHighMark,
+ new ThresholdMethod(OnPrefetchLowMark),
+ new ThresholdMethod(OnPrefetchHighMark));
+ }
+ else
+ {
+ // low and upper are the same
+ _queue = new FlowControlQueue(_defaultPrefetchHighMark, _defaultPrefetchHighMark,
+ null, null);
+ }
+ }
+
+ private AmqChannel()
+ {
+ _messageFactoryRegistry = MessageFactoryRegistry.NewDefaultRegistry();
+ }
+
+ /// <summary>
+ /// Acknowledge mode for messages received.
+ /// </summary>
+ public AcknowledgeMode AcknowledgeMode
+ {
+ get
+ {
+ CheckNotClosed();
+ return _acknowledgeMode;
+ }
+ }
+
+ /// <summary>
+ /// True if the channel should use transactions.
+ /// </summary>
+ public bool Transacted
+ {
+ get
+ {
+ CheckNotClosed();
+ return _transacted;
+ }
+ }
+
+ /// <summary>
+ /// Prefetch value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ public int DefaultPrefetch
+ {
+ get { return DefaultPrefetchHigh; }
+ }
+
+ /// <summary>
+ /// Prefetch low value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ public int DefaultPrefetchLow
+ {
+ get { return _defaultPrefetchLowMark; }
+ }
+
+ /// <summary>
+ /// Prefetch high value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ public int DefaultPrefetchHigh
+ {
+ get { return _defaultPrefetchHighMark; }
+ }
+
+ /// <summary> Indicates whether or not this channel is currently suspended. </summary>
+ public bool IsSuspended
+ {
+ get { return _suspended; }
+ }
+
+ /// <summary> Provides the channels number within the the connection. </summary>
+ public ushort ChannelId
+ {
+ get { return _channelId; }
+ }
+
+ /// <summary> Provides the connection that this channel runs over. </summary>
+ public AMQConnection Connection
+ {
+ get { return _connection; }
+ }
+
+ /// <summary>
+ /// Declare a new exchange.
+ /// </summary>
+ /// <param name="exchangeName">Name of the exchange</param>
+ /// <param name="exchangeClass">Class of the exchange, from <see cref="ExchangeClassConstants"/></param>
+ public void DeclareExchange(String exchangeName, String exchangeClass)
+ {
+ _logger.Debug(string.Format("DeclareExchange vame={0} exchangeClass={1}", exchangeName, exchangeClass));
+
+ DeclareExchange(_channelId, 0, exchangeName, exchangeClass, false, false, false, false, true, null);
+ }
+
+ /// <summary>
+ /// Declare a new exchange using the default exchange class.
+ /// </summary>
+ /// <param name="exchangeName">Name of the exchange</param>
+ public void DeleteExchange(string exchangeName)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Declare a new queue with the specified set of arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue</param>
+ /// <param name="isDurable">True if the queue should be durable</param>
+ /// <param name="isExclusive">True if the queue should be exclusive to this channel</param>
+ /// <param name="isAutoDelete">True if the queue should be deleted when the channel closes</param>
+ public void DeclareQueue(string queueName, bool isDurable, bool isExclusive, bool isAutoDelete)
+ {
+ DoQueueDeclare(queueName, isDurable, isExclusive, isAutoDelete, null);
+ }
+
+ /// <summary>
+ /// Declare a new queue with the specified set of arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue</param>
+ /// <param name="isDurable">True if the queue should be durable</param>
+ /// <param name="isExclusive">True if the queue should be exclusive to this channel</param>
+ /// <param name="isAutoDelete">True if the queue should be deleted when the channel closes</param>
+ /// <param name="args">Optional arguments to Queue.Declare</param>
+ public void DeclareQueue(string queueName, bool isDurable, bool isExclusive, bool isAutoDelete, IFieldTable args)
+ {
+ DoQueueDeclare(queueName, isDurable, isExclusive, isAutoDelete, args);
+ }
+
+ /// <summary>
+ /// Delete a queue with the specifies arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue to delete</param>
+ /// <param name="ifUnused">If true, the queue will not deleted if it has no consumers</param>
+ /// <param name="ifEmpty">If true, the queue will not deleted if it has no messages</param>
+ /// <param name="noWait">If true, the server will not respond to the method</param>
+ public void DeleteQueue(string queueName, bool ifUnused, bool ifEmpty, bool noWait)
+ {
+ DoDeleteQueue(queueName, ifUnused, ifEmpty, noWait);
+ }
+
+ /// <summary>
+ /// Generate a new Unique name to use for a queue.
+ /// </summary>
+ /// <returns>A unique name to this channel</returns>
+ public string GenerateUniqueName()
+ {
+ string result = _connection.ProtocolSession.GenerateQueueName();
+ return Regex.Replace(result, "[^a-z0-9_]", "_");
+ }
+
+ /// <summary>
+ /// Removes all messages from a queue.
+ /// </summary>
+ /// <param name="queueName">Name of the queue to delete</param>
+ /// <param name="noWait">If true, the server will not respond to the method</param>
+ public void PurgeQueue(string queueName, bool noWait)
+ {
+ DoPurgeQueue(queueName, noWait);
+ }
+
+ /// <summary>
+ /// Bind a queue to the specified exchange.
+ /// </summary>
+ /// <param name="queueName">Name of queue to bind</param>
+ /// <param name="exchangeName">Name of exchange to bind to</param>
+ /// <param name="routingKey">Routing key</param>
+ public void Bind(string queueName, string exchangeName, string routingKey)
+ {
+ DoBind(queueName, exchangeName, routingKey, new FieldTable());
+ }
+
+ /// <summary>
+ /// Bind a queue to the specified exchange.
+ /// </summary>
+ /// <param name="queueName">Name of queue to bind</param>
+ /// <param name="exchangeName">Name of exchange to bind to</param>
+ /// <param name="routingKey">Routing key</param>
+ /// <param name="args">Table of arguments for the binding. Used to bind with a Headers Exchange</param>
+ public void Bind(string queueName, string exchangeName, string routingKey, IFieldTable args)
+ {
+ DoBind(queueName, exchangeName, routingKey, (FieldTable)args);
+ }
+
+ /// <summary>
+ /// Create a new empty message with no body.
+ /// </summary>
+ /// <returns>The new message</returns>
+ public IMessage CreateMessage()
+ {
+ return (IBytesMessage)_messageFactoryRegistry.CreateMessage("application/octet-stream");
+ }
+
+ /// <summary>
+ /// Create a new message of the specified MIME type.
+ /// </summary>
+ /// <param name="mimeType">The mime type to create</param>
+ /// <returns>The new message</returns>
+ public IMessage CreateMessage(string mimeType)
+ {
+ return _messageFactoryRegistry.CreateMessage(mimeType);
+ }
+
+ /// <summary>
+ /// Creates a new message for bytes (application/octet-stream).
+ /// </summary>
+ /// <returns>The new message</returns>
+ public IBytesMessage CreateBytesMessage()
+ {
+ return (IBytesMessage)_messageFactoryRegistry.CreateMessage("application/octet-stream");
+ }
+
+ /// <summary>
+ /// Creates a new text message (text/plain) with empty content.
+ /// </summary>
+ /// <returns>The new message</returns>
+ public ITextMessage CreateTextMessage()
+ {
+ return CreateTextMessage(String.Empty);
+ }
+
+ /// <summary>
+ /// Creates a new text message (text/plain) with a body.
+ /// </summary>
+ /// <param name="text">Initial body of the message</param>
+ /// <returns>The new message</returns>
+ public ITextMessage CreateTextMessage(string text)
+ {
+ ITextMessage msg = (ITextMessage)_messageFactoryRegistry.CreateMessage("text/plain");
+ msg.Text = text;
+ return msg;
+ }
+
+ /// <summary>
+ /// Creates a new Consumer using the builder pattern.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <returns>The builder object</returns>
+ public MessageConsumerBuilder CreateConsumerBuilder(string queueName)
+ {
+ return new MessageConsumerBuilder(this, queueName);
+ }
+
+ /// <summary>
+ /// Creates a new consumer.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <param name="prefetchLow">Low prefetch value</param>
+ /// <param name="prefetchHigh">High prefetch value</param>
+ /// <param name="noLocal">If true, messages sent on this channel will not be received by this consumer</param>
+ /// <param name="exclusive">If true, the consumer opens the queue in exclusive mode</param>
+ /// <returns>The new consumer</returns>
+ public IMessageConsumer CreateConsumer(string queueName,
+ int prefetchLow,
+ int prefetchHigh,
+ bool noLocal,
+ bool exclusive)
+ {
+ _logger.Debug(String.Format("CreateConsumer queueName={0} prefetchLow={1} prefetchHigh={2} noLocal={3} exclusive={4} ",
+ queueName, prefetchLow, prefetchHigh, noLocal, exclusive));
+
+ return CreateConsumerImpl(queueName, prefetchLow, prefetchHigh, noLocal, exclusive, false);
+ }
+
+ /// <summary>
+ /// Creates a new consumer.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <param name="prefetchLow">Low prefetch value</param>
+ /// <param name="prefetchHigh">High prefetch value</param>
+ /// <param name="noLocal">If true, messages sent on this channel will not be received by this consumer</param>
+ /// <param name="exclusive">If true, the consumer opens the queue in exclusive mode</param>
+ /// <param name="browse">If true, the consumer only browses and does not consume messages</param>
+ /// <returns>The new consumer</returns>
+ public IMessageConsumer CreateConsumer(string queueName,
+ int prefetchLow,
+ int prefetchHigh,
+ bool noLocal,
+ bool exclusive,
+ bool browse)
+ {
+ _logger.Debug(String.Format("CreateConsumer queueName={0} prefetchLow={1} prefetchHigh={2} noLocal={3} exclusive={4} browse={5}",
+ queueName, prefetchLow, prefetchHigh, noLocal, exclusive, browse));
+
+ return CreateConsumerImpl(queueName, prefetchLow, prefetchHigh, noLocal, exclusive, browse);
+ }
+
+
+ /// <summary>
+ /// Unsubscribe from a queue.
+ /// </summary>
+ /// <param name="subscriptionName">Subscription name</param>
+ public void Unsubscribe(String name)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Create a new message publisher using the builder pattern.
+ /// </summary>
+ /// <returns>The builder object</returns>
+ public MessagePublisherBuilder CreatePublisherBuilder()
+ {
+ return new MessagePublisherBuilder(this);
+ }
+
+ /// <summary>
+ /// Create a new message publisher.
+ /// </summary>
+ /// <param name="exchangeName">Name of exchange to publish to</param>
+ /// <param name="routingKey">Routing key</param>
+ /// <param name="deliveryMode">Default delivery mode</param>
+ /// <param name="timeToLive">Default TTL time of messages</param>
+ /// <param name="immediate">If true, sent immediately</param>
+ /// <param name="mandatory">If true, the broker will return an error
+ /// (as a connection exception) if the message cannot be delivered</param>
+ /// <param name="priority">Default message priority</param>
+ /// <returns>The new message publisher</returns>
+ public IMessagePublisher CreatePublisher(string exchangeName, string routingKey, DeliveryMode deliveryMode,
+ long timeToLive, bool immediate, bool mandatory, int priority)
+ {
+ _logger.Debug(string.Format("Using new CreatePublisher exchangeName={0}, exchangeClass={1} routingKey={2}",
+ exchangeName, "none", routingKey));
+
+ return CreateProducerImpl(exchangeName, routingKey, deliveryMode,
+ timeToLive, immediate, mandatory, priority);
+ }
+
+ /// <summary>
+ /// Recover after transaction failure.
+ /// </summary>
+ /// <remarks>The 0-8 protocol does not support this, not implemented exception will always be thrown.</remarks>
+ public void Recover()
+ {
+ CheckNotClosed();
+ CheckNotTransacted();
+
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Commit the transaction.
+ /// </summary>
+ public void Commit()
+ {
+ // FIXME: Fail over safety. Needs FailoverSupport?
+ CheckNotClosed();
+ CheckTransacted(); // throws IllegalOperationException if not a transacted session
+
+ try
+ {
+ // Acknowledge up to message last delivered (if any) for each consumer.
+ // Need to send ack for messages delivered to consumers so far.
+ foreach (BasicMessageConsumer consumer in _consumers.Values)
+ {
+ // Sends acknowledgement to server.
+ consumer.AcknowledgeDelivered();
+ }
+
+ // Commits outstanding messages sent and outstanding acknowledgements.
+ _connection.ConvenientProtocolWriter.SyncWrite(TxCommitBody.CreateAMQFrame(_channelId), typeof(TxCommitOkBody));
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Failed to commit", e);
+ }
+ }
+
+ /// <summary>
+ /// Rollback the transaction.
+ /// </summary>
+ public void Rollback()
+ {
+ lock (_suspensionLock)
+ {
+ CheckTransacted(); // throws IllegalOperationException if not a transacted session
+
+ try
+ {
+ bool suspended = IsSuspended;
+ if (!suspended)
+ {
+ Suspend(true);
+ }
+
+ // Reject up to message last delivered (if any) for each consumer.
+ // Need to send reject for messages delivered to consumers so far.
+ foreach (BasicMessageConsumer consumer in _consumers.Values)
+ {
+ // Sends acknowledgement to server.
+ consumer.RejectUnacked();
+ }
+
+ _connection.ConvenientProtocolWriter.SyncWrite(TxRollbackBody.CreateAMQFrame(_channelId), typeof(TxRollbackOkBody));
+
+ if ( !suspended )
+ {
+ Suspend(false);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Failed to rollback", e);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Create a disconnected channel that will fault
+ /// for most things, but is useful for testing
+ /// </summary>
+ /// <returns>A new disconnected channel</returns>
+ public static IChannel CreateDisconnectedChannel()
+ {
+ return new AmqChannel();
+ }
+
+ public override void Close()
+ {
+ lock (_connection.FailoverMutex)
+ {
+ // We must close down all producers and consumers in an orderly fashion. This is the only method
+ // that can be called from a different thread of control from the one controlling the session
+
+ lock (_closingLock)
+ {
+ SetClosed();
+
+ // we pass null since this is not an error case
+ CloseProducersAndConsumers(null);
+
+ try
+ {
+ _connection.CloseSession(this);
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Error closing session: " + e);
+ }
+ finally
+ {
+ _connection.DeregisterSession(_channelId);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the server initiates the closure of the session
+ * unilaterally.
+ * @param e the exception that caused this session to be closed. Null causes the
+ */
+ public void ClosedWithException(Exception e)
+ {
+ lock (_connection.FailoverMutex)
+ {
+ // An AMQException has an error code and message already and will be passed in when closure occurs as a
+ // result of a channel close request
+ SetClosed();
+ AMQException amqe;
+
+ if (e is AMQException)
+ {
+ amqe = (AMQException) e;
+ }
+ else
+ {
+ amqe = new AMQException("Closing session forcibly", e);
+ }
+
+ _connection.DeregisterSession(_channelId);
+ CloseProducersAndConsumers(amqe);
+ }
+ }
+
+ public void MessageReceived(UnprocessedMessage message)
+ {
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Message received in session with channel id " + _channelId);
+ }
+
+ if ( message.DeliverBody == null )
+ {
+ ReturnBouncedMessage(message);
+ }
+ else
+ {
+ _queue.Enqueue(message);
+ }
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ private void SetClosed()
+ {
+ Interlocked.Exchange(ref _closed, CLOSED);
+ }
+
+ /// <summary>
+ /// Close all producers or consumers. This is called either in the error case or when closing the session normally.
+ /// <param name="amqe">the exception, may be null to indicate no error has occurred</param>
+ ///
+ private void CloseProducersAndConsumers(AMQException amqe)
+ {
+ try
+ {
+ CloseProducers();
+ }
+ catch (QpidException e)
+ {
+ _logger.Error("Error closing session: " + e, e);
+ }
+ try
+ {
+ CloseConsumers(amqe);
+ }
+ catch (QpidException e)
+ {
+ _logger.Error("Error closing session: " + e, e);
+ }
+ }
+
+ /// <summary>
+ /// Called to close message producers cleanly. This may or may <b>not</b> be as a result of an error. There is
+ /// currently no way of propagating errors to message producers (this is a JMS limitation).
+ /// </summary>
+ private void CloseProducers()
+ {
+ _logger.Debug("Closing producers on session " + this);
+
+ // we need to clone the list of producers since the close() method updates the _producers collection
+ // which would result in a concurrent modification exception
+ ArrayList clonedProducers = new ArrayList(_producers.Values);
+
+ foreach (BasicMessageProducer prod in clonedProducers)
+ {
+ _logger.Debug("Closing producer " + prod);
+ prod.Close();
+ }
+
+ // at this point the _producers map is empty
+ }
+
+ /// <summary>
+ /// Called to close message consumers cleanly. This may or may <b>not</b> be as a result of an error.
+ /// <param name="error">not null if this is a result of an error occurring at the connection level</param>
+ private void CloseConsumers(Exception error)
+ {
+ if (_dispatcher != null)
+ {
+ _dispatcher.StopDispatcher();
+ }
+
+ // we need to clone the list of consumers since the close() method updates the _consumers collection
+ // which would result in a concurrent modification exception
+ ArrayList clonedConsumers = new ArrayList(_consumers.Values);
+
+ foreach (BasicMessageConsumer con in clonedConsumers)
+ {
+ if (error != null)
+ {
+ con.NotifyError(error);
+ }
+ else
+ {
+ con.Close();
+ }
+ }
+
+ // at this point the _consumers map will be empty
+ }
+
+ private IMessagePublisher CreateProducerImpl(string exchangeName, string routingKey,
+ DeliveryMode deliveryMode,
+ long timeToLive, bool immediate, bool mandatory, int priority)
+ {
+ lock (_closingLock)
+ {
+ CheckNotClosed();
+
+ try
+ {
+ return new BasicMessageProducer(exchangeName, routingKey, _transacted, _channelId,
+ this, GetNextProducerId(),
+ deliveryMode, timeToLive, immediate, mandatory, priority);
+ }
+ catch (AMQException e)
+ {
+ _logger.Error("Error creating message producer: " + e, e);
+ throw new QpidException("Error creating message producer", e);
+ }
+ }
+ }
+
+ /// <summary> Creates a message consumer on this channel.</summary>
+ ///
+ /// <param name="queueName">The name of the queue to attach the consumer to.</param>
+ /// <param name="prefetchLow">The pre-fetch buffer low-water mark.</param>
+ /// <param name="prefetchHigh">The pre-fetch buffer high-water mark.</param>
+ /// <param name="noLocal">The no-local flag, <tt>true</tt> means that the consumer does not receive messages sent on this channel.</param>
+ /// <param name="exclusive">The exclusive flag, <tt>true</tt> gives this consumer exclusive receive access to the queue.</param>
+ ///
+ /// <return>The message consumer.</return>
+ private IMessageConsumer CreateConsumerImpl(string queueName,
+ int prefetchLow,
+ int prefetchHigh,
+ bool noLocal,
+ bool exclusive,
+ bool browse)
+ {
+ lock (_closingLock)
+ {
+ CheckNotClosed();
+
+ BasicMessageConsumer consumer = new BasicMessageConsumer(_channelId, queueName, noLocal,
+ _messageFactoryRegistry, this,
+ prefetchHigh, prefetchLow, exclusive,
+ browse);
+ try
+ {
+ RegisterConsumer(consumer);
+ }
+ catch (AMQException e)
+ {
+ throw new QpidException("Error registering consumer: " + e, e);
+ }
+
+ return consumer;
+ }
+ }
+
+ private void CheckTransacted()
+ {
+ if (!Transacted)
+ {
+ throw new InvalidOperationException("Channel is not transacted");
+ }
+ }
+
+ private void CheckNotTransacted()
+ {
+ if (Transacted)
+ {
+ throw new InvalidOperationException("Channel is transacted");
+ }
+ }
+
+ internal void Start()
+ {
+ _dispatcher = new Dispatcher(this);
+ Thread dispatcherThread = new Thread(new ThreadStart(_dispatcher.RunDispatcher));
+ dispatcherThread.IsBackground = true;
+ dispatcherThread.Start();
+ }
+
+ internal void Stop()
+ {
+ Suspend(true);
+ if (_dispatcher != null)
+ {
+ _dispatcher.StopDispatcher();
+ }
+ }
+
+ internal void RegisterConsumer(string consumerTag, IMessageConsumer consumer)
+ {
+ _consumers[consumerTag] = consumer;
+ }
+
+ /// <summary>
+ /// Called by the MessageConsumer when closing, to deregister the consumer from the
+ /// map from consumerTag to consumer instance.
+ /// </summary>
+ /// <param name="consumerTag">the consumer tag, that was broker-generated</param>
+ internal void DeregisterConsumer(string consumerTag)
+ {
+ _consumers.Remove(consumerTag);
+ }
+
+ internal void RegisterProducer(long producerId, IMessagePublisher publisher)
+ {
+ _producers[producerId] = publisher;
+ }
+
+ internal void DeregisterProducer(long producerId)
+ {
+ _producers.Remove(producerId);
+ }
+
+ private long GetNextProducerId()
+ {
+ return ++_nextProducerId;
+ }
+
+ /**
+ * Called to mark the session as being closed. Useful when the session needs to be made invalid, e.g. after
+ * failover when the client has veoted resubscription.
+ *
+ * The caller of this method must already hold the failover mutex.
+ */
+ internal void MarkClosed()
+ {
+ SetClosed();
+ _connection.DeregisterSession(_channelId);
+ MarkClosedProducersAndConsumers();
+ }
+
+ private void MarkClosedProducersAndConsumers()
+ {
+ try
+ {
+ // no need for a markClosed* method in this case since there is no protocol traffic closing a producer
+ CloseProducers();
+ }
+ catch (QpidException e)
+ {
+ _logger.Error("Error closing session: " + e, e);
+ }
+ try
+ {
+ MarkClosedConsumers();
+ }
+ catch (QpidException e)
+ {
+ _logger.Error("Error closing session: " + e, e);
+ }
+ }
+
+ private void MarkClosedConsumers()
+ {
+ if (_dispatcher != null)
+ {
+ _dispatcher.StopDispatcher();
+ }
+ // we need to clone the list of consumers since the close() method updates the _consumers collection
+ // which would result in a concurrent modification exception
+ ArrayList clonedConsumers = new ArrayList(_consumers.Values);
+
+ foreach (BasicMessageConsumer consumer in clonedConsumers)
+ {
+ consumer.MarkClosed();
+ }
+ // at this point the _consumers map will be empty
+ }
+
+ private void DoPurgeQueue(string queueName, bool noWait)
+ {
+ try
+ {
+ _logger.DebugFormat("PurgeQueue {0}", queueName);
+
+ AMQFrame purgeQueue = QueuePurgeBody.CreateAMQFrame(_channelId, 0, queueName, noWait);
+
+ if (noWait)
+ _connection.ProtocolWriter.Write(purgeQueue);
+ else
+ _connection.ConvenientProtocolWriter.SyncWrite(purgeQueue, typeof(QueuePurgeOkBody));
+ }
+ catch (AMQException)
+ {
+ throw;
+ }
+ }
+
+ /**
+ * Replays frame on fail over.
+ *
+ * @throws AMQException
+ */
+ internal void ReplayOnFailOver()
+ {
+ _logger.Debug(string.Format("Replaying frames for channel {0}", _channelId));
+ foreach (AMQFrame frame in _replayFrames)
+ {
+ _logger.Debug(string.Format("Replaying frame=[{0}]", frame));
+ _connection.ProtocolWriter.Write(frame);
+ }
+ }
+
+ /// <summary>
+ /// Callers must hold the failover mutex before calling this method.
+ /// </summary>
+ /// <param name="consumer"></param>
+ private void RegisterConsumer(BasicMessageConsumer consumer)
+ {
+ // Need to generate a consumer tag on the client so we can exploit the nowait flag.
+ String tag = string.Format("{0}-{1}", _sessionNumber, _nextConsumerNumber++);
+ consumer.ConsumerTag = tag;
+ _consumers.Add(tag, consumer);
+
+ String consumerTag = ConsumeFromQueue(consumer.QueueName, consumer.NoLocal,
+ consumer.Exclusive, consumer.AcknowledgeMode, tag, consumer.Browse);
+
+ }
+
+ internal void DoBind(string queueName, string exchangeName, string routingKey, FieldTable args)
+ {
+
+ _logger.Debug(string.Format("QueueBind queueName={0} exchangeName={1} routingKey={2}, arg={3}",
+ queueName, exchangeName, routingKey, args));
+
+ AMQFrame queueBind = QueueBindBody.CreateAMQFrame(_channelId, 0,
+ queueName, exchangeName,
+ routingKey, false, args);
+
+
+ lock (_connection.FailoverMutex)
+ {
+ _connection.ConvenientProtocolWriter.SyncWrite(queueBind, typeof(QueueBindOkBody));
+ }
+ // AS FIXME: wasnae me
+ _replayFrames.Add(QueueBindBody.CreateAMQFrame(_channelId, 0,
+ queueName, exchangeName,
+ routingKey, true, args));
+ }
+
+ private String ConsumeFromQueue(String queueName, bool noLocal, bool exclusive, AcknowledgeMode acknowledgeMode, String tag, bool browse)
+ {
+ FieldTable args = new FieldTable();
+ if(browse)
+ {
+ args["x-filter-no-consume"] = true;
+ }
+ AMQFrame basicConsume = BasicConsumeBody.CreateAMQFrame(_channelId, 0,
+ queueName, tag, noLocal,
+ acknowledgeMode == AcknowledgeMode.NoAcknowledge,
+ exclusive, true, args);
+
+ _replayFrames.Add(basicConsume);
+
+ _connection.ProtocolWriter.Write(basicConsume);
+ return tag;
+ }
+
+ private void DoDeleteQueue(string queueName, bool ifUnused, bool ifEmpty, bool noWait)
+ {
+ try
+ {
+ _logger.Debug(string.Format("DeleteQueue name={0}", queueName));
+
+ AMQFrame queueDelete = QueueDeleteBody.CreateAMQFrame(_channelId, 0, queueName, ifUnused, ifEmpty, noWait);
+
+ if (noWait)
+ {
+ _connection.ProtocolWriter.Write(queueDelete);
+ }
+ else
+ {
+ _connection.ConvenientProtocolWriter.SyncWrite(queueDelete, typeof(QueueDeleteOkBody));
+ }
+ // AS FIXME: wasnae me
+ _replayFrames.Add(QueueDeleteBody.CreateAMQFrame(_channelId, 0, queueName, ifUnused, ifEmpty, true));
+ }
+ catch (AMQException)
+ {
+ throw;
+ }
+ }
+
+ private void DoQueueDeclare(string queueName, bool isDurable, bool isExclusive, bool isAutoDelete, IFieldTable args)
+ {
+ _logger.Debug(string.Format("DeclareQueue name={0} durable={1} exclusive={2}, auto-delete={3}",
+ queueName, isDurable, isExclusive, isAutoDelete));
+
+ AMQFrame queueDeclare = QueueDeclareBody.CreateAMQFrame(_channelId, 0, queueName, false, isDurable, isExclusive,
+ isAutoDelete, false, (FieldTable) args);
+
+
+ lock (_connection.FailoverMutex)
+ {
+ _connection.ConvenientProtocolWriter.SyncWrite(queueDeclare, typeof(QueueDeclareOkBody));
+ }
+ // AS FIXME: wasnae me
+ _replayFrames.Add(QueueDeclareBody.CreateAMQFrame(_channelId, 0, queueName, false, isDurable, isExclusive,
+ isAutoDelete, true, null));
+ }
+
+ // AMQP-level method.
+ private void DeclareExchange(ushort channelId, ushort ticket, string exchangeName,
+ string exchangeClass, bool passive, bool durable,
+ bool autoDelete, bool xinternal, bool noWait, FieldTable args)
+ {
+ _logger.Debug(String.Format("DeclareExchange channelId={0} exchangeName={1} exchangeClass={2}",
+ _channelId, exchangeName, exchangeClass));
+
+ AMQFrame declareExchange = ExchangeDeclareBody.CreateAMQFrame(channelId, ticket, exchangeName, exchangeClass, passive,
+ durable, autoDelete, xinternal, noWait, args);
+
+ if (noWait)
+ {
+ lock (_connection.FailoverMutex)
+ {
+ _connection.ProtocolWriter.Write(declareExchange);
+ }
+ // AS FIXME: wasnae me
+ _replayFrames.Add(declareExchange);
+ }
+ else
+ {
+ throw new NotImplementedException("Don't use nowait=false with DeclareExchange");
+ //_connection.ConvenientProtocolWriter.SyncWrite(declareExchange, typeof (ExchangeDeclareOkBody));
+ }
+ }
+
+ /**
+ * Acknowledge a message or several messages. This method can be called via AbstractJMSMessage or from
+ * a BasicConsumer. The former where the mode is CLIENT_ACK and the latter where the mode is
+ * AUTO_ACK or similar.
+ *
+ * @param deliveryTag the tag of the last message to be acknowledged
+ * @param multiple if true will acknowledge all messages up to and including the one specified by the
+ * delivery tag
+ */
+ internal void AcknowledgeMessage(ulong deliveryTag, bool multiple)
+ {
+ AMQFrame ackFrame = BasicAckBody.CreateAMQFrame(_channelId, deliveryTag, multiple);
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Sending ack for delivery tag " + deliveryTag + " on channel " + _channelId);
+ }
+ // FIXME: lock FailoverMutex here?
+ _connection.ProtocolWriter.Write(ackFrame);
+ }
+
+ public void RejectMessage(ulong deliveryTag, bool requeue)
+ {
+ if ((_acknowledgeMode == AcknowledgeMode.ClientAcknowledge) || (_acknowledgeMode == AcknowledgeMode.SessionTransacted))
+ {
+ AMQFrame rejectFrame = BasicRejectBody.CreateAMQFrame(_channelId, deliveryTag, requeue);
+ _connection.ProtocolWriter.Write(rejectFrame);
+ }
+ }
+
+ /// <summary>
+ /// Handle a message that bounced from the server, creating
+ /// the corresponding exception and notifying the connection about it
+ /// </summary>
+ /// <param name="message">Unprocessed message</param>
+ private void ReturnBouncedMessage(UnprocessedMessage message)
+ {
+ try
+ {
+ AbstractQmsMessage bouncedMessage =
+ _messageFactoryRegistry.CreateMessage(0, false, message.ContentHeader, message.Bodies);
+
+ int errorCode = message.BounceBody.ReplyCode;
+ string reason = message.BounceBody.ReplyText;
+ _logger.Debug("Message returned with error code " + errorCode + " (" + reason + ")");
+ AMQException exception;
+
+ if (errorCode == AMQConstant.NO_CONSUMERS.Code)
+ {
+ exception = new AMQNoConsumersException(reason, bouncedMessage);
+ }
+ else if (errorCode == AMQConstant.NO_ROUTE.Code)
+ {
+ exception = new AMQNoRouteException(reason, bouncedMessage);
+ }
+ else
+ {
+ exception = new AMQUndeliveredException(errorCode, reason, bouncedMessage);
+ }
+
+ _connection.ExceptionReceived(exception);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Caught exception trying to raise undelivered message exception (dump follows) - ignoring...", ex);
+ }
+ }
+
+ private void OnPrefetchLowMark(int count)
+ {
+ if (_acknowledgeMode == AcknowledgeMode.NoAcknowledge)
+ {
+ _logger.Warn("Below threshold(" + _defaultPrefetchLowMark + ") so unsuspending channel. Current value is " + count);
+ Suspend(false);
+ }
+ }
+
+ private void OnPrefetchHighMark(int count)
+ {
+ if (_acknowledgeMode == AcknowledgeMode.NoAcknowledge)
+ {
+ _logger.Warn("Above threshold(" + _defaultPrefetchHighMark + ") so suspending channel. Current value is " + count);
+ Suspend(true);
+ }
+ }
+
+ private void Suspend(bool suspend)
+ {
+ lock (_suspensionLock)
+ {
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Setting channel flow : " + (suspend ? "suspended" : "unsuspended"));
+ }
+
+ _suspended = suspend;
+ AMQFrame frame = ChannelFlowBody.CreateAMQFrame(_channelId, !suspend);
+
+ Connection.ConvenientProtocolWriter.SyncWrite(frame, typeof(ChannelFlowOkBody));
+ }
+ }
+
+ /// <summary>A Dispatcher turns the consumption of incoming messages from an arrival queue, into event notifications on consumers.
+ /// The arrival queue is typically a blocking queue, on which a dispatcher waits for messages to consume. Upon receipt of a message
+ /// the dispatcher finds the consumer that is listening to the queue to which the message has been send and notifies it of the new
+ /// message.
+ ///
+ /// <p/>The Dispatcher also contains logic to recognize bounced messages. Bounced messages returned from the broker can be
+ /// told apart from regular deliveries because they do not have a delivery queue set on them. When the dispatcher receives a
+ /// bounced message it creates an exception and notifies the connection, to which its containing channel belongs, of the condition.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Notify consumers of message arrivals on their queues. <td> <see cref="BasicMessageConsumer"/>
+ /// <tr><td> Notify the containing connection of bounced message arrivals. <td> <see cref="AMQConnection"/>
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks>Stop mechanism seems wrong, as queue consume is evaluated after stop flag, so could consume and notify one more message.
+ /// Placing stop check after consume may also be wrong as it may cause a message to be thrown away. Seems more correct to use interupt on
+ /// the block thread to cause it to prematurely return from its wait, whereupon it can be made to re-check the stop flag.</remarks>
+ ///
+ /// <remarks>Exception swallowed, if there is an exception whilst notifying the connection on bounced messages. Unhandled excetpion should
+ /// fall through and terminate the loop, as it is a bug if it occurrs.</remarks>
+ private class Dispatcher
+ {
+ /// <summary> Flag used to indicate when this dispatcher is to be stopped (0=go, 1=stop). </summary>
+ private int _stopped = 0;
+
+ /// <summary> The channel for which this is a dispatcher. </summary>
+ private AmqChannel _containingChannel;
+
+ /// <summary> Creates a dispatcher on the specified channel. </summary>
+ ///
+ /// <param name="containingChannel"> The channel on which this is a dispatcher. </param>
+ public Dispatcher(AmqChannel containingChannel)
+ {
+ _containingChannel = containingChannel;
+ }
+
+ /// <summary>The message dispatch loop. Consumes messages from the channels queue, notifying consumers of regular deliveries, and
+ /// the connection of bounced messages.</summary>
+ public void RunDispatcher()
+ {
+ UnprocessedMessage message;
+
+ while (_stopped == 0 && (message = (UnprocessedMessage)_containingChannel._queue.Dequeue()) != null)
+ {
+ if (message.DeliverBody != null)
+ {
+ BasicMessageConsumer consumer = (BasicMessageConsumer) _containingChannel._consumers[message.DeliverBody.ConsumerTag];
+
+ if (consumer == null)
+ {
+ _logger.Warn("Received a message from queue " + message.DeliverBody.ConsumerTag + " without a f - ignoring...");
+ }
+ else
+ {
+ consumer.NotifyMessage(message, _containingChannel.ChannelId);
+ }
+ }
+ else
+ {
+ try
+ {
+ // Bounced message is processed here, away from the transport thread
+ AbstractQmsMessage bouncedMessage = _containingChannel._messageFactoryRegistry.
+ CreateMessage(0, false, message.ContentHeader, message.Bodies);
+
+ int errorCode = message.BounceBody.ReplyCode;
+ string reason = message.BounceBody.ReplyText;
+
+ _logger.Debug("Message returned with error code " + errorCode + " (" + reason + ")");
+
+ _containingChannel._connection.ExceptionReceived(new AMQUndeliveredException(errorCode, "Error: " + reason, bouncedMessage));
+ }
+ catch (Exception e)
+ {
+ _logger.Error("Caught exception trying to raise undelivered message exception (dump follows) - ignoring...", e);
+ }
+ }
+ }
+
+ _logger.Debug("Dispatcher thread terminating for channel: " + _containingChannel._channelId + ".");
+ }
+
+ /// <summary> Sets a stop flag on this dispatcher, which causes its dispatch loop to exit at the next available opportunity. </summary>
+ public void StopDispatcher()
+ {
+ Interlocked.Exchange(ref _stopped, 1);
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/BasicMessageConsumer.cs b/dotnet/Qpid.Client/Client/BasicMessageConsumer.cs
new file mode 100644
index 0000000000..fdac5e75f2
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/BasicMessageConsumer.cs
@@ -0,0 +1,485 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Collections;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client
+{
+ public class BasicMessageConsumer : Closeable, IMessageConsumer
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(BasicMessageConsumer));
+
+ private bool _noLocal;
+
+ /** Holds the exclusive status flag for the consumers access to its queue. */
+ private bool _exclusive;
+
+ public bool Exclusive
+ {
+ get { return _exclusive; }
+ }
+
+ private bool _browse;
+
+ public bool Browse
+ {
+ get { return _browse; }
+ }
+
+ public bool NoLocal
+ {
+ get { return _noLocal; }
+ set { _noLocal = value; }
+ }
+
+ private AcknowledgeMode _acknowledgeMode;
+
+ public AcknowledgeMode AcknowledgeMode
+ {
+ get { return _acknowledgeMode; }
+ }
+
+ private MessageReceivedDelegate _messageListener;
+
+ private bool IsMessageListenerSet
+ {
+ get { return _messageListener != null; }
+ }
+
+ /// <summary>
+ /// The consumer tag allows us to close the consumer by sending a jmsCancel method to the
+ /// broker
+ /// </summary>
+ private string _consumerTag;
+
+ /// <summary>
+ /// We need to know the channel id when constructing frames
+ /// </summary>
+ private ushort _channelId;
+
+ private readonly string _queueName;
+
+ /// <summary>
+ /// Protects the setting of a messageListener
+ /// </summary>
+ private readonly object _syncLock = new object();
+
+ /// <summary>
+ /// We store the high water prefetch field in order to be able to reuse it when resubscribing in the event of failover
+ /// </summary>
+ private int _prefetchHigh;
+
+ /// <summary>
+ /// We store the low water prefetch field in order to be able to reuse it when resubscribing in the event of failover
+ /// </summary>
+ private int _prefetchLow;
+
+ /// <summary>
+ /// When true indicates that either a message listener is set or that
+ /// a blocking receive call is in progress
+ /// </summary>
+ private bool _receiving;
+
+ /// <summary>
+ /// Used in the blocking receive methods to receive a message from
+ /// the Channel thread.
+ /// </summary>
+ private readonly ConsumerProducerQueue _messageQueue = new ConsumerProducerQueue();
+
+ private MessageFactoryRegistry _messageFactory;
+
+ private AmqChannel _channel;
+
+ // <summary>
+ // Tag of last message delievered, whoch should be acknowledged on commit in transaction mode.
+ // </summary>
+ //private long _lastDeliveryTag;
+
+ /// <summary>
+ /// Explicit list of all received but un-acked messages in a transaction. Used to ensure acking is completed when transaction is committed.
+ /// </summary>
+ private LinkedList<long> _receivedDeliveryTags;
+
+ /// <summary>
+ /// Number of messages unacknowledged in DUPS_OK_ACKNOWLEDGE mode
+ /// </summary>
+ private int _outstanding;
+
+ /// <summary>
+ /// Switch to enable sending of acknowledgements when using DUPS_OK_ACKNOWLEDGE mode.
+ /// Enabled when _outstannding number of msgs >= _prefetchHigh and disabled at < _prefetchLow
+ /// </summary>
+ private bool _dups_ok_acknowledge_send;
+
+ internal BasicMessageConsumer(ushort channelId, string queueName, bool noLocal,
+ MessageFactoryRegistry messageFactory, AmqChannel channel,
+ int prefetchHigh, int prefetchLow, bool exclusive, bool browse)
+ {
+ _channelId = channelId;
+ _queueName = queueName;
+ _noLocal = noLocal;
+ _messageFactory = messageFactory;
+ _channel = channel;
+ _acknowledgeMode = _channel.AcknowledgeMode;
+ _prefetchHigh = prefetchHigh;
+ _prefetchLow = prefetchLow;
+ _exclusive = exclusive;
+ _browse = browse;
+
+ if (_acknowledgeMode == AcknowledgeMode.SessionTransacted)
+ {
+ _receivedDeliveryTags = new LinkedList<long>();
+ }
+ }
+
+ #region IMessageConsumer Members
+
+ public MessageReceivedDelegate OnMessage
+ {
+ get
+ {
+ return _messageListener;
+ }
+ set
+ {
+ CheckNotClosed();
+
+ lock (_syncLock)
+ {
+ // If someone is already receiving
+ if (_messageListener != null && _receiving)
+ {
+ throw new InvalidOperationException("Another thread is already receiving...");
+ }
+
+ _messageListener = value;
+
+ _receiving = (_messageListener != null);
+
+ if (_receiving)
+ {
+ _logger.Debug("Message listener set for queue with name " + _queueName);
+ }
+ }
+ }
+ }
+
+ public IMessage Receive(long delay)
+ {
+ CheckNotClosed();
+
+ lock (_syncLock)
+ {
+ // If someone is already receiving
+ if (_receiving)
+ {
+ throw new InvalidOperationException("Another thread is already receiving (possibly asynchronously)...");
+ }
+
+ _receiving = true;
+ }
+
+ try
+ {
+ object o = _messageQueue.Dequeue(delay);
+
+ return ReturnMessageOrThrowAndPostDeliver(o);
+ }
+ finally
+ {
+ lock (_syncLock)
+ {
+ _receiving = false;
+ }
+ }
+ }
+
+ private IMessage ReturnMessageOrThrowAndPostDeliver(object o)
+ {
+ IMessage m = ReturnMessageOrThrow(o);
+ if (m != null)
+ {
+ PostDeliver(m);
+ }
+ return m;
+ }
+
+ public IMessage Receive()
+ {
+ return Receive(Timeout.Infinite);
+ }
+
+ public IMessage ReceiveNoWait()
+ {
+ return Receive(0);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// We can get back either a Message or an exception from the queue. This method examines the argument and deals
+ /// with it by throwing it (if an exception) or returning it (in any other case).
+ /// </summary>
+ /// <param name="o">the object off the queue</param>
+ /// <returns> a message only if o is a Message</returns>
+ /// <exception>JMSException if the argument is a throwable. If it is a QpidMessagingException it is rethrown as is, but if not
+ /// a QpidMessagingException is created with the linked exception set appropriately</exception>
+ private IMessage ReturnMessageOrThrow(object o)
+ {
+ // errors are passed via the queue too since there is no way of interrupting the poll() via the API.
+ if (o is Exception)
+ {
+ Exception e = (Exception) o;
+ throw new QpidException("Message consumer forcibly closed due to error: " + e, e);
+ }
+ else
+ {
+ return (IMessage) o;
+ }
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (_closed == CLOSED)
+ {
+ return;
+ }
+ // FIXME: Don't we need FailoverSupport here (as we have SyncWrite). i.e. rather than just locking FailOverMutex
+ lock (_channel.Connection.FailoverMutex)
+ {
+ lock (_closingLock)
+ {
+ Interlocked.Exchange(ref _closed, CLOSED);
+
+ AMQFrame cancelFrame = BasicCancelBody.CreateAMQFrame(_channelId, _consumerTag, false);
+
+ try
+ {
+ _channel.Connection.ConvenientProtocolWriter.SyncWrite(
+ cancelFrame, typeof(BasicCancelOkBody));
+ }
+ catch (AMQException e)
+ {
+ _logger.Error("Error closing consumer: " + e, e);
+ throw new QpidException("Error closing consumer: " + e);
+ }
+ finally
+ {
+ DeregisterConsumer();
+ }
+ }
+ }
+ }
+
+ /**
+ * Called from the AMQSession when a message has arrived for this consumer. This methods handles both the case
+ * of a message listener or a synchronous receive() caller.
+ *
+ * @param messageFrame the raw unprocessed mesage
+ * @param channelId channel on which this message was sent
+ */
+ internal void NotifyMessage(UnprocessedMessage messageFrame, int channelId)
+ {
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("notifyMessage called with message number " + messageFrame.DeliverBody.DeliveryTag);
+ }
+ try
+ {
+ AbstractQmsMessage jmsMessage = _messageFactory.CreateMessage((long)messageFrame.DeliverBody.DeliveryTag,
+ messageFrame.DeliverBody.Redelivered,
+ messageFrame.ContentHeader,
+ messageFrame.Bodies);
+
+ _logger.Debug("Message is of type: " + jmsMessage.GetType().Name);
+
+ PreDeliver(jmsMessage);
+
+ if (IsMessageListenerSet)
+ {
+ // We do not need a lock around the test above, and the dispatch below as it is invalid
+ // for an application to alter an installed listener while the session is started.
+#if __MonoCS__
+ _messageListener(jmsMessage);
+#else
+ _messageListener.Invoke(jmsMessage);
+#endif
+ PostDeliver(jmsMessage);
+ }
+ else
+ {
+ _messageQueue.Enqueue(jmsMessage);
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.Error("Caught exception (dump follows) - ignoring...", e); // FIXME
+ }
+ }
+
+
+ internal void NotifyError(Exception cause)
+ {
+ lock (_syncLock)
+ {
+ SetClosed();
+
+ // we have no way of propagating the exception to a message listener - a JMS limitation - so we
+ // deal with the case where we have a synchronous receive() waiting for a message to arrive
+ if (_messageListener == null)
+ {
+ // offer only succeeds if there is a thread waiting for an item from the queue
+ _messageQueue.Enqueue(cause);
+ _logger.Debug("Passed exception to synchronous queue for propagation to receive()");
+ }
+ DeregisterConsumer();
+ }
+ }
+
+ private void SetClosed()
+ {
+ Interlocked.Exchange(ref _closed, CLOSED);
+ }
+
+ /// <summary>
+ /// Perform cleanup to deregister this consumer. This occurs when closing the consumer in both the clean
+ /// case and in the case of an error occurring.
+ /// </summary>
+ internal void DeregisterConsumer()
+ {
+ _channel.DeregisterConsumer(_consumerTag);
+ }
+
+ public string ConsumerTag
+ {
+ get
+ {
+ return _consumerTag;
+ }
+ set
+ {
+ _consumerTag = value;
+ }
+ }
+
+ /**
+ * Called when you need to invalidate a consumer. Used for example when failover has occurred and the
+ * client has vetoed automatic resubscription.
+ * The caller must hold the failover mutex.
+ */
+ internal void MarkClosed()
+ {
+ SetClosed();
+ DeregisterConsumer();
+ }
+
+ public string QueueName
+ {
+ get { return _queueName; }
+ }
+
+ /// <summary>
+ /// Acknowledge up to last message delivered (if any). Used when commiting.
+ /// </summary>
+ internal void AcknowledgeDelivered()
+ {
+ foreach (long tag in _receivedDeliveryTags)
+ {
+ _channel.AcknowledgeMessage((ulong)tag, false);
+ }
+
+ _receivedDeliveryTags.Clear();
+ }
+
+ internal void RejectUnacked()
+ {
+ foreach (long tag in _receivedDeliveryTags)
+ {
+ _channel.RejectMessage((ulong)tag, true);
+ }
+
+ _receivedDeliveryTags.Clear();
+ }
+
+ private void PreDeliver(AbstractQmsMessage msg)
+ {
+ switch (AcknowledgeMode)
+ {
+ case AcknowledgeMode.PreAcknowledge:
+ _channel.AcknowledgeMessage((ulong)msg.DeliveryTag, false);
+ break;
+
+ case AcknowledgeMode.ClientAcknowledge:
+ // We set the session so that when the user calls acknowledge() it can call the method on session
+ // to send out the appropriate frame.
+ //msg.setAMQSession(_session);
+ msg.Channel = _channel;
+ break;
+ }
+ }
+
+ private void PostDeliver(IMessage m)
+ {
+ AbstractQmsMessage msg = (AbstractQmsMessage) m;
+ switch (AcknowledgeMode)
+ {
+ case AcknowledgeMode.DupsOkAcknowledge:
+ if (++_outstanding >= _prefetchHigh)
+ {
+ _dups_ok_acknowledge_send = true;
+ }
+ if (_outstanding <= _prefetchLow)
+ {
+ _dups_ok_acknowledge_send = false;
+ }
+ if (_dups_ok_acknowledge_send)
+ {
+ _channel.AcknowledgeMessage((ulong)msg.DeliveryTag, true);
+ }
+ break;
+
+ case AcknowledgeMode.AutoAcknowledge:
+ _channel.AcknowledgeMessage((ulong)msg.DeliveryTag, true);
+ break;
+
+ case AcknowledgeMode.SessionTransacted:
+ _receivedDeliveryTags.AddLast(msg.DeliveryTag);
+ break;
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/BasicMessageProducer.cs b/dotnet/Qpid.Client/Client/BasicMessageProducer.cs
new file mode 100644
index 0000000000..f33afc452e
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/BasicMessageProducer.cs
@@ -0,0 +1,405 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client
+{
+ public class BasicMessageProducer : Closeable, IMessagePublisher
+ {
+ protected readonly ILog _logger = LogManager.GetLogger(typeof(BasicMessageProducer));
+
+ /// <summary>
+ /// If true, messages will not get a timestamp.
+ /// </summary>
+ private bool _disableTimestamps;
+
+ /// <summary>
+ /// Priority of messages created by this producer.
+ /// </summary>
+ private int _messagePriority;
+
+ /// <summary>
+ /// Time to live of messages. Specified in milliseconds but AMQ has 1 second resolution.
+ /// </summary>
+ private long _timeToLive;
+
+ /// <summary>
+ /// Delivery mode used for this producer.
+ /// </summary>
+ private DeliveryMode _deliveryMode;
+
+ private bool _immediate;
+ private bool _mandatory;
+
+ string _exchangeName;
+ string _routingKey;
+
+ /// <summary>
+ /// Default encoding used for messages produced by this producer.
+ /// </summary>
+ private string _encoding;
+
+ /// <summary>
+ /// Default encoding used for message produced by this producer.
+ /// </summary>
+ private string _mimeType;
+
+ /// <summary>
+ /// True if this producer was created from a transacted session
+ /// </summary>
+ private bool _transacted;
+
+ private ushort _channelId;
+
+ /// <summary>
+ /// This is an id generated by the session and is used to tie individual producers to the session. This means we
+ /// can deregister a producer with the session when the producer is closed. We need to be able to tie producers
+ /// to the session so that when an error is propagated to the session it can close the producer (meaning that
+ /// a client that happens to hold onto a producer reference will get an error if he tries to use it subsequently).
+ /// </summary>
+ private long _producerId;
+
+ /// <summary>
+ /// The session used to create this producer
+ /// </summary>
+ private AmqChannel _channel;
+
+ public BasicMessageProducer(string exchangeName, string routingKey,
+ bool transacted,
+ ushort channelId,
+ AmqChannel channel,
+ long producerId,
+ DeliveryMode deliveryMode,
+ long timeToLive,
+ bool immediate,
+ bool mandatory,
+ int priority)
+ {
+ _exchangeName = exchangeName;
+ _routingKey = routingKey;
+ _transacted = transacted;
+ _channelId = channelId;
+ _channel = channel;
+ _producerId = producerId;
+ _deliveryMode = deliveryMode;
+ _timeToLive = timeToLive;
+ _immediate = immediate;
+ _mandatory = mandatory;
+ _messagePriority = priority;
+
+ _channel.RegisterProducer(producerId, this);
+ }
+
+
+ #region IMessagePublisher Members
+
+ public DeliveryMode DeliveryMode
+ {
+ get
+ {
+ CheckNotClosed();
+ return _deliveryMode;
+ }
+ set
+ {
+ CheckNotClosed();
+ _deliveryMode = value;
+ }
+ }
+
+ public string ExchangeName
+ {
+ get { return _exchangeName; }
+ }
+
+ public string RoutingKey
+ {
+ get { return _routingKey; }
+ }
+
+ public bool DisableMessageID
+ {
+ get
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ set
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+
+ public bool DisableMessageTimestamp
+ {
+ get
+ {
+ CheckNotClosed();
+ return _disableTimestamps;
+ }
+ set
+ {
+ CheckNotClosed();
+ _disableTimestamps = value;
+ }
+ }
+
+ public int Priority
+ {
+ get
+ {
+ CheckNotClosed();
+ return _messagePriority;
+ }
+ set
+ {
+ CheckNotClosed();
+ if ( value < 0 || value > 9 )
+ {
+ throw new ArgumentOutOfRangeException("Priority of " + value + " is illegal. Value must be in range 0 to 9");
+ }
+ _messagePriority = value;
+ }
+ }
+
+ public override void Close()
+ {
+ _logger.Debug("Closing producer " + this);
+ Interlocked.Exchange(ref _closed, CLOSED);
+ _channel.DeregisterProducer(_producerId);
+ }
+
+ public void Send(IMessage msg, DeliveryMode deliveryMode, int priority, long timeToLive)
+ {
+ CheckNotClosed();
+ SendImpl(
+ _exchangeName,
+ _routingKey,
+ (AbstractQmsMessage)msg,
+ deliveryMode,
+ priority,
+ (uint)timeToLive,
+ _mandatory,
+ _immediate
+ );
+ }
+
+ public void Send(IMessage msg)
+ {
+ CheckNotClosed();
+ SendImpl(
+ _exchangeName,
+ _routingKey,
+ (AbstractQmsMessage)msg,
+ _deliveryMode,
+ _messagePriority,
+ (uint)_timeToLive,
+ _mandatory,
+ _immediate
+ );
+ }
+
+ // This is a short-term hack (knowing that this code will be re-vamped sometime soon)
+ // to facilitate publishing messages to potentially non-existent recipients.
+ public void Send(IMessage msg, bool mandatory)
+ {
+ CheckNotClosed();
+ SendImpl(
+ _exchangeName,
+ _routingKey,
+ (AbstractQmsMessage)msg,
+ _deliveryMode,
+ _messagePriority,
+ (uint)_timeToLive,
+ mandatory,
+ _immediate
+ );
+ }
+
+ public long TimeToLive
+ {
+ get
+ {
+ CheckNotClosed();
+ return _timeToLive;
+ }
+ set
+ {
+ CheckNotClosed();
+ if ( value < 0 )
+ {
+ throw new ArgumentOutOfRangeException("Time to live must be non-negative - supplied value was " + value);
+ }
+ _timeToLive = value;
+ }
+ }
+
+ #endregion
+
+ public string MimeType
+ {
+ get
+ {
+ CheckNotClosed();
+ return _mimeType;
+ }
+ set
+ {
+ CheckNotClosed();
+ _mimeType = value;
+ }
+ }
+
+ public string Encoding
+ {
+ get
+ {
+ CheckNotClosed();
+ return _encoding;
+ }
+ set
+ {
+ CheckNotClosed();
+ _encoding = value;
+ }
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #region Message Publishing
+
+ private void SendImpl(string exchangeName, string routingKey, AbstractQmsMessage message, DeliveryMode deliveryMode, int priority, uint timeToLive, bool mandatory, bool immediate)
+ {
+ // todo: handle session access ticket
+ AMQFrame publishFrame = BasicPublishBody.CreateAMQFrame(
+ _channel.ChannelId, 0, exchangeName,
+ routingKey, mandatory, immediate
+ );
+
+ // fix message properties
+ if ( !_disableTimestamps )
+ {
+ message.Timestamp = DateTime.UtcNow.Ticks;
+ if (timeToLive != 0)
+ {
+ message.Expiration = message.Timestamp + timeToLive;
+ }
+ } else
+ {
+ message.Expiration = 0;
+ }
+ message.DeliveryMode = deliveryMode;
+ message.Priority = (byte)priority;
+
+ ByteBuffer payload = message.Data;
+ int payloadLength = payload.Limit;
+
+ ContentBody[] contentBodies = CreateContentBodies(payload);
+ AMQFrame[] frames = new AMQFrame[2 + contentBodies.Length];
+ for ( int i = 0; i < contentBodies.Length; i++ )
+ {
+ frames[2 + i] = ContentBody.CreateAMQFrame(_channelId, contentBodies[i]);
+ }
+ if ( contentBodies.Length > 0 && _logger.IsDebugEnabled )
+ {
+ _logger.Debug(string.Format("Sending content body frames to {{exchangeName={0} routingKey={1}}}", exchangeName, routingKey));
+ }
+
+ // weight argument of zero indicates no child content headers, just bodies
+ AMQFrame contentHeaderFrame = ContentHeaderBody.CreateAMQFrame(
+ _channelId, AmqChannel.BASIC_CONTENT_TYPE, 0,
+ message.ContentHeaderProperties, (uint)payloadLength
+ );
+ if ( _logger.IsDebugEnabled )
+ {
+ _logger.Debug(string.Format("Sending content header frame to {{exchangeName={0} routingKey={1}}}", exchangeName, routingKey));
+ }
+
+ frames[0] = publishFrame;
+ frames[1] = contentHeaderFrame;
+ CompositeAMQDataBlock compositeFrame = new CompositeAMQDataBlock(frames);
+
+ lock ( _channel.Connection.FailoverMutex )
+ {
+ _channel.Connection.ProtocolWriter.Write(compositeFrame);
+ }
+ }
+
+
+ /// <summary>
+ /// Create content bodies. This will split a large message into numerous bodies depending on the negotiated
+ /// maximum frame size.
+ /// </summary>
+ /// <param name="payload"></param>
+ /// <returns>return the array of content bodies</returns>
+ private ContentBody[] CreateContentBodies(ByteBuffer payload)
+ {
+ if ( payload == null )
+ {
+ return null;
+ } else if ( payload.Remaining == 0 )
+ {
+ return new ContentBody[0];
+ }
+ // we substract one from the total frame maximum size to account for the end of frame marker in a body frame
+ // (0xCE byte).
+ int framePayloadMax = (int)(_channel.Connection.MaximumFrameSize - 1);
+ int frameCount = CalculateContentBodyFrames(payload);
+ ContentBody[] bodies = new ContentBody[frameCount];
+ for ( int i = 0; i < frameCount; i++ )
+ {
+ int length = (payload.Remaining >= framePayloadMax)
+ ? framePayloadMax : payload.Remaining;
+ bodies[i] = new ContentBody(payload, (uint)length);
+ }
+ return bodies;
+ }
+
+ private int CalculateContentBodyFrames(ByteBuffer payload)
+ {
+ // we substract one from the total frame maximum size to account
+ // for the end of frame marker in a body frame
+ // (0xCE byte).
+ int frameCount;
+ if ( (payload == null) || (payload.Remaining == 0) )
+ {
+ frameCount = 0;
+ } else
+ {
+ int dataLength = payload.Remaining;
+ int framePayloadMax = (int)_channel.Connection.MaximumFrameSize - 1;
+ int lastFrame = ((dataLength % framePayloadMax) > 0) ? 1 : 0;
+ frameCount = (int)(dataLength / framePayloadMax) + lastFrame;
+ }
+
+ return frameCount;
+ }
+ #endregion // Message Publishing
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Closeable.cs b/dotnet/Qpid.Client/Client/Closeable.cs
new file mode 100644
index 0000000000..b9664ccea3
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Closeable.cs
@@ -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.
+ *
+ */
+using System;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client
+{
+ /// <summary>Closeable provides monitoring of the state of a closeable resource; whether it is open or closed. It also provides a lock on which
+ /// attempts to close the resource from multiple threads can be coordinated.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Close (and clean-up) a resource.
+ /// <tr><td> Monitor the state of a closeable resource.
+ /// <tr><td> Synchronous attempts to close resource from concurrent threads.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks>Poor encapsulation of the close lock. Better to completely hide the implementation, such that there is a method, e.g., DoSingleClose,
+ /// that sub-classes implement. Guaranteed to only be called by one thread at once, and iff the object is not already closed. That is, multiple
+ /// simultaneous closes will result in a single call to the real close method. Put the wait and condition checking loop in this base class.
+ /// </remarks>
+ public abstract class Closeable : ICloseable
+ {
+ /// <summary> Constant representing the closed state. </summary>
+ protected const int CLOSED = 1;
+
+ /// <summary> Constant representing the open state. </summary>
+ protected const int NOT_CLOSED = 2;
+
+ /// <summary> Used to ensure orderly closing of the object. </summary>
+ protected readonly object _closingLock = new object();
+
+ /// <summary> Indicates the state of this resource; open or closed. </summary>
+ protected int _closed = NOT_CLOSED;
+
+ /// <summary>
+ /// Checks the not closed.
+ /// </summary>
+ ///
+ /// <remarks>Don't like check methods that throw exceptions. a) it can come as a surprise without checked exceptions, b) it limits the
+ /// callers choice, if the caller would prefer a boolean, c) it is not side-effect free programming, where such could be used. Get rid
+ /// of this and replace with boolean.</remarks>
+ protected void CheckNotClosed()
+ {
+ if (_closed == CLOSED)
+ {
+ throw new InvalidOperationException("Object " + ToString() + " has been closed");
+ }
+ }
+
+ /// <summary>Indicates whether this resource is closed.</summary>
+ /// <value><c>true</c> if closed; otherwise, <c>false</c>.</value>
+ public bool Closed
+ {
+ get
+ {
+ return _closed == CLOSED;
+ }
+ }
+
+ /// <summary> Close this resource. </summary>
+ public abstract void Close();
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Configuration/AuthenticationConfigurationSectionHandler.cs b/dotnet/Qpid.Client/Client/Configuration/AuthenticationConfigurationSectionHandler.cs
new file mode 100644
index 0000000000..8d289fa956
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Configuration/AuthenticationConfigurationSectionHandler.cs
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Configuration;
+using System.Text;
+
+using Apache.Qpid.Client.Security;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Client.Configuration
+{
+ public class AuthenticationConfigurationSectionHandler
+ : IConfigurationSectionHandler
+ {
+
+ public object Create(object parent, object configContext, System.Xml.XmlNode section)
+ {
+ NameValueSectionHandler handler = new NameValueSectionHandler();
+ OrderedHashTable schemes = new OrderedHashTable();
+
+ NameValueCollection options = (NameValueCollection)
+ handler.Create(parent, configContext, section);
+
+ if ( options != null )
+ {
+ foreach ( string key in options.Keys )
+ {
+ Type type = Type.GetType(options[key]);
+ if ( type == null )
+ throw new ConfigurationException(string.Format("Type '{0}' not found", key));
+ if ( !typeof(IAMQCallbackHandler).IsAssignableFrom(type) )
+ throw new ConfigurationException(string.Format("Type '{0}' does not implement IAMQCallbackHandler", key));
+
+ schemes.Add(key, type);
+ }
+ }
+
+ return schemes;
+ }
+
+ } // class AuthenticationConfigurationSectionHandler
+
+ public class OrderedHashTable : Hashtable
+ {
+ private ArrayList _keys = new ArrayList();
+
+ public IList OrderedKeys
+ {
+ get { return _keys; }
+ }
+
+ public override void Add(object key, object value)
+ {
+ base.Add(key, value);
+ _keys.Add(key);
+ }
+ public override void Remove(object key)
+ {
+ base.Remove(key);
+ _keys.Remove(key);
+ }
+ }
+} // namespace Apache.Qpid.Client.Configuration
diff --git a/dotnet/Qpid.Client/Client/ConnectionTuneParameters.cs b/dotnet/Qpid.Client/Client/ConnectionTuneParameters.cs
new file mode 100644
index 0000000000..b21486bfa8
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/ConnectionTuneParameters.cs
@@ -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.
+ *
+ */
+namespace Apache.Qpid.Client
+{
+ public class ConnectionTuneParameters
+ {
+ private uint _frameMax;
+
+ private ushort _channelMax;
+
+ private uint _hearbeat;
+
+ private uint _txnLimit;
+
+ public uint FrameMax
+ {
+ get
+ {
+ return _frameMax;
+ }
+ set
+ {
+ _frameMax = value;
+ }
+ }
+
+ public ushort ChannelMax
+ {
+ get
+ {
+ return _channelMax;
+ }
+ set
+ {
+ _channelMax = value;
+ }
+ }
+
+ public uint Heartbeat
+ {
+ get
+ {
+ return _hearbeat;
+ }
+ set
+ {
+ _hearbeat = value;
+ }
+ }
+
+ public uint TxnLimit
+ {
+ get
+ {
+ return _txnLimit;
+ }
+ set
+ {
+ _txnLimit = value;
+ }
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Failover/FailoverException.cs b/dotnet/Qpid.Client/Client/Failover/FailoverException.cs
new file mode 100644
index 0000000000..7013746414
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Failover/FailoverException.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Client.Failover
+{
+ /// <summary>
+ /// This exception is thrown when failover is taking place and we need to let other
+ /// parts of the client know about this.
+ /// </summary>
+ [Serializable]
+ class FailoverException : Exception
+ {
+ public FailoverException(String message) : base(message)
+ {
+ }
+
+ protected FailoverException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Failover/FailoverHandler.cs b/dotnet/Qpid.Client/Client/Failover/FailoverHandler.cs
new file mode 100644
index 0000000000..83c69b7d25
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Failover/FailoverHandler.cs
@@ -0,0 +1,175 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+
+namespace Apache.Qpid.Client.Failover
+{
+ public class FailoverHandler
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(FailoverHandler));
+
+ private AMQConnection _connection;
+
+ /**
+ * Used where forcing the failover host
+ */
+ private String _host;
+
+ /**
+ * Used where forcing the failover port
+ */
+ private int _port;
+
+ public FailoverHandler(AMQConnection connection)
+ {
+ _connection = connection;
+ }
+
+ public void Run()
+ {
+ if (Thread.CurrentThread.IsBackground)
+ {
+ throw new InvalidOperationException("FailoverHandler must Run on a non-background thread.");
+ }
+
+ AMQProtocolListener pl = _connection.ProtocolListener;
+ pl.FailoverLatch = new ManualResetEvent(false);
+
+ // We wake up listeners. If they can handle failover, they will extend the
+ // FailoverSupport class and will in turn block on the latch until failover
+ // has completed before retrying the operation
+ _connection.ProtocolListener.PropagateExceptionToWaiters(new FailoverException("Failing over about to start"));
+
+ // Since failover impacts several structures we protect them all with a single mutex. These structures
+ // are also in child objects of the connection. This allows us to manipulate them without affecting
+ // client code which runs in a separate thread.
+ lock (_connection.FailoverMutex)
+ {
+ _log.Info("Starting failover process");
+
+ // We switch in a new state manager temporarily so that the interaction to get to the "connection open"
+ // state works, without us having to terminate any existing "state waiters". We could theoretically
+ // have a state waiter waiting until the connection is closed for some reason. Or in future we may have
+ // a slightly more complex state model therefore I felt it was worthwhile doing this.
+ AMQStateManager existingStateManager = _connection.ProtocolListener.StateManager;
+ _connection.ProtocolListener.StateManager = new AMQStateManager();
+ if (!_connection.FirePreFailover(_host != null))
+ {
+ _connection.ProtocolListener.StateManager = existingStateManager;
+ if (_host != null)
+ {
+ _connection.ExceptionReceived(new AMQDisconnectedException("Redirect was vetoed by client"));
+ }
+ else
+ {
+ _connection.ExceptionReceived(new AMQDisconnectedException("Failover was vetoed by client"));
+ }
+ pl.FailoverLatch.Set();
+ pl.FailoverLatch = null;
+ return;
+ }
+ bool failoverSucceeded;
+ // when host is non null we have a specified failover host otherwise we all the client to cycle through
+ // all specified hosts
+
+ // if _host has value then we are performing a redirect.
+ if (_host != null)
+ {
+ // todo: fix SSL support!
+ failoverSucceeded = _connection.AttemptReconnection(_host, _port, null);
+ }
+ else
+ {
+ failoverSucceeded = _connection.AttemptReconnection();
+ }
+
+ // XXX: at this point it appears that we are going to set StateManager to existingStateManager in
+ // XXX: both paths of control.
+ if (!failoverSucceeded)
+ {
+ _connection.ProtocolListener.StateManager = existingStateManager;
+ _connection.ExceptionReceived(
+ new AMQDisconnectedException("Server closed connection and no failover " +
+ "was successful"));
+ }
+ else
+ {
+ _connection.ProtocolListener.StateManager = existingStateManager;
+ try
+ {
+ if (_connection.FirePreResubscribe())
+ {
+ _log.Info("Resubscribing on new connection");
+ _connection.ResubscribeChannels();
+ }
+ else
+ {
+ _log.Info("Client vetoed automatic resubscription");
+ }
+ _connection.FireFailoverComplete();
+ _connection.ProtocolListener.FailoverState = FailoverState.NOT_STARTED;
+ _log.Info("Connection failover completed successfully");
+ }
+ catch (Exception e)
+ {
+ _log.Info("Failover process failed - exception being propagated by protocol handler");
+ _connection.ProtocolListener.FailoverState = FailoverState.FAILED;
+ try
+ {
+ _connection.ProtocolListener.OnException(e);
+ }
+ catch (Exception ex)
+ {
+ _log.Error("Error notifying protocol session of error: " + ex, ex);
+ }
+ }
+ }
+ }
+ pl.FailoverLatch.Set();
+ }
+
+ public String getHost()
+ {
+ return _host;
+ }
+
+ public void setHost(String host)
+ {
+ _host = host;
+ }
+
+ public int getPort()
+ {
+ return _port;
+ }
+
+ public void setPort(int port)
+ {
+ _port = port;
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Failover/FailoverState.cs b/dotnet/Qpid.Client/Client/Failover/FailoverState.cs
new file mode 100644
index 0000000000..3058cdcd69
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Failover/FailoverState.cs
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Client.Failover
+{
+ /// <summary>
+ /// Enumeration of failover states. Used to handle failover from within AMQProtocolHandler where MINA events need to be
+ /// dealt with and can happen during failover.
+ /// </summary>
+ enum FailoverState
+ {
+ NOT_STARTED, IN_PROGRESS, FAILED
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Failover/FailoverSupport.cs b/dotnet/Qpid.Client/Client/Failover/FailoverSupport.cs
new file mode 100644
index 0000000000..afa5301f39
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Failover/FailoverSupport.cs
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+namespace Apache.Qpid.Client.Failover
+{
+ public abstract class FailoverSupport
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(FailoverSupport));
+
+ public object execute(AMQConnection con)
+ {
+ // We wait until we are not in the middle of failover before acquiring the mutex and then proceeding.
+ // Any method that can potentially block for any reason should use this class so that deadlock will not
+ // occur. The FailoverException is propagated by the AMQProtocolHandler to any listeners (e.g. frame listeners)
+ // that might be causing a block. When that happens, the exception is caught here and the mutex is released
+ // before waiting for the failover to complete (either successfully or unsuccessfully).
+ while (true)
+ {
+ con.ProtocolListener.BlockUntilNotFailingOver();
+ lock (con.FailoverMutex)
+ {
+ try
+ {
+ return operation();
+ }
+ catch (FailoverException e)
+ {
+ _log.Info("Failover exception caught during operation", e);
+ }
+ }
+ }
+ }
+
+ protected abstract object operation();
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/BasicDeliverMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/BasicDeliverMethodHandler.cs
new file mode 100644
index 0000000000..def1e78e8c
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/BasicDeliverMethodHandler.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class BasicDeliverMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(BasicDeliverMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ UnprocessedMessage msg = new UnprocessedMessage();
+ msg.DeliverBody = (BasicDeliverBody) evt.Method;
+ msg.ChannelId = evt.ChannelId;
+ _logger.Debug("New JmsDeliver method received");
+ evt.ProtocolSession.UnprocessedMessageReceived(msg);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/BasicReturnMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/BasicReturnMethodHandler.cs
new file mode 100644
index 0000000000..f413dfc9c6
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/BasicReturnMethodHandler.cs
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class BasicReturnMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(BasicReturnMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ _logger.Debug("New Basic.Return method received");
+ UnprocessedMessage msg = new UnprocessedMessage();
+ msg.DeliverBody = null;
+ msg.BounceBody = (BasicReturnBody) evt.Method;
+ msg.ChannelId = evt.ChannelId;
+
+ evt.ProtocolSession.UnprocessedMessageReceived(msg);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/ChannelCloseMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ChannelCloseMethodHandler.cs
new file mode 100644
index 0000000000..9ed09a0d01
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ChannelCloseMethodHandler.cs
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Protocol;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ChannelCloseMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(ChannelCloseMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ _logger.Debug("ChannelClose method received");
+ ChannelCloseBody method = (ChannelCloseBody) evt.Method;
+
+ int errorCode = method.ReplyCode;
+ string reason = method.ReplyText;
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Channel close reply code: " + errorCode + ", reason: " + reason);
+ }
+
+ AMQFrame frame = ChannelCloseOkBody.CreateAMQFrame(evt.ChannelId);
+ evt.ProtocolSession.WriteFrame(frame);
+
+ if ( errorCode != AMQConstant.REPLY_SUCCESS.Code )
+ {
+ _logger.Debug("Channel close received with errorCode " + errorCode + ", throwing exception");
+ if ( errorCode == AMQConstant.NO_CONSUMERS.Code )
+ throw new AMQNoConsumersException(reason);
+ if ( errorCode == AMQConstant.NO_ROUTE.Code )
+ throw new AMQNoRouteException(reason);
+ if ( errorCode == AMQConstant.INVALID_ARGUMENT.Code )
+ throw new AMQInvalidArgumentException(reason);
+ if ( errorCode == AMQConstant.INVALID_ROUTING_KEY.Code )
+ throw new AMQInvalidRoutingKeyException(reason);
+ // any other
+ throw new AMQChannelClosedException(errorCode, "Error: " + reason);
+ }
+ evt.ProtocolSession.ChannelClosed(evt.ChannelId, errorCode, reason);
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionCloseMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionCloseMethodHandler.cs
new file mode 100644
index 0000000000..66cff3bc65
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionCloseMethodHandler.cs
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionCloseMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(ConnectionCloseMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ _logger.Debug("ConnectionClose frame received");
+ ConnectionCloseBody method = (ConnectionCloseBody) evt.Method;
+
+ int errorCode = method.ReplyCode;
+ String reason = method.ReplyText;
+
+ // send CloseOK
+ evt.ProtocolSession.WriteFrame(ConnectionCloseOkBody.CreateAMQFrame(evt.ChannelId));
+
+ if ( errorCode != AMQConstant.REPLY_SUCCESS.Code )
+ {
+ if ( errorCode == AMQConstant.NOT_ALLOWED.Code )
+ {
+ _logger.Info("Authentication Error: " + Thread.CurrentThread.Name);
+ evt.ProtocolSession.CloseProtocolSession();
+
+ //todo this is a bit of a fudge (could be conssidered such as each new connection needs a new state manager or at least a fresh state.
+ stateManager.ChangeState(AMQState.CONNECTION_NOT_STARTED);
+
+ throw new AMQAuthenticationException(errorCode, reason);
+ } else
+ {
+ _logger.Info("Connection close received with error code " + errorCode);
+ throw new AMQConnectionClosedException(errorCode, "Error: " + reason);
+ }
+ }
+ // this actually closes the connection in the case where it is not an error.
+ evt.ProtocolSession.CloseProtocolSession();
+ stateManager.ChangeState(AMQState.CONNECTION_CLOSED);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionCloseOkHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionCloseOkHandler.cs
new file mode 100644
index 0000000000..038da15731
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionCloseOkHandler.cs
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionCloseOkHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(ConnectionCloseOkHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ _logger.Debug("ConnectionCloseOk frame received");
+// ConnectionCloseOkBody method = (ConnectionCloseOkBody)evt.Method;
+ stateManager.ChangeState(AMQState.CONNECTION_CLOSED);
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionOpenOkMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionOpenOkMethodHandler.cs
new file mode 100644
index 0000000000..a12e4ead60
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionOpenOkMethodHandler.cs
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionOpenOkMethodHandler : IStateAwareMethodListener
+ {
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ stateManager.ChangeState(AMQState.CONNECTION_OPEN);
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionRedirectMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionRedirectMethodHandler.cs
new file mode 100644
index 0000000000..08cc580b17
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionRedirectMethodHandler.cs
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionRedirectMethodHandler : IStateAwareMethodListener
+ {
+// private static readonly ILog _logger = LogManager.GetLogger(typeof(ConnectionRedirectMethodHandler));
+
+ private const int DEFAULT_REDIRECT_PORT = 5672;
+
+ private static ConnectionRedirectMethodHandler _handler = new ConnectionRedirectMethodHandler();
+
+ public static ConnectionRedirectMethodHandler GetInstance()
+ {
+ return _handler;
+ }
+
+ private ConnectionRedirectMethodHandler()
+ {
+ }
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ /*_logger.Info("ConnectionRedirect frame received");
+ ConnectionRedirectBody method = (ConnectionRedirectBody) evt.Method;
+
+ // the host is in the form hostname:port with the port being optional
+ int portIndex = method.Host.IndexOf(':');
+ String host;
+ int port;
+ if (portIndex == -1)
+ {
+ host = method.Host;
+ port = DEFAULT_REDIRECT_PORT;
+ }
+ else
+ {
+ host = method.Host.Substring(0, portIndex);
+ port = Int32.Parse(method.Host.Substring(portIndex + 1));
+ }
+ evt.ProtocolSession.Failover(host, port);*/
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionSecureMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionSecureMethodHandler.cs
new file mode 100644
index 0000000000..9333d4d0a6
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionSecureMethodHandler.cs
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Sasl;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionSecureMethodHandler : IStateAwareMethodListener
+ {
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ ISaslClient saslClient = evt.ProtocolSession.SaslClient;
+ if ( saslClient == null )
+ {
+ throw new AMQException("No SASL client set up - cannot proceed with authentication");
+ }
+
+
+ ConnectionSecureBody body = (ConnectionSecureBody)evt.Method;
+
+ try
+ {
+ // Evaluate server challenge
+ byte[] response = saslClient.EvaluateChallenge(body.Challenge);
+ // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
+ // TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
+ // Be aware of possible changes to parameter order as versions change.
+ AMQFrame responseFrame = ConnectionSecureOkBody.CreateAMQFrame(
+ evt.ChannelId, response);
+ evt.ProtocolSession.WriteFrame(responseFrame);
+ } catch ( SaslException e )
+ {
+ throw new AMQException("Error processing SASL challenge: " + e, e);
+ }
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs
new file mode 100644
index 0000000000..c54662286b
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionStartMethodHandler.cs
@@ -0,0 +1,144 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.Security;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Sasl;
+
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionStartMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(ConnectionStartMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ ConnectionStartBody body = (ConnectionStartBody) evt.Method;
+ AMQProtocolSession ps = evt.ProtocolSession;
+
+ try
+ {
+ if ( body.Mechanisms == null )
+ {
+ throw new AMQException("mechanism not specified in ConnectionStart method frame");
+ }
+ string mechanisms = Encoding.UTF8.GetString(body.Mechanisms);
+ string selectedMechanism = ChooseMechanism(mechanisms);
+ if ( selectedMechanism == null )
+ {
+ throw new AMQException("No supported security mechanism found, passed: " + mechanisms);
+ }
+
+ byte[] saslResponse = DoAuthentication(selectedMechanism, ps);
+
+ if (body.Locales == null)
+ {
+ throw new AMQException("Locales is not defined in Connection Start method");
+ }
+ string allLocales = Encoding.ASCII.GetString(body.Locales);
+ string[] locales = allLocales.Split(' ');
+ string selectedLocale;
+ if (locales != null && locales.Length > 0)
+ {
+ selectedLocale = locales[0];
+ }
+ else
+ {
+ throw new AMQException("No locales sent from server, passed: " + locales);
+ }
+
+ stateManager.ChangeState(AMQState.CONNECTION_NOT_TUNED);
+ FieldTable clientProperties = new FieldTable();
+ clientProperties["product"] = "Apache.Qpid.NET";
+ clientProperties["version"] = "1.0";
+ clientProperties["platform"] = GetFullSystemInfo();
+ clientProperties["instance"] = ps.ClientID;
+ AMQFrame frame = ConnectionStartOkBody.CreateAMQFrame(
+ evt.ChannelId, clientProperties, selectedMechanism,
+ saslResponse, selectedLocale);
+ ps.WriteFrame(frame);
+ }
+ catch (Exception e)
+ {
+ throw new AMQException(_log, "Unable to decode data: " + e, e);
+ }
+ }
+
+ private string GetFullSystemInfo()
+ {
+ StringBuilder sysInfo = new StringBuilder();
+ // check if we're running on mono or .net
+ Type monoRuntime = Type.GetType("Mono.Runtime");
+ if ( monoRuntime != null )
+ sysInfo.Append("Mono");
+ else
+ sysInfo.Append(".NET");
+ sysInfo.Append(" ").Append(Environment.Version);
+ sysInfo.Append(", ").Append(Environment.OSVersion);
+ return sysInfo.ToString();
+ }
+
+ private string ChooseMechanism(string mechanisms)
+ {
+ return CallbackHandlerRegistry.Instance.ChooseMechanism(mechanisms);
+ }
+
+ private byte[] DoAuthentication(string selectedMechanism, AMQProtocolSession ps)
+ {
+ ISaslClient saslClient = Sasl.Sasl.CreateClient(
+ new string[] { selectedMechanism }, null, "AMQP", "localhost",
+ new Hashtable(), CreateCallbackHandler(selectedMechanism, ps)
+ );
+ if ( saslClient == null )
+ {
+ throw new AMQException("Client SASL configuration error: no SaslClient could be created for mechanism " +
+ selectedMechanism);
+ }
+ ps.SaslClient = saslClient;
+ try
+ {
+ return saslClient.HasInitialResponse ?
+ saslClient.EvaluateChallenge(new byte[0]) : null;
+ } catch ( Exception ex )
+ {
+ ps.SaslClient = null;
+ throw new AMQException("Unable to create SASL client", ex);
+ }
+ }
+
+ private IAMQCallbackHandler CreateCallbackHandler(string mechanism, AMQProtocolSession session)
+ {
+ Type type = CallbackHandlerRegistry.Instance.GetCallbackHandler(mechanism);
+ IAMQCallbackHandler handler =
+ (IAMQCallbackHandler)Activator.CreateInstance(type);
+ if ( handler == null )
+ throw new AMQException("Unable to create callback handler: " + mechanism);
+ handler.Initialize(session);
+ return handler;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/ConnectionTuneMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/ConnectionTuneMethodHandler.cs
new file mode 100644
index 0000000000..15a1d908b7
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/ConnectionTuneMethodHandler.cs
@@ -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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class ConnectionTuneMethodHandler : IStateAwareMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(ConnectionTuneMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ _logger.Debug("ConnectionTune frame received");
+ ConnectionTuneBody frame = (ConnectionTuneBody) evt.Method;
+ AMQProtocolSession session = evt.ProtocolSession;
+
+ ConnectionTuneParameters parameters = session.ConnectionTuneParameters;
+ if (parameters == null)
+ {
+ parameters = new ConnectionTuneParameters();
+ }
+
+ _logger.Debug(String.Format("ConnectionTune.heartbeat = {0}.", frame.Heartbeat));
+
+ parameters.FrameMax = frame.FrameMax;
+ parameters.Heartbeat = frame.Heartbeat;
+ session.ConnectionTuneParameters = parameters;
+
+ stateManager.ChangeState(AMQState.CONNECTION_NOT_OPENED);
+ session.WriteFrame(ConnectionTuneOkBody.CreateAMQFrame(
+ evt.ChannelId, frame.ChannelMax, frame.FrameMax, frame.Heartbeat));
+ session.WriteFrame(ConnectionOpenBody.CreateAMQFrame(
+ evt.ChannelId, session.AMQConnection.VirtualHost, null, true));
+
+ if (frame.Heartbeat > 0)
+ {
+ evt.ProtocolSession.AMQConnection.StartHeartBeatThread(frame.Heartbeat);
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/QueueDeleteOkMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/QueueDeleteOkMethodHandler.cs
new file mode 100644
index 0000000000..70aa3e1078
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/QueueDeleteOkMethodHandler.cs
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class QueueDeleteOkMethodHandler : IStateAwareMethodListener
+ {
+
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(QueueDeleteOkMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ QueueDeleteOkBody body = (QueueDeleteOkBody)evt.Method;
+ if (body != null)
+ {
+ _logger.InfoFormat("Received Queue.Delete-Ok message, message count {0}", body.MessageCount);
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Handler/QueuePurgeOkMethodHandler.cs b/dotnet/Qpid.Client/Client/Handler/QueuePurgeOkMethodHandler.cs
new file mode 100644
index 0000000000..22db70575d
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Handler/QueuePurgeOkMethodHandler.cs
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Handler
+{
+ public class QueuePurgeOkMethodHandler : IStateAwareMethodListener
+ {
+
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(QueuePurgeOkMethodHandler));
+
+ public void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt)
+ {
+ QueuePurgeOkBody body = (QueuePurgeOkBody)evt.Method;
+ if (body != null)
+ {
+ _logger.InfoFormat("Received Queue.Purge-Ok message, message count {0}", body.MessageCount);
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/AMQMessage.cs b/dotnet/Qpid.Client/Client/Message/AMQMessage.cs
new file mode 100644
index 0000000000..e58de2ab96
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/AMQMessage.cs
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class AMQMessage
+ {
+ protected IContentHeaderProperties _contentHeaderProperties;
+
+ /// <summary>
+ /// If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required
+ /// </summary>
+ protected AmqChannel _channel;
+
+ private long _deliveryTag;
+
+ public AMQMessage(IContentHeaderProperties properties, long deliveryTag)
+ {
+ _contentHeaderProperties = properties;
+ _deliveryTag = deliveryTag;
+ }
+
+ public AMQMessage(IContentHeaderProperties properties)
+ : this(properties, -1)
+ {
+ }
+
+ public long DeliveryTag
+ {
+ get { return _deliveryTag; }
+ }
+
+ public AmqChannel Channel
+ {
+ get { return _channel; }
+ set { _channel = value; }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/AMQMessageFactory.cs b/dotnet/Qpid.Client/Client/Message/AMQMessageFactory.cs
new file mode 100644
index 0000000000..f352d62c11
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/AMQMessageFactory.cs
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections;
+using Apache.Qpid.Framing;
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Message
+{
+ public abstract class AbstractQmsMessageFactory : IMessageFactory
+ {
+ public abstract AbstractQmsMessage CreateMessage(string mimeType);
+
+ private static readonly ILog _logger = LogManager.GetLogger(typeof (AbstractQmsMessageFactory));
+
+ protected abstract AbstractQmsMessage CreateMessage(long messageNbr, ByteBuffer data, ContentHeaderBody contentHeader);
+
+ protected AbstractQmsMessage CreateMessageWithBody(long messageNbr,
+ ContentHeaderBody contentHeader,
+ IList bodies)
+ {
+ ByteBuffer data;
+
+ // we optimise the non-fragmented case to avoid copying
+ if (bodies != null && bodies.Count == 1)
+ {
+ _logger.Debug("Non-fragmented message body (bodySize=" + contentHeader.BodySize +")");
+ data = ((ContentBody)bodies[0]).Payload;
+ }
+ else
+ {
+ _logger.Debug("Fragmented message body (" + bodies.Count + " frames, bodySize=" + contentHeader.BodySize + ")");
+ data = ByteBuffer.Allocate((int)contentHeader.BodySize); // XXX: Is cast a problem?
+ foreach (ContentBody body in bodies) {
+ data.Put(body.Payload);
+ //body.Payload.Release();
+ }
+
+ data.Flip();
+ }
+ _logger.Debug("Creating message from buffer with position=" + data.Position + " and remaining=" + data.Remaining);
+
+ return CreateMessage(messageNbr, data, contentHeader);
+ }
+
+ public AbstractQmsMessage CreateMessage(long messageNbr, bool redelivered,
+ ContentHeaderBody contentHeader,
+ IList bodies)
+ {
+ AbstractQmsMessage msg = CreateMessageWithBody(messageNbr, contentHeader, bodies);
+ msg.Redelivered = redelivered;
+ return msg;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs b/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs
new file mode 100644
index 0000000000..34b47137e5
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/AbstractQmsMessage.cs
@@ -0,0 +1,694 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using log4net;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Message
+{
+ public abstract class AbstractQmsMessage : AMQMessage, IMessage
+ {
+ private static ILog log = LogManager.GetLogger(typeof(AbstractQmsMessage));
+
+ protected bool _redelivered;
+
+ protected ByteBuffer _data;
+ protected bool _readableMessage = false;
+ private QpidHeaders _headers;
+
+ protected AbstractQmsMessage(ByteBuffer data)
+ : base(new BasicContentHeaderProperties())
+ {
+ Init(data);
+ }
+
+ protected AbstractQmsMessage(long deliveryTag, BasicContentHeaderProperties contentHeader, ByteBuffer data)
+ : this(contentHeader, deliveryTag)
+ {
+ Init(data);
+ }
+
+ protected AbstractQmsMessage(BasicContentHeaderProperties contentHeader, long deliveryTag) : base(contentHeader, deliveryTag)
+ {
+ Init(null);
+ }
+
+ private void Init(ByteBuffer data)
+ {
+ _data = data;
+ if ( _data != null )
+ {
+ _data.Acquire();
+ }
+ _readableMessage = (data != null);
+ if ( ContentHeaderProperties.Headers == null )
+ ContentHeaderProperties.Headers = new FieldTable();
+ _headers = new QpidHeaders(ContentHeaderProperties.Headers);
+ }
+
+ //
+ // Properties
+ //
+
+ /// <summary>
+ /// The application message identifier
+ /// </summary>
+ public string MessageId
+ {
+ get
+ {
+ if (ContentHeaderProperties.MessageId == null)
+ {
+ ContentHeaderProperties.MessageId = "ID:" + DeliveryTag;
+ }
+ return ContentHeaderProperties.MessageId;
+ }
+ set { ContentHeaderProperties.MessageId = value; }
+ }
+
+ /// <summary>
+ /// The message timestamp
+ /// </summary>
+ public long Timestamp
+ {
+ get
+ {
+ // TODO: look at ulong/long choice
+ return (long) ContentHeaderProperties.Timestamp;
+ }
+ set
+ {
+ ContentHeaderProperties.Timestamp = (ulong) value;
+ }
+ }
+
+ /// <summary>
+ /// The <see cref="CorrelationId"/> as a byte array.
+ /// </summary>
+ public byte[] CorrelationIdAsBytes
+ {
+ get { return Encoding.Default.GetBytes(ContentHeaderProperties.CorrelationId); }
+ set { ContentHeaderProperties.CorrelationId = Encoding.Default.GetString(value); }
+ }
+
+ /// <summary>
+ /// The application correlation identifier
+ /// </summary>
+ public string CorrelationId
+ {
+ get { return ContentHeaderProperties.CorrelationId; }
+ set { ContentHeaderProperties.CorrelationId = value; }
+ }
+
+ struct Dest
+ {
+ public string ExchangeName;
+ public string RoutingKey;
+
+ public Dest(string exchangeName, string routingKey)
+ {
+ ExchangeName = exchangeName;
+ RoutingKey = routingKey;
+ }
+ }
+
+ /// <summary>
+ /// Exchange name of the reply-to address
+ /// </summary>
+ public string ReplyToExchangeName
+ {
+ get
+ {
+ return ReadReplyToHeader().ExchangeName;
+ }
+ set
+ {
+ BindingURL dest = ReadReplyToHeader();
+ dest.ExchangeName = value;
+ WriteReplyToHeader(dest);
+ }
+ }
+
+ /// <summary>
+ /// Routing key of the reply-to address
+ /// </summary>
+ public string ReplyToRoutingKey
+ {
+ get
+ {
+ return ReadReplyToHeader().RoutingKey;
+ }
+ set
+ {
+ BindingURL dest = ReadReplyToHeader();
+ dest.RoutingKey = value;
+ WriteReplyToHeader(dest);
+ }
+ }
+
+ /// <summary>
+ /// Non-persistent (1) or persistent (2)
+ /// </summary>
+ public DeliveryMode DeliveryMode
+ {
+ get
+ {
+ byte b = ContentHeaderProperties.DeliveryMode;
+ switch (b)
+ {
+ case 1:
+ return DeliveryMode.NonPersistent;
+ case 2:
+ return DeliveryMode.Persistent;
+ default:
+ throw new QpidException("Illegal value for delivery mode in content header properties");
+ }
+ }
+ set
+ {
+ ContentHeaderProperties.DeliveryMode = (byte)(value==DeliveryMode.NonPersistent?1:2);
+ }
+ }
+
+ /// <summary>
+ /// True, if this is a redelivered message
+ /// </summary>
+ public bool Redelivered
+ {
+ get { return _redelivered; }
+ set { _redelivered = value; }
+ }
+
+ /// <summary>
+ /// The message type name
+ /// </summary>
+ public string Type
+ {
+ get { return ContentHeaderProperties.Type; }
+ set { ContentHeaderProperties.Type = value; }
+ }
+
+ /// <summary>
+ /// Message expiration specification
+ /// </summary>
+ public long Expiration
+ {
+ get { return ContentHeaderProperties.Expiration; }
+ set { ContentHeaderProperties.Expiration = value; }
+ }
+
+ /// <summary>
+ /// The message priority, 0 to 9
+ /// </summary>
+ public byte Priority
+ {
+ get { return ContentHeaderProperties.Priority; }
+ set { ContentHeaderProperties.Priority = (byte) value; }
+ }
+
+ /// <summary>
+ /// The MIME Content Type
+ /// </summary>
+ public string ContentType
+ {
+ get { return ContentHeaderProperties.ContentType; }
+ set { ContentHeaderProperties.ContentType = value; }
+ }
+
+ /// <summary>
+ /// The MIME Content Encoding
+ /// </summary>
+ public string ContentEncoding
+ {
+ get { return ContentHeaderProperties.Encoding; }
+ set { ContentHeaderProperties.Encoding = value; }
+ }
+
+ /// <summary>
+ /// Headers of this message
+ /// </summary>
+ public IHeaders Headers
+ {
+ get { return _headers; }
+ }
+
+ /// <summary>
+ /// The creating user id
+ /// </summary>
+ public string UserId
+ {
+ get { return ContentHeaderProperties.UserId; }
+ set { ContentHeaderProperties.UserId = value; }
+ }
+
+ /// <summary>
+ /// The creating application id
+ /// </summary>
+ public string AppId
+ {
+ get { return ContentHeaderProperties.AppId; }
+ set { ContentHeaderProperties.AppId = value; }
+ }
+
+ /// <summary>
+ /// Intra-cluster routing identifier
+ /// </summary>
+ public string ClusterId
+ {
+ get { return ContentHeaderProperties.ClusterId; }
+ set { ContentHeaderProperties.ClusterId = value; }
+ }
+
+ /// <summary>
+ /// Return the raw byte array that is used to populate the frame when sending
+ /// the message.
+ /// </summary>
+ /// <value>a byte array of message data</value>
+ public ByteBuffer Data
+ {
+ get
+ {
+ if (_data != null)
+ {
+ if (!_readableMessage)
+ {
+ _data.Flip();
+ }
+ else
+ {
+ // Make sure we rewind the data just in case any method has moved the
+ // position beyond the start.
+ _data.Rewind();
+ }
+ }
+ return _data;
+ }
+
+ set
+ {
+ _data = value;
+ }
+ }
+
+ public void Acknowledge()
+ {
+ // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
+ // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
+ if (_channel != null)
+ {
+ // we set multiple to true here since acknowledgement implies acknowledge of all count messages
+ // received on the session
+ _channel.AcknowledgeMessage((ulong)DeliveryTag, true);
+ }
+
+ }
+
+ public abstract void ClearBodyImpl();
+
+ public void ClearBody()
+ {
+ ClearBodyImpl();
+ _readableMessage = false;
+ }
+
+ /// <summary>
+ /// Get a String representation of the body of the message. Used in the
+ /// toString() method which outputs this before message properties.
+ /// </summary>
+ /// <exception cref="QpidException"></exception>
+ public abstract string ToBodyString();
+
+ public override string ToString()
+ {
+ try
+ {
+ StringBuilder buf = new StringBuilder("Body:\n");
+ buf.Append(ToBodyString());
+ buf.Append("\nQmsTimestamp: ").Append(Timestamp);
+ buf.Append("\nQmsExpiration: ").Append(Expiration);
+ buf.Append("\nQmsPriority: ").Append(Priority);
+ buf.Append("\nQmsDeliveryMode: ").Append(DeliveryMode);
+ buf.Append("\nReplyToExchangeName: ").Append(ReplyToExchangeName);
+ buf.Append("\nReplyToRoutingKey: ").Append(ReplyToRoutingKey);
+ buf.Append("\nAMQ message number: ").Append(DeliveryTag);
+ buf.Append("\nProperties:");
+ if (ContentHeaderProperties.Headers == null)
+ {
+ buf.Append("<NONE>");
+ }
+ else
+ {
+ buf.Append(Headers.ToString());
+ }
+ return buf.ToString();
+ }
+ catch (Exception e)
+ {
+ return e.ToString();
+ }
+ }
+
+ public FieldTable PopulateHeadersFromMessageProperties()
+ {
+ if (ContentHeaderProperties.Headers == null)
+ {
+ return null;
+ }
+ else
+ {
+ //
+ // We need to convert every property into a String representation
+ // Note that type information is preserved in the property name
+ //
+ FieldTable table = new FieldTable();
+ foreach (DictionaryEntry entry in ContentHeaderProperties.Headers)
+ {
+ string propertyName = (string) entry.Key;
+ if (propertyName == null)
+ {
+ continue;
+ }
+ else
+ {
+ table[propertyName] = entry.Value.ToString();
+ }
+ }
+ return table;
+ }
+ }
+
+ public BasicContentHeaderProperties ContentHeaderProperties
+ {
+ get
+ {
+ return (BasicContentHeaderProperties) _contentHeaderProperties;
+ }
+ }
+
+ protected virtual void Reset()
+ {
+ _readableMessage = true;
+ }
+
+ public bool IsReadable
+ {
+ get { return _readableMessage; }
+ }
+
+ public bool isWritable
+ {
+ get { return !_readableMessage; }
+ }
+
+ protected void CheckReadable()
+ {
+ if ( !_readableMessage )
+ {
+ throw new MessageNotReadableException("You need to call reset() to make the message readable");
+ }
+ }
+
+ /// <summary>
+ /// Decodes the replyto field if one is set.
+ ///
+ /// Splits a replyto field containing an exchange name followed by a ':', followed by a routing key into the exchange name and
+ /// routing key seperately. The exchange name may be empty in which case the empty string is returned. If the exchange name is
+ /// empty the replyto field is expected to being with ':'.
+ ///
+ /// Anyhting other than a two part replyto field sperated with a ':' will result in an exception.
+ /// </summary>
+ ///
+ /// <returns>A destination initialized to the replyto location if a replyto field was set, or an empty destination otherwise.</returns>
+ private BindingURL ReadReplyToHeader()
+ {
+ string replyToEncoding = ContentHeaderProperties.ReplyTo;
+ //log.Debug("replyToEncoding = " + replyToEncoding);
+
+ BindingURL bindingUrl = new BindingURL(replyToEncoding);
+ //log.Debug("bindingUrl = " + bindingUrl.ToString());
+
+ return bindingUrl;
+
+ //log.Info("replyToEncoding = " + replyToEncoding);
+
+// if ( replyToEncoding == null )
+// {
+// return new Dest();
+// } else
+// {
+// // Split the replyto field on a ':'
+// string[] split = replyToEncoding.Split(':');
+
+// // Ensure that the replyto field argument only consisted of two parts.
+// if ( split.Length != 2 )
+// {
+// throw new QpidException("Illegal value in ReplyTo property: " + replyToEncoding);
+// }
+
+// // Extract the exchange name and routing key from the split replyto field.
+// string exchangeName = split[0];
+
+// string[] split2 = split[1].Split('/');
+// string routingKey = split2[3];
+
+// return new Dest(exchangeName, routingKey);
+// }
+ }
+
+ private void WriteReplyToHeader(BindingURL dest)
+ {
+ string encodedDestination = string.Format("{0}:{1}", dest.ExchangeName, dest.RoutingKey);
+ ContentHeaderProperties.ReplyTo = encodedDestination;
+ }
+ }
+
+ public class BindingURL
+ {
+ public readonly static string OPTION_EXCLUSIVE = "exclusive";
+ public readonly static string OPTION_AUTODELETE = "autodelete";
+ public readonly static string OPTION_DURABLE = "durable";
+ public readonly static string OPTION_CLIENTID = "clientid";
+ public readonly static string OPTION_SUBSCRIPTION = "subscription";
+ public readonly static string OPTION_ROUTING_KEY = "routingkey";
+
+ /// <summary> Holds the undecoded URL </summary>
+ string url;
+
+ /// <summary> Holds the decoded options. </summary>
+ IDictionary options = new Hashtable();
+
+ /// <summary> Holds the decoded exchange class. </summary>
+ string exchangeClass;
+
+ /// <summary> Holds the decoded exchange name. </summary>
+ string exchangeName;
+
+ /// <summary> Holds the destination name. </summary>
+ string destination;
+
+ /// <summary> Holds the decoded queue name. </summary>
+ string queueName;
+
+ /// <summary>
+ /// The binding URL has the format:
+ /// <exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']*
+ /// </summary>
+ public BindingURL(string url)
+ {
+ this.url = url;
+ Parse();
+ }
+
+ public string Url { get { return url; } }
+
+ public string ExchangeClass
+ {
+ get { return exchangeClass; }
+ set { exchangeClass = value; }
+ }
+
+ public string ExchangeName
+ {
+ get { return exchangeName; }
+ set { exchangeName = value; }
+ }
+
+ public string QueueName
+ {
+ get { return queueName; }
+ set { queueName = value; }
+ }
+
+ public string DestinationName
+ {
+ get { return destination; }
+ set { destination = value; }
+ }
+
+ public string RoutingKey {
+ get { return (string)options[OPTION_ROUTING_KEY]; }
+ set { options[OPTION_ROUTING_KEY] = value; }
+ }
+
+ public bool ContainsOption(string key) { return options.Contains(key); }
+
+ public string ToString()
+ {
+ return "BindingURL: [ ExchangeClass = " + ExchangeClass + ", ExchangeName = " + ExchangeName + ", QueueName = " + QueueName +
+ ", DestinationName = " + DestinationName + ", RoutingKey = " + RoutingKey + " ] ";
+ }
+
+ private void Parse()
+ {
+ Uri binding = new Uri(url);
+
+ // Extract the URI scheme, this contains the exchange class. It is defaulted to the direct exchange if not specified.
+ string exchangeClass = binding.Scheme;
+
+ if (exchangeClass == null)
+ {
+ url = ExchangeNameDefaults.DIRECT_EXCHANGE_CLASS + "://" + ExchangeNameDefaults.DIRECT + "//" + url;
+ Parse();
+
+ return;
+ }
+ else
+ {
+ this.exchangeClass = exchangeClass;
+ }
+
+ // Extract the host name, this contains the exchange name. It is defaulted to the default direct exchange if not specified.
+ string exchangeName = binding.Host;
+
+ if (exchangeName == null)
+ {
+ if (exchangeClass.Equals(ExchangeNameDefaults.DIRECT_EXCHANGE_CLASS))
+ {
+ this.exchangeName = "";
+ }
+ }
+ else
+ {
+ this.exchangeName = exchangeName;
+ }
+
+ // Extract the destination and queue name.
+ if ((binding.AbsolutePath == null) || binding.AbsolutePath.Equals(""))
+ {
+ throw new UriFormatException("Destination or Queue required");
+ }
+ else
+ {
+ int slashOffset = binding.AbsolutePath.IndexOf("/", 1);
+ if (slashOffset == -1)
+ {
+ throw new UriFormatException("Destination required");
+ }
+ else
+ {
+ String path = binding.AbsolutePath;
+
+ this.destination = path.Substring(1, slashOffset - 1);
+ this.queueName = path.Substring(slashOffset + 1);
+ }
+ }
+
+ ParseOptions(options, binding.Query);
+
+ // If the routing key is not set as an option, set it to the destination name.
+ if (!ContainsOption(OPTION_ROUTING_KEY))
+ {
+ options[OPTION_ROUTING_KEY] = destination;
+ }
+ }
+
+ /// <summary>
+ /// options looks like this
+ /// brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value'
+ /// </summary>
+ public static void ParseOptions(IDictionary optionMap, string options)
+ {
+ // Check that there really are some options to parse.
+ if ((options == null) || (options.IndexOf('=') == -1))
+ {
+ return;
+ }
+
+ int optionIndex = options.IndexOf('=');
+ string option = options.Substring(0, optionIndex);
+ int length = options.Length;
+ int nestedQuotes = 0;
+
+ // Holds the index of the final "'".
+ int valueIndex = optionIndex;
+
+ // Loop over all the options.Dest
+ while ((nestedQuotes > 0) || (valueIndex < length))
+ {
+ valueIndex++;
+
+ if (valueIndex >= length)
+ {
+ break;
+ }
+
+ if (options[valueIndex] == '\'')
+ {
+ if ((valueIndex + 1) < options.Length)
+ {
+ if ((options[valueIndex + 1] == '&') ||
+ (options[valueIndex + 1] == ',') ||
+ (options[valueIndex + 1] == ';') ||
+ (options[valueIndex + 1] == '\''))
+ {
+ nestedQuotes--;
+
+ if (nestedQuotes == 0)
+ {
+ // We've found the value of an option
+ break;
+ }
+ }
+ else
+ {
+ nestedQuotes++;
+ }
+ }
+ else
+ {
+ // We are at the end of the string
+ // Check to see if we are corectly closing quotes
+ if (options[valueIndex] == '\'')
+ {
+ nestedQuotes--;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/IMessageFactory.cs b/dotnet/Qpid.Client/Client/Message/IMessageFactory.cs
new file mode 100644
index 0000000000..bed379290f
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/IMessageFactory.cs
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Message
+{
+ public interface IMessageFactory
+ {
+ /// <summary>
+ /// Create a message
+ /// </summary>
+ /// <param name="deliverTag">Delivery Tag</param>
+ /// <param name="messageNbr">Message Sequence Number</param>
+ /// <param name="redelivered">True if this is a redelivered message</param>
+ /// <param name="contentHeader">Content headers</param>
+ /// <param name="bodies">Message bodies</param>
+ /// <returns>The new message</returns>
+ /// <exception cref="QpidMessagingException">if the message cannot be created</exception>
+ AbstractQmsMessage CreateMessage(long deliverTag, bool redelivered,
+ ContentHeaderBody contentHeader,
+ IList bodies);
+
+ /// <summary>
+ /// Creates the message.
+ /// </summary>
+ /// <param name="mimeType">Mime type to associate the new message with</param>
+ /// <returns>The new message</returns>
+ /// <exception cref="QpidMessagingException">if the message cannot be created</exception>
+ AbstractQmsMessage CreateMessage(string mimeType);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Message/MessageFactoryRegistry.cs b/dotnet/Qpid.Client/Client/Message/MessageFactoryRegistry.cs
new file mode 100644
index 0000000000..fdb5e14aa6
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/MessageFactoryRegistry.cs
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class MessageFactoryRegistry
+ {
+ private readonly Hashtable _mimeToFactoryMap = new Hashtable();
+ private IMessageFactory _defaultFactory;
+
+ /// <summary>
+ /// Default factory to use for unknown message types
+ /// </summary>
+ public IMessageFactory DefaultFactory
+ {
+ get { return _defaultFactory; }
+ set { _defaultFactory = value; }
+ }
+
+ /// <summary>
+ /// Register a new message factory for a MIME type
+ /// </summary>
+ /// <param name="mimeType">Mime type to register</param>
+ /// <param name="mf"></param>
+ public void RegisterFactory(string mimeType, IMessageFactory mf)
+ {
+ if ( mf == null )
+ throw new ArgumentNullException("mf");
+ if ( mimeType == null || mimeType.Length == 0 )
+ throw new ArgumentNullException("mimeType");
+
+ _mimeToFactoryMap[mimeType] = mf;
+ }
+
+ /// <summary>
+ /// Remove a message factory
+ /// </summary>
+ /// <param name="mimeType">MIME type to unregister</param>
+ public void DeregisterFactory(string mimeType)
+ {
+ _mimeToFactoryMap.Remove(mimeType);
+ }
+
+ /// <summary>
+ /// Create a message. This looks up the MIME type from the content header and instantiates the appropriate
+ /// concrete message type.
+ /// </summary>
+ /// <param name="messageNbr">the AMQ message id</param>
+ /// <param name="redelivered">true if redelivered</param>
+ /// <param name="contentHeader">the content header that was received</param>
+ /// <param name="bodies">a list of ContentBody instances</param>
+ /// <returns>the message.</returns>
+ /// <exception cref="AMQException"/>
+ /// <exception cref="QpidException"/>
+ public AbstractQmsMessage CreateMessage(long messageNbr, bool redelivered,
+ ContentHeaderBody contentHeader,
+ IList bodies)
+ {
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties)contentHeader.Properties;
+
+ if ( properties.ContentType == null )
+ {
+ properties.ContentType = "";
+ }
+
+ IMessageFactory mf = GetFactory(properties.ContentType);
+ return mf.CreateMessage(messageNbr, redelivered, contentHeader, bodies);
+ }
+
+ /// <summary>
+ /// Create a new message of the specified type
+ /// </summary>
+ /// <param name="mimeType">The Mime type</param>
+ /// <returns>The new message</returns>
+ public AbstractQmsMessage CreateMessage(string mimeType)
+ {
+ if ( mimeType == null || mimeType.Length == 0 )
+ throw new ArgumentNullException("mimeType");
+
+ IMessageFactory mf = GetFactory(mimeType);
+ return mf.CreateMessage(mimeType);
+ }
+
+ /// <summary>
+ /// Construct a new registry with the default message factories registered
+ /// </summary>
+ /// <returns>a message factory registry</returns>
+ public static MessageFactoryRegistry NewDefaultRegistry()
+ {
+ MessageFactoryRegistry mf = new MessageFactoryRegistry();
+ mf.RegisterFactory("text/plain", new QpidTextMessageFactory());
+ mf.RegisterFactory("text/xml", new QpidTextMessageFactory());
+ mf.RegisterFactory("application/octet-stream", new QpidBytesMessageFactory());
+
+ mf.DefaultFactory = new QpidBytesMessageFactory();
+ return mf;
+ }
+
+ private IMessageFactory GetFactory(string mimeType)
+ {
+ IMessageFactory mf = (IMessageFactory)_mimeToFactoryMap[mimeType];
+ return mf != null ? mf : _defaultFactory;
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Message/QpidBytesMessage.cs b/dotnet/Qpid.Client/Client/Message/QpidBytesMessage.cs
new file mode 100644
index 0000000000..fb3efb1b0f
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/QpidBytesMessage.cs
@@ -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.
+ *
+ */
+using System;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Message
+{
+ [Serializable]
+ class MessageEOFException : QpidException
+ {
+ public MessageEOFException(string message) : base(message)
+ {
+ }
+
+ protected MessageEOFException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+
+ public class QpidBytesMessage : AbstractQmsMessage, IBytesMessage
+ {
+ private const int DEFAULT_BUFFER_INITIAL_SIZE = 1024;
+
+ public QpidBytesMessage() : this(null)
+ {
+ }
+
+ /// <summary>
+ /// Construct a bytes message with existing data.
+ /// </summary>
+ /// <param name="data">if data is not null, the message is immediately in read only mode. if data is null, it is in
+ /// write-only mode</param>
+ QpidBytesMessage(ByteBuffer data) : base(data)
+ {
+ // superclass constructor has instantiated a content header at this point
+ if (data == null)
+ {
+ _data = ByteBuffer.Allocate(DEFAULT_BUFFER_INITIAL_SIZE);
+ _data.IsAutoExpand = true;
+ }
+ }
+
+ internal QpidBytesMessage(long messageNbr, ContentHeaderBody contentHeader, ByteBuffer data)
+ // TODO: this casting is ugly. Need to review whole ContentHeaderBody idea
+ : base(messageNbr, (BasicContentHeaderProperties)contentHeader.Properties, data)
+ {
+ }
+
+ public override void ClearBodyImpl()
+ {
+ _data.Clear();
+ }
+
+ public override string ToBodyString()
+ {
+ CheckReadable();
+ try
+ {
+ return GetText();
+ }
+ catch (IOException e)
+ {
+ throw new QpidException(e.ToString());
+ }
+ }
+
+ private String GetText()
+ {
+ // this will use the default platform encoding
+ if (_data == null)
+ {
+ return null;
+ }
+ int pos = _data.Position;
+ _data.Rewind();
+ // one byte left is for the end of frame marker
+ if (_data.Remaining == 0)
+ {
+ // this is really redundant since pos must be zero
+ _data.Position = pos;
+ return null;
+ }
+ else
+ {
+ byte[] data = new byte[_data.Remaining];
+ _data.GetBytes(data);
+ return Encoding.UTF8.GetString(data);
+ }
+ }
+
+ public long BodyLength
+ {
+ get
+ {
+ CheckReadable();
+ return _data.Limit;
+ }
+ }
+
+ private void CheckWritable()
+ {
+ if (_readableMessage)
+ {
+ throw new MessageNotWriteableException("You need to call clearBody() to make the message writable");
+ }
+ }
+
+ public bool ReadBoolean()
+ {
+ CheckReadable();
+ CheckAvailable(1);
+ return _data.GetByte() != 0;
+ }
+
+ public byte ReadByte()
+ {
+ CheckReadable();
+ CheckAvailable(1);
+ return _data.GetByte();
+ }
+
+ public short ReadSignedByte()
+ {
+ CheckReadable();
+ CheckAvailable(1);
+ return _data.GetSByte();
+ }
+
+ public short ReadShort()
+ {
+ CheckReadable();
+ CheckAvailable(2);
+ return _data.GetInt16();
+ }
+
+ public char ReadChar()
+ {
+ CheckReadable();
+ CheckAvailable(2);
+ return _data.GetChar();
+ }
+
+ public int ReadInt()
+ {
+ CheckReadable();
+ CheckAvailable(4);
+ return _data.GetInt32();
+ }
+
+ public long ReadLong()
+ {
+ CheckReadable();
+ CheckAvailable(8);
+ return _data.GetInt64();
+ }
+
+ public float ReadFloat()
+ {
+ CheckReadable();
+ CheckAvailable(4);
+ return _data.GetFloat();
+ }
+
+ public double ReadDouble()
+ {
+ CheckReadable();
+ CheckAvailable(8);
+ return _data.GetDouble();
+ }
+
+ public string ReadUTF()
+ {
+ CheckReadable();
+ // we check only for one byte since theoretically the string could be only a
+ // single byte when using UTF-8 encoding
+ CheckAvailable(1);
+ try
+ {
+ byte[] data = new byte[_data.Remaining];
+ _data.GetBytes(data);
+ return Encoding.UTF8.GetString(data);
+ }
+ catch (IOException e)
+ {
+ throw new QpidException(e.ToString(), e);
+ }
+ }
+
+ public int ReadBytes(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes");
+ }
+ CheckReadable();
+ int count = (_data.Remaining >= bytes.Length ? bytes.Length : _data.Remaining);
+ if (count == 0)
+ {
+ return -1;
+ }
+ else
+ {
+ _data.GetBytes(bytes, 0, count);
+ return count;
+ }
+ }
+
+ public int ReadBytes(byte[] bytes, int maxLength)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes");
+ }
+ if (maxLength > bytes.Length)
+ {
+ throw new ArgumentOutOfRangeException("maxLength must be >= 0");
+ }
+ CheckReadable();
+ int count = (_data.Remaining >= maxLength ? maxLength : _data.Remaining);
+ if (count == 0)
+ {
+ return -1;
+ }
+ else
+ {
+ _data.GetBytes(bytes, 0, count);
+ return count;
+ }
+ }
+
+ public void WriteBoolean(bool b)
+ {
+ CheckWritable();
+ _data.Put(b ? (byte)1 : (byte)0);
+ }
+
+ public void WriteByte(byte b)
+ {
+ CheckWritable();
+ _data.Put(b);
+ }
+
+ public void WriteShort(short i)
+ {
+ CheckWritable();
+ _data.Put(i);
+ }
+
+ public void WriteChar(char c)
+ {
+ CheckWritable();
+ _data.Put(c);
+ }
+
+ public void WriteSignedByte(short value)
+ {
+ CheckWritable();
+ _data.Put(value);
+ }
+
+ public void WriteDouble(double value)
+ {
+ CheckWritable();
+ _data.Put(value);
+ }
+
+ public void WriteFloat(float value)
+ {
+ CheckWritable();
+ _data.Put(value);
+ }
+
+ public void WriteInt(int value)
+ {
+ CheckWritable();
+ _data.Put(value);
+ }
+
+ public void WriteLong(long value)
+ {
+ CheckWritable();
+ _data.Put(value);
+ }
+
+ public void WriteUTF(string value)
+ {
+ CheckWritable();
+ byte[] encodedData = Encoding.UTF8.GetBytes(value);
+ _data.Put(encodedData);
+ }
+
+ public void WriteBytes(byte[] bytes)
+ {
+ CheckWritable();
+ _data.Put(bytes);
+ }
+
+ public void WriteBytes(byte[] bytes, int offset, int length)
+ {
+ CheckWritable();
+ _data.Put(bytes, offset, length);
+ }
+
+ protected override void Reset()
+ {
+ base.Reset();
+ _data.Flip();
+ }
+
+ void IBytesMessage.Reset()
+ {
+ Reset();
+ }
+
+ /**
+ * Check that there is at least a certain number of bytes available to read
+ *
+ * @param len the number of bytes
+ * @throws MessageEOFException if there are less than len bytes available to read
+ */
+ private void CheckAvailable(int len)
+ {
+ if (_data.Remaining < len)
+ {
+ throw new MessageEOFException("Unable to read " + len + " bytes");
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/QpidBytesMessageFactory.cs b/dotnet/Qpid.Client/Client/Message/QpidBytesMessageFactory.cs
new file mode 100644
index 0000000000..3cc96cbddc
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/QpidBytesMessageFactory.cs
@@ -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.
+ *
+ */
+using System;
+using System.Collections;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class QpidBytesMessageFactory : AbstractQmsMessageFactory
+ {
+ //protected override AbstractQmsMessage CreateMessageWithBody(long messageNbr,
+ // ContentHeaderBody contentHeader,
+ // IList bodies)
+ //{
+ // byte[] data;
+
+ // // we optimise the non-fragmented case to avoid copying
+ // if (bodies != null && bodies.Count == 1)
+ // {
+ // data = ((ContentBody)bodies[0]).Payload;
+ // }
+ // else
+ // {
+ // data = new byte[(long)contentHeader.BodySize];
+ // int currentPosition = 0;
+ // foreach (ContentBody cb in bodies)
+ // {
+ // Array.Copy(cb.Payload, 0, data, currentPosition, cb.Payload.Length);
+ // currentPosition += cb.Payload.Length;
+ // }
+ // }
+
+ // return new QpidBytesMessage(messageNbr, data, contentHeader);
+ //}
+
+ //public override AbstractQmsMessage CreateMessage()
+ //{
+ // return new QpidBytesMessage();
+ //}
+
+ protected override AbstractQmsMessage CreateMessage(long deliveryTag, ByteBuffer data, ContentHeaderBody contentHeader)
+ {
+ return new QpidBytesMessage(deliveryTag, contentHeader, data);
+ }
+
+ public override AbstractQmsMessage CreateMessage(string mimeType)
+ {
+ QpidBytesMessage msg = new QpidBytesMessage();
+ msg.ContentType = mimeType;
+ return msg;
+ }
+
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Message/QpidHeaders.cs b/dotnet/Qpid.Client/Client/Message/QpidHeaders.cs
new file mode 100644
index 0000000000..9ad1c26867
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/QpidHeaders.cs
@@ -0,0 +1,233 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Client.Message
+{
+ internal class QpidHeaders : IHeaders
+ {
+ private FieldTable _headers;
+
+ public QpidHeaders(FieldTable headers)
+ {
+ if ( headers == null )
+ throw new ArgumentNullException("headers");
+ _headers = headers;
+ }
+
+ public bool Contains(string name)
+ {
+ CheckPropertyName(name);
+ return _headers.Contains(name);
+ }
+
+ public void Clear()
+ {
+ _headers.Clear();
+ }
+
+ public object this[string name]
+ {
+ get { return GetObject(name); }
+ set { SetObject(name, value); }
+ }
+
+ public bool GetBoolean(string name)
+ {
+ CheckPropertyName(name);
+ if ( Contains(name) )
+ return _headers.GetBoolean(name);
+ return false;
+ }
+
+ public void SetBoolean(string name, bool b)
+ {
+ CheckPropertyName(name);
+ _headers.SetBoolean(name, b);
+ }
+
+ public byte GetByte(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetByte(propertyName);
+ return 0;
+ }
+
+ public void SetByte(string propertyName, byte b)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetByte(propertyName, b);
+ }
+
+ // we have sbyte overloads to interoperate with java
+ // because the Java client/server uses signed bytes
+ // by default, while C#'s is unsigned
+ public sbyte GetSByte(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetSByte(propertyName);
+ return 0;
+ }
+
+ public void SetSByte(string propertyName, sbyte b)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetSByte(propertyName, b);
+ }
+
+ public short GetShort(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetInt16(propertyName);
+ return 0;
+ }
+
+ public void SetShort(string propertyName, short i)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetInt16(propertyName, i);
+ }
+
+ public int GetInt(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetInt32(propertyName);
+ return 0;
+ }
+
+ public void SetInt(string propertyName, int i)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetInt32(propertyName, i);
+ }
+
+ public long GetLong(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetInt64(propertyName);
+ return 0;
+ }
+
+ public void SetLong(string propertyName, long l)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetInt64(propertyName, l);
+ }
+
+ public float GetFloat(String propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetFloat(propertyName);
+ return 0f;
+ }
+
+ public void SetFloat(string propertyName, float f)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetFloat(propertyName, f);
+ }
+
+ public double GetDouble(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ if ( Contains(propertyName) )
+ return _headers.GetDouble(propertyName);
+ return 0;
+ }
+
+ public void SetDouble(string propertyName, double v)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetDouble(propertyName, v);
+ }
+
+ public string GetString(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ return _headers.GetString(propertyName);
+ }
+
+ public void SetString(string propertyName, string value)
+ {
+ CheckPropertyName(propertyName);
+ _headers.SetString(propertyName, value);
+ }
+
+ public object GetObject(string propertyName)
+ {
+ CheckPropertyName(propertyName);
+ return _headers[propertyName];
+ }
+
+ public void SetObject(string propertyName, object value)
+ {
+ CheckPropertyName(propertyName);
+ _headers[propertyName] = value;
+ }
+
+ private static void CheckPropertyName(string propertyName)
+ {
+ if ( propertyName == null )
+ {
+ throw new ArgumentException("Property name must not be null");
+ } else if ( "".Equals(propertyName) )
+ {
+ throw new ArgumentException("Property name must not be the empty string");
+ }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder("{");
+ int i = 0;
+ foreach ( DictionaryEntry entry in _headers )
+ {
+ ++i;
+ if ( i > 1 )
+ {
+ buf.Append(", ");
+ }
+ string propertyName = (string)entry.Key;
+ if ( propertyName == null )
+ {
+ buf.Append("\nInternal error: Property with NULL key defined");
+ } else
+ {
+ buf.Append(propertyName);
+ buf.Append(" = ").Append(entry.Value);
+ }
+ }
+ buf.Append("}");
+ return buf.ToString();
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/QpidTextMessage.cs b/dotnet/Qpid.Client/Client/Message/QpidTextMessage.cs
new file mode 100644
index 0000000000..24aef92aa5
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/QpidTextMessage.cs
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class QpidTextMessage : AbstractQmsMessage, ITextMessage
+ {
+ private string _decodedValue = null;
+ private static Encoding DEFAULT_ENCODING = Encoding.UTF8;
+
+ internal QpidTextMessage() : this(null, null)
+ {
+ ContentEncoding = DEFAULT_ENCODING.BodyName;
+ }
+
+ internal QpidTextMessage(ByteBuffer data, String encoding) : base(data)
+ {
+ ContentEncoding = encoding;
+ }
+
+ internal QpidTextMessage(long deliveryTag, BasicContentHeaderProperties contentHeader, ByteBuffer data)
+ :base(deliveryTag, contentHeader, data)
+ {
+ }
+
+ public override void ClearBodyImpl()
+ {
+ if (_data != null)
+ {
+ _data.Release();
+ }
+ _data = null;
+ _decodedValue = null;
+ }
+
+ public override string ToBodyString()
+ {
+ return Text;
+ }
+
+ public string Text
+ {
+ get
+ {
+ if (_data == null && _decodedValue == null)
+ {
+ return null;
+ }
+ else if (_decodedValue != null)
+ {
+ return _decodedValue;
+ }
+ else
+ {
+ _data.Rewind();
+
+ // Read remaining bytes.
+ byte[] bytes = new byte[_data.Remaining];
+ _data.GetBytes(bytes);
+
+ // Convert to string based on encoding.
+ if (ContentHeaderProperties.Encoding != null)
+ {
+ // throw ArgumentException if the encoding is not supported
+ _decodedValue = Encoding.GetEncoding(ContentHeaderProperties.Encoding).GetString(bytes);
+ }
+ else
+ {
+ _decodedValue = DEFAULT_ENCODING.GetString(bytes);
+ }
+ return _decodedValue;
+ }
+ }
+
+ set
+ {
+ byte[] bytes;
+ if (ContentHeaderProperties.Encoding == null)
+ {
+ bytes = Encoding.Default.GetBytes(value);
+ }
+ else
+ {
+ // throw ArgumentException if the encoding is not supported
+ bytes = Encoding.GetEncoding(ContentHeaderProperties.Encoding).GetBytes(value);
+ }
+ _data = ByteBuffer.Wrap(bytes);
+ _decodedValue = value;
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/QpidTextMessageFactory.cs b/dotnet/Qpid.Client/Client/Message/QpidTextMessageFactory.cs
new file mode 100644
index 0000000000..79871e85ca
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/QpidTextMessageFactory.cs
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class QpidTextMessageFactory : AbstractQmsMessageFactory
+ {
+ public override AbstractQmsMessage CreateMessage(string mimeType)
+ {
+ QpidTextMessage msg = new QpidTextMessage();
+ msg.ContentType = mimeType;
+ return msg;
+ }
+
+ protected override AbstractQmsMessage CreateMessage(long deliveryTag, ByteBuffer data, ContentHeaderBody contentHeader)
+ {
+ return new QpidTextMessage(deliveryTag, (BasicContentHeaderProperties) contentHeader.Properties, data);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Message/UnexpectedBodyReceivedException.cs b/dotnet/Qpid.Client/Client/Message/UnexpectedBodyReceivedException.cs
new file mode 100644
index 0000000000..4317ef3474
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/UnexpectedBodyReceivedException.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using log4net;
+
+namespace Apache.Qpid.Client.Message
+{
+ /// <summary>
+ /// Raised when a message body is received unexpectedly by the client. This typically occurs when the
+ /// length of bodies received does not match with the declared length in the content header.
+ /// </summary>
+ [Serializable]
+ public class UnexpectedBodyReceivedException : AMQException
+ {
+ public UnexpectedBodyReceivedException(ILog logger, string msg, Exception t)
+ : base(logger, msg, t)
+ {
+ }
+
+ public UnexpectedBodyReceivedException(ILog logger, string msg)
+ : base(logger, msg)
+ {
+ }
+
+ public UnexpectedBodyReceivedException(ILog logger, int errorCode, string msg)
+ : base(logger, errorCode, msg)
+ {
+ }
+
+ protected UnexpectedBodyReceivedException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Client/Client/Message/UnprocessedMessage.cs b/dotnet/Qpid.Client/Client/Message/UnprocessedMessage.cs
new file mode 100644
index 0000000000..d329712334
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Message/UnprocessedMessage.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Message
+{
+ public class UnprocessedMessage
+ {
+ private ulong _bytesReceived = 0;
+
+ public BasicDeliverBody DeliverBody;
+ public BasicReturnBody BounceBody;
+ public ushort ChannelId;
+ public ContentHeaderBody ContentHeader;
+
+ /// <summary>
+ /// List of ContentBody instances. Due to fragmentation you don't know how big this will be in general
+ /// </summary>
+ /// TODO: write and use linked list class
+ public IList Bodies = new ArrayList();
+
+ public void ReceiveBody(ContentBody body)
+ {
+ Bodies.Add(body);
+ if (body.Payload != null)
+ {
+ _bytesReceived += (uint)body.Payload.Remaining;
+ }
+ }
+
+ public bool IsAllBodyDataReceived()
+ {
+ return _bytesReceived == ContentHeader.BodySize;
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Protocol/AMQMethodEvent.cs b/dotnet/Qpid.Client/Client/Protocol/AMQMethodEvent.cs
new file mode 100644
index 0000000000..a7ce808862
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/AMQMethodEvent.cs
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Text;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ public class AMQMethodEvent
+ {
+ private AMQMethodBody _method;
+
+ private ushort _channelId;
+
+ private AMQProtocolSession _protocolSession;
+
+ public AMQMethodEvent(ushort channelId, AMQMethodBody method, AMQProtocolSession protocolSession)
+ {
+ _channelId = channelId;
+ _method = method;
+ _protocolSession = protocolSession;
+ }
+
+ public AMQMethodBody Method
+ {
+ get
+ {
+ return _method;
+ }
+ }
+
+ public ushort ChannelId
+ {
+ get
+ {
+ return _channelId;
+ }
+ }
+
+ public AMQProtocolSession ProtocolSession
+ {
+ get
+ {
+ return _protocolSession;
+ }
+ }
+
+ public override String ToString()
+ {
+ StringBuilder buf = new StringBuilder("Method event: ");
+ buf.Append("\nChannel id: ").Append(_channelId);
+ buf.Append("\nMethod: ").Append(_method);
+ return buf.ToString();
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs b/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs
new file mode 100644
index 0000000000..c51538b70e
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/AMQProtocolListener.cs
@@ -0,0 +1,318 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Failover;
+using Apache.Qpid.Client.Protocol.Listener;
+using Apache.Qpid.Client.State;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ /// <summary>
+ /// AMQProtocolListener
+ ///
+ /// <p/>Fail-over state transition rules...
+ ///
+ /// <p/>The failover handler is created when the session is created since it needs a reference to the IoSession in order
+ /// to be able to send errors during failover back to the client application. The session won't be available in the case
+ /// when failing over due to a Connection.Redirect message from the broker.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Track fail over state of a connection.
+ /// <tr><td> Manage method listeners. <td> IAMQMethodListener
+ /// <tr><td> Receive notification of all IO errors on a connection. <td> IoHandler
+ /// <tr><td> Inform method listeners of all method events on a connection. <td> IAMQMethodListener
+ /// <tr><td> Inform method listeners of all error events on a connection. <td> IAMQMethodListener
+ /// </table>
+ ///
+ /// <b>Todo:</b> The broker will close the connection with no warning if authentication fails. This may result in the fail-over process being
+ /// triggered, when it should not be.
+ ///
+ /// </summary>
+ public class AMQProtocolListener : IProtocolListener
+ {
+ /// <summary>Used for debugging.</summary>
+ private static readonly ILog _log = LogManager.GetLogger(typeof(AMQProtocolListener));
+
+ /// <summary>
+ /// Holds the failover handler for the connection. When a failure is detected, and the current failover state allows it,
+ /// the failover process is handed off to this handler.
+ /// </summary>
+ private FailoverHandler _failoverHandler;
+
+ /// <summary>Tracks the current fail-over state.</summary>
+ internal FailoverState _failoverState = FailoverState.NOT_STARTED;
+
+ internal FailoverState FailoverState
+ {
+ get { return _failoverState; }
+ set { _failoverState = value; }
+ }
+
+ internal ManualResetEvent FailoverLatch;
+
+ AMQConnection _connection;
+ AMQStateManager _stateManager;
+
+ public AMQStateManager StateManager
+ {
+ get { return _stateManager; }
+ set { _stateManager = value; }
+ }
+
+ private readonly ArrayList _frameListeners = ArrayList.Synchronized(new ArrayList());
+
+ AMQProtocolSession _protocolSession = null;
+
+ private readonly Object _lock = new Object();
+
+ public AMQProtocolSession ProtocolSession { set { _protocolSession = value; } }
+
+ public AMQProtocolListener(AMQConnection connection, AMQStateManager stateManager)
+ {
+ _connection = connection;
+ _stateManager = stateManager;
+ _failoverHandler = new FailoverHandler(connection);
+ }
+
+ public void OnMessage(IDataBlock message)
+ {
+ // Handle incorrect protocol version.
+ if (message is ProtocolInitiation)
+ {
+ string error = String.Format("Protocol mismatch - {0}", message.ToString());
+ AMQException e = new AMQProtocolHeaderException(error);
+ _log.Error("Closing connection because of protocol mismatch", e);
+ //_protocolSession.CloseProtocolSession();
+ _stateManager.Error(e);
+ return;
+ }
+
+ AMQFrame frame = (AMQFrame)message;
+
+ if (frame.BodyFrame is AMQMethodBody)
+ {
+ if (_log.IsDebugEnabled)
+ {
+ _log.Debug("Method frame received: " + frame);
+ }
+ AMQMethodEvent evt = new AMQMethodEvent(frame.Channel, (AMQMethodBody)frame.BodyFrame, _protocolSession);
+ try
+ {
+ bool wasAnyoneInterested = false;
+ lock (_frameListeners.SyncRoot)
+ {
+ foreach (IAMQMethodListener listener in _frameListeners)
+ {
+ wasAnyoneInterested = listener.MethodReceived(evt) || wasAnyoneInterested;
+ }
+ }
+ if (!wasAnyoneInterested)
+ {
+ throw new AMQException("AMQMethodEvent " + evt + " was not processed by any listener.");
+ }
+ }
+ catch (Exception e)
+ {
+ foreach (IAMQMethodListener listener in _frameListeners)
+ {
+ listener.Error(e);
+ }
+ }
+ }
+ else if (frame.BodyFrame is ContentHeaderBody)
+ {
+ _protocolSession.MessageContentHeaderReceived(frame.Channel,
+ (ContentHeaderBody)frame.BodyFrame);
+ }
+ else if (frame.BodyFrame is ContentBody)
+ {
+ _protocolSession.MessageContentBodyReceived(frame.Channel,
+ (ContentBody)frame.BodyFrame);
+ }
+ else if (frame.BodyFrame is HeartbeatBody)
+ {
+ _log.Debug("HeartBeat received");
+ }
+ }
+
+ /// <summary>
+ /// Receives notification of any IO exceptions on the connection.
+ ///
+ /// <p/>Upon receipt of a connection closed exception or any IOException, the fail-over process is attempted. If the fail-over fails, then
+ /// all method listeners and the application connection object are notified of the connection failure exception.
+ ///
+ /// <p/>All other exception types are propagated to all method listeners.
+ /// </summary>
+ public void OnException(Exception cause)
+ {
+ _log.Warn("public void OnException(Exception cause = " + cause + "): called");
+
+ // Ensure that the method listener set cannot be changed whilst this exception is propagated to all listeners. This also
+ // ensures that this exception is fully propagated to all listeners, before another one can be processed.
+ lock (_lock)
+ {
+ if (cause is AMQConnectionClosedException || cause is System.IO.IOException)
+ {
+ // Try a fail-over because the connection has failed.
+ FailoverState failoverState = AttemptFailover();
+
+ // Check if the fail-over has failed, in which case notify all method listeners of the exception.
+ // The application connection object is also notified of the failure of the connection with the exception.
+ if (failoverState == FailoverState.FAILED)
+ {
+ _log.Debug("Fail-over has failed. Notifying all method listeners of the exception.");
+
+ AMQException amqe = new AMQException("Protocol handler error: " + cause, cause);
+ PropagateExceptionToWaiters(amqe);
+ _connection.ExceptionReceived(cause);
+ }
+ }
+ // Notify all method listeners of the exception.
+ else
+ {
+ PropagateExceptionToWaiters(cause);
+ _connection.ExceptionReceived(cause);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Tries to fail-over the connection, if the connection policy will permit it, and the fail-over process has not yet been
+ /// started. If the connection does not allow fail-over then an exception will be raised. If a fail-over is already in progress
+ /// this method allows it to continue to run and will do nothing.
+ ///
+ /// <p/>This method should only be called when the connection has been remotely closed.
+ /// </summary>
+ ///
+ /// <returns>The fail-over state at the end of this attempt.</returns>
+ private FailoverState AttemptFailover()
+ {
+ _log.Debug("private void AttemptFailover(): called");
+ _log.Debug("_failoverState = " + _failoverState);
+
+ // Ensure that the connection stops sending heart beats, if it still is.
+ _connection.StopHeartBeatThread();
+
+ // Check that the connection policy allows fail-over to be attempted.
+ if (!_connection.IsFailoverAllowed)
+ {
+ _log.Debug("Connection does not allowed to failover");
+ _connection.ExceptionReceived(
+ new AMQDisconnectedException("Broker closed connection and reconnection is not permitted."));
+ }
+
+ // Check if connection was closed deliberately by the application, in which case no fail-over is attempted.
+ if (_connection.Closed)
+ {
+ return _failoverState;
+ }
+
+ // If the connection allows fail-over and fail-over has not yet been started, then it is started and the fail-over state is
+ // advanced to 'in progress'
+ if (_failoverState == FailoverState.NOT_STARTED && _connection.IsFailoverAllowed)
+ {
+ _log.Info("Starting the fail-over process.");
+
+ _failoverState = FailoverState.IN_PROGRESS;
+ StartFailoverThread();
+ }
+
+ return _failoverState;
+ }
+
+ /// <summary>
+ /// There are two cases where we have other threads potentially blocking for events to be handled by this
+ /// class. These are for the state manager (waiting for a state change) or a frame listener (waiting for a
+ /// particular type of frame to arrive). When an error occurs we need to notify these waiters so that they can
+ /// react appropriately.
+ ///
+ /// <param name="e">the exception to propagate</param>
+ /// </summary>
+ public void PropagateExceptionToWaiters(Exception e)
+ {
+ // FIXME: not sure if required as StateManager is in _frameListeners. Probably something to do with fail-over.
+ _stateManager.Error(e);
+ lock ( _lock )
+ {
+ foreach ( IAMQMethodListener listener in _frameListeners )
+ {
+ listener.Error(e);
+ }
+ }
+ }
+
+ public void AddFrameListener(IAMQMethodListener listener)
+ {
+ lock ( _lock )
+ {
+ _frameListeners.Add(listener);
+ }
+ }
+
+ public void RemoveFrameListener(IAMQMethodListener listener)
+ {
+ if (_log.IsDebugEnabled)
+ {
+ _log.Debug("Removing frame listener: " + listener.ToString());
+ }
+ lock ( _lock )
+ {
+ _frameListeners.Remove(listener);
+ }
+ }
+
+ public void BlockUntilNotFailingOver()
+ {
+ if (FailoverLatch != null)
+ {
+ FailoverLatch.WaitOne();
+ }
+ }
+
+ /// <summary>
+ /// "Failover" for redirection.
+ /// </summary>
+ /// <param name="host"></param>
+ /// <param name="port"></param>
+ public void Failover(string host, int port)
+ {
+ _failoverHandler.setHost(host);
+ _failoverHandler.setPort(port);
+ // see javadoc for FailoverHandler to see rationale for separate thread
+ StartFailoverThread();
+ }
+
+ private void StartFailoverThread()
+ {
+ Thread failoverThread = new Thread(new ThreadStart(_failoverHandler.Run));
+ failoverThread.Name = "Failover";
+ // Do not inherit daemon-ness from current thread as this can be a daemon
+ // thread such as a AnonymousIoService thread.
+ failoverThread.IsBackground = false;
+ failoverThread.Start();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/AMQProtocolSession.cs b/dotnet/Qpid.Client/Client/Protocol/AMQProtocolSession.cs
new file mode 100644
index 0000000000..1fb3d407eb
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/AMQProtocolSession.cs
@@ -0,0 +1,267 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using log4net;
+using Apache.Qpid.Client.Message;
+using Apache.Qpid.Client.Transport;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Sasl;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ public class AMQProtocolSession
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(AMQProtocolSession));
+
+ private readonly IProtocolWriter _protocolWriter;
+ private readonly IConnectionCloser _connectionCloser;
+
+ /// <summary>
+ /// Maps from the channel id to the AmqChannel that it represents.
+ /// </summary>
+ //private ConcurrentMap _channelId2SessionMap = new ConcurrentHashMap();
+ private Hashtable _channelId2SessionMap = Hashtable.Synchronized(new Hashtable());
+
+ //private ConcurrentMap _closingChannels = new ConcurrentHashMap();
+ private Hashtable _closingChannels = Hashtable.Synchronized(new Hashtable());
+
+ /// <summary>
+ /// Maps from a channel id to an unprocessed message. This is used to tie together the
+ /// JmsDeliverBody (which arrives first) with the subsequent content header and content bodies.
+ /// </summary>
+ //private ConcurrentMap _channelId2UnprocessedMsgMap = new ConcurrentHashMap();
+ private Hashtable _channelId2UnprocessedMsgMap = Hashtable.Synchronized(new Hashtable());
+
+ private AMQConnection _connection;
+
+ public string ClientID { get { return _connection.ClientID; } }
+
+ public AMQProtocolSession(IProtocolWriter protocolWriter, IConnectionCloser connectionCloser, AMQConnection connection)
+ {
+ _protocolWriter = protocolWriter;
+ _connectionCloser = connectionCloser;
+ _connection = connection;
+ }
+
+ public void Init()
+ {
+ // start the process of setting up the connection. This is the first place that
+ // data is written to the server.
+ _protocolWriter.Write(new ProtocolInitiation());
+ }
+
+ public string Username
+ {
+ get
+ {
+ return AMQConnection.Username;
+ }
+ }
+
+ public string Password
+ {
+ get
+ {
+ return AMQConnection.Password;
+ }
+ }
+
+ ConnectionTuneParameters _connectionTuneParameters; // TODO: should be able to have this in the Java too.
+
+ public ConnectionTuneParameters ConnectionTuneParameters
+ {
+ get
+ {
+ return _connectionTuneParameters;
+ }
+ set
+ {
+ _connectionTuneParameters = value;
+ AMQConnection con = AMQConnection;
+ con.SetMaximumChannelCount(value.ChannelMax);
+ con.MaximumFrameSize = value.FrameMax;
+ }
+ }
+
+ private ISaslClient _saslClient;
+ public ISaslClient SaslClient
+ {
+ get { return _saslClient; }
+ set { _saslClient = value; }
+ }
+
+ /// <summary>
+ /// Callback invoked from the BasicDeliverMethodHandler when a message has been received.
+ /// This is invoked on the MINA dispatcher thread.
+ /// </summary>
+ /// <param name="message">the unprocessed message</param>
+ /// <exception cname="AMQException">if this was not expected</exception>
+ public void UnprocessedMessageReceived(UnprocessedMessage message)
+ {
+ _channelId2UnprocessedMsgMap[message.ChannelId] = message;
+ }
+
+ public void MessageContentHeaderReceived(ushort channelId, ContentHeaderBody contentHeader)
+ {
+ UnprocessedMessage msg = (UnprocessedMessage) _channelId2UnprocessedMsgMap[channelId];
+ if (msg == null)
+ {
+ throw new AMQException("Error: received content header without having received a JMSDeliver frame first");
+ }
+ if (msg.ContentHeader != null)
+ {
+ throw new AMQException("Error: received duplicate content header or did not receive correct number of content body frames");
+ }
+ msg.ContentHeader = contentHeader;
+ if (contentHeader.BodySize == 0)
+ {
+ DeliverMessageToAMQSession(channelId, msg);
+ }
+ }
+
+ public void MessageContentBodyReceived(ushort channelId, ContentBody contentBody)
+ {
+ UnprocessedMessage msg = (UnprocessedMessage) _channelId2UnprocessedMsgMap[channelId];
+ if (msg == null)
+ {
+ throw new AMQException("Error: received content body without having received a BasicDeliver frame first");
+ }
+ if (msg.ContentHeader == null)
+ {
+ _channelId2UnprocessedMsgMap.Remove(channelId);
+ throw new AMQException("Error: received content body without having received a ContentHeader frame first");
+ }
+ try
+ {
+ msg.ReceiveBody(contentBody);
+ }
+ catch (UnexpectedBodyReceivedException e)
+ {
+ _channelId2UnprocessedMsgMap.Remove(channelId);
+ throw e;
+ }
+ if (msg.IsAllBodyDataReceived())
+ {
+ DeliverMessageToAMQSession(channelId, msg);
+ }
+ }
+
+ /// <summary>
+ /// Deliver a message to the appropriate session, removing the unprocessed message
+ /// from our map
+ /// <param name="channelId">the channel id the message should be delivered to</param>
+ /// <param name="msg"> the message</param>
+ private void DeliverMessageToAMQSession(ushort channelId, UnprocessedMessage msg)
+ {
+ AmqChannel channel = (AmqChannel) _channelId2SessionMap[channelId];
+ channel.MessageReceived(msg);
+ _channelId2UnprocessedMsgMap.Remove(channelId);
+ }
+
+ /// <summary>
+ /// Convenience method that writes a frame to the protocol session. Equivalent
+ /// to calling getProtocolSession().write().
+ /// </summary>
+ /// <param name="frame">the frame to write</param>
+ public void WriteFrame(IDataBlock frame)
+ {
+ _protocolWriter.Write(frame);
+ }
+
+ public void AddSessionByChannel(ushort channelId, AmqChannel channel)
+ {
+ if (channel == null)
+ {
+ throw new ArgumentNullException("Attempt to register a null channel");
+ }
+ _logger.Debug("Add channel with channel id " + channelId);
+ _channelId2SessionMap[channelId] = channel;
+ }
+
+ public void RemoveSessionByChannel(ushort channelId)
+ {
+ _logger.Debug("Removing session with channelId " + channelId);
+ _channelId2SessionMap.Remove(channelId);
+ }
+
+ /// <summary>
+ /// Starts the process of closing a channel
+ /// </summary>
+ /// <param name="channel" the AmqChannel being closed</param>
+ public void CloseSession(AmqChannel channel)
+ {
+ _logger.Debug("closeSession called on protocol channel for channel " + channel.ChannelId);
+ ushort channelId = channel.ChannelId;
+
+ // we need to know when a channel is closing so that we can respond
+ // with a channel.close frame when we receive any other type of frame
+ // on that channel
+ _closingChannels[channelId] = channel;
+
+ }
+
+ /// <summary>
+ /// Called from the ChannelClose handler when a channel close frame is received.
+ /// This method decides whether this is a response or an initiation. The latter
+ /// case causes the AmqChannel to be closed and an exception to be thrown if
+ /// appropriate.
+ /// </summary>
+ /// <param name="channelId">the id of the channel (session)</param>
+ /// <returns>true if the client must respond to the server, i.e. if the server
+ /// initiated the channel close, false if the channel close is just the server
+ /// responding to the client's earlier request to close the channel.</returns>
+ public bool ChannelClosed(ushort channelId, int code, string text)
+ {
+ // if this is not a response to an earlier request to close the channel
+ if (!_closingChannels.ContainsKey(channelId))
+ {
+ _closingChannels.Remove(channelId);
+ AmqChannel channel = (AmqChannel) _channelId2SessionMap[channelId];
+ channel.ClosedWithException(new AMQException(_logger, code, text));
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public AMQConnection AMQConnection
+ {
+ get
+ {
+ return _connection;
+ }
+ }
+
+ public void CloseProtocolSession()
+ {
+ _logger.Debug("Closing protocol session");
+ _connectionCloser.Close();
+ }
+
+ internal string GenerateQueueName()
+ {
+ return "ntmp_" + System.Guid.NewGuid();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs b/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs
new file mode 100644
index 0000000000..2f23a1571d
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/DefaultTimeouts.cs
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Text;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ /// <summary>
+ /// Default timeout values for the protocol
+ /// </summary>
+ sealed class DefaultTimeouts
+ {
+ /// <summary>
+ /// Maximum number of milliseconds to wait for a state change
+ /// in the protocol's state machine
+ /// </summary>
+ public const int MaxWaitForState = 30* 1000;
+ /// <summary>
+ /// Maximum number of milliseconds to wait for a reply
+ /// frame when doing synchronous writer to the broker
+ /// </summary>
+ public const int MaxWaitForSyncWriter = 30 * 1000;
+
+ private DefaultTimeouts()
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/IConnectionCloser.cs b/dotnet/Qpid.Client/Client/Protocol/IConnectionCloser.cs
new file mode 100644
index 0000000000..e3298200c4
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/IConnectionCloser.cs
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Client.Protocol
+{
+ public interface IConnectionCloser
+ {
+ void Close();
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/IProtocolListener.cs b/dotnet/Qpid.Client/Client/Protocol/IProtocolListener.cs
new file mode 100644
index 0000000000..3b53f015f8
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/IProtocolListener.cs
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Client.Protocol.Listener;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ public interface IProtocolListener
+ {
+ void OnMessage(IDataBlock message);
+ void OnException(Exception e);
+
+ // XXX: .NET way of doing listeners?
+ void AddFrameListener(IAMQMethodListener listener);
+ void RemoveFrameListener(IAMQMethodListener listener);
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs b/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs
new file mode 100644
index 0000000000..9cc9f8cee5
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/Listener/BlockingMethodFrameListener.cs
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Protocol.Listener
+{
+ public abstract class BlockingMethodFrameListener : IAMQMethodListener
+ {
+ private ManualResetEvent _resetEvent;
+
+ public abstract bool ProcessMethod(ushort channelId, AMQMethodBody frame);
+
+ /// <summary>
+ /// This is set if there is an exception thrown from processCommandFrame and the
+ /// exception is rethrown to the caller of blockForFrame()
+ /// </summary>
+ private volatile Exception _error;
+
+ protected ushort _channelId;
+
+ protected AMQMethodEvent _doneEvt = null;
+
+ public BlockingMethodFrameListener(ushort channelId)
+ {
+ _channelId = channelId;
+ _resetEvent = new ManualResetEvent(false);
+ }
+
+ /// <summary>
+ /// This method is called by the MINA dispatching thread. Note that it could
+ /// be called before BlockForFrame() has been called.
+ /// </summary>
+ /// <param name="evt">the frame event</param>
+ /// <returns>true if the listener has dealt with this frame</returns>
+ /// <exception cref="AMQException"></exception>
+ public bool MethodReceived(AMQMethodEvent evt)
+ {
+ AMQMethodBody method = evt.Method;
+
+ try
+ {
+ bool ready = (evt.ChannelId == _channelId) && ProcessMethod(evt.ChannelId, method);
+ if (ready)
+ {
+ _doneEvt = evt;
+ _resetEvent.Set();
+ }
+
+ return ready;
+ }
+ catch (AMQException e)
+ {
+ Error(e);
+ // we rethrow the error here, and the code in the frame dispatcher will go round
+ // each listener informing them that an exception has been thrown
+ throw e;
+ }
+ }
+
+ /// <summary>
+ /// This method is called by the thread that wants to wait for a frame.
+ /// </summary>
+ /// <param name="timeout">Set the number of milliseconds to wait</param>
+ public AMQMethodEvent BlockForFrame(int timeout)
+ {
+ _resetEvent.WaitOne(timeout, true);
+ //at this point the event will have been signalled. The error field might or might not be set
+ // depending on whether an error occurred
+ if (_error != null)
+ {
+ throw _error;
+ }
+
+ return _doneEvt;
+ }
+
+ /// <summary>
+ /// This is a callback, called by the MINA dispatcher thread only. It is also called from within this
+ /// class to avoid code repetition but again is only called by the MINA dispatcher thread.
+ /// </summary>
+ /// <param name="e">the exception that caused the error</param>
+ public void Error(Exception e)
+ {
+ // set the error so that the thread that is blocking (in BlockForFrame())
+ // can pick up the exception and rethrow to the caller
+ _error = e;
+ _resetEvent.Set();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Protocol/Listener/IAMQMethodListener.cs b/dotnet/Qpid.Client/Client/Protocol/Listener/IAMQMethodListener.cs
new file mode 100644
index 0000000000..b5450d00f7
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/Listener/IAMQMethodListener.cs
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client.Protocol.Listener
+{
+ public interface IAMQMethodListener
+ {
+ /// <summary>
+ /// Invoked when a method frame has been received
+ /// <param name="evt">the event</param>
+ /// <returns>true if the handler has processed the method frame, false otherwise. Note
+ /// that this does not prohibit the method event being delivered to subsequent listeners
+ /// but can be used to determine if nobody has dealt with an incoming method frame.</param>
+ /// <exception cname="AMQException">if an error has occurred. This exception will be delivered
+ /// to all registered listeners using the error() method (see below) allowing them to
+ /// perform cleanup if necessary.</exception>
+ bool MethodReceived(AMQMethodEvent evt);
+
+ /// <summary>
+ /// Callback when an error has occurred. Allows listeners to clean up.
+ /// </summary>
+ /// <param name="e">the exception</param>
+ void Error(Exception e);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Protocol/Listener/SpecificMethodFrameListener.cs b/dotnet/Qpid.Client/Client/Protocol/Listener/SpecificMethodFrameListener.cs
new file mode 100644
index 0000000000..8cdc1dbba9
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/Listener/SpecificMethodFrameListener.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Protocol.Listener
+{
+ public class SpecificMethodFrameListener : BlockingMethodFrameListener
+ {
+ private readonly Type _expectedClass;
+
+ public SpecificMethodFrameListener(ushort channelId, Type expectedClass) : base(channelId)
+ {
+ _expectedClass = expectedClass;
+ }
+
+ public override bool ProcessMethod(ushort channelId, AMQMethodBody frame)
+ {
+ return _expectedClass.IsInstanceOfType(frame);
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs b/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs
new file mode 100644
index 0000000000..11918f1ea2
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Protocol/ProtocolWriter.cs
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Client.Protocol.Listener;
+using Apache.Qpid.Client.Transport;
+using Apache.Qpid.Framing;
+
+using log4net;
+
+namespace Apache.Qpid.Client.Protocol
+{
+ /// <summary>
+ /// A convenient interface to writing protocol frames.
+ /// </summary>
+ public class ProtocolWriter
+ {
+
+ private ILog _logger = LogManager.GetLogger(typeof(ProtocolWriter));
+
+ IProtocolWriter _protocolWriter;
+ IProtocolListener _protocolListener;
+
+ public ProtocolWriter(IProtocolWriter protocolWriter, IProtocolListener protocolListener)
+ {
+ _protocolWriter = protocolWriter;
+ _protocolListener = protocolListener;
+ }
+
+ public void WriteFrame(IDataBlock frame)
+ {
+ _protocolWriter.Write(frame);
+ }
+
+ /// <summary>
+ /// Convenience method that writes a frame to the protocol session and waits for
+ /// a particular response. Equivalent to calling getProtocolSession().write() then
+ /// waiting for the response.
+ /// </summary>
+ /// <param name="frame">the frame</param>
+ /// <param name="listener">the blocking listener. Note the calling thread will block.</param>
+ /// <param name="timeout">set the number of milliseconds to wait</param>
+ private AMQMethodEvent SyncWrite(AMQFrame frame, BlockingMethodFrameListener listener, int timeout)
+ {
+ try
+ {
+ _protocolListener.AddFrameListener(listener);
+ _protocolWriter.Write(frame);
+
+ return listener.BlockForFrame(timeout);
+ }
+ finally
+ {
+ _protocolListener.RemoveFrameListener(listener);
+ }
+ // When control resumes before this line, a reply will have been received
+ // that matches the criteria defined in the blocking listener
+ }
+
+ /// <summary>
+ /// Convenience method that writes a frame to the protocol session and waits for
+ /// a particular response. Equivalent to calling getProtocolSession().write() then
+ /// waiting for the response.
+ /// </summary>
+ /// <param name="frame">the frame</param>
+ /// <param name="responseType">the type of method response</param>
+ public AMQMethodEvent SyncWrite(AMQFrame frame, Type responseType)
+ {
+ // TODO: If each frame knew it's response type, then the responseType argument would
+ // TODO: not be neccesary.
+ return SyncWrite(frame, responseType, DefaultTimeouts.MaxWaitForSyncWriter);
+ }
+
+ /// <summary>
+ /// Convenience method that writes a frame to the protocol session and waits for
+ /// a particular response. Equivalent to calling getProtocolSession().write() then
+ /// waiting for the response.
+ /// </summary>
+ /// <param name="frame">the frame</param>
+ /// <param name="responseType">the type of method response</param>
+ /// <param name="timeout">set the number of milliseconds to wait</param>
+ /// <returns>set the number of milliseconds to wait</returns>
+ public AMQMethodEvent SyncWrite(AMQFrame frame, Type responseType, int timeout)
+ {
+ return SyncWrite(frame, new SpecificMethodFrameListener(frame.Channel, responseType), timeout);
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs b/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs
new file mode 100644
index 0000000000..ede8966f37
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs
@@ -0,0 +1,504 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Net;
+using System.Text;
+using System.Text.RegularExpressions;
+using log4net;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client
+{
+
+ public class URLHelper
+ {
+ public static char DEFAULT_OPTION_SEPERATOR = '&';
+ public static char ALTERNATIVE_OPTION_SEPARATOR = ',';
+ public static char BROKER_SEPARATOR = ';';
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="optionMap"></param>
+ /// <param name="options"></param>
+ public static void parseOptions(IDictionary optionMap, string options)
+ {
+ //options looks like this
+ //brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value''
+
+ if (options == null || options.IndexOf('=') == -1)
+ {
+ return;
+ }
+
+ int optionIndex = options.IndexOf('=');
+
+ String option = options.Substring(0, optionIndex);
+
+ int length = options.Length;
+
+ int nestedQuotes = 0;
+
+ // to store index of final "'"
+ int valueIndex = optionIndex;
+
+ //Walk remainder of url.
+ while (nestedQuotes > 0 || valueIndex < length)
+ {
+ valueIndex++;
+
+ if (valueIndex >= length)
+ {
+ break;
+ }
+
+ if (options[valueIndex] == '\'')
+ {
+ if (valueIndex + 1 < options.Length)
+ {
+ if (options[valueIndex + 1] == DEFAULT_OPTION_SEPERATOR ||
+ options[valueIndex + 1] == ALTERNATIVE_OPTION_SEPARATOR ||
+ options[valueIndex + 1] == BROKER_SEPARATOR ||
+ options[valueIndex + 1] == '\'')
+ {
+ nestedQuotes--;
+ // System.out.println(
+ // options + "\n" + "-" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1));
+ if (nestedQuotes == 0)
+ {
+ //We've found the value of an option
+ break;
+ }
+ }
+ else
+ {
+ nestedQuotes++;
+ // System.out.println(
+ // options + "\n" + "+" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1));
+ }
+ }
+ else
+ {
+ // We are at the end of the string
+ // Check to see if we are corectly closing quotes
+ if (options[valueIndex] == '\'')
+ {
+ nestedQuotes--;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (nestedQuotes != 0 || valueIndex < (optionIndex + 2))
+ {
+ int sepIndex = 0;
+
+ //Try and identify illegal separator character
+ if (nestedQuotes > 1)
+ {
+ for (int i = 0; i < nestedQuotes; i++)
+ {
+ sepIndex = options.IndexOf('\'', sepIndex);
+ sepIndex++;
+ }
+ }
+
+ if (sepIndex >= options.Length || sepIndex == 0)
+ {
+ parseError(valueIndex, "Unterminated option", options);
+ }
+ else
+ {
+ parseError(sepIndex, "Unterminated option. Possible illegal option separator:'" +
+ options[sepIndex] + "'", options);
+ }
+ }
+
+ // optionIndex +2 to skip "='"
+ int sublen = valueIndex - (optionIndex + 2);
+ String value = options.Substring(optionIndex + 2, sublen);
+
+ optionMap.Add(option, value);
+
+ if (valueIndex < (options.Length - 1))
+ {
+ //Recurse to get remaining options
+ parseOptions(optionMap, options.Substring(valueIndex + 2));
+ }
+ }
+
+
+ public static void parseError(int index, String error, String url)
+ {
+ parseError(index, 1, error, url);
+ }
+
+ public static void parseError(int index, int length, String error, String url)
+ {
+ throw new UrlSyntaxException(url, error, index, length);
+ }
+
+ public static String printOptions(Hashtable options)
+ {
+ if (options.Count == 0)
+ {
+ return "";
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append('?');
+ foreach (String key in options.Keys)
+ {
+ sb.AppendFormat("{0}='{1}'{2}", key, options[key], DEFAULT_OPTION_SEPERATOR);
+ }
+
+ sb.Remove(sb.Length - 1, 1);
+ return sb.ToString();
+ }
+ }
+
+ }
+
+ public class QpidConnectionUrl
+ {
+ internal static IConnectionInfo FromUrl(string fullURL)
+ {
+ //_url = fullURL;
+ IConnectionInfo connectionInfo = new QpidConnectionInfo();
+
+
+ // _options = new HashMap<String, String>();
+ // _brokers = new LinkedList();
+ // _failoverOptions = new HashMap<String, String>();
+
+ // Connection URL format
+ //amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''"
+ // Options are of course optional except for requiring a single broker in the broker list.
+ try
+ {
+ Uri connection = new Uri(fullURL);
+
+ if (connection.Scheme == null || !(connection.Scheme.Equals(ConnectionUrlConstants.AMQ_PROTOCOL)))
+ {
+ throw new UrlSyntaxException(fullURL, "Not an AMQP URL");
+ }
+
+ if (connection.Host != null && connection.Host.Length > 0 && !connection.Host.Equals("default"))
+ {
+ connectionInfo.ClientName = connection.Host;
+ }
+
+ String userInfo = connection.UserInfo;
+ if (userInfo == null || userInfo.Length == 0)
+ {
+ URLHelper.parseError(ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3,
+ "User information not found on url", fullURL);
+ }
+ else
+ {
+ parseUserInfo(userInfo, fullURL, connectionInfo);
+ }
+ String virtualHost = connection.AbsolutePath; // XXX: is AbsolutePath corrrect?
+
+ if (virtualHost != null && virtualHost.Length > 0)
+ {
+ connectionInfo.VirtualHost = virtualHost;
+ }
+ else
+ {
+ int authLength = connection.Authority.Length;
+ int start = ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3;
+ int testIndex = start + authLength;
+ if (testIndex < fullURL.Length && fullURL[testIndex] == '?')
+ {
+ URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL);
+ }
+ else
+ {
+ URLHelper.parseError(-1, "Virtual host not specified", fullURL);
+ }
+
+ }
+
+ QpidConnectionInfo qci = (QpidConnectionInfo)connectionInfo;
+ string query = connection.Query;
+ if (query[0] == '?') query = query.Substring(1);
+ URLHelper.parseOptions(qci.GetOptions(), query);
+
+ processOptions(connectionInfo);
+
+ //Fragment is #string (not used)
+ //System.out.println(connection.getFragment());
+ return connectionInfo;
+ }
+ catch (UriFormatException uris)
+ {
+ throw uris;
+ // if (uris is UrlSyntaxException)
+ // {
+ // throw uris;
+ // }
+ //
+ // int slash = fullURL.IndexOf("\\");
+ //
+ // if (slash == -1)
+ // {
+ // URLHelper.parseError(uris.GetIndex(), uris.getReason(), uris.getInput());
+ // }
+ // else
+ // {
+ // if (slash != 0 && fullURL.charAt(slash - 1) == ':')
+ // {
+ // URLHelper.parseError(slash - 2, fullURL.indexOf('?') - slash + 2, "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL);
+ // }
+ // else
+ // {
+ // URLHelper.parseError(slash, "Forward slash not allowed in URL", fullURL);
+ // }
+ // }
+ }
+ }
+
+ private static void parseUserInfo(String userinfo, string fullUrl, IConnectionInfo connectionInfo)
+ {
+ //user info = user:pass
+
+ int colonIndex = userinfo.IndexOf(':');
+
+ if (colonIndex == -1)
+ {
+ URLHelper.parseError(ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3,
+ userinfo.Length, "Null password in user information not allowed.", fullUrl);
+ }
+ else
+ {
+ connectionInfo.Username = userinfo.Substring(0, colonIndex);
+ connectionInfo.Password = userinfo.Substring(colonIndex + 1);
+ }
+ }
+
+ private static void processOptions(IConnectionInfo connectionInfo)
+ {
+ string brokerlist = connectionInfo.GetOption(ConnectionUrlConstants.OPTIONS_BROKERLIST);
+ if (brokerlist != null)
+ {
+ //brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'
+ Regex splitter = new Regex("" + URLHelper.BROKER_SEPARATOR);
+
+ foreach (string broker in splitter.Split(brokerlist))
+ {
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo(broker));
+ }
+
+ connectionInfo.SetOption(ConnectionUrlConstants.OPTIONS_BROKERLIST, null);
+ // _options.remove(OPTIONS_BROKERLIST);
+ }
+
+ string failover = connectionInfo.GetOption(ConnectionUrlConstants.OPTIONS_FAILOVER);
+ if (failover != null)
+ {
+ // failover='method?option='value',option='value''
+
+ int methodIndex = failover.IndexOf('?');
+
+ if (methodIndex > -1)
+ {
+ connectionInfo.FailoverMethod = failover.Substring(0, methodIndex);
+ QpidConnectionInfo qpidConnectionInfo = (QpidConnectionInfo)connectionInfo;
+ URLHelper.parseOptions(qpidConnectionInfo.GetFailoverOptions(),
+ failover.Substring(methodIndex + 1));
+ }
+ else
+ {
+ connectionInfo.FailoverMethod = failover;
+ }
+
+ connectionInfo.SetOption(ConnectionUrlConstants.OPTIONS_FAILOVER, null);
+ // _options.remove(OPTIONS_FAILOVER);
+ }
+ }
+
+ internal static IConnectionInfo FromUri(Uri uri)
+ {
+ return null; // FIXME
+
+ }
+ }
+
+ public class QpidConnectionInfo : IConnectionInfo
+ {
+ const string DEFAULT_VHOST = "/";
+ string _username = "guest";
+ string _password = "guest";
+ string _virtualHost = DEFAULT_VHOST;
+
+ string _failoverMethod = null;
+ IDictionary _failoverOptions = new Hashtable();
+ IDictionary _options = new Hashtable();
+ IList _brokerInfos = new ArrayList(); // List<BrokerInfo>
+ string _clientName = String.Format("{0}{1:G}", Dns.GetHostName(), DateTime.Now.Ticks);
+
+ public IDictionary GetFailoverOptions()
+ {
+ return _failoverOptions;
+ }
+
+ public IDictionary GetOptions()
+ {
+ return _options;
+ }
+
+ public static IConnectionInfo FromUrl(String url)
+ {
+ return QpidConnectionUrl.FromUrl(url);
+ }
+
+ public string AsUrl()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("{0}://", ConnectionUrlConstants.AMQ_PROTOCOL);
+
+ if (_username != null)
+ {
+ sb.Append(_username);
+ if (_password != null)
+ {
+ sb.AppendFormat(":{0}", _password);
+ }
+ sb.Append("@");
+ }
+
+ sb.Append(_clientName);
+ sb.Append(_virtualHost);
+ sb.Append(OptionsToString());
+
+ return sb.ToString();
+ }
+
+ private String OptionsToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("?{0}='", ConnectionUrlConstants.OPTIONS_BROKERLIST);
+
+ foreach (IBrokerInfo broker in _brokerInfos)
+ {
+ sb.AppendFormat("{0};", broker);
+ }
+
+ sb.Remove(sb.Length - 1, 1);
+ sb.Append("'");
+
+ if (_failoverMethod != null)
+ {
+ sb.AppendFormat("{0}{1}='{2}{3}'", URLHelper.DEFAULT_OPTION_SEPERATOR,
+ ConnectionUrlConstants.OPTIONS_FAILOVER,
+ _failoverMethod,
+ URLHelper.printOptions((Hashtable)_failoverOptions));
+ }
+
+ return sb.ToString();
+ }
+
+
+ public string FailoverMethod
+ {
+ get { return _failoverMethod; }
+ set { _failoverMethod = value; }
+ }
+
+ public string GetFailoverOption(string key)
+ {
+ return (string)_failoverOptions[key];
+ }
+
+ public int BrokerCount
+ {
+ get { return _brokerInfos.Count; }
+ }
+
+ public IBrokerInfo GetBrokerInfo(int index)
+ {
+ return (IBrokerInfo)_brokerInfos[index];
+ }
+
+ public void AddBrokerInfo(IBrokerInfo brokerInfo)
+ {
+ if (!_brokerInfos.Contains(brokerInfo))
+ {
+ _brokerInfos.Add(brokerInfo);
+ }
+ }
+
+ public IList GetAllBrokerInfos()
+ {
+ return _brokerInfos;
+ }
+
+ public string ClientName
+ {
+ get { return _clientName; }
+ set { _clientName = value; }
+ }
+
+ public string Username
+ {
+ get { return _username; }
+ set { _username = value; }
+ }
+
+ public string Password
+ {
+ get { return _password; }
+ set { _password = value; }
+ }
+
+ public string VirtualHost
+ {
+ get { return _virtualHost; }
+ set {
+ _virtualHost = value;
+ if ( _virtualHost == null || _virtualHost.Length == 0 )
+ _virtualHost = DEFAULT_VHOST;
+ if ( _virtualHost[0] != '/' )
+ _virtualHost = '/' + _virtualHost;
+ }
+ }
+
+ public string GetOption(string key)
+ {
+ return (string)_options[key];
+ }
+
+ public void SetOption(string key, string value)
+ {
+ _options[key] = value;
+ }
+
+ public override string ToString()
+ {
+ return AsUrl();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs b/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs
new file mode 100644
index 0000000000..9ac0381850
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Configuration;
+using System.Text;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+using Apache.Qpid.Client.Configuration;
+
+namespace Apache.Qpid.Client.Security
+{
+
+ /// <summary>
+ /// Helper class to map SASL mechanisms to our
+ /// internal ISaslCallbackHandler implementations.
+ /// </summary>
+ /// <remarks>
+ /// The set of configured callback handlers and their order
+ /// controls the selection of the SASL mechanism used for authentication.
+ /// <para>
+ /// You can either replace the default handler for CRAM-MD5 and PLAIN
+ /// authentication (the two default options) using the application
+ /// configuration file. Configuration is done by especifying the SASL
+ /// mechanism name (e.g PLAIN) and the type implementing the callback handler
+ /// used to provide any data required by the mechanism like username and password.
+ /// </para>
+ /// <para>
+ /// Callback handler types should implement the IAMQCallbackHandler interface.
+ /// </para>
+ /// <para>
+ /// New callbacks or authentication mechanisms can be configured like this:
+ /// </para>
+ /// <example><![CDATA[
+ /// <configuration>
+ /// <configSections>
+ /// <sectionGroup name="qpid.client">
+ /// <section name="authentication" type="Apache.Qpid.Client.Configuration.AuthenticationConfigurationSectionHandler, Apache.Qpid.Client"/>
+ /// </sectionGroup>
+ /// </configSections>
+ /// <qpid.client>
+ /// <authentication>
+ /// <add key="TEST" value="Apache.Qpid.Client.Tests.Security.TestCallbackHandler, Apache.Qpid.Client.Tests"/>
+ /// </authentication>
+ /// </qpid.client>
+ /// </configuration>
+ /// ]]></example>
+ /// </remarks>
+ public sealed class CallbackHandlerRegistry
+ {
+ private static CallbackHandlerRegistry _instance =
+ new CallbackHandlerRegistry();
+ private OrderedHashTable _mechanism2HandlerMap;
+ private string[] _mechanisms;
+
+ public static CallbackHandlerRegistry Instance
+ {
+ get { return _instance; }
+ }
+
+ public string[] Mechanisms
+ {
+ get { return _mechanisms; }
+ }
+
+ private CallbackHandlerRegistry()
+ {
+ _mechanism2HandlerMap = (OrderedHashTable)
+ ConfigurationSettings.GetConfig("qpid.client/authentication");
+
+ // configure default options if not available
+ if ( _mechanism2HandlerMap == null )
+ _mechanism2HandlerMap = new OrderedHashTable();
+
+ if ( !_mechanism2HandlerMap.Contains(ExternalSaslClient.Mechanism) )
+ _mechanism2HandlerMap.Add(ExternalSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler));
+ if ( !_mechanism2HandlerMap.Contains(CramMD5SaslClient.Mechanism) )
+ _mechanism2HandlerMap.Add(CramMD5SaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler));
+ if ( !_mechanism2HandlerMap.Contains(CramMD5HexSaslClient.Mechanism) )
+ _mechanism2HandlerMap.Add(CramMD5HexSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler));
+ if ( !_mechanism2HandlerMap.Contains(PlainSaslClient.Mechanism) )
+ _mechanism2HandlerMap.Add(PlainSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler));
+
+ _mechanisms = new string[_mechanism2HandlerMap.Count];
+ _mechanism2HandlerMap.OrderedKeys.CopyTo(_mechanisms, 0);
+ }
+
+ public bool IsSupportedMechanism(string mechanism)
+ {
+ return _mechanism2HandlerMap.Contains(mechanism);
+ }
+
+ public string ChooseMechanism(string mechanisms)
+ {
+ IList mechs = mechanisms.Split(' ');
+ foreach ( string supportedMech in _mechanisms )
+ {
+ if ( mechs.Contains(supportedMech) )
+ return supportedMech;
+ }
+ return null;
+ }
+
+ public Type GetCallbackHandler(string mechanism)
+ {
+ return (Type)_mechanism2HandlerMap[mechanism];
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Security/IAMQCallbackHandler.cs b/dotnet/Qpid.Client/Client/Security/IAMQCallbackHandler.cs
new file mode 100644
index 0000000000..6ff45be04a
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Security/IAMQCallbackHandler.cs
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Text;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Sasl;
+
+namespace Apache.Qpid.Client.Security
+{
+ public interface IAMQCallbackHandler : ISaslCallbackHandler
+ {
+ void Initialize(AMQProtocolSession session);
+ }
+
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Security/UsernamePasswordCallbackHandler.cs b/dotnet/Qpid.Client/Client/Security/UsernamePasswordCallbackHandler.cs
new file mode 100644
index 0000000000..743ade77c9
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Security/UsernamePasswordCallbackHandler.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Sasl;
+
+namespace Apache.Qpid.Client.Security
+{
+ internal class UsernamePasswordCallbackHandler : IAMQCallbackHandler
+ {
+ private AMQProtocolSession _session;
+
+ public void Initialize(AMQProtocolSession session)
+ {
+ if ( session == null )
+ throw new ArgumentNullException("session");
+
+ _session = session;
+ }
+
+ public void Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = _session.Username;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = _session.Password;
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/SslOptions.cs b/dotnet/Qpid.Client/Client/SslOptions.cs
new file mode 100644
index 0000000000..4630121828
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/SslOptions.cs
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Apache.Qpid.Client
+{
+ /// <summary>
+ /// Configures SSL-related options to connect to an AMQP broker.
+ /// </summary>
+ /// <remarks>
+ /// If the server certificate is not trusted by the client,
+ /// connection will fail. However, you can set the
+ /// <see cref="IgnoreValidationErrors"/> property to true
+ /// to ignore any certificate verification errors for debugging purposes.
+ /// </remarks>
+ public class SslOptions
+ {
+ private X509Certificate _clientCertificate;
+ private bool _ignoreValidationErrors;
+
+ /// <summary>
+ /// Certificate to present to the broker to authenticate
+ /// this client connection
+ /// </summary>
+ public X509Certificate ClientCertificate
+ {
+ get { return _clientCertificate; }
+ }
+
+ /// <summary>
+ /// If true, the validity of the broker certificate
+ /// will not be verified on connection
+ /// </summary>
+ public bool IgnoreValidationErrors
+ {
+ get { return _ignoreValidationErrors; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance with default values
+ /// (No client certificate, don't ignore validation errors)
+ /// </summary>
+ public SslOptions()
+ {
+ }
+
+ /// <summary>
+ /// Initialize a new instance
+ /// </summary>
+ /// <param name="clientCertificate">
+ /// Certificate to use to authenticate the client to the broker
+ /// </param>
+ /// <param name="ignoreValidationErrors">
+ /// If true, ignore any validation errors when validating the server certificate
+ /// </param>
+ public SslOptions(X509Certificate clientCertificate, bool ignoreValidationErrors)
+ {
+ _clientCertificate = clientCertificate;
+ _ignoreValidationErrors = ignoreValidationErrors;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/State/AMQState.cs b/dotnet/Qpid.Client/Client/State/AMQState.cs
new file mode 100644
index 0000000000..67f8427fb2
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/AMQState.cs
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace Apache.Qpid.Client.State
+{
+ public enum AMQState
+ {
+ CONNECTION_NOT_STARTED,
+ CONNECTION_NOT_TUNED,
+ CONNECTION_NOT_OPENED,
+ CONNECTION_OPEN,
+ CONNECTION_CLOSING,
+ CONNECTION_CLOSED,
+ ALL // all is a special state used in the state manager. It is not valid to be "in" the state "all".
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/State/AMQStateChangedEvent.cs b/dotnet/Qpid.Client/Client/State/AMQStateChangedEvent.cs
new file mode 100644
index 0000000000..a464bbb6f5
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/AMQStateChangedEvent.cs
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Client.State
+{
+ public class AMQStateChangedEvent
+ {
+ private readonly AMQState _oldState;
+
+ private readonly AMQState _newState;
+
+ public AMQStateChangedEvent(AMQState oldState, AMQState newState)
+ {
+ _oldState = oldState;
+ _newState = newState;
+ }
+
+ public AMQState OldState
+ {
+ get
+ {
+ return _oldState;
+ }
+ }
+
+ public AMQState NewState
+ {
+ get
+ {
+ return _newState;
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/State/AMQStateManager.cs b/dotnet/Qpid.Client/Client/State/AMQStateManager.cs
new file mode 100644
index 0000000000..881e01e697
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/AMQStateManager.cs
@@ -0,0 +1,251 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using log4net;
+using Apache.Qpid.Client.Handler;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Client.Protocol.Listener;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.State
+{
+ public class AMQStateManager : IAMQMethodListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(AMQStateManager));
+
+ const bool InfoLoggingHack = true;
+
+ /// <summary>
+ /// The current state
+ /// </summary>
+ private AMQState _currentState;
+
+ /// <summary>
+ /// Maps from an AMQState instance to a Map from Class to StateTransitionHandler.
+ /// The class must be a subclass of AMQFrame.
+ /// </summary>
+ private readonly IDictionary _state2HandlersMap;
+ private ArrayList _stateListeners;
+ private object _syncLock;
+
+ public AMQStateManager()
+ {
+ _syncLock = new object();
+ _state2HandlersMap = new Hashtable();
+ _stateListeners = ArrayList.Synchronized(new ArrayList(5));
+ _currentState = AMQState.CONNECTION_NOT_STARTED;
+ RegisterListeners();
+ }
+
+ private void RegisterListeners()
+ {
+ IStateAwareMethodListener connectionStart = new ConnectionStartMethodHandler();
+ IStateAwareMethodListener connectionClose = new ConnectionCloseMethodHandler();
+ IStateAwareMethodListener connectionCloseOk = new ConnectionCloseOkHandler();
+ IStateAwareMethodListener connectionTune = new ConnectionTuneMethodHandler();
+ IStateAwareMethodListener connectionSecure = new ConnectionSecureMethodHandler();
+ IStateAwareMethodListener connectionOpenOk = new ConnectionOpenOkMethodHandler();
+ IStateAwareMethodListener channelClose = new ChannelCloseMethodHandler();
+ IStateAwareMethodListener basicDeliver = new BasicDeliverMethodHandler();
+ IStateAwareMethodListener basicReturn = new BasicReturnMethodHandler();
+ IStateAwareMethodListener queueDeleteOk = new QueueDeleteOkMethodHandler();
+ IStateAwareMethodListener queuePurgeOk = new QueuePurgeOkMethodHandler();
+
+ // We need to register a map for the null (i.e. all state) handlers otherwise you get
+ // a stack overflow in the handler searching code when you present it with a frame for which
+ // no handlers are registered.
+ _state2HandlersMap[AMQState.ALL] = new Hashtable();
+
+ {
+ Hashtable notStarted = new Hashtable();
+ notStarted[typeof(ConnectionStartBody)] = connectionStart;
+ notStarted[typeof(ConnectionCloseBody)] = connectionClose;
+ _state2HandlersMap[AMQState.CONNECTION_NOT_STARTED] = notStarted;
+ }
+ {
+ Hashtable notTuned = new Hashtable();
+ notTuned[typeof(ConnectionTuneBody)] = connectionTune;
+ notTuned[typeof(ConnectionSecureBody)] = connectionSecure;
+ notTuned[typeof(ConnectionCloseBody)] = connectionClose;
+ _state2HandlersMap[AMQState.CONNECTION_NOT_TUNED] = notTuned;
+ }
+ {
+ Hashtable notOpened = new Hashtable();
+ notOpened[typeof(ConnectionOpenOkBody)] = connectionOpenOk;
+ notOpened[typeof(ConnectionCloseBody)] = connectionClose;
+ _state2HandlersMap[AMQState.CONNECTION_NOT_OPENED] = notOpened;
+ }
+ {
+ Hashtable open = new Hashtable();
+ open[typeof(ChannelCloseBody)] = channelClose;
+ open[typeof(ConnectionCloseBody)] = connectionClose;
+ open[typeof(BasicDeliverBody)] = basicDeliver;
+ open[typeof(BasicReturnBody)] = basicReturn;
+ open[typeof(QueueDeleteOkBody)] = queueDeleteOk;
+ open[typeof(QueuePurgeOkBody)] = queuePurgeOk;
+ _state2HandlersMap[AMQState.CONNECTION_OPEN] = open;
+ }
+ {
+ Hashtable closing = new Hashtable();
+ closing[typeof(ConnectionCloseOkBody)] = connectionCloseOk;
+ _state2HandlersMap[AMQState.CONNECTION_CLOSING] = closing;
+ }
+ }
+
+ public AMQState CurrentState
+ {
+ get
+ {
+ return _currentState;
+ }
+ }
+
+ /// <summary>
+ /// Changes the state.
+ /// </summary>
+ /// <param name="newState">The new state.</param>
+ /// <exception cref="AMQException">if there is an error changing state</exception>
+ public void ChangeState(AMQState newState)
+ {
+ if (InfoLoggingHack)
+ {
+ _logger.Debug("State changing to " + newState + " from old state " + _currentState);
+ }
+ _logger.Debug("State changing to " + newState + " from old state " + _currentState);
+ AMQState oldState = _currentState;
+ _currentState = newState;
+
+ lock ( _syncLock )
+ {
+ foreach ( IStateListener l in _stateListeners )
+ {
+ l.StateChanged(oldState, newState);
+ }
+ }
+ }
+
+ public void Error(Exception e)
+ {
+ _logger.Debug("State manager receive error notification: " + e);
+ lock ( _syncLock )
+ {
+ foreach ( IStateListener l in _stateListeners )
+ {
+ l.Error(e);
+ }
+ }
+ }
+
+ public bool MethodReceived(AMQMethodEvent evt)
+ {
+ _logger.Debug(String.Format("Finding method handler. currentState={0} type={1}", _currentState, evt.Method.GetType()));
+ IStateAwareMethodListener handler = FindStateTransitionHandler(_currentState, evt.Method);
+ if (handler != null)
+ {
+ handler.MethodReceived(this, evt);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Finds the state transition handler.
+ /// </summary>
+ /// <param name="currentState">State of the current.</param>
+ /// <param name="frame">The frame.</param>
+ /// <returns></returns>
+ /// <exception cref="IllegalStateTransitionException">if the state transition if not allowed</exception>
+ private IStateAwareMethodListener FindStateTransitionHandler(AMQState currentState,
+ AMQMethodBody frame)
+ {
+ Type clazz = frame.GetType();
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Looking for state transition handler for frame " + clazz);
+ }
+ IDictionary classToHandlerMap = (IDictionary) _state2HandlersMap[currentState];
+
+ if (classToHandlerMap == null)
+ {
+ // if no specialised per state handler is registered look for a
+ // handler registered for "all" states
+ return FindStateTransitionHandler(AMQState.ALL, frame);
+ }
+ IStateAwareMethodListener handler = (IStateAwareMethodListener) classToHandlerMap[clazz];
+ if (handler == null)
+ {
+ if (currentState == AMQState.ALL)
+ {
+ _logger.Debug("No state transition handler defined for receiving frame " + frame);
+ return null;
+ }
+ else
+ {
+ // if no specialised per state handler is registered look for a
+ // handler registered for "all" states
+ return FindStateTransitionHandler(AMQState.ALL, frame);
+ }
+ }
+ else
+ {
+ return handler;
+ }
+ }
+
+ public void AddStateListener(IStateListener listener)
+ {
+ _logger.Debug("Adding state listener");
+ lock ( _syncLock )
+ {
+ _stateListeners.Add(listener);
+ }
+ }
+
+ public void RemoveStateListener(IStateListener listener)
+ {
+ lock ( _syncLock )
+ {
+ _stateListeners.Remove(listener);
+ }
+ }
+
+ public void AttainState(AMQState s)
+ {
+ if (_currentState != s)
+ {
+ StateWaiter sw = null;
+ try
+ {
+ _logger.Debug("Adding state wait to reach state " + s);
+ sw = new StateWaiter(s);
+ AddStateListener(sw);
+ sw.WaituntilStateHasChanged();
+ // at this point the state will have changed.
+ }
+ finally
+ {
+ RemoveStateListener(sw);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/State/IAMQStateListener.cs b/dotnet/Qpid.Client/Client/State/IAMQStateListener.cs
new file mode 100644
index 0000000000..31e4b5046d
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/IAMQStateListener.cs
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Client.State
+{
+ public interface IAMQStateListener
+ {
+ void StateChanged(AMQStateChangedEvent evt);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/State/IStateAwareMethodListener.cs b/dotnet/Qpid.Client/Client/State/IStateAwareMethodListener.cs
new file mode 100644
index 0000000000..0874f39665
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/IStateAwareMethodListener.cs
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Client.Protocol;
+
+namespace Apache.Qpid.Client.State
+{
+ public interface IStateAwareMethodListener
+ {
+ void MethodReceived(AMQStateManager stateManager, AMQMethodEvent evt);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/State/IStateListener.cs b/dotnet/Qpid.Client/Client/State/IStateListener.cs
new file mode 100644
index 0000000000..edd7382f93
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/IStateListener.cs
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client.State
+{
+ public interface IStateListener
+ {
+ void StateChanged(AMQState oldState, AMQState newState);
+
+ void Error(Exception e);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/State/IllegalStateTransitionException.cs b/dotnet/Qpid.Client/Client/State/IllegalStateTransitionException.cs
new file mode 100644
index 0000000000..81de622617
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/IllegalStateTransitionException.cs
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Client.State
+{
+ [Serializable]
+ public class IllegalStateTransitionException : AMQException
+ {
+ private AMQState _originalState;
+
+ private Type _frame;
+
+ public IllegalStateTransitionException(AMQState originalState, Type frame)
+ : base("No valid state transition defined for receiving frame " + frame +
+ " from state " + originalState)
+ {
+ _originalState = originalState;
+ _frame = frame;
+ }
+
+ protected IllegalStateTransitionException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _originalState = (AMQState)info.GetValue("OriginalState", typeof(AMQState));
+ _frame = (Type)info.GetValue("FrameType", typeof(Type));
+ }
+
+ public AMQState OriginalState
+ {
+ get
+ {
+ return _originalState;
+ }
+ }
+
+ public Type FrameType
+ {
+ get
+ {
+ return _frame;
+ }
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("OriginalState", OriginalState);
+ info.AddValue("FrameType", FrameType);
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Client/Client/State/StateWaiter.cs b/dotnet/Qpid.Client/Client/State/StateWaiter.cs
new file mode 100644
index 0000000000..e739d0cb44
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/State/StateWaiter.cs
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using Apache.Qpid.Client.Protocol;
+using log4net;
+
+namespace Apache.Qpid.Client.State
+{
+ public class StateWaiter : IStateListener
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(StateWaiter));
+
+ private readonly AMQState _state;
+ private AMQState _newState;
+
+ private volatile bool _newStateAchieved;
+
+ private volatile Exception _exception;
+
+ private ManualResetEvent _resetEvent = new ManualResetEvent(false);
+
+ public StateWaiter(AMQState state)
+ {
+ _state = state;
+ }
+
+ public void StateChanged(AMQState oldState, AMQState newState)
+ {
+ _newState = newState;
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("stateChanged called");
+ }
+ if (_state == newState)
+ {
+ _newStateAchieved = true;
+
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("New state reached so notifying monitor");
+ }
+ _resetEvent.Set();
+ }
+ }
+
+ public void Error(Exception e)
+ {
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("exceptionThrown called");
+ }
+
+ _exception = e;
+ _resetEvent.Set();
+ }
+
+ public void WaituntilStateHasChanged()
+ {
+ //
+ // The guard is required in case we are woken up by a spurious
+ // notify().
+ //
+
+ TimeSpan waitTime = TimeSpan.FromMilliseconds(DefaultTimeouts.MaxWaitForState);
+ DateTime waitUntilTime = DateTime.Now + waitTime;
+
+ while ( !_newStateAchieved
+ && _exception == null
+ && waitTime.TotalMilliseconds > 0 )
+ {
+ _logger.Debug("State not achieved so waiting...");
+ try
+ {
+ _resetEvent.WaitOne(waitTime, true);
+ }
+ finally
+ {
+ if (!_newStateAchieved)
+ {
+ waitTime = waitUntilTime - DateTime.Now;
+ }
+ }
+ }
+
+ if (_exception != null)
+ {
+ _logger.Debug("Throwable reached state waiter: " + _exception);
+ if (_exception is AMQException)
+ throw _exception;
+ else
+ throw new AMQException("Error: " + _exception, _exception);
+ }
+
+ if (!_newStateAchieved)
+ {
+ string error = string.Format("State not achieved within permitted time. Current state: {0}, desired state: {1}", _state, _newState);
+ _logger.Warn(error);
+ throw new AMQException(error);
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/AMQProtocolProvider.cs b/dotnet/Qpid.Client/Client/Transport/AMQProtocolProvider.cs
new file mode 100644
index 0000000000..dd0bb404cb
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/AMQProtocolProvider.cs
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Codec;
+using Apache.Qpid.Codec.Demux;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public class AMQProtocolProvider
+ {
+ private DemuxingProtocolCodecFactory _factory;
+
+ public AMQProtocolProvider()
+ {
+ _factory = new DemuxingProtocolCodecFactory();
+ _factory.Register(new AMQDataBlockEncoder());
+ _factory.Register(new AMQDataBlockDecoder());
+ _factory.Register(new ProtocolInitiation.Decoder());
+ }
+
+ public IProtocolCodecFactory CodecFactory
+ {
+ get
+ {
+ return _factory;
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs b/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs
new file mode 100644
index 0000000000..1e217e755b
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/AmqpChannel.cs
@@ -0,0 +1,111 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Collections;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Codec.Support;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public class AmqpChannel : IProtocolChannel
+ {
+ // Warning: don't use this log for regular logging.
+ static readonly ILog _protocolTraceLog = LogManager.GetLogger("TRACE.Qpid.Client.ProtocolChannel");
+
+ IByteChannel _byteChannel;
+ IProtocolEncoder _encoder;
+ IProtocolDecoder _decoder;
+ IProtocolDecoderOutput _decoderOutput;
+ private object _syncLock;
+
+ public AmqpChannel(IByteChannel byteChannel, IProtocolDecoderOutput decoderOutput)
+ {
+ _byteChannel = byteChannel;
+ _decoderOutput = decoderOutput;
+ _syncLock = new object();
+
+ AMQProtocolProvider protocolProvider = new AMQProtocolProvider();
+ IProtocolCodecFactory factory = protocolProvider.CodecFactory;
+ _encoder = factory.Encoder;
+ _decoder = factory.Decoder;
+ }
+
+ public void Read()
+ {
+ ByteBuffer buffer = _byteChannel.Read();
+ Decode(buffer);
+ }
+
+ public IAsyncResult BeginRead(AsyncCallback callback, object state)
+ {
+ return _byteChannel.BeginRead(callback, state);
+ }
+
+ public void EndRead(IAsyncResult result)
+ {
+ ByteBuffer buffer = _byteChannel.EndRead(result);
+ Decode(buffer);
+ }
+
+ public void Write(IDataBlock o)
+ {
+ // TODO: Refactor to decorator.
+ if (_protocolTraceLog.IsDebugEnabled)
+ {
+ _protocolTraceLog.Debug(String.Format("WRITE {0}", o));
+ }
+ // we should be doing an async write, but apparently
+ // the mentalis library doesn't queue async read/writes
+ // correctly and throws random IOException's. Stay sync for a while
+ //_byteChannel.BeginWrite(Encode(o), OnAsyncWriteDone, null);
+ _byteChannel.Write(Encode(o));
+ }
+
+ // not used for now
+ //private void OnAsyncWriteDone(IAsyncResult result)
+ //{
+ // _byteChannel.EndWrite(result);
+ //}
+
+ private void Decode(ByteBuffer buffer)
+ {
+ // make sure we don't try to decode more than
+ // one buffer at the same time
+ lock ( _syncLock )
+ {
+ _decoder.Decode(buffer, _decoderOutput);
+ }
+ }
+
+ private ByteBuffer Encode(object o)
+ {
+ SingleProtocolEncoderOutput output = new SingleProtocolEncoderOutput();
+ _encoder.Encode(o, output);
+ return output.buffer;
+ }
+
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Transport/IByteChannel.cs b/dotnet/Qpid.Client/Client/Transport/IByteChannel.cs
new file mode 100644
index 0000000000..35806f2a6e
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/IByteChannel.cs
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Transport
+{
+ /// <summary>
+ /// Represents input/output channels that read
+ /// and write <see cref="ByteBuffer"/> instances
+ /// </summary>
+ public interface IByteChannel
+ {
+ /// <summary>
+ /// Read a <see cref="ByteBuffer"/> from the underlying
+ /// network stream and any configured filters
+ /// </summary>
+ /// <returns>A ByteBuffer, if available</returns>
+ ByteBuffer Read();
+ /// <summary>
+ /// Begin an asynchronous read operation
+ /// </summary>
+ /// <param name="callback">Callback method to call when read operation completes</param>
+ /// <param name="state">State object</param>
+ /// <returns>An <see cref="System.IAsyncResult"/> object</returns>
+ IAsyncResult BeginRead(AsyncCallback callback, object state);
+ /// <summary>
+ /// End an asynchronous read operation
+ /// </summary>
+ /// <param name="result">The <see cref="System.IAsyncResult"/> object returned from <see cref="BeginRead"/></param>
+ /// <returns>The <see cref="ByteBuffer"/> read</returns>
+ ByteBuffer EndRead(IAsyncResult result);
+ /// <summary>
+ /// Write a <see cref="ByteBuffer"/> to the underlying network
+ /// stream, going through any configured filters
+ /// </summary>
+ /// <param name="buffer"></param>
+ void Write(ByteBuffer buffer);
+ /// <summary>
+ /// Begin an asynchronous write operation
+ /// </summary>
+ /// <param name="buffer">Buffer to write</param>
+ /// <param name="callback">A callback to call when the operation completes</param>
+ /// <param name="state">State object</param>
+ /// <returns>An <see cref="System.IAsyncResult"/> object</returns>
+ IAsyncResult BeginWrite(ByteBuffer buffer, AsyncCallback callback, object state);
+ /// <summary>
+ /// End an asynchronous write operation
+ /// </summary>
+ /// <param name="result">The <see cref="System.IAsyncResult"/> object returned by <see cref="BeginWrite"/></param>
+ void EndWrite(IAsyncResult result);
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/IProtocolChannel.cs b/dotnet/Qpid.Client/Client/Transport/IProtocolChannel.cs
new file mode 100644
index 0000000000..0b59ee8799
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/IProtocolChannel.cs
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public interface IProtocolChannel : IProtocolWriter
+ {
+ void Read();
+ IAsyncResult BeginRead(AsyncCallback callback, object state);
+ void EndRead(IAsyncResult result);
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/IProtocolWriter.cs b/dotnet/Qpid.Client/Client/Transport/IProtocolWriter.cs
new file mode 100644
index 0000000000..592dff3a19
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/IProtocolWriter.cs
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public interface IProtocolWriter
+ {
+ void Write(IDataBlock o);
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/IStreamFilter.cs b/dotnet/Qpid.Client/Client/Transport/IStreamFilter.cs
new file mode 100644
index 0000000000..e0e890fc5a
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/IStreamFilter.cs
@@ -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.
+ *
+ */
+using System.IO;
+
+namespace Apache.Qpid.Client.Transport
+{
+ /// <summary>
+ /// Defines a way to introduce an arbitrary filtering
+ /// stream into the stream chain managed by <see cref="IoHandler"/>
+ /// </summary>
+ public interface IStreamFilter
+ {
+ /// <summary>
+ /// Creates a new filtering stream on top of another
+ /// </summary>
+ /// <param name="lowerStream">Next stream on the stack</param>
+ /// <returns>A new filtering stream</returns>
+ Stream CreateFilterStream(Stream lowerStream);
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/ITransport.cs b/dotnet/Qpid.Client/Client/Transport/ITransport.cs
new file mode 100644
index 0000000000..693a9a9534
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/ITransport.cs
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client.Protocol;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public interface ITransport : IConnectionCloser
+ {
+ void Connect(IBrokerInfo broker, AMQConnection connection);
+ string LocalEndpoint { get; }
+ IProtocolWriter ProtocolWriter { get; }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/IoHandler.cs b/dotnet/Qpid.Client/Client/Transport/IoHandler.cs
new file mode 100644
index 0000000000..0475236d92
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/IoHandler.cs
@@ -0,0 +1,322 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.IO;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Client.Protocol;
+
+namespace Apache.Qpid.Client.Transport
+{
+ /// <summary>
+ /// Responsible for reading and writing
+ /// ByteBuffers from/to network streams, and handling
+ /// the stream filters
+ /// </summary>
+ public class IoHandler : IByteChannel, IDisposable
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(IoHandler));
+ private const int DEFAULT_BUFFER_SIZE = 32 * 1024;
+
+ private Stream _topStream;
+ private IProtocolListener _protocolListener;
+ private int _readBufferSize;
+
+ public int ReadBufferSize
+ {
+ get { return _readBufferSize; }
+ set { _readBufferSize = value; }
+ }
+
+ /// <summary>
+ /// Initialize a new instance
+ /// </summary>
+ /// <param name="stream">Underlying network stream</param>
+ /// <param name="protocolListener">Protocol listener to report exceptions to</param>
+ public IoHandler(Stream stream, IProtocolListener protocolListener)
+ {
+ if ( stream == null )
+ throw new ArgumentNullException("stream");
+ if ( protocolListener == null )
+ throw new ArgumentNullException("protocolListener");
+
+ // initially, the stream at the top of the filter
+ // chain is the underlying network stream
+ _topStream = stream;
+ _protocolListener = protocolListener;
+ _readBufferSize = DEFAULT_BUFFER_SIZE;
+ }
+
+ /// <summary>
+ /// Adds a new filter on the top of the chain
+ /// </summary>
+ /// <param name="filter">Stream filter to put on top of the chain</param>
+ /// <remarks>
+ /// This should *only* be called during initialization. We don't
+ /// support changing the filter change after the first read/write
+ /// has been done and it's not thread-safe to boot!
+ /// </remarks>
+ public void AddFilter(IStreamFilter filter)
+ {
+ _topStream = filter.CreateFilterStream(_topStream);
+ }
+
+ #region IByteChannel Implementation
+ //
+ // IByteChannel Implementation
+ //
+
+ /// <summary>
+ /// Read a <see cref="ByteBuffer"/> from the underlying
+ /// network stream and any configured filters
+ /// </summary>
+ /// <returns>A ByteBuffer, if available</returns>
+ public ByteBuffer Read()
+ {
+ byte[] bytes = AllocateBuffer();
+
+ int numOctets = _topStream.Read(bytes, 0, bytes.Length);
+
+ return WrapByteArray(bytes, numOctets);
+ }
+
+ /// <summary>
+ /// Begin an asynchronous read operation
+ /// </summary>
+ /// <param name="callback">Callback method to call when read operation completes</param>
+ /// <param name="state">State object</param>
+ /// <returns>An <see cref="System.IAsyncResult"/> object</returns>
+ public IAsyncResult BeginRead(AsyncCallback callback, object state)
+ {
+ byte[] bytes = AllocateBuffer();
+ ReadData rd = new ReadData(callback, state, bytes);
+
+ // only put a callback if the caller wants one.
+ AsyncCallback myCallback = null;
+ if ( callback != null )
+ myCallback = new AsyncCallback(OnAsyncReadDone);
+
+ IAsyncResult result = _topStream.BeginRead(
+ bytes, 0, bytes.Length, myCallback,rd
+ );
+ return new WrappedAsyncResult(result, bytes);
+ }
+
+ /// <summary>
+ /// End an asynchronous read operation
+ /// </summary>
+ /// <param name="result">The <see cref="System.IAsyncResult"/> object returned from <see cref="BeginRead"/></param>
+ /// <returns>The <see cref="ByteBuffer"/> read</returns>
+ public ByteBuffer EndRead(IAsyncResult result)
+ {
+ WrappedAsyncResult theResult = (WrappedAsyncResult)result;
+ int bytesRead = _topStream.EndRead(theResult.InnerResult);
+ return WrapByteArray(theResult.Buffer, bytesRead);
+ }
+
+ /// <summary>
+ /// Write a <see cref="ByteBuffer"/> to the underlying network
+ /// stream, going through any configured filters
+ /// </summary>
+ /// <param name="buffer"></param>
+ public void Write(ByteBuffer buffer)
+ {
+ try
+ {
+ _topStream.Write(buffer.Array, buffer.Position, buffer.Limit); // FIXME
+ }
+ catch (Exception e)
+ {
+ _log.Warn("Write caused exception", e);
+ _protocolListener.OnException(e);
+ }
+ }
+
+ /// <summary>
+ /// Begin an asynchronous write operation
+ /// </summary>
+ /// <param name="buffer">Buffer to write</param>
+ /// <param name="callback">A callback to call when the operation completes</param>
+ /// <param name="state">State object</param>
+ /// <returns>An <see cref="System.IAsyncResult"/> object</returns>
+ public IAsyncResult BeginWrite(ByteBuffer buffer, AsyncCallback callback, object state)
+ {
+ try
+ {
+ return _topStream.BeginWrite(
+ buffer.Array, buffer.Position, buffer.Limit,
+ callback, state
+ );
+ } catch ( Exception e )
+ {
+ _log.Error("BeginWrite caused exception", e);
+ // not clear if an exception here should be propagated? we still
+ // need to propagate it upwards anyway!
+ _protocolListener.OnException(e);
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// End an asynchronous write operation
+ /// </summary>
+ /// <param name="result">The <see cref="System.IAsyncResult"/> object returned by <see cref="BeginWrite"/></param>
+ public void EndWrite(IAsyncResult result)
+ {
+ try
+ {
+ _topStream.EndWrite(result);
+ } catch ( Exception e )
+ {
+ _log.Error("EndWrite caused exception", e);
+ // not clear if an exception here should be propagated?
+ _protocolListener.OnException(e);
+ //throw;
+ }
+ }
+ #endregion // IByteChannel Implementation
+
+ #region IDisposable Implementation
+ //
+ // IDisposable Implementation
+ //
+
+ public void Dispose()
+ {
+ if ( _topStream != null )
+ {
+ _topStream.Close();
+ }
+ }
+
+ #endregion // IDisposable Implementation
+
+ #region Private and Helper Classes/Methods
+ //
+ // Private and Helper Classes/Methods
+ //
+
+ private byte[] AllocateBuffer()
+ {
+ return new byte[ReadBufferSize];
+ }
+
+ private static ByteBuffer WrapByteArray(byte[] bytes, int size)
+ {
+ ByteBuffer byteBuffer = ByteBuffer.Wrap(bytes);
+ byteBuffer.Limit = size;
+ byteBuffer.Flip();
+
+ return byteBuffer;
+ }
+
+
+ private static void OnAsyncReadDone(IAsyncResult result)
+ {
+ ReadData rd = (ReadData) result.AsyncState;
+ IAsyncResult wrapped = new WrappedAsyncResult(result, rd.Buffer);
+ rd.Callback(wrapped);
+ }
+
+ class ReadData
+ {
+ private object _state;
+ private AsyncCallback _callback;
+ private byte[] _buffer;
+
+ public object State
+ {
+ get { return _state; }
+ }
+
+ public AsyncCallback Callback
+ {
+ get { return _callback; }
+ }
+
+ public byte[] Buffer
+ {
+ get { return _buffer; }
+ }
+
+ public ReadData(AsyncCallback callback, object state, byte[] buffer)
+ {
+ _callback = callback;
+ _state = state;
+ _buffer = buffer;
+ }
+ }
+
+ class WrappedAsyncResult : IAsyncResult
+ {
+ private IAsyncResult _innerResult;
+ private byte[] _buffer;
+
+ #region IAsyncResult Properties
+ //
+ // IAsyncResult Properties
+ //
+ public bool IsCompleted
+ {
+ get { return _innerResult.IsCompleted; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get { return _innerResult.AsyncWaitHandle; }
+ }
+
+ public object AsyncState
+ {
+ get { return _innerResult.AsyncState; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return _innerResult.CompletedSynchronously; }
+ }
+ #endregion // IAsyncResult Properties
+
+ public IAsyncResult InnerResult
+ {
+ get { return _innerResult; }
+ }
+ public byte[] Buffer
+ {
+ get { return _buffer; }
+ }
+
+ public WrappedAsyncResult(IAsyncResult result, byte[] buffer)
+ {
+ if ( result == null )
+ throw new ArgumentNullException("result");
+ if ( buffer == null )
+ throw new ArgumentNullException("buffer");
+
+ _innerResult = result;
+ _buffer = buffer;
+ }
+ }
+
+ #endregion // Private and Helper Classes/Methods
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/ProtocolDecoderOutput.cs b/dotnet/Qpid.Client/Client/Transport/ProtocolDecoderOutput.cs
new file mode 100644
index 0000000000..9fa313152f
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/ProtocolDecoderOutput.cs
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Framing;
+using log4net;
+
+namespace Apache.Qpid.Client.Transport
+{
+ /// <summary>
+ /// <see cref="IProtocolDecoderOutput"/> implementation that forwards
+ /// each <see cref="IDataBlock"/> as it is decoded to the
+ /// protocol listener
+ /// </summary>
+ internal class ProtocolDecoderOutput : IProtocolDecoderOutput
+ {
+ private IProtocolListener _protocolListener;
+ static readonly ILog _protocolTraceLog = LogManager.GetLogger("TRACE.Qpid.Client.ProtocolChannel");
+
+ public ProtocolDecoderOutput(IProtocolListener protocolListener)
+ {
+ if ( protocolListener == null )
+ throw new ArgumentNullException("protocolListener");
+
+ _protocolListener = protocolListener;
+ }
+
+ public void Write(object message)
+ {
+ IDataBlock block = message as IDataBlock;
+ if ( block != null )
+ {
+ _protocolTraceLog.Debug(String.Format("READ {0}", block));
+ _protocolListener.OnMessage(block);
+ }
+ }
+ }
+} // namespace Apache.Qpid.Client.Transport
+
+
diff --git a/dotnet/Qpid.Client/Client/Transport/SingleProtocolEncoderOutput.cs b/dotnet/Qpid.Client/Client/Transport/SingleProtocolEncoderOutput.cs
new file mode 100644
index 0000000000..a1aa889ba0
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/SingleProtocolEncoderOutput.cs
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Codec;
+
+namespace Apache.Qpid.Client.Transport
+{
+ public class SingleProtocolEncoderOutput : IProtocolEncoderOutput
+ {
+ public ByteBuffer buffer;
+
+ public void Write(ByteBuffer buf)
+ {
+ if (buffer != null)
+ {
+ throw new InvalidOperationException("{0} does not allow the writing of more than one buffer");
+ }
+ buffer = buf;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/BlockingSocketTransport.cs b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/BlockingSocketTransport.cs
new file mode 100644
index 0000000000..f336d8a80a
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/BlockingSocketTransport.cs
@@ -0,0 +1,150 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.IO;
+using System.Threading;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client.Protocol;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ /// <summary>
+ /// TCP Socket transport supporting both
+ /// SSL and non-SSL connections.
+ /// </summary>
+ public class BlockingSocketTransport : ITransport
+ {
+ // Configuration variables.
+ IProtocolListener _protocolListener;
+
+ // Runtime variables.
+ private ISocketConnector _connector;
+ private IoHandler _ioHandler;
+ private AmqpChannel _amqpChannel;
+ private ManualResetEvent _stopEvent;
+
+ public IProtocolWriter ProtocolWriter
+ {
+ get { return _amqpChannel; }
+ }
+ public string LocalEndpoint
+ {
+ get { return _connector.LocalEndpoint; }
+ }
+
+
+ /// <summary>
+ /// Connect to the specified broker
+ /// </summary>
+ /// <param name="broker">The broker to connect to</param>
+ /// <param name="connection">The AMQ connection</param>
+ public void Connect(IBrokerInfo broker, AMQConnection connection)
+ {
+ _stopEvent = new ManualResetEvent(false);
+ _protocolListener = connection.ProtocolListener;
+
+ _ioHandler = MakeBrokerConnection(broker, connection);
+ // todo: get default read size from config!
+
+ IProtocolDecoderOutput decoderOutput =
+ new ProtocolDecoderOutput(_protocolListener);
+ _amqpChannel =
+ new AmqpChannel(new ByteChannel(_ioHandler), decoderOutput);
+
+ // post an initial async read
+ _amqpChannel.BeginRead(new AsyncCallback(OnAsyncReadDone), this);
+ }
+
+ /// <summary>
+ /// Close the broker connection
+ /// </summary>
+ public void Close()
+ {
+ StopReading();
+ CloseBrokerConnection();
+ }
+
+ private void StopReading()
+ {
+ _stopEvent.Set();
+ }
+
+ private void CloseBrokerConnection()
+ {
+ if ( _ioHandler != null )
+ {
+ _ioHandler.Dispose();
+ _ioHandler = null;
+ }
+ if ( _connector != null )
+ {
+ _connector.Dispose();
+ _connector = null;
+ }
+ }
+
+ private IoHandler MakeBrokerConnection(IBrokerInfo broker, AMQConnection connection)
+ {
+ if ( broker.UseSSL )
+ {
+ _connector = new SslSocketConnector();
+ } else
+ {
+ _connector = new SocketConnector();
+ }
+
+ Stream stream = _connector.Connect(broker);
+ return new IoHandler(stream, connection.ProtocolListener);
+ }
+
+ private void OnAsyncReadDone(IAsyncResult result)
+ {
+ try
+ {
+ _amqpChannel.EndRead(result);
+
+ bool stopping = _stopEvent.WaitOne(0, false);
+ if ( !stopping )
+ _amqpChannel.BeginRead(new AsyncCallback(OnAsyncReadDone), null);
+ } catch ( Exception e )
+ {
+ // ignore any errors during closing
+ bool stopping = _stopEvent.WaitOne(0, false);
+ if ( !stopping )
+ _protocolListener.OnException(e);
+ }
+ }
+
+ #region IProtocolDecoderOutput Members
+
+ public void Write(object message)
+ {
+ _protocolListener.OnMessage((IDataBlock)message);
+ }
+
+ #endregion
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ByteChannel.cs b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ByteChannel.cs
new file mode 100644
index 0000000000..4540f01f4e
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ByteChannel.cs
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ class ByteChannel : IByteChannel
+ {
+ // Warning: don't use this log for regular logging.
+ private static readonly ILog _ioTraceLog = LogManager.GetLogger("TRACE.Qpid.Client.ByteChannel");
+
+ private IByteChannel _lowerChannel;
+
+ public ByteChannel(IByteChannel lowerChannel)
+ {
+ _lowerChannel = lowerChannel;
+ }
+
+ public ByteBuffer Read()
+ {
+ ByteBuffer result = _lowerChannel.Read();
+
+ // TODO: Move into decorator.
+ if (_ioTraceLog.IsDebugEnabled)
+ {
+ _ioTraceLog.Debug(String.Format("READ {0}", result));
+ }
+
+ return result;
+ }
+
+ public IAsyncResult BeginRead(AsyncCallback callback, object state)
+ {
+ return _lowerChannel.BeginRead(callback, state);
+ }
+
+ public ByteBuffer EndRead(IAsyncResult result)
+ {
+ ByteBuffer buffer = _lowerChannel.EndRead(result);
+ if ( _ioTraceLog.IsDebugEnabled )
+ {
+ _ioTraceLog.Debug(String.Format("READ {0}", buffer));
+ }
+ return buffer;
+ }
+
+ public void Write(ByteBuffer buffer)
+ {
+ // TODO: Move into decorator.
+ if (_ioTraceLog.IsDebugEnabled)
+ {
+ _ioTraceLog.Debug(String.Format("WRITE {0}", buffer));
+ }
+
+ _lowerChannel.Write(buffer);
+ }
+
+ public IAsyncResult BeginWrite(ByteBuffer buffer, AsyncCallback callback, object state)
+ {
+ if ( _ioTraceLog.IsDebugEnabled )
+ {
+ _ioTraceLog.Debug(String.Format("WRITE {0}", buffer));
+ }
+ return _lowerChannel.BeginWrite(buffer, callback, state);
+ }
+
+ public void EndWrite(IAsyncResult result)
+ {
+ _lowerChannel.EndWrite(result);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ISocketConnector.cs b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ISocketConnector.cs
new file mode 100644
index 0000000000..137fa19c0d
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/ISocketConnector.cs
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.IO;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ interface ISocketConnector : IDisposable
+ {
+ string LocalEndpoint { get; }
+ Stream Connect(IBrokerInfo broker);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SocketConnector.cs b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SocketConnector.cs
new file mode 100644
index 0000000000..b6dd8c3be1
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SocketConnector.cs
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ /// <summary>
+ /// Implements a TCP connection over regular sockets.
+ /// </summary>
+ class SocketConnector : ISocketConnector
+ {
+ private MyTcpClient _tcpClient;
+
+ public string LocalEndpoint
+ {
+ get { return _tcpClient.LocalEndpoint.ToString(); }
+ }
+
+ public Stream Connect(IBrokerInfo broker)
+ {
+ _tcpClient = new MyTcpClient(broker.Host, broker.Port);
+ return _tcpClient.GetStream();
+ }
+
+ public void Dispose()
+ {
+ if ( _tcpClient != null )
+ {
+ _tcpClient.Close();
+ _tcpClient = null;
+ }
+ }
+
+ class MyTcpClient : TcpClient
+ {
+ public MyTcpClient(string host, int port)
+ : base(host, port)
+ {
+ }
+
+ public EndPoint LocalEndpoint
+ {
+ get { return Client.LocalEndPoint; }
+ }
+ }
+
+ }
+}
+
+
diff --git a/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SslSocketConnector.cs b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SslSocketConnector.cs
new file mode 100644
index 0000000000..8436e6fc4f
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Transport/Socket/Blocking/SslSocketConnector.cs
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.IO;
+using System.Net;
+using log4net;
+using Apache.Qpid.Client.Qms;
+using Org.Mentalis.Security.Ssl;
+using MCertificate = Org.Mentalis.Security.Certificates.Certificate;
+using MCertificateChain = Org.Mentalis.Security.Certificates.CertificateChain;
+
+namespace Apache.Qpid.Client.Transport.Socket.Blocking
+{
+ /// <summary>
+ /// Implements a TLS v1.0 connection using the Mentalis.org library
+ /// </summary>
+ /// <remarks>
+ /// It would've been easier to implement this at the StreamFilter
+ /// level, but unfortunately the Mentalis library doesn't support
+ /// a passthrough SSL stream class and is tied directly
+ /// to socket-like classes.
+ /// </remarks>
+ class SslSocketConnector : ISocketConnector
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(SslSocketConnector));
+ private MyTcpClient _tcpClient;
+
+ public string LocalEndpoint
+ {
+ get { return _tcpClient.LocalEndpoint.ToString(); }
+ }
+
+ public Stream Connect(IBrokerInfo broker)
+ {
+ MCertificate cert = GetClientCert(broker);
+ SecurityOptions options = new SecurityOptions(
+ SecureProtocol.Tls1, cert, ConnectionEnd.Client
+ );
+ if ( broker.SslOptions != null
+ && broker.SslOptions.IgnoreValidationErrors )
+ {
+ _logger.Warn("Ignoring any certificate validation errors during SSL handshake...");
+ options.VerificationType = CredentialVerification.None;
+ }
+
+ _tcpClient = new MyTcpClient(broker.Host, broker.Port, options);
+ return _tcpClient.GetStream();
+ }
+
+ public void Dispose()
+ {
+ if ( _tcpClient != null )
+ {
+ _tcpClient.Close();
+ _tcpClient = null;
+ }
+ }
+
+ private static MCertificate GetClientCert(IBrokerInfo broker)
+ {
+ // if a client certificate is configured,
+ // use that to enable mutual authentication
+ MCertificate cert = null;
+ if ( broker.SslOptions != null
+ && broker.SslOptions.ClientCertificate != null )
+ {
+ cert = MCertificate.CreateFromX509Certificate(
+ broker.SslOptions.ClientCertificate
+ );
+ _logger.DebugFormat("Using Client Certificate for SSL '{0}'", cert.ToString(true));
+ }
+ return cert;
+ }
+
+ class MyTcpClient : SecureTcpClient
+ {
+ public MyTcpClient(string host, int port, SecurityOptions options)
+ : base(host, port, options)
+ {
+ }
+
+ public EndPoint LocalEndpoint
+ {
+ get { return Client.LocalEndPoint; }
+ }
+
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Client/Client/Util/FlowControlQueue.cs b/dotnet/Qpid.Client/Client/Util/FlowControlQueue.cs
new file mode 100644
index 0000000000..a06de9eac8
--- /dev/null
+++ b/dotnet/Qpid.Client/Client/Util/FlowControlQueue.cs
@@ -0,0 +1,98 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using System.Threading;
+using Apache.Qpid.Collections;
+using Apache.Qpid.Common;
+
+namespace Apache.Qpid.Client.Util
+{
+ internal delegate void ThresholdMethod(int currentCount);
+
+ /// <summary>
+ /// Basic bounded queue used to implement prefetching.
+ /// Notice we do the callbacks here asynchronously to
+ /// avoid adding more complexity to the channel impl.
+ /// </summary>
+ internal class FlowControlQueue
+ {
+ private BlockingQueue _queue = new LinkedBlockingQueue();
+ private int _itemCount;
+ private int _lowerBound;
+ private int _upperBound;
+ private ThresholdMethod _underThreshold;
+ private ThresholdMethod _overThreshold;
+
+ public FlowControlQueue(
+ int lowerBound,
+ int upperBound,
+ ThresholdMethod underThreshold,
+ ThresholdMethod overThreshold
+ )
+ {
+ _lowerBound = lowerBound;
+ _upperBound = upperBound;
+ _underThreshold = underThreshold;
+ _overThreshold = overThreshold;
+ }
+
+ public void Enqueue(object item)
+ {
+ _queue.EnqueueBlocking(item);
+ int count = Interlocked.Increment(ref _itemCount);
+ if ( _overThreshold != null )
+ {
+ if ( count == _upperBound )
+ {
+ _overThreshold.BeginInvoke(
+ count, new AsyncCallback(OnAsyncCallEnd),
+ _overThreshold
+ );
+ }
+ }
+ }
+
+ public object Dequeue()
+ {
+ object item = _queue.DequeueBlocking();
+ int count = Interlocked.Decrement(ref _itemCount);
+ if ( _underThreshold != null )
+ {
+ if ( count == _lowerBound )
+ {
+ _underThreshold.BeginInvoke(
+ count, new AsyncCallback(OnAsyncCallEnd),
+ _underThreshold
+ );
+ }
+ }
+ return item;
+ }
+
+ private void OnAsyncCallEnd(IAsyncResult res)
+ {
+ ThresholdMethod method = (ThresholdMethod)res.AsyncState;
+ method.EndInvoke(res);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/Properties/AssemblyInfo.cs b/dotnet/Qpid.Client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..670a4f90b2
--- /dev/null
+++ b/dotnet/Qpid.Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Client")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Client")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("380cb124-07a8-40c2-b67d-69a0d94cb620")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
diff --git a/dotnet/Qpid.Client/Qpid.Client.csproj b/dotnet/Qpid.Client/Qpid.Client.csproj
new file mode 100644
index 0000000000..303f885149
--- /dev/null
+++ b/dotnet/Qpid.Client/Qpid.Client.csproj
@@ -0,0 +1,102 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{68987C05-3768-452C-A6FC-6BA1D372852F}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Client</RootNamespace>
+ <AssemblyName>Apache.Qpid.Client</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.0.30714, Culture=neutral, PublicKeyToken=500ffcafb14f92df">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Common\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="Org.Mentalis.Security, Version=1.0.13.716, Culture=neutral, PublicKeyToken=085a8f6006888436">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Common\lib\seclib-1.0.0\Org.Mentalis.Security.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Codec\Qpid.Codec.csproj">
+ <Project>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</Project>
+ <Name>Qpid.Codec</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Client/default.build b/dotnet/Qpid.Client/default.build
new file mode 100644
index 0000000000..9a0ec2ea6d
--- /dev/null
+++ b/dotnet/Qpid.Client/default.build
@@ -0,0 +1,52 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Client" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/Apache.Qpid.Buffer.dll" />
+ <include name="${build.dir}/Apache.Qpid.Sasl.dll" />
+ <include name="${build.dir}/Apache.Qpid.Codec.dll" />
+ <include name="${build.dir}/Apache.Qpid.Common.dll" />
+ <include name="${build.dir}/Apache.Qpid.Messaging.dll" />
+ <include name="${build.dir}/Org.Mentalis.Security.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Client/qms/BrokerInfo.cs b/dotnet/Qpid.Client/qms/BrokerInfo.cs
new file mode 100644
index 0000000000..93c00af6e0
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/BrokerInfo.cs
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client.Qms
+{
+ /// <summary>
+ /// Know URL option names.
+ /// <seealso cref="IConnectionInfo"/>
+ /// </summary>
+ public class BrokerInfoConstants
+ {
+ public const String OPTIONS_RETRY = "retries";
+ public const String OPTIONS_SSL = ConnectionUrlConstants.OPTIONS_SSL;
+ public const String OPTIONS_CONNECT_TIMEOUT = "connecttimeout";
+ public const int DEFAULT_PORT = 5672;
+ public const String DEFAULT_TRANSPORT = "tcp";
+
+ public readonly string URL_FORMAT_EXAMPLE =
+ "<transport>://<hostname>[:<port Default=\"" + DEFAULT_PORT + "\">][?<option>='<value>'[,<option>='<value>']]";
+
+ public const long DEFAULT_CONNECT_TIMEOUT = 30000L;
+ }
+
+ public interface IBrokerInfo
+ {
+ string Host { get; set; }
+ int Port { get; set; }
+ string Transport { get; set; }
+ bool UseSSL { get; set; }
+ long Timeout { get; set; }
+ SslOptions SslOptions { get; }
+
+ String GetOption(string key);
+ void SetOption(string key, string value);
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/ConnectionInfo.cs b/dotnet/Qpid.Client/qms/ConnectionInfo.cs
new file mode 100644
index 0000000000..4d3f7698b5
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/ConnectionInfo.cs
@@ -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.
+ *
+ */
+using System.Collections;
+
+namespace Apache.Qpid.Client.Qms
+{
+ class ConnectionUrlConstants
+ {
+ public const string AMQ_PROTOCOL = "amqp";
+ public const string OPTIONS_BROKERLIST = "brokerlist";
+ public const string OPTIONS_FAILOVER = "failover";
+ public const string OPTIONS_FAILOVER_CYCLE = "cyclecount";
+ public const string OPTIONS_SSL = "ssl";
+ }
+
+ /// <summary>
+ /// Connection URL format
+ /// amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\'&amp;option=\'value\';vm://:3/virtualpath?option=\'value\''&amp;failover='method?option=\'value\'&amp;option='value''"
+ /// Options are of course optional except for requiring a single broker in the broker list.
+ /// The option seperator is defined to be either '&amp;' or ','
+ /// </summary>
+ public interface IConnectionInfo
+ {
+ string AsUrl();
+
+ string FailoverMethod { get; set; }
+ string ClientName { get; set; }
+ string Username { get; set; }
+ string Password { get; set; }
+ string VirtualHost { get; set; }
+ string GetFailoverOption(string key);
+
+ int BrokerCount { get; }
+
+ IBrokerInfo GetBrokerInfo(int index);
+
+ void AddBrokerInfo(IBrokerInfo broker);
+
+ IList GetAllBrokerInfos();
+
+ string GetOption(string key);
+
+ void SetOption(string key, string value);
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/FailoverPolicy.cs b/dotnet/Qpid.Client/qms/FailoverPolicy.cs
new file mode 100644
index 0000000000..179a695bf9
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/FailoverPolicy.cs
@@ -0,0 +1,315 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Client.Qms.Failover;
+
+namespace Apache.Qpid.Client.Qms
+{
+ public class FailoverPolicy
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(FailoverPolicy));
+
+ private const long MINUTE = 60000L;
+
+ private const long DEFAULT_METHOD_TIMEOUT = 1 * MINUTE;
+ private const long DEFAULT_FAILOVER_TIMEOUT = 4 * MINUTE;
+
+ private IFailoverMethod[] _methods = new IFailoverMethod[1];
+
+ private int _currentMethod;
+
+ private int _methodsRetries;
+
+ private int _currentRetry;
+
+ private bool _timing;
+
+ private long _lastMethodTime;
+ private long _lastFailTime;
+
+ public FailoverPolicy(IConnectionInfo connectionInfo)
+ {
+ IFailoverMethod method;
+
+ //todo This should be integrated in to the connection url when it supports
+ // multiple strategies.
+
+ _methodsRetries = 0;
+
+ if (connectionInfo.FailoverMethod == null)
+ {
+ if (connectionInfo.BrokerCount > 1)
+ {
+ method = new FailoverRoundRobin(connectionInfo);
+ }
+ else
+ {
+ method = new FailoverSingleServer(connectionInfo);
+ }
+ }
+ else
+ {
+ string failoverMethod = connectionInfo.FailoverMethod;
+
+ /*
+ if (failoverMethod.equals(FailoverMethod.RANDOM))
+ {
+ //todo write a random connection Failover
+ }
+ */
+ if (failoverMethod.Equals(FailoverMethodConstants.ROUND_ROBIN))
+ {
+ method = new FailoverRoundRobin(connectionInfo);
+ }
+ else
+ {
+ throw new NotImplementedException("Dynamic loading of FailoverMethods not yet implemented.");
+// try
+// {
+// Type[] constructorSpec = {ConnectionInfo.class};
+// Object [] params = {connectionInfo};
+//
+// method = (FailoverMethod) ClassLoader.getSystemClassLoader().
+// loadClass(failoverMethod).
+// getConstructor(constructorSpec).newInstance(params);
+// }
+// catch (Exception cnfe)
+// {
+// throw new IllegalArgumentException("Unknown failover method:" + failoverMethod);
+// }
+ }
+ }
+
+ if (method == null)
+ {
+ throw new ArgumentException("Unknown failover method specified.");
+ }
+
+ reset();
+
+ _methods[_currentMethod] = method;
+ }
+
+ public FailoverPolicy(IFailoverMethod method) : this(method, 0)
+ {
+ }
+
+ public FailoverPolicy(IFailoverMethod method, int retries)
+ {
+ _methodsRetries = retries;
+
+ reset();
+
+ _methods[_currentMethod] = method;
+ }
+
+ private void reset()
+ {
+ _currentMethod = 0;
+ _currentRetry = 0;
+ _timing = false;
+
+ }
+
+ public bool FailoverAllowed()
+ {
+ bool failoverAllowed;
+
+ if (_timing)
+ {
+ long now = CurrentTimeMilliseconds();
+
+ if ((now - _lastMethodTime) >= DEFAULT_METHOD_TIMEOUT)
+ {
+ _logger.Info("Failover method timeout");
+ _lastMethodTime = now;
+
+ if (!nextMethod())
+ {
+ return false;
+ }
+
+
+ }
+ else if ((now - _lastFailTime) >= DEFAULT_FAILOVER_TIMEOUT)
+ {
+ _logger.Info("Failover timeout");
+ return false;
+ }
+ else
+ {
+ _lastMethodTime = now;
+ }
+ }
+ else
+ {
+ _timing = true;
+ _lastMethodTime = CurrentTimeMilliseconds();
+ _lastFailTime = _lastMethodTime;
+ }
+
+
+ if (_methods[_currentMethod].FailoverAllowed())
+ {
+ failoverAllowed = true;
+ }
+ else
+ {
+ if (_currentMethod < (_methods.Length - 1))
+ {
+ nextMethod();
+ _logger.Info("Changing method to " + _methods[_currentMethod].MethodName);
+ return FailoverAllowed();
+ }
+ else
+ {
+ return cycleMethods();
+ }
+ }
+
+ return failoverAllowed;
+ }
+
+ private static long CurrentTimeMilliseconds()
+ {
+ return DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
+ }
+
+ private bool nextMethod()
+ {
+ if (_currentMethod < (_methods.Length - 1))
+ {
+ _currentMethod++;
+ _methods[_currentMethod].Reset();
+ return true;
+ }
+ else
+ {
+ return cycleMethods();
+ }
+ }
+
+ private bool cycleMethods()
+ {
+ if (_currentRetry < _methodsRetries)
+ {
+ _currentRetry++;
+
+ _currentMethod = 0;
+
+ _logger.Info("Retrying methods starting with " + _methods[_currentMethod].MethodName);
+ _methods[_currentMethod].Reset();
+ return FailoverAllowed();
+ }
+ else
+ {
+ _logger.Debug("All failover methods exhausted");
+ return false;
+ }
+ }
+
+ /**
+ * Notification that connection was successful.
+ */
+ public void attainedConnection()
+ {
+ _currentRetry = 0;
+
+ _methods[_currentMethod].AttainedConnection();
+
+ _timing = false;
+ }
+
+ public IBrokerInfo GetCurrentBrokerInfo()
+ {
+ return _methods[_currentMethod].GetCurrentBrokerInfo();
+ }
+
+ public IBrokerInfo GetNextBrokerInfo()
+ {
+ return _methods[_currentMethod].GetNextBrokerDetails();
+ }
+
+ public void setBroker(IBrokerInfo broker)
+ {
+ _methods[_currentMethod].SetBroker(broker);
+ }
+
+ public void addMethod(IFailoverMethod method)
+ {
+ int len = _methods.Length + 1;
+ IFailoverMethod[] newMethods = new IFailoverMethod[len];
+ _methods.CopyTo(newMethods, 0);
+// System.arraycopy(_methods, 0, newMethods, 0, _methods.length);
+ int index = len - 1;
+ newMethods[index] = method;
+ _methods = newMethods;
+ }
+
+ public void setMethodRetries(int retries)
+ {
+ _methodsRetries = retries;
+ }
+
+ public IFailoverMethod getCurrentMethod()
+ {
+ if (_currentMethod >= 0 && _currentMethod < (_methods.Length - 1))
+ {
+ return _methods[_currentMethod];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append("Failover Policy:\n");
+
+ if (FailoverAllowed())
+ {
+ sb.Append("Failover allowed\n");
+ }
+ else
+ {
+ sb.Append("Failover not allowed\n");
+ }
+
+ sb.Append("Failover policy methods\n");
+ for (int i = 0; i < _methods.Length; i++)
+ {
+
+ if (i == _currentMethod)
+ {
+ sb.Append(">");
+ }
+ sb.Append(_methods[i].ToString());
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/UrlSyntaxException.cs b/dotnet/Qpid.Client/qms/UrlSyntaxException.cs
new file mode 100644
index 0000000000..ab3de325d4
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/UrlSyntaxException.cs
@@ -0,0 +1,134 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Apache.Qpid.Client.Qms
+{
+ [Serializable]
+ public class UrlSyntaxException : UriFormatException
+ {
+ private string _url;
+ private int _index;
+ private int _length;
+
+ public int GetIndex()
+ {
+ return _index;
+ }
+
+ public UrlSyntaxException(String input, String reason)
+ : this(input, reason, -1)
+ {
+ }
+
+ private UrlSyntaxException(string input, string reason, int index)
+ :
+ this(input, reason, index, input.Length)
+ {
+ }
+
+ public UrlSyntaxException(String url, String error, int index, int length)
+ : base(error)
+ {
+ _url = url;
+ _index = index;
+ _length = length;
+ }
+
+ protected UrlSyntaxException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _url = info.GetString("Url");
+ _index = info.GetInt32("Index");
+ _length = info.GetInt32("Length");
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("Url", _url);
+ info.AddValue("Index", _index);
+ info.AddValue("Length", _length);
+ }
+
+ private static String getPositionString(int index, int length)
+ {
+ StringBuilder sb = new StringBuilder(index + 1);
+
+ for (int i = 0; i < index; i++)
+ {
+ sb.Append(" ");
+ }
+
+ if (length > -1)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ sb.Append('^');
+ }
+ }
+
+ return sb.ToString();
+ }
+
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+// sb.Append(getReason());
+
+ if (_index > -1)
+ {
+ if (_length != -1)
+ {
+ sb.Append(" between indicies ");
+ sb.Append(_index);
+ sb.Append(" and ");
+ sb.Append(_length);
+ }
+ else
+ {
+ sb.Append(" at index ");
+ sb.Append(_index);
+ }
+ }
+
+ sb.Append(" ");
+ if (_index != -1)
+ {
+ sb.Append("\n");
+ }
+
+ sb.Append(_url);
+
+ if (_index != -1)
+ {
+ sb.Append("\n");
+ sb.Append(getPositionString(_index, _length));
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs b/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs
new file mode 100644
index 0000000000..f32b275e84
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client.Qms.Failover
+{
+ public class FailoverMethodConstants
+ {
+ public const String ROUND_ROBIN = "roundrobin";
+ public const String RANDOM = "random";
+ }
+
+ public interface IFailoverMethod
+ {
+ /// <summary>
+ /// The name of this method for display purposes.
+ /// </summary>
+ String MethodName { get; }
+
+ /// <summary>
+ /// Reset the Failover to initial conditions
+ /// </summary>
+ void Reset();
+
+ /// <summary>
+ /// Check if failover is possible for this method
+ /// </summary>
+ /// <returns>true if failover is allowed</returns>
+ bool FailoverAllowed();
+
+ /// <summary>
+ /// Notification to the Failover method that a connection has been attained.
+ /// </summary>
+ void AttainedConnection();
+
+ /// <summary>
+ /// If there is no current BrokerInfo the null will be returned.
+ /// </summary>
+ /// <returns>The current BrokerDetail value to use</returns>
+ IBrokerInfo GetCurrentBrokerInfo();
+
+ /// <summary>
+ /// Move to the next BrokerInfo if one is available.
+ /// </summary>
+ /// <returns>the next BrokerDetail or null if there is none.</returns>
+ IBrokerInfo GetNextBrokerDetails();
+
+ /// <summary>
+ /// Set the currently active broker to be the new value.
+ /// </summary>
+ /// <param name="broker">The new BrokerDetail value</param>
+ void SetBroker(IBrokerInfo broker);
+
+ /// <summary>
+ /// Set the retries for this method
+ /// </summary>
+ /// <param name="maxRetries">the maximum number of time to retry this Method</param>
+ void SetRetries(int maxRetries);
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs b/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs
new file mode 100644
index 0000000000..8103940fb4
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs
@@ -0,0 +1,255 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+
+namespace Apache.Qpid.Client.Qms.Failover
+{
+ public class FailoverRoundRobin : IFailoverMethod
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(FailoverRoundRobin));
+
+ /** The default number of times to cycle through all servers */
+ public const int DEFAULT_CYCLE_RETRIES = 0;
+ /** The default number of times to retry each server */
+ public const int DEFAULT_SERVER_RETRIES = 0;
+
+ /**
+ * The index into the hostDetails array of the broker to which we are connected
+ */
+ private int _currentBrokerIndex = -1;
+
+ /**
+ * The number of times to retry connecting for each server
+ */
+ private int _serverRetries;
+
+ /**
+ * The current number of retry attempts made
+ */
+ private int _currentServerRetry;
+
+ /**
+ * The number of times to cycle through the servers
+ */
+ private int _cycleRetries;
+
+ /**
+ * The current number of cycles performed.
+ */
+ private int _currentCycleRetries;
+
+ /**
+ * Array of BrokerDetail used to make connections.
+ */
+ private IConnectionInfo _connectionDetails;
+
+ public FailoverRoundRobin(IConnectionInfo connectionDetails)
+ {
+ if (!(connectionDetails.BrokerCount > 0))
+ {
+ throw new ArgumentException("At least one broker details must be specified.");
+ }
+
+ _connectionDetails = connectionDetails;
+
+ //There is no current broker at startup so set it to -1.
+ _currentBrokerIndex = -1;
+
+ String cycleRetries = _connectionDetails.GetFailoverOption(ConnectionUrlConstants.OPTIONS_FAILOVER_CYCLE);
+
+ if (cycleRetries != null)
+ {
+ try
+ {
+ _cycleRetries = int.Parse(cycleRetries);
+ }
+ catch (FormatException)
+ {
+ _cycleRetries = DEFAULT_CYCLE_RETRIES;
+ }
+ }
+
+ _currentCycleRetries = 0;
+
+ _serverRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public void Reset()
+ {
+ _currentBrokerIndex = 0;
+ _currentCycleRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public bool FailoverAllowed()
+ {
+ return ((_currentCycleRetries < _cycleRetries)
+ || (_currentServerRetry < _serverRetries)
+ || (_currentBrokerIndex < (_connectionDetails.BrokerCount - 1)));
+ }
+
+ public void AttainedConnection()
+ {
+ _currentCycleRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public IBrokerInfo GetCurrentBrokerInfo()
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ return null;
+ }
+
+ return _connectionDetails.GetBrokerInfo(_currentBrokerIndex);
+ }
+
+ public IBrokerInfo GetNextBrokerDetails()
+ {
+ if (_currentBrokerIndex == (_connectionDetails.BrokerCount - 1))
+ {
+ if (_currentServerRetry < _serverRetries)
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ _currentBrokerIndex = 0;
+
+ SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex ));
+
+ _logger.Info("First Run using " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex));
+ }
+ else
+ {
+ _logger.Info("Retrying " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex));
+ }
+
+ _currentServerRetry++;
+ }
+ else
+ {
+ _currentCycleRetries++;
+ //failed to connect to first broker
+ _currentBrokerIndex = 0;
+
+ SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex ));
+
+ // This is zero rather than -1 as we are already retrieving the details.
+ _currentServerRetry = 0;
+ }
+ //else - should force client to stop as max retries has been reached.
+ }
+ else
+ {
+ if (_currentServerRetry < _serverRetries)
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ _currentBrokerIndex = 0;
+
+ SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex ));
+
+ _logger.Info("First Run using " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex));
+ }
+ else
+ {
+ _logger.Info("Retrying " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex));
+ }
+ _currentServerRetry++;
+ }
+ else
+ {
+ _currentBrokerIndex++;
+
+ SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex ));
+ // This is zero rather than -1 as we are already retrieving the details.
+ _currentServerRetry = 0;
+ }
+ }
+
+ return _connectionDetails.GetBrokerInfo(_currentBrokerIndex);
+ }
+
+ public void SetBroker(IBrokerInfo broker)
+ {
+ _connectionDetails.AddBrokerInfo(broker);
+
+ int index = _connectionDetails.GetAllBrokerInfos().IndexOf(broker);
+
+ String serverRetries = broker.GetOption(BrokerInfoConstants.OPTIONS_RETRY);
+
+ if (serverRetries != null)
+ {
+ try
+ {
+ _serverRetries = int.Parse(serverRetries);
+ }
+ catch (FormatException)
+ {
+ _serverRetries = DEFAULT_SERVER_RETRIES;
+ }
+ }
+
+ _currentServerRetry = -1;
+ _currentBrokerIndex = index;
+ }
+
+ public void SetRetries(int maxRetries)
+ {
+ _cycleRetries = maxRetries;
+ }
+
+ public String MethodName
+ {
+ get { return "Cycle Servers"; }
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append(GetType().Name).Append("\n");
+
+ sb.Append("Broker count: ").Append(_connectionDetails.BrokerCount);
+ sb.Append("\ncurrent broker index: ").Append(_currentBrokerIndex);
+
+ sb.Append("\nCycle Retries: ").Append(_cycleRetries);
+ sb.Append("\nCurrent Cycle:").Append(_currentCycleRetries);
+ sb.Append("\nServer Retries:").Append(_serverRetries);
+ sb.Append("\nCurrent Retry:").Append(_currentServerRetry);
+ sb.Append("\n");
+
+ for(int i=0; i < _connectionDetails.BrokerCount ; i++)
+ {
+ if (i == _currentBrokerIndex)
+ {
+ sb.Append(">");
+ }
+ sb.Append(_connectionDetails.GetBrokerInfo(i));
+ sb.Append("\n");
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs b/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs
new file mode 100644
index 0000000000..5e502b897e
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Client.Qms.Failover
+{
+ public class FailoverSingleServer : IFailoverMethod
+ {
+ /** The default number of times to rety a conection to this server */
+ public const int DEFAULT_SERVER_RETRIES = 1;
+
+ /**
+ * The details of the Single Server
+ */
+ private IBrokerInfo _brokerDetail;
+
+ /**
+ * The number of times to retry connecting to the sever
+ */
+ private int _retries;
+
+ /**
+ * The current number of attempts made to the server
+ */
+ private int _currentRetries;
+
+
+ public FailoverSingleServer(IConnectionInfo connectionDetails)
+ {
+ if (connectionDetails.BrokerCount > 0)
+ {
+ SetBroker(connectionDetails.GetBrokerInfo(0));
+ }
+ else
+ {
+ throw new ArgumentException("BrokerInfo details required for connection.");
+ }
+ }
+
+ public FailoverSingleServer(IBrokerInfo brokerDetail)
+ {
+ SetBroker(brokerDetail);
+ }
+
+ public void Reset()
+ {
+ _currentRetries = -1;
+ }
+
+ public bool FailoverAllowed()
+ {
+ return _currentRetries < _retries;
+ }
+
+ public void AttainedConnection()
+ {
+ Reset();
+ }
+
+ public IBrokerInfo GetCurrentBrokerInfo()
+ {
+ return _brokerDetail;
+ }
+
+ public IBrokerInfo GetNextBrokerDetails()
+ {
+ if (_currentRetries == _retries)
+ {
+ return null;
+ }
+ else
+ {
+ if (_currentRetries < _retries)
+ {
+ _currentRetries ++;
+ }
+
+ return _brokerDetail;
+ }
+ }
+
+ public void SetBroker(IBrokerInfo broker)
+ {
+ if (broker == null)
+ {
+ throw new ArgumentException("BrokerInfo details cannot be null");
+ }
+ _brokerDetail = broker;
+
+ String retries = broker.GetOption(BrokerInfoConstants.OPTIONS_RETRY);
+ if (retries != null)
+ {
+ try
+ {
+ _retries = int.Parse(retries);
+ }
+ catch (FormatException)
+ {
+ _retries = DEFAULT_SERVER_RETRIES;
+ }
+ }
+ else
+ {
+ _retries = DEFAULT_SERVER_RETRIES;
+ }
+
+ Reset();
+ }
+
+ public void SetRetries(int retries)
+ {
+ _retries = retries;
+ }
+
+ public String MethodName
+ {
+ get { return "Single Server"; }
+ }
+
+ public String toString()
+ {
+ return "SingleServer:\n"+
+ "Max Retries:"+_retries+
+ "\nCurrent Retry:"+_currentRetries+
+ "\n"+_brokerDetail+"\n";
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs b/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
new file mode 100644
index 0000000000..6cfd75c851
--- /dev/null
+++ b/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
@@ -0,0 +1,152 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec
+{
+ public abstract class CumulativeProtocolDecoder : IProtocolDecoder
+ {
+ static ILog _logger = LogManager.GetLogger(typeof(CumulativeProtocolDecoder));
+
+ ByteBuffer _remaining;
+
+ /// <summary>
+ /// Creates a new instance with the 4096 bytes initial capacity of
+ /// cumulative buffer.
+ /// </summary>
+ protected CumulativeProtocolDecoder()
+ {
+ _remaining = AllocateBuffer();
+ }
+
+ /// <summary>
+ /// Cumulates content of <tt>in</tt> into internal buffer and forwards
+ /// decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
+ /// <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
+ /// and the cumulative buffer is compacted after decoding ends.
+ /// </summary>
+ /// <exception cref="Exception">
+ /// if your <tt>doDecode()</tt> returned <tt>true</tt> not consuming the cumulative buffer.
+ /// </exception>
+ public void Decode(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ if ( _remaining.Position != 0 ) // If there were remaining undecoded bytes
+ {
+ DecodeRemainingAndInput(input, output);
+ } else
+ {
+ DecodeInput(input, output);
+ }
+ }
+
+ private void DecodeInput(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ _logger.Debug(string.Format("DecodeInput: input {0}", input.Remaining));
+ // Just decode the input buffer and remember any remaining undecoded bytes.
+ try
+ {
+ DecodeAll(input, output);
+ } finally
+ {
+ if ( input.HasRemaining )
+ {
+ _remaining.Put(input);
+ }
+ }
+ }
+
+ private void DecodeRemainingAndInput(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ _logger.Debug(string.Format("DecodeRemainingAndInput: input {0}, remaining {1}", input.Remaining, _remaining.Position));
+ // replace the _remainder buffer, so that we can leave the
+ // original one alone. Necessary because some consumer splice
+ // the buffer and only consume it until later, causing
+ // a race condition if we compact it too soon.
+ ByteBuffer newRemainding = AllocateBuffer();
+ ByteBuffer temp = _remaining;
+ _remaining = newRemainding;
+ temp.Put(input);
+ temp.Flip();
+ try
+ {
+ DecodeAll(temp, output);
+ } finally
+ {
+ if ( temp.Remaining > 0 )
+ _remaining.Put(temp);
+ }
+ }
+
+ private void DecodeAll(ByteBuffer buf, IProtocolDecoderOutput output)
+ {
+ for ( ; ; )
+ {
+ int oldPos = buf.Position;
+ bool decoded = DoDecode(buf, output);
+ if ( decoded )
+ {
+ if ( buf.Position == oldPos )
+ {
+ throw new Exception(
+ "doDecode() can't return true when buffer is not consumed.");
+ }
+
+ if ( !buf.HasRemaining )
+ {
+ break;
+ }
+ } else
+ {
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Implement this method to consume the specified cumulative buffer and
+ /// decode its content into message(s).
+ /// </summary>
+ /// <param name="input">the cumulative buffer</param>
+ /// <param name="output">decoder output</param>
+ /// <returns>
+ /// <tt>true</tt> if and only if there's more to decode in the buffer
+ /// and you want to have <tt>doDecode</tt> method invoked again.
+ /// Return <tt>false</tt> if remaining data is not enough to decode,
+ /// then this method will be invoked again when more data is cumulated.
+ /// </returns>
+ /// <exception cref="Exception">If cannot decode</exception>
+ protected abstract bool DoDecode(ByteBuffer input, IProtocolDecoderOutput output);
+
+ public void Dispose()
+ {
+ _remaining = null;
+ }
+
+ private ByteBuffer AllocateBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(4096);
+ buffer.IsAutoExpand = true;
+ return buffer;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Codec/Demux/DemuxingProtocolCodecFactory.cs b/dotnet/Qpid.Codec/Demux/DemuxingProtocolCodecFactory.cs
new file mode 100644
index 0000000000..78276202d6
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/DemuxingProtocolCodecFactory.cs
@@ -0,0 +1,387 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec.Demux
+{
+ public class DemuxingProtocolCodecFactory : IProtocolCodecFactory
+ {
+ private ArrayList _decoderFactories = new ArrayList();
+ private ArrayList _encoderFactories = new ArrayList();
+
+ public void Register(Type encoderOrDecoderClass)
+ {
+ if (encoderOrDecoderClass == null)
+ {
+ throw new ArgumentNullException("encoderOrDecoderClass");
+ }
+
+ bool registered = false;
+ if (typeof(IMessageEncoder).IsAssignableFrom(encoderOrDecoderClass))
+ {
+ Register(new DefaultConstructorMessageEncoderFactory(encoderOrDecoderClass));
+ registered = true;
+ }
+
+ if (typeof(IMessageDecoder).IsAssignableFrom(encoderOrDecoderClass))
+ {
+ Register(new DefaultConstructorMessageDecoderFactory(encoderOrDecoderClass));
+ registered = true;
+ }
+
+ if (!registered)
+ {
+ throw new ArgumentException("Unregisterable type: " + encoderOrDecoderClass);
+ }
+ }
+
+ public void Register(IMessageEncoder encoder)
+ {
+ Register(new SingletonMessageEncoderFactory(encoder));
+ }
+
+ public void Register(IMessageEncoderFactory factory)
+ {
+ if (factory == null)
+ {
+ throw new ArgumentNullException("factory");
+ }
+
+ _encoderFactories.Add(factory);
+ }
+
+ public void Register(IMessageDecoder decoder)
+ {
+ Register(new SingletonMessageDecoderFactory(decoder));
+ }
+
+ public void Register(IMessageDecoderFactory factory)
+ {
+ if (factory == null)
+ {
+ throw new ArgumentNullException("factory");
+ }
+ _decoderFactories.Add(factory);
+ }
+
+ public IProtocolEncoder Encoder
+ {
+ get
+ {
+ return new ProtocolEncoderImpl(this);
+ }
+ }
+
+ public IProtocolDecoder Decoder
+ {
+ get
+ {
+ return new ProtocolDecoderImpl(this);
+ }
+ }
+
+ protected void DisposeCodecResources()
+ {
+ // Do nothing by default
+ }
+
+ private class ProtocolEncoderImpl : IProtocolEncoder
+ {
+ private readonly Hashtable _encoders = new Hashtable();
+
+ private DemuxingProtocolCodecFactory _enclosing;
+
+ public ProtocolEncoderImpl(DemuxingProtocolCodecFactory enclosing)
+ {
+ _enclosing = enclosing;
+ ArrayList encoderFactories = enclosing._encoderFactories;
+ for (int i = encoderFactories.Count - 1; i >= 0; i--)
+ {
+ IMessageEncoder encoder = ((IMessageEncoderFactory)encoderFactories[i]).NewEncoder();
+ foreach (Type type in encoder.MessageTypes.Keys)
+ {
+ _encoders[type] = encoder;
+ }
+ }
+ }
+
+ public void Encode(object message, IProtocolEncoderOutput output)
+ {
+ Type type = message.GetType();
+ IMessageEncoder encoder = FindEncoder(type);
+ if (encoder == null)
+ {
+ throw new ProtocolEncoderException("Unexpected message type: " + type);
+ }
+
+ encoder.Encode(message, output);
+ }
+
+ private IMessageEncoder FindEncoder(Type type)
+ {
+ IMessageEncoder encoder = (IMessageEncoder)_encoders[type];
+ if (encoder == null)
+ {
+ encoder = FindEncoder(type, new Hashtable());
+ }
+
+ return encoder;
+ }
+
+ private IMessageEncoder FindEncoder(Type type, Hashtable triedClasses)
+ {
+ IMessageEncoder encoder;
+
+ if (triedClasses.Contains(type))
+ {
+ return null;
+ }
+ triedClasses[type] = 1;
+
+ encoder = (IMessageEncoder)_encoders[type];
+ if (encoder == null)
+ {
+ encoder = FindEncoder(type, triedClasses);
+ if (encoder != null)
+ {
+ return encoder;
+ }
+
+ Type[] interfaces = type.GetInterfaces();
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ encoder = FindEncoder(interfaces[i], triedClasses);
+ if (encoder != null)
+ {
+ return encoder;
+ }
+ }
+
+ return null;
+ }
+ else
+ return encoder;
+ }
+
+ public void Dispose()
+ {
+ _enclosing.DisposeCodecResources();
+ }
+ }
+
+ private class ProtocolDecoderImpl : CumulativeProtocolDecoder
+ {
+ private readonly IMessageDecoder[] _decoders;
+ private IMessageDecoder _currentDecoder;
+ private DemuxingProtocolCodecFactory _enclosing;
+
+ public ProtocolDecoderImpl(DemuxingProtocolCodecFactory enclosing)
+ {
+ _enclosing = enclosing;
+ ArrayList decoderFactories = _enclosing._decoderFactories;
+ _decoders = new IMessageDecoder[decoderFactories.Count];
+ for (int i = decoderFactories.Count - 1; i >= 0; i--)
+ {
+ _decoders[i] = ((IMessageDecoderFactory) decoderFactories[i]).NewDecoder();
+ }
+ }
+
+ protected override bool DoDecode(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ MessageDecoderResult result;
+ if (_currentDecoder == null)
+ {
+ IMessageDecoder[] decoders = _decoders;
+ int undecodables = 0;
+
+ for (int i = decoders.Length - 1; i >= 0; i --)
+ {
+ IMessageDecoder decoder = decoders[i];
+ int limit = input.Limit;
+ int pos = input.Position;
+
+ try
+ {
+ result = decoder.Decodable(input);
+ }
+ finally
+ {
+ input.Position = pos;
+ input.Limit = limit;
+ }
+
+ if (result == MessageDecoderResult.OK)
+ {
+ _currentDecoder = decoder;
+ break;
+ }
+ else if(result == MessageDecoderResult.NOT_OK)
+ {
+ undecodables ++;
+ }
+ else if (result != MessageDecoderResult.NEED_DATA)
+ {
+ throw new Exception("Unexpected decode result (see your decodable()): " + result);
+ }
+ }
+
+ if (undecodables == _decoders.Length)
+ {
+ // Throw an exception if all decoders cannot decode data.
+ input.Position = input.Limit; // Skip data
+ throw new ProtocolDecoderException(
+ "No appropriate message decoder: " + input.GetHexDump());
+ }
+
+ if (_currentDecoder == null)
+ {
+ // Decoder is not determined yet (i.e. we need more data)
+ return false;
+ }
+ }
+
+ result = _currentDecoder.Decode(input, output);
+ if (result == MessageDecoderResult.OK)
+ {
+ _currentDecoder = null;
+ return true;
+ }
+ else if (result == MessageDecoderResult.NEED_DATA)
+ {
+ return false;
+ }
+ else if (result == MessageDecoderResult.NOT_OK)
+ {
+ throw new ProtocolDecoderException("Message decoder returned NOT_OK.");
+ }
+ else
+ {
+ throw new Exception("Unexpected decode result (see your decode()): " + result);
+ }
+ }
+ }
+
+ private class SingletonMessageEncoderFactory : IMessageEncoderFactory
+ {
+ private readonly IMessageEncoder _encoder;
+
+ public SingletonMessageEncoderFactory(IMessageEncoder encoder)
+ {
+ if (encoder == null)
+ {
+ throw new ArgumentNullException("encoder");
+ }
+ _encoder = encoder;
+ }
+
+ public IMessageEncoder NewEncoder()
+ {
+ return _encoder;
+ }
+ }
+
+ private class SingletonMessageDecoderFactory : IMessageDecoderFactory
+ {
+ private readonly IMessageDecoder _decoder;
+
+ public SingletonMessageDecoderFactory(IMessageDecoder decoder)
+ {
+ if (decoder == null)
+ {
+ throw new ArgumentNullException("decoder");
+ }
+ _decoder = decoder;
+ }
+
+ public IMessageDecoder NewDecoder()
+ {
+ return _decoder;
+ }
+ }
+
+ private class DefaultConstructorMessageEncoderFactory : IMessageEncoderFactory
+ {
+ private readonly Type _encoderClass;
+
+ public DefaultConstructorMessageEncoderFactory(Type encoderClass)
+ {
+ if (encoderClass == null)
+ {
+ throw new ArgumentNullException("encoderClass");
+ }
+
+ if(!typeof(IMessageEncoder).IsAssignableFrom(encoderClass))
+ {
+ throw new ArgumentException("encoderClass is not assignable to MessageEncoder");
+ }
+ _encoderClass = encoderClass;
+ }
+
+ public IMessageEncoder NewEncoder()
+ {
+ try
+ {
+ return (IMessageEncoder) Activator.CreateInstance(_encoderClass);
+ }
+ catch (Exception e)
+ {
+ throw new Exception( "Failed to create a new instance of " + _encoderClass, e);
+ }
+ }
+ }
+
+ private class DefaultConstructorMessageDecoderFactory : IMessageDecoderFactory
+ {
+ private readonly Type _decoderClass;
+
+ public DefaultConstructorMessageDecoderFactory(Type decoderClass)
+ {
+ if (decoderClass == null)
+ {
+ throw new ArgumentNullException("decoderClass");
+ }
+
+ if(!typeof(IMessageDecoder).IsAssignableFrom(decoderClass))
+ {
+ throw new ArgumentException("decoderClass is not assignable to MessageDecoder");
+ }
+ _decoderClass = decoderClass;
+ }
+
+ public IMessageDecoder NewDecoder()
+ {
+ try
+ {
+ return (IMessageDecoder) Activator.CreateInstance(_decoderClass);
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Failed to create a new instance of " + _decoderClass, e);
+ }
+ }
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Codec/Demux/IMessageDecoder.cs b/dotnet/Qpid.Codec/Demux/IMessageDecoder.cs
new file mode 100644
index 0000000000..5892673440
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/IMessageDecoder.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec.Demux
+{
+ public interface IMessageDecoder
+ {
+ /// <summary>
+ /// Checks the specified buffer is decodable by this decoder.
+ /// </summary>
+ /// <param name="buffer">The buffer to read data from.</param>
+ /// <returns>
+ /// OK if this decoder can decode the specified buffer.
+ /// NOT_OK if this decoder cannot decode the specified buffer.
+ /// if more data is required to determine if the
+ /// specified buffer is decodable ({@link #OK}) or not decodable
+ /// {@link #NOT_OK}.</returns>
+ MessageDecoderResult Decodable(ByteBuffer buffer);
+
+ /// <summary>
+ /// Decodes binary or protocol-specific content into higher-level message objects.
+ /// MINA invokes {@link #decode(IoSession, ByteBuffer, ProtocolDecoderOutput)}
+ /// method with read data, and then the decoder implementation puts decoded
+ /// messages into {@link ProtocolDecoderOutput}.
+ /// </summary>
+ /// <returns>
+ /// {@link #OK} if you finished decoding messages successfully.
+ /// {@link #NEED_DATA} if you need more data to finish decoding current message.
+ /// {@link #NOT_OK} if you cannot decode current message due to protocol specification violation.
+ /// </returns>
+ /// <exception cref="Exception">if the read data violated protocol specification </exception>
+ MessageDecoderResult Decode(ByteBuffer buffer, IProtocolDecoderOutput output);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Demux/IMessageDecoderFactory.cs b/dotnet/Qpid.Codec/Demux/IMessageDecoderFactory.cs
new file mode 100644
index 0000000000..9e333d670f
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/IMessageDecoderFactory.cs
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Codec.Demux
+{
+ public interface IMessageDecoderFactory
+ {
+ /// <summary>
+ /// Creates a new message decoder.
+ /// </summary>
+ IMessageDecoder NewDecoder();
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Demux/IMessageEncoder.cs b/dotnet/Qpid.Codec/Demux/IMessageEncoder.cs
new file mode 100644
index 0000000000..75ae23592b
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/IMessageEncoder.cs
@@ -0,0 +1,48 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Codec.Demux
+{
+ public interface IMessageEncoder
+ {
+ /// <summary>
+ /// Returns the set of message classes this encoder can encode.
+ /// </summary>
+ Hashtable MessageTypes
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Encodes higher-level message objects into binary or protocol-specific data.
+ /// MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)}
+ /// method with message which is popped from the session write queue, and then
+ /// the encoder implementation puts encoded {@link ByteBuffer}s into
+ /// {@link ProtocolEncoderOutput}.
+ /// </summary>
+ /// <exception cref="Exception">if the message violated protocol specification</exception>
+ void Encode(Object message, IProtocolEncoderOutput output);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Demux/IMessageEncoderFactory.cs b/dotnet/Qpid.Codec/Demux/IMessageEncoderFactory.cs
new file mode 100644
index 0000000000..3001d1a963
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/IMessageEncoderFactory.cs
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Codec.Demux
+{
+ public interface IMessageEncoderFactory
+ {
+ /// <summary>
+ /// Creates a new message encoder.
+ /// </summary>
+ IMessageEncoder NewEncoder();
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Demux/MessageDecoderResult.cs b/dotnet/Qpid.Codec/Demux/MessageDecoderResult.cs
new file mode 100644
index 0000000000..ab01864bc0
--- /dev/null
+++ b/dotnet/Qpid.Codec/Demux/MessageDecoderResult.cs
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Codec.Demux
+{
+ public enum MessageDecoderResult
+ {
+ OK, NOT_OK, NEED_DATA
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/IProtocolCodecFactory.cs b/dotnet/Qpid.Codec/IProtocolCodecFactory.cs
new file mode 100644
index 0000000000..a26b91b16c
--- /dev/null
+++ b/dotnet/Qpid.Codec/IProtocolCodecFactory.cs
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Codec
+{
+ public interface IProtocolCodecFactory
+ {
+ IProtocolEncoder Encoder
+ {
+ get;
+ }
+
+ IProtocolDecoder Decoder
+ {
+ get;
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/IProtocolDecoder.cs b/dotnet/Qpid.Codec/IProtocolDecoder.cs
new file mode 100644
index 0000000000..3cccb0f7da
--- /dev/null
+++ b/dotnet/Qpid.Codec/IProtocolDecoder.cs
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec
+{
+ public interface IProtocolDecoder : IDisposable
+ {
+ /// <summary>
+ /// Decodes binary or protocol-specific content into higher-level message objects.
+ /// MINA invokes {@link #decode(IoSession, ByteBuffer, ProtocolDecoderOutput)}
+ /// method with read data, and then the decoder implementation puts decoded
+ /// messages into {@link ProtocolDecoderOutput}.
+ /// </summary>
+ /// <param name="input"></param>
+ /// <param name="output"></param>
+ /// <exception cref="Exception">if the read data violated protocol specification</exception>
+ void Decode(ByteBuffer input, IProtocolDecoderOutput output);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/IProtocolDecoderOutput.cs b/dotnet/Qpid.Codec/IProtocolDecoderOutput.cs
new file mode 100644
index 0000000000..77a1aea9db
--- /dev/null
+++ b/dotnet/Qpid.Codec/IProtocolDecoderOutput.cs
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace Apache.Qpid.Codec
+{
+ public interface IProtocolDecoderOutput
+ {
+ /// <summary>
+ /// Callback for {@link ProtocolDecoder} to generate decoded messages.
+ /// {@link ProtocolDecoder} must call {@link #write(Object)} for each
+ /// decoded messages.
+ /// </summary>
+ /// <param name="message">the decoded message</param>
+ void Write(object message);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/IProtocolEncoder.cs b/dotnet/Qpid.Codec/IProtocolEncoder.cs
new file mode 100644
index 0000000000..a16f2ad9d6
--- /dev/null
+++ b/dotnet/Qpid.Codec/IProtocolEncoder.cs
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Codec
+{
+ public interface IProtocolEncoder : IDisposable
+ {
+ /// <summary>
+ /// Encodes higher-level message objects into binary or protocol-specific data.
+ /// MINA invokes {@link #encode(IoSession, Object, ProtocolEncoderOutput)}
+ /// method with message which is popped from the session write queue, and then
+ /// the encoder implementation puts encoded {@link ByteBuffer}s into
+ /// {@link ProtocolEncoderOutput}.
+ /// </summary>
+ /// <param name="message"></param>
+ /// <param name="output"></param>
+ /// <exception cref="Exception">if the message violated protocol specification</exception>
+ void Encode(Object message, IProtocolEncoderOutput output);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/IProtocolEncoderOutput.cs b/dotnet/Qpid.Codec/IProtocolEncoderOutput.cs
new file mode 100644
index 0000000000..70f9be38dc
--- /dev/null
+++ b/dotnet/Qpid.Codec/IProtocolEncoderOutput.cs
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec
+{
+ public interface IProtocolEncoderOutput
+ {
+ /// <summary>
+ /// Callback for {@link ProtocolEncoder} to generate encoded
+ /// {@link ByteBuffer}s. {@link ProtocolEncoder} must call
+ /// {@link #write(ByteBuffer)} for each decoded messages.
+ /// </summary>
+ /// <param name="buf">the buffer which contains encoded data</param>
+ void Write(ByteBuffer buf);
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Properties/AssemblyInfo.cs b/dotnet/Qpid.Codec/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..5261a62ec5
--- /dev/null
+++ b/dotnet/Qpid.Codec/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Codec")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Codec")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8bfe84f8-cd88-48f7-b0d2-0010411a14e5")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Codec/ProtocolCodecException.cs b/dotnet/Qpid.Codec/ProtocolCodecException.cs
new file mode 100644
index 0000000000..49678d2c11
--- /dev/null
+++ b/dotnet/Qpid.Codec/ProtocolCodecException.cs
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Codec
+{
+ [Serializable]
+ public class ProtocolCodecException : Exception
+ {
+ public ProtocolCodecException() : base()
+ {
+ }
+
+ public ProtocolCodecException(string message) : base(message)
+ {
+ }
+
+ public ProtocolCodecException(Exception cause) : base("Codec Exception", cause)
+ {
+ }
+
+ protected ProtocolCodecException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Codec/ProtocolDecoderException.cs b/dotnet/Qpid.Codec/ProtocolDecoderException.cs
new file mode 100644
index 0000000000..8e7e6da145
--- /dev/null
+++ b/dotnet/Qpid.Codec/ProtocolDecoderException.cs
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Codec
+{
+ [Serializable]
+ public class ProtocolDecoderException : ProtocolCodecException
+ {
+ private string _hexdump;
+
+ public ProtocolDecoderException() : base()
+ {
+ }
+
+ public ProtocolDecoderException(string message) : base(message)
+ {
+ }
+
+ public ProtocolDecoderException(Exception cause) : base(cause)
+ {
+ }
+
+ protected ProtocolDecoderException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _hexdump = info.GetString("HexDump");
+ }
+
+ public string HexDump
+ {
+ get
+ {
+ return _hexdump;
+ }
+ set
+ {
+ _hexdump = value;
+ }
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("HexDump", _hexdump);
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Codec/ProtocolEncoderException.cs b/dotnet/Qpid.Codec/ProtocolEncoderException.cs
new file mode 100644
index 0000000000..ac565a308b
--- /dev/null
+++ b/dotnet/Qpid.Codec/ProtocolEncoderException.cs
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Codec
+{
+ [Serializable]
+ public class ProtocolEncoderException : ProtocolCodecException
+ {
+ public ProtocolEncoderException() : base()
+ {
+ }
+
+ public ProtocolEncoderException(string message) : base(message)
+ {
+ }
+
+ public ProtocolEncoderException(Exception cause) : base(cause)
+ {
+ }
+
+ protected ProtocolEncoderException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
+
+
+
diff --git a/dotnet/Qpid.Codec/Qpid.Codec.csproj b/dotnet/Qpid.Codec/Qpid.Codec.csproj
new file mode 100644
index 0000000000..a0217cffa3
--- /dev/null
+++ b/dotnet/Qpid.Codec/Qpid.Codec.csproj
@@ -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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Codec</RootNamespace>
+ <AssemblyName>Apache.Qpid.Codec</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.0.30714, Culture=neutral, PublicKeyToken=500ffcafb14f92df">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Common\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Codec/Support/SimpleProtocolDecoderOutput.cs b/dotnet/Qpid.Codec/Support/SimpleProtocolDecoderOutput.cs
new file mode 100644
index 0000000000..0a4ff10ff0
--- /dev/null
+++ b/dotnet/Qpid.Codec/Support/SimpleProtocolDecoderOutput.cs
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections;
+
+namespace Apache.Qpid.Codec.Support
+{
+ public class SimpleProtocolDecoderOutput : IProtocolDecoderOutput
+ {
+ private readonly Queue _messageQueue = new Queue();
+
+ public Queue MessageQueue
+ {
+ get
+ {
+ return _messageQueue;
+ }
+ }
+
+ public void Write(object message)
+ {
+ _messageQueue.Enqueue(message);
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Codec/Support/SimpleProtocolEncoderOutput.cs b/dotnet/Qpid.Codec/Support/SimpleProtocolEncoderOutput.cs
new file mode 100644
index 0000000000..2e4224ef98
--- /dev/null
+++ b/dotnet/Qpid.Codec/Support/SimpleProtocolEncoderOutput.cs
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Collections;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Codec.Support
+{
+ public abstract class SimpleProtocolEncoderOutput : IProtocolEncoderOutput
+ {
+ private readonly Queue _bufferQueue = new Queue();
+
+ public Queue BufferQueue
+ {
+ get
+ {
+ return _bufferQueue;
+ }
+ }
+
+ public void Write(ByteBuffer buf)
+ {
+ _bufferQueue.Enqueue(buf);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Codec/default.build b/dotnet/Qpid.Codec/default.build
new file mode 100644
index 0000000000..dd59df7d6a
--- /dev/null
+++ b/dotnet/Qpid.Codec/default.build
@@ -0,0 +1,47 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Codec" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/Apache.Qpid.Buffer.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Common.Tests/Properties/AssemblyInfo.cs b/dotnet/Qpid.Common.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..2516a73035
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Common.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Common.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("2c0d906c-375d-4b04-8ad0-a22fcb4e7337")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Common.Tests/Qpid.Common.Tests.csproj b/dotnet/Qpid.Common.Tests/Qpid.Common.Tests.csproj
new file mode 100644
index 0000000000..c99217cc51
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Qpid.Common.Tests.csproj
@@ -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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F83624B0-762B-4D82-900D-FF4C1B36E36E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Tests</RootNamespace>
+ <AssemblyName>Apache.Qpid.Common.Tests</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.2.6.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Client.Tests\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Common.Tests/Qpid/Collections/TestConsumerProducerQueue.cs b/dotnet/Qpid.Common.Tests/Qpid/Collections/TestConsumerProducerQueue.cs
new file mode 100644
index 0000000000..3e19508bac
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Qpid/Collections/TestConsumerProducerQueue.cs
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using Apache.Qpid.Collections;
+
+namespace Apache.Qpid.Collections.Tests
+{
+ [TestFixture]
+ public class TestConsumerProducerQueue
+ {
+ private ConsumerProducerQueue _queue;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _queue = new ConsumerProducerQueue();
+ }
+
+ [Test]
+ public void CanDequeueWithInifiniteWait()
+ {
+ Thread producer = new Thread(new ThreadStart(ProduceFive));
+ producer.Start();
+ for ( int i = 0; i < 5; i++ )
+ {
+ object item = _queue.Dequeue();
+ Assert.IsNotNull(item);
+ }
+ }
+
+ [Test]
+ public void ReturnsNullOnDequeueTimeout()
+ {
+ // queue is empty
+ Assert.IsNull(_queue.Dequeue(500));
+ }
+
+ [Test]
+ public void DequeueTillEmpty()
+ {
+ _queue.Enqueue(1);
+ _queue.Enqueue(2);
+ _queue.Enqueue(3);
+ Assert.AreEqual(1, _queue.Dequeue());
+ Assert.AreEqual(2, _queue.Dequeue());
+ Assert.AreEqual(3, _queue.Dequeue());
+ // no messages in queue, will timeout
+ Assert.IsNull(_queue.Dequeue(500));
+ }
+
+
+ private void ProduceFive()
+ {
+ Thread.Sleep(1000);
+ _queue.Enqueue("test item 1");
+ _queue.Enqueue("test item 2");
+ _queue.Enqueue("test item 3");
+ Thread.Sleep(0);
+ _queue.Enqueue("test item 4");
+ _queue.Enqueue("test item 5");
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common.Tests/Qpid/Collections/TestLinkedHashtable.cs b/dotnet/Qpid.Common.Tests/Qpid/Collections/TestLinkedHashtable.cs
new file mode 100644
index 0000000000..dbbc98a2e6
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Qpid/Collections/TestLinkedHashtable.cs
@@ -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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using NUnit.Framework;
+
+namespace Apache.Qpid.Collections
+{
+ [TestFixture]
+ public class TestLinkedHashtable
+ {
+ [Test]
+ public void Test1()
+ {
+ LinkedHashtable table = new LinkedHashtable();
+ table["Super"] = "Ayr";
+ table["Ayr"] = "United";
+ table["Fred"] = "Wilma";
+ table["Dumbarton"] = "Gubbed";
+ dumpDictionary(table);
+
+ Console.WriteLine("\nRemoving XXX (non-existant)");
+ table.Remove("XXX");
+ dumpDictionary(table);
+
+ Console.WriteLine("\nRemoving Fred");
+ table.Remove("Fred");
+ dumpDictionary(table);
+
+ Console.WriteLine("\nMoving Dumbarton to head");
+ table.MoveToHead("Dumbarton");
+ dumpDictionary(table);
+ }
+
+ private static void dumpDictionary(LinkedHashtable table)
+ {
+ foreach (DictionaryEntry o in table)
+ {
+ Console.WriteLine(string.Format("Item: key={0} value={1}", o.Key, o.Value));
+ }
+
+ Console.WriteLine("keys are " + InspectCollection(table.Keys));
+ Console.WriteLine("values are " + InspectCollection(table.Values));
+ }
+
+ static string InspectCollection(ICollection collection)
+ {
+ StringBuilder sb = null;
+ foreach (object o in collection)
+ {
+ if (sb == null)
+ {
+ sb = new StringBuilder(o.ToString());
+ }
+ else
+ {
+ sb.Append(", ");
+ sb.Append(o.ToString());
+ }
+ }
+ return sb.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common.Tests/Qpid/Framing/TestAMQType.cs b/dotnet/Qpid.Common.Tests/Qpid/Framing/TestAMQType.cs
new file mode 100644
index 0000000000..23cb71c9f8
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Qpid/Framing/TestAMQType.cs
@@ -0,0 +1,270 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using NUnit.Framework;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Framing.Tests
+{
+ [TestFixture]
+ public class TestAMQType
+ {
+
+ #region LONG_STRING tests
+ [Test]
+ public void LONG_STRING_ReadWrite()
+ {
+ AMQType type = AMQType.LONG_STRING;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const string VALUE = "simple string 1";
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // LONG_STRING tests
+
+ #region UINT32 tests
+ [Test]
+ public void UINT32_CanGetEncodingSize()
+ {
+ AMQType type = AMQType.UINT32;
+ Assert.AreEqual(4, type.GetEncodingSize(1234443));
+ }
+
+ [Test]
+ public void UINT32_ToNativeValue()
+ {
+ AMQType type = AMQType.UINT32;
+ Assert.AreEqual(1, type.ToNativeValue(1));
+ Assert.AreEqual(1, type.ToNativeValue((short)1));
+ Assert.AreEqual(1, type.ToNativeValue((byte)1));
+ Assert.AreEqual(1, type.ToNativeValue("1"));
+
+ try
+ {
+ Assert.AreEqual(1, type.ToNativeValue("adasdads"));
+ Assert.Fail("Invalid format allowed");
+ } catch ( FormatException )
+ {
+ }
+ }
+
+ [Test]
+ public void UINT32_ReadWrite()
+ {
+ AMQType type = AMQType.UINT32;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const uint VALUE = 0xFFEEDDCC;
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // UINT32 Tests
+
+ #region VOID Tests
+ [Test]
+ public void VOID_CanGetEncodingSize()
+ {
+ AMQType type = AMQType.VOID;
+ Assert.AreEqual(0, type.GetEncodingSize(null));
+ }
+
+ [Test]
+ public void VOID_ToNativeValue()
+ {
+ AMQType type = AMQType.VOID;
+ Assert.IsNull(type.ToNativeValue(null));
+
+ try
+ {
+ type.ToNativeValue("asdasd");
+ Assert.Fail("converted invalid value");
+ } catch (FormatException)
+ {
+ }
+ }
+
+ [Test]
+ public void VOID_ReadWrite()
+ {
+ AMQType type = AMQType.VOID;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+
+ type.WriteToBuffer(null, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(null, value.Value);
+ }
+
+ #endregion // VOID Tests
+
+ #region BOOLEAN Tests
+ [Test]
+ public void BOOLEAN_CanGetEncodingSize()
+ {
+ AMQType type = AMQType.BOOLEAN;
+ Assert.AreEqual(1, type.GetEncodingSize(true));
+ }
+
+ [Test]
+ public void BOOLEAN_ToNativeValue()
+ {
+ AMQType type = AMQType.BOOLEAN;
+ Assert.AreEqual(true, type.ToNativeValue(true));
+ Assert.AreEqual(false, type.ToNativeValue("false"));
+
+ try
+ {
+ type.ToNativeValue("asdasd");
+ Assert.Fail("converted invalid value");
+ } catch ( FormatException )
+ {
+ }
+ }
+
+ [Test]
+ public void BOOLEAN_ReadWrite()
+ {
+ AMQType type = AMQType.BOOLEAN;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+
+ type.WriteToBuffer(true, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(true, value.Value);
+ }
+ #endregion // BOOLEAN Tests
+
+ #region INT16 tests
+ [Test]
+ public void INT16_ReadWrite()
+ {
+ AMQType type = AMQType.INT16;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const short VALUE = -32765;
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ //public void UINT16_ReadWrite()
+ //{
+ // AMQType type = AMQType.UINT16;
+ // ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ // const ushort VALUE = 64321;
+
+ // type.WriteToBuffer(VALUE, buffer);
+ // buffer.Flip();
+ // buffer.Rewind();
+ // AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ // Assert.AreEqual(VALUE, value.Value);
+ //}
+ #endregion // INT16 Tests
+
+ #region INT32 tests
+ [Test]
+ public void INT32_ReadWrite()
+ {
+ AMQType type = AMQType.INT32;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const int VALUE = -39273563;
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // INT32 Tests
+
+ #region INT64 tests
+ [Test]
+ public void INT64_ReadWrite()
+ {
+ AMQType type = AMQType.INT64;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const long VALUE = -(2^43+1233123);
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ [Test]
+ public void UINT64_ReadWrite()
+ {
+ AMQType type = AMQType.UINT64;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const ulong VALUE = (2 ^ 61 + 1233123);
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // INT64 Tests
+
+ #region FLOAT tests
+ [Test]
+ public void FLOAT_ReadWrite()
+ {
+ AMQType type = AMQType.FLOAT;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const float VALUE = 1.2345000E-035f;
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // FLOAT Tests
+
+ #region DOUBLE tests
+ [Test]
+ public void DOUBLE_ReadWrite()
+ {
+ AMQType type = AMQType.DOUBLE;
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ const double VALUE = 1.2345000E-045;
+
+ type.WriteToBuffer(VALUE, buffer);
+ buffer.Flip();
+ buffer.Rewind();
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ Assert.AreEqual(VALUE, value.Value);
+ }
+ #endregion // FLOAT Tests
+ }
+}
diff --git a/dotnet/Qpid.Common.Tests/Qpid/Framing/TestEncodingUtils.cs b/dotnet/Qpid.Common.Tests/Qpid/Framing/TestEncodingUtils.cs
new file mode 100644
index 0000000000..a8202dc70d
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/Qpid/Framing/TestEncodingUtils.cs
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using NUnit.Framework;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Framing.Tests
+{
+ [TestFixture]
+ public class TestEncodingUtils
+ {
+ [Test]
+ public void CanReadLongAsShortString()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ EncodingUtils.WriteShortStringBytes(buffer, "98878122");
+ buffer.Flip();
+ long value = EncodingUtils.ReadLongAsShortString(buffer);
+ Assert.AreEqual(98878122, value);
+ }
+ [Test]
+ public void CanReadLongAsShortStringNegative()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ EncodingUtils.WriteShortStringBytes(buffer, "-98878122");
+ buffer.Flip();
+ long value = EncodingUtils.ReadLongAsShortString(buffer);
+ Assert.AreEqual(-98878122, value);
+ }
+ [Test]
+ public void CanReadLongAsShortStringEmpty()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(0x1000);
+ EncodingUtils.WriteShortStringBytes(buffer, "");
+ buffer.Flip();
+ long value = EncodingUtils.ReadLongAsShortString(buffer);
+ Assert.AreEqual(0, value);
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Common.Tests/default.build b/dotnet/Qpid.Common.Tests/default.build
new file mode 100644
index 0000000000..a97c0282c2
--- /dev/null
+++ b/dotnet/Qpid.Common.Tests/default.build
@@ -0,0 +1,52 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Common" default="test">
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="true" debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.Tests.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/${project::get-name()}.dll" />
+ <include name="${build.dir}/Apache.Qpid.Codec.dll" />
+ <include name="${build.dir}/Apache.Qpid.Messaging.dll" />
+ <include name="${build.dir}/Apache.Qpid.Buffer.dll" />
+ </references>
+
+ </csc>
+ </target>
+ <target name="test" depends="build">
+ <nunit2>
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test assemblyname="${build.dir}/${project::get-name()}.Tests.dll" />
+ </nunit2>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Common/AMQChannelClosedException.cs b/dotnet/Qpid.Common/AMQChannelClosedException.cs
new file mode 100644
index 0000000000..98c6966cd1
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQChannelClosedException.cs
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid
+{
+ [Serializable]
+ public class AMQChannelClosedException : AMQException
+ {
+ public AMQChannelClosedException(int errorCode, string message)
+ : base(errorCode, message)
+ {
+ }
+
+ protected AMQChannelClosedException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQConnectionClosedException.cs b/dotnet/Qpid.Common/AMQConnectionClosedException.cs
new file mode 100644
index 0000000000..136131144b
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQConnectionClosedException.cs
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid
+{
+ /// <summary>
+ /// AMQConnectionClosedException indicates that a connection has been closed.
+ ///
+ /// <p/>This exception is really used as an event, in order that the method handler that raises it creates an event
+ /// which is propagated to the io handler, in order to notify it of the connection closure.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Represents a the closure of a connection.
+ /// </table>
+ /// </summary>
+ [Serializable]
+ public class AMQConnectionClosedException : AMQException
+ {
+ public AMQConnectionClosedException(int errorCode, string message)
+ : base(errorCode, message)
+ {
+ }
+
+ protected AMQConnectionClosedException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQDisconnectedException.cs b/dotnet/Qpid.Common/AMQDisconnectedException.cs
new file mode 100644
index 0000000000..b5c4d544cd
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQDisconnectedException.cs
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid
+{
+ [Serializable]
+ public class AMQDisconnectedException : AMQException
+ {
+ public AMQDisconnectedException(int errorCode, string message)
+ : base(errorCode, message)
+ {
+ }
+
+ public AMQDisconnectedException(string message)
+ : base(message)
+ {
+ }
+
+ protected AMQDisconnectedException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQException.cs b/dotnet/Qpid.Common/AMQException.cs
new file mode 100644
index 0000000000..f9f7158a26
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQException.cs
@@ -0,0 +1,149 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using log4net;
+
+namespace Apache.Qpid
+{
+ /// <summary>
+ /// The generic AMQ exception.
+ /// </summary>
+ [Serializable]
+ public class AMQException : Exception
+ {
+ private int _errorCode;
+
+ public AMQException(string message)
+ : base(message)
+ {
+ }
+
+ public AMQException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public AMQException(int errorCode, string message)
+ : base(message)
+ {
+ _errorCode = errorCode;
+ }
+
+ public AMQException(int errorCode, string message, Exception innerException)
+ : base(message, innerException)
+ {
+ _errorCode = errorCode;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:AMQException"/> class, with a logger that will
+ /// be used to output log information upon construction. This saves having to log separately.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="message">The message.</param>
+ public AMQException(ILog logger, string message)
+ : base(message)
+ {
+ logger.Error(message);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:AMQException"/> class, with a logger that will
+ /// be used to output log information upon construction. This saves having to log separately.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="message">The message.</param>
+ /// <param name="innerException">The root cause</param>
+ public AMQException(ILog logger, string message, Exception innerException)
+ : base(message, innerException)
+ {
+ logger.Error(message, innerException);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:AMQException"/> class, with a logger that will
+ /// be used to output log information upon construction. This saves having to log separately.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="message">The message.</param>
+ /// <param name="errorCode">The AMQ error code. See RFC 006 for details of error codes</param>
+ public AMQException(ILog logger, int errorCode, string message)
+ : this(errorCode, message)
+ {
+ logger.Error(message);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:AMQException"/> class, with a logger that will
+ /// be used to output log information upon construction. This saves having to log separately.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="message">The message.</param>
+ /// <param name="errorCode">The AMQ error code. See RFC 006 for details of error codes</param>
+ /// <param name="innerException">The root cause</param>
+ public AMQException(ILog logger, int errorCode, string message, Exception innerException)
+ : this(errorCode, message, innerException)
+ {
+ logger.Error(message, innerException);
+ }
+
+ /// <summary>
+ /// Serialization Constructor
+ /// </summary>
+ /// <param name="info">SerializationInfo object</param>
+ /// <param name="ctxt">StreamingContext object</param>
+ protected AMQException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _errorCode = info.GetInt32("ErrorCode");
+ }
+
+ /// <summary>
+ /// ISerializable implementation of GetObjectData()
+ /// </summary>
+ /// <param name="info">SerializationInfo object</param>
+ /// <param name="ctxt">StreamingContext object</param>
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("ErrorCode", _errorCode);
+ }
+
+
+ /// <summary>
+ /// Gets or sets the error code. See RFC 006 for details of error codes.
+ /// </summary>
+ /// <value>The error code.</value>
+ public int ErrorCode
+ {
+ get
+ {
+ return _errorCode;
+ }
+ set
+ {
+ _errorCode = value;
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQInvalidArgumentException.cs b/dotnet/Qpid.Common/AMQInvalidArgumentException.cs
new file mode 100644
index 0000000000..831f7bab0e
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQInvalidArgumentException.cs
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid
+{
+ /// <summary>
+ /// Thrown when an invalid argument was supplied to the broker
+ /// </summary>
+ [Serializable]
+ public class AMQInvalidArgumentException : AMQException
+ {
+ public AMQInvalidArgumentException(string message)
+ : base(AMQConstant.INVALID_ARGUMENT.Code, message, null)
+ {
+ }
+
+ protected AMQInvalidArgumentException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQInvalidRoutingKeyException.cs b/dotnet/Qpid.Common/AMQInvalidRoutingKeyException.cs
new file mode 100644
index 0000000000..a3ce813d1b
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQInvalidRoutingKeyException.cs
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+using Apache.Qpid.Protocol;
+
+namespace Apache.Qpid
+{
+ /// <summary>
+ /// Thrown when an invalid routing key was sent to the broker
+ /// </summary>
+ [Serializable]
+ public class AMQInvalidRoutingKeyException : AMQException
+ {
+ public AMQInvalidRoutingKeyException(string message)
+ : base(AMQConstant.INVALID_ROUTING_KEY.Code, message, null)
+ {
+ }
+
+ protected AMQInvalidRoutingKeyException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Common/AMQUndeliveredException.cs b/dotnet/Qpid.Common/AMQUndeliveredException.cs
new file mode 100644
index 0000000000..70ad86c8a3
--- /dev/null
+++ b/dotnet/Qpid.Common/AMQUndeliveredException.cs
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid
+{
+ /// <summary>
+ /// Thrown when a message has been bounced by the broker, indicating it could not be delivered.
+ /// </summary>
+ [Serializable]
+ public class AMQUndeliveredException : AMQException
+ {
+ // TODO: Warning, no guarantee that the value stored here is serializable!
+ private object _bounced;
+
+ public AMQUndeliveredException(int errorCode, string message, object bounced)
+ : base(errorCode, message)
+ {
+ _bounced = bounced;
+ }
+
+ protected AMQUndeliveredException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _bounced = info.GetValue("bounced", typeof(object));
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("bounced", _bounced);
+ }
+
+ public object GetUndeliveredMessage()
+ {
+ return _bounced;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/AssemblySettings.cs b/dotnet/Qpid.Common/AssemblySettings.cs
new file mode 100644
index 0000000000..888de692e8
--- /dev/null
+++ b/dotnet/Qpid.Common/AssemblySettings.cs
@@ -0,0 +1,160 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using log4net;
+
+namespace Apache.Qpid.Common
+{
+ /// <summary>
+ ///
+ /// Mike Woodring
+ /// Bear Canyon Consulting LLC
+ /// http://www.bearcanyon.com
+ ///
+ /// AssemblySettings usage:
+ ///
+ /// If you know the keys you're after, the following is probably
+ /// the most convenient:
+ ///
+ /// AssemblySettings settings = new AssemblySettings();
+ /// string someSetting1 = settings["someKey1"];
+ /// string someSetting2 = settings["someKey2"];
+ ///
+ /// If you want to enumerate over the settings (or just as an
+ /// alternative approach), you can do this too:
+ ///
+ /// IDictionary settings = AssemblySettings.GetConfig();
+ ///
+ /// foreach( DictionaryEntry entry in settings )
+ /// {
+ /// // Use entry.Key or entry.Value as desired...
+ /// }
+ ///
+ /// In either of the above two scenarios, the calling assembly
+ /// (the one that called the constructor or GetConfig) is used
+ /// to determine what file to parse and what the name of the
+ /// settings collection element is. For example, if the calling
+ /// assembly is c:\foo\bar\TestLib.dll, then the configuration file
+ /// that's parsed is c:\foo\bar\TestLib.dll.config, and the
+ /// configuration section that's parsed must be named <assemblySettings>.
+ ///
+ /// To retrieve the configuration information for an arbitrary assembly,
+ /// use the overloaded constructor or GetConfig method that takes an
+ /// Assembly reference as input.
+ ///
+ /// If your assembly is being automatically downloaded from a web
+ /// site by an "href-exe" (an application that's run directly from a link
+ /// on a web page), then the enclosed web.config shows the mechanism
+ /// for allowing the AssemblySettings library to download the
+ /// configuration files you're using for your assemblies (while not
+ /// allowing web.config itself to be downloaded).
+ ///
+ /// If the assembly you are trying to use this with is installed in, and loaded
+ /// from, the GAC then you'll need to place the config file in the GAC directory where
+ /// the assembly is installed. On the first release of the CLR, this directory is
+ /// <windir>\assembly\gac\libName\verNum__pubKeyToken]]>. For example,
+ /// the assembly "SomeLib, Version=1.2.3.4, Culture=neutral, PublicKeyToken=abcd1234"
+ /// would be installed to the c:\winnt\assembly\gac\SomeLib\1.2.3.4__abcd1234 diretory
+ /// (assuming the OS is installed in c:\winnt). For future versions of the CLR, this
+ /// directory scheme may change, so you'll need to check the <code>CodeBase</code> property
+ /// of a GAC-loaded assembly in the debugger to determine the correct directory location.
+ ///
+ /// </summary>
+ public class AssemblySettings
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(AssemblySettings));
+
+ private IDictionary settings;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public AssemblySettings()
+ : this(Assembly.GetCallingAssembly())
+ {
+ }
+
+ public AssemblySettings(Assembly asm)
+ {
+ settings = GetConfig(asm);
+ }
+
+ public string this[string key]
+ {
+ get
+ {
+ string settingValue = null;
+
+ if (settings != null)
+ {
+ settingValue = settings[key] as string;
+ }
+
+ return (settingValue == null ? "" : settingValue);
+ }
+ }
+
+ public static IDictionary GetConfig()
+ {
+ return GetConfig(Assembly.GetCallingAssembly());
+ }
+
+ public static IDictionary GetConfig(Assembly asm)
+ {
+ // Open and parse configuration file for specified
+ // assembly, returning collection to caller for future
+ // use outside of this class.
+ string cfgFile = asm.CodeBase + ".config";
+ try
+ {
+ const string nodeName = "assemblySettings";
+
+ XmlDocument doc = new XmlDocument();
+ doc.Load(new XmlTextReader(cfgFile));
+
+ XmlNodeList nodes = doc.GetElementsByTagName(nodeName);
+
+ foreach (XmlNode node in nodes)
+ {
+ if (node.LocalName == nodeName)
+ {
+ DictionarySectionHandler handler = new DictionarySectionHandler();
+ return (IDictionary)handler.Create(null, null, node);
+ }
+ }
+ }
+ catch (FileNotFoundException)
+ {
+ _log.Warn("Assembly configuration file not found: " + cfgFile);
+ }
+ catch (Exception e)
+ {
+ _log.Warn("Failed to load .config file: " + cfgFile, e);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Collections/BlockingQueue.cs b/dotnet/Qpid.Common/Collections/BlockingQueue.cs
new file mode 100644
index 0000000000..dcfacf8474
--- /dev/null
+++ b/dotnet/Qpid.Common/Collections/BlockingQueue.cs
@@ -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.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Collections
+{
+ public abstract class BlockingQueue : Queue
+ {
+ /**
+ * Inserts the specified element into this queue if it is possible to do
+ * so immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * available. When using a capacity-restricted queue, this method is
+ * generally preferable to {@link #add}, which can fail to insert an
+ * element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ public abstract bool EnqueueNoThrow(Object e);
+
+ /**
+ * Inserts the specified element into this queue, waiting if necessary
+ * for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ public abstract void EnqueueBlocking(object e);
+
+ /**
+ * Retrieves and removes the head of this queue, waiting up to the
+ * specified wait time if necessary for an element to become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ public abstract object DequeueBlocking();
+
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+ * limit.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ *
+ * @return the remaining capacity
+ */
+ public abstract int RemainingCapacity
+ {
+ get;
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Common/Collections/ConsumerProducerQueue.cs b/dotnet/Qpid.Common/Collections/ConsumerProducerQueue.cs
new file mode 100644
index 0000000000..131f316da6
--- /dev/null
+++ b/dotnet/Qpid.Common/Collections/ConsumerProducerQueue.cs
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Threading;
+
+
+namespace Apache.Qpid.Collections
+{
+ /// <summary>
+ /// Simple FIFO queue to support multi-threaded consumer
+ /// and producers. It supports timeouts in dequeue operations.
+ /// </summary>
+ public sealed class ConsumerProducerQueue
+ {
+ private Queue _queue = new Queue();
+ private WaitSemaphore _semaphore = new WaitSemaphore();
+
+ /// <summary>
+ /// Put an item into the tail of the queue
+ /// </summary>
+ /// <param name="item"></param>
+ public void Enqueue(object item)
+ {
+ lock ( _queue.SyncRoot )
+ {
+ _queue.Enqueue(item);
+ _semaphore.Increment();
+ }
+ }
+
+ /// <summary>
+ /// Wait indefinitely for an item to be available
+ /// on the queue.
+ /// </summary>
+ /// <returns>The object at the head of the queue</returns>
+ public object Dequeue()
+ {
+ return Dequeue(Timeout.Infinite);
+ }
+
+ /// <summary>
+ /// Wait up to the number of milliseconds specified
+ /// for an item to be available on the queue
+ /// </summary>
+ /// <param name="timeout">Number of milliseconds to wait</param>
+ /// <returns>The object at the head of the queue, or null
+ /// if the timeout expires</returns>
+ public object Dequeue(long timeout)
+ {
+ if ( _semaphore.Decrement(timeout) )
+ {
+ lock ( _queue.SyncRoot )
+ {
+ return _queue.Dequeue();
+ }
+ }
+ return null;
+ }
+
+ #region Simple Semaphore
+ //
+ // Simple Semaphore
+ //
+
+ class WaitSemaphore
+ {
+ private int _count;
+ private AutoResetEvent _event = new AutoResetEvent(false);
+
+ public void Increment()
+ {
+ Interlocked.Increment(ref _count);
+ _event.Set();
+ }
+
+ public bool Decrement(long timeout)
+ {
+ if ( timeout > int.MaxValue )
+ throw new ArgumentOutOfRangeException("timeout", timeout, "Must be <= Int32.MaxValue");
+
+ int millis = (int) (timeout & 0x7FFFFFFF);
+ if ( Interlocked.Decrement(ref _count) > 0 )
+ {
+ // there are messages in queue, so no need to wait
+ return true;
+ } else
+ {
+ return _event.WaitOne(millis, false);
+ }
+ }
+ }
+ #endregion // Simple Semaphore
+ }
+}
diff --git a/dotnet/Qpid.Common/Collections/LinkedBlockingQueue.cs b/dotnet/Qpid.Common/Collections/LinkedBlockingQueue.cs
new file mode 100644
index 0000000000..be92576951
--- /dev/null
+++ b/dotnet/Qpid.Common/Collections/LinkedBlockingQueue.cs
@@ -0,0 +1,384 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+
+namespace Apache.Qpid.Collections
+{
+ public class LinkedBlockingQueue : BlockingQueue
+ {
+
+ /*
+ * A variant of the "two lock queue" algorithm. The putLock gates
+ * entry to put (and offer), and has an associated condition for
+ * waiting puts. Similarly for the takeLock. The "count" field
+ * that they both rely on is maintained as an atomic to avoid
+ * needing to get both locks in most cases. Also, to minimize need
+ * for puts to get takeLock and vice-versa, cascading notifies are
+ * used. When a put notices that it has enabled at least one take,
+ * it signals taker. That taker in turn signals others if more
+ * items have been entered since the signal. And symmetrically for
+ * takes signalling puts. Operations such as remove(Object) and
+ * iterators acquire both locks.
+ */
+
+ /**
+ * Linked list node class
+ */
+ internal class Node
+ {
+ /** The item, volatile to ensure barrier separating write and read */
+ internal volatile Object item;
+ internal Node next;
+ internal Node(Object x) { item = x; }
+ }
+
+ /** The capacity bound, or Integer.MAX_VALUE if none */
+ private readonly int capacity;
+
+ /** Current number of elements */
+ private volatile int count = 0;
+
+ /** Head of linked list */
+ private Node head;
+
+ /** Tail of linked list */
+ private Node last;
+
+ /** Lock held by take, poll, etc */
+ private readonly object takeLock = new Object(); //new SerializableLock();
+
+ /** Lock held by put, offer, etc */
+ private readonly object putLock = new Object();//new SerializableLock();
+
+ /**
+ * Signals a waiting take. Called only from put/offer (which do not
+ * otherwise ordinarily lock takeLock.)
+ */
+ private void SignalNotEmpty()
+ {
+ lock (takeLock)
+ {
+ Monitor.Pulse(takeLock);
+ }
+ }
+
+ /**
+ * Signals a waiting put. Called only from take/poll.
+ */
+ private void SignalNotFull()
+ {
+ lock (putLock)
+ {
+ Monitor.Pulse(putLock);
+ }
+ }
+
+ /**
+ * Creates a node and links it at end of queue.
+ * @param x the item
+ */
+ private void Insert(Object x)
+ {
+ last = last.next = new Node(x);
+ }
+
+ /**
+ * Removes a node from head of queue,
+ * @return the node
+ */
+ private Object Extract()
+ {
+ Node first = head.next;
+ head = first;
+ Object x = first.item;
+ first.item = null;
+ return x;
+ }
+
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingQueue() : this(Int32.MaxValue)
+ {
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this queue
+ * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
+ * than zero
+ */
+ public LinkedBlockingQueue(int capacity)
+ {
+ if (capacity <= 0) throw new ArgumentException("Capacity must be positive, was passed " + capacity);
+ this.capacity = capacity;
+ last = head = new Node(null);
+ }
+
+ // this doc comment is overridden to remove the reference to collections
+ // greater in size than Integer.MAX_VALUE
+ /**
+ * Returns the number of elements in this queue.
+ *
+ * @return the number of elements in this queue
+ */
+ public int Size
+ {
+ get
+ {
+ return count;
+ }
+ }
+
+ // this doc comment is a modified copy of the inherited doc comment,
+ // without the reference to unlimited queues.
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this queue
+ * less the current <tt>size</tt> of this queue.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public override int RemainingCapacity
+ {
+ get
+ {
+ return capacity - count;
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting if
+ * necessary for space to become available.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public override void EnqueueBlocking(Object e)
+ {
+ if (e == null) throw new ArgumentNullException("Object must not be null");
+ // Note: convention in all put/take/etc is to preset
+ // local var holding count negative to indicate failure unless set.
+ int c = -1;
+ lock (putLock)
+ {
+ /*
+ * Note that count is used in wait guard even though it is
+ * not protected by lock. This works because count can
+ * only decrease at this point (all other puts are shut
+ * out by lock), and we (or some other waiting put) are
+ * signalled if it ever changes from
+ * capacity. Similarly for all other uses of count in
+ * other wait guards.
+ */
+ while (count == capacity)
+ {
+ Monitor.Wait(putLock);
+ }
+
+ Insert(e);
+ lock(this)
+ {
+ c = count++;
+ }
+ if (c + 1 < capacity)
+ {
+ Monitor.Pulse(putLock);
+ }
+ }
+
+ if (c == 0)
+ {
+ SignalNotEmpty();
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue if it is
+ * possible to do so immediately without exceeding the queue's capacity,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+ * is full.
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to method {@link BlockingQueue#add add}, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * @throws NullPointerException if the specified element is null
+ */
+ public override bool EnqueueNoThrow(Object e)
+ {
+ if (e == null) throw new ArgumentNullException("e must not be null");
+ if (count == capacity)
+ {
+ return false;
+ }
+ int c = -1;
+ lock (putLock)
+ {
+ if (count < capacity)
+ {
+ Insert(e);
+ lock (this)
+ {
+ c = count++;
+ }
+ if (c + 1 < capacity)
+ {
+ Monitor.Pulse(putLock);
+ }
+ }
+ }
+ if (c == 0)
+ {
+ SignalNotEmpty();
+ }
+ return c >= 0;
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element becomes available.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException if interrupted while waiting
+ */
+ public override Object DequeueBlocking()
+ {
+ Object x;
+ int c = -1;
+ lock (takeLock)
+ {
+
+ while (count == 0)
+ {
+ Monitor.Wait(takeLock);
+ }
+
+
+ x = Extract();
+ lock (this) { c = count--; }
+ if (c > 1)
+ {
+ Monitor.Pulse(takeLock);
+ }
+ }
+ if (c == capacity)
+ {
+ SignalNotFull();
+ }
+ return x;
+ }
+
+ public Object Poll()
+ {
+ if (count == 0)
+ {
+ return null;
+ }
+ Object x = null;
+ int c = -1;
+ lock (takeLock)
+ {
+ if (count > 0)
+ {
+ x = Extract();
+ lock (this) { c = count--; }
+ if (c > 1)
+ {
+ Monitor.Pulse(takeLock);
+ }
+ }
+ }
+ if (c == capacity)
+ {
+ SignalNotFull();
+ }
+ return x;
+ }
+
+
+ public override Object Peek()
+ {
+ if (count == 0)
+ {
+ return null;
+ }
+ lock (takeLock)
+ {
+ Node first = head.next;
+ if (first == null)
+ {
+ return null;
+ }
+ else
+ {
+ return first.item;
+ }
+ }
+ }
+
+ public override String ToString()
+ {
+ lock (putLock)
+ {
+ lock (takeLock)
+ {
+ return base.ToString();
+ }
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public override void Clear()
+ {
+ lock (putLock)
+ {
+ lock (takeLock)
+ {
+ head.next = null;
+ last = head;
+ int c;
+ lock (this)
+ {
+ c = count;
+ count = 0;
+ }
+ if (c == capacity)
+ {
+ Monitor.PulseAll(putLock);
+ }
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/dotnet/Qpid.Common/Collections/LinkedHashtable.cs b/dotnet/Qpid.Common/Collections/LinkedHashtable.cs
new file mode 100644
index 0000000000..10ab5c674d
--- /dev/null
+++ b/dotnet/Qpid.Common/Collections/LinkedHashtable.cs
@@ -0,0 +1,327 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Collections
+{
+ public class LinkedHashtable : IDictionary
+ {
+ /// <summary>
+ /// Maps from key to LinkedDictionaryEntry
+ /// </summary>
+ private Hashtable _indexedValues = new Hashtable();
+
+ private LinkedDictionaryEntry _head;
+
+ private LinkedDictionaryEntry _tail;
+
+ private class LinkedDictionaryEntry
+ {
+ public LinkedDictionaryEntry _previous;
+ public LinkedDictionaryEntry _next;
+ internal DictionaryEntry _entry;
+
+ public LinkedDictionaryEntry(object key, object value)
+ {
+ _entry = new DictionaryEntry(key, value);
+ }
+ }
+
+ public object this[object key]
+ {
+ get
+ {
+ LinkedDictionaryEntry entry = (LinkedDictionaryEntry)_indexedValues[key];
+ if (entry == null)
+ {
+ return null; // key not found
+ }
+ else
+ {
+ return entry._entry.Value;
+ }
+ }
+
+ set
+ {
+ LinkedDictionaryEntry entry = (LinkedDictionaryEntry)_indexedValues[key];
+ if (entry == null)
+ {
+ Add(key, value);
+ }
+ else
+ {
+ entry._entry.Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Collect keys in linked order.
+ /// </summary>
+ public ICollection Keys
+ {
+ get
+ {
+ IList result = new ArrayList();
+ foreach (DictionaryEntry entry in this)
+ {
+ result.Add(entry.Key);
+ }
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Collect values in linked order.
+ /// </summary>
+ public ICollection Values
+ {
+ get
+ {
+ IList result = new ArrayList();
+ foreach (DictionaryEntry entry in this)
+ {
+ result.Add(entry.Value);
+ }
+ return result;
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return _indexedValues.IsReadOnly; }
+ }
+
+ public bool IsFixedSize
+ {
+ get { return _indexedValues.IsFixedSize; }
+ }
+
+ public bool Contains(object key)
+ {
+ return _indexedValues.Contains(key);
+ }
+
+ public void Add(object key, object value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ if (Contains(key))
+ {
+ throw new ArgumentException("LinkedHashtable already contains key. key=" + key);
+ }
+
+ LinkedDictionaryEntry de = new LinkedDictionaryEntry(key, value);
+ if (_head == null)
+ {
+ _head = de;
+ _tail = de;
+ }
+ else
+ {
+ _tail._next = de;
+ de._previous = _tail;
+ _tail = de;
+ }
+ _indexedValues[key] = de;
+ }
+
+ public void Clear()
+ {
+ _indexedValues.Clear();
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator()
+ {
+ return new LHTEnumerator(this);
+ }
+
+ public void Remove(object key)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ LinkedDictionaryEntry de = (LinkedDictionaryEntry)_indexedValues[key];
+ if (de == null) return; // key not found.
+ LinkedDictionaryEntry prev = de._previous;
+ if (prev == null)
+ {
+ _head = de._next;
+ }
+ else
+ {
+ prev._next = de._next;
+ }
+
+ LinkedDictionaryEntry next = de._next;
+ if (next == null)
+ {
+ _tail = de;
+ }
+ else
+ {
+ next._previous = de._previous;
+ }
+ }
+
+ private LinkedDictionaryEntry Head
+ {
+ get
+ {
+ return _head;
+ }
+ }
+
+// private LinkedDictionaryEntry Tail
+// {
+// get
+// {
+// return _tail;
+// }
+// }
+
+ private class LHTEnumerator : IDictionaryEnumerator
+ {
+ private LinkedHashtable _container;
+
+ private LinkedDictionaryEntry _current;
+
+ /// <summary>
+ /// Set once we have navigated off the end of the collection
+ /// </summary>
+ private bool _needsReset = false;
+
+ public LHTEnumerator(LinkedHashtable container)
+ {
+ _container = container;
+ }
+
+ public object Current
+ {
+ get
+ {
+ if (_current == null)
+ {
+ throw new Exception("Iterator before first element");
+ }
+ else
+ {
+ return _current._entry;
+ }
+ }
+ }
+
+ public object Key
+ {
+ get { return _current._entry.Key; }
+ }
+
+ public object Value
+ {
+ get { return _current._entry.Value; }
+ }
+
+ public DictionaryEntry Entry
+ {
+ get
+ {
+ return _current._entry;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ if (_needsReset)
+ {
+ return false;
+ }
+ else if (_current == null)
+ {
+ _current = _container.Head;
+ }
+ else
+ {
+ _current = _current._next;
+ }
+ _needsReset = (_current == null);
+ return !_needsReset;
+ }
+
+ public void Reset()
+ {
+ _current = null;
+ _needsReset = false;
+ }
+ }
+
+ public void MoveToHead(object key)
+ {
+ LinkedDictionaryEntry de = (LinkedDictionaryEntry)_indexedValues[key];
+ if (de == null)
+ {
+ throw new ArgumentException("Key " + key + " not found");
+ }
+ // if the head is the element then there is nothing to do
+ if (_head == de)
+ {
+ return;
+ }
+ de._previous._next = de._next;
+ if (de._next != null)
+ {
+ de._next._previous = de._previous;
+ }
+ else
+ {
+ _tail = de._previous;
+ }
+ de._next = _head;
+ _head = de;
+ de._previous = null;
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ _indexedValues.CopyTo(array, index);
+ }
+
+ public int Count
+ {
+ get { return _indexedValues.Count; }
+ }
+
+ public object SyncRoot
+ {
+ get { return _indexedValues.SyncRoot; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return _indexedValues.IsSynchronized; }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return new LHTEnumerator(this);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Collections/SynchronousQueue.cs b/dotnet/Qpid.Common/Collections/SynchronousQueue.cs
new file mode 100644
index 0000000000..3c12df6067
--- /dev/null
+++ b/dotnet/Qpid.Common/Collections/SynchronousQueue.cs
@@ -0,0 +1,375 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+
+namespace Apache.Qpid.Collections
+{
+ public class SynchronousQueue : BlockingQueue
+ {
+ /// <summary>
+ /// Lock protecting both wait queues
+ /// </summary>
+// private readonly object _qlock = new object();
+
+ /// <summary>
+ /// Queue holding waiting puts
+ /// </summary>
+// private readonly WaitQueue _waitingProducers;
+
+ /// <summary>
+ /// Queue holding waiting takes
+ /// </summary>
+// private readonly WaitQueue _waitingConsumers;
+
+ /**
+ * Queue to hold waiting puts/takes; specialized to Fifo/Lifo below.
+ * These queues have all transient fields, but are serializable
+ * in order to recover fairness settings when deserialized.
+ */
+ internal abstract class WaitQueue
+ {
+ /** Creates, adds, and returns node for x. */
+ internal abstract Node Enq(Object x);
+ /** Removes and returns node, or null if empty. */
+ internal abstract Node Deq();
+ /** Removes a cancelled node to avoid garbage retention. */
+ internal abstract void Unlink(Node node);
+ /** Returns true if a cancelled node might be on queue. */
+ internal abstract bool ShouldUnlink(Node node);
+ }
+
+ /**
+ * FIFO queue to hold waiting puts/takes.
+ */
+ sealed class FifoWaitQueue : WaitQueue
+ {
+ private Node head;
+ private Node last;
+
+ internal override Node Enq(Object x)
+ {
+ Node p = new Node(x);
+ if (last == null)
+ {
+ last = head = p;
+ }
+ else
+ {
+ last = last.next = p;
+ }
+ return p;
+ }
+
+ internal override Node Deq()
+ {
+ Node p = head;
+ if (p != null)
+ {
+ if ((head = p.next) == null)
+ {
+ last = null;
+ }
+ p.next = null;
+ }
+ return p;
+ }
+
+ internal override bool ShouldUnlink(Node node)
+ {
+ return (node == last || node.next != null);
+ }
+
+ internal override void Unlink(Node node)
+ {
+ Node p = head;
+ Node trail = null;
+ while (p != null)
+ {
+ if (p == node)
+ {
+ Node next = p.next;
+ if (trail == null)
+ {
+ head = next;
+ }
+ else
+ {
+ trail.next = next;
+ }
+ if (last == node)
+ {
+ last = trail;
+ }
+ break;
+ }
+ trail = p;
+ p = p.next;
+ }
+ }
+ }
+
+ /**
+ * LIFO queue to hold waiting puts/takes.
+ */
+ sealed class LifoWaitQueue : WaitQueue
+ {
+ private Node head;
+
+ internal override Node Enq(Object x)
+ {
+ return head = new Node(x, head);
+ }
+
+ internal override Node Deq()
+ {
+ Node p = head;
+ if (p != null)
+ {
+ head = p.next;
+ p.next = null;
+ }
+ return p;
+ }
+
+ internal override bool ShouldUnlink(Node node)
+ {
+ // Return false if already dequeued or is bottom node (in which
+ // case we might retain at most one garbage node)
+ return (node == head || node.next != null);
+ }
+
+ internal override void Unlink(Node node)
+ {
+ Node p = head;
+ Node trail = null;
+ while (p != null)
+ {
+ if (p == node)
+ {
+ Node next = p.next;
+ if (trail == null)
+ head = next;
+ else
+ trail.next = next;
+ break;
+ }
+ trail = p;
+ p = p.next;
+ }
+ }
+ }
+
+ /**
+ * Nodes each maintain an item and handle waits and signals for
+ * getting and setting it. The class extends
+ * AbstractQueuedSynchronizer to manage blocking, using AQS state
+ * 0 for waiting, 1 for ack, -1 for cancelled.
+ */
+ sealed internal class Node
+ {
+
+ /** Synchronization state value representing that node acked */
+ private const int ACK = 1;
+ /** Synchronization state value representing that node cancelled */
+ private const int CANCEL = -1;
+
+ internal int state = 0;
+
+ /** The item being transferred */
+ internal Object item;
+ /** Next node in wait queue */
+ internal Node next;
+
+ /** Creates a node with initial item */
+ internal Node(Object x)
+ {
+ item = x;
+ }
+
+ /** Creates a node with initial item and next */
+ internal Node(Object x, Node n)
+ {
+ item = x;
+ next = n;
+ }
+
+ /**
+ * Takes item and nulls out field (for sake of GC)
+ *
+ * PRE: lock owned
+ */
+ private Object Extract()
+ {
+ Object x = item;
+ item = null;
+ return x;
+ }
+
+ /**
+ * Tries to cancel on interrupt; if so rethrowing,
+ * else setting interrupt state
+ *
+ * PRE: lock owned
+ */
+ /*private void checkCancellationOnInterrupt(InterruptedException ie)
+ throws InterruptedException
+ {
+ if (state == 0) {
+ state = CANCEL;
+ notify();
+ throw ie;
+ }
+ Thread.currentThread().interrupt();
+ }*/
+
+ /**
+ * Fills in the slot created by the consumer and signal consumer to
+ * continue.
+ */
+ internal bool SetItem(Object x)
+ {
+ lock (this)
+ {
+ if (state != 0) return false;
+ item = x;
+ state = ACK;
+ Monitor.Pulse(this);
+ return true;
+ }
+ }
+
+ /**
+ * Removes item from slot created by producer and signal producer
+ * to continue.
+ */
+ internal Object GetItem()
+ {
+ if (state != 0) return null;
+ state = ACK;
+ Monitor.Pulse(this);
+ return Extract();
+ }
+
+ /**
+ * Waits for a consumer to take item placed by producer.
+ */
+ internal void WaitForTake() //throws InterruptedException {
+ {
+ while (state == 0)
+ {
+ Monitor.Wait(this);
+ }
+ }
+
+ /**
+ * Waits for a producer to put item placed by consumer.
+ */
+ internal object WaitForPut()
+ {
+ lock (this)
+ {
+ while (state == 0) Monitor.Wait(this);
+ }
+ return Extract();
+ }
+
+ private bool Attempt(long nanos)
+ {
+ if (state != 0) return true;
+ if (nanos <= 0) {
+ state = CANCEL;
+ Monitor.Pulse(this);
+ return false;
+ }
+
+ while (true)
+ {
+ Monitor.Wait(nanos);
+ //TimeUnit.NANOSECONDS.timedWait(this, nanos);
+ if (state != 0)
+ {
+ return true;
+ }
+ //nanos = deadline - Utils.nanoTime();
+ //if (nanos <= 0)
+ else
+ {
+ state = CANCEL;
+ Monitor.Pulse(this);
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Waits for a consumer to take item placed by producer or time out.
+ */
+ internal bool WaitForTake(long nanos)
+ {
+ return Attempt(nanos);
+ }
+
+ /**
+ * Waits for a producer to put item placed by consumer, or time out.
+ */
+ internal object WaitForPut(long nanos)
+ {
+ if (!Attempt(nanos))
+ {
+ return null;
+ }
+ else
+ {
+ return Extract();
+ }
+ }
+ }
+
+ public SynchronousQueue(bool strict)
+ {
+ // TODO !!!!
+ }
+
+ public override bool EnqueueNoThrow(object e)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void EnqueueBlocking(object e)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object DequeueBlocking()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override int RemainingCapacity
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQDataBlockDecoder.cs b/dotnet/Qpid.Common/Framing/AMQDataBlockDecoder.cs
new file mode 100644
index 0000000000..7867650e50
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQDataBlockDecoder.cs
@@ -0,0 +1,155 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Codec.Demux;
+
+namespace Apache.Qpid.Framing
+{
+ public class AMQDataBlockDecoder : IMessageDecoder
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(AMQDataBlockDecoder));
+
+ private Hashtable _supportedBodies = new Hashtable();
+
+ private bool _disabled = false;
+
+ public AMQDataBlockDecoder()
+ {
+ _supportedBodies[AMQMethodBody.TYPE] = AMQMethodBodyFactory.GetInstance();
+ _supportedBodies[ContentHeaderBody.TYPE] = ContentHeaderBodyFactory.GetInstance();
+ _supportedBodies[ContentBody.TYPE] = ContentBodyFactory.GetInstance();
+ _supportedBodies[HeartbeatBody.TYPE] = new HeartbeatBodyFactory();
+ }
+
+ public MessageDecoderResult Decodable(ByteBuffer input)
+ {
+ if (_disabled)
+ {
+ return MessageDecoderResult.NOT_OK;
+ }
+ // final +1 represents the command end which we know we must require even
+ // if there is an empty body
+ if (input.Remaining < 1)
+ {
+ return MessageDecoderResult.NEED_DATA;
+ }
+ byte type = input.GetByte();
+
+ // we have to check this isn't a protocol initiation frame here - we can't tell later on and we end up
+ // waiting for more data. This could be improved if MINA supported some kind of state awareness when decoding
+ if ((char)type == 'A')
+ {
+ _logger.Error("Received what appears to be a protocol initiation frame");
+ return MessageDecoderResult.NOT_OK;
+ }
+ // zero, channel, body size and end byte
+ if (input.Remaining < (1 + 2 + 4 + 1))
+ {
+ return MessageDecoderResult.NEED_DATA;
+ }
+
+ int channel = input.GetUInt16();
+ long bodySize = input.GetUInt32();
+
+ // bodySize can be zero
+ if (type <= 0 || channel < 0 || bodySize < 0)
+ {
+ _logger.Error(String.Format("Error decoding frame: Type={0}, Channel={1}, BodySize={2}", type, channel, bodySize));
+ return MessageDecoderResult.NOT_OK;
+ }
+
+ if (input.Remaining < (bodySize + 1))
+ {
+ return MessageDecoderResult.NEED_DATA;
+ }
+
+ if (IsSupportedFrameType(type))
+ {
+ if (_logger.IsDebugEnabled)
+ {
+ // we have read 7 bytes so far, so output 7 + bodysize + 1 (for end byte) to get complete data block size
+ // this logging statement is useful when looking at exactly what size of data is coming in/out
+ // the broker
+ _logger.Debug("Able to decode data block of size " + (bodySize + 8));
+ }
+ return MessageDecoderResult.OK;
+ }
+ else
+ {
+ return MessageDecoderResult.NOT_OK;
+ }
+ }
+
+ private bool IsSupportedFrameType(byte frameType)
+ {
+ bool result = _supportedBodies.ContainsKey(frameType);
+
+ if (!result)
+ {
+ _logger.Warn("AMQDataBlockDecoder does not handle frame type " + frameType);
+ }
+
+ return result;
+ }
+
+ protected Object CreateAndPopulateFrame(ByteBuffer input)
+ {
+ byte type = input.GetByte();
+ ushort channel = input.GetUInt16();
+ uint bodySize = input.GetUInt32();
+
+ IBodyFactory bodyFactory = (IBodyFactory)_supportedBodies[type];
+ if (bodyFactory == null)
+ {
+ throw new AMQFrameDecodingException("Unsupported body type: " + type);
+ }
+ AMQFrame frame = new AMQFrame();
+
+ frame.PopulateFromBuffer(input, channel, bodySize, bodyFactory);
+
+ byte marker = input.GetByte();
+ if (marker != 0xCE) {
+ throw new FormatException("marker is not 0xCE");
+ }
+ return frame;
+ }
+
+ public MessageDecoderResult Decode(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+
+ output.Write(CreateAndPopulateFrame(input));
+
+ return MessageDecoderResult.OK;
+ }
+
+ public bool Disabled
+ {
+ set
+ {
+ _disabled = value;
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQDataBlockEncoder.cs b/dotnet/Qpid.Common/Framing/AMQDataBlockEncoder.cs
new file mode 100644
index 0000000000..e2645c630e
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQDataBlockEncoder.cs
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Collections;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Codec.Demux;
+
+namespace Apache.Qpid.Framing
+{
+ public class AMQDataBlockEncoder : IMessageEncoder
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(AMQDataBlockEncoder));
+
+ private Hashtable _messageTypes;
+
+ public AMQDataBlockEncoder()
+ {
+ _messageTypes = new Hashtable();
+ _messageTypes[typeof (IEncodableAMQDataBlock)] = 1;
+ }
+
+
+ public Hashtable MessageTypes
+ {
+ get
+ {
+ return _messageTypes;
+ }
+ }
+
+ public void Encode(object message, IProtocolEncoderOutput output)
+ {
+ IDataBlock frame = (IDataBlock) message;
+ int frameSize = (int)frame.Size; // TODO: sort out signed/unsigned
+ ByteBuffer buffer = ByteBuffer.Allocate(frameSize);
+ frame.WritePayload(buffer);
+
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug("Encoded frame byte-buffer is '" + ByteBufferHexDumper.GetHexDump(buffer) + "'");
+ }
+ buffer.Flip();
+ output.Write(buffer);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQFrame.cs b/dotnet/Qpid.Common/Framing/AMQFrame.cs
new file mode 100644
index 0000000000..912be72d30
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQFrame.cs
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class AMQFrame : IDataBlock
+ {
+ private ushort _channel;
+
+ private IBody _bodyFrame;
+
+ public AMQFrame()
+ {
+ }
+
+ public AMQFrame(ushort channel, IBody bodyFrame)
+ {
+ _channel = channel;
+ _bodyFrame = bodyFrame;
+ }
+
+ public ushort Channel
+ {
+ get
+ {
+ return _channel;
+ }
+ set
+ {
+ _channel = value;
+ }
+ }
+
+ public IBody BodyFrame
+ {
+ get
+ {
+ return _bodyFrame;
+ }
+ set
+ {
+ _bodyFrame = value;
+ }
+ }
+
+ #region IDataBlock Members
+
+ public uint Size
+ {
+ get
+ {
+ return (uint) (1 + 2 + 4 + _bodyFrame.Size + 1);
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ buffer.Put(_bodyFrame.BodyType);
+ // TODO: how does channel get populated
+ buffer.Put(_channel);
+ buffer.Put(_bodyFrame.Size);
+ _bodyFrame.WritePayload(buffer);
+ buffer.Put((byte) 0xCE);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Populates the frame instance data from the supplied buffer.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="channel">The channel.</param>
+ /// <param name="bodySize">Size of the body in bytes</param>
+ /// <param name="bodyFactory">The body factory.</param>
+ /// <exception cref="AMQFrameDecodingException">Thrown if the buffer cannot be decoded</exception>
+ public void PopulateFromBuffer(ByteBuffer buffer, ushort channel, uint bodySize, IBodyFactory bodyFactory)
+ {
+ _channel = channel;
+ _bodyFrame = bodyFactory.CreateBody(buffer);
+ _bodyFrame.PopulateFromBuffer(buffer, bodySize);
+ }
+
+ public override string ToString()
+ {
+ return "Frame channelId: " + _channel + ", bodyFrame: " + _bodyFrame.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQFrameDecodingException.cs b/dotnet/Qpid.Common/Framing/AMQFrameDecodingException.cs
new file mode 100644
index 0000000000..cda8c84ecf
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQFrameDecodingException.cs
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+using log4net;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// Thrown when a frame cannot be decoded. This generally indicates a mismatch between the broker and the
+ /// client.
+ /// </summary>
+ [Serializable]
+ public class AMQFrameDecodingException : AMQException
+ {
+ public AMQFrameDecodingException(string message)
+ : base(message)
+ {
+ }
+
+ public AMQFrameDecodingException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public AMQFrameDecodingException(ILog logger, string message)
+ : base(logger, message)
+ {
+ }
+
+ public AMQFrameDecodingException(ILog logger, string message, Exception innerException)
+ : base(logger, message, innerException)
+ {
+ }
+
+ protected AMQFrameDecodingException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQMethodBody.cs b/dotnet/Qpid.Common/Framing/AMQMethodBody.cs
new file mode 100644
index 0000000000..a3c4337147
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQMethodBody.cs
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public abstract class AMQMethodBody : IBody
+ {
+ public const byte TYPE = 1;
+
+ protected abstract uint BodySize
+ {
+ get;
+ }
+
+ protected abstract ushort Clazz
+ {
+ get;
+ }
+
+ protected abstract ushort Method
+ {
+ get;
+ }
+
+ protected abstract void WriteMethodPayload(ByteBuffer buffer);
+
+ public byte BodyType
+ {
+ get
+ {
+ return TYPE;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return (uint) (2 + 2 + BodySize);
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ buffer.Put(Clazz);
+ buffer.Put(Method);
+ WriteMethodPayload(buffer);
+ }
+
+ /// <summary>
+ /// Populates the method body by decoding the specified buffer
+ /// </summary>
+ /// <param name="buffer">The buffer to decode.</param>
+ /// <exception cref="AMQFrameDecodingException">If the buffer cannot be decoded</exception>
+ protected abstract void PopulateMethodBodyFromBuffer(ByteBuffer buffer);
+
+ /// <summary>
+ /// Populates this instance from a buffer of data.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="size">The size.</param>
+ /// <exception cref="AMQFrameDecodingException">If the buffer contains data that cannot be decoded</exception>
+ public void PopulateFromBuffer(ByteBuffer buffer, uint size)
+ {
+ PopulateMethodBodyFromBuffer(buffer);
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0}{{ Class: {1} Method: {2} }}", GetType().Name, Clazz, Method);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQMethodBodyFactory.cs b/dotnet/Qpid.Common/Framing/AMQMethodBodyFactory.cs
new file mode 100644
index 0000000000..c1fd3f887a
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQMethodBodyFactory.cs
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class AMQMethodBodyFactory : IBodyFactory
+ {
+ private static readonly AMQMethodBodyFactory _instance = new AMQMethodBodyFactory();
+
+ public static AMQMethodBodyFactory GetInstance()
+ {
+ return _instance;
+ }
+
+ /// <summary>
+ /// Creates the body.
+ /// </summary>
+ /// <param name="inbuf">The ByteBuffer containing data from the network</param>
+ /// <returns></returns>
+ /// <exception>AMQFrameDecodingException</exception>
+ public IBody CreateBody(ByteBuffer inbuf)
+ {
+ return MethodBodyDecoderRegistry.Get(inbuf.GetUInt16(), inbuf.GetUInt16());
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQProtocolHeaderException.cs b/dotnet/Qpid.Common/Framing/AMQProtocolHeaderException.cs
new file mode 100644
index 0000000000..379e5d00ba
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQProtocolHeaderException.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Framing
+{
+ [Serializable]
+ public class AMQProtocolHeaderException : AMQException
+ {
+ public AMQProtocolHeaderException(string message) : base(message)
+ {
+ }
+
+ protected AMQProtocolHeaderException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQType.cs b/dotnet/Qpid.Common/Framing/AMQType.cs
new file mode 100644
index 0000000000..95da72b907
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQType.cs
@@ -0,0 +1,700 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// Base class for the Field Table Type system.
+ /// Ported over from the Java AMQType enumeration
+ /// </summary>
+ public abstract class AMQType
+ {
+ private byte _identifier;
+
+ /// <summary>
+ /// Type code identifier for this type
+ /// </summary>
+ public byte Identifier
+ {
+ get { return _identifier; }
+ }
+
+ protected AMQType(char identifier)
+ {
+ _identifier = (byte)identifier;
+ }
+
+ /// <summary>
+ /// Create a new <see cref="AMQTypedValue"/> instance
+ /// </summary>
+ /// <param name="value">Value to initialize with</param>
+ /// <returns>A new typed value instance</returns>
+ public AMQTypedValue AsTypedValue(object value)
+ {
+ return new AMQTypedValue(this, ToNativeValue(value));
+ }
+
+ /// <summary>
+ /// Write the specified value to the buffer using the encoding
+ /// specified for this type
+ /// </summary>
+ /// <param name="value">Value to write</param>
+ /// <param name="buffer">Buffer to write to</param>
+ public void WriteToBuffer(object value, ByteBuffer buffer)
+ {
+ buffer.Put(Identifier);
+ WriteValueImpl(value, buffer);
+ }
+
+ public override string ToString()
+ {
+ return ((Char) Identifier).ToString();
+ }
+
+ /// <summary>
+ /// Get the encoding size for the specified value in this type format
+ /// </summary>
+ /// <param name="value">Value to find encoded size for</param>
+ /// <returns>The encoded size</returns>
+ public abstract uint GetEncodingSize(object value);
+ /// <summary>
+ /// Convert the specified value to this type
+ /// </summary>
+ /// <param name="value">Value to convert</param>
+ /// <returns>The converted value</returns>
+ public abstract object ToNativeValue(object value);
+
+ /// <summary>
+ /// Read a value from the specified buffer using the encoding for
+ /// this type
+ /// </summary>
+ /// <param name="buffer">Buffer to read from</param>
+ /// <returns>The value read</returns>
+ public abstract object ReadValueFromBuffer(ByteBuffer buffer);
+
+ protected abstract void WriteValueImpl(Object value, ByteBuffer buffer);
+
+
+ #region Known Types
+ //
+ // Known Types
+ //
+
+ // long string is not defined in the proposed specification,
+ // and the 'S' discriminator is left for unsigned short (16-bit) values
+ public static readonly AMQType LONG_STRING = new AMQLongStringType();
+ public static readonly AMQType UINT32 = new AMQUInt32Type();
+ public static readonly AMQType DECIMAL = new AMQDecimalType();
+ public static readonly AMQType TIMESTAMP = new AMQTimeStampType();
+ public static readonly AMQType FIELD_TABLE = new AMQFieldTableType();
+ public static readonly AMQType VOID = new AMQVoidType();
+ public static readonly AMQType BINARY = new AMQBinaryType();
+ public static readonly AMQType ASCII_STRING = new AMQAsciiStringType();
+ public static readonly AMQType WIDE_STRING = new AMQWideStringType();
+ public static readonly AMQType BOOLEAN = new AMQBooleanType();
+ public static readonly AMQType ASCII_CHARACTER = new AMQAsciiCharType();
+ public static readonly AMQType BYTE = new AMQByteType();
+ public static readonly AMQType SBYTE = new AMQSByteType();
+ public static readonly AMQType INT16 = new AMQInt16Type();
+ public static readonly AMQType UINT16 = new AMQUInt16Type();
+ public static readonly AMQType INT32 = new AMQInt32Type();
+ public static readonly AMQType INT64 = new AMQInt64Type();
+ public static readonly AMQType UINT64 = new AMQUInt64Type();
+ public static readonly AMQType FLOAT = new AMQFloatType();
+ public static readonly AMQType DOUBLE = new AMQDoubleType();
+
+ #endregion // Known Types
+
+ #region Type Implementation
+ //
+ // Type Implementation
+ //
+
+ sealed class AMQLongStringType : AMQType
+ {
+ public AMQLongStringType() : base('S')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedLongStringLength((string) value);
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ if ( value == null )
+ throw new ArgumentNullException("value");
+ return value.ToString();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadLongString(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteLongStringBytes(buffer, (string) value);
+ }
+
+ }
+
+ sealed class AMQUInt32Type : AMQType
+ {
+ public AMQUInt32Type() : base('i')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.UnsignedIntegerLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToUInt32(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadUnsignedInteger(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteUnsignedInteger(buffer, (uint) value);
+ }
+
+ }
+
+ sealed class AMQDecimalType : AMQType
+ {
+ public AMQDecimalType() : base('D')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ sealed class AMQTimeStampType : AMQType
+ {
+ public AMQTimeStampType() : base('T')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ sealed class AMQFieldTableType : AMQType
+ {
+ public AMQFieldTableType() : base('F')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ sealed class AMQVoidType : AMQType
+ {
+ public AMQVoidType() : base('V')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return 0;
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ if ( value != null )
+ throw new FormatException(string.Format("Cannot convert {0} to VOID type", value));
+ return null;
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return null;
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ }
+ }
+
+ // Extended Types
+
+ sealed class AMQBinaryType : AMQType
+ {
+ public AMQBinaryType() : base('x')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedLongstrLength((byte[]) value);
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ if ( value is byte[] || value == null )
+ {
+ return value;
+ }
+ throw new ArgumentException("Value cannot be converted to byte[]");
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadLongstr(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteLongstr(buffer, (byte[])value);
+ }
+ }
+
+ sealed class AMQAsciiStringType : AMQType
+ {
+ public AMQAsciiStringType() : base('c')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedAsciiStringLength((string)value);
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ if ( value == null )
+ throw new ArgumentNullException("value");
+ return value.ToString();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadAsciiString(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteAsciiString(buffer, (string)value);
+ }
+ }
+
+ sealed class AMQWideStringType : AMQType
+ {
+ // todo: Change encoding to UTF16 (java code still uses default
+ // ascii encoding for wide strings
+ private static readonly Encoding ENCODING = Encoding.ASCII;
+
+ public AMQWideStringType()
+ : base('C')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedLongStringLength((string)value, ENCODING);
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ if ( value == null )
+ throw new ArgumentNullException("value");
+ return value.ToString();
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadLongString(buffer, ENCODING);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteLongStringBytes(buffer, (string)value, ENCODING);
+ }
+ }
+
+ sealed class AMQBooleanType : AMQType
+ {
+ public AMQBooleanType() : base('t')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedBooleanLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToBoolean(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadBoolean(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteBoolean(buffer, (bool)value);
+ }
+ }
+
+ sealed class AMQAsciiCharType : AMQType
+ {
+ public AMQAsciiCharType() : base('k')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedCharLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToChar(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadChar(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteChar(buffer, (char)value);
+ }
+ }
+
+ sealed class AMQByteType : AMQType
+ {
+ public AMQByteType() : base('B')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedByteLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToByte(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadByte(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteByte(buffer, (byte)value);
+ }
+ }
+
+ sealed class AMQSByteType : AMQType
+ {
+ public AMQSByteType()
+ : base('b')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedSByteLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToSByte(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadSByte(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteSByte(buffer, (sbyte)value);
+ }
+ }
+
+ sealed class AMQInt16Type : AMQType
+ {
+ public AMQInt16Type() : base('s')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedShortLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToInt16(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadShort(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteShort(buffer, (short)value);
+ }
+ }
+
+ sealed class AMQUInt16Type : AMQType
+ {
+ public AMQUInt16Type()
+ : base('S')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedUnsignedShortLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToUInt16(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadUnsignedShort(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteUnsignedShort(buffer, (ushort)value);
+ }
+ }
+
+ sealed class AMQInt32Type : AMQType
+ {
+ public AMQInt32Type() : base('I')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedIntegerLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToInt32(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadInteger(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteInteger(buffer, (int)value);
+ }
+ }
+
+ sealed class AMQInt64Type : AMQType
+ {
+ public AMQInt64Type() : base('l')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedLongLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToInt64(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadLong(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteLong(buffer, (long)value);
+ }
+ }
+
+ sealed class AMQUInt64Type : AMQType
+ {
+ public AMQUInt64Type()
+ : base('L')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedUnsignedLongLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToUInt64(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadUnsignedLong(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteUnsignedLong(buffer, (ulong)value);
+ }
+ }
+
+ sealed class AMQFloatType : AMQType
+ {
+ public AMQFloatType() : base('f')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedFloatLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToSingle(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadFloat(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteFloat(buffer, (float)value);
+ }
+ }
+
+ sealed class AMQDoubleType : AMQType
+ {
+ public AMQDoubleType() : base('d')
+ {
+ }
+
+ public override uint GetEncodingSize(object value)
+ {
+ return EncodingUtils.EncodedDoubleLength();
+ }
+
+ public override object ToNativeValue(object value)
+ {
+ return Convert.ToDouble(value);
+ }
+
+ public override object ReadValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.ReadDouble(buffer);
+ }
+
+ protected override void WriteValueImpl(object value, ByteBuffer buffer)
+ {
+ EncodingUtils.WriteDouble(buffer, (double)value);
+ }
+ }
+
+ #endregion // Type Implementation
+
+ } // class AMQType
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQTypeMap.cs b/dotnet/Qpid.Common/Framing/AMQTypeMap.cs
new file mode 100644
index 0000000000..8497c283f9
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQTypeMap.cs
@@ -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.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Framing
+{
+ public sealed class AMQTypeMap
+ {
+ private static Hashtable _reverseTypeMap;
+
+ private AMQTypeMap()
+ {
+ }
+
+ static AMQTypeMap()
+ {
+ _reverseTypeMap = Hashtable.Synchronized(new Hashtable());
+
+ Add(AMQType.LONG_STRING);
+ Add(AMQType.BOOLEAN);
+ Add(AMQType.BYTE);
+ Add(AMQType.SBYTE);
+ Add(AMQType.INT16);
+ // not supported for now as type code conflicts
+ // with LONG_STRING
+ //Add(AMQType.UINT16);
+ Add(AMQType.INT32);
+ Add(AMQType.UINT32);
+ Add(AMQType.INT64);
+ Add(AMQType.UINT64);
+ Add(AMQType.FLOAT);
+ Add(AMQType.DOUBLE);
+ Add(AMQType.DECIMAL);
+ Add(AMQType.BINARY);
+ Add(AMQType.ASCII_STRING);
+ Add(AMQType.WIDE_STRING);
+ Add(AMQType.ASCII_CHARACTER);
+ Add(AMQType.TIMESTAMP);
+ Add(AMQType.FIELD_TABLE);
+ Add(AMQType.VOID);
+ }
+
+ public static AMQType GetType(byte identifier)
+ {
+ AMQType type = (AMQType)_reverseTypeMap[identifier];
+ if ( type == null )
+ throw new ArgumentOutOfRangeException(string.Format("No such type code: {0:x}", identifier));
+ return type;
+ }
+
+ private static void Add(AMQType type)
+ {
+ _reverseTypeMap.Add(type.Identifier, type);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/AMQTypedValue.cs b/dotnet/Qpid.Common/Framing/AMQTypedValue.cs
new file mode 100644
index 0000000000..3d2e313fa6
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/AMQTypedValue.cs
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class AMQTypedValue
+ {
+ private readonly AMQType _type;
+ private readonly object _value;
+
+ public AMQType Type
+ {
+ get { return _type; }
+ }
+
+ public object Value
+ {
+ get { return _value; }
+ }
+
+ public uint EncodingLength
+ {
+ get { return _type.GetEncodingSize(_value); }
+ }
+
+ public AMQTypedValue(AMQType type, object value)
+ {
+ if ( type == null )
+ throw new ArgumentNullException("type");
+ _type = type;
+ _value = type.ToNativeValue(value);
+ }
+
+ public AMQTypedValue(AMQType type, ByteBuffer buffer)
+ {
+ _type = type;
+ _value = type.ReadValueFromBuffer(buffer);
+ }
+
+ public void WriteToBuffer(ByteBuffer buffer)
+ {
+ _type.WriteToBuffer(_value, buffer);
+ }
+
+ public static AMQTypedValue ReadFromBuffer(ByteBuffer buffer)
+ {
+ AMQType type = AMQTypeMap.GetType(buffer.GetByte());
+ return new AMQTypedValue(type, buffer);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}: {1}", Type, Value);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/BasicContentHeaderProperties.cs b/dotnet/Qpid.Common/Framing/BasicContentHeaderProperties.cs
new file mode 100644
index 0000000000..47db7b0887
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/BasicContentHeaderProperties.cs
@@ -0,0 +1,290 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Framing
+{
+ public class BasicContentHeaderProperties : IContentHeaderProperties
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(BasicContentHeaderProperties));
+
+ private string _contentType;
+ private string _encoding;
+ private FieldTable _headers;
+ private byte _deliveryMode;
+ private byte _priority;
+ private string _correlationId;
+ private long _expiration;
+ private string _replyTo;
+ private string _messageId;
+ private ulong _timestamp;
+ private string _type;
+ private string _userId;
+ private string _appId;
+ private string _clusterId;
+
+
+ #region Properties
+ //
+ // Properties
+ //
+
+ /// <summary>
+ /// The MIME Content Type
+ /// </summary>
+ public string ContentType
+ {
+ get { return _contentType; }
+ set { _contentType = value; }
+ }
+
+ /// <summary>
+ /// The MIME Content Encoding
+ /// </summary>
+ public string Encoding
+ {
+ get { return _encoding; }
+ set { _encoding = value; }
+ }
+
+ /// <summary>
+ /// Message headers
+ /// </summary>
+ public FieldTable Headers
+ {
+ get { return _headers; }
+ set { _headers = value; }
+ }
+
+ /// <summary>
+ /// Non-persistent (1) or persistent (2)
+ /// </summary>
+ public byte DeliveryMode
+ {
+ get { return _deliveryMode; }
+ set { _deliveryMode = value; }
+ }
+
+ /// <summary>
+ /// The message priority, 0 to 9
+ /// </summary>
+ public byte Priority
+ {
+ get { return _priority; }
+ set { _priority = value; }
+ }
+
+ /// <summary>
+ /// The application correlation identifier
+ /// </summary>
+ public string CorrelationId
+ {
+ get { return _correlationId; }
+ set { _correlationId = value; }
+ }
+
+ /// <summary>
+ /// Message expiration specification
+ /// </summary>
+ // TODO: Should be string according to spec
+ public long Expiration
+ {
+ get { return _expiration; }
+ set { _expiration = value; }
+ }
+
+ /// <summary>
+ /// The destination to reply to
+ /// </summary>
+ public string ReplyTo
+ {
+ get { return _replyTo; }
+ set { _replyTo = value; }
+ }
+
+ /// <summary>
+ /// The application message identifier
+ /// </summary>
+ public string MessageId
+ {
+ get { return _messageId; }
+ set { _messageId = value; }
+ }
+
+ /// <summary>
+ /// The message timestamp
+ /// </summary>
+ public ulong Timestamp
+ {
+ get { return _timestamp; }
+ set { _timestamp = value; }
+ }
+
+ /// <summary>
+ /// The message type name
+ /// </summary>
+ public string Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+
+ /// <summary>
+ /// The creating user id
+ /// </summary>
+ public string UserId
+ {
+ get { return _userId; }
+ set { _userId = value; }
+ }
+
+ /// <summary>
+ /// The creating application id
+ /// </summary>
+ public string AppId
+ {
+ get { return _appId; }
+ set { _appId = value; }
+ }
+
+ /// <summary>
+ /// Intra-cluster routing identifier
+ /// </summary>
+ public string ClusterId
+ {
+ get { return _clusterId; }
+ set { _clusterId = value; }
+ }
+
+ #endregion // Properties
+
+
+ public BasicContentHeaderProperties()
+ {
+ }
+
+ public uint PropertyListSize
+ {
+ get
+ {
+ return (uint)(EncodingUtils.EncodedShortStringLength(ContentType) +
+ EncodingUtils.EncodedShortStringLength(Encoding) +
+ EncodingUtils.EncodedFieldTableLength(Headers) +
+ 1 + 1 +
+ EncodingUtils.EncodedShortStringLength(CorrelationId) +
+ EncodingUtils.EncodedShortStringLength(ReplyTo) +
+ EncodingUtils.EncodedShortStringLength(String.Format("{0:D}", Expiration)) +
+ EncodingUtils.EncodedShortStringLength(MessageId) +
+ 8 +
+ EncodingUtils.EncodedShortStringLength(Type) +
+ EncodingUtils.EncodedShortStringLength(UserId) +
+ EncodingUtils.EncodedShortStringLength(AppId) +
+ EncodingUtils.EncodedShortStringLength(ClusterId));
+
+ }
+ }
+
+ public ushort PropertyFlags
+ {
+ get
+ {
+ int value = 0;
+
+ // for now we just blast in all properties
+ for ( int i = 0; i < 14; i++ )
+ {
+ value += (1 << (15 - i));
+ }
+ return (ushort)value;
+ }
+ }
+
+ public void WritePropertyListPayload(ByteBuffer buffer)
+ {
+ EncodingUtils.WriteShortStringBytes(buffer, ContentType);
+ EncodingUtils.WriteShortStringBytes(buffer, Encoding);
+ EncodingUtils.WriteFieldTableBytes(buffer, Headers);
+ buffer.Put(DeliveryMode);
+ buffer.Put(Priority);
+ EncodingUtils.WriteShortStringBytes(buffer, CorrelationId);
+ EncodingUtils.WriteShortStringBytes(buffer, ReplyTo);
+ EncodingUtils.WriteShortStringBytes(buffer, String.Format("{0:D}", Expiration));
+ EncodingUtils.WriteShortStringBytes(buffer, MessageId);
+ buffer.Put(Timestamp);
+ EncodingUtils.WriteShortStringBytes(buffer, Type);
+ EncodingUtils.WriteShortStringBytes(buffer, UserId);
+ EncodingUtils.WriteShortStringBytes(buffer, AppId);
+ EncodingUtils.WriteShortStringBytes(buffer, ClusterId);
+ }
+
+ public void PopulatePropertiesFromBuffer(ByteBuffer buffer, ushort propertyFlags)
+ {
+ _log.Debug("Property flags: " + propertyFlags);
+ if ( (propertyFlags & (1 << 15)) > 0 )
+ ContentType = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 14)) > 0 )
+ Encoding = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 13)) > 0 )
+ Headers = EncodingUtils.ReadFieldTable(buffer);
+ if ( (propertyFlags & (1 << 12)) > 0 )
+ DeliveryMode = buffer.GetByte();
+ if ( (propertyFlags & (1 << 11)) > 0 )
+ Priority = buffer.GetByte();
+ if ( (propertyFlags & (1 << 10)) > 0 )
+ CorrelationId = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 9)) > 0 )
+ ReplyTo = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 8)) > 0 )
+ Expiration = EncodingUtils.ReadLongAsShortString(buffer);
+ if ( (propertyFlags & (1 << 7)) > 0 )
+ MessageId = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 6)) > 0 )
+ Timestamp = buffer.GetUInt64();
+ if ( (propertyFlags & (1 << 5)) > 0 )
+ Type = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 4)) > 0 )
+ UserId = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 3)) > 0 )
+ AppId = EncodingUtils.ReadShortString(buffer);
+ if ( (propertyFlags & (1 << 2)) > 0 )
+ ClusterId = EncodingUtils.ReadShortString(buffer);
+ }
+
+ public void SetDeliveryMode(DeliveryMode deliveryMode)
+ {
+ if ( deliveryMode == Messaging.DeliveryMode.NonPersistent )
+ {
+ DeliveryMode = 1;
+ } else
+ {
+ DeliveryMode = 2;
+ }
+ }
+
+ public override string ToString()
+ {
+ return "Properties: " + ContentType + " " + Encoding + " " + Timestamp + " " + Type;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/CompositeAMQDataBlock.cs b/dotnet/Qpid.Common/Framing/CompositeAMQDataBlock.cs
new file mode 100644
index 0000000000..d2b7f606b2
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/CompositeAMQDataBlock.cs
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Text;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class CompositeAMQDataBlock : IDataBlock, IEncodableAMQDataBlock
+ {
+ private IDataBlock[] _blocks;
+
+ public CompositeAMQDataBlock(IDataBlock[] blocks)
+ {
+ _blocks = blocks;
+ }
+
+ public IDataBlock[] Blocks
+ {
+ get
+ {
+ return _blocks;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ uint frameSize = 0;
+ foreach (IDataBlock block in _blocks)
+ {
+ frameSize += block.Size;
+ }
+ return frameSize;
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ foreach (IDataBlock block in _blocks)
+ {
+ block.WritePayload(buffer);
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_blocks == null)
+ {
+ return "No blocks contained in composite frame";
+ }
+ else
+ {
+ StringBuilder buf = new StringBuilder(GetType().Name);
+ buf.Append("{");
+ //buf.Append("encodedBlock=").Append(_encodedBlock);
+ for (int i = 0; i < _blocks.Length; i++)
+ {
+ buf.Append(" ").Append(i).Append("=[").Append(_blocks[i].ToString()).Append("]");
+ }
+ buf.Append("}");
+ return buf.ToString();
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ContentBody.cs b/dotnet/Qpid.Common/Framing/ContentBody.cs
new file mode 100644
index 0000000000..7a2142985d
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ContentBody.cs
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class ContentBody : IBody
+ {
+ public const byte TYPE = 3;
+
+ private ByteBuffer _payload;
+
+ public ByteBuffer Payload
+ {
+ get { return _payload; }
+ }
+
+ public ContentBody()
+ {
+ }
+ public ContentBody(ByteBuffer payload)
+ {
+ PopulateFromBuffer(payload, (uint)payload.Remaining);
+ }
+ public ContentBody(ByteBuffer payload, uint length)
+ {
+ PopulateFromBuffer(payload, length);
+ }
+
+ #region IBody Members
+
+ public byte BodyType
+ {
+ get
+ {
+ return TYPE;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return (ushort)(Payload == null ? 0 : Payload.Remaining);
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ if (Payload != null)
+ {
+ buffer.Put(Payload);
+ Payload.Rewind();
+ }
+ }
+
+ public void PopulateFromBuffer(ByteBuffer buffer, uint size)
+ {
+ if (size > 0)
+ {
+ _payload = buffer.Slice();
+ _payload.Limit = (int)size;
+ buffer.Skip((int)size);
+ }
+ }
+
+ #endregion
+
+ public static AMQFrame CreateAMQFrame(ushort channelId, ContentBody body)
+ {
+ AMQFrame frame = new AMQFrame();
+ frame.Channel = channelId;
+ frame.BodyFrame = body;
+ return frame;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("ContentBody [ Size: {0} ]", Size);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ContentBodyFactory.cs b/dotnet/Qpid.Common/Framing/ContentBodyFactory.cs
new file mode 100644
index 0000000000..400b2aec08
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ContentBodyFactory.cs
@@ -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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class ContentBodyFactory : IBodyFactory
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(ContentBodyFactory));
+
+ private static readonly ContentBodyFactory _instance = new ContentBodyFactory();
+
+ public static ContentBodyFactory GetInstance()
+ {
+ return _instance;
+ }
+
+ private ContentBodyFactory()
+ {
+ _log.Debug("Creating content body factory");
+ }
+
+ /// <summary>
+ /// Creates the body.
+ /// </summary>
+ /// <param name="inbuf">The ByteBuffer containing data from the network</param>
+ /// <returns></returns>
+ /// <exception>AMQFrameDecodingException</exception>
+ public IBody CreateBody(ByteBuffer inbuf)
+ {
+ return new ContentBody();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ContentHeaderBody.cs b/dotnet/Qpid.Common/Framing/ContentHeaderBody.cs
new file mode 100644
index 0000000000..82889c23c8
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ContentHeaderBody.cs
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class ContentHeaderBody : IBody
+ {
+ public static readonly byte TYPE = 2;
+
+ public ushort ClassId;
+
+ public ushort Weight;
+
+ public ulong BodySize;
+
+ /** must never be null */
+ public IContentHeaderProperties Properties;
+
+ public ContentHeaderBody()
+ {
+ }
+
+ public ContentHeaderBody(IContentHeaderProperties props, ushort classId)
+ {
+ Properties = props;
+ ClassId = classId;
+ }
+
+ public ContentHeaderBody(ushort classId, ushort weight, IContentHeaderProperties props, uint bodySize)
+ : this(props, classId)
+ {
+ Weight = weight;
+ BodySize = bodySize;
+ }
+
+ #region IBody Members
+
+ public byte BodyType
+ {
+ get
+ {
+ return TYPE;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return (2 + 2 + 8 + 2 + Properties.PropertyListSize);
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ buffer.Put(ClassId);
+ buffer.Put(Weight);
+ buffer.Put(BodySize);
+ buffer.Put(Properties.PropertyFlags);
+ Properties.WritePropertyListPayload(buffer);
+ }
+
+ public void PopulateFromBuffer(ByteBuffer buffer, uint size)
+ {
+ ClassId = buffer.GetUInt16();
+ Weight = buffer.GetUInt16();
+ BodySize = buffer.GetUInt64();
+ ushort propertyFlags = buffer.GetUInt16();
+ ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.GetInstance();
+ Properties = factory.CreateContentHeaderProperties(ClassId, propertyFlags, buffer);
+ }
+
+ #endregion
+
+ public static AMQFrame CreateAMQFrame(ushort channelId, ushort classId, ushort weight, BasicContentHeaderProperties properties,
+ uint bodySize)
+ {
+ AMQFrame frame = new AMQFrame();
+ frame.Channel = channelId;
+ frame.BodyFrame = new ContentHeaderBody(classId, weight, properties, bodySize);
+ return frame;
+ }
+
+ public static AMQFrame CreateAMQFrame(ushort channelId, ContentHeaderBody body)
+ {
+ AMQFrame frame = new AMQFrame();
+ frame.Channel = channelId;
+ frame.BodyFrame = body;
+ return frame;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("ContentHeaderBody: ClassId {0}, Weight {1}, BodySize {2}, Properties {3}", ClassId, Weight,
+ BodySize, Properties);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ContentHeaderBodyFactory.cs b/dotnet/Qpid.Common/Framing/ContentHeaderBodyFactory.cs
new file mode 100644
index 0000000000..c95a10871d
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ContentHeaderBodyFactory.cs
@@ -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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class ContentHeaderBodyFactory : IBodyFactory
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(ContentHeaderBodyFactory));
+
+ private static readonly ContentHeaderBodyFactory _instance = new ContentHeaderBodyFactory();
+
+ public static ContentHeaderBodyFactory GetInstance()
+ {
+ return _instance;
+ }
+
+ private ContentHeaderBodyFactory()
+ {
+ _log.Debug("Creating content header body factory");
+ }
+
+ #region IBodyFactory Members
+
+ public IBody CreateBody(ByteBuffer inbuf)
+ {
+ // all content headers are the same - it is only the properties that differ.
+ // the content header body further delegates construction of properties
+ return new ContentHeaderBody();
+ }
+
+ #endregion
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ContentHeaderPropertiesFactory.cs b/dotnet/Qpid.Common/Framing/ContentHeaderPropertiesFactory.cs
new file mode 100644
index 0000000000..bac5d10fd4
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ContentHeaderPropertiesFactory.cs
@@ -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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class ContentHeaderPropertiesFactory
+ {
+
+ private static readonly ContentHeaderPropertiesFactory _instance = new ContentHeaderPropertiesFactory();
+
+ public static ContentHeaderPropertiesFactory GetInstance()
+ {
+ return _instance;
+ }
+
+ private ContentHeaderPropertiesFactory()
+ {
+ }
+
+ /// <summary>
+ /// Creates the content header properties from a buffer.
+ /// </summary>
+ /// <param name="classId">The class id.</param>
+ /// <param name="propertyFlags">The property flags.</param>
+ /// <param name="buffer">The buffer.</param>
+ /// <returns>a populated properties structure</returns>
+ /// <exception cref="AMQFrameDecodingException">if the buffer cannot be decoded</exception>
+ public IContentHeaderProperties CreateContentHeaderProperties(ushort classId, ushort propertyFlags,
+ ByteBuffer buffer)
+ {
+ IContentHeaderProperties properties;
+ switch (classId)
+ {
+ case 60:
+ properties = new BasicContentHeaderProperties();
+ break;
+ default:
+ throw new AMQFrameDecodingException("Unsupport content header class id: " + classId);
+ }
+ properties.PopulatePropertiesFromBuffer(buffer, propertyFlags);
+ return properties;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/EncodingUtils.cs b/dotnet/Qpid.Common/Framing/EncodingUtils.cs
new file mode 100644
index 0000000000..4d424656f9
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/EncodingUtils.cs
@@ -0,0 +1,460 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Globalization;
+using System.Text;
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class EncodingUtils
+ {
+ private static readonly Encoding DEFAULT_ENCODER = Encoding.ASCII;
+
+ // SHORT STRING
+ public static ushort EncodedShortStringLength(string s)
+ {
+ if ( s == null )
+ {
+ return 1;
+ } else
+ {
+ return (ushort)(1 + s.Length);
+ }
+ }
+ public static void WriteShortStringBytes(ByteBuffer buffer, string s)
+ {
+ if ( s != null )
+ {
+ //try
+ //{
+ //final byte[] encodedString = s.getBytes(STRING_ENCODING);
+ byte[] encodedString;
+ lock ( DEFAULT_ENCODER )
+ {
+ encodedString = DEFAULT_ENCODER.GetBytes(s);
+ }
+ // TODO: check length fits in an unsigned byte
+ buffer.Put((byte)encodedString.Length);
+ buffer.Put(encodedString);
+
+ } else
+ {
+ // really writing out unsigned byte
+ buffer.Put((byte)0);
+ }
+ }
+
+ // ASCII STRINGS
+ public static uint EncodedAsciiStringLength(string s)
+ {
+ // TODO: move this to 2-byte length once the proposed encodings
+ // have been approved. Also, validate length!
+ if ( s == null )
+ return 4;
+ else
+ return (uint) (4 + s.Length);
+ }
+ public static string ReadAsciiString(ByteBuffer buffer)
+ {
+ return ReadLongString(buffer, DEFAULT_ENCODER);
+ }
+ public static void WriteAsciiString(ByteBuffer buffer, string s)
+ {
+ WriteLongStringBytes(buffer, s, DEFAULT_ENCODER);
+ }
+
+ // LONG STRING
+ public static uint EncodedLongStringLength(string s)
+ {
+ return EncodedLongStringLength(s, DEFAULT_ENCODER);
+ }
+
+ public static uint EncodedLongStringLength(string s, Encoding encoding)
+ {
+ if ( s == null )
+ {
+ return 4;
+ } else
+ {
+ return (uint)(4 + encoding.GetByteCount(s));
+ }
+ }
+ public static string ReadLongString(ByteBuffer buffer)
+ {
+ return ReadLongString(buffer, DEFAULT_ENCODER);
+ }
+ public static string ReadLongString(ByteBuffer buffer, Encoding encoding)
+ {
+ uint length = buffer.GetUInt32();
+ if ( length == 0 )
+ {
+ return null;
+ } else
+ {
+ byte[] data = new byte[length];
+ buffer.GetBytes(data);
+ lock ( encoding )
+ {
+ return encoding.GetString(data);
+ }
+ }
+ }
+ public static void WriteLongStringBytes(ByteBuffer buffer, string s)
+ {
+ WriteLongStringBytes(buffer, s, DEFAULT_ENCODER);
+ }
+
+ public static void WriteLongStringBytes(ByteBuffer buffer, string s, Encoding encoding)
+ {
+ if ( !(s == null || s.Length <= 0xFFFE) )
+ {
+ throw new ArgumentException("String too long");
+ }
+ if ( s != null )
+ {
+ lock ( encoding )
+ {
+ byte[] encodedString = encoding.GetBytes(s);
+ buffer.Put((uint)encodedString.Length);
+ buffer.Put(encodedString);
+ }
+ } else
+ {
+ buffer.Put((uint)0);
+ }
+ }
+
+ // BINARY
+ public static uint EncodedLongstrLength(byte[] bytes)
+ {
+ if ( bytes == null )
+ {
+ return 4;
+ } else
+ {
+ return (uint)(4 + bytes.Length);
+ }
+ }
+ public static byte[] ReadLongstr(ByteBuffer buffer)
+ {
+ uint length = buffer.GetUInt32();
+ if ( length == 0 )
+ {
+ return null;
+ } else
+ {
+ byte[] result = new byte[length];
+ buffer.GetBytes(result);
+ return result;
+ }
+ }
+ public static void WriteLongstr(ByteBuffer buffer, byte[] data)
+ {
+ if ( data != null )
+ {
+ buffer.Put((uint)data.Length);
+ buffer.Put(data);
+ } else
+ {
+ buffer.Put((uint)0);
+ }
+ }
+
+ // BOOLEANS
+ public static bool[] ReadBooleans(ByteBuffer buffer)
+ {
+ byte packedValue = buffer.GetByte();
+ bool[] result = new bool[8];
+
+ for ( int i = 0; i < 8; i++ )
+ {
+ result[i] = ((packedValue & (1 << i)) != 0);
+ }
+ return result;
+ }
+ public static void WriteBooleans(ByteBuffer buffer, bool[] values)
+ {
+ byte packedValue = 0;
+ for ( int i = 0; i < values.Length; i++ )
+ {
+ if ( values[i] )
+ {
+ packedValue = (byte)(packedValue | (1 << i));
+ }
+ }
+
+ buffer.Put(packedValue);
+ }
+
+ // FIELD TABLES
+ public static uint EncodedFieldTableLength(FieldTable table)
+ {
+ if ( table == null )
+ {
+ // size is encoded as 4 octets
+ return 4;
+ } else
+ {
+ // size of the table plus 4 octets for the size
+ return table.EncodedSize + 4;
+ }
+ }
+ /// <summary>
+ /// Reads the field table using the data in the specified buffer
+ /// </summary>
+ /// <param name="buffer">The buffer to read from.</param>
+ /// <returns>a populated field table</returns>
+ /// <exception cref="AMQFrameDecodingException">if the buffer does not contain a decodable field table</exception>
+ public static FieldTable ReadFieldTable(ByteBuffer buffer)
+ {
+ uint length = buffer.GetUInt32();
+ if ( length == 0 )
+ {
+ return null;
+ } else
+ {
+ return new FieldTable(buffer, length);
+ }
+ }
+ public static void WriteFieldTableBytes(ByteBuffer buffer, FieldTable table)
+ {
+ if ( table != null )
+ {
+ table.WriteToBuffer(buffer);
+ } else
+ {
+ buffer.Put((uint)0);
+ }
+ }
+
+
+ /// <summary>
+ /// Read a short string from the buffer
+ /// </summary>
+ /// <param name="buffer">The buffer to read from.</param>
+ /// <returns>a string</returns>
+ /// <exception cref="AMQFrameDecodingException">if the buffer does not contain a decodable short string</exception>
+ public static string ReadShortString(ByteBuffer buffer)
+ {
+ byte length = buffer.GetByte();
+ if ( length == 0 )
+ {
+ return null;
+ } else
+ {
+ byte[] data = new byte[length];
+ buffer.GetBytes(data);
+
+ lock ( DEFAULT_ENCODER )
+ {
+ return DEFAULT_ENCODER.GetString(data);
+ }
+ }
+ }
+
+
+
+ // BOOLEAN
+ public static uint EncodedBooleanLength()
+ {
+ return 1;
+ }
+ public static bool ReadBoolean(ByteBuffer buffer)
+ {
+ byte packedValue = buffer.GetByte();
+ return (packedValue == 1);
+ }
+ public static void WriteBoolean(ByteBuffer buffer, bool value)
+ {
+ buffer.Put((byte)(value ? 1 : 0));
+ }
+
+
+ // CHAR
+ public static uint EncodedCharLength()
+ {
+ return EncodedByteLength();
+ }
+ public static char ReadChar(ByteBuffer buffer)
+ {
+ return (char)buffer.GetByte();
+ }
+ public static void WriteChar(ByteBuffer buffer, char value)
+ {
+ buffer.Put((byte)value);
+ }
+
+ // BYTE
+ public static uint EncodedByteLength()
+ {
+ return 1;
+ }
+ public static byte ReadByte(ByteBuffer buffer)
+ {
+ return buffer.GetByte();
+ }
+ public static void WriteByte(ByteBuffer buffer, byte value)
+ {
+ buffer.Put(value);
+ }
+
+ // SBYTE
+ public static uint EncodedSByteLength()
+ {
+ return 1;
+ }
+ public static sbyte ReadSByte(ByteBuffer buffer)
+ {
+ return buffer.GetSByte();
+ }
+ public static void WriteSByte(ByteBuffer buffer, sbyte value)
+ {
+ buffer.Put(value);
+ }
+
+ // INT16
+ public static uint EncodedShortLength()
+ {
+ return 2;
+ }
+
+ public static short ReadShort(ByteBuffer buffer)
+ {
+ return buffer.GetInt16();
+ }
+ public static void WriteShort(ByteBuffer buffer, short value)
+ {
+ buffer.Put(value);
+ }
+
+ // UINT16
+ public static uint EncodedUnsignedShortLength()
+ {
+ return 2;
+ }
+
+ public static ushort ReadUnsignedShort(ByteBuffer buffer)
+ {
+ return buffer.GetUInt16();
+ }
+ public static void WriteUnsignedShort(ByteBuffer buffer, ushort value)
+ {
+ buffer.Put(value);
+ }
+
+
+ // INT32
+ public static uint EncodedIntegerLength()
+ {
+ return 4;
+ }
+ public static int ReadInteger(ByteBuffer buffer)
+ {
+ return buffer.GetInt32();
+ }
+ public static void WriteInteger(ByteBuffer buffer, int value)
+ {
+ buffer.Put(value);
+ }
+
+ // UINT32
+ public static uint UnsignedIntegerLength()
+ {
+ return 4;
+ }
+ public static void WriteUnsignedInteger(ByteBuffer buffer, uint value)
+ {
+ buffer.Put(value);
+ }
+ public static uint ReadUnsignedInteger(ByteBuffer buffer)
+ {
+ return buffer.GetUInt32();
+ }
+
+ // INT64
+ public static uint EncodedUnsignedLongLength()
+ {
+ return 8;
+ }
+ public static ulong ReadUnsignedLong(ByteBuffer buffer)
+ {
+ return buffer.GetUInt64();
+ }
+ public static void WriteUnsignedLong(ByteBuffer buffer, ulong value)
+ {
+ buffer.Put(value);
+ }
+
+ // UINT64
+ public static uint EncodedLongLength()
+ {
+ return 8;
+ }
+ public static long ReadLong(ByteBuffer buffer)
+ {
+ return buffer.GetInt64();
+ }
+ public static void WriteLong(ByteBuffer buffer, long value)
+ {
+ buffer.Put(value);
+ }
+
+ // FLOAT
+ public static uint EncodedFloatLength()
+ {
+ return 4;
+ }
+ public static void WriteFloat(ByteBuffer buffer, float value)
+ {
+ buffer.Put(value);
+ }
+ public static float ReadFloat(ByteBuffer buffer)
+ {
+ return buffer.GetFloat();
+ }
+
+ // DOUBLE
+ public static uint EncodedDoubleLength()
+ {
+ return 8;
+ }
+ public static void WriteDouble(ByteBuffer buffer, double value)
+ {
+ buffer.Put(value);
+ }
+ public static double ReadDouble(ByteBuffer buffer)
+ {
+ return buffer.GetDouble();
+ }
+
+ // OTHER
+ public static long ReadLongAsShortString(ByteBuffer buffer)
+ {
+ string value = ReadShortString(buffer);
+ if ( value == null || value.Length == 0 )
+ return 0L;
+ return Convert.ToInt64(value, CultureInfo.InvariantCulture);
+ }
+
+ }
+
+}
diff --git a/dotnet/Qpid.Common/Framing/FieldTable.cs b/dotnet/Qpid.Common/Framing/FieldTable.cs
new file mode 100644
index 0000000000..6567bf58ab
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/FieldTable.cs
@@ -0,0 +1,633 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Collections;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Framing
+{
+ public class FieldTable : IFieldTable, IEnumerable
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(FieldTable));
+
+ IDictionary _properties;
+ private ByteBuffer _encodedForm;
+ private object _syncLock;
+ private uint _encodedSize;
+
+ public FieldTable()
+ {
+ _syncLock = new object();
+ }
+
+ /// <summary>
+ /// Construct a new field table.
+ /// </summary>
+ /// <param name="buffer">the buffer from which to read data. The length byte must be read already</param>
+ /// <param name="length">the length of the field table. Must be > 0.</param>
+ public FieldTable(ByteBuffer buffer, uint length) : this()
+ {
+ _encodedForm = buffer.Slice();
+ _encodedForm.Limit = (int)length;
+ _encodedSize = length;
+ buffer.Skip((int)length);
+ }
+
+ /// <summary>
+ /// The set of all property names
+ /// </summary>
+ public ICollection Keys
+ {
+ get
+ {
+ InitMapIfNecessary();
+ return _properties.Keys;
+ }
+ }
+
+ /// <summary>
+ /// Calculated size of this field table once encoded
+ /// </summary>
+ public uint EncodedSize
+ {
+ get { return _encodedSize; }
+ }
+
+ /// <summary>
+ /// Number of properties in the field table
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ InitMapIfNecessary();
+ return _properties.Count;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the specified property.
+ /// </summary>
+ /// <param name="key">Property name</param>
+ /// <returns>The specified property value</returns>
+ public object this[string key]
+ {
+ get { return GetObject(key); }
+ set { SetObject(key, value); }
+ }
+
+ #region Typed Setters and Getters
+ //
+ // Typed Setters and Getters
+ //
+ public bool GetBoolean(string key)
+ {
+ return (bool)this[key];
+ }
+ public void SetBoolean(string key, bool value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.BOOLEAN.AsTypedValue(value));
+ }
+ public byte GetByte(string key)
+ {
+ return (byte)this[key];
+ }
+ public void SetByte(string key, byte value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.BYTE.AsTypedValue(value));
+ }
+ public sbyte GetSByte(string key)
+ {
+ return (sbyte)this[key];
+ }
+ public void SetSByte(string key, sbyte value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.SBYTE.AsTypedValue(value));
+ }
+ public short GetInt16(string key)
+ {
+ return (short)this[key];
+ }
+ public void SetInt16(string key, short value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.INT16.AsTypedValue(value));
+ }
+ public int GetInt32(string key)
+ {
+ return (int)this[key];
+ }
+ public void SetInt32(string key, int value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.INT32.AsTypedValue(value));
+ }
+ public long GetInt64(string key)
+ {
+ return (long)this[key];
+ }
+ public void SetInt64(string key, long value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.INT64.AsTypedValue(value));
+ }
+ public char GetChar(string key)
+ {
+ return (char)this[key];
+ }
+ public void SetChar(string key, char value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.ASCII_CHARACTER.AsTypedValue(value));
+ }
+ public float GetFloat(string key)
+ {
+ return (float)this[key];
+ }
+ public void SetFloat(string key, float value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.FLOAT.AsTypedValue(value));
+ }
+ public double GetDouble(string key)
+ {
+ return (double)this[key];
+ }
+ public void SetDouble(string key, double value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.DOUBLE.AsTypedValue(value));
+ }
+ public decimal GetDecimal(string key)
+ {
+ return (decimal)this[key];
+ }
+ public void SetDecimal(string key, decimal value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.DECIMAL.AsTypedValue(value));
+ }
+ public string GetString(string key)
+ {
+ return (string)this[key];
+ }
+ public void SetString(string key, string value)
+ {
+ CheckPropertyName(key);
+ if ( value == null )
+ SetProperty(key, AMQType.VOID.AsTypedValue(null));
+ else
+ SetProperty(key, AMQType.LONG_STRING.AsTypedValue(value));
+ }
+ public byte[] GetBytes(string key)
+ {
+ return (byte[])this[key];
+ }
+ public void SetBytes(string key, byte[] value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.BINARY.AsTypedValue(value));
+ }
+ public ushort GetUInt16(string key)
+ {
+ return (ushort)this[key];
+ }
+ public void SetUInt16(string key, ushort value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.UINT16.AsTypedValue(value));
+ }
+ public uint GetUInt32(string key)
+ {
+ return (uint)this[key];
+ }
+ public void SetUInt32(string key, uint value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.UINT32.AsTypedValue(value));
+ }
+ public ulong GetUInt64(string key)
+ {
+ return (ulong)this[key];
+ }
+ public void SetUInt64(string key, ulong value)
+ {
+ CheckPropertyName(key);
+ SetProperty(key, AMQType.UINT64.AsTypedValue(value));
+ }
+
+ #endregion // Typed Setters and Getters
+
+ #region Public Methods
+ //
+ // Public Methods
+ //
+
+ /// <summary>
+ /// Removes the property with the specified name
+ /// </summary>
+ /// <param name="key">The name of the property to remove</param>
+ /// <returns>The previous value of the property or null</returns>
+ public AMQTypedValue RemoveKey(string key)
+ {
+ InitMapIfNecessary();
+ _encodedForm = null;
+ AMQTypedValue value = (AMQTypedValue)_properties[key];
+ if ( value != null )
+ {
+ _properties.Remove(key);
+ _encodedSize -= EncodingUtils.EncodedShortStringLength(key);
+ _encodedSize--;
+ _encodedSize -= value.EncodingLength;
+
+ }
+ return value;
+ }
+
+
+ /// <summary>
+ /// Remove the property with the specified name
+ /// </summary>
+ /// <param name="key">The name of the property to remove</param>
+ public void Remove(string key)
+ {
+ RemoveKey(key);
+ }
+
+ /// <summary>
+ /// Remove all properties from the table
+ /// </summary>
+ public void Clear()
+ {
+ InitMapIfNecessary();
+ _encodedForm = null;
+ _properties.Clear();
+ _encodedSize = 0;
+ }
+
+ /// <summary>
+ /// Adds all the items from one field table in this one. Will overwrite any items in the current table
+ /// with the same key.
+ /// </summary>
+ /// <param name="ft">the source field table</param>
+ public void AddAll(IFieldTable ft)
+ {
+ foreach ( DictionaryEntry dictionaryEntry in ft )
+ {
+ this[(string)dictionaryEntry.Key] = dictionaryEntry.Value;
+ }
+ }
+
+ /// <summary>
+ /// Get a enumerator over the internal property set.
+ /// Notice the enumerator will DictionaryEntry objects with
+ /// a string as the Key and an <see cref="AMQTypedValue"/> instance as the value
+ /// </summary>
+ /// <returns>The enumerator object</returns>
+ public IEnumerator GetEnumerator()
+ {
+ InitMapIfNecessary();
+ return _properties.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Indicates if a property with the given name exists
+ /// </summary>
+ /// <param name="s">Property name to check</param>
+ /// <returns>True if the property exists</returns>
+ public bool Contains(string s)
+ {
+ InitMapIfNecessary();
+ return _properties.Contains(s);
+ }
+
+ /// <summary>
+ /// Returns a dictionary mapping Property Names to the corresponding
+ /// <see cref="AMQTypedValue"/> value
+ /// </summary>
+ /// <returns>The internal dictionary</returns>
+ public IDictionary AsDictionary()
+ {
+ InitMapIfNecessary();
+ return _properties;
+ }
+
+ /// <summary>
+ /// Returns a string representation of this field table
+ /// </summary>
+ /// <returns>A string</returns>
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder("FieldTable {");
+
+ bool first = true;
+ InitMapIfNecessary();
+ foreach ( DictionaryEntry entry in _properties )
+ {
+ if ( !first )
+ {
+ sb.Append(", ");
+ }
+ first = false;
+ sb.Append(entry.Key).Append(" => ").Append(entry.Value);
+ }
+
+ sb.Append("}");
+ return sb.ToString();
+ }
+
+ /// <summary>
+ /// Serializes this instance to the specified <see cref="ByteBuffer"/>.
+ /// </summary>
+ /// <param name="buffer">The buffer to write to</param>
+ public void WriteToBuffer(ByteBuffer buffer)
+ {
+ if ( _log.IsDebugEnabled )
+ {
+ _log.Debug("FieldTable::writeToBuffer: Writing encoded length of " + EncodedSize + "...");
+ }
+
+ EncodingUtils.WriteUnsignedInteger(buffer, EncodedSize);
+ WritePayload(buffer);
+ }
+
+ /// <summary>
+ /// Returns a byte array with the serialized representation
+ /// of this field table
+ /// </summary>
+ /// <returns>An array of bytes</returns>
+ public byte[] GetDataAsBytes()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate((int)_encodedSize);
+ WritePayload(buffer);
+ byte[] result = new byte[_encodedSize];
+ buffer.Flip();
+ buffer.GetBytes(result);
+ //buffer.Release();
+ return result;
+ }
+
+ #endregion // Public Methods
+
+ #region Private Methods
+ //
+ // Private Methods
+ //
+
+ private static void CheckPropertyName(string propertyName)
+ {
+ if ( propertyName == null || propertyName.Length == 0 )
+ throw new ArgumentNullException("propertyName");
+ CheckIdentifierFormat(propertyName);
+ }
+
+ private static void CheckIdentifierFormat(string propertyName)
+ {
+ // AMQP Spec: 4.2.5.5 Field Tables
+ // Guidelines for implementers:
+ // * Field names MUST start with a letter, '$' or '#' and may continue with
+ // letters, '$' or '#', digits, or underlines, to a maximum length of 128
+ // characters.
+ // * The server SHOULD validate field names and upon receiving an invalid
+ // field name, it SHOULD signal a connection exception with reply code
+ // 503 (syntax error). Conformance test: amq_wlp_table_01.
+ // * A peer MUST handle duplicate fields by using only the first instance.
+
+
+ // AMQP length limit
+ if ( propertyName.Length > 128 )
+ {
+ throw new ArgumentException("AMQP limits property names to 128 characters");
+ }
+
+ // AMQ start character
+ if ( !(Char.IsLetter(propertyName[0])
+ || propertyName[0] == '$'
+ || propertyName[0] == '#'
+ || propertyName[0] == '_' ) )// Not official AMQP added for JMS.
+ {
+ throw new ArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character");
+ }
+ }
+
+ private object GetObject(string key)
+ {
+ AMQTypedValue value = GetProperty(key);
+ return value != null ? value.Value : null;
+ }
+
+ private void SetObject(string key, object value)
+ {
+ if ( value is bool )
+ {
+ SetBoolean(key, (bool)value);
+ } else if ( value is byte )
+ {
+ SetByte(key, (byte)value);
+ } else if ( value is sbyte )
+ {
+ SetSByte(key, (sbyte)value);
+ } else if ( value is short )
+ {
+ SetInt16(key, (short)value);
+ } else if ( value is ushort )
+ {
+ SetUInt16(key, (ushort)value);
+ } else if ( value is int )
+ {
+ SetInt32(key, (int) value);
+ } else if ( value is uint )
+ {
+ SetUInt32(key, (uint)value);
+ } else if ( value is long )
+ {
+ SetInt64(key, (long) value);
+ } else if ( value is ulong )
+ {
+ SetUInt64(key, (ulong)value);
+ } else if ( value is char )
+ {
+ SetChar(key, (char) value);
+ } else if ( value is float )
+ {
+ SetFloat(key, (float) value);
+ } else if ( value is double )
+ {
+ SetDouble(key, (double) value);
+ } else if ( value is decimal )
+ {
+ SetDecimal(key, (decimal) value);
+ } else if ( value is string )
+ {
+ SetString(key, (string) value);
+ } else if ( value is byte[] )
+ {
+ SetBytes(key, (byte[])value);
+ } else
+ {
+ throw new ArgumentException("Data type not supported yet");
+ }
+ }
+
+ private AMQTypedValue GetProperty(string name)
+ {
+ InitMapIfNecessary();
+ return (AMQTypedValue) _properties[name];
+ }
+
+ private void PopulateFromBuffer()
+ {
+ try
+ {
+ ByteBuffer buffer = _encodedForm;
+ _encodedForm = null;
+ if ( buffer != null )
+ SetFromBuffer(buffer, _encodedSize);
+ } catch ( AMQFrameDecodingException e )
+ {
+ _log.Error("Error decoding FieldTable in deferred decoding mode ", e);
+ throw;
+ }
+ }
+
+ private void SetFromBuffer(ByteBuffer buffer, uint length)
+ {
+ bool trace = _log.IsDebugEnabled;
+ if ( length > 0 )
+ {
+ int expectedRemaining = buffer.Remaining - (int)length;
+ _properties = new LinkedHashtable();
+
+ do
+ {
+ string key = EncodingUtils.ReadShortString(buffer);
+ AMQTypedValue value = AMQTypedValue.ReadFromBuffer(buffer);
+ if ( trace )
+ {
+ _log.Debug(string.Format("FieldTable::PropFieldTable(buffer,{0}): Read type '{1}', key '{2}', value '{3}'", length, value.Type, key, value.Value));
+ }
+ _properties.Add(key, value);
+
+ } while ( buffer.Remaining > expectedRemaining );
+ _encodedSize = length;
+ }
+ if ( trace )
+ {
+ _log.Debug("FieldTable::FieldTable(buffer," + length + "): Done.");
+ }
+ }
+
+ private void InitMapIfNecessary()
+ {
+ lock ( _syncLock )
+ {
+ if ( _properties == null )
+ {
+ if ( _encodedForm == null )
+ {
+ _properties = new LinkedHashtable();
+ } else
+ {
+ PopulateFromBuffer();
+ }
+ }
+ }
+ }
+
+ private AMQTypedValue SetProperty(string key, AMQTypedValue value)
+ {
+ InitMapIfNecessary();
+ _encodedForm = null;
+ if ( value == null )
+ {
+ RemoveKey(key);
+ }
+ AMQTypedValue oldVal = (AMQTypedValue)_properties[key];
+ _properties.Add(key, value);
+ if ( oldVal != null )
+ {
+ _encodedSize -= oldVal.EncodingLength;
+ } else
+ {
+ _encodedSize += EncodingUtils.EncodedShortStringLength(key) + (uint)1;
+ }
+ if ( value != null )
+ {
+ _encodedSize += value.EncodingLength;
+ }
+
+ return oldVal;
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ if ( _encodedForm != null )
+ {
+ lock ( _syncLock )
+ {
+ buffer.Put(_encodedForm);
+ _encodedForm.Flip();
+ }
+ } else if ( _properties != null )
+ {
+ foreach ( DictionaryEntry de in _properties )
+ {
+ string key = (string)de.Key;
+ AMQTypedValue value = (AMQTypedValue)de.Value;
+ try
+ {
+ if ( _log.IsDebugEnabled )
+ {
+ _log.Debug("Writing Property:" + key +
+ " Type:" + value.Type +
+ " Value:" + value.Value);
+ _log.Debug("Buffer Position:" + buffer.Position +
+ " Remaining:" + buffer.Remaining);
+ }
+ //Write the actual parameter name
+ EncodingUtils.WriteShortStringBytes(buffer, key);
+ value.WriteToBuffer(buffer);
+ } catch ( Exception ex )
+ {
+ if ( _log.IsDebugEnabled )
+ {
+ _log.Debug("Exception thrown:" + ex);
+ _log.Debug("Writing Property:" + key +
+ " Type:" + value.Type +
+ " Value:" + value.Value);
+ _log.Debug("Buffer Position:" + buffer.Position +
+ " Remaining:" + buffer.Remaining);
+ }
+ throw;
+ }
+ }
+ }
+ }
+ #endregion // Private Methods
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/HeartbeatBody.cs b/dotnet/Qpid.Common/Framing/HeartbeatBody.cs
new file mode 100644
index 0000000000..a8906f5ba8
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/HeartbeatBody.cs
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class HeartbeatBody : IBody
+{
+ public const byte TYPE = 8;
+ public static AMQFrame FRAME = new HeartbeatBody().ToFrame();
+
+ public byte BodyType
+ {
+ get
+ {
+ return TYPE;
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return 0;//heartbeats we generate have no payload
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ }
+
+ public void PopulateFromBuffer(ByteBuffer buffer, uint size)
+ {
+ if (size > 0)
+ {
+ //allow other implementations to have a payload, but ignore it:
+ buffer.Skip((int) size);
+ }
+ }
+
+ public AMQFrame ToFrame()
+ {
+ return new AMQFrame(0, this);
+ }
+}
+}
diff --git a/dotnet/Qpid.Common/Framing/HeartbeatBodyFactory.cs b/dotnet/Qpid.Common/Framing/HeartbeatBodyFactory.cs
new file mode 100644
index 0000000000..90e5c7768e
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/HeartbeatBodyFactory.cs
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ public class HeartbeatBodyFactory : IBodyFactory
+ {
+ public IBody CreateBody(ByteBuffer input)
+ {
+ return new HeartbeatBody();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/IBody.cs b/dotnet/Qpid.Common/Framing/IBody.cs
new file mode 100644
index 0000000000..97b4459e5c
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/IBody.cs
@@ -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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// An IBody is contained within a top level frame. As such, it is not en/decodable on its own but
+ /// is decoded as a step within a the overall en/decoding process.
+ /// </summary>
+ public interface IBody
+ {
+ /// <summary>
+ /// Gets the type. See RFC 006 for the meaning of "type" in this context.
+ /// </summary>
+ /// <value>The type.</value>
+ byte BodyType
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Get the size of the body
+ /// </summary>
+ /// <value>The size in bytes.</value>
+ uint Size
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Writes this instance to a buffer.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ void WritePayload(ByteBuffer buffer);
+
+ /// <summary>
+ /// Populates this instance from a buffer of data.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ /// <param name="size">The size.</param>
+ /// <exception cref="AMQFrameDecodingException">If the buffer contains data that cannot be decoded</exception>
+ void PopulateFromBuffer(ByteBuffer buffer, uint size);
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/IBodyFactory.cs b/dotnet/Qpid.Common/Framing/IBodyFactory.cs
new file mode 100644
index 0000000000..dd7960ddbe
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/IBodyFactory.cs
@@ -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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// Any class that is capable of turning a stream of bytes into an AMQ structure must implement this interface.
+ /// </summary>
+ public interface IBodyFactory
+ {
+ /// <summary>
+ /// Creates the body.
+ /// </summary>
+ /// <param name="inbuf">The ByteBuffer containing data from the network</param>
+ /// <returns></returns>
+ /// <exception>AMQFrameDecodingException</exception>
+ IBody CreateBody(ByteBuffer inbuf);
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/IContentHeaderProperties.cs b/dotnet/Qpid.Common/Framing/IContentHeaderProperties.cs
new file mode 100644
index 0000000000..676d0910d4
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/IContentHeaderProperties.cs
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// There will be an implementation of this interface for each content type. All content types have associated
+ /// header properties and this provides a way to encode and decode them.
+ /// </summary>
+ public interface IContentHeaderProperties
+ {
+ /// <summary>
+ /// Writes the property list to the buffer, in a suitably encoded form.
+ /// </summary>
+ /// <param name="buffer">The buffer to write to</param>
+ void WritePropertyListPayload(ByteBuffer buffer);
+
+ /// <summary>
+ /// Populates the properties from buffer.
+ /// </summary>
+ /// <param name="buffer">The buffer to read from.</param>
+ /// <param name="propertyFlags">The property flags.</param>
+ /// <exception cref="AMQFrameDecodingException">Thrown when the buffer does not contain valid data</exception>
+ void PopulatePropertiesFromBuffer(ByteBuffer buffer, ushort propertyFlags);
+
+ /// <summary>
+ /// Gets the size of the encoded property list in bytes.
+ /// </summary>
+ /// <value>The size of the property list in bytes</value>
+ uint PropertyListSize
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Gets the property flags. Property flags indicate which properties are set in the list. The
+ /// position and meaning of each flag is defined in the protocol specification for the particular
+ /// content type with which these properties are associated.
+ /// </summary>
+ /// <value>the flags as an unsigned integer</value>
+ ushort PropertyFlags
+ {
+ get;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/IDataBlock.cs b/dotnet/Qpid.Common/Framing/IDataBlock.cs
new file mode 100644
index 0000000000..c61ed90d10
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/IDataBlock.cs
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Buffer;
+
+namespace Apache.Qpid.Framing
+{
+ /// <summary>
+ /// A data block represents something that has a size in bytes and the ability to write itself to a byte
+ /// buffer (similar to a byte array). It represents "top level" frames in the protocol specification.
+ /// </summary>
+ public interface IDataBlock : IEncodableAMQDataBlock
+ {
+ /// <summary>
+ /// Get the size of buffer needed to store the byte representation of this
+ /// frame.
+ /// </summary>
+ /// <returns>size in bytes</returns>
+ uint Size
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Writes the datablock to the specified buffer.
+ /// </summary>
+ /// <param name="buffer">The buffer to write to. Must be the correct size.</param>
+ void WritePayload(ByteBuffer buffer);
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/IEncodableAMQDataBlock.cs b/dotnet/Qpid.Common/Framing/IEncodableAMQDataBlock.cs
new file mode 100644
index 0000000000..da8bf9fef9
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/IEncodableAMQDataBlock.cs
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Framing
+{
+
+ /// <summary>
+ /// Marker interface to indicate to MINA that a data block should be encoded with the
+ /// single encoder/decoder that we have defined.
+ /// </summary>
+ public interface IEncodableAMQDataBlock
+ {
+ }
+}
diff --git a/dotnet/Qpid.Common/Framing/ProtocolInitiation.cs b/dotnet/Qpid.Common/Framing/ProtocolInitiation.cs
new file mode 100644
index 0000000000..5407bc08d5
--- /dev/null
+++ b/dotnet/Qpid.Common/Framing/ProtocolInitiation.cs
@@ -0,0 +1,158 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Collections;
+using System.Configuration;
+using System.Reflection;
+using System.Xml;
+using log4net;
+using Apache.Qpid.Buffer;
+using Apache.Qpid.Codec;
+using Apache.Qpid.Codec.Demux;
+using Apache.Qpid.Common;
+
+namespace Apache.Qpid.Framing
+{
+ public class ProtocolInitiation : IDataBlock, IEncodableAMQDataBlock
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(ProtocolInitiation));
+
+ public char[] Header = new char[]{'A','M','Q','P'};
+
+ private const byte CURRENT_PROTOCOL_CLASS = 1;
+ private const int CURRENT_PROTOCOL_INSTANCE = 1;
+ // FIXME: Needs to be tweakable from GRM.dll.config file. i.e. Major version 7 or 8 +
+ // FIXME: a configuration item for avoiding Basic.Qos (for OpenAMQ compatibility)
+ public static int CURRENT_PROTOCOL_VERSION_MAJOR = 8; // FIXME: put back to 7 for OpenAMQ!
+ private const int CURRENT_PROTOCOL_VERSION_MINOR = 0;
+
+ public byte ProtocolClass = CURRENT_PROTOCOL_CLASS;
+ public byte ProtocolInstance = CURRENT_PROTOCOL_INSTANCE;
+ public byte ProtocolMajor = (byte)CURRENT_PROTOCOL_VERSION_MAJOR;
+ public byte ProtocolMinor = CURRENT_PROTOCOL_VERSION_MINOR;
+
+ static ProtocolInitiation()
+ {
+ AssemblySettings settings = new AssemblySettings();
+
+ /*
+ string openAMQ = settings["OpenAMQ1d4Compatibility"];
+ if (openAMQ.Equals("true"))
+ {
+ _log.Warn("Starting in OpenAMQ-1.0d4 compatibility mode. ProtocolMajorVersion is 7 and Basic.Qos will not be sent.");
+ CURRENT_PROTOCOL_VERSION_MAJOR = 7;
+ }
+ */
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return 4 + 1 + 1 + 1 + 1;
+ }
+ }
+
+ public void WritePayload(ByteBuffer buffer)
+ {
+ foreach (char c in Header)
+ {
+ buffer.Put((byte) c);
+ }
+ buffer.Put(ProtocolClass);
+ buffer.Put(ProtocolInstance);
+ buffer.Put(ProtocolMajor);
+ buffer.Put(ProtocolMinor);
+ }
+
+ /// <summary>
+ /// Populates from buffer.
+ /// </summary>
+ /// <param name="buffer">The buffer.</param>
+ public void PopulateFromBuffer(ByteBuffer buffer)
+ {
+ throw new AMQException("Method not implemented");
+ }
+
+ public class Decoder : IMessageDecoder
+ {
+ private bool _disabled = false;
+
+ public MessageDecoderResult Decodable(ByteBuffer inbuf)
+ {
+ if (_disabled)
+ {
+ return MessageDecoderResult.NOT_OK;
+ }
+ if (inbuf.Remaining < 8)
+ {
+ return MessageDecoderResult.NEED_DATA;
+ }
+ else
+ {
+ char[] expected = new char[]{'A', 'M', 'Q', 'P'};
+ for (int i = 0; i < 4; i++)
+ {
+ if (((char) inbuf.GetByte()) != expected[i])
+ {
+ return MessageDecoderResult.NOT_OK;
+ }
+ }
+ return MessageDecoderResult.OK;
+ }
+ }
+
+ /// <summary>
+ /// Decodes the specified session.
+ /// </summary>
+ /// <param name="inbuf">The inbuf.</param>
+ /// <param name="output">The protocol output.</param>
+ /// <returns></returns>
+ public MessageDecoderResult Decode(ByteBuffer inbuf, IProtocolDecoderOutput output)
+ {
+ byte[] header = new byte[4];
+ inbuf.GetBytes(header);
+ ProtocolInitiation pi = new ProtocolInitiation();
+ pi.Header = new char[]{'A','M','Q','P'};
+ pi.ProtocolClass = inbuf.GetByte();
+ pi.ProtocolInstance = inbuf.GetByte();
+ pi.ProtocolMajor = inbuf.GetByte();
+ pi.ProtocolMinor = inbuf.GetByte();
+ output.Write(pi);
+ return MessageDecoderResult.OK;
+ }
+
+ public bool Disabled
+ {
+ set
+ {
+ _disabled = value;
+ }
+ }
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0}{{Class={1} Instance={2} Major={3} Minor={4}}}",
+ GetType().Name, ProtocolClass, ProtocolInstance, ProtocolMajor, ProtocolMinor);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Common/Properties/AssemblyInfo.cs b/dotnet/Qpid.Common/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..3847429519
--- /dev/null
+++ b/dotnet/Qpid.Common/Properties/AssemblyInfo.cs
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Common")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Common")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8dea7c69-1383-4bf7-99e9-e172eba639a2")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
diff --git a/dotnet/Qpid.Common/Protocol/AMQConstant.cs b/dotnet/Qpid.Common/Protocol/AMQConstant.cs
new file mode 100644
index 0000000000..9400b1bd80
--- /dev/null
+++ b/dotnet/Qpid.Common/Protocol/AMQConstant.cs
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+
+namespace Apache.Qpid.Protocol
+{
+ public sealed class AMQConstant
+ {
+ private int _code;
+ private string _name;
+ private static Hashtable _codeMap = new Hashtable();
+
+ public int Code
+ {
+ get { return _code; }
+ }
+
+ public string Name
+ {
+ get { return _name; }
+ }
+
+ private AMQConstant(int code, string name, bool map)
+ {
+ _code = code;
+ _name = name;
+
+ if ( map )
+ {
+ _codeMap.Add(code, this);
+ }
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}: {1}", Code, Name);
+ }
+
+ public static AMQConstant GetConstant(int code)
+ {
+ AMQConstant c = (AMQConstant)_codeMap[code];
+ if ( c == null )
+ {
+ c = new AMQConstant(code, "unknown code", false);
+ }
+ return c;
+ }
+
+ #region Constants
+ //
+ // Constants
+ //
+ public static readonly AMQConstant FRAME_MIN_SIZE = new AMQConstant(4096, "frame min size", true);
+ public static readonly AMQConstant FRAME_END = new AMQConstant(206, "frame end", true);
+ public static readonly AMQConstant REPLY_SUCCESS = new AMQConstant(200, "reply success", true);
+ public static readonly AMQConstant NOT_DELIVERED = new AMQConstant(310, "not delivered", true);
+ public static readonly AMQConstant MESSAGE_TOO_LARGE = new AMQConstant(311, "message too large", true);
+ public static readonly AMQConstant NO_ROUTE = new AMQConstant(312, "no route", true);
+ public static readonly AMQConstant NO_CONSUMERS = new AMQConstant(313, "no consumers", true);
+ public static readonly AMQConstant CONTEXT_IN_USE = new AMQConstant(320, "context in use", true);
+ public static readonly AMQConstant INVALID_PATH = new AMQConstant(402, "invalid path", true);
+ public static readonly AMQConstant ACCESS_REFUSED = new AMQConstant(403, "access refused", true);
+ public static readonly AMQConstant NOT_FOUND = new AMQConstant(404, "not found", true);
+ public static readonly AMQConstant ALREADY_EXISTS = new AMQConstant(405, "already exists", true);
+ public static readonly AMQConstant IN_USE = new AMQConstant(406, "in use", true);
+ public static readonly AMQConstant INVALID_ROUTING_KEY = new AMQConstant(407, "routing key invalid", true);
+ public static readonly AMQConstant REQUEST_TIMEOUT = new AMQConstant(408, "request timeout", true);
+ public static readonly AMQConstant INVALID_ARGUMENT = new AMQConstant(409, "argument invalid", true);
+ public static readonly AMQConstant FRAME_ERROR = new AMQConstant(501, "frame error", true);
+ public static readonly AMQConstant SYNTAX_ERROR = new AMQConstant(502, "syntax error", true);
+ public static readonly AMQConstant COMMAND_INVALID = new AMQConstant(503, "command invalid", true);
+ public static readonly AMQConstant CHANNEL_ERROR = new AMQConstant(504, "channel error", true);
+ public static readonly AMQConstant RESOURCE_ERROR = new AMQConstant(506, "resource error", true);
+ public static readonly AMQConstant NOT_ALLOWED = new AMQConstant(530, "not allowed", true);
+ public static readonly AMQConstant NOT_IMPLEMENTED = new AMQConstant(540, "not implemented", true);
+ public static readonly AMQConstant INTERNAL_ERROR = new AMQConstant(541, "internal error", true);
+
+ #endregion // Constants
+
+ }
+}
diff --git a/dotnet/Qpid.Common/Qpid.Common.csproj b/dotnet/Qpid.Common/Qpid.Common.csproj
new file mode 100644
index 0000000000..09f0a96ba9
--- /dev/null
+++ b/dotnet/Qpid.Common/Qpid.Common.csproj
@@ -0,0 +1,104 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid</RootNamespace>
+ <AssemblyName>Apache.Qpid.Common</AssemblyName>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Codec\Qpid.Codec.csproj">
+ <Project>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</Project>
+ <Name>Qpid.Codec</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="stylesheets\csharp.xsl" />
+ <Content Include="stylesheets\framing.xsl" />
+ <Content Include="stylesheets\java.xsl" />
+ <Content Include="stylesheets\prepare1.xsl" />
+ <Content Include="stylesheets\prepare2.xsl" />
+ <Content Include="stylesheets\prepare3.xsl" />
+ <Content Include="stylesheets\readme.txt" />
+ <Content Include="stylesheets\registry.xsl" />
+ <Content Include="stylesheets\utils.xsl" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Common/amqp.xml b/dotnet/Qpid.Common/amqp.xml
new file mode 100644
index 0000000000..ddd4b5be4b
--- /dev/null
+++ b/dotnet/Qpid.Common/amqp.xml
@@ -0,0 +1,3929 @@
+<?xml version="1.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.
+
+-->
+
+
+<!--
+Copyright Notice
+================
+© Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc.,
+iMatix Corporation, IONA� Technologies, Red Hat, Inc.,
+TWIST Process Innovations, and 29West Inc. 2006. All rights reserved.
+
+License
+=======
+JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix
+Corporation, IONA� Technologies, Red Hat, Inc., TWIST Process Innovations, and
+29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide,
+perpetual, royalty-free, nontransferable, nonexclusive license to
+(i) copy, display, and implement the Advanced Messaging Queue Protocol
+("AMQP") Specification and (ii) the Licensed Claims that are held by
+the Authors, all for the purpose of implementing the Advanced Messaging
+Queue Protocol Specification. Your license and any rights under this
+Agreement will terminate immediately without notice from
+any Author if you bring any claim, suit, demand, or action related to
+the Advanced Messaging Queue Protocol Specification against any Author.
+Upon termination, you shall destroy all copies of the Advanced Messaging
+Queue Protocol Specification in your possession or control.
+
+As used hereunder, "Licensed Claims" means those claims of a patent or
+patent application, throughout the world, excluding design patents and
+design registrations, owned or controlled, or that can be sublicensed
+without fee and in compliance with the requirements of this
+Agreement, by an Author or its affiliates now or at any
+future time and which would necessarily be infringed by implementation
+of the Advanced Messaging Queue Protocol Specification. A claim is
+necessarily infringed hereunder only when it is not possible to avoid
+infringing it because there is no plausible non-infringing alternative
+for implementing the required portions of the Advanced Messaging Queue
+Protocol Specification. Notwithstanding the foregoing, Licensed Claims
+shall not include any claims other than as set forth above even if
+contained in the same patent as Licensed Claims; or that read solely
+on any implementations of any portion of the Advanced Messaging Queue
+Protocol Specification that are not required by the Advanced Messaging
+Queue Protocol Specification, or that, if licensed, would require a
+payment of royalties by the licensor to unaffiliated third parties.
+Moreover, Licensed Claims shall not include (i) any enabling technologies
+that may be necessary to make or use any Licensed Product but are not
+themselves expressly set forth in the Advanced Messaging Queue Protocol
+Specification (e.g., semiconductor manufacturing technology, compiler
+technology, object oriented technology, networking technology, operating
+system technology, and the like); or (ii) the implementation of other
+published standards developed elsewhere and merely referred to in the
+body of the Advanced Messaging Queue Protocol Specification, or
+(iii) any Licensed Product and any combinations thereof the purpose or
+function of which is not required for compliance with the Advanced
+Messaging Queue Protocol Specification. For purposes of this definition,
+the Advanced Messaging Queue Protocol Specification shall be deemed to
+include both architectural and interconnection requirements essential
+for interoperability and may also include supporting source code artifacts
+where such architectural, interconnection requirements and source code
+artifacts are expressly identified as being required or documentation to
+achieve compliance with the Advanced Messaging Queue Protocol Specification.
+
+As used hereunder, "Licensed Products" means only those specific portions
+of products (hardware, software or combinations thereof) that implement
+and are compliant with all relevant portions of the Advanced Messaging
+Queue Protocol Specification.
+
+The following disclaimers, which you hereby also acknowledge as to any
+use you may make of the Advanced Messaging Queue Protocol Specification:
+
+THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS,"
+AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE
+CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE
+SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED
+MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY
+PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
+INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
+USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE
+PROTOCOL SPECIFICATION.
+
+The name and trademarks of the Authors may NOT be used in any manner,
+including advertising or publicity pertaining to the Advanced Messaging
+Queue Protocol Specification or its contents without specific, written
+prior permission. Title to copyright in the Advanced Messaging Queue
+Protocol Specification will at all times remain with the Authors.
+
+No other rights are granted by implication, estoppel or otherwise.
+
+Upon termination of your license or rights under this Agreement, you
+shall destroy all copies of the Advanced Messaging Queue Protocol
+Specification in your possession or control.
+
+Trademarks
+==========
+"JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the
+Octagon Symbol are trademarks of JPMorgan Chase & Co.
+
+IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
+
+IONA, IONA Technologies, and the IONA logos are trademarks of IONA
+Technologies PLC and/or its subsidiaries.
+
+LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered
+trademarks of Red Hat, Inc. in the US and other countries.
+
+Java, all Java-based trademarks and OpenOffice.org are trademarks of
+Sun Microsystems, Inc. in the United States, other countries, or both.
+
+Other company, product, or service names may be trademarks or service
+marks of others.
+
+Links to full AMQP specification:
+=================================
+http://www.envoytech.org/spec/amq/
+http://www.iona.com/opensource/amqp/
+http://www.redhat.com/solutions/specifications/amqp/
+http://www.twiststandards.org/tiki-index.php?page=AMQ
+http://www.imatix.com/amqp
+
+-->
+
+<amqp major="8" minor="0" port="5672" comment="AMQ protocol 0.80">
+ AMQ Protocol 0.80
+<!--
+======================================================
+== CONSTANTS
+======================================================
+-->
+ <constant name="frame method" value="1"/>
+ <constant name="frame header" value="2"/>
+ <constant name="frame body" value="3"/>
+ <constant name="frame oob method" value="4"/>
+ <constant name="frame oob header" value="5"/>
+ <constant name="frame oob body" value="6"/>
+ <constant name="frame trace" value="7"/>
+ <constant name="frame heartbeat" value="8"/>
+ <constant name="frame min size" value="4096"/>
+ <constant name="frame end" value="206"/>
+ <constant name="reply success" value="200">
+ Indicates that the method completed successfully. This reply code is
+ reserved for future use - the current protocol design does not use
+ positive confirmation and reply codes are sent only in case of an
+ error.
+</constant>
+ <constant name="not delivered" value="310" class="soft error">
+ The client asked for a specific message that is no longer available.
+ The message was delivered to another client, or was purged from the
+ queue for some other reason.
+</constant>
+ <constant name="content too large" value="311" class="soft error">
+ The client attempted to transfer content larger than the server
+ could accept at the present time. The client may retry at a later
+ time.
+</constant>
+ <constant name="connection forced" value="320" class="hard error">
+ An operator intervened to close the connection for some reason.
+ The client may retry at some later date.
+</constant>
+ <constant name="invalid path" value="402" class="hard error">
+ The client tried to work with an unknown virtual host or cluster.
+</constant>
+ <constant name="access refused" value="403" class="soft error">
+ The client attempted to work with a server entity to which it has
+ no due to security settings.
+</constant>
+ <constant name="not found" value="404" class="soft error">
+ The client attempted to work with a server entity that does not exist.
+</constant>
+ <constant name="resource locked" value="405" class="soft error">
+ The client attempted to work with a server entity to which it has
+ no access because another client is working with it.
+</constant>
+ <constant name="frame error" value="501" class="hard error">
+ The client sent a malformed frame that the server could not decode.
+ This strongly implies a programming error in the client.
+</constant>
+ <constant name="syntax error" value="502" class="hard error">
+ The client sent a frame that contained illegal values for one or more
+ fields. This strongly implies a programming error in the client.
+</constant>
+ <constant name="command invalid" value="503" class="hard error">
+ The client sent an invalid sequence of frames, attempting to perform
+ an operation that was considered invalid by the server. This usually
+ implies a programming error in the client.
+</constant>
+ <constant name="channel error" value="504" class="hard error">
+ The client attempted to work with a channel that had not been
+ correctly opened. This most likely indicates a fault in the client
+ layer.
+</constant>
+ <constant name="resource error" value="506" class="hard error">
+ The server could not complete the method because it lacked sufficient
+ resources. This may be due to the client creating too many of some
+ type of entity.
+</constant>
+ <constant name="not allowed" value="530" class="hard error">
+ The client tried to work with some entity in a manner that is
+ prohibited by the server, due to security settings or by some other
+ criteria.
+</constant>
+ <constant name="not implemented" value="540" class="hard error">
+ The client tried to use functionality that is not implemented in the
+ server.
+</constant>
+ <constant name="internal error" value="541" class="hard error">
+ The server could not complete the method because of an internal error.
+ The server may require intervention by an operator in order to resume
+ normal operations.
+</constant>
+ <!--
+======================================================
+== DOMAIN TYPES
+======================================================
+-->
+ <domain name="access ticket" type="short">
+ access ticket granted by server
+ <doc>
+ An access ticket granted by the server for a certain set of access
+ rights within a specific realm. Access tickets are valid within the
+ channel where they were created, and expire when the channel closes.
+ </doc>
+ <assert check="ne" value="0"/>
+ </domain>
+ <domain name="class id" type="short"/>
+ <domain name="consumer tag" type="shortstr">
+ consumer tag
+ <doc>
+ Identifier for the consumer, valid within the current connection.
+ </doc>
+ <rule implement="MUST">
+ The consumer tag is valid only within the channel from which the
+ consumer was created. I.e. a client MUST NOT create a consumer in
+ one channel and then use it in another.
+ </rule>
+ </domain>
+ <domain name="delivery tag" type="longlong">
+ server-assigned delivery tag
+ <doc>
+ The server-assigned and channel-specific delivery tag
+ </doc>
+ <rule implement="MUST">
+ The delivery tag is valid only within the channel from which the
+ message was received. I.e. a client MUST NOT receive a message on
+ one channel and then acknowledge it on another.
+ </rule>
+ <rule implement="MUST">
+ The server MUST NOT use a zero value for delivery tags. Zero is
+ reserved for client use, meaning "all messages so far received".
+ </rule>
+ </domain>
+ <domain name="exchange name" type="shortstr">
+ exchange name
+ <doc>
+ The exchange name is a client-selected string that identifies
+ the exchange for publish methods. Exchange names may consist
+ of any mixture of digits, letters, and underscores. Exchange
+ names are scoped by the virtual host.
+ </doc>
+ <assert check="length" value="127"/>
+ </domain>
+ <domain name="known hosts" type="shortstr">
+list of known hosts
+<doc>
+Specifies the list of equivalent or alternative hosts that the server
+knows about, which will normally include the current server itself.
+Clients can cache this information and use it when reconnecting to a
+server after a failure.
+</doc>
+ <rule implement="MAY">
+The server MAY leave this field empty if it knows of no other
+hosts than itself.
+</rule>
+ </domain>
+ <domain name="method id" type="short"/>
+ <domain name="no ack" type="bit">
+ no acknowledgement needed
+ <doc>
+ If this field is set the server does not expect acknowledgments
+ for messages. That is, when a message is delivered to the client
+ the server automatically and silently acknowledges it on behalf
+ of the client. This functionality increases performance but at
+ the cost of reliability. Messages can get lost if a client dies
+ before it can deliver them to the application.
+ </doc>
+ </domain>
+ <domain name="no local" type="bit">
+ do not deliver own messages
+ <doc>
+ If the no-local field is set the server will not send messages to
+ the client that published them.
+ </doc>
+ </domain>
+ <domain name="path" type="shortstr">
+ <doc>
+ Must start with a slash "/" and continue with path names
+ separated by slashes. A path name consists of any combination
+ of at least one of [A-Za-z0-9] plus zero or more of [.-_+!=:].
+</doc>
+ <assert check="notnull"/>
+ <assert check="syntax" rule="path"/>
+ <assert check="length" value="127"/>
+ </domain>
+ <domain name="peer properties" type="table">
+ <doc>
+This string provides a set of peer properties, used for
+identification, debugging, and general information.
+</doc>
+ <rule implement="SHOULD">
+The properties SHOULD contain these fields:
+"product", giving the name of the peer product, "version", giving
+the name of the peer version, "platform", giving the name of the
+operating system, "copyright", if appropriate, and "information",
+giving other general information.
+</rule>
+ </domain>
+ <domain name="queue name" type="shortstr">
+ queue name
+ <doc>
+ The queue name identifies the queue within the vhost. Queue
+ names may consist of any mixture of digits, letters, and
+ underscores.
+ </doc>
+ <assert check="length" value="127"/>
+ </domain>
+ <domain name="redelivered" type="bit">
+ message is being redelivered
+ <doc>
+ This indicates that the message has been previously delivered to
+ this or another client.
+ </doc>
+ <rule implement="SHOULD">
+ The server SHOULD try to signal redelivered messages when it can.
+ When redelivering a message that was not successfully acknowledged,
+ the server SHOULD deliver it to the original client if possible.
+ </rule>
+ <rule implement="MUST">
+ The client MUST NOT rely on the redelivered field but MUST take it
+ as a hint that the message may already have been processed. A
+ fully robust client must be able to track duplicate received messages
+ on non-transacted, and locally-transacted channels.
+ </rule>
+ </domain>
+ <domain name="reply code" type="short">
+reply code from server
+<doc>
+ The reply code. The AMQ reply codes are defined in AMQ RFC 011.
+</doc>
+ <assert check="notnull"/>
+ </domain>
+ <domain name="reply text" type="shortstr">
+localised reply text
+<doc>
+ The localised reply text. This text can be logged as an aid to
+ resolving issues.
+</doc>
+ <assert check="notnull"/>
+ </domain>
+ <class name="connection" handler="connection" index="10">
+ <!--
+======================================================
+== CONNECTION
+======================================================
+-->
+ work with socket connections
+<doc>
+ The connection class provides methods for a client to establish a
+ network connection to a server, and for both peers to operate the
+ connection thereafter.
+</doc>
+ <doc name="grammar">
+ connection = open-connection *use-connection close-connection
+ open-connection = C:protocol-header
+ S:START C:START-OK
+ *challenge
+ S:TUNE C:TUNE-OK
+ C:OPEN S:OPEN-OK | S:REDIRECT
+ challenge = S:SECURE C:SECURE-OK
+ use-connection = *channel
+ close-connection = C:CLOSE S:CLOSE-OK
+ / S:CLOSE C:CLOSE-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="start" synchronous="1" index="10">
+ start connection negotiation
+ <doc>
+ This method starts the connection negotiation process by telling
+ the client the protocol version that the server proposes, along
+ with a list of security mechanisms which the client can use for
+ authentication.
+ </doc>
+ <rule implement="MUST">
+ If the client cannot handle the protocol version suggested by the
+ server it MUST close the socket connection.
+ </rule>
+ <rule implement="MUST">
+ The server MUST provide a protocol version that is lower than or
+ equal to that requested by the client in the protocol header. If
+ the server cannot support the specified protocol it MUST NOT send
+ this method, but MUST close the socket connection.
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <response name="start-ok"/>
+ <field name="version major" type="octet">
+ protocol major version
+ <doc>
+ The protocol major version that the server agrees to use, which
+ cannot be higher than the client's major version.
+ </doc>
+ </field>
+ <field name="version minor" type="octet">
+ protocol major version
+ <doc>
+ The protocol minor version that the server agrees to use, which
+ cannot be higher than the client's minor version.
+ </doc>
+ </field>
+ <field name="server properties" domain="peer properties">
+ server properties
+ </field>
+ <field name="mechanisms" type="longstr">
+ available security mechanisms
+ <doc>
+ A list of the security mechanisms that the server supports, delimited
+ by spaces. Currently ASL supports these mechanisms: PLAIN.
+ </doc>
+ <see name="security mechanisms"/>
+ <assert check="notnull"/>
+ </field>
+ <field name="locales" type="longstr">
+ available message locales
+ <doc>
+ A list of the message locales that the server supports, delimited
+ by spaces. The locale defines the language in which the server
+ will send reply texts.
+ </doc>
+ <rule implement="MUST">
+ All servers MUST support at least the en_US locale.
+ </rule>
+ <assert check="notnull"/>
+ </field>
+ </method>
+ <method name="start-ok" synchronous="1" index="11">
+ select security mechanism and locale
+ <doc>
+ This method selects a SASL security mechanism. ASL uses SASL
+ (RFC2222) to negotiate authentication and encryption.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <field name="client properties" domain="peer properties">
+ client properties
+ </field>
+ <field name="mechanism" type="shortstr">
+ selected security mechanism
+ <doc>
+ A single security mechanisms selected by the client, which must be
+ one of those specified by the server.
+ </doc>
+ <rule implement="SHOULD">
+ The client SHOULD authenticate using the highest-level security
+ profile it can handle from the list provided by the server.
+ </rule>
+ <rule implement="MUST">
+ The mechanism field MUST contain one of the security mechanisms
+ proposed by the server in the Start method. If it doesn't, the
+ server MUST close the socket.
+ </rule>
+ <assert check="notnull"/>
+ </field>
+ <field name="response" type="longstr">
+ security response data
+ <doc>
+ A block of opaque data passed to the security mechanism. The contents
+ of this data are defined by the SASL security mechanism. For the
+ PLAIN security mechanism this is defined as a field table holding
+ two fields, LOGIN and PASSWORD.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ <field name="locale" type="shortstr">
+ selected message locale
+ <doc>
+ A single message local selected by the client, which must be one
+ of those specified by the server.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="secure" synchronous="1" index="20">
+ security mechanism challenge
+ <doc>
+ The SASL protocol works by exchanging challenges and responses until
+ both peers have received sufficient information to authenticate each
+ other. This method challenges the client to provide more information.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <response name="secure-ok"/>
+ <field name="challenge" type="longstr">
+ security challenge data
+ <doc>
+ Challenge information, a block of opaque binary data passed to
+ the security mechanism.
+ </doc>
+ <see name="security mechanisms"/>
+ </field>
+ </method>
+ <method name="secure-ok" synchronous="1" index="21">
+ security mechanism response
+ <doc>
+ This method attempts to authenticate, passing a block of SASL data
+ for the security mechanism at the server side.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <field name="response" type="longstr">
+ security response data
+ <doc>
+ A block of opaque data passed to the security mechanism. The contents
+ of this data are defined by the SASL security mechanism.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="tune" synchronous="1" index="30">
+ propose connection tuning parameters
+ <doc>
+ This method proposes a set of connection configuration values
+ to the client. The client can accept and/or adjust these.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <response name="tune-ok"/>
+ <field name="channel max" type="short">
+ proposed maximum channels
+ <doc>
+ The maximum total number of channels that the server allows
+ per connection. Zero means that the server does not impose a
+ fixed limit, but the number of allowed channels may be limited
+ by available server resources.
+ </doc>
+ </field>
+ <field name="frame max" type="long">
+ proposed maximum frame size
+ <doc>
+ The largest frame size that the server proposes for the
+ connection. The client can negotiate a lower value. Zero means
+ that the server does not impose any specific limit but may reject
+ very large frames if it cannot allocate resources for them.
+ </doc>
+ <rule implement="MUST">
+ Until the frame-max has been negotiated, both peers MUST accept
+ frames of up to 4096 octets large. The minimum non-zero value for
+ the frame-max field is 4096.
+ </rule>
+ </field>
+ <field name="heartbeat" type="short">
+ desired heartbeat delay
+ <doc>
+ The delay, in seconds, of the connection heartbeat that the server
+ wants. Zero means the server does not want a heartbeat.
+ </doc>
+ </field>
+ </method>
+ <method name="tune-ok" synchronous="1" index="31">
+ negotiate connection tuning parameters
+ <doc>
+ This method sends the client's connection tuning parameters to the
+ server. Certain fields are negotiated, others provide capability
+ information.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <field name="channel max" type="short">
+ negotiated maximum channels
+ <doc>
+ The maximum total number of channels that the client will use
+ per connection. May not be higher than the value specified by
+ the server.
+ </doc>
+ <rule implement="MAY">
+ The server MAY ignore the channel-max value or MAY use it for
+ tuning its resource allocation.
+ </rule>
+ <assert check="notnull"/>
+ <assert check="le" method="tune" field="channel max"/>
+ </field>
+ <field name="frame max" type="long">
+ negotiated maximum frame size
+ <doc>
+ The largest frame size that the client and server will use for
+ the connection. Zero means that the client does not impose any
+ specific limit but may reject very large frames if it cannot
+ allocate resources for them. Note that the frame-max limit
+ applies principally to content frames, where large contents
+ can be broken into frames of arbitrary size.
+ </doc>
+ <rule implement="MUST">
+ Until the frame-max has been negotiated, both peers must accept
+ frames of up to 4096 octets large. The minimum non-zero value for
+ the frame-max field is 4096.
+ </rule>
+ </field>
+ <field name="heartbeat" type="short">
+ desired heartbeat delay
+ <doc>
+ The delay, in seconds, of the connection heartbeat that the client
+ wants. Zero means the client does not want a heartbeat.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="open" synchronous="1" index="40">
+ open connection to virtual host
+ <doc>
+ This method opens a connection to a virtual host, which is a
+ collection of resources, and acts to separate multiple application
+ domains within a server.
+ </doc>
+ <rule implement="MUST">
+ The client MUST open the context before doing any work on the
+ connection.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="open-ok"/>
+ <response name="redirect"/>
+ <field name="virtual host" domain="path">
+ virtual host name
+ <assert check="regexp" value="^[a-zA-Z0-9/-_]+$"/>
+ <doc>
+ The name of the virtual host to work with.
+ </doc>
+ <rule implement="MUST">
+ If the server supports multiple virtual hosts, it MUST enforce a
+ full separation of exchanges, queues, and all associated entities
+ per virtual host. An application, connected to a specific virtual
+ host, MUST NOT be able to access resources of another virtual host.
+ </rule>
+ <rule implement="SHOULD">
+ The server SHOULD verify that the client has permission to access
+ the specified virtual host.
+ </rule>
+ <rule implement="MAY">
+ The server MAY configure arbitrary limits per virtual host, such
+ as the number of each type of entity that may be used, per
+ connection and/or in total.
+ </rule>
+ </field>
+ <field name="capabilities" type="shortstr">
+ required capabilities
+ <doc>
+ The client may specify a number of capability names, delimited by
+ spaces. The server can use this string to how to process the
+ client's connection request.
+ </doc>
+ </field>
+ <field name="insist" type="bit">
+ insist on connecting to server
+ <doc>
+ In a configuration with multiple load-sharing servers, the server
+ may respond to a Connection.Open method with a Connection.Redirect.
+ The insist option tells the server that the client is insisting on
+ a connection to the specified server.
+ </doc>
+ <rule implement="SHOULD">
+ When the client uses the insist option, the server SHOULD accept
+ the client connection unless it is technically unable to do so.
+ </rule>
+ </field>
+ </method>
+ <method name="open-ok" synchronous="1" index="41">
+ signal that the connection is ready
+ <doc>
+ This method signals to the client that the connection is ready for
+ use.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <field name="known hosts" domain="known hosts"/>
+ </method>
+ <method name="redirect" synchronous="1" index="50">
+ asks the client to use a different server
+ <doc>
+ This method redirects the client to another server, based on the
+ requested virtual host and/or capabilities.
+ </doc>
+ <rule implement="SHOULD">
+ When getting the Connection.Redirect method, the client SHOULD
+ reconnect to the host specified, and if that host is not present,
+ to any of the hosts specified in the known-hosts list.
+ </rule>
+ <chassis name="client" implement="MAY"/>
+ <field name="host" type="shortstr">
+ server to connect to
+ <doc>
+ Specifies the server to connect to. This is an IP address or a
+ DNS name, optionally followed by a colon and a port number. If
+ no port number is specified, the client should use the default
+ port number for the protocol.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ <field name="known hosts" domain="known hosts"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="close" synchronous="1" index="60">
+ request a connection close
+ <doc>
+ This method indicates that the sender wants to close the connection.
+ This may be due to internal conditions (e.g. a forced shut-down) or
+ due to an error handling a specific method, i.e. an exception. When
+ a close is due to an exception, the sender provides the class and
+ method id of the method which caused the exception.
+ </doc>
+ <rule implement="MUST">
+ After sending this method any received method except the Close-OK
+ method MUST be discarded.
+ </rule>
+ <rule implement="MAY">
+ The peer sending this method MAY use a counter or timeout to
+ detect failure of the other peer to respond correctly with
+ the Close-OK method.
+ </rule>
+ <rule implement="MUST">
+ When a server receives the Close method from a client it MUST
+ delete all server-side resources associated with the client's
+ context. A client CANNOT reconnect to a context after sending
+ or receiving a Close method.
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="close-ok"/>
+ <field name="reply code" domain="reply code"/>
+ <field name="reply text" domain="reply text"/>
+ <field name="class id" domain="class id">
+ failing method class
+ <doc>
+ When the close is provoked by a method exception, this is the
+ class of the method.
+ </doc>
+ </field>
+ <field name="method id" domain="class id">
+ failing method ID
+ <doc>
+ When the close is provoked by a method exception, this is the
+ ID of the method.
+ </doc>
+ </field>
+ </method>
+ <method name="close-ok" synchronous="1" index="61">
+ confirm a connection close
+ <doc>
+ This method confirms a Connection.Close method and tells the
+ recipient that it is safe to release resources for the connection
+ and close the socket.
+ </doc>
+ <rule implement="SHOULD">
+ A peer that detects a socket closure without having received a
+ Close-Ok handshake method SHOULD log the error.
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ </method>
+ </class>
+ <class name="channel" handler="channel" index="20">
+ <!--
+======================================================
+== CHANNEL
+======================================================
+-->
+ work with channels
+<doc>
+ The channel class provides methods for a client to establish a virtual
+ connection - a channel - to a server and for both peers to operate the
+ virtual connection thereafter.
+</doc>
+ <doc name="grammar">
+ channel = open-channel *use-channel close-channel
+ open-channel = C:OPEN S:OPEN-OK
+ use-channel = C:FLOW S:FLOW-OK
+ / S:FLOW C:FLOW-OK
+ / S:ALERT
+ / functional-class
+ close-channel = C:CLOSE S:CLOSE-OK
+ / S:CLOSE C:CLOSE-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="open" synchronous="1" index="10">
+ open a channel for use
+ <doc>
+ This method opens a virtual connection (a channel).
+ </doc>
+ <rule implement="MUST">
+ This method MUST NOT be called when the channel is already open.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="open-ok"/>
+ <field name="out of band" type="shortstr">
+ out-of-band settings
+ <doc>
+ Configures out-of-band transfers on this channel. The syntax and
+ meaning of this field will be formally defined at a later date.
+ </doc>
+ <assert check="null"/>
+ </field>
+ </method>
+ <method name="open-ok" synchronous="1" index="11">
+ signal that the channel is ready
+ <doc>
+ This method signals to the client that the channel is ready for use.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="flow" synchronous="1" index="20">
+ enable/disable flow from peer
+ <doc>
+ This method asks the peer to pause or restart the flow of content
+ data. This is a simple flow-control mechanism that a peer can use
+ to avoid oveflowing its queues or otherwise finding itself receiving
+ more messages than it can process. Note that this method is not
+ intended for window control. The peer that receives a request to
+ stop sending content should finish sending the current content, if
+ any, and then wait until it receives a Flow restart method.
+ </doc>
+ <rule implement="MAY">
+ When a new channel is opened, it is active. Some applications
+ assume that channels are inactive until started. To emulate this
+ behaviour a client MAY open the channel, then pause it.
+ </rule>
+ <rule implement="SHOULD">
+ When sending content data in multiple frames, a peer SHOULD monitor
+ the channel for incoming methods and respond to a Channel.Flow as
+ rapidly as possible.
+ </rule>
+ <rule implement="MAY">
+ A peer MAY use the Channel.Flow method to throttle incoming content
+ data for internal reasons, for example, when exchangeing data over a
+ slower connection.
+ </rule>
+ <rule implement="MAY">
+ The peer that requests a Channel.Flow method MAY disconnect and/or
+ ban a peer that does not respect the request.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <response name="flow-ok"/>
+ <field name="active" type="bit">
+ start/stop content frames
+ <doc>
+ If 1, the peer starts sending content frames. If 0, the peer
+ stops sending content frames.
+ </doc>
+ </field>
+ </method>
+ <method name="flow-ok" index="21">
+ confirm a flow method
+ <doc>
+ Confirms to the peer that a flow command was received and processed.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <field name="active" type="bit">
+ current flow setting
+ <doc>
+ Confirms the setting of the processed flow method: 1 means the
+ peer will start sending or continue to send content frames; 0
+ means it will not.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="alert" index="30">
+ send a non-fatal warning message
+ <doc>
+ This method allows the server to send a non-fatal warning to the
+ client. This is used for methods that are normally asynchronous
+ and thus do not have confirmations, and for which the server may
+ detect errors that need to be reported. Fatal errors are handled
+ as channel or connection exceptions; non-fatal errors are sent
+ through this method.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <field name="reply code" domain="reply code"/>
+ <field name="reply text" domain="reply text"/>
+ <field name="details" type="table">
+ detailed information for warning
+ <doc>
+ A set of fields that provide more information about the
+ problem. The meaning of these fields are defined on a
+ per-reply-code basis (TO BE DEFINED).
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="close" synchronous="1" index="40">
+ request a channel close
+ <doc>
+ This method indicates that the sender wants to close the channel.
+ This may be due to internal conditions (e.g. a forced shut-down) or
+ due to an error handling a specific method, i.e. an exception. When
+ a close is due to an exception, the sender provides the class and
+ method id of the method which caused the exception.
+ </doc>
+ <rule implement="MUST">
+ After sending this method any received method except
+ Channel.Close-OK MUST be discarded.
+ </rule>
+ <rule implement="MAY">
+ The peer sending this method MAY use a counter or timeout to detect
+ failure of the other peer to respond correctly with Channel.Close-OK..
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="close-ok"/>
+ <field name="reply code" domain="reply code"/>
+ <field name="reply text" domain="reply text"/>
+ <field name="class id" domain="class id">
+ failing method class
+ <doc>
+ When the close is provoked by a method exception, this is the
+ class of the method.
+ </doc>
+ </field>
+ <field name="method id" domain="method id">
+ failing method ID
+ <doc>
+ When the close is provoked by a method exception, this is the
+ ID of the method.
+ </doc>
+ </field>
+ </method>
+ <method name="close-ok" synchronous="1" index="41">
+ confirm a channel close
+ <doc>
+ This method confirms a Channel.Close method and tells the recipient
+ that it is safe to release resources for the channel and close the
+ socket.
+ </doc>
+ <rule implement="SHOULD">
+ A peer that detects a socket closure without having received a
+ Channel.Close-Ok handshake method SHOULD log the error.
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ </method>
+ </class>
+ <class name="access" handler="connection" index="30">
+ <!--
+======================================================
+== ACCESS CONTROL
+======================================================
+-->
+ work with access tickets
+<doc>
+ The protocol control access to server resources using access tickets.
+ A client must explicitly request access tickets before doing work.
+ An access ticket grants a client the right to use a specific set of
+ resources - called a "realm" - in specific ways.
+</doc>
+ <doc name="grammar">
+ access = C:REQUEST S:REQUEST-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="request" synchronous="1" index="10">
+ request an access ticket
+ <doc>
+ This method requests an access ticket for an access realm.
+ The server responds by granting the access ticket. If the
+ client does not have access rights to the requested realm
+ this causes a connection exception. Access tickets are a
+ per-channel resource.
+ </doc>
+ <rule implement="MUST">
+ The realm name MUST start with either "/data" (for application
+ resources) or "/admin" (for server administration resources).
+ If the realm starts with any other path, the server MUST raise
+ a connection exception with reply code 403 (access refused).
+ </rule>
+ <rule implement="MUST">
+ The server MUST implement the /data realm and MAY implement the
+ /admin realm. The mapping of resources to realms is not
+ defined in the protocol - this is a server-side configuration
+ issue.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="request-ok"/>
+ <field name="realm" domain="path">
+ name of requested realm
+ <rule implement="MUST">
+ If the specified realm is not known to the server, the server
+ must raise a channel exception with reply code 402 (invalid
+ path).
+ </rule>
+ </field>
+ <field name="exclusive" type="bit">
+ request exclusive access
+ <doc>
+ Request exclusive access to the realm. If the server cannot grant
+ this - because there are other active tickets for the realm - it
+ raises a channel exception.
+ </doc>
+ </field>
+ <field name="passive" type="bit">
+ request passive access
+ <doc>
+ Request message passive access to the specified access realm.
+ Passive access lets a client get information about resources in
+ the realm but not to make any changes to them.
+ </doc>
+ </field>
+ <field name="active" type="bit">
+ request active access
+ <doc>
+ Request message active access to the specified access realm.
+ Acvtive access lets a client get create and delete resources in
+ the realm.
+ </doc>
+ </field>
+ <field name="write" type="bit">
+ request write access
+ <doc>
+ Request write access to the specified access realm. Write access
+ lets a client publish messages to all exchanges in the realm.
+ </doc>
+ </field>
+ <field name="read" type="bit">
+ request read access
+ <doc>
+ Request read access to the specified access realm. Read access
+ lets a client consume messages from queues in the realm.
+ </doc>
+ </field>
+ </method>
+ <method name="request-ok" synchronous="1" index="11">
+ grant access to server resources
+ <doc>
+ This method provides the client with an access ticket. The access
+ ticket is valid within the current channel and for the lifespan of
+ the channel.
+ </doc>
+ <rule implement="MUST">
+ The client MUST NOT use access tickets except within the same
+ channel as originally granted.
+ </rule>
+ <rule implement="MUST">
+ The server MUST isolate access tickets per channel and treat an
+ attempt by a client to mix these as a connection exception.
+ </rule>
+ <chassis name="client" implement="MUST"/>
+ <field name="ticket" domain="access ticket"/>
+ </method>
+ </class>
+ <class name="exchange" handler="channel" index="40">
+ <!--
+======================================================
+== EXCHANGES (or "routers", if you prefer)
+== (Or matchers, plugins, extensions, agents,... Routing is just one of
+== the many fun things an exchange can do.)
+======================================================
+-->
+ work with exchanges
+<doc>
+ Exchanges match and distribute messages across queues. Exchanges can be
+ configured in the server or created at runtime.
+</doc>
+ <doc name="grammar">
+ exchange = C:DECLARE S:DECLARE-OK
+ / C:DELETE S:DELETE-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <rule implement="MUST">
+ <test>amq_exchange_19</test>
+ The server MUST implement the direct and fanout exchange types, and
+ predeclare the corresponding exchanges named amq.direct and amq.fanout
+ in each virtual host. The server MUST also predeclare a direct
+ exchange to act as the default exchange for content Publish methods
+ and for default queue bindings.
+</rule>
+ <rule implement="SHOULD">
+ <test>amq_exchange_20</test>
+ The server SHOULD implement the topic exchange type, and predeclare
+ the corresponding exchange named amq.topic in each virtual host.
+</rule>
+ <rule implement="MAY">
+ <test>amq_exchange_21</test>
+ The server MAY implement the system exchange type, and predeclare the
+ corresponding exchanges named amq.system in each virtual host. If the
+ client attempts to bind a queue to the system exchange, the server
+ MUST raise a connection exception with reply code 507 (not allowed).
+</rule>
+ <rule implement="MUST">
+ <test>amq_exchange_22</test>
+ The default exchange MUST be defined as internal, and be inaccessible
+ to the client except by specifying an empty exchange name in a content
+ Publish method. That is, the server MUST NOT let clients make explicit
+ bindings to this exchange.
+</rule>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="declare" synchronous="1" index="10">
+ declare exchange, create if needed
+ <doc>
+ This method creates an exchange if it does not already exist, and if the
+ exchange exists, verifies that it is of the correct and expected class.
+ </doc>
+ <rule implement="SHOULD">
+ <test>amq_exchange_23</test>
+ The server SHOULD support a minimum of 16 exchanges per virtual host
+ and ideally, impose no limit except as defined by available resources.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="declare-ok"/>
+ <field name="ticket" domain="access ticket">
+ <doc>
+ When a client defines a new exchange, this belongs to the access realm
+ of the ticket used. All further work done with that exchange must be
+ done with an access ticket for the same realm.
+ </doc>
+ <rule implement="MUST">
+ The client MUST provide a valid access ticket giving "active" access
+ to the realm in which the exchange exists or will be created, or
+ "passive" access if the if-exists flag is set.
+ </rule>
+ </field>
+ <field name="exchange" domain="exchange name">
+ <rule implement="MUST">
+ <test>amq_exchange_15</test>
+ Exchange names starting with "amq." are reserved for predeclared
+ and standardised exchanges. If the client attempts to create an
+ exchange starting with "amq.", the server MUST raise a channel
+ exception with reply code 403 (access refused).
+ </rule>
+ <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
+ </field>
+ <field name="type" type="shortstr">
+ exchange type
+ <doc>
+ Each exchange belongs to one of a set of exchange types implemented
+ by the server. The exchange types define the functionality of the
+ exchange - i.e. how messages are routed through it. It is not valid
+ or meaningful to attempt to change the type of an existing exchange.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_exchange_16</test>
+ If the exchange already exists with a different type, the server
+ MUST raise a connection exception with a reply code 507 (not allowed).
+ </rule>
+ <rule implement="MUST">
+ <test>amq_exchange_18</test>
+ If the server does not support the requested exchange type it MUST
+ raise a connection exception with a reply code 503 (command invalid).
+ </rule>
+ <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
+ </field>
+ <field name="passive" type="bit">
+ do not create exchange
+ <doc>
+ If set, the server will not create the exchange. The client can use
+ this to check whether an exchange exists without modifying the server
+ state.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_exchange_05</test>
+ If set, and the exchange does not already exist, the server MUST
+ raise a channel exception with reply code 404 (not found).
+ </rule>
+ </field>
+ <field name="durable" type="bit">
+ request a durable exchange
+ <doc>
+ If set when creating a new exchange, the exchange will be marked as
+ durable. Durable exchanges remain active when a server restarts.
+ Non-durable exchanges (transient exchanges) are purged if/when a
+ server restarts.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_exchange_24</test>
+ The server MUST support both durable and transient exchanges.
+ </rule>
+ <rule implement="MUST">
+ The server MUST ignore the durable field if the exchange already
+ exists.
+ </rule>
+ </field>
+ <field name="auto delete" type="bit">
+ auto-delete when unused
+ <doc>
+ If set, the exchange is deleted when all queues have finished
+ using it.
+ </doc>
+ <rule implement="SHOULD">
+ <test>amq_exchange_02</test>
+ The server SHOULD allow for a reasonable delay between the point
+ when it determines that an exchange is not being used (or no longer
+ used), and the point when it deletes the exchange. At the least it
+ must allow a client to create an exchange and then bind a queue to
+ it, with a small but non-zero delay between these two actions.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_exchange_25</test>
+ The server MUST ignore the auto-delete field if the exchange already
+ exists.
+ </rule>
+ </field>
+ <field name="internal" type="bit">
+ create internal exchange
+ <doc>
+ If set, the exchange may not be used directly by publishers, but
+ only when bound to other exchanges. Internal exchanges are used to
+ construct wiring that is not visible to applications.
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+
+ <field name="arguments" type="table">
+ arguments for declaration
+ <doc>
+ A set of arguments for the declaration. The syntax and semantics
+ of these arguments depends on the server implementation. This
+ field is ignored if passive is 1.
+ </doc>
+ </field>
+ </method>
+ <method name="declare-ok" synchronous="1" index="11">
+ confirms an exchange declaration
+ <doc>
+ This method confirms a Declare method and confirms the name of the
+ exchange, essential for automatically-named exchanges.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="delete" synchronous="1" index="20">
+ delete an exchange
+ <doc>
+ This method deletes an exchange. When an exchange is deleted all queue
+ bindings on the exchange are cancelled.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <response name="delete-ok"/>
+ <field name="ticket" domain="access ticket">
+ <rule implement="MUST">
+ The client MUST provide a valid access ticket giving "active"
+ access rights to the exchange's access realm.
+ </rule>
+ </field>
+ <field name="exchange" domain="exchange name">
+ <rule implement="MUST">
+ <test>amq_exchange_11</test>
+ The exchange MUST exist. Attempting to delete a non-existing exchange
+ causes a channel exception.
+ </rule>
+ <assert check="notnull"/>
+ </field>
+ <field name="if unused" type="bit">
+ delete only if unused
+ <doc>
+ If set, the server will only delete the exchange if it has no queue
+ bindings. If the exchange has queue bindings the server does not
+ delete it but raises a channel exception instead.
+ </doc>
+ <rule implement="SHOULD">
+ <test>amq_exchange_12</test>
+ If set, the server SHOULD delete the exchange but only if it has
+ no queue bindings.
+ </rule>
+ <rule implement="SHOULD">
+ <test>amq_exchange_13</test>
+ If set, the server SHOULD raise a channel exception if the exchange is in
+ use.
+ </rule>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+
+ </method>
+ <method name="delete-ok" synchronous="1" index="21">
+ confirm deletion of an exchange
+ <doc>
+ This method confirms the deletion of an exchange.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ </class>
+ <class name="queue" handler="channel" index="50">
+ <!--
+======================================================
+== QUEUES
+======================================================
+-->
+ work with queues
+
+<doc>
+ Queues store and forward messages. Queues can be configured in the server
+ or created at runtime. Queues must be attached to at least one exchange
+ in order to receive messages from publishers.
+</doc>
+ <doc name="grammar">
+ queue = C:DECLARE S:DECLARE-OK
+ / C:BIND S:BIND-OK
+ / C:PURGE S:PURGE-OK
+ / C:DELETE S:DELETE-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="MUST"/>
+ <rule implement="MUST">
+ <test>amq_queue_33</test>
+ A server MUST allow any content class to be sent to any queue, in any
+ mix, and queue and delivery these content classes independently. Note
+ that all methods that fetch content off queues are specific to a given
+ content class.
+</rule>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="declare" synchronous="1" index="10">
+ declare queue, create if needed
+ <doc>
+ This method creates or checks a queue. When creating a new queue
+ the client can specify various properties that control the durability
+ of the queue and its contents, and the level of sharing for the queue.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_34</test>
+ The server MUST create a default binding for a newly-created queue
+ to the default exchange, which is an exchange of type 'direct'.
+ </rule>
+ <rule implement="SHOULD">
+ <test>amq_queue_35</test>
+ The server SHOULD support a minimum of 256 queues per virtual host
+ and ideally, impose no limit except as defined by available resources.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="declare-ok"/>
+ <field name="ticket" domain="access ticket">
+ <doc>
+ When a client defines a new queue, this belongs to the access realm
+ of the ticket used. All further work done with that queue must be
+ done with an access ticket for the same realm.
+ </doc>
+ <doc>
+ The client provides a valid access ticket giving "active" access
+ to the realm in which the queue exists or will be created, or
+ "passive" access if the if-exists flag is set.
+ </doc>
+ </field>
+ <field name="queue" domain="queue name">
+ <rule implement="MAY">
+ <test>amq_queue_10</test>
+ The queue name MAY be empty, in which case the server MUST create
+ a new queue with a unique generated name and return this to the
+ client in the Declare-Ok method.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_32</test>
+ Queue names starting with "amq." are reserved for predeclared and
+ standardised server queues. If the queue name starts with "amq."
+ and the passive option is zero, the server MUST raise a connection
+ exception with reply code 403 (access refused).
+ </rule>
+ <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
+ </field>
+ <field name="passive" type="bit">
+ do not create queue
+ <doc>
+ If set, the server will not create the queue. The client can use
+ this to check whether a queue exists without modifying the server
+ state.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_05</test>
+ If set, and the queue does not already exist, the server MUST
+ respond with a reply code 404 (not found) and raise a channel
+ exception.
+ </rule>
+ </field>
+ <field name="durable" type="bit">
+ request a durable queue
+ <doc>
+ If set when creating a new queue, the queue will be marked as
+ durable. Durable queues remain active when a server restarts.
+ Non-durable queues (transient queues) are purged if/when a
+ server restarts. Note that durable queues do not necessarily
+ hold persistent messages, although it does not make sense to
+ send persistent messages to a transient queue.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_03</test>
+ The server MUST recreate the durable queue after a restart.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_36</test>
+ The server MUST support both durable and transient queues.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_37</test>
+ The server MUST ignore the durable field if the queue already
+ exists.
+ </rule>
+ </field>
+ <field name="exclusive" type="bit">
+ request an exclusive queue
+ <doc>
+ Exclusive queues may only be consumed from by the current connection.
+ Setting the 'exclusive' flag always implies 'auto-delete'.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_38</test>
+ The server MUST support both exclusive (private) and non-exclusive
+ (shared) queues.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_04</test>
+ The server MUST raise a channel exception if 'exclusive' is specified
+ and the queue already exists and is owned by a different connection.
+ </rule>
+ </field>
+ <field name="auto delete" type="bit">
+ auto-delete queue when unused
+ <doc>
+ If set, the queue is deleted when all consumers have finished
+ using it. Last consumer can be cancelled either explicitly or because
+ its channel is closed. If there was no consumer ever on the queue, it
+ won't be deleted.
+ </doc>
+ <rule implement="SHOULD">
+ <test>amq_queue_02</test>
+ The server SHOULD allow for a reasonable delay between the point
+ when it determines that a queue is not being used (or no longer
+ used), and the point when it deletes the queue. At the least it
+ must allow a client to create a queue and then create a consumer
+ to read from it, with a small but non-zero delay between these
+ two actions. The server should equally allow for clients that may
+ be disconnected prematurely, and wish to re-consume from the same
+ queue without losing messages. We would recommend a configurable
+ timeout, with a suitable default value being one minute.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_31</test>
+ The server MUST ignore the auto-delete field if the queue already
+ exists.
+ </rule>
+ </field>
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+
+ <field name="arguments" type="table">
+ arguments for declaration
+ <doc>
+ A set of arguments for the declaration. The syntax and semantics
+ of these arguments depends on the server implementation. This
+ field is ignored if passive is 1.
+ </doc>
+ </field>
+ </method>
+ <method name="declare-ok" synchronous="1" index="11">
+ confirms a queue definition
+ <doc>
+ This method confirms a Declare method and confirms the name of the
+ queue, essential for automatically-named queues.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <field name="queue" domain="queue name">
+ <doc>
+ Reports the name of the queue. If the server generated a queue
+ name, this field contains that name.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ <field name="message count" type="long">
+ number of messages in queue
+ <doc>
+ Reports the number of messages in the queue, which will be zero
+ for newly-created queues.
+ </doc>
+ </field>
+ <field name="consumer count" type="long">
+ number of consumers
+ <doc>
+ Reports the number of active consumers for the queue. Note that
+ consumers can suspend activity (Channel.Flow) in which case they
+ do not appear in this count.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="bind" synchronous="1" index="20">
+ bind queue to an exchange
+ <doc>
+ This method binds a queue to an exchange. Until a queue is
+ bound it will not receive any messages. In a classic messaging
+ model, store-and-forward queues are bound to a dest exchange
+ and subscription queues are bound to a dest_wild exchange.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_25</test>
+ A server MUST allow ignore duplicate bindings - that is, two or
+ more bind methods for a specific queue, with identical arguments
+ - without treating these as an error.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_39</test>
+ If a bind fails, the server MUST raise a connection exception.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_12</test>
+ The server MUST NOT allow a durable queue to bind to a transient
+ exchange. If the client attempts this the server MUST raise a
+ channel exception.
+ </rule>
+ <rule implement="SHOULD">
+ <test>amq_queue_13</test>
+ Bindings for durable queues are automatically durable and the
+ server SHOULD restore such bindings after a server restart.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_17</test>
+ If the client attempts to an exchange that was declared as internal,
+ the server MUST raise a connection exception with reply code 530
+ (not allowed).
+ </rule>
+ <rule implement="SHOULD">
+ <test>amq_queue_40</test>
+ The server SHOULD support at least 4 bindings per queue, and
+ ideally, impose no limit except as defined by available resources.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="bind-ok"/>
+ <field name="ticket" domain="access ticket">
+ <doc>
+ The client provides a valid access ticket giving "active"
+ access rights to the queue's access realm.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to bind. If the queue name is
+ empty, refers to the current queue for the channel, which is
+ the last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue
+ name in this method is empty, the server MUST raise a connection
+ exception with reply code 530 (not allowed).
+ </doc>
+ <doc name = "rule" test = "amq_queue_26">
+ If the queue does not exist the server MUST raise a channel exception
+ with reply code 404 (not found).
+ </doc>
+ </field>
+
+ <field name="exchange" domain="exchange name">
+ The name of the exchange to bind to.
+ <rule implement="MUST">
+ <test>amq_queue_14</test>
+ If the exchange does not exist the server MUST raise a channel
+ exception with reply code 404 (not found).
+ </rule>
+ </field>
+ <field name="routing key" type="shortstr">
+ message routing key
+ <doc>
+ Specifies the routing key for the binding. The routing key is
+ used for routing messages depending on the exchange configuration.
+ Not all exchanges use a routing key - refer to the specific
+ exchange documentation. If the routing key is empty and the queue
+ name is empty, the routing key will be the current queue for the
+ channel, which is the last declared queue.
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+
+ <field name="arguments" type="table">
+ arguments for binding
+ <doc>
+ A set of arguments for the binding. The syntax and semantics of
+ these arguments depends on the exchange class.
+ </doc>
+ </field>
+ </method>
+ <method name="bind-ok" synchronous="1" index="21">
+ confirm bind successful
+ <doc>
+ This method confirms that the bind was successful.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="purge" synchronous="1" index="30">
+ purge a queue
+ <doc>
+ This method removes all messages from a queue. It does not cancel
+ consumers. Purged messages are deleted without any formal "undo"
+ mechanism.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_15</test>
+ A call to purge MUST result in an empty queue.
+ </rule>
+ <rule implement="MUST">
+ <test>amq_queue_41</test>
+ On transacted channels the server MUST not purge messages that have
+ already been sent to a client but not yet acknowledged.
+ </rule>
+ <rule implement="MAY">
+ <test>amq_queue_42</test>
+ The server MAY implement a purge queue or log that allows system
+ administrators to recover accidentally-purged messages. The server
+ SHOULD NOT keep purged messages in the same storage spaces as the
+ live messages since the volumes of purged messages may get very
+ large.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="purge-ok"/>
+ <field name="ticket" domain="access ticket">
+ <doc>
+ The access ticket must be for the access realm that holds the
+ queue.
+ </doc>
+ <rule implement="MUST">
+ The client MUST provide a valid access ticket giving "read" access
+ rights to the queue's access realm. Note that purging a queue is
+ equivalent to reading all messages and discarding them.
+ </rule>
+ </field>
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to purge. If the queue name is
+ empty, refers to the current queue for the channel, which is
+ the last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue
+ name in this method is empty, the server MUST raise a connection
+ exception with reply code 530 (not allowed).
+ </doc>
+ <doc name = "rule" test = "amq_queue_16">
+ The queue must exist. Attempting to purge a non-existing queue
+ causes a channel exception.
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+ </method>
+ <method name="purge-ok" synchronous="1" index="31">
+ confirms a queue purge
+ <doc>
+ This method confirms the purge of a queue.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <field name="message count" type="long">
+ number of messages purged
+ <doc>
+ Reports the number of messages purged.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="delete" synchronous="1" index="40">
+ delete a queue
+ <doc>
+ This method deletes a queue. When a queue is deleted any pending
+ messages are sent to a dead-letter queue if this is defined in the
+ server configuration, and all consumers on the queue are cancelled.
+ </doc>
+ <rule implement="SHOULD">
+ <test>amq_queue_43</test>
+ The server SHOULD use a dead-letter queue to hold messages that
+ were pending on a deleted queue, and MAY provide facilities for
+ a system administrator to move these messages back to an active
+ queue.
+ </rule>
+ <chassis name="server" implement="MUST"/>
+ <response name="delete-ok"/>
+ <field name="ticket" domain="access ticket">
+ <doc>
+ The client provides a valid access ticket giving "active"
+ access rights to the queue's access realm.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to delete. If the queue name is
+ empty, refers to the current queue for the channel, which is the
+ last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue
+ name in this method is empty, the server MUST raise a connection
+ exception with reply code 530 (not allowed).
+ </doc>
+ <doc name = "rule" test = "amq_queue_21">
+ The queue must exist. Attempting to delete a non-existing queue
+ causes a channel exception.
+ </doc>
+ </field>
+
+ <field name="if unused" type="bit">
+ delete only if unused
+ <doc>
+ If set, the server will only delete the queue if it has no
+ consumers. If the queue has consumers the server does does not
+ delete it but raises a channel exception instead.
+ </doc>
+ <rule implement="MUST">
+ <test>amq_queue_29</test>
+ <test>amq_queue_30</test>
+ The server MUST respect the if-unused flag when deleting a queue.
+ </rule>
+ </field>
+ <field name="if empty" type="bit">
+ delete only if empty
+ <test>amq_queue_27</test>
+ <doc>
+ If set, the server will only delete the queue if it has no
+ messages. If the queue is not empty the server raises a channel
+ exception.
+ </doc>
+ </field>
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+ </method>
+
+ <method name="delete-ok" synchronous="1" index="41">
+ confirm deletion of a queue
+ <doc>
+ This method confirms the deletion of a queue.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <field name="message count" type="long">
+ number of messages purged
+ <doc>
+ Reports the number of messages purged.
+ </doc>
+ </field>
+ </method>
+ </class>
+ <class name="basic" handler="channel" index="60">
+ <!--
+======================================================
+== BASIC MIDDLEWARE
+======================================================
+-->
+ work with basic content
+<doc>
+ The Basic class provides methods that support an industry-standard
+ messaging model.
+</doc>
+
+<doc name = "grammar">
+ basic = C:QOS S:QOS-OK
+ / C:CONSUME S:CONSUME-OK
+ / C:CANCEL S:CANCEL-OK
+ / C:PUBLISH content
+ / S:RETURN content
+ / S:DELIVER content
+ / C:GET ( S:GET-OK content / S:GET-EMPTY )
+ / C:ACK
+ / C:REJECT
+</doc>
+
+<chassis name = "server" implement = "MUST" />
+<chassis name = "client" implement = "MAY" />
+
+<doc name = "rule" test = "amq_basic_08">
+ The server SHOULD respect the persistent property of basic messages
+ and SHOULD make a best-effort to hold persistent basic messages on a
+ reliable storage mechanism.
+</doc>
+<doc name = "rule" test = "amq_basic_09">
+ The server MUST NOT discard a persistent basic message in case of a
+ queue overflow. The server MAY use the Channel.Flow method to slow
+ or stop a basic message publisher when necessary.
+</doc>
+<doc name = "rule" test = "amq_basic_10">
+ The server MAY overflow non-persistent basic messages to persistent
+ storage and MAY discard or dead-letter non-persistent basic messages
+ on a priority basis if the queue size exceeds some configured limit.
+</doc>
+<doc name = "rule" test = "amq_basic_11">
+ The server MUST implement at least 2 priority levels for basic
+ messages, where priorities 0-4 and 5-9 are treated as two distinct
+ levels. The server MAY implement up to 10 priority levels.
+</doc>
+<doc name = "rule" test = "amq_basic_12">
+ The server MUST deliver messages of the same priority in order
+ irrespective of their individual persistence.
+</doc>
+<doc name = "rule" test = "amq_basic_13">
+ The server MUST support both automatic and explicit acknowledgements
+ on Basic content.
+</doc>
+
+<!-- These are the properties for a Basic content -->
+
+<field name = "content type" type = "shortstr">
+ MIME content type
+</field>
+<field name = "content encoding" type = "shortstr">
+ MIME content encoding
+</field>
+<field name = "headers" type = "table">
+ Message header field table
+</field>
+<field name = "delivery mode" type = "octet">
+ Non-persistent (1) or persistent (2)
+</field>
+<field name = "priority" type = "octet">
+ The message priority, 0 to 9
+</field>
+<field name = "correlation id" type = "shortstr">
+ The application correlation identifier
+</field>
+<field name = "reply to" type = "shortstr">
+ The destination to reply to
+</field>
+<field name = "expiration" type = "shortstr">
+ Message expiration specification
+</field>
+<field name = "message id" type = "shortstr">
+ The application message identifier
+</field>
+<field name = "timestamp" type = "timestamp">
+ The message timestamp
+</field>
+<field name = "type" type = "shortstr">
+ The message type name
+</field>
+<field name = "user id" type = "shortstr">
+ The creating user id
+</field>
+<field name = "app id" type = "shortstr">
+ The creating application id
+</field>
+<field name = "cluster id" type = "shortstr">
+ Intra-cluster routing identifier
+</field>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "qos" synchronous = "1" index = "10">
+ specify quality of service
+ <doc>
+ This method requests a specific quality of service. The QoS can
+ be specified for the current channel or for all channels on the
+ connection. The particular properties and semantics of a qos method
+ always depend on the content class semantics. Though the qos method
+ could in principle apply to both peers, it is currently meaningful
+ only for the server.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "qos-ok" />
+
+ <field name = "prefetch size" type = "long">
+ prefetch window in octets
+ <doc>
+ The client can request that messages be sent in advance so that
+ when the client finishes processing a message, the following
+ message is already held locally, rather than needing to be sent
+ down the channel. Prefetching gives a performance improvement.
+ This field specifies the prefetch window size in octets. The
+ server will send a message in advance if it is equal to or
+ smaller in size than the available prefetch size (and also falls
+ into other prefetch limits). May be set to zero, meaning "no
+ specific limit", although other prefetch limits may still apply.
+ The prefetch-size is ignored if the no-ack option is set.
+ </doc>
+ <doc name = "rule" test = "amq_basic_17">
+ The server MUST ignore this setting when the client is not
+ processing any messages - i.e. the prefetch size does not limit
+ the transfer of single messages to a client, only the sending in
+ advance of more messages while the client still has one or more
+ unacknowledged messages.
+ </doc>
+ </field>
+
+ <field name = "prefetch count" type = "short">
+ prefetch window in messages
+ <doc>
+ Specifies a prefetch window in terms of whole messages. This
+ field may be used in combination with the prefetch-size field;
+ a message will only be sent in advance if both prefetch windows
+ (and those at the channel and connection level) allow it.
+ The prefetch-count is ignored if the no-ack option is set.
+ </doc>
+ <doc name = "rule" test = "amq_basic_18">
+ The server MAY send less data in advance than allowed by the
+ client's specified prefetch windows but it MUST NOT send more.
+ </doc>
+ </field>
+
+ <field name = "global" type = "bit">
+ apply to entire connection
+ <doc>
+ By default the QoS settings apply to the current channel only. If
+ this field is set, they are applied to the entire connection.
+ </doc>
+ </field>
+</method>
+
+<method name = "qos-ok" synchronous = "1" index = "11">
+ confirm the requested qos
+ <doc>
+ This method tells the client that the requested QoS levels could
+ be handled by the server. The requested QoS applies to all active
+ consumers until a new QoS is defined.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "consume" synchronous = "1" index = "20">
+ start a queue consumer
+ <doc>
+ This method asks the server to start a "consumer", which is a
+ transient request for messages from a specific queue. Consumers
+ last as long as the channel they were created on, or until the
+ client cancels them.
+ </doc>
+ <doc name = "rule" test = "amq_basic_01">
+ The server SHOULD support at least 16 consumers per queue, unless
+ the queue was declared as private, and ideally, impose no limit
+ except as defined by available resources.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "consume-ok" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "read" access
+ rights to the realm for the queue.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to consume from. If the queue name
+ is null, refers to the current queue for the channel, which is the
+ last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue name
+ in this method is empty, the server MUST raise a connection exception
+ with reply code 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Specifies the identifier for the consumer. The consumer tag is
+ local to a connection, so two clients can use the same consumer
+ tags. If this field is empty the server will generate a unique
+ tag.
+ </doc>
+ <doc name = "rule" test = "todo">
+ The tag MUST NOT refer to an existing consumer. If the client
+ attempts to create two consumers with the same non-empty tag
+ the server MUST raise a connection exception with reply code
+ 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "no local" domain = "no local" />
+
+ <field name = "no ack" domain = "no ack" />
+
+ <field name = "exclusive" type = "bit">
+ request exclusive access
+ <doc>
+ Request exclusive consumer access, meaning only this consumer can
+ access the queue.
+ </doc>
+ <doc name = "rule" test = "amq_basic_02">
+ If the server cannot grant exclusive access to the queue when asked,
+ - because there are other consumers active - it MUST raise a channel
+ exception with return code 403 (access refused).
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+<method name = "consume-ok" synchronous = "1" index = "21">
+ confirm a new consumer
+ <doc>
+ The server provides the client with a consumer tag, which is used
+ by the client for methods called on the consumer at a later stage.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Holds the consumer tag specified by the client or provided by
+ the server.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "cancel" synchronous = "1" index = "30">
+ end a queue consumer
+ <doc test = "amq_basic_04">
+ This method cancels a consumer. This does not affect already
+ delivered messages, but it does mean the server will not send any
+ more messages for that consumer. The client may receive an
+ abitrary number of messages in between sending the cancel method
+ and receiving the cancel-ok reply.
+ </doc>
+ <doc name = "rule" test = "todo">
+ If the queue no longer exists when the client sends a cancel command,
+ or the consumer has been cancelled for other reasons, this command
+ has no effect.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "cancel-ok" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+<method name = "cancel-ok" synchronous = "1" index = "31">
+ confirm a cancelled consumer
+ <doc>
+ This method confirms that the cancellation was completed.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "publish" content = "1" index = "40">
+ publish a message
+ <doc>
+ This method publishes a message to a specific exchange. The message
+ will be routed to queues as defined by the exchange configuration
+ and distributed to any active consumers when the transaction, if any,
+ is committed.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "write"
+ access rights to the access realm for the exchange.
+ </doc>
+ </field>
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange to publish to. The exchange
+ name can be empty, meaning the default exchange. If the exchange
+ name is specified, and that exchange does not exist, the server
+ will raise a channel exception.
+ </doc>
+ <doc name = "rule" test = "amq_basic_06">
+ The server MUST accept a blank exchange name to mean the default
+ exchange.
+ </doc>
+ <doc name = "rule" test = "amq_basic_14">
+ If the exchange was declared as an internal exchange, the server
+ MUST raise a channel exception with a reply code 403 (access
+ refused).
+ </doc>
+ <doc name = "rule" test = "amq_basic_15">
+ The exchange MAY refuse basic content in which case it MUST raise
+ a channel exception with reply code 540 (not implemented).
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key for the message. The routing key is
+ used for routing messages depending on the exchange configuration.
+ </doc>
+ </field>
+
+ <field name = "mandatory" type = "bit">
+ indicate mandatory routing
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue. If this flag is set, the server will return an
+ unroutable message with a Return method. If this flag is zero, the
+ server silently drops the message.
+ </doc>
+ <doc name = "rule" test = "amq_basic_07">
+ The server SHOULD implement the mandatory flag.
+ </doc>
+ </field>
+
+ <field name = "immediate" type = "bit">
+ request immediate delivery
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue consumer immediately. If this flag is set, the
+ server will return an undeliverable message with a Return method.
+ If this flag is zero, the server will queue the message, but with
+ no guarantee that it will ever be consumed.
+ </doc>
+ <doc name = "rule" test = "amq_basic_16">
+ The server SHOULD implement the immediate flag.
+ </doc>
+ </field>
+</method>
+
+<method name = "return" content = "1" index = "50">
+ return a failed message
+ <doc>
+ This method returns an undeliverable message that was published
+ with the "immediate" flag set, or an unroutable message published
+ with the "mandatory" flag set. The reply code and text provide
+ information about the reason that the message was undeliverable.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "reply code" domain = "reply code" />
+ <field name = "reply text" domain = "reply text" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was
+ originally published to.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "deliver" content = "1" index = "60">
+ notify the client of a consumer message
+ <doc>
+ This method delivers a message to the client, via a consumer. In
+ the asynchronous message delivery model, the client starts a
+ consumer using the Consume method, then the server responds with
+ Deliver methods as and when messages arrive for that consumer.
+ </doc>
+ <doc name = "rule" test = "amq_basic_19">
+ The server SHOULD track the number of times a message has been
+ delivered to clients and when a message is redelivered a certain
+ number of times - e.g. 5 times - without being acknowledged, the
+ server SHOULD consider the message to be unprocessable (possibly
+ causing client applications to abort), and move the message to a
+ dead letter queue.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "redelivered" domain = "redelivered" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was
+ originally published to.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "get" synchronous = "1" index = "70">
+ direct access to a queue
+ <doc>
+ This method provides a direct access to the messages in a queue
+ using a synchronous dialogue that is designed for specific types of
+ application where synchronous functionality is more important than
+ performance.
+ </doc>
+ <response name = "get-ok" />
+ <response name = "get-empty" />
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "read"
+ access rights to the realm for the queue.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to consume from. If the queue name
+ is null, refers to the current queue for the channel, which is the
+ last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue name
+ in this method is empty, the server MUST raise a connection exception
+ with reply code 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "no ack" domain = "no ack" />
+</method>
+
+<method name = "get-ok" synchronous = "1" content = "1" index = "71">
+ provide client with a message
+ <doc>
+ This method delivers a message to the client following a get
+ method. A message delivered by 'get-ok' must be acknowledged
+ unless the no-ack option was set in the get method.
+ </doc>
+ <chassis name = "client" implement = "MAY" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "redelivered" domain = "redelivered" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was originally
+ published to. If empty, the message was published to the default
+ exchange.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+
+ <field name = "message count" type = "long" >
+ number of messages pending
+ <doc>
+ This field reports the number of messages pending on the queue,
+ excluding the message being delivered. Note that this figure is
+ indicative, not reliable, and can change arbitrarily as messages
+ are added to the queue and removed by other clients.
+ </doc>
+ </field>
+</method>
+
+
+<method name = "get-empty" synchronous = "1" index = "72">
+ indicate no messages available
+ <doc>
+ This method tells the client that the queue has no messages
+ available for the client.
+ </doc>
+ <chassis name = "client" implement = "MAY" />
+
+ <field name = "cluster id" type = "shortstr">
+ Cluster id
+ <doc>
+ For use by cluster applications, should not be used by
+ client applications.
+ </doc>
+ </field>
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "ack" index = "80">
+ acknowledge one or more messages
+ <doc>
+ This method acknowledges one or more messages delivered via the
+ Deliver or Get-Ok methods. The client can ask to confirm a
+ single message or a set of messages up to and including a specific
+ message.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "multiple" type = "bit">
+ acknowledge multiple messages
+ <doc>
+ If set to 1, the delivery tag is treated as "up to and including",
+ so that the client can acknowledge multiple messages with a single
+ method. If set to zero, the delivery tag refers to a single
+ message. If the multiple field is 1, and the delivery tag is zero,
+ tells the server to acknowledge all outstanding mesages.
+ </doc>
+ <doc name = "rule" test = "amq_basic_20">
+ The server MUST validate that a non-zero delivery-tag refers to an
+ delivered message, and raise a channel exception if this is not the
+ case.
+ </doc>
+ </field>
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "reject" index = "90">
+ reject an incoming message
+ <doc>
+ This method allows a client to reject a message. It can be used to
+ interrupt and cancel large incoming messages, or return untreatable
+ messages to their original queue.
+ </doc>
+ <doc name = "rule" test = "amq_basic_21">
+ The server SHOULD be capable of accepting and process the Reject
+ method while sending message content with a Deliver or Get-Ok
+ method. I.e. the server should read and process incoming methods
+ while sending output frames. To cancel a partially-send content,
+ the server sends a content body frame of size 1 (i.e. with no data
+ except the frame-end octet).
+ </doc>
+ <doc name = "rule" test = "amq_basic_22">
+ The server SHOULD interpret this method as meaning that the client
+ is unable to process the message at this time.
+ </doc>
+ <doc name = "rule">
+ A client MUST NOT use this method as a means of selecting messages
+ to process. A rejected message MAY be discarded or dead-lettered,
+ not necessarily passed to another client.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "requeue" type = "bit">
+ requeue the message
+ <doc>
+ If this field is zero, the message will be discarded. If this bit
+ is 1, the server will attempt to requeue the message.
+ </doc>
+ <doc name = "rule" test = "amq_basic_23">
+ The server MUST NOT deliver the message to the same client within
+ the context of the current channel. The recommended strategy is
+ to attempt to deliver the message to an alternative consumer, and
+ if that is not possible, to move the message to a dead-letter
+ queue. The server MAY use more sophisticated tracking to hold
+ the message on the queue and redeliver it to the same client at
+ a later stage.
+ </doc>
+ </field>
+</method>
+
+<method name = "recover" index = "100">
+ redeliver unacknowledged messages. This method is only allowed on non-transacted channels.
+ <doc>
+ This method asks the broker to redeliver all unacknowledged messages on a
+ specifieid channel. Zero or more messages may be redelivered.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "requeue" type = "bit">
+ requeue the message
+ <doc>
+ If this field is zero, the message will be redelivered to the original recipient. If this bit
+ is 1, the server will attempt to requeue the message, potentially then delivering it to an
+ alternative subscriber.
+ </doc>
+ </field>
+
+ <doc name="rule">
+ The server MUST set the redelivered flag on all messages that are resent.
+ </doc>
+ <doc name="rule">
+ The server MUST raise a channel exception if this is called on a transacted channel.
+ </doc>
+</method>
+
+
+</class>
+
+
+ <class name="file" handler="channel" index="70">
+ <!--
+======================================================
+== FILE TRANSFER
+======================================================
+-->
+ work with file content
+<doc>
+ The file class provides methods that support reliable file transfer.
+ File messages have a specific set of properties that are required for
+ interoperability with file transfer applications. File messages and
+ acknowledgements are subject to channel transactions. Note that the
+ file class does not provide message browsing methods; these are not
+ compatible with the staging model. Applications that need browsable
+ file transfer should use Basic content and the Basic class.
+</doc>
+
+<doc name = "grammar">
+ file = C:QOS S:QOS-OK
+ / C:CONSUME S:CONSUME-OK
+ / C:CANCEL S:CANCEL-OK
+ / C:OPEN S:OPEN-OK C:STAGE content
+ / S:OPEN C:OPEN-OK S:STAGE content
+ / C:PUBLISH
+ / S:DELIVER
+ / S:RETURN
+ / C:ACK
+ / C:REJECT
+</doc>
+
+<chassis name = "server" implement = "MAY" />
+<chassis name = "client" implement = "MAY" />
+
+<doc name = "rule">
+ The server MUST make a best-effort to hold file messages on a
+ reliable storage mechanism.
+</doc>
+<doc name = "rule">
+ The server MUST NOT discard a file message in case of a queue
+ overflow. The server MUST use the Channel.Flow method to slow or stop
+ a file message publisher when necessary.
+</doc>
+<doc name = "rule">
+ The server MUST implement at least 2 priority levels for file
+ messages, where priorities 0-4 and 5-9 are treated as two distinct
+ levels. The server MAY implement up to 10 priority levels.
+</doc>
+<doc name = "rule">
+ The server MUST support both automatic and explicit acknowledgements
+ on file content.
+</doc>
+
+<!-- These are the properties for a File content -->
+
+<field name = "content type" type = "shortstr">
+ MIME content type
+</field>
+<field name = "content encoding" type = "shortstr">
+ MIME content encoding
+</field>
+<field name = "headers" type = "table">
+ Message header field table
+</field>
+<field name = "priority" type = "octet">
+ The message priority, 0 to 9
+</field>
+<field name = "reply to" type = "shortstr">
+ The destination to reply to
+</field>
+<field name = "message id" type = "shortstr">
+ The application message identifier
+</field>
+<field name = "filename" type = "shortstr">
+ The message filename
+</field>
+<field name = "timestamp" type = "timestamp">
+ The message timestamp
+</field>
+<field name = "cluster id" type = "shortstr">
+ Intra-cluster routing identifier
+</field>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "qos" synchronous = "1" index = "10">
+ specify quality of service
+ <doc>
+ This method requests a specific quality of service. The QoS can
+ be specified for the current channel or for all channels on the
+ connection. The particular properties and semantics of a qos method
+ always depend on the content class semantics. Though the qos method
+ could in principle apply to both peers, it is currently meaningful
+ only for the server.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "qos-ok" />
+
+ <field name = "prefetch size" type = "long">
+ prefetch window in octets
+ <doc>
+ The client can request that messages be sent in advance so that
+ when the client finishes processing a message, the following
+ message is already held locally, rather than needing to be sent
+ down the channel. Prefetching gives a performance improvement.
+ This field specifies the prefetch window size in octets. May be
+ set to zero, meaning "no specific limit". Note that other
+ prefetch limits may still apply. The prefetch-size is ignored
+ if the no-ack option is set.
+ </doc>
+ </field>
+
+ <field name = "prefetch count" type = "short">
+ prefetch window in messages
+ <doc>
+ Specifies a prefetch window in terms of whole messages. This
+ is compatible with some file API implementations. This field
+ may be used in combination with the prefetch-size field; a
+ message will only be sent in advance if both prefetch windows
+ (and those at the channel and connection level) allow it.
+ The prefetch-count is ignored if the no-ack option is set.
+ </doc>
+ <doc name = "rule">
+ The server MAY send less data in advance than allowed by the
+ client's specified prefetch windows but it MUST NOT send more.
+ </doc>
+ </field>
+
+ <field name = "global" type = "bit">
+ apply to entire connection
+ <doc>
+ By default the QoS settings apply to the current channel only. If
+ this field is set, they are applied to the entire connection.
+ </doc>
+ </field>
+</method>
+
+<method name = "qos-ok" synchronous = "1" index = "11">
+ confirm the requested qos
+ <doc>
+ This method tells the client that the requested QoS levels could
+ be handled by the server. The requested QoS applies to all active
+ consumers until a new QoS is defined.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "consume" synchronous = "1" index = "20">
+ start a queue consumer
+ <doc>
+ This method asks the server to start a "consumer", which is a
+ transient request for messages from a specific queue. Consumers
+ last as long as the channel they were created on, or until the
+ client cancels them.
+ </doc>
+ <doc name = "rule">
+ The server SHOULD support at least 16 consumers per queue, unless
+ the queue was declared as private, and ideally, impose no limit
+ except as defined by available resources.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "consume-ok" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "read" access
+ rights to the realm for the queue.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to consume from. If the queue name
+ is null, refers to the current queue for the channel, which is the
+ last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue name
+ in this method is empty, the server MUST raise a connection exception
+ with reply code 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Specifies the identifier for the consumer. The consumer tag is
+ local to a connection, so two clients can use the same consumer
+ tags. If this field is empty the server will generate a unique
+ tag.
+ </doc>
+ <doc name = "rule" test = "todo">
+ The tag MUST NOT refer to an existing consumer. If the client
+ attempts to create two consumers with the same non-empty tag
+ the server MUST raise a connection exception with reply code
+ 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "no local" domain = "no local" />
+
+ <field name = "no ack" domain = "no ack" />
+
+ <field name = "exclusive" type = "bit">
+ request exclusive access
+ <doc>
+ Request exclusive consumer access, meaning only this consumer can
+ access the queue.
+ </doc>
+ <doc name = "rule" test = "amq_file_00">
+ If the server cannot grant exclusive access to the queue when asked,
+ - because there are other consumers active - it MUST raise a channel
+ exception with return code 405 (resource locked).
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+<method name = "consume-ok" synchronous = "1" index = "21">
+ confirm a new consumer
+ <doc>
+ This method provides the client with a consumer tag which it MUST
+ use in methods that work with the consumer.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Holds the consumer tag specified by the client or provided by
+ the server.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "cancel" synchronous = "1" index = "30">
+ end a queue consumer
+ <doc>
+ This method cancels a consumer. This does not affect already
+ delivered messages, but it does mean the server will not send any
+ more messages for that consumer.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "cancel-ok" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+<method name = "cancel-ok" synchronous = "1" index = "31">
+ confirm a cancelled consumer
+ <doc>
+ This method confirms that the cancellation was completed.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "open" synchronous = "1" index = "40">
+ request to start staging
+ <doc>
+ This method requests permission to start staging a message. Staging
+ means sending the message into a temporary area at the recipient end
+ and then delivering the message by referring to this temporary area.
+ Staging is how the protocol handles partial file transfers - if a
+ message is partially staged and the connection breaks, the next time
+ the sender starts to stage it, it can restart from where it left off.
+ </doc>
+ <response name = "open-ok" />
+ <chassis name = "server" implement = "MUST" />
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "identifier" type = "shortstr">
+ staging identifier
+ <doc>
+ This is the staging identifier. This is an arbitrary string chosen
+ by the sender. For staging to work correctly the sender must use
+ the same staging identifier when staging the same message a second
+ time after recovery from a failure. A good choice for the staging
+ identifier would be the SHA1 hash of the message properties data
+ (including the original filename, revised time, etc.).
+ </doc>
+ </field>
+
+ <field name = "content size" type = "longlong">
+ message content size
+ <doc>
+ The size of the content in octets. The recipient may use this
+ information to allocate or check available space in advance, to
+ avoid "disk full" errors during staging of very large messages.
+ </doc>
+ <doc name = "rule">
+ The sender MUST accurately fill the content-size field.
+ Zero-length content is permitted.
+ </doc>
+ </field>
+</method>
+
+<method name = "open-ok" synchronous = "1" index = "41">
+ confirm staging ready
+ <doc>
+ This method confirms that the recipient is ready to accept staged
+ data. If the message was already partially-staged at a previous
+ time the recipient will report the number of octets already staged.
+ </doc>
+ <response name = "stage" />
+ <chassis name = "server" implement = "MUST" />
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "staged size" type = "longlong">
+ already staged amount
+ <doc>
+ The amount of previously-staged content in octets. For a new
+ message this will be zero.
+ </doc>
+ <doc name = "rule">
+ The sender MUST start sending data from this octet offset in the
+ message, counting from zero.
+ </doc>
+ <doc name = "rule">
+ The recipient MAY decide how long to hold partially-staged content
+ and MAY implement staging by always discarding partially-staged
+ content. However if it uses the file content type it MUST support
+ the staging methods.
+ </doc>
+ </field>
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "stage" content = "1" index = "50">
+ stage message content
+ <doc>
+ This method stages the message, sending the message content to the
+ recipient from the octet offset specified in the Open-Ok method.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <chassis name = "client" implement = "MUST" />
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "publish" index = "60">
+ publish a message
+ <doc>
+ This method publishes a staged file message to a specific exchange.
+ The file message will be routed to queues as defined by the exchange
+ configuration and distributed to any active consumers when the
+ transaction, if any, is committed.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "write"
+ access rights to the access realm for the exchange.
+ </doc>
+ </field>
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange to publish to. The exchange
+ name can be empty, meaning the default exchange. If the exchange
+ name is specified, and that exchange does not exist, the server
+ will raise a channel exception.
+ </doc>
+ <doc name = "rule">
+ The server MUST accept a blank exchange name to mean the default
+ exchange.
+ </doc>
+ <doc name = "rule">
+ If the exchange was declared as an internal exchange, the server
+ MUST respond with a reply code 403 (access refused) and raise a
+ channel exception.
+ </doc>
+ <doc name = "rule">
+ The exchange MAY refuse file content in which case it MUST respond
+ with a reply code 540 (not implemented) and raise a channel
+ exception.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key for the message. The routing key is
+ used for routing messages depending on the exchange configuration.
+ </doc>
+ </field>
+
+ <field name = "mandatory" type = "bit">
+ indicate mandatory routing
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue. If this flag is set, the server will return an
+ unroutable message with a Return method. If this flag is zero, the
+ server silently drops the message.
+ </doc>
+ <doc name = "rule" test = "amq_file_00">
+ The server SHOULD implement the mandatory flag.
+ </doc>
+ </field>
+
+ <field name = "immediate" type = "bit">
+ request immediate delivery
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue consumer immediately. If this flag is set, the
+ server will return an undeliverable message with a Return method.
+ If this flag is zero, the server will queue the message, but with
+ no guarantee that it will ever be consumed.
+ </doc>
+ <doc name = "rule" test = "amq_file_00">
+ The server SHOULD implement the immediate flag.
+ </doc>
+ </field>
+
+ <field name = "identifier" type = "shortstr">
+ staging identifier
+ <doc>
+ This is the staging identifier of the message to publish. The
+ message must have been staged. Note that a client can send the
+ Publish method asynchronously without waiting for staging to
+ finish.
+ </doc>
+ </field>
+</method>
+
+<method name = "return" content = "1" index = "70">
+ return a failed message
+ <doc>
+ This method returns an undeliverable message that was published
+ with the "immediate" flag set, or an unroutable message published
+ with the "mandatory" flag set. The reply code and text provide
+ information about the reason that the message was undeliverable.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "reply code" domain = "reply code" />
+ <field name = "reply text" domain = "reply text" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was
+ originally published to.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "deliver" index = "80">
+ notify the client of a consumer message
+ <doc>
+ This method delivers a staged file message to the client, via a
+ consumer. In the asynchronous message delivery model, the client
+ starts a consumer using the Consume method, then the server
+ responds with Deliver methods as and when messages arrive for
+ that consumer.
+ </doc>
+ <doc name = "rule">
+ The server SHOULD track the number of times a message has been
+ delivered to clients and when a message is redelivered a certain
+ number of times - e.g. 5 times - without being acknowledged, the
+ server SHOULD consider the message to be unprocessable (possibly
+ causing client applications to abort), and move the message to a
+ dead letter queue.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "redelivered" domain = "redelivered" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was originally
+ published to.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+
+ <field name = "identifier" type = "shortstr">
+ staging identifier
+ <doc>
+ This is the staging identifier of the message to deliver. The
+ message must have been staged. Note that a server can send the
+ Deliver method asynchronously without waiting for staging to
+ finish.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "ack" index = "90">
+ acknowledge one or more messages
+ <doc>
+ This method acknowledges one or more messages delivered via the
+ Deliver method. The client can ask to confirm a single message or
+ a set of messages up to and including a specific message.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "multiple" type = "bit">
+ acknowledge multiple messages
+ <doc>
+ If set to 1, the delivery tag is treated as "up to and including",
+ so that the client can acknowledge multiple messages with a single
+ method. If set to zero, the delivery tag refers to a single
+ message. If the multiple field is 1, and the delivery tag is zero,
+ tells the server to acknowledge all outstanding mesages.
+ </doc>
+ <doc name = "rule">
+ The server MUST validate that a non-zero delivery-tag refers to an
+ delivered message, and raise a channel exception if this is not the
+ case.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "reject" index = "100">
+ reject an incoming message
+ <doc>
+ This method allows a client to reject a message. It can be used to
+ return untreatable messages to their original queue. Note that file
+ content is staged before delivery, so the client will not use this
+ method to interrupt delivery of a large message.
+ </doc>
+ <doc name = "rule">
+ The server SHOULD interpret this method as meaning that the client
+ is unable to process the message at this time.
+ </doc>
+ <doc name = "rule">
+ A client MUST NOT use this method as a means of selecting messages
+ to process. A rejected message MAY be discarded or dead-lettered,
+ not necessarily passed to another client.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "requeue" type = "bit">
+ requeue the message
+ <doc>
+ If this field is zero, the message will be discarded. If this bit
+ is 1, the server will attempt to requeue the message.
+ </doc>
+ <doc name = "rule">
+ The server MUST NOT deliver the message to the same client within
+ the context of the current channel. The recommended strategy is
+ to attempt to deliver the message to an alternative consumer, and
+ if that is not possible, to move the message to a dead-letter
+ queue. The server MAY use more sophisticated tracking to hold
+ the message on the queue and redeliver it to the same client at
+ a later stage.
+ </doc>
+ </field>
+</method>
+
+</class>
+
+ <class name="stream" handler="channel" index="80">
+ <!--
+======================================================
+== STREAMING
+======================================================
+-->
+ work with streaming content
+
+<doc>
+ The stream class provides methods that support multimedia streaming.
+ The stream class uses the following semantics: one message is one
+ packet of data; delivery is unacknowleged and unreliable; the consumer
+ can specify quality of service parameters that the server can try to
+ adhere to; lower-priority messages may be discarded in favour of high
+ priority messages.
+</doc>
+
+<doc name = "grammar">
+ stream = C:QOS S:QOS-OK
+ / C:CONSUME S:CONSUME-OK
+ / C:CANCEL S:CANCEL-OK
+ / C:PUBLISH content
+ / S:RETURN
+ / S:DELIVER content
+</doc>
+
+<chassis name = "server" implement = "MAY" />
+<chassis name = "client" implement = "MAY" />
+
+<doc name = "rule">
+ The server SHOULD discard stream messages on a priority basis if
+ the queue size exceeds some configured limit.
+</doc>
+<doc name = "rule">
+ The server MUST implement at least 2 priority levels for stream
+ messages, where priorities 0-4 and 5-9 are treated as two distinct
+ levels. The server MAY implement up to 10 priority levels.
+</doc>
+<doc name = "rule">
+ The server MUST implement automatic acknowledgements on stream
+ content. That is, as soon as a message is delivered to a client
+ via a Deliver method, the server must remove it from the queue.
+</doc>
+
+
+<!-- These are the properties for a Stream content -->
+
+<field name = "content type" type = "shortstr">
+ MIME content type
+</field>
+<field name = "content encoding" type = "shortstr">
+ MIME content encoding
+</field>
+<field name = "headers" type = "table">
+ Message header field table
+</field>
+<field name = "priority" type = "octet">
+ The message priority, 0 to 9
+</field>
+<field name = "timestamp" type = "timestamp">
+ The message timestamp
+</field>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "qos" synchronous = "1" index = "10">
+ specify quality of service
+ <doc>
+ This method requests a specific quality of service. The QoS can
+ be specified for the current channel or for all channels on the
+ connection. The particular properties and semantics of a qos method
+ always depend on the content class semantics. Though the qos method
+ could in principle apply to both peers, it is currently meaningful
+ only for the server.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "qos-ok" />
+
+ <field name = "prefetch size" type = "long">
+ prefetch window in octets
+ <doc>
+ The client can request that messages be sent in advance so that
+ when the client finishes processing a message, the following
+ message is already held locally, rather than needing to be sent
+ down the channel. Prefetching gives a performance improvement.
+ This field specifies the prefetch window size in octets. May be
+ set to zero, meaning "no specific limit". Note that other
+ prefetch limits may still apply.
+ </doc>
+ </field>
+
+ <field name = "prefetch count" type = "short">
+ prefetch window in messages
+ <doc>
+ Specifies a prefetch window in terms of whole messages. This
+ field may be used in combination with the prefetch-size field;
+ a message will only be sent in advance if both prefetch windows
+ (and those at the channel and connection level) allow it.
+ </doc>
+ </field>
+
+ <field name = "consume rate" type = "long">
+ transfer rate in octets/second
+ <doc>
+ Specifies a desired transfer rate in octets per second. This is
+ usually determined by the application that uses the streaming
+ data. A value of zero means "no limit", i.e. as rapidly as
+ possible.
+ </doc>
+ <doc name = "rule">
+ The server MAY ignore the prefetch values and consume rates,
+ depending on the type of stream and the ability of the server
+ to queue and/or reply it. The server MAY drop low-priority
+ messages in favour of high-priority messages.
+ </doc>
+ </field>
+
+ <field name = "global" type = "bit">
+ apply to entire connection
+ <doc>
+ By default the QoS settings apply to the current channel only. If
+ this field is set, they are applied to the entire connection.
+ </doc>
+ </field>
+</method>
+
+<method name = "qos-ok" synchronous = "1" index = "11">
+ confirm the requested qos
+ <doc>
+ This method tells the client that the requested QoS levels could
+ be handled by the server. The requested QoS applies to all active
+ consumers until a new QoS is defined.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "consume" synchronous = "1" index = "20">
+ start a queue consumer
+ <doc>
+ This method asks the server to start a "consumer", which is a
+ transient request for messages from a specific queue. Consumers
+ last as long as the channel they were created on, or until the
+ client cancels them.
+ </doc>
+ <doc name = "rule">
+ The server SHOULD support at least 16 consumers per queue, unless
+ the queue was declared as private, and ideally, impose no limit
+ except as defined by available resources.
+ </doc>
+ <doc name = "rule">
+ Streaming applications SHOULD use different channels to select
+ different streaming resolutions. AMQP makes no provision for
+ filtering and/or transforming streams except on the basis of
+ priority-based selective delivery of individual messages.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "consume-ok" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "read" access
+ rights to the realm for the queue.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue to consume from. If the queue name
+ is null, refers to the current queue for the channel, which is the
+ last declared queue.
+ </doc>
+ <doc name = "rule">
+ If the client did not previously declare a queue, and the queue name
+ in this method is empty, the server MUST raise a connection exception
+ with reply code 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Specifies the identifier for the consumer. The consumer tag is
+ local to a connection, so two clients can use the same consumer
+ tags. If this field is empty the server will generate a unique
+ tag.
+ </doc>
+ <doc name = "rule" test = "todo">
+ The tag MUST NOT refer to an existing consumer. If the client
+ attempts to create two consumers with the same non-empty tag
+ the server MUST raise a connection exception with reply code
+ 530 (not allowed).
+ </doc>
+ </field>
+
+ <field name = "no local" domain = "no local" />
+
+ <field name = "exclusive" type = "bit">
+ request exclusive access
+ <doc>
+ Request exclusive consumer access, meaning only this consumer can
+ access the queue.
+ </doc>
+ <doc name = "rule" test = "amq_file_00">
+ If the server cannot grant exclusive access to the queue when asked,
+ - because there are other consumers active - it MUST raise a channel
+ exception with return code 405 (resource locked).
+ </doc>
+ </field>
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+
+<method name = "consume-ok" synchronous = "1" index = "21">
+ confirm a new consumer
+ <doc>
+ This method provides the client with a consumer tag which it may
+ use in methods that work with the consumer.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag">
+ <doc>
+ Holds the consumer tag specified by the client or provided by
+ the server.
+ </doc>
+ </field>
+</method>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "cancel" synchronous = "1" index = "30">
+ end a queue consumer
+ <doc>
+ This method cancels a consumer. Since message delivery is
+ asynchronous the client may continue to receive messages for
+ a short while after canceling a consumer. It may process or
+ discard these as appropriate.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+ <response name = "cancel-ok" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "nowait" type = "bit">
+ do not send a reply method
+ <doc>
+ If set, the server will not respond to the method. The client should
+ not wait for a reply method. If the server could not complete the
+ method it will raise a channel or connection exception.
+ </doc>
+ </field>
+</method>
+
+<method name = "cancel-ok" synchronous = "1" index = "31">
+ confirm a cancelled consumer
+ <doc>
+ This method confirms that the cancellation was completed.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "publish" content = "1" index = "40">
+ publish a message
+ <doc>
+ This method publishes a message to a specific exchange. The message
+ will be routed to queues as defined by the exchange configuration
+ and distributed to any active consumers as appropriate.
+ </doc>
+ <chassis name = "server" implement = "MUST" />
+
+ <field name = "ticket" domain = "access ticket">
+ <doc name = "rule">
+ The client MUST provide a valid access ticket giving "write"
+ access rights to the access realm for the exchange.
+ </doc>
+ </field>
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange to publish to. The exchange
+ name can be empty, meaning the default exchange. If the exchange
+ name is specified, and that exchange does not exist, the server
+ will raise a channel exception.
+ </doc>
+ <doc name = "rule">
+ The server MUST accept a blank exchange name to mean the default
+ exchange.
+ </doc>
+ <doc name = "rule">
+ If the exchange was declared as an internal exchange, the server
+ MUST respond with a reply code 403 (access refused) and raise a
+ channel exception.
+ </doc>
+ <doc name = "rule">
+ The exchange MAY refuse stream content in which case it MUST
+ respond with a reply code 540 (not implemented) and raise a
+ channel exception.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key for the message. The routing key is
+ used for routing messages depending on the exchange configuration.
+ </doc>
+ </field>
+
+ <field name = "mandatory" type = "bit">
+ indicate mandatory routing
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue. If this flag is set, the server will return an
+ unroutable message with a Return method. If this flag is zero, the
+ server silently drops the message.
+ </doc>
+ <doc name = "rule" test = "amq_stream_00">
+ The server SHOULD implement the mandatory flag.
+ </doc>
+ </field>
+
+ <field name = "immediate" type = "bit">
+ request immediate delivery
+ <doc>
+ This flag tells the server how to react if the message cannot be
+ routed to a queue consumer immediately. If this flag is set, the
+ server will return an undeliverable message with a Return method.
+ If this flag is zero, the server will queue the message, but with
+ no guarantee that it will ever be consumed.
+ </doc>
+ <doc name = "rule" test = "amq_stream_00">
+ The server SHOULD implement the immediate flag.
+ </doc>
+ </field>
+</method>
+
+<method name = "return" content = "1" index = "50">
+ return a failed message
+ <doc>
+ This method returns an undeliverable message that was published
+ with the "immediate" flag set, or an unroutable message published
+ with the "mandatory" flag set. The reply code and text provide
+ information about the reason that the message was undeliverable.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "reply code" domain = "reply code" />
+ <field name = "reply text" domain = "reply text" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was
+ originally published to.
+ </doc>
+ </field>
+
+ <field name = "routing key" type = "shortstr">
+ Message routing key
+ <doc>
+ Specifies the routing key name specified when the message was
+ published.
+ </doc>
+ </field>
+</method>
+
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<method name = "deliver" content = "1" index = "60">
+ notify the client of a consumer message
+ <doc>
+ This method delivers a message to the client, via a consumer. In
+ the asynchronous message delivery model, the client starts a
+ consumer using the Consume method, then the server responds with
+ Deliver methods as and when messages arrive for that consumer.
+ </doc>
+ <chassis name = "client" implement = "MUST" />
+
+ <field name = "consumer tag" domain = "consumer tag" />
+
+ <field name = "delivery tag" domain = "delivery tag" />
+
+ <field name = "exchange" domain = "exchange name">
+ <doc>
+ Specifies the name of the exchange that the message was originally
+ published to.
+ </doc>
+ </field>
+
+ <field name = "queue" domain = "queue name">
+ <doc>
+ Specifies the name of the queue that the message came from. Note
+ that a single channel can start many consumers on different
+ queues.
+ </doc>
+ <assert check = "notnull" />
+ </field>
+</method>
+ </class>
+
+ <class name="tx" handler="channel" index="90">
+ <!--
+======================================================
+== TRANSACTIONS
+======================================================
+-->
+ work with standard transactions
+
+<doc>
+ Standard transactions provide so-called "1.5 phase commit". We can
+ ensure that work is never lost, but there is a chance of confirmations
+ being lost, so that messages may be resent. Applications that use
+ standard transactions must be able to detect and ignore duplicate
+ messages.
+</doc>
+ <rule implement="SHOULD">
+ An client using standard transactions SHOULD be able to track all
+ messages received within a reasonable period, and thus detect and
+ reject duplicates of the same message. It SHOULD NOT pass these to
+ the application layer.
+</rule>
+ <doc name="grammar">
+ tx = C:SELECT S:SELECT-OK
+ / C:COMMIT S:COMMIT-OK
+ / C:ROLLBACK S:ROLLBACK-OK
+</doc>
+ <chassis name="server" implement="SHOULD"/>
+ <chassis name="client" implement="MAY"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="select" synchronous="1" index="10">
+select standard transaction mode
+ <doc>
+ This method sets the channel to use standard transactions. The
+ client must use this method at least once on a channel before
+ using the Commit or Rollback methods.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <response name="select-ok"/>
+ </method>
+ <method name="select-ok" synchronous="1" index="11">
+confirm transaction mode
+ <doc>
+ This method confirms to the client that the channel was successfully
+ set to use standard transactions.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="commit" synchronous="1" index="20">
+commit the current transaction
+ <doc>
+ This method commits all messages published and acknowledged in
+ the current transaction. A new transaction starts immediately
+ after a commit.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <response name="commit-ok"/>
+ </method>
+ <method name="commit-ok" synchronous="1" index="21">
+confirm a successful commit
+ <doc>
+ This method confirms to the client that the commit succeeded.
+ Note that if a commit fails, the server raises a channel exception.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="rollback" synchronous="1" index="30">
+abandon the current transaction
+ <doc>
+ This method abandons all messages published and acknowledged in
+ the current transaction. A new transaction starts immediately
+ after a rollback.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <response name="rollback-ok"/>
+ </method>
+ <method name="rollback-ok" synchronous="1" index="31">
+confirm a successful rollback
+ <doc>
+ This method confirms to the client that the rollback succeeded.
+ Note that if an rollback fails, the server raises a channel exception.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ </class>
+ <class name="dtx" handler="channel" index="100">
+ <!--
+======================================================
+== DISTRIBUTED TRANSACTIONS
+======================================================
+-->
+ work with distributed transactions
+
+<doc>
+ Distributed transactions provide so-called "2-phase commit". The
+ AMQP distributed transaction model supports the X-Open XA
+ architecture and other distributed transaction implementations.
+ The Dtx class assumes that the server has a private communications
+ channel (not AMQP) to a distributed transaction coordinator.
+</doc>
+ <doc name="grammar">
+ dtx = C:SELECT S:SELECT-OK
+ C:START S:START-OK
+</doc>
+ <chassis name="server" implement="MAY"/>
+ <chassis name="client" implement="MAY"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="select" synchronous="1" index="10">
+select standard transaction mode
+ <doc>
+ This method sets the channel to use distributed transactions. The
+ client must use this method at least once on a channel before
+ using the Start method.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <response name="select-ok"/>
+ </method>
+ <method name="select-ok" synchronous="1" index="11">
+confirm transaction mode
+ <doc>
+ This method confirms to the client that the channel was successfully
+ set to use distributed transactions.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="start" synchronous="1" index="20">
+ start a new distributed transaction
+ <doc>
+ This method starts a new distributed transaction. This must be
+ the first method on a new channel that uses the distributed
+ transaction mode, before any methods that publish or consume
+ messages.
+ </doc>
+ <chassis name="server" implement="MAY"/>
+ <response name="start-ok"/>
+ <field name="dtx identifier" type="shortstr">
+ transaction identifier
+ <doc>
+ The distributed transaction key. This identifies the transaction
+ so that the AMQP server can coordinate with the distributed
+ transaction coordinator.
+ </doc>
+ <assert check="notnull"/>
+ </field>
+ </method>
+ <method name="start-ok" synchronous="1" index="21">
+ confirm the start of a new distributed transaction
+ <doc>
+ This method confirms to the client that the transaction started.
+ Note that if a start fails, the server raises a channel exception.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ </method>
+ </class>
+ <class name="tunnel" handler="tunnel" index="110">
+ <!--
+======================================================
+== TUNNEL
+======================================================
+-->
+ methods for protocol tunneling.
+
+<doc>
+ The tunnel methods are used to send blocks of binary data - which
+ can be serialised AMQP methods or other protocol frames - between
+ AMQP peers.
+</doc>
+ <doc name="grammar">
+ tunnel = C:REQUEST
+ / S:REQUEST
+</doc>
+ <chassis name="server" implement="MAY"/>
+ <chassis name="client" implement="MAY"/>
+ <field name="headers" type="table">
+ Message header field table
+</field>
+ <field name="proxy name" type="shortstr">
+ The identity of the tunnelling proxy
+</field>
+ <field name="data name" type="shortstr">
+ The name or type of the message being tunnelled
+</field>
+ <field name="durable" type="octet">
+ The message durability indicator
+</field>
+ <field name="broadcast" type="octet">
+ The message broadcast mode
+</field>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="request" content="1" index="10">
+ sends a tunnelled method
+ <doc>
+ This method tunnels a block of binary data, which can be an
+ encoded AMQP method or other data. The binary data is sent
+ as the content for the Tunnel.Request method.
+ </doc>
+ <chassis name="server" implement="MUST"/>
+ <field name="meta data" type="table">
+ meta data for the tunnelled block
+ <doc>
+ This field table holds arbitrary meta-data that the sender needs
+ to pass to the recipient.
+ </doc>
+ </field>
+ </method>
+ </class>
+ <class name="test" handler="channel" index="120">
+ <!--
+======================================================
+== TEST - CHECK FUNCTIONAL CAPABILITIES OF AN IMPLEMENTATION
+======================================================
+-->
+ test functional primitives of the implementation
+
+<doc>
+ The test class provides methods for a peer to test the basic
+ operational correctness of another peer. The test methods are
+ intended to ensure that all peers respect at least the basic
+ elements of the protocol, such as frame and content organisation
+ and field types. We assume that a specially-designed peer, a
+ "monitor client" would perform such tests.
+</doc>
+ <doc name="grammar">
+ test = C:INTEGER S:INTEGER-OK
+ / S:INTEGER C:INTEGER-OK
+ / C:STRING S:STRING-OK
+ / S:STRING C:STRING-OK
+ / C:TABLE S:TABLE-OK
+ / S:TABLE C:TABLE-OK
+ / C:CONTENT S:CONTENT-OK
+ / S:CONTENT C:CONTENT-OK
+</doc>
+ <chassis name="server" implement="MUST"/>
+ <chassis name="client" implement="SHOULD"/>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="integer" synchronous="1" index="10">
+ test integer handling
+ <doc>
+ This method tests the peer's capability to correctly marshal integer
+ data.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="integer-ok"/>
+ <field name="integer 1" type="octet">
+ octet test value
+ <doc>
+ An octet integer test value.
+ </doc>
+ </field>
+ <field name="integer 2" type="short">
+ short test value
+ <doc>
+ A short integer test value.
+ </doc>
+ </field>
+ <field name="integer 3" type="long">
+ long test value
+ <doc>
+ A long integer test value.
+ </doc>
+ </field>
+ <field name="integer 4" type="longlong">
+ long-long test value
+ <doc>
+ A long long integer test value.
+ </doc>
+ </field>
+ <field name="operation" type="octet">
+ operation to test
+ <doc>
+ The client must execute this operation on the provided integer
+ test fields and return the result.
+ </doc>
+ <assert check="enum">
+ <value name="add">return sum of test values</value>
+ <value name="min">return lowest of test values</value>
+ <value name="max">return highest of test values</value>
+ </assert>
+ </field>
+ </method>
+ <method name="integer-ok" synchronous="1" index="11">
+ report integer test result
+ <doc>
+ This method reports the result of an Integer method.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <field name="result" type="longlong">
+ result value
+ <doc>
+ The result of the tested operation.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="string" synchronous="1" index="20">
+ test string handling
+ <doc>
+ This method tests the peer's capability to correctly marshal string
+ data.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="string-ok"/>
+ <field name="string 1" type="shortstr">
+ short string test value
+ <doc>
+ An short string test value.
+ </doc>
+ </field>
+ <field name="string 2" type="longstr">
+ long string test value
+ <doc>
+ A long string test value.
+ </doc>
+ </field>
+ <field name="operation" type="octet">
+ operation to test
+ <doc>
+ The client must execute this operation on the provided string
+ test fields and return the result.
+ </doc>
+ <assert check="enum">
+ <value name="add">return concatentation of test strings</value>
+ <value name="min">return shortest of test strings</value>
+ <value name="max">return longest of test strings</value>
+ </assert>
+ </field>
+ </method>
+ <method name="string-ok" synchronous="1" index="21">
+ report string test result
+ <doc>
+ This method reports the result of a String method.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <field name="result" type="longstr">
+ result value
+ <doc>
+ The result of the tested operation.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="table" synchronous="1" index="30">
+ test field table handling
+ <doc>
+ This method tests the peer's capability to correctly marshal field
+ table data.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="table-ok"/>
+ <field name="table" type="table">
+ field table of test values
+ <doc>
+ A field table of test values.
+ </doc>
+ </field>
+ <field name="integer op" type="octet">
+ operation to test on integers
+ <doc>
+ The client must execute this operation on the provided field
+ table integer values and return the result.
+ </doc>
+ <assert check="enum">
+ <value name="add">return sum of numeric field values</value>
+ <value name="min">return min of numeric field values</value>
+ <value name="max">return max of numeric field values</value>
+ </assert>
+ </field>
+ <field name="string op" type="octet">
+ operation to test on strings
+ <doc>
+ The client must execute this operation on the provided field
+ table string values and return the result.
+ </doc>
+ <assert check="enum">
+ <value name="add">return concatenation of string field values</value>
+ <value name="min">return shortest of string field values</value>
+ <value name="max">return longest of string field values</value>
+ </assert>
+ </field>
+ </method>
+ <method name="table-ok" synchronous="1" index="31">
+ report table test result
+ <doc>
+ This method reports the result of a Table method.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <field name="integer result" type="longlong">
+ integer result value
+ <doc>
+ The result of the tested integer operation.
+ </doc>
+ </field>
+ <field name="string result" type="longstr">
+ string result value
+ <doc>
+ The result of the tested string operation.
+ </doc>
+ </field>
+ </method>
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <method name="content" synchronous="1" content="1" index="40">
+ test content handling
+ <doc>
+ This method tests the peer's capability to correctly marshal content.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <response name="content-ok"/>
+ </method>
+ <method name="content-ok" synchronous="1" content="1" index="41">
+ report content test result
+ <doc>
+ This method reports the result of a Content method. It contains the
+ content checksum and echoes the original content as provided.
+ </doc>
+ <chassis name="client" implement="MUST"/>
+ <chassis name="server" implement="MUST"/>
+ <field name="content checksum" type="long">
+ content hash
+ <doc>
+ The 32-bit checksum of the content, calculated by adding the
+ content into a 32-bit accumulator.
+ </doc>
+ </field>
+ </method>
+ </class>
+</amqp>
diff --git a/dotnet/Qpid.Common/build.xml b/dotnet/Qpid.Common/build.xml
new file mode 100644
index 0000000000..96dd877722
--- /dev/null
+++ b/dotnet/Qpid.Common/build.xml
@@ -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.
+
+-->
+
+
+<!--
+ This sole purpose of this build script is to generate the framing layer for the .net client from the AMQ spec.
+ -->
+<project name="AMQ Dot Net Framing Layer" default="generate">
+
+ <property name="amq.home" value="../.."/>
+
+ <property name="stylesheet" value="stylesheets/framing.xsl"/>
+ <property name="registry_stylesheet" value="stylesheets/registry.xsl"/>
+ <property name="registry_template" value="resources/registry.template"/>
+ <property name="saxon.jar" value="lib/saxon/saxon8.jar"/>
+ <property name="generated.src" value="generated"/>
+ <property name="static.src" value="src"/>
+ <property name="resources" value="resources"/>
+ <property name="base.lib" value="lib"/>
+
+ <path id="amq.home.path">
+ <pathelement location="${amq.home}"/>
+ </path>
+
+ <pathconvert targetos="unix" property="amq.home.fixed" refid="amq.home.path"/>
+
+<!-- Some spec changes break the build, reverting to private copy in Qpid.Common temporarily till this is fixed. -->
+ <property name="amq.asl" value="${amq.home.fixed}/specs/amqp.0-8.xml"/>
+
+ <target name="clean" description="Deletes the generated sources.">
+ <delete>
+ <fileset dir="${generated.src}" includes="**/*"/>
+ </delete>
+ </target>
+
+ <!--
+ Checks if the generation step needs to be performed. It will be skipped if the sources are up to date with the spec and provided that the
+ force flag has not been set.
+ -->
+ <target name="check-generate"
+ description="Checks if the generated sources are up-to-date. Use -Dforce=true or the 'forcegen' target to force generation.">
+
+ <condition property="generateNotRequired">
+ <and>
+ <uptodate targetfile="${generated.src}/results.out" srcfile="${amq.asl}"/>
+ <not><isset property="force"/></not>
+ </and>
+ </condition>
+ </target>
+
+ <!-- Applies a transformation to the AMQP spec to generate the framing layer. -->
+ <target name="generate" depends="check-generate" unless="generateNotRequired" description="generates code">
+
+ <mkdir dir="${generated.src}"/>
+
+ <java jar="${saxon.jar}" fork="true">
+ <arg value="-o"/>
+ <arg value="${generated.src}/results.out"/>
+ <arg value="${amq.asl}"/>
+ <arg value="${stylesheet}"/>
+ <arg value="asl_base=${asl.base}"/>
+ <arg value="registry_name=MainRegistry"/>
+ </java>
+
+ <java jar="${saxon.jar}" fork="true">
+ <arg value="-o"/>
+ <arg value="${generated.src}/registry.out"/>
+ <arg value="${registry_template}"/>
+ <arg value="${registry_stylesheet}"/>
+ </java>
+ </target>
+
+ <!-- Does a clean and forces re-generation of the sources. -->
+ <target name="forcegen" depends="clean, generate" description="Forces clean re-generation of the code.">
+ </target>
+
+</project>
diff --git a/dotnet/Qpid.Common/default.build b/dotnet/Qpid.Common/default.build
new file mode 100644
index 0000000000..df07397d0b
--- /dev/null
+++ b/dotnet/Qpid.Common/default.build
@@ -0,0 +1,49 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Common" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/Apache.Qpid.Buffer.dll" />
+ <include name="${build.dir}/Apache.Qpid.Messaging.dll" />
+ <include name="${build.dir}/Apache.Qpid.Codec.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Common/lib/log4net/log4net-licence.txt b/dotnet/Qpid.Common/lib/log4net/log4net-licence.txt
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/log4net/log4net-licence.txt
@@ -0,0 +1,201 @@
+ 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/dotnet/Qpid.Common/lib/log4net/log4net.dll b/dotnet/Qpid.Common/lib/log4net/log4net.dll
new file mode 100644
index 0000000000..995816f27b
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/log4net/log4net.dll
Binary files differ
diff --git a/dotnet/Qpid.Common/lib/log4net/log4net.xml b/dotnet/Qpid.Common/lib/log4net/log4net.xml
new file mode 100644
index 0000000000..5beb669ab0
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/log4net/log4net.xml
@@ -0,0 +1,28676 @@
+<?xml version="1.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.
+
+-->
+
+<doc>
+ <assembly>
+ <name>log4net</name>
+ </assembly>
+ <members>
+ <member name="T:log4net.Appender.AdoNetAppender">
+ <summary>
+ Appender that logs to a database.
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Appender.AdoNetAppender"/> appends logging events to a table within a
+ database. The appender can be configured to specify the connection
+ string by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionString"/> property.
+ The connection type (provider) can be specified by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/>
+ property. For more information on database connection strings for
+ your specific database see <a href="http://www.connectionstrings.com/">http://www.connectionstrings.com/</a>.
+ </para>
+ <para>
+ Records are written into the database either using a prepared
+ statement or a stored procedure. The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property
+ is set to <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify a prepared statement
+ or to <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify a stored
+ procedure.
+ </para>
+ <para>
+ The prepared statement text or the name of the stored procedure
+ must be set in the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property.
+ </para>
+ <para>
+ The prepared statement or stored procedure can take a number
+ of parameters. Parameters are added using the <see cref="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)"/>
+ method. This adds a single <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> to the
+ ordered list of parameters. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/>
+ type may be subclassed if required to provide database specific
+ functionality. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> specifies
+ the parameter name, database type, size, and how the value should
+ be generated using a <see cref="T:log4net.Layout.ILayout"/>.
+ </para>
+ </remarks>
+ <example>
+ An example of a SQL Server table that could be logged to:
+ <code lang="SQL">
+ CREATE TABLE [dbo].[Log] (
+ [ID] [int] IDENTITY (1, 1) NOT NULL ,
+ [Date] [datetime] NOT NULL ,
+ [Thread] [varchar] (255) NOT NULL ,
+ [Level] [varchar] (20) NOT NULL ,
+ [Logger] [varchar] (255) NOT NULL ,
+ [Message] [varchar] (4000) NOT NULL
+ ) ON [PRIMARY]
+ </code>
+ </example>
+ <example>
+ An example configuration to log to the above table:
+ <code lang="XML" escaped="true">
+ <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
+ <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
+ <connectionString value="data source=SQLSVR;initial catalog=test_log4net;integrated security=false;persist security info=True;User ID=sa;Password=sa"/>
+ <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)"/>
+ <parameter>
+ <parameterName value="@log_date"/>
+ <dbType value="DateTime"/>
+ <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@thread"/>
+ <dbType value="String"/>
+ <size value="255"/>
+ <layout type="log4net.Layout.PatternLayout" value="%thread"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@log_level"/>
+ <dbType value="String"/>
+ <size value="50"/>
+ <layout type="log4net.Layout.PatternLayout" value="%level"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@logger"/>
+ <dbType value="String"/>
+ <size value="255"/>
+ <layout type="log4net.Layout.PatternLayout" value="%logger"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@message"/>
+ <dbType value="String"/>
+ <size value="4000"/>
+ <layout type="log4net.Layout.PatternLayout" value="%message"/>
+ </parameter>
+ </appender>
+ </code>
+ </example>
+ <author>Julian Biddle</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Lance Nehring</author>
+ </member>
+ <member name="T:log4net.Appender.BufferingAppenderSkeleton">
+ <summary>
+ Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/> that
+ buffers events in a fixed size buffer.
+ </summary>
+ <remarks>
+ <para>
+ This base class should be used by appenders that need to buffer a
+ number of events before logging them. For example the <see cref="T:log4net.Appender.AdoNetAppender"/>
+ buffers events and then submits the entire contents of the buffer to
+ the underlying database in one go.
+ </para>
+ <para>
+ Subclasses should override the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>
+ method to deliver the buffered events.
+ </para>
+ <para>The BufferingAppenderSkeleton maintains a fixed size cyclic
+ buffer of events. The size of the buffer is set using
+ the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> property.
+ </para>
+ <para>A <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> is used to inspect
+ each event as it arrives in the appender. If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/>
+ triggers, then the current buffer is sent immediately
+ (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>). Otherwise the event
+ is stored in the buffer. For example, an evaluator can be used to
+ deliver the events immediately when an ERROR event arrives.
+ </para>
+ <para>
+ The buffering appender can be configured in a <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode.
+ By default the appender is NOT lossy. When the buffer is full all
+ the buffered events are sent with <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+ If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property is set to <c>true</c> then the
+ buffer will not be sent when it is full, and new events arriving
+ in the appender will overwrite the oldest event in the buffer.
+ In lossy mode the buffer will only be sent when the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/>
+ triggers. This can be useful behavior when you need to know about
+ ERROR events but not about events with a lower level, configure an
+ evaluator that will trigger when an ERROR event arrives, the whole
+ buffer will be sent which gives a history of events leading up to
+ the ERROR event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Appender.AppenderSkeleton">
+ <summary>
+ Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ This class provides the code for common functionality, such
+ as support for threshold filtering and support for general filters.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Appender.IAppender">
+ <summary>
+ Implement this interface for your own strategies for printing log statements.
+ </summary>
+ <remarks>
+ <para>
+ Implementors should consider extending the <see cref="T:log4net.Appender.AppenderSkeleton"/>
+ class which provides a default implementation of this interface.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.IAppender.Close">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logging event in Appender specific way.
+ </summary>
+ <param name="loggingEvent">The event to log</param>
+ <remarks>
+ <para>
+ This method is called to log a message into this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.IAppender.Name">
+ <summary>
+ Gets or sets the name of this appender.
+ </summary>
+ <value>The name of the appender.</value>
+ <remarks>
+ <para>The name uniquely identifies the appender.</para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.IBulkAppender">
+ <summary>
+ Interface for appenders that support bulk logging.
+ </summary>
+ <remarks>
+ <para>
+ This interface extends the <see cref="T:log4net.Appender.IAppender"/> interface to
+ support bulk logging of <see cref="T:log4net.Core.LoggingEvent"/> objects. Appenders
+ should only implement this interface if they can bulk log efficiently.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.IBulkAppender.DoAppend(log4net.Core.LoggingEvent[])">
+ <summary>
+ Log the array of logging events in Appender specific way.
+ </summary>
+ <param name="loggingEvents">The events to log</param>
+ <remarks>
+ <para>
+ This method is called to log an array of events into this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.IOptionHandler">
+ <summary>
+ Interface used to delay activate a configured object.
+ </summary>
+ <remarks>
+ <para>
+ This allows an object to defer activation of its options until all
+ options have been set. This is required for components which have
+ related options that remain ambiguous until all are set.
+ </para>
+ <para>
+ If a component implements this interface then the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ must be called by the container after its all the configured properties have been set
+ and before the component can be used.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.IOptionHandler.ActivateOptions">
+ <summary>
+ Activate the options that were previously set with calls to properties.
+ </summary>
+ <remarks>
+ <para>
+ This allows an object to defer activation of its options until all
+ options have been set. This is required for components which have
+ related options that remain ambiguous until all are set.
+ </para>
+ <para>
+ If a component implements this interface then this method must be called
+ after its properties have been set before the component can be used.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferSize">
+ <summary>
+ Initial buffer size
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferMaxCapacity">
+ <summary>
+ Maximum buffer size before it is recycled
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>Empty default constructor</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Finalize">
+ <summary>
+ Finalizes this appender by calling the implementation's
+ <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> method.
+ </summary>
+ <remarks>
+ <para>
+ If this appender has not been closed then the <c>Finalize</c> method
+ will call <see cref="M:log4net.Appender.AppenderSkeleton.Close"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Close">
+ <summary>
+ Closes the appender and release resources.
+ </summary>
+ <remarks>
+ <para>
+ Release any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ <para>
+ This method cannot be overridden by subclasses. This method
+ delegates the closing of the appender to the <see cref="M:log4net.Appender.AppenderSkeleton.OnClose"/>
+ method which must be overridden in the subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)">
+ <summary>
+ Performs threshold checks and invokes filters before
+ delegating actual logging to the subclasses specific
+ <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ This method cannot be overridden by derived classes. A
+ derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method
+ which is called by this method.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ <item>
+ <description>
+ Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that
+ it returns <c>true</c>.</description>
+ </item>
+ </list>
+ </para>
+ <para>
+ If all of the above steps succeed then the <paramref name="loggingEvent"/>
+ will be passed to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])">
+ <summary>
+ Performs threshold checks and invokes filters before
+ delegating actual logging to the subclasses specific
+ <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ This method cannot be overridden by derived classes. A
+ derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method
+ which is called by this method.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ <item>
+ <description>
+ Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that
+ it returns <c>true</c>.</description>
+ </item>
+ </list>
+ </para>
+ <para>
+ If all of the above steps succeed then the <paramref name="loggingEvents"/>
+ will be passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.FilterEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Test if the logging event should we output by this appender
+ </summary>
+ <param name="loggingEvent">the event to test</param>
+ <returns><c>true</c> if the event should be output, <c>false</c> if the event should be ignored</returns>
+ <remarks>
+ <para>
+ This method checks the logging event against the threshold level set
+ on this appender and also against the filters specified on this
+ appender.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.AddFilter(log4net.Filter.IFilter)">
+ <summary>
+ Adds a filter to the end of the filter chain.
+ </summary>
+ <param name="filter">the filter to add to this appender</param>
+ <remarks>
+ <para>
+ The Filters are organized in a linked list.
+ </para>
+ <para>
+ Setting this property causes the new filter to be pushed onto the
+ back of the filter chain.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.ClearFilters">
+ <summary>
+ Clears the filter list for this appender.
+ </summary>
+ <remarks>
+ <para>
+ Clears the filter list for this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.IsAsSevereAsThreshold(log4net.Core.Level)">
+ <summary>
+ Checks if the message level is below this appender's threshold.
+ </summary>
+ <param name="level"><see cref="T:log4net.Core.Level"/> to test against.</param>
+ <remarks>
+ <para>
+ If there is no threshold set, then the return value is always <c>true</c>.
+ </para>
+ </remarks>
+ <returns>
+ <c>true</c> if the <paramref name="level"/> meets the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/>
+ requirements of this appender.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.OnClose">
+ <summary>
+ Is called when the appender is closed. Derived classes should override
+ this method if resources need to be released.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Subclasses of <see cref="T:log4net.Appender.AppenderSkeleton"/> should implement this method
+ to perform actual logging.
+ </summary>
+ <param name="loggingEvent">The event to append.</param>
+ <remarks>
+ <para>
+ A subclass must implement this method to perform
+ logging of the <paramref name="loggingEvent"/>.
+ </para>
+ <para>This method will be called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ if all the conditions listed for that method are met.
+ </para>
+ <para>
+ To restrict the logging of events in the appender
+ override the <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Append a bulk array of logging events.
+ </summary>
+ <param name="loggingEvents">the array of logging events</param>
+ <remarks>
+ <para>
+ This base class implementation calls the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>
+ method for each element in the bulk array.
+ </para>
+ <para>
+ A sub class that can better process a bulk array of events should
+ override this method in addition to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.PreAppendCheck">
+ <summary>
+ Called before <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> as a precondition.
+ </summary>
+ <remarks>
+ <para>
+ This method is called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ before the call to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ This method can be overridden in a subclass to extend the checks
+ made before the event is passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ A subclass should ensure that they delegate this call to
+ this base class if it is overridden.
+ </para>
+ </remarks>
+ <returns><c>true</c> if the call to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> should proceed.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+ </summary>
+ <param name="loggingEvent">The event to render.</param>
+ <returns>The event rendered as a string.</returns>
+ <remarks>
+ <para>
+ Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to
+ a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+ set to render the <paramref name="loggingEvent"/> to
+ a string.
+ </para>
+ <para>If there is exception data in the logging event and
+ the layout does not process the exception, this method
+ will append the exception text to the rendered string.
+ </para>
+ <para>
+ Where possible use the alternative version of this method
+ <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)"/>.
+ That method streams the rendering onto an existing Writer
+ which can give better performance if the caller already has
+ a <see cref="T:System.IO.TextWriter"/> open and ready for writing.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+ </summary>
+ <param name="loggingEvent">The event to render.</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to
+ a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+ set to render the <paramref name="loggingEvent"/> to
+ a string.
+ </para>
+ <para>If there is exception data in the logging event and
+ the layout does not process the exception, this method
+ will append the exception text to the rendered string.
+ </para>
+ <para>
+ Use this method in preference to <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/>
+ where possible. If, however, the caller needs to render the event
+ to a string then <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/> does
+ provide an efficient mechanism for doing so.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_layout">
+ <summary>
+ The layout of this appender.
+ </summary>
+ <remarks>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_name">
+ <summary>
+ The name of this appender.
+ </summary>
+ <remarks>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Name"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_threshold">
+ <summary>
+ The level threshold of this appender.
+ </summary>
+ <remarks>
+ <para>
+ There is no level threshold filtering by default.
+ </para>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_errorHandler">
+ <summary>
+ It is assumed and enforced that errorHandler is never null.
+ </summary>
+ <remarks>
+ <para>
+ It is assumed and enforced that errorHandler is never null.
+ </para>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_headFilter">
+ <summary>
+ The first filter in the filter chain.
+ </summary>
+ <remarks>
+ <para>
+ Set to <c>null</c> initially.
+ </para>
+ <para>
+ See <see cref="T:log4net.Filter.IFilter"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_tailFilter">
+ <summary>
+ The last filter in the filter chain.
+ </summary>
+ <remarks>
+ See <see cref="T:log4net.Filter.IFilter"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_closed">
+ <summary>
+ Flag indicating if this appender is closed.
+ </summary>
+ <remarks>
+ See <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_recursiveGuard">
+ <summary>
+ The guard prevents an appender from repeatedly calling its own DoAppend method
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_renderWriter">
+ <summary>
+ StringWriter used to render events
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Threshold">
+ <summary>
+ Gets or sets the threshold <see cref="T:log4net.Core.Level"/> of this appender.
+ </summary>
+ <value>
+ The threshold <see cref="T:log4net.Core.Level"/> of the appender.
+ </value>
+ <remarks>
+ <para>
+ All log events with lower level than the threshold level are ignored
+ by the appender.
+ </para>
+ <para>
+ In configuration files this option is specified by setting the
+ value of the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> option to a level
+ string, such as "DEBUG", "INFO" and so on.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.ErrorHandler">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.IErrorHandler"/> for this appender.
+ </summary>
+ <value>The <see cref="T:log4net.Core.IErrorHandler"/> of the appender</value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Appender.AppenderSkeleton"/> provides a default
+ implementation for the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.FilterHead">
+ <summary>
+ The filter chain.
+ </summary>
+ <value>The head of the filter chain filter chain.</value>
+ <remarks>
+ <para>
+ Returns the head Filter. The Filters are organized in a linked list
+ and so all Filters on this Appender are available through the result.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Layout">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Layout.ILayout"/> for this appender.
+ </summary>
+ <value>The layout of the appender.</value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/> for more information.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Name">
+ <summary>
+ Gets or sets the name of this appender.
+ </summary>
+ <value>The name of the appender.</value>
+ <remarks>
+ <para>
+ The name uniquely identifies the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.RequiresLayout">
+ <summary>
+ Tests if this appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </summary>
+ <remarks>
+ <para>
+ In the rather exceptional case, where the appender
+ implementation admits a layout but can also work without it,
+ then the appender should return <c>true</c>.
+ </para>
+ <para>
+ This default implementation always returns <c>true</c>.
+ </para>
+ </remarks>
+ <returns>
+ <c>true</c> if the appender requires a layout object, otherwise <c>false</c>.
+ </returns>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE">
+ <summary>
+ The default buffer size.
+ </summary>
+ <remarks>
+ The default size of the cyclic buffer used to store events.
+ This is set to 512 by default.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Protected default constructor to allow subclassing.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor(System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+ </summary>
+ <param name="eventMustBeFixed">the events passed through this appender must be
+ fixed by the time that they arrive in the derived class' <c>SendBuffer</c> method.</param>
+ <remarks>
+ <para>
+ Protected constructor to allow subclassing.
+ </para>
+ <para>
+ The <paramref name="eventMustBeFixed"/> should be set if the subclass
+ expects the events delivered to be fixed even if the
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to zero, i.e. when no buffering occurs.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush">
+ <summary>
+ Flush the currently buffered events
+ </summary>
+ <remarks>
+ <para>
+ Flushes any events that have been buffered.
+ </para>
+ <para>
+ If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+ of the buffer will NOT be flushed to the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush(System.Boolean)">
+ <summary>
+ Flush the currently buffered events
+ </summary>
+ <param name="flushLossyBuffer">set to <c>true</c> to flush the buffer of lossy events</param>
+ <remarks>
+ <para>
+ Flushes events that have been buffered. If <paramref name="flushLossyBuffer"/> is
+ <c>false</c> then events will only be flushed if this buffer is non-lossy mode.
+ </para>
+ <para>
+ If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+ of the buffer will only be flushed if <paramref name="flushLossyBuffer"/> is <c>true</c>.
+ In this case the contents of the buffer will be tested against the
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator"/> and if triggering will be output. All other buffered
+ events will be discarded.
+ </para>
+ <para>
+ If <paramref name="flushLossyBuffer"/> is <c>true</c> then the buffer will always
+ be emptied by calling this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.OnClose">
+ <summary>
+ Close this appender instance.
+ </summary>
+ <remarks>
+ <para>
+ Close this appender instance. If this appender is marked
+ as not <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> then the remaining events in
+ the buffer must be sent when the appender is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Stores the <paramref name="loggingEvent"/> in the cyclic buffer.
+ </para>
+ <para>
+ The buffer will be sent (i.e. passed to the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>
+ method) if one of the following conditions is met:
+ </para>
+ <list type="bullet">
+ <item>
+ <description>The cyclic buffer is full and this appender is
+ marked as not lossy (see <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>)</description>
+ </item>
+ <item>
+ <description>An <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> is set and
+ it is triggered for the <paramref name="loggingEvent"/>
+ specified.</description>
+ </item>
+ </list>
+ <para>
+ Before the event is stored in the buffer it is fixed
+ (see <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/>) to ensure that
+ any data referenced by the event will be valid when the buffer
+ is processed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendFromBuffer(log4net.Core.LoggingEvent,log4net.Util.CyclicBuffer)">
+ <summary>
+ Sends the contents of the buffer.
+ </summary>
+ <param name="firstLoggingEvent">The first logging event.</param>
+ <param name="buffer">The buffer containing the events that need to be send.</param>
+ <remarks>
+ <para>
+ The subclass must override <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the events.
+ </summary>
+ <param name="events">The events that need to be send.</param>
+ <remarks>
+ <para>
+ The subclass must override this method to process the buffered events.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_bufferSize">
+ <summary>
+ The size of the cyclic buffer used to hold the logging events.
+ </summary>
+ <remarks>
+ Set to <see cref="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE"/> by default.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_cb">
+ <summary>
+ The cyclic buffer used to store the logging events.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_evaluator">
+ <summary>
+ The triggering event evaluator that causes the buffer to be sent immediately.
+ </summary>
+ <remarks>
+ The object that is used to determine if an event causes the entire
+ buffer to be sent immediately. This field can be <c>null</c>, which
+ indicates that event triggering is not to be done. The evaluator
+ can be set using the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> property. If this appender
+ has the <see cref="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy"/> (<see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property) set to
+ <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be set.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy">
+ <summary>
+ Indicates if the appender should overwrite events in the cyclic buffer
+ when it becomes full, or if the buffer should be flushed when the
+ buffer is full.
+ </summary>
+ <remarks>
+ If this field is set to <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must
+ be set.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossyEvaluator">
+ <summary>
+ The triggering event evaluator filters discarded events.
+ </summary>
+ <remarks>
+ The object that is used to determine if an event that is discarded should
+ really be discarded or if it should be sent to the appenders.
+ This field can be <c>null</c>, which indicates that all discarded events will
+ be discarded.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_fixFlags">
+ <summary>
+ Value indicating which fields in the event should be fixed
+ </summary>
+ <remarks>
+ By default all fields are fixed
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_eventMustBeFixed">
+ <summary>
+ The events delivered to the subclass must be fixed.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Lossy">
+ <summary>
+ Gets or sets a value that indicates whether the appender is lossy.
+ </summary>
+ <value>
+ <c>true</c> if the appender is lossy, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ This appender uses a buffer to store logging events before
+ delivering them. A triggering event causes the whole buffer
+ to be send to the remote sink. If the buffer overruns before
+ a triggering event then logging events could be lost. Set
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> to <c>false</c> to prevent logging events
+ from being lost.
+ </para>
+ <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize">
+ <summary>
+ Gets or sets the size of the cyclic buffer used to hold the
+ logging events.
+ </summary>
+ <value>
+ The size of the cyclic buffer used to hold the logging events.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option takes a positive integer
+ representing the maximum number of logging events to collect in
+ a cyclic buffer. When the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is reached,
+ oldest events are deleted as new events are added to the
+ buffer. By default the size of the cyclic buffer is 512 events.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to a value less than
+ or equal to 1 then no buffering will occur. The logging event
+ will be delivered synchronously (depending on the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>
+ and <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> properties). Otherwise the event will
+ be buffered.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the
+ buffer to be sent immediately.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the buffer to be
+ sent immediately.
+ </value>
+ <remarks>
+ <para>
+ The evaluator will be called for each event that is appended to this
+ appender. If the evaluator triggers then the current buffer will
+ immediately be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+ </para>
+ <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator">
+ <summary>
+ Gets or sets the value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+ </summary>
+ <value>
+ The value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+ </value>
+ <remarks>
+ <para>
+ The evaluator will be called for each event that is discarded from this
+ appender. If the evaluator triggers then the current buffer will immediately
+ be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.OnlyFixPartialEventData">
+ <summary>
+ Gets or sets a value indicating if only part of the logging event data
+ should be fixed.
+ </summary>
+ <value>
+ <c>true</c> if the appender should only fix part of the logging event
+ data, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Setting this property to <c>true</c> will cause only part of the
+ event data to be fixed and serialized. This will improve performance.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Fix">
+ <summary>
+ Gets or sets a the fields that will be fixed in the event
+ </summary>
+ <value>
+ The event fields that will be fixed before the event is buffered
+ </value>
+ <remarks>
+ <para>
+ The logging event needs to have certain thread specific values
+ captured before it can be buffered. See <see cref="P:log4net.Core.LoggingEvent.Fix"/>
+ for details.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Core.LoggingEvent.Fix"/>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppender"/> class.
+ </summary>
+ <remarks>
+ Public default constructor to initialize a new instance of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.OnClose">
+ <summary>
+ Override the parent method to close the database
+ </summary>
+ <remarks>
+ <para>
+ Closes the database command and database connection.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Inserts the events into the database.
+ </summary>
+ <param name="events">The events to insert into the database.</param>
+ <remarks>
+ <para>
+ Insert all the events specified in the <paramref name="events"/>
+ array into the database.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)">
+ <summary>
+ Adds a parameter to the command.
+ </summary>
+ <param name="parameter">The parameter to add to the command.</param>
+ <remarks>
+ <para>
+ Adds a parameter to the ordered list of command parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(System.Data.IDbTransaction,log4net.Core.LoggingEvent[])">
+ <summary>
+ Writes the events to the database using the transaction specified.
+ </summary>
+ <param name="dbTran">The transaction that the events will be executed under.</param>
+ <param name="events">The array of events to insert into the database.</param>
+ <remarks>
+ <para>
+ The transaction argument can be <c>null</c> if the appender has been
+ configured not to use transactions. See <see cref="P:log4net.Appender.AdoNetAppender.UseTransactions"/>
+ property for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.GetLogStatement(log4net.Core.LoggingEvent)">
+ <summary>
+ Formats the log message into database statement text.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ This method can be overridden by subclasses to provide
+ more control over the format of the database statement.
+ </remarks>
+ <returns>
+ Text that can be passed to a <see cref="T:System.Data.IDbCommand"/>.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseConnection">
+ <summary>
+ Connects to the database.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.ResolveConnectionType">
+ <summary>
+ Retrieves the class type of the ADO.NET provider.
+ </summary>
+ <remarks>
+ <para>
+ Gets the Type of the ADO.NET provider to use to connect to the
+ database. This method resolves the type specified in the
+ <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> property.
+ </para>
+ <para>
+ Subclasses can override this method to return a different type
+ if necessary.
+ </para>
+ </remarks>
+ <returns>The <see cref="T:System.Type"/> of the ADO.NET provider</returns>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseCommand">
+ <summary>
+ Prepares the database command and initialize the parameters.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_usePreparedCommand">
+ <summary>
+ Flag to indicate if we are using a command object
+ </summary>
+ <remarks>
+ <para>
+ Set to <c>true</c> when the appender is to use a prepared
+ statement or stored procedure to insert into the database.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_parameters">
+ <summary>
+ The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+ </summary>
+ <remarks>
+ <para>
+ The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_dbConnection">
+ <summary>
+ The <see cref="T:System.Data.IDbConnection"/> that will be used
+ to insert logging events into a database.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_dbCommand">
+ <summary>
+ The database command.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_connectionString">
+ <summary>
+ Database connection string.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_connectionType">
+ <summary>
+ String type name of the <see cref="T:System.Data.IDbConnection"/> type name.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_commandText">
+ <summary>
+ The text of the command.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_commandType">
+ <summary>
+ The command type.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_useTransactions">
+ <summary>
+ Indicates whether to use transactions when writing to the database.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_reconnectOnError">
+ <summary>
+ Indicates whether to use transactions when writing to the database.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ConnectionString">
+ <summary>
+ Gets or sets the database connection string that is used to connect to
+ the database.
+ </summary>
+ <value>
+ The database connection string used to connect to the database.
+ </value>
+ <remarks>
+ <para>
+ The connections string is specific to the connection type.
+ See <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> for more information.
+ </para>
+ </remarks>
+ <example>Connection string for MS Access via ODBC:
+ <code>"DSN=MS Access Database;UID=admin;PWD=;SystemDB=C:\data\System.mdw;SafeTransactions = 0;FIL=MS Access;DriverID = 25;DBQ=C:\data\train33.mdb"</code>
+ </example>
+ <example>Another connection string for MS Access via ODBC:
+ <code>"Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Work\cvs_root\log4net-1.2\access.mdb;UID=;PWD=;"</code>
+ </example>
+ <example>Connection string for MS Access via OLE DB:
+ <code>"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Work\cvs_root\log4net-1.2\access.mdb;User Id=;Password=;"</code>
+ </example>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ConnectionType">
+ <summary>
+ Gets or sets the type name of the <see cref="T:System.Data.IDbConnection"/> connection
+ that should be created.
+ </summary>
+ <value>
+ The type name of the <see cref="T:System.Data.IDbConnection"/> connection.
+ </value>
+ <remarks>
+ <para>
+ The type name of the ADO.NET provider to use.
+ </para>
+ <para>
+ The default is to use the OLE DB provider.
+ </para>
+ </remarks>
+ <example>Use the OLE DB Provider. This is the default value.
+ <code>System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ </example>
+ <example>Use the MS SQL Server Provider.
+ <code>System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ </example>
+ <example>Use the ODBC Provider.
+ <code>Microsoft.Data.Odbc.OdbcConnection,Microsoft.Data.Odbc,version=1.0.3300.0,publicKeyToken=b77a5c561934e089,culture=neutral</code>
+ This is an optional package that you can download from
+ <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a>
+ search for <b>ODBC .NET Data Provider</b>.
+ </example>
+ <example>Use the Oracle Provider.
+ <code>System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ This is an optional package that you can download from
+ <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a>
+ search for <b>.NET Managed Provider for Oracle</b>.
+ </example>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.CommandText">
+ <summary>
+ Gets or sets the command text that is used to insert logging events
+ into the database.
+ </summary>
+ <value>
+ The command text used to insert logging events into the database.
+ </value>
+ <remarks>
+ <para>
+ Either the text of the prepared statement or the
+ name of the stored procedure to execute to write into
+ the database.
+ </para>
+ <para>
+ The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property determines if
+ this text is a prepared statement or a stored procedure.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.CommandType">
+ <summary>
+ Gets or sets the command type to execute.
+ </summary>
+ <value>
+ The command type to execute.
+ </value>
+ <remarks>
+ <para>
+ This value may be either <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify
+ that the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> is a prepared statement to execute,
+ or <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify that the
+ <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property is the name of a stored procedure
+ to execute.
+ </para>
+ <para>
+ The default value is <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.UseTransactions">
+ <summary>
+ Should transactions be used to insert logging events in the database.
+ </summary>
+ <value>
+ <c>true</c> if transactions should be used to insert logging events in
+ the database, otherwise <c>false</c>. The default value is <c>true</c>.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets a value that indicates whether transactions should be used
+ to insert logging events in the database.
+ </para>
+ <para>
+ When set a single transaction will be used to insert the buffered events
+ into the database. Otherwise each event will be inserted without using
+ an explicit transaction.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ReconnectOnError">
+ <summary>
+ Should this appender try to reconnect to the database on error.
+ </summary>
+ <value>
+ <c>true</c> if the appender should try to reconnect to the database after an
+ error has occurred, otherwise <c>false</c>. The default value is <c>false</c>,
+ i.e. not to try to reconnect.
+ </value>
+ <remarks>
+ <para>
+ The default behaviour is for the appender not to try to reconnect to the
+ database if an error occurs. Subsequent logging events are discarded.
+ </para>
+ <para>
+ To force the appender to attempt to reconnect to the database set this
+ property to <c>true</c>.
+ </para>
+ <note>
+ When the appender attempts to connect to the database there may be a
+ delay of up to the connection timeout specified in the connection string.
+ This delay will block the calling application's thread.
+ Until the connection can be reestablished this potential delay may occur multiple times.
+ </note>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.Connection">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.Data.IDbConnection"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.Data.IDbConnection"/>.
+ </value>
+ <remarks>
+ <see cref="T:log4net.Appender.AdoNetAppender"/> creates a <see cref="T:System.Data.IDbConnection"/> to insert
+ logging events into a database. Classes deriving from <see cref="T:log4net.Appender.AdoNetAppender"/>
+ can use this property to get or set this <see cref="T:System.Data.IDbConnection"/>. Use the
+ underlying <see cref="T:System.Data.IDbConnection"/> returned from <see cref="P:log4net.Appender.AdoNetAppender.Connection"/> if
+ you require access beyond that which <see cref="T:log4net.Appender.AdoNetAppender"/> provides.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AdoNetAppenderParameter">
+ <summary>
+ Parameter type used by the <see cref="T:log4net.Appender.AdoNetAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ This class provides the basic database parameter properties
+ as defined by the <see cref="T:System.Data.IDbDataParameter"/> interface.
+ </para>
+ <para>This type can be subclassed to provide database specific
+ functionality. The two methods that are called externally are
+ <see cref="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)"/> and <see cref="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> class.
+ </summary>
+ <remarks>
+ Default constructor for the AdoNetAppenderParameter class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)">
+ <summary>
+ Prepare the specified database command object.
+ </summary>
+ <param name="command">The command to prepare.</param>
+ <remarks>
+ <para>
+ Prepares the database command object by adding
+ this parameter to its collection of parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the logging event and set the parameter value in the command.
+ </summary>
+ <param name="command">The command containing the parameter.</param>
+ <param name="loggingEvent">The event to be rendered.</param>
+ <remarks>
+ <para>
+ Renders the logging event using this parameters layout
+ object. Sets the value of the parameter on the command object.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_parameterName">
+ <summary>
+ The name of this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_dbType">
+ <summary>
+ The database type for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_inferType">
+ <summary>
+ Flag to infer type rather than use the DbType
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_precision">
+ <summary>
+ The precision for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_scale">
+ <summary>
+ The scale for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_size">
+ <summary>
+ The size for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_layout">
+ <summary>
+ The <see cref="T:log4net.Layout.IRawLayout"/> to use to render the
+ logging event into an object for this parameter.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.ParameterName">
+ <summary>
+ Gets or sets the name of this parameter.
+ </summary>
+ <value>
+ The name of this parameter.
+ </value>
+ <remarks>
+ <para>
+ The name of this parameter. The parameter name
+ must match up to a named parameter to the SQL stored procedure
+ or prepared statement.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.DbType">
+ <summary>
+ Gets or sets the database type for this parameter.
+ </summary>
+ <value>
+ The database type for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The database type for this parameter. This property should
+ be set to the database type from the <see cref="P:log4net.Appender.AdoNetAppenderParameter.DbType"/>
+ enumeration. See <see cref="P:System.Data.IDataParameter.DbType"/>.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the type from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDataParameter.DbType"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Precision">
+ <summary>
+ Gets or sets the precision for this parameter.
+ </summary>
+ <value>
+ The precision for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The maximum number of digits used to represent the Value.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the precision from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Precision"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Scale">
+ <summary>
+ Gets or sets the scale for this parameter.
+ </summary>
+ <value>
+ The scale for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The number of decimal places to which Value is resolved.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the scale from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Scale"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Size">
+ <summary>
+ Gets or sets the size for this parameter.
+ </summary>
+ <value>
+ The size for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The maximum size, in bytes, of the data within the column.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the size from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Size"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Layout">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Layout.IRawLayout"/> to use to
+ render the logging event into an object for this
+ parameter.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Layout.IRawLayout"/> used to render the
+ logging event into an object for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Layout.IRawLayout"/> that renders the value for this
+ parameter.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.RawLayoutConverter"/> can be used to adapt
+ any <see cref="T:log4net.Layout.ILayout"/> into a <see cref="T:log4net.Layout.IRawLayout"/>
+ for use in the property.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender">
+ <summary>
+ Appends logging events to the terminal using ANSI color escape sequences.
+ </summary>
+ <remarks>
+ <para>
+ AnsiColorTerminalAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user. It also allows the color of a specific level of message to be set.
+ </para>
+ <note>
+ This appender expects the terminal to understand the VT100 control set
+ in order to interpret the color codes. If the terminal or console does not
+ understand the control codes the behavior is not defined.
+ </note>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes each message to the <c>System.Console.Out</c> or
+ <c>System.Console.Error</c> that is set at the time the event is appended.
+ Therefore it is possible to programmatically redirect the output of this appender
+ (for example NUnit does this to capture program output). While this is the desired
+ behavior of this appender it may have security implications in your application.
+ </para>
+ <para>
+ When configuring the ANSI colored terminal appender, a mapping should be
+ specified to map a logging level to a color. For example:
+ </para>
+ <code lang="XML" escaped="true">
+ <mapping>
+ <level value="ERROR"/>
+ <foreColor value="White"/>
+ <backColor value="Red"/>
+ <attributes value="Bright,Underscore"/>
+ </mapping>
+ <mapping>
+ <level value="DEBUG"/>
+ <backColor value="Green"/>
+ </mapping>
+ </code>
+ <para>
+ The Level is the standard log4net logging level and ForeColor and BackColor can be any
+ of the following values:
+ <list type="bullet">
+ <item><term>Blue</term><description></description></item>
+ <item><term>Green</term><description></description></item>
+ <item><term>Red</term><description></description></item>
+ <item><term>White</term><description></description></item>
+ <item><term>Yellow</term><description></description></item>
+ <item><term>Purple</term><description></description></item>
+ <item><term>Cyan</term><description></description></item>
+ </list>
+ These color values cannot be combined together to make new colors.
+ </para>
+ <para>
+ The attributes can be any combination of the following:
+ <list type="bullet">
+ <item><term>Bright</term><description>foreground is brighter</description></item>
+ <item><term>Dim</term><description>foreground is dimmer</description></item>
+ <item><term>Underscore</term><description>message is underlined</description></item>
+ <item><term>Blink</term><description>foreground is blinking (does not work on all terminals)</description></item>
+ <item><term>Reverse</term><description>foreground and background are reversed</description></item>
+ <item><term>Hidden</term><description>output is hidden</description></item>
+ <item><term>Strikethrough</term><description>message has a line through it</description></item>
+ </list>
+ While any of these attributes may be combined together not all combinations
+ work well together, for example setting both <i>Bright</i> and <i>Dim</i> attributes makes
+ no sense.
+ </para>
+ </remarks>
+ <author>Patrick Wagstrom</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.PostEventCodes">
+ <summary>
+ Ansi code to reset terminal
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.AddMapping(log4net.Appender.AnsiColorTerminalAppender.LevelColors)">
+ <summary>
+ Add a mapping of level to color
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors"/> mapping to this appender.
+ Each mapping defines the foreground and background colours
+ for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to color mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_writeToErrorStream">
+ <summary>
+ Flag to write output to the error stream rather than the standard output stream
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to color value
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes">
+ <summary>
+ The enum of possible display attributes
+ </summary>
+ <remarks>
+ <para>
+ The following flags can be combined together to
+ form the ANSI color attributes.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Bright">
+ <summary>
+ text is bright
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Dim">
+ <summary>
+ text is dim
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Underscore">
+ <summary>
+ text is underlined
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Blink">
+ <summary>
+ text is blinking
+ </summary>
+ <remarks>
+ Not all terminals support this attribute
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Reverse">
+ <summary>
+ text and background colors are reversed
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Hidden">
+ <summary>
+ text is hidden
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Strikethrough">
+ <summary>
+ text is displayed with a strikethrough
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiColor">
+ <summary>
+ The enum of possible foreground or background color values for
+ use with the color mapping method
+ </summary>
+ <remarks>
+ <para>
+ The output can be in one for the following ANSI colors.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Black">
+ <summary>
+ color is black
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Red">
+ <summary>
+ color is red
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Green">
+ <summary>
+ color is green
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Yellow">
+ <summary>
+ color is yellow
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Blue">
+ <summary>
+ color is blue
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Magenta">
+ <summary>
+ color is magenta
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Cyan">
+ <summary>
+ color is cyan
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.White">
+ <summary>
+ color is white
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and the color it should be displayed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LevelMappingEntry">
+ <summary>
+ An entry in the <see cref="T:log4net.Util.LevelMapping"/>
+ </summary>
+ <remarks>
+ <para>
+ This is an abstract base class for types that are stored in the
+ <see cref="T:log4net.Util.LevelMapping"/> object.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LevelMappingEntry.#ctor">
+ <summary>
+ Default protected constructor
+ </summary>
+ <remarks>
+ <para>
+ Default protected constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMappingEntry.ActivateOptions">
+ <summary>
+ Initialize any options defined on this entry
+ </summary>
+ <remarks>
+ <para>
+ Should be overridden by any classes that need to initialise based on their options
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LevelMappingEntry.Level">
+ <summary>
+ The level that is the key for this mapping
+ </summary>
+ <value>
+ The <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this mapping
+ </value>
+ <remarks>
+ <para>
+ Get or set the <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this
+ mapping subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ActivateOptions">
+ <summary>
+ Initialize the options for the object
+ </summary>
+ <remarks>
+ <para>
+ Combine the <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> together
+ and append the attributes.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor">
+ <summary>
+ The mapped foreground color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped foreground color for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor">
+ <summary>
+ The mapped background color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped background color for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes">
+ <summary>
+ The color attributes for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The color attributes for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.CombinedColor">
+ <summary>
+ The combined <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/>, <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> and
+ <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes"/> suitable for setting the ansi terminal color.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Appender.IAppender"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ReadOnly(log4net.Appender.AppenderCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>AppenderCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ An <c>AppenderCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="F:log4net.Appender.AppenderCollection.EmptyCollection">
+ <summary>
+ An empty readonly static AppenderCollection
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>AppenderCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <c>AppenderCollection</c>.
+ </summary>
+ <param name="c">The <c>AppenderCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.IAppender[])">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Appender.IAppender"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[])">
+ <summary>
+ Copies the entire <c>AppenderCollection</c> to a one-dimensional
+ <see cref="T:log4net.Appender.IAppender"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[],System.Int32)">
+ <summary>
+ Copies the entire <c>AppenderCollection</c> to a one-dimensional
+ <see cref="T:log4net.Appender.IAppender"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Add(log4net.Appender.IAppender)">
+ <summary>
+ Adds a <see cref="T:log4net.Appender.IAppender"/> to the end of the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Clear">
+ <summary>
+ Removes all elements from the <c>AppenderCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Appender.AppenderCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Contains(log4net.Appender.IAppender)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Appender.IAppender"/> is in the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>AppenderCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IndexOf(log4net.Appender.IAppender)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Appender.IAppender"/>
+ in the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to locate in the <c>AppenderCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>AppenderCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Insert(System.Int32,log4net.Appender.IAppender)">
+ <summary>
+ Inserts an element into the <c>AppenderCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Remove(log4net.Appender.IAppender)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Appender.IAppender"/> from the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to remove from the <c>AppenderCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Appender.IAppender"/> was not found in the <c>AppenderCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>AppenderCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>AppenderCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Appender.AppenderCollection.Enumerator"/> for the entire <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.AppenderCollection)">
+ <summary>
+ Adds the elements of another <c>AppenderCollection</c> to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="x">The <c>AppenderCollection</c> whose elements should be added to the end of the current <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.IAppender[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> array to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Appender.IAppender"/> array whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> collection to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ToArray">
+ <summary>
+ Return the collection elements as an array
+ </summary>
+ <returns>the array</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>AppenderCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <returns>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</returns>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Appender.IAppender"/> at the specified index.
+ </summary>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value>true if the collection is read-only; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>AppenderCollection</c> can contain.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ <exclude/>
+ </member>
+ <member name="F:log4net.Appender.AppenderCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.#ctor(log4net.Appender.AppenderCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.ReadOnlyAppenderCollection">
+ <exclude/>
+ </member>
+ <member name="T:log4net.Appender.AspNetTraceAppender">
+ <summary>
+ <para>
+ Appends log events to the ASP.NET <see cref="T:System.Web.TraceContext"/> system.
+ </para>
+ </summary>
+ <remarks>
+ <para>
+ Diagnostic information and tracing messages that you specify are appended to the output
+ of the page that is sent to the requesting browser. Optionally, you can view this information
+ from a separate trace viewer (Trace.axd) that displays trace information for every page in a
+ given application.
+ </para>
+ <para>
+ Trace statements are processed and displayed only when tracing is enabled. You can control
+ whether tracing is displayed to a page, to the trace viewer, or both.
+ </para>
+ <para>
+ The logging event is passed to the <see cref="M:System.Web.TraceContext.Write(System.String)"/> or
+ <see cref="M:System.Web.TraceContext.Warn(System.String)"/> method depending on the level of the logging event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.AspNetTraceAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AspNetTraceAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AspNetTraceAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write the logging event to the ASP.NET trace
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Write the logging event to the ASP.NET trace
+ <c>HttpContext.Current.Trace</c>
+ (<see cref="T:System.Web.TraceContext"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AspNetTraceAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.BufferingForwardingAppender">
+ <summary>
+ Buffers events and then forwards them to attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ The events are buffered in this appender until conditions are
+ met to allow the appender to deliver the events to the attached
+ appenders. See <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> for the
+ conditions that cause the buffer to be sent.
+ </para>
+ <para>The forwarding appender can be used to specify different
+ thresholds and filters for the same appender at different locations
+ within the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Core.IAppenderAttachable">
+ <summary>
+ Interface for attaching appenders to objects.
+ </summary>
+ <remarks>
+ <para>
+ Interface for attaching, removing and retrieving appenders.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Attaches an appender.
+ </summary>
+ <param name="appender">The appender to add.</param>
+ <remarks>
+ <para>
+ Add the specified appender. The implementation may
+ choose to allow or deny duplicate appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.GetAppender(System.String)">
+ <summary>
+ Gets an attached appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to get.</param>
+ <returns>
+ The appender with the name specified, or <c>null</c> if no appender with the
+ specified name is found.
+ </returns>
+ <remarks>
+ <para>
+ Returns an attached appender with the <paramref name="name"/> specified.
+ If no appender with the specified name is found <c>null</c> will be
+ returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAllAppenders">
+ <summary>
+ Removes all attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ Removes and closes all attached appenders
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of attached appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.IAppenderAttachable.Appenders">
+ <summary>
+ Gets all attached appenders.
+ </summary>
+ <value>
+ A collection of attached appenders.
+ </value>
+ <remarks>
+ <para>
+ Gets a collection of attached appenders.
+ If there are no attached appenders the
+ implementation should return an empty
+ collection rather than <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingForwardingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.OnClose">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Send the events.
+ </summary>
+ <param name="events">The events that need to be send.</param>
+ <remarks>
+ <para>
+ Forwards the events to the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Adds an <see cref="T:log4net.Appender.IAppender"/> to the list of appenders of this
+ instance.
+ </summary>
+ <param name="newAppender">The <see cref="T:log4net.Appender.IAppender"/> to add to this appender.</param>
+ <remarks>
+ <para>
+ If the specified <see cref="T:log4net.Appender.IAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.GetAppender(System.String)">
+ <summary>
+ Looks for the appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to lookup.</param>
+ <returns>
+ The appender with the specified name, or <c>null</c>.
+ </returns>
+ <remarks>
+ <para>
+ Get the named appender attached to this buffering appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAllAppenders">
+ <summary>
+ Removes all previously added appenders from this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingForwardingAppender.m_appenderAttachedImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.BufferingForwardingAppender.Appenders">
+ <summary>
+ Gets the appenders contained in this appender as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ If no appenders can be found, then an <see cref="T:log4net.Util.EmptyCollection"/>
+ is returned.
+ </remarks>
+ <returns>
+ A collection of the appenders in this appender.
+ </returns>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender">
+ <summary>
+ Appends logging events to the console.
+ </summary>
+ <remarks>
+ <para>
+ ColoredConsoleAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user. It also allows the color of a specific type of message to be set.
+ </para>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes directly to the application's attached console
+ not to the <c>System.Console.Out</c> or <c>System.Console.Error</c> <c>TextWriter</c>.
+ The <c>System.Console.Out</c> and <c>System.Console.Error</c> streams can be
+ programmatically redirected (for example NUnit does this to capture program output).
+ This appender will ignore these redirections because it needs to use Win32
+ API calls to colorize the output. To respect these redirections the <see cref="T:log4net.Appender.ConsoleAppender"/>
+ must be used.
+ </para>
+ <para>
+ When configuring the colored console appender, mapping should be
+ specified to map a logging level to a color. For example:
+ </para>
+ <code lang="XML" escaped="true">
+ <mapping>
+ <level value="ERROR"/>
+ <foreColor value="White"/>
+ <backColor value="Red, HighIntensity"/>
+ </mapping>
+ <mapping>
+ <level value="DEBUG"/>
+ <backColor value="Green"/>
+ </mapping>
+ </code>
+ <para>
+ The Level is the standard log4net logging level and ForeColor and BackColor can be any
+ combination of the following values:
+ <list type="bullet">
+ <item><term>Blue</term><description></description></item>
+ <item><term>Green</term><description></description></item>
+ <item><term>Red</term><description></description></item>
+ <item><term>White</term><description></description></item>
+ <item><term>Yellow</term><description></description></item>
+ <item><term>Purple</term><description></description></item>
+ <item><term>Cyan</term><description></description></item>
+ <item><term>HighIntensity</term><description></description></item>
+ </list>
+ </para>
+ </remarks>
+ <author>Rick Hobbs</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor(log4net.Layout.ILayout,System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <param name="writeToErrorStream">flag set to <c>true</c> to write to the console error stream</param>
+ <remarks>
+ When <paramref name="writeToErrorStream"/> is set to <c>true</c>, output is written to
+ the standard error output stream. Otherwise, output is written to the standard
+ output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.AddMapping(log4net.Appender.ColoredConsoleAppender.LevelColors)">
+ <summary>
+ Add a mapping of level to color - done by the config file
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.ColoredConsoleAppender.LevelColors"/> mapping to this appender.
+ Each mapping defines the foreground and background colors
+ for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to color mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_writeToErrorStream">
+ <summary>
+ Flag to write output to the error stream rather than the standard output stream
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to color value
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_consoleOutputWriter">
+ <summary>
+ The console output stream writer to write to
+ </summary>
+ <remarks>
+ <para>
+ This writer is not thread safe.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender.Colors">
+ <summary>
+ The enum of possible color values for use with the color mapping method
+ </summary>
+ <remarks>
+ <para>
+ The following flags can be combined together to
+ form the colors.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.ColoredConsoleAppender"/>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Blue">
+ <summary>
+ color is blue
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Green">
+ <summary>
+ color is green
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Red">
+ <summary>
+ color is red
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.White">
+ <summary>
+ color is white
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Yellow">
+ <summary>
+ color is yellow
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Purple">
+ <summary>
+ color is purple
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Cyan">
+ <summary>
+ color is cyan
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.HighIntensity">
+ <summary>
+ color is intensified
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender.LevelColors">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and the color it should be displayed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.LevelColors.ActivateOptions">
+ <summary>
+ Initialize the options for the object
+ </summary>
+ <remarks>
+ <para>
+ Combine the <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor"/> together.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor">
+ <summary>
+ The mapped foreground color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped foreground color for the specified level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor">
+ <summary>
+ The mapped background color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped background color for the specified level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.CombinedColor">
+ <summary>
+ The combined <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor"/> suitable for
+ setting the console color.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.ConsoleAppender">
+ <summary>
+ Appends logging events to the console.
+ </summary>
+ <remarks>
+ <para>
+ ConsoleAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user.
+ </para>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes each message to the <c>System.Console.Out</c> or
+ <c>System.Console.Error</c> that is set at the time the event is appended.
+ Therefore it is possible to programmatically redirect the output of this appender
+ (for example NUnit does this to capture program output). While this is the desired
+ behavior of this appender it may have security implications in your application.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Appender.ConsoleAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ConsoleAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor(log4net.Layout.ILayout,System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <param name="writeToErrorStream">flag set to <c>true</c> to write to the console error stream</param>
+ <remarks>
+ When <paramref name="writeToErrorStream"/> is set to <c>true</c>, output is written to
+ the standard error output stream. Otherwise, output is written to the standard
+ output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ConsoleAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ConsoleAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.DebugAppender">
+ <summary>
+ Appends log events to the <see cref="T:System.Diagnostics.Debug"/> system.
+ </summary>
+ <remarks>
+ <para>
+ The application configuration file can be used to control what listeners
+ are actually used. See the MSDN documentation for the
+ <see cref="T:System.Diagnostics.Debug"/> class for details on configuring the
+ debug system.
+ </para>
+ <para>
+ Events are written using the <see cref="M:System.Diagnostics.Debug.Write(System.String,System.String)"/>
+ method. The event's logger name is passed as the value for the category name to the Write method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.DebugAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.DebugAppender"/>
+ with a specified layout.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Debug"/> system.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Debug"/> system.
+ If <see cref="P:log4net.Appender.DebugAppender.ImmediateFlush"/> is <c>true</c> then the <see cref="M:System.Diagnostics.Debug.Flush"/>
+ is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.DebugAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying writer or output stream
+ will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.DebugAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logs events are not actually written to persistent media if and
+ when the application crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.DebugAppender.ImmediateFlush">
+ <summary>
+ Gets or sets a value that indicates whether the appender will
+ flush at the end of each write.
+ </summary>
+ <remarks>
+ <para>The default behavior is to flush at the end of each
+ write. If the option is set to<c>false</c>, then the underlying
+ stream can defer writing to physical medium to a later time.
+ </para>
+ <para>
+ Avoiding the flush operation at the end of each append results
+ in a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.DebugAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.EventLogAppender">
+ <summary>
+ Writes events to the system event log.
+ </summary>
+ <remarks>
+ <para>
+ The <c>EventID</c> of the event log entry can be
+ set using the <c>EventLogEventID</c> property (<see cref="P:log4net.Core.LoggingEvent.Properties"/>)
+ on the <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ <para>
+ There is a limit of 32K characters for an event log message
+ </para>
+ <para>
+ When configuring the EventLogAppender a mapping can be
+ specified to map a logging level to an event log entry type. For example:
+ </para>
+ <code lang="XML">
+ &lt;mapping&gt;
+ &lt;level value="ERROR" /&gt;
+ &lt;eventLogEntryType value="Error" /&gt;
+ &lt;/mapping&gt;
+ &lt;mapping&gt;
+ &lt;level value="DEBUG" /&gt;
+ &lt;eventLogEntryType value="Information" /&gt;
+ &lt;/mapping&gt;
+ </code>
+ <para>
+ The Level is the standard log4net logging level and eventLogEntryType can be any value
+ from the <see cref="T:System.Diagnostics.EventLogEntryType"/> enum, i.e.:
+ <list type="bullet">
+ <item><term>Error</term><description>an error event</description></item>
+ <item><term>Warning</term><description>a warning event</description></item>
+ <item><term>Information</term><description>an informational event</description></item>
+ </list>
+ </para>
+ </remarks>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Thomas Voss</author>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.EventLogAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.EventLogAppender"/> class
+ with the specified <see cref="T:log4net.Layout.ILayout"/>.
+ </summary>
+ <param name="layout">The <see cref="T:log4net.Layout.ILayout"/> to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.AddMapping(log4net.Appender.EventLogAppender.Level2EventLogEntryType)">
+ <summary>
+ Add a mapping of level to <see cref="T:System.Diagnostics.EventLogEntryType"/> - done by the config file
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.EventLogAppender.Level2EventLogEntryType"/> mapping to this appender.
+ Each mapping defines the event log entry type for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.CreateEventSource(System.String,System.String,System.String)">
+ <summary>
+ Create an event log source
+ </summary>
+ <remarks>
+ Uses different API calls under NET_2_0
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>Writes the event to the system event log using the
+ <see cref="P:log4net.Appender.EventLogAppender.ApplicationName"/>.</para>
+
+ <para>If the event has an <c>EventID</c> property (see <see cref="P:log4net.Core.LoggingEvent.Properties"/>)
+ set then this integer will be used as the event log event id.</para>
+
+ <para>
+ There is a limit of 32K characters for an event log message
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.GetEntryType(log4net.Core.Level)">
+ <summary>
+ Get the equivalent <see cref="T:System.Diagnostics.EventLogEntryType"/> for a <see cref="T:log4net.Core.Level"/> <paramref name="p"/>
+ </summary>
+ <param name="level">the Level to convert to an EventLogEntryType</param>
+ <returns>The equivalent <see cref="T:System.Diagnostics.EventLogEntryType"/> for a <see cref="T:log4net.Core.Level"/> <paramref name="p"/></returns>
+ <remarks>
+ Because there are fewer applicable <see cref="T:System.Diagnostics.EventLogEntryType"/>
+ values to use in logging levels than there are in the
+ <see cref="T:log4net.Core.Level"/> this is a one way mapping. There is
+ a loss of information during the conversion.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_logName">
+ <summary>
+ The log name is the section in the event logs where the messages
+ are stored.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_applicationName">
+ <summary>
+ Name of the application to use when logging. This appears in the
+ application column of the event log named by <see cref="F:log4net.Appender.EventLogAppender.m_logName"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_machineName">
+ <summary>
+ The name of the machine which holds the event log. This is
+ currently only allowed to be '.' i.e. the current machine.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to EventLogEntryType
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.LogName">
+ <summary>
+ The name of the log where messages will be stored.
+ </summary>
+ <value>
+ The string name of the log where messages will be stored.
+ </value>
+ <remarks>
+ <para>This is the name of the log as it appears in the Event Viewer
+ tree. The default value is to log into the <c>Application</c>
+ log, this is where most applications write their events. However
+ if you need a separate log for your application (or applications)
+ then you should set the <see cref="P:log4net.Appender.EventLogAppender.LogName"/> appropriately.</para>
+ <para>This should not be used to distinguish your event log messages
+ from those of other applications, the <see cref="P:log4net.Appender.EventLogAppender.ApplicationName"/>
+ property should be used to distinguish events. This property should be
+ used to group together events into a single log.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.ApplicationName">
+ <summary>
+ Property used to set the Application name. This appears in the
+ event logs when logging.
+ </summary>
+ <value>
+ The string used to distinguish events from different sources.
+ </value>
+ <remarks>
+ Sets the event log source property.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.MachineName">
+ <summary>
+ This property is used to return the name of the computer to use
+ when accessing the event logs. Currently, this is the current
+ computer, denoted by a dot "."
+ </summary>
+ <value>
+ The string name of the machine holding the event log that
+ will be logged into.
+ </value>
+ <remarks>
+ This property cannot be changed. It is currently set to '.'
+ i.e. the local machine. This may be changed in future.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> used to write to the EventLog.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> used to write to the EventLog.
+ </value>
+ <remarks>
+ <para>
+ The system security context used to write to the EventLog.
+ </para>
+ <para>
+ Unless a <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.EventLogAppender.Level2EventLogEntryType">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and its event log entry type.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType">
+ <summary>
+ The <see cref="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType"/> for this entry
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The <see cref="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType"/> for this entry
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender">
+ <summary>
+ Appends logging events to a file.
+ </summary>
+ <remarks>
+ <para>
+ Logging events are sent to the file specified by
+ the <see cref="P:log4net.Appender.FileAppender.File"/> property.
+ </para>
+ <para>
+ The file can be opened in either append or overwrite mode
+ by specifying the <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property.
+ If the file path is relative it is taken as relative from
+ the application base directory. The file encoding can be
+ specified by setting the <see cref="P:log4net.Appender.FileAppender.Encoding"/> property.
+ </para>
+ <para>
+ The layout's <see cref="P:log4net.Layout.ILayout.Header"/> and <see cref="P:log4net.Layout.ILayout.Footer"/>
+ values will be written each time the file is opened and closed
+ respectively. If the <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property is <see langword="true"/>
+ then the file may contain multiple copies of the header and footer.
+ </para>
+ <para>
+ This appender will first try to open the file for writing when <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/>
+ is called. This will typically be during configuration.
+ If the file cannot be opened for writing the appender will attempt
+ to open the file again each time a message is logged to the appender.
+ If the file cannot be opened for writing when a message is logged then
+ the message will be discarded by this appender.
+ </para>
+ <para>
+ The <see cref="T:log4net.Appender.FileAppender"/> supports pluggable file locking models via
+ the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> property.
+ The default behavior, implemented by <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/>
+ is to obtain an exclusive write lock on the file until this appender is closed.
+ The alternative model, <see cref="T:log4net.Appender.FileAppender.MinimalLock"/>, only holds a
+ write lock while the appender is writing a logging event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Rodrigo B. de Oliveira</author>
+ <author>Douglas de la Torre</author>
+ <author>Niall Daley</author>
+ </member>
+ <member name="T:log4net.Appender.TextWriterAppender">
+ <summary>
+ Sends logging events to a <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ An Appender that writes to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ <para>
+ This appender may be used stand alone if initialized with an appropriate
+ writer, however it is typically used as a base class for an appender that
+ can open a <see cref="T:System.IO.TextWriter"/> to write to.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor(log4net.Layout.ILayout,System.IO.Stream)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class and
+ sets the output destination to a new <see cref="T:System.IO.StreamWriter"/> initialized
+ with the specified <see cref="T:System.IO.Stream"/>.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <param name="os">The <see cref="T:System.IO.Stream"/> to output to.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor(log4net.Layout.ILayout,System.IO.TextWriter)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class and sets
+ the output destination to the specified <see cref="T:System.IO.StreamWriter"/>.
+ </summary>
+ <param name="layout">The layout to use with this appender</param>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to output to</param>
+ <remarks>
+ The <see cref="T:System.IO.TextWriter"/> must have been previously opened.
+ </remarks>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.PreAppendCheck">
+ <summary>
+ This method determines if there is a sense in attempting to append.
+ </summary>
+ <remarks>
+ <para>
+ This method checked if an output target has been set and if a
+ layout has been set.
+ </para>
+ </remarks>
+ <returns><c>false</c> if any of the preconditions fail.</returns>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes a log statement to the output stream if the output stream exists
+ and is writable.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])"/>
+ method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ This method writes all the bulk logged events to the output writer
+ before flushing the stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.OnClose">
+ <summary>
+ Close this appender instance. The underlying stream or writer is also closed.
+ </summary>
+ <remarks>
+ Closed appenders cannot be reused.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteFooterAndCloseWriter">
+ <summary>
+ Writes the footer and closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Writes the footer and closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.CloseWriter">
+ <summary>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Reset">
+ <summary>
+ Clears internal references to the underlying <see cref="T:System.IO.TextWriter"/>
+ and other variables.
+ </summary>
+ <remarks>
+ <para>
+ Subclasses can override this method for an alternate closing behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteFooter">
+ <summary>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteHeader">
+ <summary>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.PrepareWriter">
+ <summary>
+ Called to allow a subclass to lazily initialize the writer
+ </summary>
+ <remarks>
+ <para>
+ This method is called when an event is logged and the <see cref="P:log4net.Appender.TextWriterAppender.Writer"/> or
+ <see cref="P:log4net.Appender.TextWriterAppender.QuietWriter"/> have not been set. This allows a subclass to
+ attempt to initialize the writer multiple times.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.TextWriterAppender.m_qtw">
+ <summary>
+ This is the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.TextWriterAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying <see cref="T:System.IO.TextWriter"/>
+ or output stream will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.TextWriterAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logging events are not actually persisted if and when the application
+ crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.ImmediateFlush">
+ <summary>
+ Gets or set whether the appender will flush at the end
+ of each append operation.
+ </summary>
+ <value>
+ <para>
+ The default behavior is to flush at the end of each
+ append operation.
+ </para>
+ <para>
+ If this option is set to <c>false</c>, then the underlying
+ stream can defer persisting the logging event to a later
+ time.
+ </para>
+ </value>
+ <remarks>
+ Avoiding the flush operation at the end of each append results in
+ a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.Writer">
+ <summary>
+ Sets the <see cref="T:System.IO.TextWriter"/> where the log output will go.
+ </summary>
+ <remarks>
+ <para>
+ The specified <see cref="T:System.IO.TextWriter"/> must be open and writable.
+ </para>
+ <para>
+ The <see cref="T:System.IO.TextWriter"/> will be closed when the appender
+ instance is closed.
+ </para>
+ <para>
+ <b>Note:</b> Logging to an unopened <see cref="T:System.IO.TextWriter"/> will fail.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.ErrorHandler">
+ <summary>
+ Gets or set the <see cref="T:log4net.Core.IErrorHandler"/> and the underlying
+ <see cref="T:log4net.Util.QuietTextWriter"/>, if any, for this appender.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.IErrorHandler"/> for this appender.
+ </value>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.QuietWriter">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Util.QuietTextWriter"/> where logging events are written.
+ </value>
+ <remarks>
+ <para>
+ This is the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor(log4net.Layout.ILayout,System.String,System.Boolean)">
+ <summary>
+ Construct a new appender using the layout, file and append mode.
+ </summary>
+ <param name="layout">the layout to use with this appender</param>
+ <param name="filename">the full path to the file to write to</param>
+ <param name="append">flag to indicate if the file should be appended to</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor(log4net.Layout.ILayout,System.String)">
+ <summary>
+ Construct a new appender using the layout and file specified.
+ The file will be appended to.
+ </summary>
+ <param name="layout">the layout to use with this appender</param>
+ <param name="filename">the full path to the file to write to</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ActivateOptions">
+ <summary>
+ Activate the options on the file appender.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ This will cause the file to be opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Reset">
+ <summary>
+ Closes any previously opened file and calls the parent's <see cref="M:log4net.Appender.TextWriterAppender.Reset"/>.
+ </summary>
+ <remarks>
+ <para>
+ Resets the filename and the file stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.PrepareWriter">
+ <summary>
+ Called to initialize the file writer
+ </summary>
+ <remarks>
+ <para>
+ Will be called for each logged message until the file is
+ successfully opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes a log statement to the output stream if the output stream exists
+ and is writable.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])"/>
+ method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ Acquires the output file locks once before writing all the events to
+ the stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.WriteFooter">
+ <summary>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.WriteHeader">
+ <summary>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.CloseWriter">
+ <summary>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.CloseFile">
+ <summary>
+ Closes the previously opened file.
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Layout.ILayout.Footer"/> to the file and then
+ closes the file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SafeOpenFile(System.String,System.Boolean)">
+ <summary>
+ Sets and <i>opens</i> the file where the log output will go. The specified file must be writable.
+ </summary>
+ <param name="fileName">The path to the log file. Must be a fully qualified path.</param>
+ <param name="append">If true will append to fileName. Otherwise will truncate fileName</param>
+ <remarks>
+ <para>
+ Calls <see cref="M:log4net.Appender.FileAppender.OpenFile(System.String,System.Boolean)"/> but guarantees not to throw an exception.
+ Errors are passed to the <see cref="P:log4net.Appender.TextWriterAppender.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.OpenFile(System.String,System.Boolean)">
+ <summary>
+ Sets and <i>opens</i> the file where the log output will go. The specified file must be writable.
+ </summary>
+ <param name="fileName">The path to the log file. Must be a fully qualified path.</param>
+ <param name="append">If true will append to fileName. Otherwise will truncate fileName</param>
+ <remarks>
+ <para>
+ If there was already an opened file, then the previous file
+ is closed first.
+ </para>
+ <para>
+ This method will ensure that the directory structure
+ for the <paramref name="fileName"/> specified exists.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.Stream)">
+ <summary>
+ Sets the quiet writer used for file output
+ </summary>
+ <param name="fileStream">the file stream that has been opened for writing</param>
+ <remarks>
+ <para>
+ This implementation of <see cref="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.Stream)"/> creates a <see cref="T:System.IO.StreamWriter"/>
+ over the <paramref name="fileStream"/> and passes it to the
+ <see cref="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.TextWriter)"/> method.
+ </para>
+ <para>
+ This method can be overridden by sub classes that want to wrap the
+ <see cref="T:System.IO.Stream"/> in some way, for example to encrypt the output
+ data using a <c>System.Security.Cryptography.CryptoStream</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.TextWriter)">
+ <summary>
+ Sets the quiet writer being used.
+ </summary>
+ <param name="writer">the writer over the file stream that has been opened for writing</param>
+ <remarks>
+ <para>
+ This method can be overridden by sub classes that want to
+ wrap the <see cref="T:System.IO.TextWriter"/> in some way.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_appendToFile">
+ <summary>
+ Flag to indicate if we should append to the file
+ or overwrite the file. The default is to append.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_fileName">
+ <summary>
+ The name of the log file.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_encoding">
+ <summary>
+ The encoding to use for the file stream.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_stream">
+ <summary>
+ The stream to log to. Has added locking semantics
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_lockingModel">
+ <summary>
+ The locking model to use
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.File">
+ <summary>
+ Gets or sets the path to the file that logging will be written to.
+ </summary>
+ <value>
+ The path to the file that logging will be written to.
+ </value>
+ <remarks>
+ <para>
+ If the path is relative it is taken as relative from
+ the application base directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.AppendToFile">
+ <summary>
+ Gets or sets a flag that indicates whether the file should be
+ appended to or overwritten.
+ </summary>
+ <value>
+ Indicates whether the file should be appended to or overwritten.
+ </value>
+ <remarks>
+ <para>
+ If the value is set to false then the file will be overwritten, if
+ it is set to true then the file will be appended to.
+ </para>
+ The default value is true.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.Encoding">
+ <summary>
+ Gets or sets <see cref="P:log4net.Appender.FileAppender.Encoding"/> used to write to the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.Encoding"/> used to write to the file.
+ </value>
+ <remarks>
+ <para>
+ The default encoding set is <see cref="P:System.Text.Encoding.Default"/>
+ which is the encoding for the system's current ANSI code page.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> used to write to the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> used to write to the file.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.LockingModel">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to handle locking of the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to lock the file.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to handle locking of the file.
+ </para>
+ <para>
+ There are two built in locking models, <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/> and <see cref="T:log4net.Appender.FileAppender.MinimalLock"/>.
+ The former locks the file from the start of logging to the end and the
+ later lock only for the minimal amount of time when logging each message.
+ </para>
+ <para>
+ The default locking model is the <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.LockingStream">
+ <summary>
+ Write only <see cref="T:System.IO.Stream"/> that uses the <see cref="T:log4net.Appender.FileAppender.LockingModelBase"/>
+ to manage access to an underlying resource.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingStream.BeginWrite(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)">
+ <summary>
+ True asynchronous writes are not supported, the implementation forces a synchronous write.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LogException">
+ <summary>
+ Exception base type for log4net.
+ </summary>
+ <remarks>
+ <para>
+ This type extends <see cref="T:System.ApplicationException"/>. It
+ does not add any new functionality but does differentiate the
+ type of exception being thrown.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class with
+ the specified message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.String,System.Exception)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class
+ with the specified message and inner exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.LockingModelBase">
+ <summary>
+ Locking model base class
+ </summary>
+ <remarks>
+ <para>
+ Base class for the locking models available to the <see cref="T:log4net.Appender.FileAppender"/> derived loggers.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Open the output file
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.LockingModelBase.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Acquire the lock on the file in preparation for writing to it.
+ Return a stream pointing to the file. <see cref="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock"/>
+ must be called to release the lock on the output file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Release the lock on the file. No further writes will be made to the
+ stream until <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/> is called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.LockingModelBase.CurrentAppender">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Appender.FileAppender"/> for this LockingModel
+ </summary>
+ <value>
+ The <see cref="T:log4net.Appender.FileAppender"/> for this LockingModel
+ </value>
+ <remarks>
+ <para>
+ The file appender this locking model is attached to and working on
+ behalf of.
+ </para>
+ <para>
+ The file appender is used to locate the security context and the error handler to use.
+ </para>
+ <para>
+ The value of this property will be set before <see cref="M:log4net.Appender.FileAppender.LockingModelBase.OpenFile(System.String,System.Boolean,System.Text.Encoding)"/> is
+ called.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.ExclusiveLock">
+ <summary>
+ Hold an exclusive lock on the output file
+ </summary>
+ <remarks>
+ <para>
+ Open the file once for writing and hold it open until <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile"/> is called.
+ Maintains an exclusive lock on the file during this time.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Open the file specified and prepare for logging.
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Does nothing. The lock is already taken
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Does nothing. The lock will be released when the file is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.MinimalLock">
+ <summary>
+ Acquires the file lock for each write
+ </summary>
+ <remarks>
+ <para>
+ Opens the file once for each <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/>/<see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/> cycle,
+ thus holding the lock for the minimal amount of time. This method of locking
+ is considerably slower than <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/> but allows
+ other processes to move/delete the log file whilst logging continues.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Prepares to open the file when the first message is logged.
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.MinimalLock.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Acquire the lock on the file in preparation for writing to it.
+ Return a stream pointing to the file. <see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/>
+ must be called to release the lock on the output file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Release the lock on the file. No further writes will be made to the
+ stream until <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/> is called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.ForwardingAppender">
+ <summary>
+ This appender forwards logging events to attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ The forwarding appender can be used to specify different thresholds
+ and filters for the same appender at different locations within the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ForwardingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.OnClose">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Forward the logging event to the attached appenders
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Delivers the logging event to all the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Forward the logging events to the attached appenders
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ Delivers the logging events to all the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Adds an <see cref="T:log4net.Appender.IAppender"/> to the list of appenders of this
+ instance.
+ </summary>
+ <param name="newAppender">The <see cref="T:log4net.Appender.IAppender"/> to add to this appender.</param>
+ <remarks>
+ <para>
+ If the specified <see cref="T:log4net.Appender.IAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.GetAppender(System.String)">
+ <summary>
+ Looks for the appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to lookup.</param>
+ <returns>
+ The appender with the specified name, or <c>null</c>.
+ </returns>
+ <remarks>
+ <para>
+ Get the named appender attached to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAllAppenders">
+ <summary>
+ Removes all previously added appenders from this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ForwardingAppender.m_appenderAttachedImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.ForwardingAppender.Appenders">
+ <summary>
+ Gets the appenders contained in this appender as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ If no appenders can be found, then an <see cref="T:log4net.Util.EmptyCollection"/>
+ is returned.
+ </remarks>
+ <returns>
+ A collection of the appenders in this appender.
+ </returns>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender">
+ <summary>
+ Logs events to a local syslog service.
+ </summary>
+ <remarks>
+ <note>
+ This appender uses the POSIX libc library functions <c>openlog</c>, <c>syslog</c>, and <c>closelog</c>.
+ If these functions are not available on the local system then this appender will not work!
+ </note>
+ <para>
+ The functions <c>openlog</c>, <c>syslog</c>, and <c>closelog</c> are specified in SUSv2 and
+ POSIX 1003.1-2001 standards. These are used to log messages to the local syslog service.
+ </para>
+ <para>
+ This appender talks to a local syslog service. If you need to log to a remote syslog
+ daemon and you cannot configure your local syslog service to do this you may be
+ able to use the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> to log via UDP.
+ </para>
+ <para>
+ Syslog messages must have a facility and and a severity. The severity
+ is derived from the Level of the logging event.
+ The facility must be chosen from the set of defined syslog
+ <see cref="T:log4net.Appender.LocalSyslogAppender.SyslogFacility"/> values. The facilities list is predefined
+ and cannot be extended.
+ </para>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.LocalSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Util.SystemInfo.ApplicationFriendlyName"/>).
+ </para>
+ </remarks>
+ <author>Rob Lyon</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.LocalSyslogAppender"/> class.
+ </summary>
+ <remarks>
+ This instance of the <see cref="T:log4net.Appender.LocalSyslogAppender"/> class is set up to write
+ to a local syslog service.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.AddMapping(log4net.Appender.LocalSyslogAppender.LevelSeverity)">
+ <summary>
+ Add a mapping of level to severity
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Adds a <see cref="T:log4net.Appender.LocalSyslogAppender.LevelSeverity"/> to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to a remote syslog daemon.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.OnClose">
+ <summary>
+ Close the syslog when the appender is closed
+ </summary>
+ <remarks>
+ <para>
+ Close the syslog when the appender is closed
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.GetSeverity(log4net.Core.Level)">
+ <summary>
+ Translates a log4net level to a syslog severity.
+ </summary>
+ <param name="level">A log4net level.</param>
+ <returns>A syslog severity.</returns>
+ <remarks>
+ <para>
+ Translates a log4net level to a syslog severity.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.GeneratePriority(log4net.Appender.LocalSyslogAppender.SyslogFacility,log4net.Appender.LocalSyslogAppender.SyslogSeverity)">
+ <summary>
+ Generate a syslog priority.
+ </summary>
+ <param name="facility">The syslog facility.</param>
+ <param name="severity">The syslog severity.</param>
+ <returns>A syslog priority.</returns>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_facility">
+ <summary>
+ The facility. The default facility is <see cref="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_identity">
+ <summary>
+ The message identity
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_handleToIdentity">
+ <summary>
+ Marshaled handle to the identity string. We have to hold on to the
+ string as the <c>openlog</c> and <c>syslog</c> APIs just hold the
+ pointer to the ident and dereference it for each log message.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to syslog severity
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.openlog(System.IntPtr,System.Int32,log4net.Appender.LocalSyslogAppender.SyslogFacility)">
+ <summary>
+ Open connection to system logger.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.syslog(System.Int32,System.String,System.String)">
+ <summary>
+ Generate a log message.
+ </summary>
+ <remarks>
+ <para>
+ The libc syslog method takes a format string and a variable argument list similar
+ to the classic printf function. As this type of vararg list is not supported
+ by C# we need to specify the arguments explicitly. Here we have specified the
+ format string with a single message argument. The caller must set the format
+ string to <c>"%s"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.closelog">
+ <summary>
+ Close descriptor used to write to system logger.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.Identity">
+ <summary>
+ Message identity
+ </summary>
+ <remarks>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.LocalSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Util.SystemInfo.ApplicationFriendlyName"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.Facility">
+ <summary>
+ Syslog facility
+ </summary>
+ <remarks>
+ Set to one of the <see cref="T:log4net.Appender.LocalSyslogAppender.SyslogFacility"/> values. The list of
+ facilities is predefined and cannot be extended. The default value
+ is <see cref="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User"/>.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.SyslogSeverity">
+ <summary>
+ syslog severities
+ </summary>
+ <remarks>
+ <para>
+ The log4net Level maps to a syslog severity using the
+ <see cref="M:log4net.Appender.LocalSyslogAppender.AddMapping(log4net.Appender.LocalSyslogAppender.LevelSeverity)"/> method and the <see cref="T:log4net.Appender.LocalSyslogAppender.LevelSeverity"/>
+ class. The severity is set on <see cref="P:log4net.Appender.LocalSyslogAppender.LevelSeverity.Severity"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Emergency">
+ <summary>
+ system is unusable
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Alert">
+ <summary>
+ action must be taken immediately
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Critical">
+ <summary>
+ critical conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Error">
+ <summary>
+ error conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Warning">
+ <summary>
+ warning conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Notice">
+ <summary>
+ normal but significant condition
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Informational">
+ <summary>
+ informational
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Debug">
+ <summary>
+ debug-level messages
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.SyslogFacility">
+ <summary>
+ syslog facilities
+ </summary>
+ <remarks>
+ <para>
+ The syslog facility defines which subsystem the logging comes from.
+ This is set on the <see cref="P:log4net.Appender.LocalSyslogAppender.Facility"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Kernel">
+ <summary>
+ kernel messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User">
+ <summary>
+ random user-level messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Mail">
+ <summary>
+ mail system
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Daemons">
+ <summary>
+ system daemons
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Authorization">
+ <summary>
+ security/authorization messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Syslog">
+ <summary>
+ messages generated internally by syslogd
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Printer">
+ <summary>
+ line printer subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.News">
+ <summary>
+ network news subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Uucp">
+ <summary>
+ UUCP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Clock">
+ <summary>
+ clock (cron/at) daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Authorization2">
+ <summary>
+ security/authorization messages (private)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Ftp">
+ <summary>
+ ftp daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Ntp">
+ <summary>
+ NTP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Audit">
+ <summary>
+ log audit
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Alert">
+ <summary>
+ log alert
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Clock2">
+ <summary>
+ clock daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local0">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local1">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local2">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local3">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local4">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local5">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local6">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local7">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.LevelSeverity">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </summary>
+ <remarks>
+ <para>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.LevelSeverity.Severity">
+ <summary>
+ The mapped syslog severity for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped syslog severity for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.MemoryAppender">
+ <summary>
+ Stores logging events in an array.
+ </summary>
+ <remarks>
+ <para>
+ The memory appender stores all the logging events
+ that are appended in an in-memory array.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Appender.MemoryAppender.GetEvents"/> method to get
+ the current list of events that have been appended.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Appender.MemoryAppender.Clear"/> method to clear the
+ current list of events.
+ </para>
+ </remarks>
+ <author>Julian Biddle</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.MemoryAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.GetEvents">
+ <summary>
+ Gets the events that have been logged.
+ </summary>
+ <returns>The events that have been logged</returns>
+ <remarks>
+ <para>
+ Gets the events that have been logged.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>Stores the <paramref name="loggingEvent"/> in the events list.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.Clear">
+ <summary>
+ Clear the list of events
+ </summary>
+ <remarks>
+ Clear the list of events
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.MemoryAppender.m_eventsList">
+ <summary>
+ The list of events that have been appended.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.MemoryAppender.m_fixFlags">
+ <summary>
+ Value indicating which fields in the event should be fixed
+ </summary>
+ <remarks>
+ By default all fields are fixed
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.MemoryAppender.OnlyFixPartialEventData">
+ <summary>
+ Gets or sets a value indicating whether only part of the logging event
+ data should be fixed.
+ </summary>
+ <value>
+ <c>true</c> if the appender should only fix part of the logging event
+ data, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Setting this property to <c>true</c> will cause only part of the event
+ data to be fixed and stored in the appender, hereby improving performance.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.MemoryAppender.Fix">
+ <summary>
+ Gets or sets the fields that will be fixed in the event
+ </summary>
+ <remarks>
+ <para>
+ The logging event needs to have certain thread specific values
+ captured before it can be buffered. See <see cref="P:log4net.Core.LoggingEvent.Fix"/>
+ for details.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.NetSendAppender">
+ <summary>
+ Logs entries by sending network messages using the
+ <see cref="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)"/> native function.
+ </summary>
+ <remarks>
+ <para>
+ You can send messages only to names that are active
+ on the network. If you send the message to a user name,
+ that user must be logged on and running the Messenger
+ service to receive the message.
+ </para>
+ <para>
+ The receiver will get a top most window displaying the
+ messages one at a time, therefore this appender should
+ not be used to deliver a high volume of messages.
+ </para>
+ <para>
+ The following table lists some possible uses for this appender :
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>Action</term>
+ <description>Property Value(s)</description>
+ </listheader>
+ <item>
+ <term>Send a message to a user account on the local machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the local machine&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to a user account on a remote machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the remote machine&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to a domain user account</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of a domain controller | uninitialized&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to all the names in a workgroup or domain</term>
+ <description>
+ <para>
+ <paramref name="Recipient"/> = &lt;workgroup name | domain name&gt;*
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message from the local machine to a remote machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the local machine | uninitialized&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;name of the remote machine&gt;
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ <b>Note :</b> security restrictions apply for sending
+ network messages, see <see cref="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)"/>
+ for more information.
+ </para>
+ </remarks>
+ <example>
+ <para>
+ An example configuration section to log information
+ using this appender from the local machine, named
+ LOCAL_PC, to machine OPERATOR_PC :
+ </para>
+ <code lang="XML" escaped="true">
+ <appender name="NetSendAppender_Operator" type="log4net.Appender.NetSendAppender">
+ <server value="LOCAL_PC"/>
+ <recipient value="OPERATOR_PC"/>
+ <layout type="log4net.Layout.PatternLayout" value="%-5p %c [%x] - %m%n"/>
+ </appender>
+ </code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_server">
+ <summary>
+ The DNS or NetBIOS name of the server on which the function is to execute.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_sender">
+ <summary>
+ The sender of the network message.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_recipient">
+ <summary>
+ The message alias to which the message should be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.#ctor">
+ <summary>
+ Initializes the appender.
+ </summary>
+ <remarks>
+ The default constructor initializes all fields to their default values.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The appender will be ignored if no <see cref="P:log4net.Appender.NetSendAppender.Recipient"/> was specified.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required property <see cref="P:log4net.Appender.NetSendAppender.Recipient"/> was not specified.</exception>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Sends the event using a network message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)">
+ <summary>
+ Sends a buffer of information to a registered message alias.
+ </summary>
+ <param name="serverName">The DNS or NetBIOS name of the server on which the function is to execute.</param>
+ <param name="msgName">The message alias to which the message buffer should be sent</param>
+ <param name="fromName">The originator of the message.</param>
+ <param name="buffer">The message text.</param>
+ <param name="bufferSize">The length, in bytes, of the message text.</param>
+ <remarks>
+ <para>
+ The following restrictions apply for sending network messages:
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>Platform</term>
+ <description>Requirements</description>
+ </listheader>
+ <item>
+ <term>Windows NT</term>
+ <description>
+ <para>
+ No special group membership is required to send a network message.
+ </para>
+ <para>
+ Admin, Accounts, Print, or Server Operator group membership is required to
+ successfully send a network message on a remote server.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Windows 2000 or later</term>
+ <description>
+ <para>
+ If you send a message on a domain controller that is running Active Directory,
+ access is allowed or denied based on the access control list (ACL) for the securable
+ object. The default ACL permits only Domain Admins and Account Operators to send a network message.
+ </para>
+ <para>
+ On a member server or workstation, only Administrators and Server Operators can send a network message.
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ For more information see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/security_requirements_for_the_network_management_functions.asp">Security Requirements for the Network Management Functions</a>.
+ </para>
+ </remarks>
+ <returns>
+ <para>
+ If the function succeeds, the return value is zero.
+ </para>
+ </returns>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Sender">
+ <summary>
+ Gets or sets the sender of the message.
+ </summary>
+ <value>
+ The sender of the message.
+ </value>
+ <remarks>
+ If this property is not specified, the message is sent from the local computer.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Recipient">
+ <summary>
+ Gets or sets the message alias to which the message should be sent.
+ </summary>
+ <value>
+ The recipient of the message.
+ </value>
+ <remarks>
+ This property should always be specified in order to send a message.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Server">
+ <summary>
+ Gets or sets the DNS or NetBIOS name of the remote server on which the function is to execute.
+ </summary>
+ <value>
+ DNS or NetBIOS name of the remote server on which the function is to execute.
+ </value>
+ <remarks>
+ <para>
+ For Windows NT 4.0 and earlier, the string should begin with \\.
+ </para>
+ <para>
+ If this property is not specified, the local computer is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> used to call the NetSend method.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> used to call the NetSend method.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.OutputDebugStringAppender">
+ <summary>
+ Appends log events to the OutputDebugString system.
+ </summary>
+ <remarks>
+ <para>
+ OutputDebugStringAppender appends log events to the
+ OutputDebugString system.
+ </para>
+ <para>
+ The string is passed to the native <c>OutputDebugString</c>
+ function.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.OutputDebugStringAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write the logging event to the output debug string API
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Write the logging event to the output debug string API
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.OutputDebugString(System.String)">
+ <summary>
+ Stub for OutputDebugString native method
+ </summary>
+ <param name="message">the string to output</param>
+ <remarks>
+ <para>
+ Stub for OutputDebugString native method
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.OutputDebugStringAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender">
+ <summary>
+ Logs events to a remote syslog daemon.
+ </summary>
+ <remarks>
+ <para>
+ The BSD syslog protocol is used to remotely log to
+ a syslog daemon. The syslogd listens for for messages
+ on UDP port 514.
+ </para>
+ <para>
+ The syslog UDP protocol is not authenticated. Most syslog daemons
+ do not accept remote log messages because of the security implications.
+ You may be able to use the LocalSyslogAppender to talk to a local
+ syslog service.
+ </para>
+ <para>
+ There is an RFC 3164 that claims to document the BSD Syslog Protocol.
+ This RFC can be seen here: http://www.faqs.org/rfcs/rfc3164.html.
+ This appender generates what the RFC calls an "Original Device Message",
+ i.e. does not include the TIMESTAMP or HOSTNAME fields. By observation
+ this format of message will be accepted by all current syslog daemon
+ implementations. The daemon will attach the current time and the source
+ hostname or IP address to any messages received.
+ </para>
+ <para>
+ Syslog messages must have a facility and and a severity. The severity
+ is derived from the Level of the logging event.
+ The facility must be chosen from the set of defined syslog
+ <see cref="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility"/> values. The facilities list is predefined
+ and cannot be extended.
+ </para>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.RemoteSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Core.LoggingEvent.Domain"/>).
+ </para>
+ </remarks>
+ <author>Rob Lyon</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Appender.UdpAppender">
+ <summary>
+ Sends logging events as connectionless UDP datagrams to a remote host or a
+ multicast group using an <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </summary>
+ <remarks>
+ <para>
+ UDP guarantees neither that messages arrive, nor that they arrive in the correct order.
+ </para>
+ <para>
+ To view the logging results, a custom application can be developed that listens for logging
+ events.
+ </para>
+ <para>
+ When decoding events send via this appender remember to use the same encoding
+ to decode the events as was used to send the events. See the <see cref="P:log4net.Appender.UdpAppender.Encoding"/>
+ property to specify the encoding to use.
+ </para>
+ </remarks>
+ <example>
+ This example shows how to log receive logging events that are sent
+ on IP address 244.0.0.1 and port 8080 to the console. The event is
+ encoded in the packet as a unicode string and it is decoded as such.
+ <code lang="C#">
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ UdpClient udpClient;
+ byte[] buffer;
+ string loggingEvent;
+
+ try
+ {
+ udpClient = new UdpClient(8080);
+
+ while(true)
+ {
+ buffer = udpClient.Receive(ref remoteEndPoint);
+ loggingEvent = System.Text.Encoding.Unicode.GetString(buffer);
+ Console.WriteLine(loggingEvent);
+ }
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ </code>
+ <code lang="Visual Basic">
+ Dim remoteEndPoint as IPEndPoint
+ Dim udpClient as UdpClient
+ Dim buffer as Byte()
+ Dim loggingEvent as String
+
+ Try
+ remoteEndPoint = new IPEndPoint(IPAddress.Any, 0)
+ udpClient = new UdpClient(8080)
+
+ While True
+ buffer = udpClient.Receive(ByRef remoteEndPoint)
+ loggingEvent = System.Text.Encoding.Unicode.GetString(buffer)
+ Console.WriteLine(loggingEvent)
+ Wend
+ Catch e As Exception
+ Console.WriteLine(e.ToString())
+ End Try
+ </code>
+ <para>
+ An example configuration section to log information using this appender to the
+ IP 224.0.0.1 on port 8080:
+ </para>
+ <code lang="XML" escaped="true">
+ <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
+ <remoteAddress value="224.0.0.1"/>
+ <remotePort value="8080"/>
+ <layout type="log4net.Layout.PatternLayout" value="%-5level %logger [%ndc] - %message%newline"/>
+ </appender>
+ </code>
+ </example>
+ <author>Gert Driesen</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.UdpAppender"/> class.
+ </summary>
+ <remarks>
+ The default constructor initializes all fields to their default values.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The appender will be ignored if no <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> was specified or
+ an invalid remote or local TCP port number was specified.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required property <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> was not specified.</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException">The TCP port number assigned to <see cref="P:log4net.Appender.UdpAppender.LocalPort"/> or <see cref="P:log4net.Appender.UdpAppender.RemotePort"/> is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Sends the event using an UDP datagram.
+ </para>
+ <para>
+ Exceptions are passed to the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.OnClose">
+ <summary>
+ Closes the UDP connection and releases all resources associated with
+ this <see cref="T:log4net.Appender.UdpAppender"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Disables the underlying <see cref="T:System.Net.Sockets.UdpClient"/> and releases all managed
+ and unmanaged resources associated with the <see cref="T:log4net.Appender.UdpAppender"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.InitializeClientConnection">
+ <summary>
+ Initializes the underlying <see cref="T:System.Net.Sockets.UdpClient"/> connection.
+ </summary>
+ <remarks>
+ <para>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> is initialized and binds to the
+ port number from which you intend to communicate.
+ </para>
+ <para>
+ Exceptions are passed to the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remoteAddress">
+ <summary>
+ The IP address of the remote host or multicast group to which
+ the logging event will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remotePort">
+ <summary>
+ The TCP port number of the remote host or multicast group to
+ which the logging event will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remoteEndPoint">
+ <summary>
+ The cached remote endpoint to which the logging events will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_localPort">
+ <summary>
+ The TCP port number from which the <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_client">
+ <summary>
+ The <see cref="T:System.Net.Sockets.UdpClient"/> instance that will be used for sending the
+ logging events.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_encoding">
+ <summary>
+ The encoding to use for the packet.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemoteAddress">
+ <summary>
+ Gets or sets the IP address of the remote host or multicast group to which
+ the underlying <see cref="T:System.Net.Sockets.UdpClient"/> should sent the logging event.
+ </summary>
+ <value>
+ The IP address of the remote host or multicast group to which the logging event
+ will be sent.
+ </value>
+ <remarks>
+ <para>
+ Multicast addresses are identified by IP class <b>D</b> addresses (in the range 224.0.0.0 to
+ 239.255.255.255). Multicast packets can pass across different networks through routers, so
+ it is possible to use multicasts in an Internet scenario as long as your network provider
+ supports multicasting.
+ </para>
+ <para>
+ Hosts that want to receive particular multicast messages must register their interest by joining
+ the multicast group. Multicast messages are not sent to networks where no host has joined
+ the multicast group. Class <b>D</b> IP addresses are used for multicast groups, to differentiate
+ them from normal host addresses, allowing nodes to easily detect if a message is of interest.
+ </para>
+ <para>
+ Static multicast addresses that are needed globally are assigned by IANA. A few examples are listed in the table below:
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>IP Address</term>
+ <description>Description</description>
+ </listheader>
+ <item>
+ <term>224.0.0.1</term>
+ <description>
+ <para>
+ Sends a message to all system on the subnet.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>224.0.0.2</term>
+ <description>
+ <para>
+ Sends a message to all routers on the subnet.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>224.0.0.12</term>
+ <description>
+ <para>
+ The DHCP server answers messages on the IP address 224.0.0.12, but only on a subnet.
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ A complete list of actually reserved multicast addresses and their owners in the ranges
+ defined by RFC 3171 can be found at the <A href="http://www.iana.org/assignments/multicast-addresses">IANA web site</A>.
+ </para>
+ <para>
+ The address range 239.0.0.0 to 239.255.255.255 is reserved for administrative scope-relative
+ addresses. These addresses can be reused with other local groups. Routers are typically
+ configured with filters to prevent multicast traffic in this range from flowing outside
+ of the local network.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemotePort">
+ <summary>
+ Gets or sets the TCP port number of the remote host or multicast group to which
+ the underlying <see cref="T:System.Net.Sockets.UdpClient"/> should sent the logging event.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number of the remote host or multicast group to which the logging event
+ will be sent.
+ </value>
+ <remarks>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> will send messages to this TCP port number
+ on the remote host or multicast group.
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.LocalPort">
+ <summary>
+ Gets or sets the TCP port number from which the underlying <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number from which the underlying <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </value>
+ <remarks>
+ <para>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> will bind to this port for sending messages.
+ </para>
+ <para>
+ Setting the value to 0 (the default) will cause the udp client not to bind to
+ a local port.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.Encoding">
+ <summary>
+ Gets or sets <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.Client">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </value>
+ <remarks>
+ <see cref="T:log4net.Appender.UdpAppender"/> creates a <see cref="T:System.Net.Sockets.UdpClient"/> to send logging events
+ over a network. Classes deriving from <see cref="T:log4net.Appender.UdpAppender"/> can use this
+ property to get or set this <see cref="T:System.Net.Sockets.UdpClient"/>. Use the underlying <see cref="T:System.Net.Sockets.UdpClient"/>
+ returned from <see cref="P:log4net.Appender.UdpAppender.Client"/> if you require access beyond that which
+ <see cref="T:log4net.Appender.UdpAppender"/> provides.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemoteEndPoint">
+ <summary>
+ Gets or sets the cached remote endpoint to which the logging events should be sent.
+ </summary>
+ <value>
+ The cached remote endpoint to which the logging events will be sent.
+ </value>
+ <remarks>
+ The <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> method will initialize the remote endpoint
+ with the values of the <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> and <see cref="P:log4net.Appender.UdpAppender.RemotePort"/>
+ properties.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.DefaultSyslogPort">
+ <summary>
+ Syslog port 514
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> class.
+ </summary>
+ <remarks>
+ This instance of the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> class is set up to write
+ to a remote syslog daemon.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.AddMapping(log4net.Appender.RemoteSyslogAppender.LevelSeverity)">
+ <summary>
+ Add a mapping of level to severity
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.RemoteSyslogAppender.LevelSeverity"/> mapping to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to a remote syslog daemon.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to syslog severity mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.GetSeverity(log4net.Core.Level)">
+ <summary>
+ Translates a log4net level to a syslog severity.
+ </summary>
+ <param name="level">A log4net level.</param>
+ <returns>A syslog severity.</returns>
+ <remarks>
+ <para>
+ Translates a log4net level to a syslog severity.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.GeneratePriority(log4net.Appender.RemoteSyslogAppender.SyslogFacility,log4net.Appender.RemoteSyslogAppender.SyslogSeverity)">
+ <summary>
+ Generate a syslog priority.
+ </summary>
+ <param name="facility">The syslog facility.</param>
+ <param name="severity">The syslog severity.</param>
+ <returns>A syslog priority.</returns>
+ <remarks>
+ <para>
+ Generate a syslog priority.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_facility">
+ <summary>
+ The facility. The default facility is <see cref="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_identity">
+ <summary>
+ The message identity
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to syslog severity
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.Identity">
+ <summary>
+ Message identity
+ </summary>
+ <remarks>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.RemoteSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Core.LoggingEvent.Domain"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.Facility">
+ <summary>
+ Syslog facility
+ </summary>
+ <remarks>
+ Set to one of the <see cref="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility"/> values. The list of
+ facilities is predefined and cannot be extended. The default value
+ is <see cref="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User"/>.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.SyslogSeverity">
+ <summary>
+ syslog severities
+ </summary>
+ <remarks>
+ <para>
+ The syslog severities.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Emergency">
+ <summary>
+ system is unusable
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Alert">
+ <summary>
+ action must be taken immediately
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Critical">
+ <summary>
+ critical conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Error">
+ <summary>
+ error conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Warning">
+ <summary>
+ warning conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Notice">
+ <summary>
+ normal but significant condition
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Informational">
+ <summary>
+ informational
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Debug">
+ <summary>
+ debug-level messages
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility">
+ <summary>
+ syslog facilities
+ </summary>
+ <remarks>
+ <para>
+ The syslog facilities
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Kernel">
+ <summary>
+ kernel messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User">
+ <summary>
+ random user-level messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Mail">
+ <summary>
+ mail system
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Daemons">
+ <summary>
+ system daemons
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Authorization">
+ <summary>
+ security/authorization messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Syslog">
+ <summary>
+ messages generated internally by syslogd
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Printer">
+ <summary>
+ line printer subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.News">
+ <summary>
+ network news subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Uucp">
+ <summary>
+ UUCP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Clock">
+ <summary>
+ clock (cron/at) daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Authorization2">
+ <summary>
+ security/authorization messages (private)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Ftp">
+ <summary>
+ ftp daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Ntp">
+ <summary>
+ NTP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Audit">
+ <summary>
+ log audit
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Alert">
+ <summary>
+ log alert
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Clock2">
+ <summary>
+ clock daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local0">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local1">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local2">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local3">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local4">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local5">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local6">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local7">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.LevelSeverity">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </summary>
+ <remarks>
+ <para>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.LevelSeverity.Severity">
+ <summary>
+ The mapped syslog severity for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped syslog severity for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemotingAppender">
+ <summary>
+ Delivers logging events to a remote logging sink.
+ </summary>
+ <remarks>
+ <para>
+ This Appender is designed to deliver events to a remote sink.
+ That is any object that implements the <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ interface. It delivers the events using .NET remoting. The
+ object to deliver events to is specified by setting the
+ appenders <see cref="P:log4net.Appender.RemotingAppender.Sink"/> property.</para>
+ <para>
+ The RemotingAppender buffers events before sending them. This allows it to
+ make more efficient use of the remoting infrastructure.</para>
+ <para>
+ Once the buffer is full the events are still not sent immediately.
+ They are scheduled to be sent using a pool thread. The effect is that
+ the send occurs asynchronously. This is very important for a
+ number of non obvious reasons. The remoting infrastructure will
+ flow thread local variables (stored in the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>),
+ if they are marked as <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>, across the
+ remoting boundary. If the server is not contactable then
+ the remoting infrastructure will clear the <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>
+ objects from the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>. To prevent a logging failure from
+ having side effects on the calling application the remoting call must be made
+ from a separate thread to the one used by the application. A <see cref="T:System.Threading.ThreadPool"/>
+ thread is used for this. If no <see cref="T:System.Threading.ThreadPool"/> thread is available then
+ the events will block in the thread pool manager until a thread is available.</para>
+ <para>
+ Because the events are sent asynchronously using pool threads it is possible to close
+ this appender before all the queued events have been sent.
+ When closing the appender attempts to wait until all the queued events have been sent, but
+ this will timeout after 30 seconds regardless.</para>
+ <para>
+ If this appender is being closed because the <see cref="E:System.AppDomain.ProcessExit"/>
+ event has fired it may not be possible to send all the queued events. During process
+ exit the runtime limits the time that a <see cref="E:System.AppDomain.ProcessExit"/>
+ event handler is allowed to run for. If the runtime terminates the threads before
+ the queued events have been sent then they will be lost. To ensure that all events
+ are sent the appender must be closed before the application exits. See
+ <see cref="M:log4net.Core.LoggerManager.Shutdown"/> for details on how to shutdown
+ log4net programmatically.</para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RemotingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Send the contents of the buffer to the remote sink.
+ </summary>
+ <remarks>
+ The events are not sent immediately. They are scheduled to be sent
+ using a pool thread. The effect is that the send occurs asynchronously.
+ This is very important for a number of non obvious reasons. The remoting
+ infrastructure will flow thread local variables (stored in the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>),
+ if they are marked as <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>, across the
+ remoting boundary. If the server is not contactable then
+ the remoting infrastructure will clear the <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>
+ objects from the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>. To prevent a logging failure from
+ having side effects on the calling application the remoting call must be made
+ from a separate thread to the one used by the application. A <see cref="T:System.Threading.ThreadPool"/>
+ thread is used for this. If no <see cref="T:System.Threading.ThreadPool"/> thread is available then
+ the events will block in the thread pool manager until a thread is available.
+ </remarks>
+ <param name="events">The events to send.</param>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.OnClose">
+ <summary>
+ Override base class close.
+ </summary>
+ <remarks>
+ <para>
+ This method waits while there are queued work items. The events are
+ sent asynchronously using <see cref="T:System.Threading.ThreadPool"/> work items. These items
+ will be sent once a thread pool thread is available to send them, therefore
+ it is possible to close the appender before all the queued events have been
+ sent.</para>
+ <para>
+ This method attempts to wait until all the queued events have been sent, but this
+ method will timeout after 30 seconds regardless.</para>
+ <para>
+ If the appender is being closed because the <see cref="E:System.AppDomain.ProcessExit"/>
+ event has fired it may not be possible to send all the queued events. During process
+ exit the runtime limits the time that a <see cref="E:System.AppDomain.ProcessExit"/>
+ event handler is allowed to run for.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.BeginAsyncSend">
+ <summary>
+ A work item is being queued into the thread pool
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.EndAsyncSend">
+ <summary>
+ A work item from the thread pool has completed
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.SendBufferCallback(System.Object)">
+ <summary>
+ Send the contents of the buffer to the remote sink.
+ </summary>
+ <remarks>
+ This method is designed to be used with the <see cref="T:System.Threading.ThreadPool"/>.
+ This method expects to be passed an array of <see cref="T:log4net.Core.LoggingEvent"/>
+ objects in the state param.
+ </remarks>
+ <param name="state">the logging events to send</param>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_sinkUrl">
+ <summary>
+ The URL of the remote sink.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_sinkObj">
+ <summary>
+ The local proxy (.NET remoting) for the remote logging sink.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_queuedCallbackCount">
+ <summary>
+ The number of queued callbacks currently waiting or executing
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_workQueueEmptyEvent">
+ <summary>
+ Event used to signal when there are no queued work items
+ </summary>
+ <remarks>
+ This event is set when there are no queued work items. In this
+ state it is safe to close the appender.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemotingAppender.Sink">
+ <summary>
+ Gets or sets the URL of the well-known object that will accept
+ the logging events.
+ </summary>
+ <value>
+ The well-known URL of the remote sink.
+ </value>
+ <remarks>
+ <para>
+ The URL of the remoting sink that will accept logging events.
+ The sink must implement the <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ interface.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink">
+ <summary>
+ Interface used to deliver <see cref="T:log4net.Core.LoggingEvent"/> objects to a remote sink.
+ </summary>
+ <remarks>
+ This interface must be implemented by a remoting sink
+ if the <see cref="T:log4net.Appender.RemotingAppender"/> is to be used
+ to deliver logging events to the sink.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.IRemoteLoggingSink.LogEvents(log4net.Core.LoggingEvent[])">
+ <summary>
+ Delivers logging events to the remote sink
+ </summary>
+ <param name="events">Array of events to log.</param>
+ <remarks>
+ <para>
+ Delivers logging events to the remote sink
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender">
+ <summary>
+ Appender that rolls log files based on size or date or both.
+ </summary>
+ <remarks>
+ <para>
+ RollingFileAppender can roll log files based on size or date or both
+ depending on the setting of the <see cref="P:log4net.Appender.RollingFileAppender.RollingStyle"/> property.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Size"/> the log file will be rolled
+ once its size exceeds the <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/>.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Date"/> the log file will be rolled
+ once the date boundary specified in the <see cref="P:log4net.Appender.RollingFileAppender.DatePattern"/> property
+ is crossed.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Composite"/> the log file will be
+ rolled once the date boundary specified in the <see cref="P:log4net.Appender.RollingFileAppender.DatePattern"/> property
+ is crossed, but within a date boundary the file will also be rolled
+ once its size exceeds the <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/>.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Once"/> the log file will be rolled when
+ the appender is configured. This effectively means that the log file can be
+ rolled once per program execution.
+ </para>
+ <para>
+ A of few additional optional features have been added:
+ <list type="bullet">
+ <item>Attach date pattern for current log file <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/></item>
+ <item>Backup number increments for newer files <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/></item>
+ <item>Infinite number of backups by file size <see cref="P:log4net.Appender.RollingFileAppender.MaxSizeRollBackups"/></item>
+ </list>
+ </para>
+
+ <note>
+ <para>
+ For large or infinite numbers of backup files a <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/>
+ greater than zero is highly recommended, otherwise all the backup files need
+ to be renamed each time a new backup is created.
+ </para>
+ <para>
+ When Date/Time based rolling is used setting <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/>
+ to <see langword="true"/> will reduce the number of file renamings to few or none.
+ </para>
+ </note>
+
+ <note type="caution">
+ <para>
+ Changing <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/> or <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> without clearing
+ the log file directory of backup files will cause unexpected and unwanted side effects.
+ </para>
+ </note>
+
+ <para>
+ If Date/Time based rolling is enabled this appender will attempt to roll existing files
+ in the directory without a Date/Time tag based on the last write date of the base log file.
+ The appender only rolls the log file when a message is logged. If Date/Time based rolling
+ is enabled then the appender will not roll the log file at the Date/Time boundary but
+ at the point when the next message is logged after the boundary has been crossed.
+ </para>
+
+ <para>
+ The <see cref="T:log4net.Appender.RollingFileAppender"/> extends the <see cref="T:log4net.Appender.FileAppender"/> and
+ has the same behavior when opening the log file.
+ The appender will first try to open the file for writing when <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>
+ is called. This will typically be during configuration.
+ If the file cannot be opened for writing the appender will attempt
+ to open the file again each time a message is logged to the appender.
+ If the file cannot be opened for writing when a message is logged then
+ the message will be discarded by this appender.
+ </para>
+ <para>
+ When rolling a backup file necessitates deleting an older backup file the
+ file to be deleted is moved to a temporary name before being deleted.
+ </para>
+
+ <note type="caution">
+ <para>
+ A maximum number of backup files when rolling on date/time boundaries is not supported.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ <author>Edward Smit</author>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RollingFileAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.SetQWForFiles(System.IO.TextWriter)">
+ <summary>
+ Sets the quiet writer being used.
+ </summary>
+ <remarks>
+ This method can be overridden by sub classes.
+ </remarks>
+ <param name="writer">the writer to set</param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write out a logging event.
+ </summary>
+ <param name="loggingEvent">the event to write to file.</param>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Write out an array of logging events.
+ </summary>
+ <param name="loggingEvents">the events to write to file.</param>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.AdjustFileBeforeAppend">
+ <summary>
+ Performs any required rolling before outputting the next event
+ </summary>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.OpenFile(System.String,System.Boolean)">
+ <summary>
+ Creates and opens the file for logging. If <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/>
+ is false then the fully qualified name is determined and used.
+ </summary>
+ <param name="fileName">the name of the file to open</param>
+ <param name="append">true to append to existing file</param>
+ <remarks>
+ <para>This method will ensure that the directory structure
+ for the <paramref name="fileName"/> specified exists.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetNextOutputFileName(System.String)">
+ <summary>
+ Get the current output file name
+ </summary>
+ <param name="fileName">the base file name</param>
+ <returns>the output file name</returns>
+ <remarks>
+ The output file name is based on the base fileName specified.
+ If <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/> is set then the output
+ file name is the same as the base file passed in. Otherwise
+ the output file depends on the date pattern, on the count
+ direction or both.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.DetermineCurSizeRollBackups">
+ <summary>
+ Determines curSizeRollBackups (only within the current roll point)
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetWildcardPatternForFile(System.String)">
+ <summary>
+ Generates a wildcard pattern that can be used to find all files
+ that are similar to the base file name.
+ </summary>
+ <param name="baseFileName"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetExistingFiles(System.String)">
+ <summary>
+ Builds a list of filenames for all files matching the base filename plus a file
+ pattern.
+ </summary>
+ <param name="baseFilePath"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverIfDateBoundaryCrossing">
+ <summary>
+ Initiates a roll over if needed for crossing a date boundary since the last run.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ExistingInit">
+ <summary>
+ Initializes based on existing conditions at time of <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>.
+ </summary>
+ <remarks>
+ <para>
+ Initializes based on existing conditions at time of <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>.
+ The following is done
+ <list type="bullet">
+ <item>determine curSizeRollBackups (only within the current roll point)</item>
+ <item>initiates a roll over if needed for crossing a date boundary since the last run.</item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.InitializeFromOneFile(System.String,System.String)">
+ <summary>
+ Does the work of bumping the 'current' file counter higher
+ to the highest count when an incremental file name is seen.
+ The highest count is either the first file (when count direction
+ is greater than 0) or the last file (when count direction less than 0).
+ In either case, we want to know the highest count that is present.
+ </summary>
+ <param name="baseFile"></param>
+ <param name="curFileName"></param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.InitializeRollBackups(System.String,System.Collections.ArrayList)">
+ <summary>
+ Takes a list of files and a base file name, and looks for
+ 'incremented' versions of the base file. Bumps the max
+ count up to the highest count seen.
+ </summary>
+ <param name="baseFile"></param>
+ <param name="arrayFiles"></param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ComputeCheckPeriod(System.String)">
+ <summary>
+ Calculates the RollPoint for the datePattern supplied.
+ </summary>
+ <param name="datePattern">the date pattern to calculate the check period for</param>
+ <returns>The RollPoint that is most accurate for the date pattern supplied</returns>
+ <remarks>
+ Essentially the date pattern is examined to determine what the
+ most suitable roll point is. The roll point chosen is the roll point
+ with the smallest period that can be detected using the date pattern
+ supplied. i.e. if the date pattern only outputs the year, month, day
+ and hour then the smallest roll point that can be detected would be
+ and hourly roll point as minutes could not be detected.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Sets initial conditions including date/time roll over information, first check,
+ scheduledFilename, and calls <see cref="M:log4net.Appender.RollingFileAppender.ExistingInit"/> to initialize
+ the current number of backups.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverTime(System.Boolean)">
+ <summary>
+ Rollover the file(s) to date/time tagged file(s).
+ </summary>
+ <param name="fileIsOpen">set to true if the file to be rolled is currently open</param>
+ <remarks>
+ <para>
+ Rollover the file(s) to date/time tagged file(s).
+ Resets curSizeRollBackups.
+ If fileIsOpen is set then the new file is opened (through SafeOpenFile).
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollFile(System.String,System.String)">
+ <summary>
+ Renames file <paramref name="fromFile"/> to file <paramref name="toFile"/>.
+ </summary>
+ <param name="fromFile">Name of existing file to roll.</param>
+ <param name="toFile">New name for file.</param>
+ <remarks>
+ <para>
+ Renames file <paramref name="fromFile"/> to file <paramref name="toFile"/>. It
+ also checks for existence of target file and deletes if it does.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.FileExists(System.String)">
+ <summary>
+ Test if a file exists at a specified path
+ </summary>
+ <param name="path">the path to the file</param>
+ <returns>true if the file exists</returns>
+ <remarks>
+ <para>
+ Test if a file exists at a specified path
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.DeleteFile(System.String)">
+ <summary>
+ Deletes the specified file if it exists.
+ </summary>
+ <param name="fileName">The file to delete.</param>
+ <remarks>
+ <para>
+ Delete a file if is exists.
+ The file is first moved to a new filename then deleted.
+ This allows the file to be removed even when it cannot
+ be deleted, but it still can be moved.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverSize">
+ <summary>
+ Implements file roll base on file size.
+ </summary>
+ <remarks>
+ <para>
+ If the maximum number of size based backups is reached
+ (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
+ file is deleted -- its index determined by the sign of countDirection.
+ If <c>countDirection</c> &lt; 0, then files
+ {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
+ are renamed to {<c>File.2</c>, ...,
+ <c>File.curSizeRollBackups</c>}. Moreover, <c>File</c> is
+ renamed <c>File.1</c> and closed.
+ </para>
+ <para>
+ A new file is created to receive further log output.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> is equal to zero, then the
+ <c>File</c> is truncated with no backup files created.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
+ renamed if needed and no files are deleted.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverRenameFiles(System.String)">
+ <summary>
+ Implements file roll.
+ </summary>
+ <param name="baseFileName">the base name to rename</param>
+ <remarks>
+ <para>
+ If the maximum number of size based backups is reached
+ (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
+ file is deleted -- its index determined by the sign of countDirection.
+ If <c>countDirection</c> &lt; 0, then files
+ {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
+ are renamed to {<c>File.2</c>, ...,
+ <c>File.curSizeRollBackups</c>}.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> is equal to zero, then the
+ <c>File</c> is truncated with no backup files created.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
+ renamed if needed and no files are deleted.
+ </para>
+ <para>
+ This is called by <see cref="M:log4net.Appender.RollingFileAppender.RollOverSize"/> to rename the files.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.NextCheckDate(System.DateTime,log4net.Appender.RollingFileAppender.RollPoint)">
+ <summary>
+ Get the start time of the next window for the current rollpoint
+ </summary>
+ <param name="currentDateTime">the current date</param>
+ <param name="rollPoint">the type of roll point we are working with</param>
+ <returns>the start time for the next roll point an interval after the currentDateTime date</returns>
+ <remarks>
+ <para>
+ Returns the date of the next roll point after the currentDateTime date passed to the method.
+ </para>
+ <para>
+ The basic strategy is to subtract the time parts that are less significant
+ than the rollpoint from the current time. This should roll the time back to
+ the start of the time window for the current rollpoint. Then we add 1 window
+ worth of time and get the start time of the next window for the rollpoint.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_dateTime">
+ <summary>
+ This object supplies the current date/time. Allows test code to plug in
+ a method to control this class when testing date/time based rolling.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_datePattern">
+ <summary>
+ The date pattern. By default, the pattern is set to <c>".yyyy-MM-dd"</c>
+ meaning daily rollover.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_scheduledFilename">
+ <summary>
+ The actual formatted filename that is currently being written to
+ or will be the file transferred to on roll over
+ (based on staticLogFileName).
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_nextCheck">
+ <summary>
+ The timestamp when we shall next recompute the filename.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_now">
+ <summary>
+ Holds date of last roll over
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollPoint">
+ <summary>
+ The type of rolling done
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_maxFileSize">
+ <summary>
+ The default maximum file size is 10MB
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_maxSizeRollBackups">
+ <summary>
+ There is zero backup files by default
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_curSizeRollBackups">
+ <summary>
+ How many sized based backups have been made so far
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_countDirection">
+ <summary>
+ The rolling file count direction.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollingStyle">
+ <summary>
+ The rolling mode used in this appender.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollDate">
+ <summary>
+ Cache flag set if we are rolling by date.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollSize">
+ <summary>
+ Cache flag set if we are rolling by size.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_staticLogFileName">
+ <summary>
+ Value indicating whether to always log to the same file.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_baseFileName">
+ <summary>
+ FileName provided in configuration. Used for rolling properly
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.s_date1970">
+ <summary>
+ The 1st of January 1970 in UTC
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.DatePattern">
+ <summary>
+ Gets or sets the date pattern to be used for generating file names
+ when rolling over on date.
+ </summary>
+ <value>
+ The date pattern to be used for generating file names when rolling
+ over on date.
+ </value>
+ <remarks>
+ <para>
+ Takes a string in the same format as expected by
+ <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/>.
+ </para>
+ <para>
+ This property determines the rollover schedule when rolling over
+ on date.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaxSizeRollBackups">
+ <summary>
+ Gets or sets the maximum number of backup files that are kept before
+ the oldest is erased.
+ </summary>
+ <value>
+ The maximum number of backup files that are kept before the oldest is
+ erased.
+ </value>
+ <remarks>
+ <para>
+ If set to zero, then there will be no backup files and the log file
+ will be truncated when it reaches <see cref="P:log4net.Appender.RollingFileAppender.MaxFileSize"/>.
+ </para>
+ <para>
+ If a negative number is supplied then no deletions will be made. Note
+ that this could result in very slow performance as a large number of
+ files are rolled over unless <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> is used.
+ </para>
+ <para>
+ The maximum applies to <b>each</b> time based group of files and
+ <b>not</b> the total.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaxFileSize">
+ <summary>
+ Gets or sets the maximum size that the output file is allowed to reach
+ before being rolled over to backup files.
+ </summary>
+ <value>
+ The maximum size in bytes that the output file is allowed to reach before being
+ rolled over to backup files.
+ </value>
+ <remarks>
+ <para>
+ This property is equivalent to <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/> except
+ that it is required for differentiating the setter taking a
+ <see cref="T:System.Int64"/> argument from the setter taking a <see cref="T:System.String"/>
+ argument.
+ </para>
+ <para>
+ The default maximum file size is 10MB (10*1024*1024).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaximumFileSize">
+ <summary>
+ Gets or sets the maximum size that the output file is allowed to reach
+ before being rolled over to backup files.
+ </summary>
+ <value>
+ The maximum size that the output file is allowed to reach before being
+ rolled over to backup files.
+ </value>
+ <remarks>
+ <para>
+ This property allows you to specify the maximum size with the
+ suffixes "KB", "MB" or "GB" so that the size is interpreted being
+ expressed respectively in kilobytes, megabytes or gigabytes.
+ </para>
+ <para>
+ For example, the value "10KB" will be interpreted as 10240 bytes.
+ </para>
+ <para>
+ The default maximum file size is 10MB.
+ </para>
+ <para>
+ If you have the option to set the maximum file size programmatically
+ consider using the <see cref="P:log4net.Appender.RollingFileAppender.MaxFileSize"/> property instead as this
+ allows you to set the size in bytes as a <see cref="T:System.Int64"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.CountDirection">
+ <summary>
+ Gets or sets the rolling file count direction.
+ </summary>
+ <value>
+ The rolling file count direction.
+ </value>
+ <remarks>
+ <para>
+ Indicates if the current file is the lowest numbered file or the
+ highest numbered file.
+ </para>
+ <para>
+ By default newer files have lower numbers (<see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &lt; 0),
+ i.e. log.1 is most recent, log.5 is the 5th backup, etc...
+ </para>
+ <para>
+ <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &gt;= 0 does the opposite i.e.
+ log.1 is the first backup made, log.5 is the 5th backup made, etc.
+ For infinite backups use <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &gt;= 0 to reduce
+ rollover costs.
+ </para>
+ <para>The default file count direction is -1.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.RollingStyle">
+ <summary>
+ Gets or sets the rolling style.
+ </summary>
+ <value>The rolling style.</value>
+ <remarks>
+ <para>
+ The default rolling style is <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Composite"/>.
+ </para>
+ <para>
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Once"/> this appender's
+ <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property is set to <c>false</c>, otherwise
+ the appender would append to a single file rather than rolling
+ the file each time it is opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.StaticLogFileName">
+ <summary>
+ Gets or sets a value indicating whether to always log to
+ the same file.
+ </summary>
+ <value>
+ <c>true</c> if always should be logged to the same file, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ By default file.log is always the current file. Optionally
+ file.log.yyyy-mm-dd for current formatted datePattern can by the currently
+ logging file (or file.log.curSizeRollBackup or even
+ file.log.yyyy-mm-dd.curSizeRollBackup).
+ </para>
+ <para>
+ This will make time based rollovers with a large number of backups
+ much faster as the appender it won't have to rename all the backups!
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.RollingMode">
+ <summary>
+ Style of rolling to use
+ </summary>
+ <remarks>
+ <para>
+ Style of rolling to use
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Once">
+ <summary>
+ Roll files once per program execution
+ </summary>
+ <remarks>
+ <para>
+ Roll files once per program execution.
+ Well really once each time this appender is
+ configured.
+ </para>
+ <para>
+ Setting this option also sets <c>AppendToFile</c> to
+ <c>false</c> on the <c>RollingFileAppender</c>, otherwise
+ this appender would just be a normal file appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Size">
+ <summary>
+ Roll files based only on the size of the file
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Date">
+ <summary>
+ Roll files based only on the date
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Composite">
+ <summary>
+ Roll files based on both the size and date of the file
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.RollPoint">
+ <summary>
+ The code assumes that the following 'time' constants are in a increasing sequence.
+ </summary>
+ <remarks>
+ <para>
+ The code assumes that the following 'time' constants are in a increasing sequence.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.InvalidRollPoint">
+ <summary>
+ Roll the log not based on the date
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfMinute">
+ <summary>
+ Roll the log for each minute
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfHour">
+ <summary>
+ Roll the log for each hour
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.HalfDay">
+ <summary>
+ Roll the log twice a day (midday and midnight)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfDay">
+ <summary>
+ Roll the log each day (midnight)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfWeek">
+ <summary>
+ Roll the log each week
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfMonth">
+ <summary>
+ Roll the log each month
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.IDateTime">
+ <summary>
+ This interface is used to supply Date/Time information to the <see cref="T:log4net.Appender.RollingFileAppender"/>.
+ </summary>
+ <remarks>
+ This interface is used to supply Date/Time information to the <see cref="T:log4net.Appender.RollingFileAppender"/>.
+ Used primarily to allow test classes to plug themselves in so they can
+ supply test date/times.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.IDateTime.Now">
+ <summary>
+ Gets the <i>current</i> time.
+ </summary>
+ <value>The <i>current</i> time.</value>
+ <remarks>
+ <para>
+ Gets the <i>current</i> time.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.DefaultDateTime">
+ <summary>
+ Default implementation of <see cref="T:log4net.Appender.RollingFileAppender.IDateTime"/> that returns the current time.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.DefaultDateTime.Now">
+ <summary>
+ Gets the <b>current</b> time.
+ </summary>
+ <value>The <b>current</b> time.</value>
+ <remarks>
+ <para>
+ Gets the <b>current</b> time.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpAppender">
+ <summary>
+ Send an e-mail when a specific logging event occurs, typically on errors
+ or fatal errors.
+ </summary>
+ <remarks>
+ <para>
+ The number of logging events delivered in this e-mail depend on
+ the value of <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option. The
+ <see cref="T:log4net.Appender.SmtpAppender"/> keeps only the last
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> logging events in its
+ cyclic buffer. This keeps memory requirements at a reasonable level while
+ still delivering useful application context.
+ </para>
+ <note type="caution">
+ Authentication and setting the server Port are only available on the MS .NET 1.1 runtime.
+ For these features to be enabled you need to ensure that you are using a version of
+ the log4net assembly that is built against the MS .NET 1.1 framework and that you are
+ running the your application on the MS .NET 1.1 runtime. On all other platforms only sending
+ unauthenticated messages to a server listening on port 25 (the default) is supported.
+ </note>
+ <para>
+ Authentication is supported by setting the <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> property to
+ either <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> or <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/>.
+ If using <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> authentication then the <see cref="P:log4net.Appender.SmtpAppender.Username"/>
+ and <see cref="P:log4net.Appender.SmtpAppender.Password"/> properties must also be set.
+ </para>
+ <para>
+ To set the SMTP server port use the <see cref="P:log4net.Appender.SmtpAppender.Port"/> property. The default port is 25.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </summary>
+ <param name="events">The logging events to send.</param>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.SendEmail(System.String)">
+ <summary>
+ Send the email message
+ </summary>
+ <param name="messageBody">the body text to include in the mail</param>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.To">
+ <summary>
+ Gets or sets a semicolon-delimited list of recipient e-mail addresses.
+ </summary>
+ <value>
+ A semicolon-delimited list of e-mail addresses.
+ </value>
+ <remarks>
+ <para>
+ A semicolon-delimited list of recipient e-mail addresses.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.From">
+ <summary>
+ Gets or sets the e-mail address of the sender.
+ </summary>
+ <value>
+ The e-mail address of the sender.
+ </value>
+ <remarks>
+ <para>
+ The e-mail address of the sender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Subject">
+ <summary>
+ Gets or sets the subject line of the e-mail message.
+ </summary>
+ <value>
+ The subject line of the e-mail message.
+ </value>
+ <remarks>
+ <para>
+ The subject line of the e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.SmtpHost">
+ <summary>
+ Gets or sets the name of the SMTP relay mail server to use to send
+ the e-mail messages.
+ </summary>
+ <value>
+ The name of the e-mail relay server. If SmtpServer is not set, the
+ name of the local SMTP server is used.
+ </value>
+ <remarks>
+ <para>
+ The name of the e-mail relay server. If SmtpServer is not set, the
+ name of the local SMTP server is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.LocationInfo">
+ <summary>
+ Obsolete
+ </summary>
+ <remarks>
+ Use the BufferingAppenderSkeleton Fix methods instead
+ </remarks>
+ <remarks>
+ <para>
+ Obsolete property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Authentication">
+ <summary>
+ The mode to use to authentication with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ Valid Authentication mode values are: <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None"/>,
+ <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>, and <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/>.
+ The default value is <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None"/>. When using
+ <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> you must specify the <see cref="P:log4net.Appender.SmtpAppender.Username"/>
+ and <see cref="P:log4net.Appender.SmtpAppender.Password"/> to use to authenticate.
+ When using <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/> the Windows credentials for the current
+ thread, if impersonating, or the process will be used to authenticate.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Username">
+ <summary>
+ The username to use to authenticate with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ A <see cref="P:log4net.Appender.SmtpAppender.Username"/> and <see cref="P:log4net.Appender.SmtpAppender.Password"/> must be specified when
+ <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> is set to <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>,
+ otherwise the username will be ignored.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Password">
+ <summary>
+ The password to use to authenticate with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ A <see cref="P:log4net.Appender.SmtpAppender.Username"/> and <see cref="P:log4net.Appender.SmtpAppender.Password"/> must be specified when
+ <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> is set to <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>,
+ otherwise the password will be ignored.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Port">
+ <summary>
+ The port on which the SMTP server is listening
+ </summary>
+ <remarks>
+ <note type="caution">Server Port is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ The port on which the SMTP server is listening. The default
+ port is <c>25</c>. The Port can only be changed when running on
+ the MS .NET 1.1 runtime.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Priority">
+ <summary>
+ Gets or sets the priority of the e-mail message
+ </summary>
+ <value>
+ One of the <see cref="T:System.Web.Mail.MailPriority"/> values.
+ </value>
+ <remarks>
+ <para>
+ Sets the priority of the e-mails generated by this
+ appender. The default priority is <see cref="F:System.Web.Mail.MailPriority.Normal"/>.
+ </para>
+ <para>
+ If you are using this appender to report errors then
+ you may want to set the priority to <see cref="F:System.Web.Mail.MailPriority.High"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpAppender.SmtpAuthentication">
+ <summary>
+ Values for the <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> property.
+ </summary>
+ <remarks>
+ <para>
+ SMTP authentication modes.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None">
+ <summary>
+ No authentication
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic">
+ <summary>
+ Basic authentication.
+ </summary>
+ <remarks>
+ Requires a username and password to be supplied
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm">
+ <summary>
+ Integrated authentication
+ </summary>
+ <remarks>
+ Uses the Windows credentials from the current thread or process to authenticate.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpPickupDirAppender">
+ <summary>
+ Send an email when a specific logging event occurs, typically on errors
+ or fatal errors. Rather than sending via smtp it writes a file into the
+ directory specified by <see cref="P:log4net.Appender.SmtpPickupDirAppender.PickupDir"/>. This allows services such
+ as the IIS SMTP agent to manage sending the messages.
+ </summary>
+ <remarks>
+ <para>
+ The configuration for this appender is identical to that of the <c>SMTPAppender</c>,
+ except that instead of specifying the <c>SMTPAppender.SMTPHost</c> you specify
+ <see cref="P:log4net.Appender.SmtpPickupDirAppender.PickupDir"/>.
+ </para>
+ <para>
+ The number of logging events delivered in this e-mail depend on
+ the value of <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option. The
+ <see cref="T:log4net.Appender.SmtpPickupDirAppender"/> keeps only the last
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> logging events in its
+ cyclic buffer. This keeps memory requirements at a reasonable level while
+ still delivering useful application context.
+ </para>
+ </remarks>
+ <author>Niall Daley</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </summary>
+ <param name="events">The logging events to send.</param>
+ <remarks>
+ <para>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions">
+ <summary>
+ Activate the options on this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpPickupDirAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.To">
+ <summary>
+ Gets or sets a semicolon-delimited list of recipient e-mail addresses.
+ </summary>
+ <value>
+ A semicolon-delimited list of e-mail addresses.
+ </value>
+ <remarks>
+ <para>
+ A semicolon-delimited list of e-mail addresses.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.From">
+ <summary>
+ Gets or sets the e-mail address of the sender.
+ </summary>
+ <value>
+ The e-mail address of the sender.
+ </value>
+ <remarks>
+ <para>
+ The e-mail address of the sender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.Subject">
+ <summary>
+ Gets or sets the subject line of the e-mail message.
+ </summary>
+ <value>
+ The subject line of the e-mail message.
+ </value>
+ <remarks>
+ <para>
+ The subject line of the e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.PickupDir">
+ <summary>
+ Gets or sets the path to write the messages to.
+ </summary>
+ <remarks>
+ <para>
+ Gets or sets the path to write the messages to. This should be the same
+ as that used by the agent sending the messages.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> used to write to the pickup directory.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> used to write to the pickup directory.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender">
+ <summary>
+ Appender that allows clients to connect via Telnet to receive log messages
+ </summary>
+ <remarks>
+ <para>
+ The TelnetAppender accepts socket connections and streams logging messages
+ back to the client.
+ The output is provided in a telnet-friendly way so that a log can be monitored
+ over a TCP/IP socket.
+ This allows simple remote monitoring of application logging.
+ </para>
+ <para>
+ The default <see cref="P:log4net.Appender.TelnetAppender.Port"/> is 23 (the telnet port).
+ </para>
+ </remarks>
+ <author>Keith Long</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.OnClose">
+ <summary>
+ Overrides the parent method to close the socket handler
+ </summary>
+ <remarks>
+ <para>
+ Closes all the outstanding connections.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Create the socket handler and wait for connections
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to each connected client.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to each connected client.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.Port">
+ <summary>
+ Gets or sets the TCP port number on which this <see cref="T:log4net.Appender.TelnetAppender"/> will listen for connections.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number on which this <see cref="T:log4net.Appender.TelnetAppender"/> will listen for connections.
+ </value>
+ <remarks>
+ <para>
+ The default value is 23 (the telnet port).
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/>
+ or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender.SocketHandler">
+ <summary>
+ Helper class to manage connected clients
+ </summary>
+ <remarks>
+ <para>
+ The SocketHandler class is used to accept connections from
+ clients. It is threaded so that clients can connect/disconnect
+ asynchronously.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.#ctor(System.Int32)">
+ <summary>
+ Opens a new server port on <paramref ref="port"/>
+ </summary>
+ <param name="port">the local port to listen on for connections</param>
+ <remarks>
+ <para>
+ Creates a socket handler on the specified local server port.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.Send(System.String)">
+ <summary>
+ Sends a string message to each of the connected clients
+ </summary>
+ <param name="message">the text to send</param>
+ <remarks>
+ <para>
+ Sends a string message to each of the connected clients
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.AddClient(log4net.Appender.TelnetAppender.SocketHandler.SocketClient)">
+ <summary>
+ Add a client to the internal clients list
+ </summary>
+ <param name="client">client to add</param>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.RemoveClient(log4net.Appender.TelnetAppender.SocketHandler.SocketClient)">
+ <summary>
+ Remove a client from the internal clients list
+ </summary>
+ <param name="client">client to remove</param>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.OnConnect(System.IAsyncResult)">
+ <summary>
+ Callback used to accept a connection on the server socket
+ </summary>
+ <param name="asyncResult">The result of the asynchronous operation</param>
+ <remarks>
+ <para>
+ On connection adds to the list of connections
+ if there are two many open connections you will be disconnected
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.Dispose">
+ <summary>
+ Close all network connections
+ </summary>
+ <remarks>
+ <para>
+ Make sure we close all network connections
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.SocketHandler.HasConnections">
+ <summary>
+ Test if this handler has active connections
+ </summary>
+ <value>
+ <c>true</c> if this handler has active connections
+ </value>
+ <remarks>
+ <para>
+ This property will be <c>true</c> while this handler has
+ active connections, that is at least one connection that
+ the handler will attempt to send a message to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender.SocketHandler.SocketClient">
+ <summary>
+ Class that represents a client connected to this handler
+ </summary>
+ <remarks>
+ <para>
+ Class that represents a client connected to this handler
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.#ctor(System.Net.Sockets.Socket)">
+ <summary>
+ Create this <see cref="T:log4net.Appender.TelnetAppender.SocketHandler.SocketClient"/> for the specified <see cref="T:System.Net.Sockets.Socket"/>
+ </summary>
+ <param name="socket">the client's socket</param>
+ <remarks>
+ <para>
+ Opens a stream writer on the socket.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.Send(System.String)">
+ <summary>
+ Write a string to the client
+ </summary>
+ <param name="message">string to send</param>
+ <remarks>
+ <para>
+ Write a string to the client
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.Dispose">
+ <summary>
+ Cleanup the clients connection
+ </summary>
+ <remarks>
+ <para>
+ Close the socket connection.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TraceAppender">
+ <summary>
+ Appends log events to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </summary>
+ <remarks>
+ <para>
+ The application configuration file can be used to control what listeners
+ are actually used. See the MSDN documentation for the
+ <see cref="T:System.Diagnostics.Trace"/> class for details on configuring the
+ trace system.
+ </para>
+ <para>
+ Events are written using the <c>System.Diagnostics.Trace.Write(string,string)</c>
+ method. The event's logger name is passed as the value for the category name to the Write method.
+ </para>
+ <para>
+ <b>Compact Framework</b><br/>
+ The Compact Framework does not support the <see cref="T:System.Diagnostics.Trace"/>
+ class for any operation except <c>Assert</c>. When using the Compact Framework this
+ appender will write to the <see cref="T:System.Diagnostics.Debug"/> system rather than
+ the Trace system. This appender will therefore behave like the <see cref="T:log4net.Appender.DebugAppender"/>.
+ </para>
+ </remarks>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TraceAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TraceAppender"/>
+ with a specified layout.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.TraceAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying writer or output stream
+ will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.TraceAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logs events are not actually written to persistent media if and
+ when the application crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TraceAppender.ImmediateFlush">
+ <summary>
+ Gets or sets a value that indicates whether the appender will
+ flush at the end of each write.
+ </summary>
+ <remarks>
+ <para>The default behavior is to flush at the end of each
+ write. If the option is set to<c>false</c>, then the underlying
+ stream can defer writing to physical medium to a later time.
+ </para>
+ <para>
+ Avoiding the flush operation at the end of each append results
+ in a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TraceAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.AliasDomainAttribute">
+ <summary>
+ Assembly level attribute that specifies a domain to alias to this assembly's repository.
+ </summary>
+ <remarks>
+ <para>
+ <b>AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute.</b>
+ </para>
+ <para>
+ An assembly's logger repository is defined by its <see cref="T:log4net.Config.DomainAttribute"/>,
+ however this can be overridden by an assembly loaded before the target assembly.
+ </para>
+ <para>
+ An assembly can alias another assembly's domain to its repository by
+ specifying this attribute with the name of the target domain.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may be used
+ as many times as necessary to alias all the required domains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.AliasRepositoryAttribute">
+ <summary>
+ Assembly level attribute that specifies a repository to alias to this assembly's repository.
+ </summary>
+ <remarks>
+ <para>
+ An assembly's logger repository is defined by its <see cref="T:log4net.Config.RepositoryAttribute"/>,
+ however this can be overridden by an assembly loaded before the target assembly.
+ </para>
+ <para>
+ An assembly can alias another assembly's repository to its repository by
+ specifying this attribute with the name of the target repository.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may be used
+ as many times as necessary to alias all the required repositories.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.AliasRepositoryAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasRepositoryAttribute"/> class with
+ the specified repository to alias to this assembly's repository.
+ </summary>
+ <param name="name">The repository to alias to this assemby's repository.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasRepositoryAttribute"/> class with
+ the specified repository to alias to this assembly's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.AliasRepositoryAttribute.Name">
+ <summary>
+ Gets or sets the repository to alias to this assemby's repository.
+ </summary>
+ <value>
+ The repository to alias to this assemby's repository.
+ </value>
+ <remarks>
+ <para>
+ The name of the repository to alias to this assemby's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.AliasDomainAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasDomainAttribute"/> class with
+ the specified domain to alias to this assembly's repository.
+ </summary>
+ <param name="name">The domain to alias to this assemby's repository.</param>
+ <remarks>
+ <para>
+ Obsolete. Use <see cref="T:log4net.Config.AliasRepositoryAttribute"/> instead of <see cref="T:log4net.Config.AliasDomainAttribute"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.BasicConfigurator">
+ <summary>
+ Use this class to quickly configure a <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </summary>
+ <remarks>
+ <para>
+ Allows very simple programmatic configuration of log4net.
+ </para>
+ <para>
+ Only one appender can be configured using this configurator.
+ The appender is set at the root of the hierarchy and all logging
+ events will be delivered to that appender.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.BasicConfigurator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure">
+ <summary>
+ Initializes the log4net system with a default configuration.
+ </summary>
+ <remarks>
+ <para>
+ Initializes the log4net logging system using a <see cref="T:log4net.Appender.ConsoleAppender"/>
+ that will write to <c>Console.Out</c>. The log messages are
+ formatted using the <see cref="T:log4net.Layout.PatternLayout"/> layout object
+ with the <see cref="F:log4net.Layout.PatternLayout.DetailConversionPattern"/>
+ layout style.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initializes the log4net system using the specified appender.
+ </summary>
+ <param name="appender">The appender to use to log all logging events.</param>
+ <remarks>
+ <para>
+ Initializes the log4net system using the specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> with a default configuration.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Initializes the specified repository using a <see cref="T:log4net.Appender.ConsoleAppender"/>
+ that will write to <c>Console.Out</c>. The log messages are
+ formatted using the <see cref="T:log4net.Layout.PatternLayout"/> layout object
+ with the <see cref="F:log4net.Layout.PatternLayout.DetailConversionPattern"/>
+ layout style.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Repository.ILoggerRepository,log4net.Appender.IAppender)">
+ <summary>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified appender.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="appender">The appender to use to log all logging events.</param>
+ <remarks>
+ <para>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.ConfiguratorAttribute">
+ <summary>
+ Base class for all log4net configuration attributes.
+ </summary>
+ <remarks>
+ This is an abstract class that must be extended by
+ specific configurators. This attribute allows the
+ configurator to be parameterized by an assembly level
+ attribute.
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.#ctor(System.Int32)">
+ <summary>
+ Constructor used by subclasses.
+ </summary>
+ <param name="priority">the ordering priority for this configurator</param>
+ <remarks>
+ <para>
+ The <paramref name="priority"/> is used to order the configurator
+ attributes before they are invoked. Higher priority configurators are executed
+ before lower priority ones.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Abstract method implemented by a subclass. When this method is called
+ the subclass should configure the <paramref name="targetRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.CompareTo(System.Object)">
+ <summary>
+ Compare this instance to another ConfiguratorAttribute
+ </summary>
+ <param name="obj">the object to compare to</param>
+ <returns>see <see cref="M:System.IComparable.CompareTo(System.Object)"/></returns>
+ <remarks>
+ <para>
+ Compares the priorities of the two <see cref="T:log4net.Config.ConfiguratorAttribute"/> instances.
+ Sorts by priority in descending order. Objects with the same priority are
+ randomly ordered.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.DomainAttribute">
+ <summary>
+ Assembly level attribute that specifies the logging domain for the assembly.
+ </summary>
+ <remarks>
+ <para>
+ <b>DomainAttribute is obsolete. Use RepositoryAttribute instead of DomainAttribute.</b>
+ </para>
+ <para>
+ Assemblies are mapped to logging domains. Each domain has its own
+ logging repository. This attribute specified on the assembly controls
+ the configuration of the domain. The <see cref="P:log4net.Config.RepositoryAttribute.Name"/> property specifies the name
+ of the domain that this assembly is a part of. The <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/>
+ specifies the type of the repository objects to create for the domain. If
+ this attribute is not specified and a <see cref="P:log4net.Config.RepositoryAttribute.Name"/> is not specified
+ then the assembly will be part of the default shared logging domain.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may only be used
+ once per assembly.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.RepositoryAttribute">
+ <summary>
+ Assembly level attribute that specifies the logging repository for the assembly.
+ </summary>
+ <remarks>
+ <para>
+ Assemblies are mapped to logging repository. This attribute specified
+ on the assembly controls
+ the configuration of the repository. The <see cref="P:log4net.Config.RepositoryAttribute.Name"/> property specifies the name
+ of the repository that this assembly is a part of. The <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/>
+ specifies the type of the <see cref="T:log4net.Repository.ILoggerRepository"/> object
+ to create for the assembly. If this attribute is not specified or a <see cref="P:log4net.Config.RepositoryAttribute.Name"/>
+ is not specified then the assembly will be part of the default shared logging repository.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may only be used
+ once per assembly.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.RepositoryAttribute.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.RepositoryAttribute"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.RepositoryAttribute.#ctor(System.String)">
+ <summary>
+ Initialize a new instance of the <see cref="T:log4net.Config.RepositoryAttribute"/> class
+ with the name of the repository.
+ </summary>
+ <param name="name">The name of the repository.</param>
+ <remarks>
+ <para>
+ Initialize the attribute with the name for the assembly's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.RepositoryAttribute.Name">
+ <summary>
+ Gets or sets the name of the logging repository.
+ </summary>
+ <value>
+ The string name to use as the name of the repository associated with this
+ assembly.
+ </value>
+ <remarks>
+ <para>
+ This value does not have to be unique. Several assemblies can share the
+ same repository. They will share the logging configuration of the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.RepositoryAttribute.RepositoryType">
+ <summary>
+ Gets or sets the type of repository to create for this assembly.
+ </summary>
+ <value>
+ The type of repository to create for this assembly.
+ </value>
+ <remarks>
+ <para>
+ The type of the repository to create for the assembly.
+ The type must implement the <see cref="T:log4net.Repository.ILoggerRepository"/>
+ interface.
+ </para>
+ <para>
+ This will be the type of repository created when
+ the repository is created. If multiple assemblies reference the
+ same repository then the repository is only created once using the
+ <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/> of the first assembly to call into the
+ repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DomainAttribute.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.DomainAttribute"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Obsolete. Use RepositoryAttribute instead of DomainAttribute.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DomainAttribute.#ctor(System.String)">
+ <summary>
+ Initialize a new instance of the <see cref="T:log4net.Config.DomainAttribute"/> class
+ with the name of the domain.
+ </summary>
+ <param name="name">The name of the domain.</param>
+ <remarks>
+ <para>
+ Obsolete. Use RepositoryAttribute instead of DomainAttribute.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.DOMConfigurator">
+ <summary>
+ Use this class to initialize the log4net environment using an Xml tree.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ Configures a <see cref="T:log4net.Repository.ILoggerRepository"/> using an Xml tree.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure">
+ <summary>
+ Automatically configures the log4net system based on the
+ application's configuration settings.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Automatically configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using settings
+ stored in the application's configuration file.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configures log4net using a <c>log4net</c> element
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified XML
+ element.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.IO.Stream)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configStream">A stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.Stream)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configStream">The stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.ConfigureAndWatch(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the file specified, monitors the file for changes
+ and reloads the configuration if a change is detected.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.ConfigureAndWatch(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the file specified,
+ monitors the file for changes and reloads the configuration if a change
+ is detected.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="T:log4net.Config.DOMConfiguratorAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </summary>
+ <remarks>
+ <para>
+ <b>AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute.</b>
+ </para>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.XmlConfiguratorAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </summary>
+ <remarks>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ <para>
+ If neither of the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> or <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>
+ properties are set the configuration is loaded from the application's .config file.
+ If set the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> property takes priority over the
+ <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> property. The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> property
+ specifies a path to a file to load the config from. The path is relative to the
+ application's base directory; <see cref="P:System.AppDomain.BaseDirectory"/>.
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> property is used as a postfix to the assembly file name.
+ The config file must be located in the application's base directory; <see cref="P:System.AppDomain.BaseDirectory"/>.
+ For example in a console application setting the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> to
+ <c>config</c> has the same effect as not specifying the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> or
+ <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> properties.
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.Watch"/> property can be set to cause the <see cref="T:log4net.Config.XmlConfigurator"/>
+ to watch the configuration file for changes.
+ </para>
+ <note>
+ <para>
+ Log4net will only look for assembly level configuration attributes once.
+ When using the log4net assembly level attributes to control the configuration
+ of log4net you must ensure that the first call to any of the
+ <see cref="T:log4net.Core.LoggerManager"/> methods is made from the assembly with the configuration
+ attributes.
+ </para>
+ <para>
+ If you cannot guarantee the order in which log4net calls will be made from
+ different assemblies you must use programmatic configuration instead, i.e.
+ call the <see cref="M:log4net.Config.XmlConfigurator.Configure"/> method directly.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Configure the repository using the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ The <paramref name="targetRepository"/> specified must extend the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>
+ class otherwise the <see cref="T:log4net.Config.XmlConfigurator"/> will not be able to
+ configure it.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="repository"/> does not extend <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.</exception>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromFile(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attempt to load configuration from the local file system
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromFile(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configure the specified repository using a <see cref="T:System.IO.FileInfo"/>
+ </summary>
+ <param name="targetRepository">The repository to configure.</param>
+ <param name="configFile">the FileInfo pointing to the config file</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromUri(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attempt to load configuration from a URI
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile">
+ <summary>
+ Gets or sets the filename of the configuration file.
+ </summary>
+ <value>
+ The filename of the configuration file.
+ </value>
+ <remarks>
+ <para>
+ If specified, this is the name of the configuration file to use with
+ the <see cref="T:log4net.Config.XmlConfigurator"/>. This file path is relative to the
+ <b>application base</b> directory (<see cref="P:System.AppDomain.BaseDirectory"/>).
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> takes priority over the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension">
+ <summary>
+ Gets or sets the extension of the configuration file.
+ </summary>
+ <value>
+ The extension of the configuration file.
+ </value>
+ <remarks>
+ <para>
+ If specified this is the extension for the configuration file.
+ The path to the config file is built by using the <b>application
+ base</b> directory (<see cref="P:System.AppDomain.BaseDirectory"/>),
+ the <b>assembly file name</b> and the config file extension.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> is set to <c>MyExt</c> then
+ possible config file names would be: <c>MyConsoleApp.exe.MyExt</c> or
+ <c>MyClassLibrary.dll.MyExt</c>.
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> takes priority over the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.Watch">
+ <summary>
+ Gets or sets a value indicating whether to watch the configuration file.
+ </summary>
+ <value>
+ <c>true</c> if the configuration should be watched, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ If this flag is specified and set to <c>true</c> then the framework
+ will watch the configuration file and will reload the config each time
+ the file is modified.
+ </para>
+ <para>
+ The config file can only be watched if it is loaded from local disk.
+ In a No-Touch (Smart Client) deployment where the application is downloaded
+ from a web server the config file may not reside on the local disk
+ and therefore it may not be able to watch it.
+ </para>
+ <note>
+ Watching configuration is not supported on the SSCLI.
+ </note>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.Log4NetConfigurationSectionHandler">
+ <summary>
+ Class to register for the log4net section of the configuration file
+ </summary>
+ <remarks>
+ The log4net section of the configuration file needs to have a section
+ handler registered. This is the section handler used. It simply returns
+ the XML element that is the root of the section.
+ </remarks>
+ <example>
+ Example of registering the log4net section handler :
+ <code lang="XML" escaped="true">
+ <configuration>
+ <configSections>
+ <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
+ </configSections>
+ <log4net>
+ log4net configuration XML goes here
+ </log4net>
+ </configuration>
+ </code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.Log4NetConfigurationSectionHandler.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.Log4NetConfigurationSectionHandler.Create(System.Object,System.Object,System.Xml.XmlNode)">
+ <summary>
+ Parses the configuration section.
+ </summary>
+ <param name="parent">The configuration settings in a corresponding parent configuration section.</param>
+ <param name="configContext">The configuration context when called from the ASP.NET configuration system. Otherwise, this parameter is reserved and is a null reference.</param>
+ <param name="section">The <see cref="T:System.Xml.XmlNode"/> for the log4net section.</param>
+ <returns>The <see cref="T:System.Xml.XmlNode"/> for the log4net section.</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="T:System.Xml.XmlNode"/> containing the configuration data,
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.PluginAttribute">
+ <summary>
+ Assembly level attribute that specifies a plugin to attach to
+ the repository.
+ </summary>
+ <remarks>
+ <para>
+ Specifies the type of a plugin to create and attach to the
+ assembly's repository. The plugin type must implement the
+ <see cref="T:log4net.Plugin.IPlugin"/> interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Plugin.IPluginFactory">
+ <summary>
+ Interface used to create plugins.
+ </summary>
+ <remarks>
+ <para>
+ Interface used to create a plugin.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.IPluginFactory.CreatePlugin">
+ <summary>
+ Creates the plugin object.
+ </summary>
+ <returns>the new plugin instance</returns>
+ <remarks>
+ <para>
+ Create and return a new plugin instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.PluginAttribute"/> class
+ with the specified type.
+ </summary>
+ <param name="typeName">The type name of plugin to create.</param>
+ <remarks>
+ <para>
+ Create the attribute with the plugin type specified.
+ </para>
+ <para>
+ Where possible use the constructor that takes a <see cref="T:System.Type"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.#ctor(System.Type)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.PluginAttribute"/> class
+ with the specified type.
+ </summary>
+ <param name="type">The type of plugin to create.</param>
+ <remarks>
+ <para>
+ Create the attribute with the plugin type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.CreatePlugin">
+ <summary>
+ Creates the plugin object defined by this attribute.
+ </summary>
+ <remarks>
+ <para>
+ Creates the instance of the <see cref="T:log4net.Plugin.IPlugin"/> object as
+ specified by this attribute.
+ </para>
+ </remarks>
+ <returns>The plugin object.</returns>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.ToString">
+ <summary>
+ Returns a representation of the properties of this object.
+ </summary>
+ <remarks>
+ <para>
+ Overrides base class <see cref="M:System.Object.ToString"/> method to
+ return a representation of the properties of this object.
+ </para>
+ </remarks>
+ <returns>A representation of the properties of this object</returns>
+ </member>
+ <member name="P:log4net.Config.PluginAttribute.Type">
+ <summary>
+ Gets or sets the type for the plugin.
+ </summary>
+ <value>
+ The type for the plugin.
+ </value>
+ <remarks>
+ <para>
+ The type for the plugin.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.PluginAttribute.TypeName">
+ <summary>
+ Gets or sets the type name for the plugin.
+ </summary>
+ <value>
+ The type name for the plugin.
+ </value>
+ <remarks>
+ <para>
+ The type name for the plugin.
+ </para>
+ <para>
+ Where possible use the <see cref="P:log4net.Config.PluginAttribute.Type"/> property instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.SecurityContextProviderAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Core.SecurityContextProvider"/>.
+ </summary>
+ <remarks>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Config.SecurityContextProviderAttribute.#ctor(System.Type)">
+ <summary>
+ Construct provider attribute with type specified
+ </summary>
+ <param name="providerType">the type of the provider to use</param>
+ <remarks>
+ <para>
+ The provider specified must subclass the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.SecurityContextProviderAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the SecurityContextProvider
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Creates a provider instance from the <see cref="P:log4net.Config.SecurityContextProviderAttribute.ProviderType"/> specified.
+ Sets this as the default security context provider <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.SecurityContextProviderAttribute.ProviderType">
+ <summary>
+ Gets or sets the type of the provider to use.
+ </summary>
+ <value>
+ the type of the provider to use.
+ </value>
+ <remarks>
+ <para>
+ The provider specified must subclass the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ class.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.XmlConfigurator">
+ <summary>
+ Use this class to initialize the log4net environment using an Xml tree.
+ </summary>
+ <remarks>
+ <para>
+ Configures a <see cref="T:log4net.Repository.ILoggerRepository"/> using an Xml tree.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure">
+ <summary>
+ Automatically configures the log4net system based on the
+ application's configuration settings.
+ </summary>
+ <remarks>
+ <para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </para>
+ <para>
+ To use this method to configure log4net you must specify
+ the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> section
+ handler for the <c>log4net</c> configuration section. See the
+ <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> for an example.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Automatically configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using settings
+ stored in the application's configuration file.
+ </summary>
+ <remarks>
+ <para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </para>
+ <para>
+ To use this method to configure log4net you must specify
+ the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> section
+ handler for the <c>log4net</c> configuration section. See the
+ <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> for an example.
+ </para>
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configures log4net using a <c>log4net</c> element
+ </summary>
+ <remarks>
+ <para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </para>
+ </remarks>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified XML
+ element.
+ </summary>
+ <remarks>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <para>
+ The first element matching <c>&lt;configuration&gt;</c> will be read as the
+ configuration. If this file is also a .NET .config file then you must specify
+ a configuration section for the <c>log4net</c> element otherwise .NET will
+ complain. Set the type for the section handler to <see cref="T:System.Configuration.IgnoreSectionHandler"/>, for example:
+ <code lang="XML" escaped="true">
+ <configSections>
+ <section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
+ </configSections>
+ </code>
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.Uri)">
+ <summary>
+ Configures log4net using the specified configuration URI.
+ </summary>
+ <param name="configUri">A URI to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The <see cref="T:System.Net.WebRequest"/> must support the URI scheme specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.IO.Stream)">
+ <summary>
+ Configures log4net using the specified configuration data stream.
+ </summary>
+ <param name="configStream">A stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <para>
+ The first element matching <c>&lt;configuration&gt;</c> will be read as the
+ configuration. If this file is also a .NET .config file then you must specify
+ a configuration section for the <c>log4net</c> element otherwise .NET will
+ complain. Set the type for the section handler to <see cref="T:System.Configuration.IgnoreSectionHandler"/>, for example:
+ <code lang="XML" escaped="true">
+ <configSections>
+ <section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
+ </configSections>
+ </code>
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Uri)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ URI.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configUri">A URI to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The <see cref="T:System.Net.WebRequest"/> must support the URI scheme specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.Stream)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configStream">The stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the file specified, monitors the file for changes
+ and reloads the configuration if a change is detected.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatch(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the file specified,
+ monitors the file for changes and reloads the configuration if a change
+ is detected.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureFromXml(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the specified repository using a <c>log4net</c> element.
+ </summary>
+ <param name="repository">The hierarchy to configure.</param>
+ <param name="element">The element to parse.</param>
+ <remarks>
+ <para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </para>
+ <para>
+ This method is ultimately called by one of the Configure methods
+ to load the configuration from an <see cref="T:System.Xml.XmlElement"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler">
+ <summary>
+ Class used to watch config files.
+ </summary>
+ <remarks>
+ <para>
+ Uses the <see cref="T:System.IO.FileSystemWatcher"/> to monitor
+ changes to a specified file. Because multiple change notifications
+ may be raised when the file is modified, a timer is used to
+ compress the notifications into a single event. The timer
+ waits for <see cref="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis"/> time before delivering
+ the event notification. If any further <see cref="T:System.IO.FileSystemWatcher"/>
+ change notifications arrive while the timer is waiting it
+ is reset and waits again for <see cref="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis"/> to
+ elapse.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis">
+ <summary>
+ The default amount of time to wait after receiving notification
+ before reloading the config file.
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.StartWatching(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Watch a specified config file used to configure a repository
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The configuration file to watch.</param>
+ <remarks>
+ <para>
+ Watch a specified config file used to configure a repository
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_configFile">
+ <summary>
+ Holds the FileInfo used to configure the XmlConfigurator
+ </summary>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_repository">
+ <summary>
+ Holds the repository being configured.
+ </summary>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_timer">
+ <summary>
+ The timer used to compress the notification events.
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.#ctor(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/> class.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The configuration file to watch.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.ConfigureAndWatchHandler_OnChanged(System.Object,System.IO.FileSystemEventArgs)">
+ <summary>
+ Event handler used by <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/>.
+ </summary>
+ <param name="source">The <see cref="T:System.IO.FileSystemWatcher"/> firing the event.</param>
+ <param name="e">The argument indicates the file that caused the event to be fired.</param>
+ <remarks>
+ <para>
+ This handler reloads the configuration from the file when the event is fired.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.ConfigureAndWatchHandler_OnRenamed(System.Object,System.IO.RenamedEventArgs)">
+ <summary>
+ Event handler used by <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/>.
+ </summary>
+ <param name="source">The <see cref="T:System.IO.FileSystemWatcher"/> firing the event.</param>
+ <param name="e">The argument indicates the file that caused the event to be fired.</param>
+ <remarks>
+ <para>
+ This handler reloads the configuration from the file when the event is fired.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.OnWatchedFileChange(System.Object)">
+ <summary>
+ Called by the timer when the configuration has been updated.
+ </summary>
+ <param name="state">null</param>
+ </member>
+ <member name="T:log4net.Core.CompactRepositorySelector">
+ <summary>
+ The implementation of the <see cref="T:log4net.Core.IRepositorySelector"/> interface suitable
+ for use with the compact framework
+ </summary>
+ <remarks>
+ <para>
+ This <see cref="T:log4net.Core.IRepositorySelector"/> implementation is a simple
+ mapping between repository name and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ object.
+ </para>
+ <para>
+ The .NET Compact Framework 1.0 does not support retrieving assembly
+ level attributes therefore unlike the <c>DefaultRepositorySelector</c>
+ this selector does not examine the calling assembly for attributes.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Core.IRepositorySelector">
+ <summary>
+ Interface used by the <see cref="T:log4net.LogManager"/> to select the <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.LogManager"/> uses a <see cref="T:log4net.Core.IRepositorySelector"/>
+ to specify the policy for selecting the correct <see cref="T:log4net.Repository.ILoggerRepository"/>
+ to return to the caller.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="assembly">The assembly to use to lookup to the <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the assembly.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </para>
+ <para>
+ How the association between <see cref="T:System.Reflection.Assembly"/> and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ is made is not defined. The implementation may choose any method for
+ this association. The results of this method must be repeatable, i.e.
+ when called again with the same arguments the result must be the
+ save value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Gets the named <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repositoryName">The name to use to lookup to the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The named <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ Lookup a named <see cref="T:log4net.Repository.ILoggerRepository"/>. This is the repository created by
+ calling <see cref="M:log4net.Core.IRepositorySelector.CreateRepository(System.String,System.Type)"/>.
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a new repository for the assembly specified.
+ </summary>
+ <param name="assembly">The assembly to use to create the domain to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the domain
+ specified such that a call to <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ How the association between <see cref="T:System.Reflection.Assembly"/> and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ is made is not defined. The implementation may choose any method for
+ this association.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a new repository with the name specified.
+ </summary>
+ <param name="repositoryName">The name to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the name
+ specified such that a call to <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.String)"/> with the
+ same name will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.IRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets an array of all currently defined repositories.
+ </summary>
+ <returns>
+ An array of the <see cref="T:log4net.Repository.ILoggerRepository"/> instances created by
+ this <see cref="T:log4net.Core.IRepositorySelector"/>.</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.#ctor(System.Type)">
+ <summary>
+ Create a new repository selector
+ </summary>
+ <param name="defaultRepositoryType">the type of the repositories to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <remarks>
+ <para>
+ Create an new compact repository selector.
+ The default type for repositories must be specified,
+ an appropriate value would be <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="defaultRepositoryType"/> is null</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException">throw if <paramref name="defaultRepositoryType"/> does not implement <see cref="T:log4net.Repository.ILoggerRepository"/></exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Get the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly
+ </summary>
+ <param name="assembly">not used</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ <para>
+ The <paramref name="assembly"/> argument is not used. This selector does not create a
+ separate repository for each assembly.
+ </para>
+ <para>
+ As a named repository is not specified the default repository is
+ returned. The default repository is named <c>log4net-default-repository</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Get the named <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </summary>
+ <param name="repositoryName">the name of the repository to lookup</param>
+ <returns>The named <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ <para>
+ Get the named <see cref="T:log4net.Repository.ILoggerRepository"/>. The default
+ repository is <c>log4net-default-repository</c>. Other repositories
+ must be created using the <see cref="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)"/>.
+ If the named repository does not exist an exception is thrown.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
+ <exception cref="T:log4net.Core.LogException">throw if the <paramref name="repositoryName"/> does not exist</exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Create a new repository for the assembly specified
+ </summary>
+ <param name="assembly">not used</param>
+ <param name="repositoryType">the type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <returns>the repository created</returns>
+ <remarks>
+ <para>
+ The <paramref name="assembly"/> argument is not used. This selector does not create a
+ separate repository for each assembly.
+ </para>
+ <para>
+ If the <paramref name="repositoryType"/> is <c>null</c> then the
+ default repository type specified to the constructor is used.
+ </para>
+ <para>
+ As a named repository is not specified the default repository is
+ returned. The default repository is named <c>log4net-default-repository</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Create a new repository for the repository specified
+ </summary>
+ <param name="repositoryName">the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <param name="repositoryType">the type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ If this param is null then the default repository type is used.</param>
+ <returns>the repository created</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)"/> with the
+ same repository specified will return the same repository instance.
+ </para>
+ <para>
+ If the named repository already exists an exception will be thrown.
+ </para>
+ <para>
+ If <paramref name="repositoryType"/> is <c>null</c> then the default
+ repository type specified to the constructor is used.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
+ <exception cref="T:log4net.Core.LogException">throw if the <paramref name="repositoryName"/> already exists</exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets a list of <see cref="T:log4net.Repository.ILoggerRepository"/> objects
+ </summary>
+ <returns>an array of all known <see cref="T:log4net.Repository.ILoggerRepository"/> objects</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.OnLoggerRepositoryCreatedEvent(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Notify the registered listeners that the repository has been created
+ </summary>
+ <param name="repository">The repository that has been created</param>
+ <remarks>
+ <para>
+ Raises the <event cref="E:log4net.Core.CompactRepositorySelector.LoggerRepositoryCreatedEvent">LoggerRepositoryCreatedEvent</event>
+ event.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Core.CompactRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.DefaultRepositorySelector">
+ <summary>
+ The default implementation of the <see cref="T:log4net.Core.IRepositorySelector"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ Uses attributes defined on the calling assembly to determine how to
+ configure the hierarchy for the repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.#ctor(System.Type)">
+ <summary>
+ Creates a new repository selector.
+ </summary>
+ <param name="defaultRepositoryType">The type of the repositories to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <remarks>
+ <para>
+ Create an new repository selector.
+ The default type for repositories must be specified,
+ an appropriate value would be <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="defaultRepositoryType"/> is <see langword="null"/>.</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="defaultRepositoryType"/> does not implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="repositoryAssembly">The assembly use to lookup the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <remarks>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and the repository
+ to create can be overridden by specifying the <see cref="T:log4net.Config.RepositoryAttribute"/>
+ attribute on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ The default values are to use the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>
+ implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically configured using
+ any <see cref="T:log4net.Config.ConfiguratorAttribute"/> attributes defined on
+ the <paramref name="repositoryAssembly"/>.
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the assembly</returns>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified repository.
+ </summary>
+ <param name="repositoryName">The repository to use to lookup the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified repository.</returns>
+ <remarks>
+ <para>
+ Returns the named repository. If <paramref name="repositoryName"/> is <c>null</c>
+ a <see cref="T:System.ArgumentNullException"/> is thrown. If the repository
+ does not exist a <see cref="T:log4net.Core.LogException"/> is thrown.
+ </para>
+ <para>
+ Use <see cref="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)"/> to create a repository.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryName"/> is <see langword="null"/>.</exception>
+ <exception cref="T:log4net.Core.LogException"><paramref name="repositoryName"/> does not exist.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Create a new repository for the assembly specified
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to create the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and
+ the repository to create can be overridden by specifying the
+ <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ <paramref name="repositoryAssembly"/>. The default values are to use the
+ <paramref name="repositoryType"/> implementation of the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically
+ configured using any <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes defined on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ If a repository for the <paramref name="repositoryAssembly"/> already exists
+ that repository will be returned. An error will not be raised and that
+ repository may be of a different type to that specified in <paramref name="repositoryType"/>.
+ Also the <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ assembly may be used to override the repository type specified in
+ <paramref name="repositoryType"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type,System.String,System.Boolean)">
+ <summary>
+ Creates a new repository for the assembly specified.
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to create the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryName">The name to assign to the created repository</param>
+ <param name="readAssemblyAttributes">Set to <c>true</c> to read and apply the assembly attributes</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and
+ the repository to create can be overridden by specifying the
+ <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ <paramref name="repositoryAssembly"/>. The default values are to use the
+ <paramref name="repositoryType"/> implementation of the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically
+ configured using any <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes defined on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ If a repository for the <paramref name="repositoryAssembly"/> already exists
+ that repository will be returned. An error will not be raised and that
+ repository may be of a different type to that specified in <paramref name="repositoryType"/>.
+ Also the <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ assembly may be used to override the repository type specified in
+ <paramref name="repositoryType"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a new repository for the specified repository.
+ </summary>
+ <param name="repositoryName">The repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ If this param is <see langword="null"/> then the default repository type is used.</param>
+ <returns>The new repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)"/> with the
+ same repository specified will return the same repository instance.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryName"/> is <see langword="null"/>.</exception>
+ <exception cref="T:log4net.Core.LogException"><paramref name="repositoryName"/> already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets a list of <see cref="T:log4net.Repository.ILoggerRepository"/> objects
+ </summary>
+ <returns>an array of all known <see cref="T:log4net.Repository.ILoggerRepository"/> objects</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.AliasRepository(System.String,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Aliases a repository to an existing repository.
+ </summary>
+ <param name="repositoryAlias">The repository to alias.</param>
+ <param name="repositoryTarget">The repository that the repository is aliased to.</param>
+ <remarks>
+ <para>
+ The repository specified will be aliased to the repository when created.
+ The repository must not already exist.
+ </para>
+ <para>
+ When the repository is created it must utilize the same repository type as
+ the repository it is aliased to, otherwise the aliasing will fail.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="repositoryAlias"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repositoryTarget"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.OnLoggerRepositoryCreatedEvent(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Notifies the registered listeners that the repository has been created.
+ </summary>
+ <param name="repository">The repository that has been created.</param>
+ <remarks>
+ <para>
+ Raises the <see cref="E:log4net.Core.DefaultRepositorySelector.LoggerRepositoryCreatedEvent"/> event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetInfoForAssembly(System.Reflection.Assembly,System.String@,System.Type@)">
+ <summary>
+ Gets the repository name and repository type for the specified assembly.
+ </summary>
+ <param name="assembly">The assembly that has a <see cref="T:log4net.Config.RepositoryAttribute"/>.</param>
+ <param name="repositoryName">in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling.</param>
+ <param name="repositoryType">in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling.</param>
+ <exception cref="T:System.ArgumentNullException"><paramref name="assembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.ConfigureRepository(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the repository using information from the assembly.
+ </summary>
+ <param name="assembly">The assembly containing <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes which define the configuration for the repository.</param>
+ <param name="repository">The repository to configure.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.LoadPlugins(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Loads the attribute defined plugins on the assembly.
+ </summary>
+ <param name="assembly">The assembly that contains the attributes.</param>
+ <param name="repository">The repository to add the plugins to.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.LoadAliases(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Loads the attribute defined aliases on the assembly.
+ </summary>
+ <param name="assembly">The assembly that contains the attributes.</param>
+ <param name="repository">The repository to alias to.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="E:log4net.Core.DefaultRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ErrorCode">
+ <summary>
+ Defined error codes that can be passed to the <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ Values passed to the <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.GenericFailure">
+ <summary>
+ A general error
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.WriteFailure">
+ <summary>
+ Error while writing output
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.FlushFailure">
+ <summary>
+ Failed to flush file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.CloseFailure">
+ <summary>
+ Failed to close file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.FileOpenFailure">
+ <summary>
+ Unable to open output file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.MissingLayout">
+ <summary>
+ No layout specified
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.AddressParseFailure">
+ <summary>
+ Failed to parse address
+ </summary>
+ </member>
+ <member name="T:log4net.Core.IErrorHandler">
+ <summary>
+ Appenders may delegate their error handling to an <see cref="T:log4net.Core.IErrorHandler"/>.
+ </summary>
+ <remarks>
+ <para>
+ Error handling is a particularly tedious to get right because by
+ definition errors are hard to predict and to reproduce.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)">
+ <summary>
+ Handles the error and information about the error condition is passed as
+ a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <param name="e">The <see cref="T:System.Exception"/> that was thrown when the error occurred.</param>
+ <param name="errorCode">The error code associated with the error.</param>
+ <remarks>
+ <para>
+ Handles the error and information about the error condition is passed as
+ a parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception)">
+ <summary>
+ Prints the error message passed as a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <param name="e">The <see cref="T:System.Exception"/> that was thrown when the error occurred.</param>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String)">
+ <summary>
+ Prints the error message passed as a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.IFixingRequired">
+ <summary>
+ Interface for objects that require fixing.
+ </summary>
+ <remarks>
+ <para>
+ Interface that indicates that the object requires fixing before it
+ can be taken outside the context of the appender's
+ <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ When objects that implement this interface are stored
+ in the context properties maps <see cref="T:log4net.GlobalContext"/>
+ <see cref="P:log4net.GlobalContext.Properties"/> and <see cref="T:log4net.ThreadContext"/>
+ <see cref="P:log4net.ThreadContext.Properties"/> are fixed
+ (see <see cref="P:log4net.Core.LoggingEvent.Fix"/>) the <see cref="M:log4net.Core.IFixingRequired.GetFixedObject"/>
+ method will be called.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.IFixingRequired.GetFixedObject">
+ <summary>
+ Get a portable version of this object
+ </summary>
+ <returns>the portable instance of this object</returns>
+ <remarks>
+ <para>
+ Get a portable instance object that represents the current
+ state of this object. The portable object can be stored
+ and logged from any thread with identical results.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ILogger">
+ <summary>
+ Interface that all loggers implement
+ </summary>
+ <remarks>
+ <para>
+ This interface supports logging events and testing if a level
+ is enabled for logging.
+ </para>
+ <para>
+ These methods will not throw exceptions. Note to implementor, ensure
+ that the implementation of these methods cannot allow an exception
+ to be thrown to the caller.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.ILogger.Log(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This generic form is intended to be used by wrappers.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">the exception to log, including its stack trace. Pass <c>null</c> to not log an exception.</param>
+ <remarks>
+ <para>
+ Generates a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/> and <paramref name="exception"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.ILogger.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ This is the most generic printing method that is intended to be used
+ by wrappers.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Logs the specified logging event through this logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.ILogger.IsEnabledFor(log4net.Core.Level)">
+ <summary>
+ Checks if this logger is enabled for a given <see cref="T:log4net.Core.Level"/> passed as parameter.
+ </summary>
+ <param name="level">The level to check.</param>
+ <returns>
+ <c>true</c> if this logger is enabled for <c>level</c>, otherwise <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Test if this logger is going to log events of the specified <paramref name="level"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.ILogger.Name">
+ <summary>
+ Gets the name of the logger.
+ </summary>
+ <value>
+ The name of the logger.
+ </value>
+ <remarks>
+ <para>
+ The name of this logger
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.ILogger.Repository">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this logger belongs to.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ILoggerWrapper">
+ <summary>
+ Base interface for all wrappers
+ </summary>
+ <remarks>
+ <para>
+ Base interface for all wrappers.
+ </para>
+ <para>
+ All wrappers must implement this interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="P:log4net.Core.ILoggerWrapper.Logger">
+ <summary>
+ Get the implementation behind this wrapper object.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ILogger"/> object that in implementing this object.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Core.ILogger"/> object that in implementing this
+ object. The <c>Logger</c> object may not
+ be the same object as this object because of logger decorators.
+ This gets the actual underlying objects that is used to process
+ the log events.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerRepositoryCreationEventHandler">
+ <summary>
+ Delegate used to handle logger repository creation event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Core.IRepositorySelector"/> which created the repository.</param>
+ <param name="e">The <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> event args
+ that holds the <see cref="T:log4net.Repository.ILoggerRepository"/> instance that has been created.</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository creation event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerRepositoryCreationEventArgs">
+ <summary>
+ Provides data for the <see cref="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent"/> event.
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent"/>
+ event is raised every time a <see cref="T:log4net.Repository.ILoggerRepository"/> is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerRepositoryCreationEventArgs.m_repository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LoggerRepositoryCreationEventArgs.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Construct instance using <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ </summary>
+ <param name="repository">the <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created</param>
+ <remarks>
+ <para>
+ Construct instance using <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggerRepositoryCreationEventArgs.LoggerRepository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ITriggeringEventEvaluator">
+ <summary>
+ Test if an <see cref="T:log4net.Core.LoggingEvent"/> triggers an action
+ </summary>
+ <remarks>
+ <para>
+ Implementations of this interface allow certain appenders to decide
+ when to perform an appender specific action.
+ </para>
+ <para>
+ The action or behavior triggered is defined by the implementation.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.ITriggeringEventEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Test if this event triggers the action
+ </summary>
+ <param name="loggingEvent">The event to check</param>
+ <returns><c>true</c> if this event triggers the action, otherwise <c>false</c></returns>
+ <remarks>
+ <para>
+ Return <c>true</c> if this event triggers the action
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.Level">
+ <summary>
+ Defines the default set of levels recognized by the system.
+ </summary>
+ <remarks>
+ <para>
+ Each <see cref="T:log4net.Core.LoggingEvent"/> has an associated <see cref="T:log4net.Core.Level"/>.
+ </para>
+ <para>
+ Levels have a numeric <see cref="P:log4net.Core.Level.Value"/> that defines the relative
+ ordering between levels. Two Levels with the same <see cref="P:log4net.Core.Level.Value"/>
+ are deemed to be equivalent.
+ </para>
+ <para>
+ The levels that are recognized by log4net are set for each <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and each repository can have different levels defined. The levels are stored
+ in the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/> on the repository. Levels are
+ looked up by name from the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>.
+ </para>
+ <para>
+ When logging at level INFO the actual level used is not <see cref="F:log4net.Core.Level.Info"/> but
+ the value of <c>LoggerRepository.LevelMap["INFO"]</c>. The default value for this is
+ <see cref="F:log4net.Core.Level.Info"/>, but this can be changed by reconfiguring the level map.
+ </para>
+ <para>
+ Each level has a <see cref="P:log4net.Core.Level.DisplayName"/> in addition to its <see cref="P:log4net.Core.Level.Name"/>. The
+ <see cref="P:log4net.Core.Level.DisplayName"/> is the string that is written into the output log. By default
+ the display name is the same as the level name, but this can be used to alias levels
+ or to localize the log output.
+ </para>
+ <para>
+ Some of the predefined levels recognized by the system are:
+ </para>
+ <list type="bullet">
+ <item>
+ <description><see cref="F:log4net.Core.Level.Off"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Fatal"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Error"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Warn"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Info"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Debug"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.All"/>.</description>
+ </item>
+ </list>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.Level.#ctor(System.Int32,System.String,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="level">Integer value for this level, higher values represent more severe levels.</param>
+ <param name="levelName">The string name of this level.</param>
+ <param name="displayName">The display name for this level. This may be localized or otherwise different from the name</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.Level"/> class with
+ the specified level name and value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.#ctor(System.Int32,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="level">Integer value for this level, higher values represent more severe levels.</param>
+ <param name="levelName">The string name of this level.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.Level"/> class with
+ the specified level name and value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.ToString">
+ <summary>
+ Returns the <see cref="T:System.String"/> representation of the current
+ <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <returns>
+ A <see cref="T:System.String"/> representation of the current <see cref="T:log4net.Core.Level"/>.
+ </returns>
+ <remarks>
+ <para>
+ Returns the level <see cref="P:log4net.Core.Level.Name"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.Equals(System.Object)">
+ <summary>
+ Compares levels.
+ </summary>
+ <param name="o">The object to compare against.</param>
+ <returns><c>true</c> if the objects are equal.</returns>
+ <remarks>
+ <para>
+ Compares the levels of <see cref="T:log4net.Core.Level"/> instances, and
+ defers to base class if the target object is not a <see cref="T:log4net.Core.Level"/>
+ instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.GetHashCode">
+ <summary>
+ Returns a hash code
+ </summary>
+ <returns>A hash code for the current <see cref="T:log4net.Core.Level"/>.</returns>
+ <remarks>
+ <para>
+ Returns a hash code suitable for use in hashing algorithms and data
+ structures like a hash table.
+ </para>
+ <para>
+ Returns the hash code of the level <see cref="P:log4net.Core.Level.Value"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.CompareTo(System.Object)">
+ <summary>
+ Compares this instance to a specified object and returns an
+ indication of their relative values.
+ </summary>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> instance or <see langword="null"/> to compare with this instance.</param>
+ <returns>
+ A 32-bit signed integer that indicates the relative order of the
+ values compared. The return value has these meanings:
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Meaning</description>
+ </listheader>
+ <item>
+ <term>Less than zero</term>
+ <description>This instance is less than <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Zero</term>
+ <description>This instance is equal to <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Greater than zero</term>
+ <description>
+ <para>This instance is greater than <paramref name="r"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="r"/> is <see langword="null"/>.</para>
+ </description>
+ </item>
+ </list>
+ </returns>
+ <remarks>
+ <para>
+ <paramref name="r"/> must be an instance of <see cref="T:log4net.Core.Level"/>
+ or <see langword="null"/>; otherwise, an exception is thrown.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException"><paramref name="r"/> is not a <see cref="T:log4net.Core.Level"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.Level.op_GreaterThan(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is greater than another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is greater than
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_LessThan(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is less than another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is less than
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_GreaterThanOrEqual(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is greater than or equal to another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is greater than or equal to
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_LessThanOrEqual(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is less than or equal to another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is less than or equal to
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_Equality(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether two specified <see cref="T:log4net.Core.Level"/>
+ objects have the same value.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <returns>
+ <c>true</c> if the value of <paramref name="l"/> is the same as the
+ value of <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_Inequality(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether two specified <see cref="T:log4net.Core.Level"/>
+ objects have different values.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <returns>
+ <c>true</c> if the value of <paramref name="l"/> is different from
+ the value of <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.Compare(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Compares two specified <see cref="T:log4net.Core.Level"/> instances.
+ </summary>
+ <param name="l">The first <see cref="T:log4net.Core.Level"/> to compare.</param>
+ <param name="r">The second <see cref="T:log4net.Core.Level"/> to compare.</param>
+ <returns>
+ A 32-bit signed integer that indicates the relative order of the
+ two values compared. The return value has these meanings:
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Meaning</description>
+ </listheader>
+ <item>
+ <term>Less than zero</term>
+ <description><paramref name="l"/> is less than <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Zero</term>
+ <description><paramref name="l"/> is equal to <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Greater than zero</term>
+ <description><paramref name="l"/> is greater than <paramref name="r"/>.</description>
+ </item>
+ </list>
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.Level.Off">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Off"/> level designates a higher level than all the rest.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Emergency">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Emergency"/> level designates very severe error events.
+ System unusable, emergencies.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Fatal">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Fatal"/> level designates very severe error events
+ that will presumably lead the application to abort.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Alert">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Alert"/> level designates very severe error events.
+ Take immediate action, alerts.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Critical">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Critical"/> level designates very severe error events.
+ Critical condition, critical.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Severe">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Severe"/> level designates very severe error events.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Error">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Error"/> level designates error events that might
+ still allow the application to continue running.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Warn">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Warn"/> level designates potentially harmful
+ situations.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Notice">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Notice"/> level designates informational messages
+ that highlight the progress of the application at the highest level.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Info">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Info"/> level designates informational messages that
+ highlight the progress of the application at coarse-grained level.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Debug">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Debug"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Fine">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Fine"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Trace">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Trace"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Finer">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Finer"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Verbose">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Verbose"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Finest">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Finest"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.All">
+ <summary>
+ The <see cref="F:log4net.Core.Level.All"/> level designates the lowest level possible.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.Level.Name">
+ <summary>
+ Gets the name of this level.
+ </summary>
+ <value>
+ The name of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the name of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.Level.Value">
+ <summary>
+ Gets the value of this level.
+ </summary>
+ <value>
+ The value of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the value of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.Level.DisplayName">
+ <summary>
+ Gets the display name of this level.
+ </summary>
+ <value>
+ The display name of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the display name of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LevelCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Core.Level"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ReadOnly(log4net.Core.LevelCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>LevelCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ A <c>LevelCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>LevelCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.LevelCollection)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <c>LevelCollection</c>.
+ </summary>
+ <param name="c">The <c>LevelCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.Level[])">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Core.Level"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Core.Level"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Core.Level"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Core.Level"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.LevelCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.CopyTo(log4net.Core.Level[])">
+ <summary>
+ Copies the entire <c>LevelCollection</c> to a one-dimensional
+ <see cref="T:log4net.Core.Level"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Core.Level"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.CopyTo(log4net.Core.Level[],System.Int32)">
+ <summary>
+ Copies the entire <c>LevelCollection</c> to a one-dimensional
+ <see cref="T:log4net.Core.Level"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Core.Level"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Add(log4net.Core.Level)">
+ <summary>
+ Adds a <see cref="T:log4net.Core.Level"/> to the end of the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Clear">
+ <summary>
+ Removes all elements from the <c>LevelCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Core.LevelCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Contains(log4net.Core.Level)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Core.Level"/> is in the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>LevelCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.IndexOf(log4net.Core.Level)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Core.Level"/>
+ in the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to locate in the <c>LevelCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>LevelCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Insert(System.Int32,log4net.Core.Level)">
+ <summary>
+ Inserts an element into the <c>LevelCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Remove(log4net.Core.Level)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Core.Level"/> from the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to remove from the <c>LevelCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Core.Level"/> was not found in the <c>LevelCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>LevelCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>LevelCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Core.LevelCollection.Enumerator"/> for the entire <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(log4net.Core.LevelCollection)">
+ <summary>
+ Adds the elements of another <c>LevelCollection</c> to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="x">The <c>LevelCollection</c> whose elements should be added to the end of the current <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(log4net.Core.Level[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Core.Level"/> array to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Core.Level"/> array whose elements should be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Core.Level"/> collection to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Core.Level"/> collection whose elements should be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>LevelCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <value>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.Level"/> at the specified index.
+ </summary>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value>true if the collection is read-only; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>LevelCollection</c> can contain.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.ILevelCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ILevelCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ILevelCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.ILevelCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LevelCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.#ctor(log4net.Core.LevelCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelEvaluator">
+ <summary>
+ An evaluator that triggers at a threshold level
+ </summary>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LevelEvaluator.m_threshold">
+ <summary>
+ The threshold for triggering
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.#ctor">
+ <summary>
+ Create a new evaluator using the <see cref="F:log4net.Core.Level.Off"/> threshold.
+ </summary>
+ <remarks>
+ <para>
+ Create a new evaluator using the <see cref="F:log4net.Core.Level.Off"/> threshold.
+ </para>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.#ctor(log4net.Core.Level)">
+ <summary>
+ Create a new evaluator using the specified <see cref="T:log4net.Core.Level"/> threshold.
+ </summary>
+ <param name="threshold">the threshold to trigger at</param>
+ <remarks>
+ <para>
+ Create a new evaluator using the specified <see cref="T:log4net.Core.Level"/> threshold.
+ </para>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Is this <paramref name="loggingEvent"/> the triggering event?
+ </summary>
+ <param name="loggingEvent">The event to check</param>
+ <returns>This method returns <c>true</c>, if the event level
+ is equal or higher than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>.
+ Otherwise it returns <c>false</c></returns>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelEvaluator.Threshold">
+ <summary>
+ the threshold to trigger at
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.Level"/> that will cause this evaluator to trigger
+ </value>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LevelMap">
+ <summary>
+ Mapping between string name and Level object
+ </summary>
+ <remarks>
+ <para>
+ Mapping between string name and <see cref="T:log4net.Core.Level"/> object.
+ This mapping is held separately for each <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ The level name is case insensitive.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LevelMap.m_mapName2Level">
+ <summary>
+ Mapping from level name to Level object. The
+ level name is case insensitive
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelMap.#ctor">
+ <summary>
+ Construct the level map
+ </summary>
+ <remarks>
+ <para>
+ Construct the level map.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Clear">
+ <summary>
+ Clear the internal maps of all levels
+ </summary>
+ <remarks>
+ <para>
+ Clear the internal maps of all levels
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(System.String,System.Int32)">
+ <summary>
+ Create a new Level and add it to the map
+ </summary>
+ <param name="name">the string to display for the Level</param>
+ <param name="value">the level value to give to the Level</param>
+ <remarks>
+ <para>
+ Create a new Level and add it to the map
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LevelMap.Add(System.String,System.Int32,System.String)"/>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(System.String,System.Int32,System.String)">
+ <summary>
+ Create a new Level and add it to the map
+ </summary>
+ <param name="name">the string to display for the Level</param>
+ <param name="value">the level value to give to the Level</param>
+ <param name="displayName">the display name to give to the Level</param>
+ <remarks>
+ <para>
+ Create a new Level and add it to the map
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(log4net.Core.Level)">
+ <summary>
+ Add a Level to the map
+ </summary>
+ <param name="level">the Level to add</param>
+ <remarks>
+ <para>
+ Add a Level to the map
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.LookupWithDefault(log4net.Core.Level)">
+ <summary>
+ Lookup a named level from the map
+ </summary>
+ <param name="defaultLevel">the name of the level to lookup is taken from this level.
+ If the level is not set on the map then this level is added</param>
+ <returns>the level in the map with the name specified</returns>
+ <remarks>
+ <para>
+ Lookup a named level from the map. The name of the level to lookup is taken
+ from the <see cref="P:log4net.Core.Level.Name"/> property of the <paramref name="defaultLevel"/>
+ argument.
+ </para>
+ <para>
+ If no level with the specified name is found then the
+ <paramref name="defaultLevel"/> argument is added to the level map
+ and returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelMap.Item(System.String)">
+ <summary>
+ Lookup a <see cref="T:log4net.Core.Level"/> by name
+ </summary>
+ <param name="name">The name of the Level to lookup</param>
+ <returns>a Level from the map with the name specified</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="T:log4net.Core.Level"/> from the
+ map with the name specified. If the no level is
+ found then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelMap.AllLevels">
+ <summary>
+ Return all possible levels as a list of Level objects.
+ </summary>
+ <returns>all possible levels as a list of Level objects</returns>
+ <remarks>
+ <para>
+ Return all possible levels as a list of Level objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LocationInfo">
+ <summary>
+ The internal representation of caller location information.
+ </summary>
+ <remarks>
+ <para>
+ This class uses the <c>System.Diagnostics.StackTrace</c> class to generate
+ a call stack. The caller's information is then extracted from this stack.
+ </para>
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class is not supported on the
+ .NET Compact Framework 1.0 therefore caller location information is not
+ available on that framework.
+ </para>
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
+ </para>
+ <para>
+ "StackTrace information will be most informative with Debug build configurations.
+ By default, Debug builds include debug symbols, while Release builds do not. The
+ debug symbols contain most of the file, method name, line number, and column
+ information used in constructing StackFrame and StackTrace objects. StackTrace
+ might not report as many method calls as expected, due to code transformations
+ that occur during optimization."
+ </para>
+ <para>
+ This means that in a Release build the caller information may be incomplete or may
+ not exist at all! Therefore caller location information cannot be relied upon in a Release build.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Core.LocationInfo.NA">
+ <summary>
+ When location information is not available the constant
+ <c>NA</c> is returned. Current value of this string
+ constant is <b>?</b>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LocationInfo.#ctor(System.Type)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LocationInfo"/>
+ class based on the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LocationInfo.#ctor(System.String,System.String,System.String,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="className">The fully qualified class name.</param>
+ <param name="methodName">The method name.</param>
+ <param name="fileName">The file name.</param>
+ <param name="lineNumber">The line number of the method within the file.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LocationInfo"/>
+ class with the specified data.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.ClassName">
+ <summary>
+ Gets the fully qualified class name of the caller making the logging
+ request.
+ </summary>
+ <value>
+ The fully qualified class name of the caller making the logging
+ request.
+ </value>
+ <remarks>
+ <para>
+ Gets the fully qualified class name of the caller making the logging
+ request.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.FileName">
+ <summary>
+ Gets the file name of the caller.
+ </summary>
+ <value>
+ The file name of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the file name of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.LineNumber">
+ <summary>
+ Gets the line number of the caller.
+ </summary>
+ <value>
+ The line number of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the line number of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.MethodName">
+ <summary>
+ Gets the method name of the caller.
+ </summary>
+ <value>
+ The method name of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the method name of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.FullInfo">
+ <summary>
+ Gets all available caller information
+ </summary>
+ <value>
+ All available caller information, in the format
+ <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+ </value>
+ <remarks>
+ <para>
+ Gets all available caller information, in the format
+ <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerManager">
+ <summary>
+ Static manager that controls the creation of repositories
+ </summary>
+ <remarks>
+ <para>
+ Static manager that controls the creation of repositories
+ </para>
+ <para>
+ This class is used by the wrapper managers (e.g. <see cref="T:log4net.LogManager"/>)
+ to provide access to the <see cref="T:log4net.Core.ILogger"/> objects.
+ </para>
+ <para>
+ This manager also holds the <see cref="T:log4net.Core.IRepositorySelector"/> that is used to
+ lookup and create repositories. The selector can be set either programmatically using
+ the <see cref="P:log4net.Core.LoggerManager.RepositorySelector"/> property, or by setting the <c>log4net.RepositorySelector</c>
+ AppSetting in the applications config file to the fully qualified type name of the
+ selector to use.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.#ctor">
+ <summary>
+ Private constructor to prevent instances. Only static methods should be used.
+ </summary>
+ <remarks>
+ <para>
+ Private constructor to prevent instances. Only static methods should be used.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.#cctor">
+ <summary>
+ Hook the shutdown event
+ </summary>
+ <remarks>
+ <para>
+ On the full .NET runtime, the static constructor hooks up the
+ <c>AppDomain.ProcessExit</c> and <c>AppDomain.DomainUnload</c>> events.
+ These are used to shutdown the log4net system as the application exits.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.RegisterAppDomainEvents">
+ <summary>
+ Register for ProcessExit and DomainUnload events on the AppDomain
+ </summary>
+ <remarks>
+ <para>
+ This needs to be in a separate method because the events make
+ a LinkDemand for the ControlAppDomain SecurityPermission. Because
+ this is a LinkDemand it is demanded at JIT time. Therefore we cannot
+ catch the exception in the method itself, we have to catch it in the
+ caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLoggerRepository(System.String)">
+ <summary>
+ Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repository">the repository to lookup in</param>
+ <returns>Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLoggerRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetRepository(System.String)">
+ <summary>
+ Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repository">the repository to lookup in</param>
+ <returns>Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Exists(System.String,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the named logger does not exist in the
+ specified repository.
+ </returns>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Exists(System.Reflection.Assembly,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the named logger does not exist in the
+ specified assembly's repository.
+ </returns>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified assembly's repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetCurrentLoggers(System.String)">
+ <summary>
+ Returns all the currently defined loggers in the specified repository.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <returns>All the defined loggers.</returns>
+ <remarks>
+ <para>
+ The root logger is <b>not</b> included in the returned array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetCurrentLoggers(System.Reflection.Assembly)">
+ <summary>
+ Returns all the currently defined loggers in the specified assembly's repository.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>All the defined loggers.</returns>
+ <remarks>
+ <para>
+ The root logger is <b>not</b> included in the returned array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.String,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.Reflection.Assembly,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.String,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Gets the logger for the fully qualified name of the type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to lookup the repository</param>
+ <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Gets the logger for the fully qualified name of the type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Shutdown">
+ <summary>
+ Shuts down the log4net system.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in all the
+ default repositories.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ShutdownRepository(System.String)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <param name="repository">The repository to shutdown.</param>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository for the <paramref name="repository"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ShutdownRepository(System.Reflection.Assembly)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository for the repository. The repository is looked up using
+ the <paramref name="repositoryAssembly"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ResetConfiguration(System.String)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <param name="repository">The repository to reset.</param>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ResetConfiguration(System.Reflection.Assembly)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository to reset.</param>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An Exception will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An Exception will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetAllRepositories">
+ <summary>
+ Gets an array of all currently defined repositories.
+ </summary>
+ <returns>An array of all the known <see cref="T:log4net.Repository.ILoggerRepository"/> objects.</returns>
+ <remarks>
+ <para>
+ Gets an array of all currently defined repositories.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetVersionInfo">
+ <summary>
+ Internal method to get pertinent version info.
+ </summary>
+ <returns>A string of version info.</returns>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.OnDomainUnload(System.Object,System.EventArgs)">
+ <summary>
+ Called when the <see cref="E:System.AppDomain.DomainUnload"/> event fires
+ </summary>
+ <param name="sender">the <see cref="T:System.AppDomain"/> that is exiting</param>
+ <param name="e">null</param>
+ <remarks>
+ <para>
+ Called when the <see cref="E:System.AppDomain.DomainUnload"/> event fires.
+ </para>
+ <para>
+ When the event is triggered the log4net system is <see cref="M:log4net.Core.LoggerManager.Shutdown"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.OnProcessExit(System.Object,System.EventArgs)">
+ <summary>
+ Called when the <see cref="E:System.AppDomain.ProcessExit"/> event fires
+ </summary>
+ <param name="sender">the <see cref="T:System.AppDomain"/> that is exiting</param>
+ <param name="e">null</param>
+ <remarks>
+ <para>
+ Called when the <see cref="E:System.AppDomain.ProcessExit"/> event fires.
+ </para>
+ <para>
+ When the event is triggered the log4net system is <see cref="M:log4net.Core.LoggerManager.Shutdown"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerManager.s_repositorySelector">
+ <summary>
+ Initialize the default repository selector
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LoggerManager.RepositorySelector">
+ <summary>
+ Gets or sets the repository selector used by the <see cref="T:log4net.LogManager"/>.
+ </summary>
+ <value>
+ The repository selector used by the <see cref="T:log4net.LogManager"/>.
+ </value>
+ <remarks>
+ <para>
+ The repository selector (<see cref="T:log4net.Core.IRepositorySelector"/>) is used by
+ the <see cref="T:log4net.LogManager"/> to create and select repositories
+ (<see cref="T:log4net.Repository.ILoggerRepository"/>).
+ </para>
+ <para>
+ The caller to <see cref="T:log4net.LogManager"/> supplies either a string name
+ or an assembly (if not supplied the assembly is inferred using
+ <see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ <para>
+ This context is used by the selector to lookup a specific repository.
+ </para>
+ <para>
+ For the full .NET Framework, the default repository is <c>DefaultRepositorySelector</c>;
+ for the .NET Compact Framework <c>CompactRepositorySelector</c> is the default
+ repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerWrapperImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.ILoggerWrapper"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ This class should be used as the base for all wrapper implementations.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LoggerWrapperImpl.#ctor(log4net.Core.ILogger)">
+ <summary>
+ Constructs a new wrapper for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <remarks>
+ <para>
+ Constructs a new wrapper for the specified logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerWrapperImpl.m_logger">
+ <summary>
+ The logger that this object is wrapping
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LoggerWrapperImpl.Logger">
+ <summary>
+ Gets the implementation behind this wrapper object.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ILogger"/> object that this object is implementing.
+ </value>
+ <remarks>
+ <para>
+ The <c>Logger</c> object may not be the same object as this object
+ because of logger decorators.
+ </para>
+ <para>
+ This gets the actual underlying objects that is used to process
+ the log events.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggingEventData">
+ <summary>
+ Portable data structure used by <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Portable data structure used by <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.LoggerName">
+ <summary>
+ The logger name.
+ </summary>
+ <remarks>
+ <para>
+ The logger name.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Level">
+ <summary>
+ Level of logging event.
+ </summary>
+ <remarks>
+ <para>
+ Level of logging event. Level cannot be Serializable
+ because it is a flyweight. Due to its special serialization it
+ cannot be declared final either.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Message">
+ <summary>
+ The application supplied message.
+ </summary>
+ <remarks>
+ <para>
+ The application supplied message of logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.ThreadName">
+ <summary>
+ The name of thread
+ </summary>
+ <remarks>
+ <para>
+ The name of thread in which this logging event was generated
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.TimeStamp">
+ <summary>
+ The time the event was logged
+ </summary>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.LocationInfo">
+ <summary>
+ Location information for the caller.
+ </summary>
+ <remarks>
+ <para>
+ Location information for the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.UserName">
+ <summary>
+ String representation of the user
+ </summary>
+ <remarks>
+ <para>
+ String representation of the user's windows name,
+ like DOMAIN\username
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Identity">
+ <summary>
+ String representation of the identity.
+ </summary>
+ <remarks>
+ <para>
+ String representation of the current thread's principal identity.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.ExceptionString">
+ <summary>
+ The string representation of the exception
+ </summary>
+ <remarks>
+ <para>
+ The string representation of the exception
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Domain">
+ <summary>
+ String representation of the AppDomain.
+ </summary>
+ <remarks>
+ <para>
+ String representation of the AppDomain.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Properties">
+ <summary>
+ Additional event specific properties
+ </summary>
+ <remarks>
+ <para>
+ A logger or an appender may attach additional
+ properties to specific events. These properties
+ have a string key and an object value.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.FixFlags">
+ <summary>
+ Flags passed to the <see cref="P:log4net.Core.LoggingEvent.Fix"/> property
+ </summary>
+ <remarks>
+ <para>
+ Flags passed to the <see cref="P:log4net.Core.LoggingEvent.Fix"/> property
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Mdc">
+ <summary>
+ Fix the MDC
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Ndc">
+ <summary>
+ Fix the NDC
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Message">
+ <summary>
+ Fix the rendered message
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.ThreadName">
+ <summary>
+ Fix the thread name
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.LocationInfo">
+ <summary>
+ Fix the callers location information
+ </summary>
+ <remarks>
+ CAUTION: Very slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.UserName">
+ <summary>
+ Fix the callers windows user name
+ </summary>
+ <remarks>
+ CAUTION: Slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Domain">
+ <summary>
+ Fix the domain friendly name
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Identity">
+ <summary>
+ Fix the callers principal name
+ </summary>
+ <remarks>
+ CAUTION: May be slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Exception">
+ <summary>
+ Fix the exception text
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Properties">
+ <summary>
+ Fix the event properties
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.None">
+ <summary>
+ No fields fixed
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.All">
+ <summary>
+ All fields fixed
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Partial">
+ <summary>
+ Partial fields fixed
+ </summary>
+ <remarks>
+ <para>
+ This set of partial fields gives good performance. The following fields are fixed:
+ </para>
+ <list type="bullet">
+ <item><description><see cref="F:log4net.Core.FixFlags.Message"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.ThreadName"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Exception"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Domain"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Properties"/></description></item>
+ </list>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggingEvent">
+ <summary>
+ The internal representation of logging events.
+ </summary>
+ <remarks>
+ <para>
+ When an affirmative decision is made to log then a
+ <see cref="T:log4net.Core.LoggingEvent"/> instance is created. This instance
+ is passed around to the different log4net components.
+ </para>
+ <para>
+ This class is of concern to those wishing to extend log4net.
+ </para>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ for incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.HostNameProperty">
+ <summary>
+ The key into the Properties map for the host name value.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.IdentityProperty">
+ <summary>
+ The key into the Properties map for the thread identity value.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.UserNameProperty">
+ <summary>
+ The key into the Properties map for the user name value.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,System.String,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ from the supplied parameters.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="loggerName">The name of the logger of this event.</param>
+ <param name="level">The level of this event.</param>
+ <param name="message">The message of this event.</param>
+ <param name="exception">The exception for this event.</param>
+ <remarks>
+ <para>
+ Except <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>, <see cref="P:log4net.Core.LoggingEvent.Level"/> and <see cref="P:log4net.Core.LoggingEvent.LoggerName"/>,
+ all fields of <c>LoggingEvent</c> are filled when actually needed. Call
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> to cache all data locally
+ to prevent inconsistencies.
+ </para>
+ <para>This method is called by the log4net framework
+ to create a logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,log4net.Core.LoggingEventData,log4net.Core.FixFlags)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="data">Data used to initialize the logging event.</param>
+ <param name="fixedData">The fields in the <paranref name="data"/> struct that have already been fixed.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ The <paramref name="fixedData"/> parameter should be used to specify which fields in the
+ <paramref name="data"/> struct have been preset. Fields not specified in the <paramref name="fixedData"/>
+ will be captured from the environment if requested or fixed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,log4net.Core.LoggingEventData)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="data">Data used to initialize the logging event.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ This constructor sets this objects <see cref="P:log4net.Core.LoggingEvent.Fix"/> flags to <see cref="F:log4net.Core.FixFlags.All"/>,
+ this assumes that all the data relating to this event is passed in via the <paramref name="data"/>
+ parameter and no other data should be captured from the environment.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(log4net.Core.LoggingEventData)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="data">Data used to initialize the logging event.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ This constructor sets this objects <see cref="P:log4net.Core.LoggingEvent.Fix"/> flags to <see cref="F:log4net.Core.FixFlags.All"/>,
+ this assumes that all the data relating to this event is passed in via the <paramref name="data"/>
+ parameter and no other data should be captured from the environment.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.EnsureRepository(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Ensure that the repository is set.
+ </summary>
+ <param name="repository">the value for the repository</param>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)">
+ <summary>
+ Write the rendered message to a TextWriter
+ </summary>
+ <param name="writer">the writer to write the message to</param>
+ <remarks>
+ <para>
+ Unlike the <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property this method
+ does store the message data in the internal cache. Therefore
+ if called only once this method should be faster than the
+ <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property, however if the message is
+ to be accessed multiple times then the property will be more efficient.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
+ <param name="context">The destination for this serialization.</param>
+ <remarks>
+ <para>
+ The data in this event must be fixed before it can be serialized.
+ </para>
+ <para>
+ The <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> method must be called during the
+ <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method call if this event
+ is to be used outside that method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetLoggingEventData">
+ <summary>
+ Gets the portable data for this <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <returns>The <see cref="T:log4net.Core.LoggingEventData"/> for this event.</returns>
+ <remarks>
+ <para>
+ A new <see cref="T:log4net.Core.LoggingEvent"/> can be constructed using a
+ <see cref="T:log4net.Core.LoggingEventData"/> instance.
+ </para>
+ <para>
+ Does a <see cref="F:log4net.Core.FixFlags.Partial"/> fix of the data
+ in the logging event before returning the event data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)">
+ <summary>
+ Gets the portable data for this <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <param name="fixFlags">The set of data to ensure is fixed in the LoggingEventData</param>
+ <returns>The <see cref="T:log4net.Core.LoggingEventData"/> for this event.</returns>
+ <remarks>
+ <para>
+ A new <see cref="T:log4net.Core.LoggingEvent"/> can be constructed using a
+ <see cref="T:log4net.Core.LoggingEventData"/> instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetExceptionStrRep">
+ <summary>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <returns>
+ This event's exception's rendered using the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </returns>
+ <remarks>
+ <para>
+ <b>Obsolete. Use <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/> instead.</b>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetExceptionString">
+ <summary>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <returns>
+ This event's exception's rendered using the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </returns>
+ <remarks>
+ <para>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData">
+ <summary>
+ Fix instance fields that hold volatile data.
+ </summary>
+ <remarks>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ <para>
+ Calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> is equivalent to
+ calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> passing the parameter
+ <c>false</c>.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> for more
+ information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)">
+ <summary>
+ Fixes instance fields that hold volatile data.
+ </summary>
+ <param name="fastButLoose">Set to <c>true</c> to not fix data that takes a long time to fix.</param>
+ <remarks>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ for incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ <para>
+ The <paramref name="fastButLoose"/> param controls the data that
+ is fixed. Some of the data that can be fixed takes a long time to
+ generate, therefore if you do not require those settings to be fixed
+ they can be ignored by setting the <paramref name="fastButLoose"/> param
+ to <c>true</c>. This setting will ignore the <see cref="P:log4net.Core.LoggingEvent.LocationInformation"/>
+ and <see cref="P:log4net.Core.LoggingEvent.UserName"/> settings.
+ </para>
+ <para>
+ Set <paramref name="fastButLoose"/> to <c>false</c> to ensure that all
+ settings are fixed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)">
+ <summary>
+ Fix the fields specified by the <see cref="T:log4net.Core.FixFlags"/> parameter
+ </summary>
+ <param name="flags">the fields to fix</param>
+ <remarks>
+ <para>
+ Only fields specified in the <paramref name="flags"/> will be fixed.
+ Fields will not be fixed if they have previously been fixed.
+ It is not possible to 'unfix' a field.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.LookupProperty(System.String)">
+ <summary>
+ Lookup a composite property in this event
+ </summary>
+ <param name="key">the key for the property to lookup</param>
+ <returns>the value for the property</returns>
+ <remarks>
+ <para>
+ This event has composite properties that combine together properties from
+ several different contexts in the following order:
+ <list type="definition">
+ <item>
+ <term>this events properties</term>
+ <description>
+ This event has <see cref="P:log4net.Core.LoggingEvent.Properties"/> that can be set. These
+ properties are specific to this event only.
+ </description>
+ </item>
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetProperties">
+ <summary>
+ Get all the composite properties in this event
+ </summary>
+ <returns>the <see cref="T:log4net.Util.PropertiesDictionary"/> containing all the properties</returns>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.LookupProperty(System.String)"/> for details of the composite properties
+ stored by the event.
+ </para>
+ <para>
+ This method returns a single <see cref="T:log4net.Util.PropertiesDictionary"/> containing all the
+ properties defined for this event.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_data">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_compositeProperties">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_eventProperties">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_callerStackBoundaryDeclaringType">
+ <summary>
+ The fully qualified Type of the calling
+ logger class in the stack frame (i.e. the declaring type of the method).
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_message">
+ <summary>
+ The application supplied message of logging event.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_thrownException">
+ <summary>
+ The exception that was thrown.
+ </summary>
+ <remarks>
+ This is not serialized. The string representation
+ is serialized instead.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_repository">
+ <summary>
+ The repository that generated the logging event
+ </summary>
+ <remarks>
+ This is not serialized.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_fixFlags">
+ <summary>
+ The fix state for this event
+ </summary>
+ <remarks>
+ These flags indicate which fields have been fixed.
+ Not serialized.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_cacheUpdatable">
+ <summary>
+ Indicated that the internal cache is updateable (ie not fixed)
+ </summary>
+ <remarks>
+ This is a seperate flag to m_fixFlags as it allows incrementel fixing and simpler
+ changes in the caching strategy.
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.StartTime">
+ <summary>
+ Gets the time when the current process started.
+ </summary>
+ <value>
+ This is the time when this process started.
+ </value>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ <para>
+ Tries to get the start time for the current process.
+ Failing that it returns the time of the first call to
+ this property.
+ </para>
+ <para>
+ Note that AppDomains may be loaded and unloaded within the
+ same process without the process terminating and therefore
+ without the process start time being reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Level">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.TimeStamp">
+ <summary>
+ Gets the time of the logging event.
+ </summary>
+ <value>
+ The time of the logging event.
+ </value>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.LoggerName">
+ <summary>
+ Gets the name of the logger that logged the event.
+ </summary>
+ <value>
+ The name of the logger that logged the event.
+ </value>
+ <remarks>
+ <para>
+ Gets the name of the logger that logged the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.LocationInformation">
+ <summary>
+ Gets the location information for this logging event.
+ </summary>
+ <value>
+ The location information for this logging event.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Core.LocationInfo"/> class for more information on
+ supported frameworks and the different behavior in Debug and
+ Release builds.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.MessageObject">
+ <summary>
+ Gets the message object used to initialize this event.
+ </summary>
+ <value>
+ The message object used to initialize this event.
+ </value>
+ <remarks>
+ <para>
+ Gets the message object used to initialize this event.
+ Note that this event may not have a valid message object.
+ If the event is serialized the message object will not
+ be transferred. To get the text of the message the
+ <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property must be used
+ not this property.
+ </para>
+ <para>
+ If there is no defined message object for this event then
+ null will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.ExceptionObject">
+ <summary>
+ Gets the exception object used to initialize this event.
+ </summary>
+ <value>
+ The exception object used to initialize this event.
+ </value>
+ <remarks>
+ <para>
+ Gets the exception object used to initialize this event.
+ Note that this event may not have a valid exception object.
+ If the event is serialized the exception object will not
+ be transferred. To get the text of the exception the
+ <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/> method must be used
+ not this property.
+ </para>
+ <para>
+ If there is no defined exception object for this event then
+ null will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Repository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this event was created in.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this event was created in.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.RenderedMessage">
+ <summary>
+ Gets the message, rendered through the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <value>
+ The message rendered through the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.ThreadName">
+ <summary>
+ Gets the name of the current thread.
+ </summary>
+ <value>
+ The name of the current thread, or the thread ID when
+ the name is not available.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.UserName">
+ <summary>
+ Gets the name of the current user.
+ </summary>
+ <value>
+ The name of the current user, or <c>NOT AVAILABLE</c> when the
+ underlying runtime has no support for retrieving the name of the
+ current user.
+ </value>
+ <remarks>
+ <para>
+ Calls <c>WindowsIdentity.GetCurrent().Name</c> to get the name of
+ the current windows user.
+ </para>
+ <para>
+ To improve performance, we could cache the string representation of
+ the name, and reuse that as long as the identity stayed constant.
+ Once the identity changed, we would need to re-assign and re-render
+ the string.
+ </para>
+ <para>
+ However, the <c>WindowsIdentity.GetCurrent()</c> call seems to
+ return different objects every time, so the current implementation
+ doesn't do this type of caching.
+ </para>
+ <para>
+ Timing for these operations:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Method</term>
+ <description>Results</description>
+ </listheader>
+ <item>
+ <term><c>WindowsIdentity.GetCurrent()</c></term>
+ <description>10000 loops, 00:00:00.2031250 seconds</description>
+ </item>
+ <item>
+ <term><c>WindowsIdentity.GetCurrent().Name</c></term>
+ <description>10000 loops, 00:00:08.0468750 seconds</description>
+ </item>
+ </list>
+ <para>
+ This means we could speed things up almost 40 times by caching the
+ value of the <c>WindowsIdentity.GetCurrent().Name</c> property, since
+ this takes (8.04-0.20) = 7.84375 seconds.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Identity">
+ <summary>
+ Gets the identity of the current thread principal.
+ </summary>
+ <value>
+ The string name of the identity of the current thread principal.
+ </value>
+ <remarks>
+ <para>
+ Calls <c>System.Threading.Thread.CurrentPrincipal.Identity.Name</c> to get
+ the name of the current thread principal.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Domain">
+ <summary>
+ Gets the AppDomain friendly name.
+ </summary>
+ <value>
+ The AppDomain friendly name.
+ </value>
+ <remarks>
+ <para>
+ Gets the AppDomain friendly name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Properties">
+ <summary>
+ Additional event specific properties.
+ </summary>
+ <value>
+ Additional event specific properties.
+ </value>
+ <remarks>
+ <para>
+ A logger or an appender may attach additional
+ properties to specific events. These properties
+ have a string key and an object value.
+ </para>
+ <para>
+ This property is for events that have been added directly to
+ this event. The aggregate properties (which include these
+ event properties) can be retrieved using <see cref="M:log4net.Core.LoggingEvent.LookupProperty(System.String)"/>
+ and <see cref="M:log4net.Core.LoggingEvent.GetProperties"/>.
+ </para>
+ <para>
+ Once the properties have been fixed <see cref="P:log4net.Core.LoggingEvent.Fix"/> this property
+ returns the combined cached properties. This ensures that updates to
+ this property are always reflected in the underlying storage. When
+ returning the combined properties there may be more keys in the
+ Dictionary than expected.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Fix">
+ <summary>
+ The fixed fields in this event
+ </summary>
+ <value>
+ The set of fields that are fixed in this event
+ </value>
+ <remarks>
+ <para>
+ Fields will not be fixed if they have previously been fixed.
+ It is not possible to 'unfix' a field.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LogImpl">
+ <summary>
+ Implementation of <see cref="T:log4net.ILog"/> wrapper interface.
+ </summary>
+ <remarks>
+ <para>
+ This implementation of the <see cref="T:log4net.ILog"/> interface
+ forwards to the <see cref="T:log4net.Core.ILogger"/> held by the base class.
+ </para>
+ <para>
+ This logger has methods to allow the caller to log at the following
+ levels:
+ </para>
+ <list type="definition">
+ <item>
+ <term>DEBUG</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>DEBUG</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Debug"/>. The <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>INFO</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>INFO</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Info"/>. The <see cref="P:log4net.Core.LogImpl.IsInfoEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>WARN</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>WARN</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Warn"/>. The <see cref="P:log4net.Core.LogImpl.IsWarnEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>ERROR</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>ERROR</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Error"/>. The <see cref="P:log4net.Core.LogImpl.IsErrorEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>FATAL</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>FATAL</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Fatal"/>. The <see cref="P:log4net.Core.LogImpl.IsFatalEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ </list>
+ <para>
+ The values for these levels and their semantic meanings can be changed by
+ configuring the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/> for the repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.ILog">
+ <summary>
+ The ILog interface is use by application to log messages into
+ the log4net framework.
+ </summary>
+ <remarks>
+ <para>
+ Use the <see cref="T:log4net.LogManager"/> to obtain logger instances
+ that implement this interface. The <see cref="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)"/>
+ static method is used to get logger instances.
+ </para>
+ <para>
+ This class contains methods for logging at different levels and also
+ has properties for determining if those logging levels are
+ enabled in the current configuration.
+ </para>
+ <para>
+ This interface can be implemented in different ways. This documentation
+ specifies reasonable behavior that a caller can expect from the actual
+ implementation, however different implementations reserve the right to
+ do things differently.
+ </para>
+ </remarks>
+ <example>Simple example of logging messages
+ <code lang="C#">
+ ILog log = LogManager.GetLogger("application-log");
+
+ log.Info("Application Start");
+ log.Debug("This is a debug message");
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is another debug message");
+ }
+ </code>
+ </example>
+ <seealso cref="T:log4net.LogManager"/>
+ <seealso cref="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ILog.Debug(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>DEBUG</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Debug"/> level. If this logger is
+ <c>DEBUG</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of
+ the additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Debug(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Debug(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object[])">
+ <overloads>Log a formatted string with the <see cref="F:log4net.Core.Level.Debug"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Info(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Info"/> level.</overloads>
+ <summary>
+ Logs a message object with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>INFO</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Info"/> level. If this logger is
+ <c>INFO</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Info(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Info(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Warn(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>WARN</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Warn"/> level. If this logger is
+ <c>WARN</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Warn(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Warn(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Error(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Error"/> level.</overloads>
+ <summary>
+ Logs a message object with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>ERROR</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Error"/> level. If this logger is
+ <c>ERROR</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Error(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Error"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Error(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Fatal(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>FATAL</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Fatal"/> level. If this logger is
+ <c>FATAL</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Fatal(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Fatal(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsDebugEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Debug"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ This function is intended to lessen the computational cost of
+ disabled log debug statements.
+ </para>
+ <para> For some ILog interface <c>log</c>, when you write:</para>
+ <code lang="C#">
+ log.Debug("This is entry number: " + i );
+ </code>
+ <para>
+ You incur the cost constructing the message, string construction and concatenation in
+ this case, regardless of whether the message is logged or not.
+ </para>
+ <para>
+ If you are worried about speed (who isn't), then you should write:
+ </para>
+ <code lang="C#">
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way you will not incur the cost of parameter
+ construction if debugging is disabled for <c>log</c>. On
+ the other hand, if the <c>log</c> is debug enabled, you
+ will incur the cost of evaluating whether the logger is debug
+ enabled twice. Once in <see cref="P:log4net.ILog.IsDebugEnabled"/> and once in
+ the <see cref="M:log4net.ILog.Debug(System.Object)"/>. This is an insignificant overhead
+ since evaluating a logger takes about 1% of the time it
+ takes to actually log. This is the preferred style of logging.
+ </para>
+ <para>Alternatively if your logger is available statically then the is debug
+ enabled state can be stored in a static variable like this:
+ </para>
+ <code lang="C#">
+ private static readonly bool isDebugEnabled = log.IsDebugEnabled;
+ </code>
+ <para>
+ Then when you come to log you can write:
+ </para>
+ <code lang="C#">
+ if (isDebugEnabled)
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way the debug enabled state is only queried once
+ when the class is loaded. Using a <c>private static readonly</c>
+ variable is the most efficient because it is a run time constant
+ and can be heavily optimized by the JIT compiler.
+ </para>
+ <para>
+ Of course if you use a static readonly variable to
+ hold the enabled state of the logger then you cannot
+ change the enabled state at runtime to vary the logging
+ that is produced. You have to decide if you need absolute
+ speed or runtime flexibility.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="M:log4net.ILog.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ </member>
+ <member name="P:log4net.ILog.IsInfoEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Info"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="M:log4net.ILog.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsWarnEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Warn"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="M:log4net.ILog.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsErrorEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Error"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="M:log4net.ILog.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsFatalEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Fatal"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="M:log4net.ILog.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.#ctor(log4net.Core.ILogger)">
+ <summary>
+ Construct a new wrapper for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <remarks>
+ <para>
+ Construct a new wrapper for the specified logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ReloadLevels(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Virtual method called when the configuration of the repository changes
+ </summary>
+ <param name="repository">the repository holding the levels</param>
+ <remarks>
+ <para>
+ Virtual method called when the configuration of the repository changes
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Debug(System.Object)">
+ <summary>
+ Logs a message object with the <c>DEBUG</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>DEBUG</c>
+ enabled by comparing the level of this logger with the
+ <c>DEBUG</c> level. If this logger is
+ <c>DEBUG</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Debug(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Debug(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>DEBUG</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>DEBUG</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/> passed
+ as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Info(System.Object)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>INFO</c>
+ enabled by comparing the level of this logger with the
+ <c>INFO</c> level. If this logger is
+ <c>INFO</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of
+ the additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Info(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Info(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>INFO</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Warn(System.Object)">
+ <summary>
+ Logs a message object with the <c>WARN</c> level.
+ </summary>
+ <param name="message">the message object to log</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>WARN</c>
+ enabled by comparing the level of this logger with the
+ <c>WARN</c> level. If this logger is
+ <c>WARN</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Warn(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Warn(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>WARN</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>WARN</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Error(System.Object)">
+ <summary>
+ Logs a message object with the <c>ERROR</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>ERROR</c>
+ enabled by comparing the level of this logger with the
+ <c>ERROR</c> level. If this logger is
+ <c>ERROR</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Error(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Error(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>ERROR</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>ERROR</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Fatal(System.Object)">
+ <summary>
+ Logs a message object with the <c>FATAL</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>FATAL</c>
+ enabled by comparing the level of this logger with the
+ <c>FATAL</c> level. If this logger is
+ <c>FATAL</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Fatal(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Fatal(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>FATAL</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>FATAL</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.LoggerRepositoryConfigurationChanged(System.Object,System.EventArgs)">
+ <summary>
+ Event handler for the <see cref="E:log4net.Repository.ILoggerRepository.ConfigurationChanged"/> event
+ </summary>
+ <param name="sender">the repository</param>
+ <param name="e">Empty</param>
+ </member>
+ <member name="F:log4net.Core.LogImpl.ThisDeclaringType">
+ <summary>
+ The fully qualified name of this declaring type not the type of any subclass.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsDebugEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>DEBUG</c>
+ level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>DEBUG</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ This function is intended to lessen the computational cost of
+ disabled log debug statements.
+ </para>
+ <para>
+ For some <c>log</c> Logger object, when you write:
+ </para>
+ <code lang="C#">
+ log.Debug("This is entry number: " + i );
+ </code>
+ <para>
+ You incur the cost constructing the message, concatenation in
+ this case, regardless of whether the message is logged or not.
+ </para>
+ <para>
+ If you are worried about speed, then you should write:
+ </para>
+ <code lang="C#">
+ if (log.IsDebugEnabled())
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way you will not incur the cost of parameter
+ construction if debugging is disabled for <c>log</c>. On
+ the other hand, if the <c>log</c> is debug enabled, you
+ will incur the cost of evaluating whether the logger is debug
+ enabled twice. Once in <c>IsDebugEnabled</c> and once in
+ the <c>Debug</c>. This is an insignificant overhead
+ since evaluating a logger takes about 1% of the time it
+ takes to actually log.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsInfoEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>INFO</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>INFO</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples
+ of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Core.LogImpl.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsWarnEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>WARN</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>WARN</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples
+ of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsErrorEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>ERROR</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>ERROR</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsFatalEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>FATAL</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>FATAL</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="T:log4net.Core.SecurityContext">
+ <summary>
+ A SecurityContext used by log4net when interacting with protected resources
+ </summary>
+ <remarks>
+ <para>
+ A SecurityContext used by log4net when interacting with protected resources
+ for example with operating system services. This can be used to impersonate
+ a principal that has been granted privileges on the system resources.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.SecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate this SecurityContext
+ </summary>
+ <param name="state">State supplied by the caller</param>
+ <returns>An <see cref="T:System.IDisposable"/> instance that will
+ revoke the impersonation of this SecurityContext, or <c>null</c></returns>
+ <remarks>
+ <para>
+ Impersonate this security context. Further calls on the current
+ thread should now be made in the security context provided
+ by this object. When the <see cref="T:System.IDisposable"/> result
+ <see cref="M:System.IDisposable.Dispose"/> method is called the security
+ context of the thread should be reverted to the state it was in
+ before <see cref="M:log4net.Core.SecurityContext.Impersonate(System.Object)"/> was called.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.SecurityContextProvider">
+ <summary>
+ The <see cref="T:log4net.Core.SecurityContextProvider"/> providers default <see cref="T:log4net.Core.SecurityContext"/> instances.
+ </summary>
+ <remarks>
+ <para>
+ A configured component that interacts with potentially protected system
+ resources uses a <see cref="T:log4net.Core.SecurityContext"/> to provide the elevated
+ privileges required. If the <see cref="T:log4net.Core.SecurityContext"/> object has
+ been not been explicitly provided to the component then the component
+ will request one from this <see cref="T:log4net.Core.SecurityContextProvider"/>.
+ </para>
+ <para>
+ By default the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is
+ an instance of <see cref="T:log4net.Core.SecurityContextProvider"/> which returns only
+ <see cref="T:log4net.Util.NullSecurityContext"/> objects. This is a reasonable default
+ where the privileges required are not know by the system.
+ </para>
+ <para>
+ This default behavior can be overridden by subclassing the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ and overriding the <see cref="M:log4net.Core.SecurityContextProvider.CreateSecurityContext(System.Object)"/> method to return
+ the desired <see cref="T:log4net.Core.SecurityContext"/> objects. The default provider
+ can be replaced by programmatically setting the value of the
+ <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> property.
+ </para>
+ <para>
+ An alternative is to use the <c>log4net.Config.SecurityContextProviderAttribute</c>
+ This attribute can be applied to an assembly in the same way as the
+ <c>log4net.Config.XmlConfiguratorAttribute"</c>. The attribute takes
+ the type to use as the <see cref="T:log4net.Core.SecurityContextProvider"/> as an argument.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.SecurityContextProvider.s_defaultProvider">
+ <summary>
+ The default provider
+ </summary>
+ </member>
+ <member name="M:log4net.Core.SecurityContextProvider.#ctor">
+ <summary>
+ Protected default constructor to allow subclassing
+ </summary>
+ <remarks>
+ <para>
+ Protected default constructor to allow subclassing
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.SecurityContextProvider.CreateSecurityContext(System.Object)">
+ <summary>
+ Create a SecurityContext for a consumer
+ </summary>
+ <param name="consumer">The consumer requesting the SecurityContext</param>
+ <returns>An impersonation context</returns>
+ <remarks>
+ <para>
+ The default implementation is to return a <see cref="T:log4net.Util.NullSecurityContext"/>.
+ </para>
+ <para>
+ Subclasses should override this method to provide their own
+ behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.SecurityContextProvider.DefaultProvider">
+ <summary>
+ Gets or sets the default SecurityContextProvider
+ </summary>
+ <value>
+ The default SecurityContextProvider
+ </value>
+ <remarks>
+ <para>
+ The default provider is used by configured components that
+ require a <see cref="T:log4net.Core.SecurityContext"/> and have not had one
+ given to them.
+ </para>
+ <para>
+ By default this is an instance of <see cref="T:log4net.Core.SecurityContextProvider"/>
+ that returns <see cref="T:log4net.Util.NullSecurityContext"/> objects.
+ </para>
+ <para>
+ The default provider can be set programmatically by setting
+ the value of this property to a sub class of <see cref="T:log4net.Core.SecurityContextProvider"/>
+ that has the desired behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.WrapperCreationHandler">
+ <summary>
+ Delegate used to handle creation of new wrappers.
+ </summary>
+ <param name="logger">The logger to wrap in a wrapper.</param>
+ <remarks>
+ <para>
+ Delegate used to handle creation of new wrappers. This delegate
+ is called from the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/>
+ method to construct the wrapper for the specified logger.
+ </para>
+ <para>
+ The delegate to use is supplied to the <see cref="T:log4net.Core.WrapperMap"/>
+ constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.WrapperMap">
+ <summary>
+ Maps between logger objects and wrapper objects.
+ </summary>
+ <remarks>
+ <para>
+ This class maintains a mapping between <see cref="T:log4net.Core.ILogger"/> objects and
+ <see cref="T:log4net.Core.ILoggerWrapper"/> objects. Use the <see cref="M:log4net.Core.WrapperMap.GetWrapper(log4net.Core.ILogger)"/> method to
+ lookup the <see cref="T:log4net.Core.ILoggerWrapper"/> for the specified <see cref="T:log4net.Core.ILogger"/>.
+ </para>
+ <para>
+ New wrapper instances are created by the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/>
+ method. The default behavior is for this method to delegate construction
+ of the wrapper to the <see cref="T:log4net.Core.WrapperCreationHandler"/> delegate supplied
+ to the constructor. This allows specialization of the behavior without
+ requiring subclassing of this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.#ctor(log4net.Core.WrapperCreationHandler)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.WrapperMap"/>
+ </summary>
+ <param name="createWrapperHandler">The handler to use to create the wrapper objects.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.WrapperMap"/> class with
+ the specified handler to create the wrapper objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.GetWrapper(log4net.Core.ILogger)">
+ <summary>
+ Gets the wrapper object for the specified logger.
+ </summary>
+ <returns>The wrapper object for the specified logger</returns>
+ <remarks>
+ <para>
+ If the logger is null then the corresponding wrapper is null.
+ </para>
+ <para>
+ Looks up the wrapper it it has previously been requested and
+ returns it. If the wrapper has never been requested before then
+ the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/> virtual method is
+ called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)">
+ <summary>
+ Creates the wrapper object for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap in a wrapper.</param>
+ <returns>The wrapper object for the logger.</returns>
+ <remarks>
+ <para>
+ This implementation uses the <see cref="T:log4net.Core.WrapperCreationHandler"/>
+ passed to the constructor to create the wrapper. This method
+ can be overridden in a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.RepositoryShutdown(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Called when a monitored repository shutdown event is received.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that is shutting down</param>
+ <remarks>
+ <para>
+ This method is called when a <see cref="T:log4net.Repository.ILoggerRepository"/> that this
+ <see cref="T:log4net.Core.WrapperMap"/> is holding loggers for has signaled its shutdown
+ event <see cref="E:log4net.Repository.ILoggerRepository.ShutdownEvent"/>. The default
+ behavior of this method is to release the references to the loggers
+ and their wrappers generated for this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.ILoggerRepository_Shutdown(System.Object,System.EventArgs)">
+ <summary>
+ Event handler for repository shutdown event.
+ </summary>
+ <param name="sender">The sender of the event.</param>
+ <param name="e">The event args.</param>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_repositories">
+ <summary>
+ Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings
+ </summary>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_createWrapperHandler">
+ <summary>
+ The handler to use to create the extension wrapper objects.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_shutdownHandler">
+ <summary>
+ Internal reference to the delegate used to register for repository shutdown events.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.WrapperMap.Repositories">
+ <summary>
+ Gets the map of logger repositories.
+ </summary>
+ <value>
+ Map of logger repositories.
+ </value>
+ <remarks>
+ <para>
+ Gets the hashtable that is keyed on <see cref="T:log4net.Repository.ILoggerRepository"/>. The
+ values are hashtables keyed on <see cref="T:log4net.Core.ILogger"/> with the
+ value being the corresponding <see cref="T:log4net.Core.ILoggerWrapper"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.DateFormatter.AbsoluteTimeDateFormatter">
+ <summary>
+ Formats a <see cref="T:System.DateTime"/> as <c>"HH:mm:ss,fff"</c>.
+ </summary>
+ <remarks>
+ <para>
+ Formats a <see cref="T:System.DateTime"/> in the format <c>"HH:mm:ss,fff"</c> for example, <c>"15:49:37,459"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.DateFormatter.IDateFormatter">
+ <summary>
+ Render a <see cref="T:System.DateTime"/> as a string.
+ </summary>
+ <remarks>
+ <para>
+ Interface to abstract the rendering of a <see cref="T:System.DateTime"/>
+ instance into a string.
+ </para>
+ <para>
+ The <see cref="M:log4net.DateFormatter.IDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)"/> method is used to render the
+ date to a text writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.IDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Formats the specified date as a string.
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Format the <see cref="T:System.DateTime"/> as a string and write it
+ to the <see cref="T:System.IO.TextWriter"/> provided.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat">
+ <summary>
+ String constant used to specify AbsoluteTimeDateFormat in layouts. Current value is <b>ABSOLUTE</b>.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.DateAndTimeDateFormat">
+ <summary>
+ String constant used to specify DateTimeDateFormat in layouts. Current value is <b>DATE</b>.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.Iso8601TimeDateFormat">
+ <summary>
+ String constant used to specify ISO8601DateFormat in layouts. Current value is <b>ISO8601</b>.
+ </summary>
+ </member>
+ <member name="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Renders the date into a string. Format is <c>"HH:mm:ss"</c>.
+ </summary>
+ <param name="dateToFormat">The date to render into a string.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Subclasses should override this method to render the date
+ into a string using a precision up to the second. This method
+ will be called at most once per second and the result will be
+ reused if it is needed again during the same second.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Renders the date into a string. Format is "HH:mm:ss,fff".
+ </summary>
+ <param name="dateToFormat">The date to render into a string.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> method to generate the
+ time string up to the seconds and then appends the current
+ milliseconds. The results from <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> are
+ cached and <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> is called at most once
+ per second.
+ </para>
+ <para>
+ Sub classes should override <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/>
+ rather than <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeToTheSecond">
+ <summary>
+ Last stored time with precision up to the second.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeBuf">
+ <summary>
+ Last stored time with precision up to the second, formatted
+ as a string.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeString">
+ <summary>
+ Last stored time with precision up to the second, formatted
+ as a string.
+ </summary>
+ </member>
+ <member name="T:log4net.DateFormatter.DateTimeDateFormatter">
+ <summary>
+ Formats a <see cref="T:System.DateTime"/> as <c>"dd MMM yyyy HH:mm:ss,fff"</c>
+ </summary>
+ <remarks>
+ <para>
+ Formats a <see cref="T:System.DateTime"/> in the format
+ <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example,
+ <c>"06 Nov 1994 15:49:37,459"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Angelika Schnagl</author>
+ </member>
+ <member name="M:log4net.DateFormatter.DateTimeDateFormatter.#ctor">
+ <summary>
+ Default constructor.
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.DateTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Formats the date without the milliseconds part
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Formats a DateTime in the format <c>"dd MMM yyyy HH:mm:ss"</c>
+ for example, <c>"06 Nov 1994 15:49:37"</c>.
+ </para>
+ <para>
+ The base class will append the <c>",fff"</c> milliseconds section.
+ This method will only be called at most once per second.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.DateTimeDateFormatter.m_dateTimeFormatInfo">
+ <summary>
+ The format info for the invariant culture.
+ </summary>
+ </member>
+ <member name="T:log4net.DateFormatter.Iso8601DateFormatter">
+ <summary>
+ Formats the <see cref="T:System.DateTime"/> as <c>"yyyy-MM-dd HH:mm:ss,fff"</c>.
+ </summary>
+ <remarks>
+ <para>
+ Formats the <see cref="T:System.DateTime"/> specified as a string: <c>"yyyy-MM-dd HH:mm:ss,fff"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.Iso8601DateFormatter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.Iso8601DateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Formats the date without the milliseconds part
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Formats the date specified as a string: <c>"yyyy-MM-dd HH:mm:ss"</c>.
+ </para>
+ <para>
+ The base class will append the <c>",fff"</c> milliseconds section.
+ This method will only be called at most once per second.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.DateFormatter.SimpleDateFormatter">
+ <summary>
+ Formats the <see cref="T:System.DateTime"/> using the <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ Formats the <see cref="T:System.DateTime"/> using the <see cref="T:System.DateTime"/> <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.SimpleDateFormatter.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="format">The format string.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> class
+ with the specified format string.
+ </para>
+ <para>
+ The format string must be compatible with the options
+ that can be supplied to <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.SimpleDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Formats the date using <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </summary>
+ <param name="dateToFormat">The date to convert to a string.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Uses the date format string supplied to the constructor to call
+ the <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method to format the date.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.SimpleDateFormatter.m_formatString">
+ <summary>
+ The format string used to format the <see cref="T:System.DateTime"/>.
+ </summary>
+ <remarks>
+ <para>
+ The format string must be compatible with the options
+ that can be supplied to <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.DenyAllFilter">
+ <summary>
+ This filter drops all <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <remarks>
+ <para>
+ You can add this filter to the end of a filter chain to
+ switch from the default "accept all unless instructed otherwise"
+ filtering behavior to a "deny all unless instructed otherwise"
+ behavior.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.FilterSkeleton">
+ <summary>
+ Subclass this type to implement customized logging event filtering
+ </summary>
+ <remarks>
+ <para>
+ Users should extend this class to implement customized logging
+ event filtering. Note that <see cref="T:log4net.Repository.Hierarchy.Logger"/> and
+ <see cref="T:log4net.Appender.AppenderSkeleton"/>, the parent class of all standard
+ appenders, have built-in filtering rules. It is suggested that you
+ first use and understand the built-in rules before rushing to write
+ your own custom filters.
+ </para>
+ <para>
+ This abstract class assumes and also imposes that filters be
+ organized in a linear chain. The <see cref="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)"/>
+ method of each filter is called sequentially, in the order of their
+ addition to the chain.
+ </para>
+ <para>
+ The <see cref="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)"/> method must return one
+ of the integer constants <see cref="F:log4net.Filter.FilterDecision.Deny"/>,
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> or <see cref="F:log4net.Filter.FilterDecision.Accept"/>.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned, then the log event is dropped
+ immediately without consulting with the remaining filters.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned, then the next filter
+ in the chain is consulted. If there are no more filters in the
+ chain, then the log event is logged. Thus, in the presence of no
+ filters, the default behavior is to log all logging events.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, then the log
+ event is logged without consulting the remaining filters.
+ </para>
+ <para>
+ The philosophy of log4net filters is largely inspired from the
+ Linux ipchains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.IFilter">
+ <summary>
+ Implement this interface to provide customized logging event filtering
+ </summary>
+ <remarks>
+ <para>
+ Users should implement this interface to implement customized logging
+ event filtering. Note that <see cref="T:log4net.Repository.Hierarchy.Logger"/> and
+ <see cref="T:log4net.Appender.AppenderSkeleton"/>, the parent class of all standard
+ appenders, have built-in filtering rules. It is suggested that you
+ first use and understand the built-in rules before rushing to write
+ your own custom filters.
+ </para>
+ <para>
+ This abstract class assumes and also imposes that filters be
+ organized in a linear chain. The <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ method of each filter is called sequentially, in the order of their
+ addition to the chain.
+ </para>
+ <para>
+ The <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/> method must return one
+ of the integer constants <see cref="F:log4net.Filter.FilterDecision.Deny"/>,
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> or <see cref="F:log4net.Filter.FilterDecision.Accept"/>.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned, then the log event is dropped
+ immediately without consulting with the remaining filters.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned, then the next filter
+ in the chain is consulted. If there are no more filters in the
+ chain, then the log event is logged. Thus, in the presence of no
+ filters, the default behavior is to log all logging events.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, then the log
+ event is logged without consulting the remaining filters.
+ </para>
+ <para>
+ The philosophy of log4net filters is largely inspired from the
+ Linux ipchains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Decide if the logging event should be logged through an appender.
+ </summary>
+ <param name="loggingEvent">The LoggingEvent to decide upon</param>
+ <returns>The decision of the filter</returns>
+ <remarks>
+ <para>
+ If the decision is <see cref="F:log4net.Filter.FilterDecision.Deny"/>, then the event will be
+ dropped. If the decision is <see cref="F:log4net.Filter.FilterDecision.Neutral"/>, then the next
+ filter, if any, will be invoked. If the decision is <see cref="F:log4net.Filter.FilterDecision.Accept"/> then
+ the event will be logged without consulting with other filters in
+ the chain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.IFilter.Next">
+ <summary>
+ Property to get and set the next filter
+ </summary>
+ <value>
+ The next filter in the chain
+ </value>
+ <remarks>
+ <para>
+ Filters are typically composed into chains. This property allows the next filter in
+ the chain to be accessed.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.FilterSkeleton.m_next">
+ <summary>
+ Points to the next filter in the filter chain.
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Filter.FilterSkeleton.Next"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.FilterSkeleton.ActivateOptions">
+ <summary>
+ Initialize the filter with the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Typically filter's options become active immediately on set,
+ however this method must still be called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Decide if the <see cref="T:log4net.Core.LoggingEvent"/> should be logged through an appender.
+ </summary>
+ <param name="loggingEvent">The <see cref="T:log4net.Core.LoggingEvent"/> to decide upon</param>
+ <returns>The decision of the filter</returns>
+ <remarks>
+ <para>
+ If the decision is <see cref="F:log4net.Filter.FilterDecision.Deny"/>, then the event will be
+ dropped. If the decision is <see cref="F:log4net.Filter.FilterDecision.Neutral"/>, then the next
+ filter, if any, will be invoked. If the decision is <see cref="F:log4net.Filter.FilterDecision.Accept"/> then
+ the event will be logged without consulting with other filters in
+ the chain.
+ </para>
+ <para>
+ This method is marked <c>abstract</c> and must be implemented
+ in a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.FilterSkeleton.Next">
+ <summary>
+ Property to get and set the next filter
+ </summary>
+ <value>
+ The next filter in the chain
+ </value>
+ <remarks>
+ <para>
+ Filters are typically composed into chains. This property allows the next filter in
+ the chain to be accessed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.DenyAllFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.DenyAllFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Always returns the integer constant <see cref="F:log4net.Filter.FilterDecision.Deny"/>
+ </summary>
+ <param name="loggingEvent">the LoggingEvent to filter</param>
+ <returns>Always returns <see cref="F:log4net.Filter.FilterDecision.Deny"/></returns>
+ <remarks>
+ <para>
+ Ignores the event being logged and just returns
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/>. This can be used to change the default filter
+ chain behavior from <see cref="F:log4net.Filter.FilterDecision.Accept"/> to <see cref="F:log4net.Filter.FilterDecision.Deny"/>. This filter
+ should only be used as the last filter in the chain
+ as any further filters will be ignored!
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.FilterDecision">
+ <summary>
+ The return result from <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ </summary>
+ <remarks>
+ <para>
+ The return result from <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Deny">
+ <summary>
+ The log event must be dropped immediately without
+ consulting with the remaining filters, if any, in the chain.
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Neutral">
+ <summary>
+ This filter is neutral with respect to the log event.
+ The remaining filters, if any, should be consulted for a final decision.
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Accept">
+ <summary>
+ The log event must be logged immediately without
+ consulting with the remaining filters, if any, in the chain.
+ </summary>
+ </member>
+ <member name="T:log4net.Filter.LevelMatchFilter">
+ <summary>
+ This is a very simple filter based on <see cref="T:log4net.Core.Level"/> matching.
+ </summary>
+ <remarks>
+ <para>
+ The filter admits two options <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/> and
+ <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>. If there is an exact match between the value
+ of the <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/> option and the <see cref="T:log4net.Core.Level"/> of the
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the <see cref="M:log4net.Filter.LevelMatchFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in
+ case the <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/> option value is set
+ to <c>true</c>, if it is <c>false</c> then
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned. If the <see cref="T:log4net.Core.Level"/> does not match then
+ the result will be <see cref="F:log4net.Filter.FilterDecision.Neutral"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.LevelMatchFilter.m_acceptOnMatch">
+ <summary>
+ flag to indicate if the filter should <see cref="F:log4net.Filter.FilterDecision.Accept"/> on a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelMatchFilter.m_levelToMatch">
+ <summary>
+ the <see cref="T:log4net.Core.Level"/> to match against
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Tests if the <see cref="T:log4net.Core.Level"/> of the logging event matches that of the filter
+ </summary>
+ <param name="loggingEvent">the event to filter</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ If the <see cref="T:log4net.Core.Level"/> of the event matches the level of the
+ filter then the result of the function depends on the
+ value of <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>. If it is true then
+ the function will return <see cref="F:log4net.Filter.FilterDecision.Accept"/>, it it is false then it
+ will return <see cref="F:log4net.Filter.FilterDecision.Deny"/>. If the <see cref="T:log4net.Core.Level"/> does not match then
+ the result will be <see cref="F:log4net.Filter.FilterDecision.Neutral"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Deny"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelMatchFilter.LevelToMatch">
+ <summary>
+ The <see cref="T:log4net.Core.Level"/> that the filter will match
+ </summary>
+ <remarks>
+ <para>
+ The level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.LevelRangeFilter">
+ <summary>
+ This is a simple filter based on <see cref="T:log4net.Core.Level"/> matching.
+ </summary>
+ <remarks>
+ <para>
+ The filter admits three options <see cref="P:log4net.Filter.LevelRangeFilter.LevelMin"/> and <see cref="P:log4net.Filter.LevelRangeFilter.LevelMax"/>
+ that determine the range of priorities that are matched, and
+ <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>. If there is a match between the range
+ of priorities and the <see cref="T:log4net.Core.Level"/> of the <see cref="T:log4net.Core.LoggingEvent"/>, then the
+ <see cref="M:log4net.Filter.LevelRangeFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in case the <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>
+ option value is set to <c>true</c>, if it is <c>false</c>
+ then <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned. If there is no match, <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when matching a <see cref="T:log4net.Core.Level"/>
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_levelMin">
+ <summary>
+ the minimum <see cref="T:log4net.Core.Level"/> value to match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_levelMax">
+ <summary>
+ the maximum <see cref="T:log4net.Core.Level"/> value to match
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelRangeFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelRangeFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if the event should be logged.
+ </summary>
+ <param name="loggingEvent">the logging event to check</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ If the <see cref="T:log4net.Core.Level"/> of the logging event is outside the range
+ matched by this filter then <see cref="F:log4net.Filter.FilterDecision.Deny"/>
+ is returned. If the <see cref="T:log4net.Core.Level"/> is matched then the value of
+ <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/> is checked. If it is true then
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LevelRangeFilter.LevelMin"/> and <see cref="P:log4net.Filter.LevelRangeFilter.LevelMax"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Neutral"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.LevelMin">
+ <summary>
+ Set the minimum matched <see cref="T:log4net.Core.Level"/>
+ </summary>
+ <remarks>
+ <para>
+ The minimum level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.LevelMax">
+ <summary>
+ Sets the maximum matched <see cref="T:log4net.Core.Level"/>
+ </summary>
+ <remarks>
+ <para>
+ The maximum level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.LoggerMatchFilter">
+ <summary>
+ Simple filter to match a string in the event's logger name.
+ </summary>
+ <remarks>
+ <para>
+ The works very similar to the <see cref="T:log4net.Filter.LevelMatchFilter"/>. It admits two
+ options <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> and <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/>. If the
+ <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the <see cref="T:log4net.Core.LoggingEvent"/> starts
+ with the value of the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> option, then the
+ <see cref="M:log4net.Filter.LoggerMatchFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in
+ case the <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> option value is set to <c>true</c>,
+ if it is <c>false</c> then <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Filter.LoggerMatchFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when we have a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LoggerMatchFilter.m_loggerToMatch">
+ <summary>
+ The logger name string to substring match against the event
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LoggerMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LoggerMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The rendered message is matched against the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/>.
+ If the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> equals the beginning of
+ the incoming <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> (<see cref="M:System.String.StartsWith(System.String)"/>)
+ then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Deny"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch">
+ <summary>
+ The <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> that the filter will match
+ </summary>
+ <remarks>
+ <para>
+ This filter will attempt to match this value against logger name in
+ the following way. The match will be done against the beginning of the
+ logger name (using <see cref="M:System.String.StartsWith(System.String)"/>). The match is
+ case sensitive. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.MdcFilter">
+ <summary>
+ Simple filter to match a keyed string in the <see cref="T:log4net.MDC"/>
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a keyed string in the <see cref="T:log4net.MDC"/>
+ </para>
+ <para>
+ As the MDC has been replaced with layered properties the
+ <see cref="T:log4net.Filter.PropertyFilter"/> should be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.PropertyFilter">
+ <summary>
+ Simple filter to match a string an event property
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the value for a
+ specific event property
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Filter.StringMatchFilter">
+ <summary>
+ Simple filter to match a string in the rendered message
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the rendered message
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when we have a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_stringToMatch">
+ <summary>
+ The string to substring match against the message
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_stringRegexToMatch">
+ <summary>
+ A string regex to match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_regexToMatch">
+ <summary>
+ A regex object to match (generated from m_stringRegexToMatch)
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.ActivateOptions">
+ <summary>
+ Initialize and precompile the Regex if required
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The rendered message is matched against the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/>.
+ If the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> occurs as a substring within
+ the message then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Neutral"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.StringToMatch">
+ <summary>
+ Sets the static string to match
+ </summary>
+ <remarks>
+ <para>
+ The string that will be substring matched against
+ the rendered message. If the message contains this
+ string then the filter will match. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/>.
+ </para>
+ <para>
+ One of <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ must be specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.RegexToMatch">
+ <summary>
+ Sets the regular expression to match
+ </summary>
+ <remarks>
+ <para>
+ The regular expression pattern that will be matched against
+ the rendered message. If the message matches this
+ pattern then the filter will match. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/>.
+ </para>
+ <para>
+ One of <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ must be specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.PropertyFilter.m_key">
+ <summary>
+ The key to use to lookup the string from the event properties
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.PropertyFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.PropertyFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The event property for the <see cref="P:log4net.Filter.PropertyFilter.Key"/> is matched against
+ the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/>.
+ If the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> occurs as a substring within
+ the property value then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.PropertyFilter.Key">
+ <summary>
+ The key to lookup in the event properties and then match against.
+ </summary>
+ <remarks>
+ <para>
+ The key name to use to lookup in the properties map of the
+ <see cref="T:log4net.Core.LoggingEvent"/>. The match will be performed against
+ the value of this property if it exists.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.NdcFilter">
+ <summary>
+ Simple filter to match a string in the <see cref="T:log4net.NDC"/>
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the <see cref="T:log4net.NDC"/>
+ </para>
+ <para>
+ As the MDC has been replaced with named stacks stored in the
+ properties collections the <see cref="T:log4net.Filter.PropertyFilter"/> should
+ be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Filter.NdcFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Sets the <see cref="P:log4net.Filter.PropertyFilter.Key"/> to <c>"NDC"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.AppDomainPatternConverter">
+ <summary>
+ Write the event appdomain name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.Domain"/> to the output writer.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Layout.Pattern.PatternLayoutConverter">
+ <summary>
+ Abstract class that provides the formatting functionality that
+ derived classes need.
+ </summary>
+ <remarks>
+ Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting a logging event in a converter specific manner.
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Util.PatternConverter">
+ <summary>
+ Abstract class that provides the formatting functionality that
+ derived classes need.
+ </summary>
+ <remarks>
+ <para>
+ Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting a logging event in a converter specific manner.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.c_renderBufferSize">
+ <summary>
+ Initial buffer size
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.c_renderBufferMaxCapacity">
+ <summary>
+ Maximum buffer size before it is recycled
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.#ctor">
+ <summary>
+ Protected constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PatternConverter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Evaluate this pattern converter and write the output to a writer.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ <remarks>
+ <para>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the appropriate way.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.SetNext(log4net.Util.PatternConverter)">
+ <summary>
+ Set the next pattern converter in the chains
+ </summary>
+ <param name="patternConverter">the pattern converter that should follow this converter in the chain</param>
+ <returns>the next converter</returns>
+ <remarks>
+ <para>
+ The PatternConverter can merge with its neighbor during this method (or a sub class).
+ Therefore the return value may or may not be the value of the argument passed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.Format(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the pattern converter to the writer with appropriate formatting
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ <remarks>
+ <para>
+ This method calls <see cref="M:log4net.Util.PatternConverter.Convert(System.IO.TextWriter,System.Object)"/> to allow the subclass to perform
+ appropriate conversion of the pattern converter. If formatting options have
+ been specified via the <see cref="P:log4net.Util.PatternConverter.FormattingInfo"/> then this method will
+ apply those formattings before writing the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.SpacePad(System.IO.TextWriter,System.Int32)">
+ <summary>
+ Fast space padding method.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> to which the spaces will be appended.</param>
+ <param name="length">The number of spaces to be padded.</param>
+ <remarks>
+ <para>
+ Fast space padding method.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.m_option">
+ <summary>
+ The option string to the converter
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.WriteDictionary(System.IO.TextWriter,log4net.Repository.ILoggerRepository,System.Collections.IDictionary)">
+ <summary>
+ Write an dictionary to a <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="repository">a <see cref="T:log4net.Repository.ILoggerRepository"/> to use for object conversion</param>
+ <param name="value">the value to write to the writer</param>
+ <remarks>
+ <para>
+ Writes the <see cref="T:System.Collections.IDictionary"/> to a writer in the form:
+ </para>
+ <code>
+ {key1=value1, key2=value2, key3=value3}
+ </code>
+ <para>
+ If the <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ is not null then it is used to render the key and value to text, otherwise
+ the object's ToString method is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.WriteObject(System.IO.TextWriter,log4net.Repository.ILoggerRepository,System.Object)">
+ <summary>
+ Write an object to a <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="repository">a <see cref="T:log4net.Repository.ILoggerRepository"/> to use for object conversion</param>
+ <param name="value">the value to write to the writer</param>
+ <remarks>
+ <para>
+ Writes the Object to a writer. If the <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ is not null then it is used to render the object to text, otherwise
+ the object's ToString method is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.Next">
+ <summary>
+ Get the next pattern converter in the chain
+ </summary>
+ <value>
+ the next pattern converter in the chain
+ </value>
+ <remarks>
+ <para>
+ Get the next pattern converter in the chain
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.FormattingInfo">
+ <summary>
+ Gets or sets the formatting info for this converter
+ </summary>
+ <value>
+ The formatting info for this converter
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the formatting info for this converter
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.Option">
+ <summary>
+ Gets or sets the option value for this converter
+ </summary>
+ <summary>
+ The option for this converter
+ </summary>
+ <remarks>
+ <para>
+ Gets or sets the option value for this converter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Layout.Pattern.PatternLayoutConverter"/> class.
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the correct way.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">The <see cref="T:log4net.Core.LoggingEvent"/> on which the pattern converter should be executed.</param>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the correct way.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ </member>
+ <member name="F:log4net.Layout.Pattern.PatternLayoutConverter.m_ignoresException">
+ <summary>
+ Flag indicating if this converter handles exceptions
+ </summary>
+ <remarks>
+ <c>false</c> if this converter handles exceptions
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.Pattern.PatternLayoutConverter.IgnoresException">
+ <summary>
+ Flag indicating if this converter handles the logging event exception
+ </summary>
+ <value><c>false</c> if this converter handles the logging event exception</value>
+ <remarks>
+ <para>
+ If this converter handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then this property should be set to
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the property should be set to <c>true</c>.
+ </para>
+ <para>
+ Set this value to override a this default setting. The default
+ value is <c>true</c>, this converter does not handle the exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.AppDomainPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event appdomain name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.Domain"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.DatePatternConverter">
+ <summary>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the date of a <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <remarks>
+ <para>
+ Render the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the writer as a string.
+ </para>
+ <para>
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the formatting of the date. The following values are allowed:
+ <list type="definition">
+ <listheader>
+ <term>Option value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>ISO8601</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> formatter.
+ Formats using the <c>"yyyy-MM-dd HH:mm:ss,fff"</c> pattern.
+ </description>
+ </item>
+ <item>
+ <term>DATE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> formatter.
+ Formats using the <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example, <c>"06 Nov 1994 15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>ABSOLUTE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/> formatter.
+ Formats using the <c>"HH:mm:ss,yyyy"</c> for example, <c>"15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ Any other pattern string uses the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> formatter.
+ This formatter passes the pattern string to the <see cref="T:System.DateTime"/>
+ <see cref="M:System.DateTime.ToString(System.String)"/> method.
+ For details on valid patterns see
+ <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">DateTimeFormatInfo Class</a>.
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> is in the local time zone and is rendered in that zone.
+ To output the time in Universal time see <see cref="T:log4net.Layout.Pattern.UtcDatePatternConverter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Layout.Pattern.DatePatternConverter.m_dateFormatter">
+ <summary>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter pattern based on the <see cref="P:log4net.Util.PatternConverter.Option"/> property.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.DatePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern into the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Pass the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> passed is in the local time zone.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.ExceptionPatternConverter">
+ <summary>
+ Write the exception text to the output
+ </summary>
+ <remarks>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ </para>
+ <para>
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ExceptionPatternConverter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ExceptionPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the exception text to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ </para>
+ <para>
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.FileLocationPatternConverter">
+ <summary>
+ Writes the caller location file name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.FileName"/> for
+ the event to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.FileLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location file name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.FileName"/> for
+ the <paramref name="loggingEvent"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.FullLocationPatternConverter">
+ <summary>
+ Write the caller location info to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LocationInfo.FullInfo"/> to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.FullLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location info to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LocationInfo.FullInfo"/> to the output writer.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.IdentityPatternConverter">
+ <summary>
+ Writes the event identity to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LoggingEvent.Identity"/> to
+ the output writer.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.IdentityPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the event identity to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <paramref name="loggingEvent"/>
+ <see cref="P:log4net.Core.LoggingEvent.Identity"/> to
+ the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LevelPatternConverter">
+ <summary>
+ Write the event level to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the display name of the event <see cref="P:log4net.Core.LoggingEvent.Level"/>
+ to the writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LevelPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event level to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.Level.DisplayName"/> of the <paramref name="loggingEvent"/> <see cref="P:log4net.Core.LoggingEvent.Level"/>
+ to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LineLocationPatternConverter">
+ <summary>
+ Write the caller location line number to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.LineNumber"/> for
+ the event to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LineLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location line number to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.LineNumber"/> for
+ the <paramref name="loggingEvent"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LoggerPatternConverter">
+ <summary>
+ Converter for logger name
+ </summary>
+ <remarks>
+ <para>
+ Outputs the <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Layout.Pattern.NamedPatternConverter">
+ <summary>
+ Converter to output and truncate <c>'.'</c> separated strings
+ </summary>
+ <remarks>
+ <para>
+ This abstract class supports truncating a <c>'.'</c> separated string
+ to show a specified number of elements from the right hand side.
+ This is used to truncate class names that are fully qualified.
+ </para>
+ <para>
+ Subclasses should override the <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)"/> method to
+ return the fully qualified string.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Get the fully qualified string data
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>the fully qualified name</returns>
+ <remarks>
+ <para>
+ Overridden by subclasses to get the fully qualified name before the
+ precision is applied to it.
+ </para>
+ <para>
+ Return the fully qualified <c>'.'</c> (dot/period) separated string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern to the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ Render the <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)"/> to the precision
+ specified by the <see cref="P:log4net.Util.PatternConverter.Option"/> property.
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LoggerPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the fully qualified name of the logger
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>The fully qualified logger name</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the <paramref name="loggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.MessagePatternConverter">
+ <summary>
+ Writes the event message to the output
+ </summary>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)"/> method
+ to write out the event message.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.MessagePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the event message to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)"/> method
+ to write out the event message.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.MethodLocationPatternConverter">
+ <summary>
+ Write the method name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the caller location <see cref="P:log4net.Core.LocationInfo.MethodName"/> to
+ the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.MethodLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the method name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the caller location <see cref="P:log4net.Core.LocationInfo.MethodName"/> to
+ the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.NdcPatternConverter">
+ <summary>
+ Converter to include event NDC
+ </summary>
+ <remarks>
+ <para>
+ Outputs the value of the event property named <c>NDC</c>.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.Pattern.PropertyPatternConverter"/> should be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NdcPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event NDC to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ As the thread context stacks are now stored in named event properties
+ this converter simply looks up the value of the <c>NDC</c> property.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.Pattern.PropertyPatternConverter"/> should be used instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.PropertyPatternConverter">
+ <summary>
+ Property pattern converter
+ </summary>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PropertyPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the property value to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.RelativeTimePatternConverter">
+ <summary>
+ Converter to output the relative time of the event
+ </summary>
+ <remarks>
+ <para>
+ Converter to output the time of the event relative to the start of the program.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.RelativeTimePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the relative time to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes out the relative time of the event in milliseconds.
+ That is the number of milliseconds between the event <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>
+ and the <see cref="P:log4net.Core.LoggingEvent.StartTime"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.RelativeTimePatternConverter.TimeDifferenceInMillis(System.DateTime,System.DateTime)">
+ <summary>
+ Helper method to get the time difference between two DateTime objects
+ </summary>
+ <param name="start">start time (in the current local time zone)</param>
+ <param name="end">end time (in the current local time zone)</param>
+ <returns>the time difference in milliseconds</returns>
+ </member>
+ <member name="T:log4net.Layout.Pattern.ThreadPatternConverter">
+ <summary>
+ Converter to include event thread name
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.ThreadName"/> to the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ThreadPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the ThreadName to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.ThreadName"/> to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.TypeNamePatternConverter">
+ <summary>
+ Pattern converter for the class name
+ </summary>
+ <remarks>
+ <para>
+ Outputs the <see cref="P:log4net.Core.LocationInfo.ClassName"/> of the event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.TypeNamePatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the fully qualified name of the class
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>The fully qualified type name for the caller location</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="P:log4net.Core.LocationInfo.ClassName"/> of the <paramref name="loggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.UserNamePatternConverter">
+ <summary>
+ Converter to include event user name
+ </summary>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.UserNamePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern to the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ </member>
+ <member name="T:log4net.Layout.Pattern.UtcDatePatternConverter">
+ <summary>
+ Write the TimeStamp to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the date of a <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ <para>
+ Uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>
+ in Universal time.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Layout.Pattern.DatePatternConverter"/> for details on the date pattern syntax.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Layout.Pattern.DatePatternConverter"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.UtcDatePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the TimeStamp to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Pass the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> passed is in the local time zone, this is converted
+ to Universal time before it is rendered.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Layout.Pattern.DatePatternConverter"/>
+ </member>
+ <member name="T:log4net.Layout.ExceptionLayout">
+ <summary>
+ A Layout that renders only the Exception text from the logging event
+ </summary>
+ <remarks>
+ <para>
+ A Layout that renders only the Exception text from the logging event.
+ </para>
+ <para>
+ This Layout should only be used with appenders that utilize multiple
+ layouts (e.g. <see cref="T:log4net.Appender.AdoNetAppender"/>).
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.LayoutSkeleton">
+ <summary>
+ Extend this abstract class to create your own log layout format.
+ </summary>
+ <remarks>
+ <para>
+ This is the base implementation of the <see cref="T:log4net.Layout.ILayout"/>
+ interface. Most layout objects should extend this class.
+ </para>
+ </remarks>
+ <remarks>
+ <note type="inheritinfo">
+ <para>
+ Subclasses must implement the <see cref="M:log4net.Layout.LayoutSkeleton.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/>
+ method.
+ </para>
+ <para>
+ Subclasses should set the <see cref="P:log4net.Layout.LayoutSkeleton.IgnoresException"/> in their default
+ constructor.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.ILayout">
+ <summary>
+ Interface implemented by layout objects
+ </summary>
+ <remarks>
+ <para>
+ An <see cref="T:log4net.Layout.ILayout"/> object is used to format a <see cref="T:log4net.Core.LoggingEvent"/>
+ as text. The <see cref="M:log4net.Layout.ILayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/> method is called by an
+ appender to transform the <see cref="T:log4net.Core.LoggingEvent"/> into a string.
+ </para>
+ <para>
+ The layout can also supply <see cref="P:log4net.Layout.ILayout.Header"/> and <see cref="P:log4net.Layout.ILayout.Footer"/>
+ text that is appender before any events and after all the events respectively.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.ILayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">The event to format</param>
+ <remarks>
+ <para>
+ This method is called by an appender to format
+ the <paramref name="loggingEvent"/> as text and output to a writer.
+ </para>
+ <para>
+ If the caller does not have a <see cref="T:System.IO.TextWriter"/> and prefers the
+ event to be formatted as a <see cref="T:System.String"/> then the following
+ code can be used to format the event into a <see cref="T:System.IO.StringWriter"/>.
+ </para>
+ <code lang="C#">
+ StringWriter writer = new StringWriter();
+ Layout.Format(writer, loggingEvent);
+ string formattedEvent = writer.ToString();
+ </code>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.ContentType">
+ <summary>
+ The content type output by this layout.
+ </summary>
+ <value>The content type</value>
+ <remarks>
+ <para>
+ The content type output by this layout.
+ </para>
+ <para>
+ This is a MIME type e.g. <c>"text/plain"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.Header">
+ <summary>
+ The header for the layout format.
+ </summary>
+ <value>the layout header</value>
+ <remarks>
+ <para>
+ The Header text will be appended before any logging events
+ are formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.Footer">
+ <summary>
+ The footer for the layout format.
+ </summary>
+ <value>the layout footer</value>
+ <remarks>
+ <para>
+ The Footer text will be appended after all the logging events
+ have been formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.IgnoresException">
+ <summary>
+ Flag indicating if this layout handle exceptions
+ </summary>
+ <value><c>false</c> if this layout handles exceptions</value>
+ <remarks>
+ <para>
+ If this layout handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the layout should return
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the layout should return <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_header">
+ <summary>
+ The header text
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Layout.LayoutSkeleton.Header"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_footer">
+ <summary>
+ The footer text
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Layout.LayoutSkeleton.Footer"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_ignoresException">
+ <summary>
+ Flag indicating if this layout handles exceptions
+ </summary>
+ <remarks>
+ <para>
+ <c>false</c> if this layout handles exceptions
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.#ctor">
+ <summary>
+ Empty default constructor
+ </summary>
+ <remarks>
+ <para>
+ Empty default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.ActivateOptions">
+ <summary>
+ Activate component options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ This method must be implemented by the subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">The event to format</param>
+ <remarks>
+ <para>
+ This method is called by an appender to format
+ the <paramref name="loggingEvent"/> as text.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.ContentType">
+ <summary>
+ The content type output by this layout.
+ </summary>
+ <value>The content type is <c>"text/plain"</c></value>
+ <remarks>
+ <para>
+ The content type output by this layout.
+ </para>
+ <para>
+ This base class uses the value <c>"text/plain"</c>.
+ To change this value a subclass must override this
+ property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.Header">
+ <summary>
+ The header for the layout format.
+ </summary>
+ <value>the layout header</value>
+ <remarks>
+ <para>
+ The Header text will be appended before any logging events
+ are formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.Footer">
+ <summary>
+ The footer for the layout format.
+ </summary>
+ <value>the layout footer</value>
+ <remarks>
+ <para>
+ The Footer text will be appended after all the logging events
+ have been formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.IgnoresException">
+ <summary>
+ Flag indicating if this layout handles exceptions
+ </summary>
+ <value><c>false</c> if this layout handles exceptions</value>
+ <remarks>
+ <para>
+ If this layout handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the layout should return
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the layout should return <c>true</c>.
+ </para>
+ <para>
+ Set this value to override a this default setting. The default
+ value is <c>true</c>, this layout does not handle the exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Constructs a ExceptionLayout
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.ActivateOptions">
+ <summary>
+ Activate component options
+ </summary>
+ <remarks>
+ <para>
+ Part of the <see cref="T:log4net.Core.IOptionHandler"/> component activation
+ framework.
+ </para>
+ <para>
+ This method does nothing as options become effective immediately.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the exception text from the logging event
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Write the exception string to the <see cref="T:System.IO.TextWriter"/>.
+ The exception string is retrieved from <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.IRawLayout">
+ <summary>
+ Interface for raw layout objects
+ </summary>
+ <remarks>
+ <para>
+ Interface used to format a <see cref="T:log4net.Core.LoggingEvent"/>
+ to an object.
+ </para>
+ <para>
+ This interface should not be confused with the
+ <see cref="T:log4net.Layout.ILayout"/> interface. This interface is used in
+ only certain specialized situations where a raw object is
+ required rather than a formatted string. The <see cref="T:log4net.Layout.ILayout"/>
+ is not generally useful than this interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.IRawLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the formatted event</returns>
+ <remarks>
+ <para>
+ Implement this method to create your own layout format.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Layout2RawLayoutAdapter">
+ <summary>
+ Adapts any <see cref="T:log4net.Layout.ILayout"/> to a <see cref="T:log4net.Layout.IRawLayout"/>
+ </summary>
+ <remarks>
+ <para>
+ Where an <see cref="T:log4net.Layout.IRawLayout"/> is required this adapter
+ allows a <see cref="T:log4net.Layout.ILayout"/> to be specified.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Layout.Layout2RawLayoutAdapter.m_layout">
+ <summary>
+ The layout to adapt
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Layout2RawLayoutAdapter.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Construct a new adapter
+ </summary>
+ <param name="layout">the layout to adapt</param>
+ <remarks>
+ <para>
+ Create the adapter for the specified <paramref name="layout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Layout2RawLayoutAdapter.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Format the logging event as an object.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the formatted event</returns>
+ <remarks>
+ <para>
+ Format the logging event as an object.
+ </para>
+ <para>
+ Uses the <see cref="T:log4net.Layout.ILayout"/> object supplied to
+ the constructor to perform the formatting.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.PatternLayout">
+ <summary>
+ A flexible layout configurable with pattern string.
+ </summary>
+ <remarks>
+ <para>
+ The goal of this class is to <see cref="M:log4net.Layout.PatternLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/> a
+ <see cref="T:log4net.Core.LoggingEvent"/> as a string. The results
+ depend on the <i>conversion pattern</i>.
+ </para>
+ <para>
+ The conversion pattern is closely related to the conversion
+ pattern of the printf function in C. A conversion pattern is
+ composed of literal text and format control expressions called
+ <i>conversion specifiers</i>.
+ </para>
+ <para>
+ <i>You are free to insert any literal text within the conversion
+ pattern.</i>
+ </para>
+ <para>
+ Each conversion specifier starts with a percent sign (%) and is
+ followed by optional <i>format modifiers</i> and a <i>conversion
+ pattern name</i>. The conversion pattern name specifies the type of
+ data, e.g. logger, level, date, thread name. The format
+ modifiers control such things as field width, padding, left and
+ right justification. The following is a simple example.
+ </para>
+ <para>
+ Let the conversion pattern be <b>"%-5level [%thread]: %message%newline"</b> and assume
+ that the log4net environment was set to use a PatternLayout. Then the
+ statements
+ </para>
+ <code lang="C#">
+ ILog log = LogManager.GetLogger(typeof(TestApp));
+ log.Debug("Message 1");
+ log.Warn("Message 2");
+ </code>
+ <para>would yield the output</para>
+ <code>
+ DEBUG [main]: Message 1
+ WARN [main]: Message 2
+ </code>
+ <para>
+ Note that there is no explicit separator between text and
+ conversion specifiers. The pattern parser knows when it has reached
+ the end of a conversion specifier when it reads a conversion
+ character. In the example above the conversion specifier
+ <b>%-5level</b> means the level of the logging event should be left
+ justified to a width of five characters.
+ </para>
+ <para>
+ The recognized conversion pattern names are:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Conversion Pattern Name</term>
+ <description>Effect</description>
+ </listheader>
+ <item>
+ <term>a</term>
+ <description>Equivalent to <b>appdomain</b></description>
+ </item>
+ <item>
+ <term>appdomain</term>
+ <description>
+ Used to output the friendly name of the AppDomain where the
+ logging event was generated.
+ </description>
+ </item>
+ <item>
+ <term>c</term>
+ <description>Equivalent to <b>logger</b></description>
+ </item>
+ <item>
+ <term>C</term>
+ <description>Equivalent to <b>type</b></description>
+ </item>
+ <item>
+ <term>class</term>
+ <description>Equivalent to <b>type</b></description>
+ </item>
+ <item>
+ <term>d</term>
+ <description>Equivalent to <b>date</b></description>
+ </item>
+ <item>
+ <term>date</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in the local time zone.
+ To output the date in universal time use the <c>%utcdate</c> pattern.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
+ <b>%date{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>exception</term>
+ <description>
+ <para>
+ Used to output the exception passed in with the log message.
+ </para>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>F</term>
+ <description>Equivalent to <b>file</b></description>
+ </item>
+ <item>
+ <term>file</term>
+ <description>
+ <para>
+ Used to output the file name where the logging request was
+ issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>identity</term>
+ <description>
+ <para>
+ Used to output the user name for the currently active user
+ (Principal.Identity.Name).
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>l</term>
+ <description>Equivalent to <b>location</b></description>
+ </item>
+ <item>
+ <term>L</term>
+ <description>Equivalent to <b>line</b></description>
+ </item>
+ <item>
+ <term>location</term>
+ <description>
+ <para>
+ Used to output location information of the caller which generated
+ the logging event.
+ </para>
+ <para>
+ The location information depends on the CLI implementation but
+ usually consists of the fully qualified name of the calling
+ method followed by the callers source the file name and line
+ number between parentheses.
+ </para>
+ <para>
+ The location information can be very useful. However, its
+ generation is <b>extremely</b> slow. Its use should be avoided
+ unless execution speed is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>level</term>
+ <description>
+ <para>
+ Used to output the level of the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>line</term>
+ <description>
+ <para>
+ Used to output the line number from where the logging request
+ was issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>logger</term>
+ <description>
+ <para>
+ Used to output the logger of the logging event. The
+ logger conversion specifier can be optionally followed by
+ <i>precision specifier</i>, that is a decimal constant in
+ brackets.
+ </para>
+ <para>
+ If a precision specifier is given, then only the corresponding
+ number of right most components of the logger name will be
+ printed. By default the logger name is printed in full.
+ </para>
+ <para>
+ For example, for the logger name "a.b.c" the pattern
+ <b>%logger{2}</b> will output "b.c".
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>m</term>
+ <description>Equivalent to <b>message</b></description>
+ </item>
+ <item>
+ <term>M</term>
+ <description>Equivalent to <b>method</b></description>
+ </item>
+ <item>
+ <term>message</term>
+ <description>
+ <para>
+ Used to output the application supplied message associated with
+ the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>mdc</term>
+ <description>
+ <para>
+ The MDC (old name for the ThreadContext.Properties) is now part of the
+ combined event properties. This pattern is supported for compatibility
+ but is equivalent to <b>property</b>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>method</term>
+ <description>
+ <para>
+ Used to output the method name where the logging request was
+ issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>n</term>
+ <description>Equivalent to <b>newline</b></description>
+ </item>
+ <item>
+ <term>newline</term>
+ <description>
+ <para>
+ Outputs the platform dependent line separator character or
+ characters.
+ </para>
+ <para>
+ This conversion pattern offers the same performance as using
+ non-portable line separator strings such as "\n", or "\r\n".
+ Thus, it is the preferred way of specifying a line separator.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>ndc</term>
+ <description>
+ <para>
+ Used to output the NDC (nested diagnostic context) associated
+ with the thread that generated the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>p</term>
+ <description>Equivalent to <b>level</b></description>
+ </item>
+ <item>
+ <term>P</term>
+ <description>Equivalent to <b>property</b></description>
+ </item>
+ <item>
+ <term>properties</term>
+ <description>Equivalent to <b>property</b></description>
+ </item>
+ <item>
+ <term>property</term>
+ <description>
+ <para>
+ Used to output the an event specific property. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%property{user}</b> would include the value
+ from the property that is keyed by the string 'user'. Each property value
+ that is to be included in the log must be specified separately.
+ Properties are added to events by loggers or appenders. By default
+ the <c>log4net:HostName</c> property is set to the name of machine on
+ which the event was originally logged.
+ </para>
+ <para>
+ If no key is specified, e.g. <b>%property</b> then all the keys and their
+ values are printed in a comma separated list.
+ </para>
+ <para>
+ The properties of an event are combined from a number of different
+ contexts. These are listed below in the order in which they are searched.
+ </para>
+ <list type="definition">
+ <item>
+ <term>the event properties</term>
+ <description>
+ The event has <see cref="P:log4net.Core.LoggingEvent.Properties"/> that can be set. These
+ properties are specific to this event only.
+ </description>
+ </item>
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+
+ </description>
+ </item>
+ <item>
+ <term>r</term>
+ <description>Equivalent to <b>timestamp</b></description>
+ </item>
+ <item>
+ <term>t</term>
+ <description>Equivalent to <b>thread</b></description>
+ </item>
+ <item>
+ <term>timestamp</term>
+ <description>
+ <para>
+ Used to output the number of milliseconds elapsed since the start
+ of the application until the creation of the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>thread</term>
+ <description>
+ <para>
+ Used to output the name of the thread that generated the
+ logging event. Uses the thread number if no name is available.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>type</term>
+ <description>
+ <para>
+ Used to output the fully qualified type name of the caller
+ issuing the logging request. This conversion specifier
+ can be optionally followed by <i>precision specifier</i>, that
+ is a decimal constant in brackets.
+ </para>
+ <para>
+ If a precision specifier is given, then only the corresponding
+ number of right most components of the class name will be
+ printed. By default the class name is output in fully qualified form.
+ </para>
+ <para>
+ For example, for the class name "log4net.Layout.PatternLayout", the
+ pattern <b>%type{1}</b> will output "PatternLayout".
+ </para>
+ <para>
+ <b>WARNING</b> Generating the caller class information is
+ slow. Thus, its use should be avoided unless execution speed is
+ not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>u</term>
+ <description>Equivalent to <b>identity</b></description>
+ </item>
+ <item>
+ <term>username</term>
+ <description>
+ <para>
+ Used to output the WindowsIdentity for the currently
+ active user.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller WindowsIdentity information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>utcdate</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in universal time.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
+ <b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>w</term>
+ <description>Equivalent to <b>username</b></description>
+ </item>
+ <item>
+ <term>x</term>
+ <description>Equivalent to <b>ndc</b></description>
+ </item>
+ <item>
+ <term>X</term>
+ <description>Equivalent to <b>mdc</b></description>
+ </item>
+ <item>
+ <term>%</term>
+ <description>
+ <para>
+ The sequence %% outputs a single percent sign.
+ </para>
+ </description>
+ </item>
+ </list>
+ <para>
+ The single letter patterns are deprecated in favor of the
+ longer more descriptive pattern names.
+ </para>
+ <para>
+ By default the relevant information is output as is. However,
+ with the aid of format modifiers it is possible to change the
+ minimum field width, the maximum field width and justification.
+ </para>
+ <para>
+ The optional format modifier is placed between the percent sign
+ and the conversion pattern name.
+ </para>
+ <para>
+ The first optional format modifier is the <i>left justification
+ flag</i> which is just the minus (-) character. Then comes the
+ optional <i>minimum field width</i> modifier. This is a decimal
+ constant that represents the minimum number of characters to
+ output. If the data item requires fewer characters, it is padded on
+ either the left or the right until the minimum width is
+ reached. The default is to pad on the left (right justify) but you
+ can specify right padding with the left justification flag. The
+ padding character is space. If the data item is larger than the
+ minimum field width, the field is expanded to accommodate the
+ data. The value is never truncated.
+ </para>
+ <para>
+ This behavior can be changed using the <i>maximum field
+ width</i> modifier which is designated by a period followed by a
+ decimal constant. If the data item is longer than the maximum
+ field, then the extra characters are removed from the
+ <i>beginning</i> of the data item and not from the end. For
+ example, it the maximum field width is eight and the data item is
+ ten characters long, then the first two characters of the data item
+ are dropped. This behavior deviates from the printf function in C
+ where truncation is done from the end.
+ </para>
+ <para>
+ Below are various format modifier examples for the logger
+ conversion specifier.
+ </para>
+ <div class="tablediv">
+ <table class="dtTABLE" cellspacing="0">
+ <tr>
+ <th>Format modifier</th>
+ <th>left justify</th>
+ <th>minimum width</th>
+ <th>maximum width</th>
+ <th>comment</th>
+ </tr>
+ <tr>
+ <td align="center">%20logger</td>
+ <td align="center">false</td>
+ <td align="center">20</td>
+ <td align="center">none</td>
+ <td>
+ <para>
+ Left pad with spaces if the logger name is less than 20
+ characters long.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%-20logger</td>
+ <td align="center">true</td>
+ <td align="center">20</td>
+ <td align="center">none</td>
+ <td>
+ <para>
+ Right pad with spaces if the logger
+ name is less than 20 characters long.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%.30logger</td>
+ <td align="center">NA</td>
+ <td align="center">none</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Truncate from the beginning if the logger
+ name is longer than 30 characters.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center"><nobr>%20.30logger</nobr></td>
+ <td align="center">false</td>
+ <td align="center">20</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Left pad with spaces if the logger name is shorter than 20
+ characters. However, if logger name is longer than 30 characters,
+ then truncate from the beginning.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%-20.30logger</td>
+ <td align="center">true</td>
+ <td align="center">20</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Right pad with spaces if the logger name is shorter than 20
+ characters. However, if logger name is longer than 30 characters,
+ then truncate from the beginning.
+ </para>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <para>
+ <b>Note about caller location information.</b><br/>
+ The following patterns <c>%type %file %line %method %location %class %C %F %L %l %M</c>
+ all generate caller location information.
+ Location information uses the <c>System.Diagnostics.StackTrace</c> class to generate
+ a call stack. The caller's information is then extracted from this stack.
+ </para>
+ <note type="caution">
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class is not supported on the
+ .NET Compact Framework 1.0 therefore caller location information is not
+ available on that framework.
+ </para>
+ </note>
+ <note type="caution">
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
+ </para>
+ <para>
+ "StackTrace information will be most informative with Debug build configurations.
+ By default, Debug builds include debug symbols, while Release builds do not. The
+ debug symbols contain most of the file, method name, line number, and column
+ information used in constructing StackFrame and StackTrace objects. StackTrace
+ might not report as many method calls as expected, due to code transformations
+ that occur during optimization."
+ </para>
+ <para>
+ This means that in a Release build the caller information may be incomplete or may
+ not exist at all! Therefore caller location information cannot be relied upon in a Release build.
+ </para>
+ </note>
+ <para>
+ Additional pattern converters may be registered with a specific <see cref="T:log4net.Layout.PatternLayout"/>
+ instance using the <see cref="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ <example>
+ This is a more detailed pattern.
+ <code><b>%timestamp [%thread] %level %logger %ndc - %message%newline</b></code>
+ </example>
+ <example>
+ A similar pattern except that the relative time is
+ right padded if less than 6 digits, thread name is right padded if
+ less than 15 characters and truncated if longer and the logger
+ name is left padded if shorter than 30 characters and truncated if
+ longer.
+ <code><b>%-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline</b></code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.DefaultConversionPattern">
+ <summary>
+ Default pattern string for log output.
+ </summary>
+ <remarks>
+ <para>
+ Default pattern string for log output.
+ Currently set to the string <b>"%message%newline"</b>
+ which just prints the application supplied message.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.DetailConversionPattern">
+ <summary>
+ A detailed conversion pattern
+ </summary>
+ <remarks>
+ <para>
+ A conversion pattern which includes Time, Thread, Logger, and Nested Context.
+ Current value is <b>%timestamp [%thread] %level %logger %ndc - %message%newline</b>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.s_globalRulesRegistry">
+ <summary>
+ Internal map of converter identifiers to converter types.
+ </summary>
+ <remarks>
+ <para>
+ This static map is overridden by the m_converterRegistry instance map
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_pattern">
+ <summary>
+ the pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_head">
+ <summary>
+ the head of the pattern converter chain
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_instanceRulesRegistry">
+ <summary>
+ patterns defined on this PatternLayout only
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#cctor">
+ <summary>
+ Initialize the global registry
+ </summary>
+ <remarks>
+ <para>
+ Defines the builtin global rules.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#ctor">
+ <summary>
+ Constructs a PatternLayout using the DefaultConversionPattern
+ </summary>
+ <remarks>
+ <para>
+ The default pattern just produces the application supplied message.
+ </para>
+ <para>
+ Note to Inheritors: This constructor calls the virtual method
+ <see cref="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)"/>. If you override this method be
+ aware that it will be called before your is called constructor.
+ </para>
+ <para>
+ As per the <see cref="T:log4net.Core.IOptionHandler"/> contract the <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/>
+ method must be called after the properties on this object have been
+ configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#ctor(System.String)">
+ <summary>
+ Constructs a PatternLayout using the supplied conversion pattern
+ </summary>
+ <param name="pattern">the pattern to use</param>
+ <remarks>
+ <para>
+ Note to Inheritors: This constructor calls the virtual method
+ <see cref="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)"/>. If you override this method be
+ aware that it will be called before your is called constructor.
+ </para>
+ <para>
+ When using this constructor the <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> method
+ need not be called. This may not be the case when using a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)">
+ <summary>
+ Create the pattern parser instance
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <returns>The <see cref="T:log4net.Util.PatternParser"/> that will format the event</returns>
+ <remarks>
+ <para>
+ Creates the <see cref="T:log4net.Util.PatternParser"/> used to parse the conversion string. Sets the
+ global and instance rules on the <see cref="T:log4net.Util.PatternParser"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a formatted string as specified by the conversion pattern.
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Parse the <see cref="T:log4net.Core.LoggingEvent"/> using the patter format
+ specified in the <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.AddConverter(log4net.Layout.PatternLayout.ConverterInfo)">
+ <summary>
+ Add a converter to this PatternLayout
+ </summary>
+ <param name="converterInfo">the converter info</param>
+ <remarks>
+ <para>
+ This version of the method is used by the configurator.
+ Programmatic users should use the alternative <see cref="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)">
+ <summary>
+ Add a converter to this PatternLayout
+ </summary>
+ <param name="name">the name of the conversion pattern for this converter</param>
+ <param name="type">the type of the converter</param>
+ <remarks>
+ <para>
+ Add a named pattern converter to this instance. This
+ converter will be used in the formatting of the event.
+ This method must be called before <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/>.
+ </para>
+ <para>
+ The <paramref name="type"/> specified must extend the
+ <see cref="T:log4net.Util.PatternConverter"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConversionPattern">
+ <summary>
+ The pattern formatting string
+ </summary>
+ <remarks>
+ <para>
+ The <b>ConversionPattern</b> option. This is the string which
+ controls formatting and consists of a mix of literal content and
+ conversion specifiers.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.PatternLayout.ConverterInfo">
+ <summary>
+ Wrapper class used to map converter names to converter types
+ </summary>
+ <remarks>
+ <para>
+ Pattern converter info class used during configuration to
+ pass to the <see cref="M:log4net.Layout.PatternLayout.AddConverter(log4net.Layout.PatternLayout.ConverterInfo)"/>
+ method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.ConverterInfo.#ctor">
+ <summary>
+ default constructor
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConverterInfo.Name">
+ <summary>
+ Gets or sets the name of the conversion pattern
+ </summary>
+ <remarks>
+ <para>
+ The name of the pattern in the format string
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConverterInfo.Type">
+ <summary>
+ Gets or sets the type of the converter
+ </summary>
+ <remarks>
+ <para>
+ The value specified must extend the
+ <see cref="T:log4net.Util.PatternConverter"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawLayoutConverter">
+ <summary>
+ Type converter for the <see cref="T:log4net.Layout.IRawLayout"/> interface
+ </summary>
+ <remarks>
+ <para>
+ Used to convert objects to the <see cref="T:log4net.Layout.IRawLayout"/> interface.
+ Supports converting from the <see cref="T:log4net.Layout.ILayout"/> interface to
+ the <see cref="T:log4net.Layout.IRawLayout"/> interface using the <see cref="T:log4net.Layout.Layout2RawLayoutAdapter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IConvertFrom">
+ <summary>
+ Interface supported by type converters
+ </summary>
+ <remarks>
+ <para>
+ This interface supports conversion from arbitrary types
+ to a single target type. See <see cref="T:log4net.Util.TypeConverters.TypeConverterAttribute"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertFrom.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Test if the <paramref name="sourceType"/> can be converted to the
+ type supported by this converter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertFrom.ConvertFrom(System.Object)">
+ <summary>
+ Convert the source object to the type supported by this object
+ </summary>
+ <param name="source">the object to convert</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Converts the <paramref name="source"/> to the type supported
+ by this converter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.RawLayoutConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the sourceType be converted to an <see cref="T:log4net.Layout.IRawLayout"/>
+ </summary>
+ <param name="sourceType">the source to be to be converted</param>
+ <returns><c>true</c> if the source type can be converted to <see cref="T:log4net.Layout.IRawLayout"/></returns>
+ <remarks>
+ <para>
+ Test if the <paramref name="sourceType"/> can be converted to a
+ <see cref="T:log4net.Layout.IRawLayout"/>. Only <see cref="T:log4net.Layout.ILayout"/> is supported
+ as the <paramref name="sourceType"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.RawLayoutConverter.ConvertFrom(System.Object)">
+ <summary>
+ Convert the value to a <see cref="T:log4net.Layout.IRawLayout"/> object
+ </summary>
+ <param name="source">the value to convert</param>
+ <returns>the <see cref="T:log4net.Layout.IRawLayout"/> object</returns>
+ <remarks>
+ <para>
+ Convert the <paramref name="source"/> object to a
+ <see cref="T:log4net.Layout.IRawLayout"/> object. If the <paramref name="source"/> object
+ is a <see cref="T:log4net.Layout.ILayout"/> then the <see cref="T:log4net.Layout.Layout2RawLayoutAdapter"/>
+ is used to adapt between the two interfaces, otherwise an
+ exception is thrown.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawPropertyLayout">
+ <summary>
+ Extract the value of a property from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the value of a property from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.RawPropertyLayout.#ctor">
+ <summary>
+ Constructs a RawPropertyLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawPropertyLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Lookup the property for <see cref="P:log4net.Layout.RawPropertyLayout.Key"/>
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns property value</returns>
+ <remarks>
+ <para>
+ Looks up and returns the object value of the property
+ named <see cref="P:log4net.Layout.RawPropertyLayout.Key"/>. If there is no property defined
+ with than name then <c>null</c> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.RawPropertyLayout.Key">
+ <summary>
+ The name of the value to lookup in the LoggingEvent Properties collection.
+ </summary>
+ <value>
+ Value to lookup in the LoggingEvent Properties collection
+ </value>
+ <remarks>
+ <para>
+ String name of the property to lookup in the <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawTimeStampLayout">
+ <summary>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.RawTimeStampLayout.#ctor">
+ <summary>
+ Constructs a RawTimeStampLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawTimeStampLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the time stamp</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </para>
+ <para>
+ The time stamp is in local time. To format the time stamp
+ in universal time use <see cref="T:log4net.Layout.RawUtcTimeStampLayout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawUtcTimeStampLayout">
+ <summary>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.RawUtcTimeStampLayout.#ctor">
+ <summary>
+ Constructs a RawUtcTimeStampLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawUtcTimeStampLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the time stamp</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </para>
+ <para>
+ The time stamp is in universal time. To format the time stamp
+ in local time use <see cref="T:log4net.Layout.RawTimeStampLayout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.SimpleLayout">
+ <summary>
+ A very simple layout
+ </summary>
+ <remarks>
+ <para>
+ SimpleLayout consists of the level of the log statement,
+ followed by " - " and then the log message itself. For example,
+ <code>
+ DEBUG - Hello world
+ </code>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.#ctor">
+ <summary>
+ Constructs a SimpleLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a simple formatted output.
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Formats the event as the level of the even,
+ followed by " - " and then the log message itself. The
+ output is terminated by a newline.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.XmlLayout">
+ <summary>
+ Layout that formats the log events as XML elements.
+ </summary>
+ <remarks>
+ <para>
+ The output of the <see cref="T:log4net.Layout.XmlLayout"/> consists of a series of
+ log4net:event elements. It does not output a complete well-formed XML
+ file. The output is designed to be included as an <em>external entity</em>
+ in a separate file to form a correct XML file.
+ </para>
+ <para>
+ For example, if <c>abc</c> is the name of the file where
+ the <see cref="T:log4net.Layout.XmlLayout"/> output goes, then a well-formed XML file would
+ be:
+ </para>
+ <code lang="XML">
+ &lt;?xml version="1.0" ?&gt;
+
+ &lt;!DOCTYPE log4net:events SYSTEM "log4net-events.dtd" [&lt;!ENTITY data SYSTEM "abc"&gt;]&gt;
+
+ &lt;log4net:events version="1.2" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2&gt;
+ &amp;data;
+ &lt;/log4net:events&gt;
+ </code>
+ <para>
+ This approach enforces the independence of the <see cref="T:log4net.Layout.XmlLayout"/>
+ and the appender where it is embedded.
+ </para>
+ <para>
+ The <c>version</c> attribute helps components to correctly
+ interpret output generated by <see cref="T:log4net.Layout.XmlLayout"/>. The value of
+ this attribute should be "1.2" for release 1.2 and later.
+ </para>
+ <para>
+ Alternatively the <c>Header</c> and <c>Footer</c> properties can be
+ configured to output the correct XML header, open tag and close tag.
+ When setting the <c>Header</c> and <c>Footer</c> properties it is essential
+ that the underlying data store not be appendable otherwise the data
+ will become invalid XML.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.XmlLayoutBase">
+ <summary>
+ Layout that formats the log events as XML elements.
+ </summary>
+ <remarks>
+ <para>
+ This is an abstract class that must be subclassed by an implementation
+ to conform to a specific schema.
+ </para>
+ <para>
+ Deriving classes must implement the <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.#ctor">
+ <summary>
+ Protected constructor to support subclasses
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Layout.XmlLayoutBase"/> class
+ with no location info.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.#ctor(System.Boolean)">
+ <summary>
+ Protected constructor to support subclasses
+ </summary>
+ <remarks>
+ <para>
+ The <paramref name="locationInfo" /> parameter determines whether
+ location information will be output by the layout. If
+ <paramref name="locationInfo" /> is set to <c>true</c>, then the
+ file name and line number of the statement at the origin of the log
+ statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SMTPAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a formatted string.
+ </summary>
+ <param name="loggingEvent">The event being logged.</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Format the <see cref="T:log4net.Core.LoggingEvent"/> and write it to the <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ <para>
+ This method creates an <see cref="T:System.Xml.XmlTextWriter"/> that writes to the
+ <paramref name="writer"/>. The <see cref="T:System.Xml.XmlTextWriter"/> is passed
+ to the <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method. Subclasses should override the
+ <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method rather than this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Does the actual writing of the XML.
+ </summary>
+ <param name="writer">The writer to use to output the event to.</param>
+ <param name="loggingEvent">The event to write.</param>
+ <remarks>
+ <para>
+ Subclasses should override this method to format
+ the <see cref="T:log4net.Core.LoggingEvent"/> as XML.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_locationInfo">
+ <summary>
+ Flag to indicate if location information should be included in
+ the XML events.
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_protectCloseTextWriter">
+ <summary>
+ Writer adapter that ignores Close
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_invalidCharReplacement">
+ <summary>
+ The string to replace invalid chars with
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.LocationInfo">
+ <summary>
+ Gets a value indicating whether to include location information in
+ the XML events.
+ </summary>
+ <value>
+ <c>true</c> if location information should be included in the XML
+ events; otherwise, <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ If <see cref="P:log4net.Layout.XmlLayoutBase.LocationInfo"/> is set to <c>true</c>, then the file
+ name and line number of the statement at the origin of the log
+ statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an <c>SMTPAppender</c>
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement">
+ <summary>
+ The string to replace characters that can not be expressed in XML with.
+ <remarks>
+ <para>
+ Not all characters may be expressed in XML. This property contains the
+ string to replace those that can not with. This defaults to a ?. Set it
+ to the empty string to simply remove offending characters. For more
+ details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets
+ Character replacement will occur in the log message, the property names
+ and the property values.
+ </para>
+ </remarks>
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.ContentType">
+ <summary>
+ Gets the content type output by this layout.
+ </summary>
+ <value>
+ As this is the XML layout, the value is always <c>"text/xml"</c>.
+ </value>
+ <remarks>
+ <para>
+ As this is the XML layout, the value is always <c>"text/xml"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.#ctor">
+ <summary>
+ Constructs an XmlLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.#ctor(System.Boolean)">
+ <summary>
+ Constructs an XmlLayout.
+ </summary>
+ <remarks>
+ <para>
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SmtpAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Builds a cache of the element names
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Does the actual writing of the XML.
+ </summary>
+ <param name="writer">The writer to use to output the event to.</param>
+ <param name="loggingEvent">The event to write.</param>
+ <remarks>
+ <para>
+ Override the base class <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method
+ to write the <see cref="T:log4net.Core.LoggingEvent"/> to the <see cref="T:System.Xml.XmlWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.XmlLayout.m_prefix">
+ <summary>
+ The prefix to use for all generated element names
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Prefix">
+ <summary>
+ The prefix to use for all element names
+ </summary>
+ <remarks>
+ <para>
+ The default prefix is <b>log4net</b>. Set this property
+ to change the prefix. If the prefix is set to an empty string
+ then no prefix will be written.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Base64EncodeMessage">
+ <summary>
+ Set whether or not to base64 encode the message.
+ </summary>
+ <remarks>
+ <para>
+ By default the log message will be written as text to the xml
+ output. This can cause problems when the message contains binary
+ data. By setting this to true the contents of the message will be
+ base64 encoded. If this is set then invalid character replacement
+ (see <see cref="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement"/>) will not be performed
+ on the log message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Base64EncodeProperties">
+ <summary>
+ Set whether or not to base64 encode the property values.
+ </summary>
+ <remarks>
+ <para>
+ By default the properties will be written as text to the xml
+ output. This can cause problems when one or more properties contain
+ binary data. By setting this to true the values of the properties
+ will be base64 encoded. If this is set then invalid character replacement
+ (see <see cref="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement"/>) will not be performed
+ on the property values.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.XmlLayoutSchemaLog4j">
+ <summary>
+ Layout that formats the log events as XML elements compatible with the log4j schema
+ </summary>
+ <remarks>
+ <para>
+ Formats the log events according to the http://logging.apache.org/log4j schema.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutSchemaLog4j.s_date1970">
+ <summary>
+ The 1st of January 1970 in UTC
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.#ctor">
+ <summary>
+ Constructs an XMLLayoutSchemaLog4j
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.#ctor(System.Boolean)">
+ <summary>
+ Constructs an XMLLayoutSchemaLog4j.
+ </summary>
+ <remarks>
+ <para>
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SMTPAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Actually do the writing of the xml
+ </summary>
+ <param name="writer">the writer to use</param>
+ <param name="loggingEvent">the event to write</param>
+ <remarks>
+ <para>
+ Generate XML that is compatible with the log4j schema.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutSchemaLog4j.Version">
+ <summary>
+ The version of the log4j schema to use.
+ </summary>
+ <remarks>
+ <para>
+ Only version 1.2 of the log4j schema is supported.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.ObjectRenderer.DefaultRenderer">
+ <summary>
+ The default object Renderer.
+ </summary>
+ <remarks>
+ <para>
+ The default renderer supports rendering objects and collections to strings.
+ </para>
+ <para>
+ See the <see cref="M:log4net.ObjectRenderer.DefaultRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)"/> method for details of the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.ObjectRenderer.IObjectRenderer">
+ <summary>
+ Implement this interface in order to render objects as strings
+ </summary>
+ <remarks>
+ <para>
+ Certain types require special case conversion to
+ string form. This conversion is done by an object renderer.
+ Object renderers implement the <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>
+ interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ObjectRenderer.IObjectRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)">
+ <summary>
+ Render the object <paramref name="obj"/> to a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="obj">The object to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the object <paramref name="obj"/> to a
+ string.
+ </para>
+ <para>
+ The <paramref name="rendererMap"/> parameter is
+ provided to lookup and render other objects. This is
+ very useful where <paramref name="obj"/> contains
+ nested objects of unknown type. The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)"/>
+ method can be used to render these objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)">
+ <summary>
+ Render the object <paramref name="obj"/> to a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="obj">The object to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the object <paramref name="obj"/> to a string.
+ </para>
+ <para>
+ The <paramref name="rendererMap"/> parameter is
+ provided to lookup and render other objects. This is
+ very useful where <paramref name="obj"/> contains
+ nested objects of unknown type. The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)"/>
+ method can be used to render these objects.
+ </para>
+ <para>
+ The default renderer supports rendering objects to strings as follows:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Rendered String</description>
+ </listheader>
+ <item>
+ <term><c>null</c></term>
+ <description>
+ <para>"(null)"</para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Array"/></term>
+ <description>
+ <para>
+ For a one dimensional array this is the
+ array type name, an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace.
+ </para>
+ <para>
+ For example: <c>int[] {1, 2, 3}</c>.
+ </para>
+ <para>
+ If the array is not one dimensional the
+ <c>Array.ToString()</c> is returned.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Collections.IEnumerable"/>, <see cref="T:System.Collections.ICollection"/> &amp; <see cref="T:System.Collections.IEnumerator"/></term>
+ <description>
+ <para>
+ Rendered as an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace.
+ </para>
+ <para>
+ For example: <c>{a, b, c}</c>.
+ </para>
+ <para>
+ All collection classes that implement <see cref="T:System.Collections.ICollection"/> its subclasses,
+ or generic equivalents all implement the <see cref="T:System.Collections.IEnumerable"/> interface.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Collections.DictionaryEntry"/></term>
+ <description>
+ <para>
+ Rendered as the key, an equals sign ('='), and the value (using the appropriate
+ renderer).
+ </para>
+ <para>
+ For example: <c>key=value</c>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ <para><c>Object.ToString()</c></para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderArray(log4net.ObjectRenderer.RendererMap,System.Array,System.IO.TextWriter)">
+ <summary>
+ Render the array argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="array">the array to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ For a one dimensional array this is the
+ array type name, an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace. For example:
+ <c>int[] {1, 2, 3}</c>.
+ </para>
+ <para>
+ If the array is not one dimensional the
+ <c>Array.ToString()</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderEnumerator(log4net.ObjectRenderer.RendererMap,System.Collections.IEnumerator,System.IO.TextWriter)">
+ <summary>
+ Render the enumerator argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="enumerator">the enumerator to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Rendered as an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace. For example:
+ <c>{a, b, c}</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderDictionaryEntry(log4net.ObjectRenderer.RendererMap,System.Collections.DictionaryEntry,System.IO.TextWriter)">
+ <summary>
+ Render the DictionaryEntry argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="entry">the DictionaryEntry to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the key, an equals sign ('='), and the value (using the appropriate
+ renderer). For example: <c>key=value</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.ObjectRenderer.RendererMap">
+ <summary>
+ Map class objects to an <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>.
+ </summary>
+ <remarks>
+ <para>
+ Maintains a mapping between types that require special
+ rendering and the <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> that
+ is used to render them.
+ </para>
+ <para>
+ The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)"/> method is used to render an
+ <c>object</c> using the appropriate renderers defined in this map.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)">
+ <summary>
+ Render <paramref name="obj"/> using the appropriate renderer.
+ </summary>
+ <param name="obj">the object to render to a string</param>
+ <returns>the object rendered as a string</returns>
+ <remarks>
+ <para>
+ This is a convenience method used to render an object to a string.
+ The alternative method <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)"/>
+ should be used when streaming output to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)">
+ <summary>
+ Render <paramref name="obj"/> using the appropriate renderer.
+ </summary>
+ <param name="obj">the object to render to a string</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Find the appropriate renderer for the type of the
+ <paramref name="obj"/> parameter. This is accomplished by calling the
+ <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/> method. Once a renderer is found, it is
+ applied on the object <paramref name="obj"/> and the result is returned
+ as a <see cref="T:System.String"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Get(System.Object)">
+ <summary>
+ Gets the renderer for the specified object type
+ </summary>
+ <param name="obj">the object to lookup the renderer for</param>
+ <returns>the renderer for <paramref name="obj"/></returns>
+ <remarks>
+ <param>
+ Gets the renderer for the specified object type.
+ </param>
+ <param>
+ Syntactic sugar method that calls <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/>
+ with the type of the object parameter.
+ </param>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)">
+ <summary>
+ Gets the renderer for the specified type
+ </summary>
+ <param name="type">the type to lookup the renderer for</param>
+ <returns>the renderer for the specified type</returns>
+ <remarks>
+ <para>
+ Returns the renderer for the specified type.
+ If no specific renderer has been defined the
+ <see cref="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer"/> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.SearchTypeAndInterfaces(System.Type)">
+ <summary>
+ Internal function to recursively search interfaces
+ </summary>
+ <param name="type">the type to lookup the renderer for</param>
+ <returns>the renderer for the specified type</returns>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Clear">
+ <summary>
+ Clear the map of renderers
+ </summary>
+ <remarks>
+ <para>
+ Clear the custom renderers defined by using
+ <see cref="M:log4net.ObjectRenderer.RendererMap.Put(System.Type,log4net.ObjectRenderer.IObjectRenderer)"/>. The <see cref="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer"/>
+ cannot be removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Put(System.Type,log4net.ObjectRenderer.IObjectRenderer)">
+ <summary>
+ Register an <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> for <paramref name="typeToRender"/>.
+ </summary>
+ <param name="typeToRender">the type that will be rendered by <paramref name="renderer"/></param>
+ <param name="renderer">the renderer for <paramref name="typeToRender"/></param>
+ <remarks>
+ <para>
+ Register an object renderer for a specific source type.
+ This renderer will be returned from a call to <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/>
+ specifying the same <paramref name="typeToRender"/> as an argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer">
+ <summary>
+ Get the default renderer instance
+ </summary>
+ <value>the default renderer</value>
+ <remarks>
+ <para>
+ Get the default renderer
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.IPlugin">
+ <summary>
+ Interface implemented by logger repository plugins.
+ </summary>
+ <remarks>
+ <para>
+ Plugins define additional behavior that can be associated
+ with a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ The <see cref="T:log4net.Plugin.PluginMap"/> held by the <see cref="P:log4net.Repository.ILoggerRepository.PluginMap"/>
+ property is used to store the plugins for a repository.
+ </para>
+ <para>
+ The <c>log4net.Config.PluginAttribute</c> can be used to
+ attach plugins to repositories created using configuration
+ attributes.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.IPlugin.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches the plugin to the specified <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.IPlugin.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ This method is called to notify the plugin that
+ it should stop operating and should detach from
+ the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.IPlugin.Name">
+ <summary>
+ Gets the name of the plugin.
+ </summary>
+ <value>
+ The name of the plugin.
+ </value>
+ <remarks>
+ <para>
+ Plugins are stored in the <see cref="T:log4net.Plugin.PluginMap"/>
+ keyed by name. Each plugin instance attached to a
+ repository must be a unique name.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Plugin.IPlugin"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ReadOnly(log4net.Plugin.PluginCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>PluginCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ A <c>PluginCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>PluginCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.PluginCollection)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <c>PluginCollection</c>.
+ </summary>
+ <param name="c">The <c>PluginCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.IPlugin[])">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Plugin.IPlugin"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Plugin.IPlugin"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Plugin.IPlugin"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Plugin.IPlugin"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.PluginCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.CopyTo(log4net.Plugin.IPlugin[])">
+ <summary>
+ Copies the entire <c>PluginCollection</c> to a one-dimensional
+ <see cref="T:log4net.Plugin.IPlugin"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Plugin.IPlugin"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.CopyTo(log4net.Plugin.IPlugin[],System.Int32)">
+ <summary>
+ Copies the entire <c>PluginCollection</c> to a one-dimensional
+ <see cref="T:log4net.Plugin.IPlugin"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Plugin.IPlugin"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Add(log4net.Plugin.IPlugin)">
+ <summary>
+ Adds a <see cref="T:log4net.Plugin.IPlugin"/> to the end of the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Clear">
+ <summary>
+ Removes all elements from the <c>PluginCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Plugin.PluginCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Contains(log4net.Plugin.IPlugin)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Plugin.IPlugin"/> is in the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>PluginCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IndexOf(log4net.Plugin.IPlugin)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Plugin.IPlugin"/>
+ in the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to locate in the <c>PluginCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>PluginCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Insert(System.Int32,log4net.Plugin.IPlugin)">
+ <summary>
+ Inserts an element into the <c>PluginCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Remove(log4net.Plugin.IPlugin)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Plugin.IPlugin"/> from the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to remove from the <c>PluginCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Plugin.IPlugin"/> was not found in the <c>PluginCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>PluginCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>PluginCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Plugin.PluginCollection.Enumerator"/> for the entire <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(log4net.Plugin.PluginCollection)">
+ <summary>
+ Adds the elements of another <c>PluginCollection</c> to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="x">The <c>PluginCollection</c> whose elements should be added to the end of the current <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(log4net.Plugin.IPlugin[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Plugin.IPlugin"/> array to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Plugin.IPlugin"/> array whose elements should be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Plugin.IPlugin"/> collection to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Plugin.IPlugin"/> collection whose elements should be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>PluginCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <returns>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</returns>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the collection.
+ </value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Plugin.IPlugin"/> at the specified index.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Plugin.IPlugin"/> at the specified index.
+ </value>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value><c>true</c> if the collection has a fixed size; otherwise, <c>false</c>. The default is <c>false</c>.</value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value><c>true</c> if the collection is read-only; otherwise, <c>false</c>. The default is <c>false</c>.</value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>PluginCollection</c> can contain.
+ </summary>
+ <value>
+ The number of elements the <c>PluginCollection</c> can contain.
+ </value>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ <exclude/>
+ </member>
+ <member name="F:log4net.Plugin.PluginCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.#ctor(log4net.Plugin.PluginCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ <value>
+ The current element in the collection.
+ </value>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.ReadOnlyPluginCollection">
+ <exclude/>
+ </member>
+ <member name="T:log4net.Plugin.PluginMap">
+ <summary>
+ Map of repository plugins.
+ </summary>
+ <remarks>
+ <para>
+ This class is a name keyed map of the plugins that are
+ attached to a repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="repository">The repository that the plugins should be attached to.</param>
+ <remarks>
+ <para>
+ Initialize a new instance of the <see cref="T:log4net.Plugin.PluginMap"/> class with a
+ repository that the plugins should be attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.Add(log4net.Plugin.IPlugin)">
+ <summary>
+ Adds a <see cref="T:log4net.Plugin.IPlugin"/> to the map.
+ </summary>
+ <param name="plugin">The <see cref="T:log4net.Plugin.IPlugin"/> to add to the map.</param>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Plugin.IPlugin"/> will be attached to the repository when added.
+ </para>
+ <para>
+ If there already exists a plugin with the same name
+ attached to the repository then the old plugin will
+ be <see cref="M:log4net.Plugin.IPlugin.Shutdown"/> and replaced with
+ the new plugin.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.Remove(log4net.Plugin.IPlugin)">
+ <summary>
+ Removes a <see cref="T:log4net.Plugin.IPlugin"/> from the map.
+ </summary>
+ <param name="plugin">The <see cref="T:log4net.Plugin.IPlugin"/> to remove from the map.</param>
+ <remarks>
+ <para>
+ Remove a specific plugin from this map.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginMap.Item(System.String)">
+ <summary>
+ Gets a <see cref="T:log4net.Plugin.IPlugin"/> by name.
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Plugin.IPlugin"/> to lookup.</param>
+ <returns>
+ The <see cref="T:log4net.Plugin.IPlugin"/> from the map with the name specified, or
+ <c>null</c> if no plugin is found.
+ </returns>
+ <remarks>
+ <para>
+ Lookup a plugin by name. If the plugin is not found <c>null</c>
+ will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginMap.AllPlugins">
+ <summary>
+ Gets all possible plugins as a list of <see cref="T:log4net.Plugin.IPlugin"/> objects.
+ </summary>
+ <value>All possible plugins as a list of <see cref="T:log4net.Plugin.IPlugin"/> objects.</value>
+ <remarks>
+ <para>
+ Get a collection of all the plugins defined in this map.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.PluginSkeleton">
+ <summary>
+ Base implementation of <see cref="T:log4net.Plugin.IPlugin"/>
+ </summary>
+ <remarks>
+ <para>
+ Default abstract implementation of the <see cref="T:log4net.Plugin.IPlugin"/>
+ interface. This base class can be used by implementors
+ of the <see cref="T:log4net.Plugin.IPlugin"/> interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="name">the name of the plugin</param>
+ <remarks>
+ Initializes a new Plugin with the specified name.
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches this plugin to a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ This method is called to notify the plugin that
+ it should stop operating and should detach from
+ the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Plugin.PluginSkeleton.m_name">
+ <summary>
+ The name of this plugin.
+ </summary>
+ </member>
+ <member name="F:log4net.Plugin.PluginSkeleton.m_repository">
+ <summary>
+ The repository this plugin is attached to.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginSkeleton.Name">
+ <summary>
+ Gets or sets the name of the plugin.
+ </summary>
+ <value>
+ The name of the plugin.
+ </value>
+ <remarks>
+ <para>
+ Plugins are stored in the <see cref="T:log4net.Plugin.PluginMap"/>
+ keyed by name. Each plugin instance attached to a
+ repository must be a unique name.
+ </para>
+ <para>
+ The name of the plugin must not change one the
+ plugin has been attached to a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginSkeleton.LoggerRepository">
+ <summary>
+ The repository for this plugin
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin is attached to.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin is
+ attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.RemoteLoggingServerPlugin">
+ <summary>
+ Plugin that listens for events from the <see cref="T:log4net.Appender.RemotingAppender"/>
+ </summary>
+ <remarks>
+ <para>
+ This plugin publishes an instance of <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ on a specified <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/>. This listens for logging events delivered from
+ a remote <see cref="T:log4net.Appender.RemotingAppender"/>.
+ </para>
+ <para>
+ When an event is received it is relogged within the attached repository
+ as if it had been raised locally.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin"/> class.
+ </para>
+ <para>
+ The <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/> property must be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.#ctor(System.String)">
+ <summary>
+ Construct with sink Uri.
+ </summary>
+ <param name="sinkUri">The name to publish the sink under in the remoting infrastructure.
+ See <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/> for more details.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin"/> class
+ with specified name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches this plugin to a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ When the plugin is shutdown the remote logging
+ sink is disconnected.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri">
+ <summary>
+ Gets or sets the URI of this sink.
+ </summary>
+ <value>
+ The URI of this sink.
+ </value>
+ <remarks>
+ <para>
+ This is the name under which the object is marshaled.
+ <see cref="M:System.Runtime.Remoting.RemotingServices.Marshal(System.MarshalByRefObject,System.String,System.Type)"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl">
+ <summary>
+ Delivers <see cref="T:log4net.Core.LoggingEvent"/> objects to a remote sink.
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to listen for logging events
+ and deliver them to the local repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="repository">The repository to log to.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl"/> for the
+ specified <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.LogEvents(log4net.Core.LoggingEvent[])">
+ <summary>
+ Logs the events to the repository.
+ </summary>
+ <param name="events">The events to log.</param>
+ <remarks>
+ <para>
+ The events passed are logged to the <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.InitializeLifetimeService">
+ <summary>
+ Obtains a lifetime service object to control the lifetime
+ policy for this instance.
+ </summary>
+ <returns><c>null</c> to indicate that this instance should live forever.</returns>
+ <remarks>
+ <para>
+ Obtains a lifetime service object to control the lifetime
+ policy for this instance. This object should live forever
+ therefore this implementation returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.m_repository">
+ <summary>
+ The underlying <see cref="T:log4net.Repository.ILoggerRepository"/> that events should
+ be logged to.
+ </summary>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.DefaultLoggerFactory">
+ <summary>
+ Default implementation of <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ </summary>
+ <remarks>
+ <para>
+ This default implementation of the <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ interface is used to create the default subclass
+ of the <see cref="T:log4net.Repository.Hierarchy.Logger"/> object.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.ILoggerFactory">
+ <summary>
+ Interface abstracts creation of <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances
+ </summary>
+ <remarks>
+ <para>
+ This interface is used by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to
+ create new <see cref="T:log4net.Repository.Hierarchy.Logger"/> objects.
+ </para>
+ <para>
+ The <see cref="M:log4net.Repository.Hierarchy.ILoggerFactory.CreateLogger(System.String)"/> method is called
+ to create a named <see cref="T:log4net.Repository.Hierarchy.Logger"/>.
+ </para>
+ <para>
+ Implement this interface to create new subclasses of <see cref="T:log4net.Repository.Hierarchy.Logger"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.ILoggerFactory.CreateLogger(System.String)">
+ <summary>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance for the specified name.</returns>
+ <remarks>
+ <para>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance with the
+ specified name.
+ </para>
+ <para>
+ Called by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to create
+ new named <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances.
+ </para>
+ <para>
+ If the <paramref name="name"/> is <c>null</c> then the root logger
+ must be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.CreateLogger(System.String)">
+ <summary>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance for the specified name.</returns>
+ <remarks>
+ <para>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance with the
+ specified name.
+ </para>
+ <para>
+ Called by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to create
+ new named <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances.
+ </para>
+ <para>
+ If the <paramref name="name"/> is <c>null</c> then the root logger
+ must be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl">
+ <summary>
+ Default internal subclass of <see cref="T:log4net.Repository.Hierarchy.Logger"/>
+ </summary>
+ <remarks>
+ <para>
+ This subclass has no additional behavior over the
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> class but does allow instances
+ to be created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Logger">
+ <summary>
+ Implementation of <see cref="T:log4net.Core.ILogger"/> used by <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to provide implementation of <see cref="T:log4net.Core.ILogger"/>
+ interface. Applications should use <see cref="T:log4net.LogManager"/> to get
+ logger instances.
+ </para>
+ <para>
+ This is one of the central classes in the log4net implementation. One of the
+ distinctive features of log4net are hierarchical loggers and their
+ evaluation. The <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/> organizes the <see cref="T:log4net.Repository.Hierarchy.Logger"/>
+ instances into a rooted tree hierarchy.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.Hierarchy.Logger"/> class is abstract. Only concrete subclasses of
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> can be created. The <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ is used to create instances of this type for the <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.#ctor(System.String)">
+ <summary>
+ This constructor created a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance and
+ sets its name.
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <remarks>
+ <para>
+ This constructor is protected and designed to be used by
+ a subclass that is not abstract.
+ </para>
+ <para>
+ Loggers are constructed by <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ objects. See <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory"/> for the default
+ logger creator.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Add <paramref name="newAppender"/> to the list of appenders of this
+ Logger instance.
+ </summary>
+ <param name="newAppender">An appender to add to this logger</param>
+ <remarks>
+ <para>
+ Add <paramref name="newAppender"/> to the list of appenders of this
+ Logger instance.
+ </para>
+ <para>
+ If <paramref name="newAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.GetAppender(System.String)">
+ <summary>
+ Look for the appender named as <c>name</c>
+ </summary>
+ <param name="name">The name of the appender to lookup</param>
+ <returns>The appender with the name specified, or <c>null</c>.</returns>
+ <remarks>
+ <para>
+ Returns the named appender, or null if the appender is not found.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAllAppenders">
+ <summary>
+ Remove all previously added appenders from this Logger instance.
+ </summary>
+ <remarks>
+ <para>
+ Remove all previously added appenders from this Logger instance.
+ </para>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Remove the appender passed as parameter form the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ Remove the appender passed as parameter form the list of appenders.
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAppender(System.String)">
+ <summary>
+ Remove the appender passed as parameter form the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ Remove the named appender passed as parameter form the list of appenders.
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This generic form is intended to be used by wrappers.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generate a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/> and <paramref name="exception"/>.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ This is the most generic printing method that is intended to be used
+ by wrappers.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Logs the specified logging event through this logger.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.IsEnabledFor(log4net.Core.Level)">
+ <summary>
+ Checks if this logger is enabled for a given <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> passed as parameter.
+ </summary>
+ <param name="level">The level to check.</param>
+ <returns>
+ <c>true</c> if this logger is enabled for <c>level</c>, otherwise <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Test if this logger is going to log events of the specified <paramref name="level"/>.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.CallAppenders(log4net.Core.LoggingEvent)">
+ <summary>
+ Deliver the <see cref="T:log4net.Core.LoggingEvent"/> to the attached appenders.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Call the appenders in the hierarchy starting at
+ <c>this</c>. If no appenders could be found, emit a
+ warning.
+ </para>
+ <para>
+ This method calls all the appenders inherited from the
+ hierarchy circumventing any evaluation of whether to log or not
+ to log the particular log request.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.CloseNestedAppenders">
+ <summary>
+ Closes all attached appenders implementing the <see cref="T:log4net.Core.IAppenderAttachable"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ Used to ensure that the appenders are correctly shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This is the most generic printing method. This generic form is intended to be used by wrappers
+ </summary>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generate a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.ForcedLog(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ Creates a new logging event and logs the event without further checks.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generates a logging event and delivers it to the attached
+ appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.ForcedLog(log4net.Core.LoggingEvent)">
+ <summary>
+ Creates a new logging event and logs the event without further checks.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Delivers the logging event to the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.ThisDeclaringType">
+ <summary>
+ The fully qualified type of the Logger class.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_name">
+ <summary>
+ The name of this logger.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_level">
+ <summary>
+ The assigned level of this logger.
+ </summary>
+ <remarks>
+ <para>
+ The <c>level</c> variable need not be
+ assigned a value in which case it is inherited
+ form the hierarchy.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_parent">
+ <summary>
+ The parent of this logger.
+ </summary>
+ <remarks>
+ <para>
+ The parent of this logger.
+ All loggers have at least one ancestor which is the root logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_hierarchy">
+ <summary>
+ Loggers need to know what Hierarchy they are in.
+ </summary>
+ <remarks>
+ <para>
+ Loggers need to know what Hierarchy they are in.
+ The hierarchy that this logger is a member of is stored
+ here.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_appenderAttachedImpl">
+ <summary>
+ Helper implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_additive">
+ <summary>
+ Flag indicating if child loggers inherit their parents appenders
+ </summary>
+ <remarks>
+ <para>
+ Additivity is set to true by default, that is children inherit
+ the appenders of their ancestors by default. If this variable is
+ set to <c>false</c> then the appenders found in the
+ ancestors of this logger are not used. However, the children
+ of this logger will inherit its appenders, unless the children
+ have their additivity flag set to <c>false</c> too. See
+ the user manual for more details.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_appenderLock">
+ <summary>
+ Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl
+ </summary>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Parent">
+ <summary>
+ Gets or sets the parent logger in the hierarchy.
+ </summary>
+ <value>
+ The parent logger in the hierarchy.
+ </value>
+ <remarks>
+ <para>
+ Part of the Composite pattern that makes the hierarchy.
+ The hierarchy is parent linked rather than child linked.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Additivity">
+ <summary>
+ Gets or sets a value indicating if child loggers inherit their parent's appenders.
+ </summary>
+ <value>
+ <c>true</c> if child loggers inherit their parent's appenders.
+ </value>
+ <remarks>
+ <para>
+ Additivity is set to <c>true</c> by default, that is children inherit
+ the appenders of their ancestors by default. If this variable is
+ set to <c>false</c> then the appenders found in the
+ ancestors of this logger are not used. However, the children
+ of this logger will inherit its appenders, unless the children
+ have their additivity flag set to <c>false</c> too. See
+ the user manual for more details.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.EffectiveLevel">
+ <summary>
+ Gets the effective level for this logger.
+ </summary>
+ <returns>The nearest level in the logger hierarchy.</returns>
+ <remarks>
+ <para>
+ Starting from this logger, searches the logger hierarchy for a
+ non-null level and returns it. Otherwise, returns the level of the
+ root logger.
+ </para>
+ <para>The Logger class is designed so that this method executes as
+ quickly as possible.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Hierarchy">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>The hierarchy that this logger belongs to.</value>
+ <remarks>
+ <para>
+ This logger must be attached to a single <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Level">
+ <summary>
+ Gets or sets the assigned <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/>, if any, for this Logger.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> of this logger.
+ </value>
+ <remarks>
+ <para>
+ The assigned <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> can be <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Appenders">
+ <summary>
+ Get the appenders contained in this logger as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <returns>A collection of the appenders in this logger</returns>
+ <remarks>
+ <para>
+ Get the appenders contained in this logger as an
+ <see cref="T:System.Collections.ICollection"/>. If no appenders
+ can be found, then a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Name">
+ <summary>
+ Gets the logger name.
+ </summary>
+ <value>
+ The name of the logger.
+ </value>
+ <remarks>
+ <para>
+ The name of this logger
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Repository">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this logger belongs to.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl.#ctor(System.String)">
+ <summary>
+ Construct a new Logger
+ </summary>
+ <param name="name">the name of the logger</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl"/> class
+ with the specified name.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerCreationEventHandler">
+ <summary>
+ Delegate used to handle logger creation event notifications.
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> in which the <see cref="T:log4net.Repository.Hierarchy.Logger"/> has been created.</param>
+ <param name="e">The <see cref="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs"/> event args that hold the <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance that has been created.</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger creation event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs">
+ <summary>
+ Provides data for the <see cref="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent"/> event.
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent"/> event is raised every time a
+ <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.LoggerCreationEventArgs.m_log">
+ <summary>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> created
+ </summary>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerCreationEventArgs.#ctor(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="log">The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs"/> event argument
+ class,with the specified <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger">
+ <summary>
+ Gets the <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy">
+ <summary>
+ Hierarchical organization of loggers
+ </summary>
+ <remarks>
+ <para>
+ <i>The casual user should not have to deal with this class
+ directly.</i>
+ </para>
+ <para>
+ This class is specialized in retrieving loggers by name and
+ also maintaining the logger hierarchy. Implements the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ </para>
+ <para>
+ The structure of the logger hierarchy is maintained by the
+ <see cref="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String)"/> method. The hierarchy is such that children
+ link to their parent but parents do not have any references to their
+ children. Moreover, loggers can be instantiated in any order, in
+ particular descendant before ancestor.
+ </para>
+ <para>
+ In case a descendant is created before a particular ancestor,
+ then it creates a provision node for the ancestor and adds itself
+ to the provision node. Other descendants of the same ancestor add
+ themselves to the previously created provision node.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositorySkeleton">
+ <summary>
+ Base implementation of <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </summary>
+ <remarks>
+ <para>
+ Default abstract implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ </para>
+ <para>
+ Skeleton implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ All <see cref="T:log4net.Repository.ILoggerRepository"/> types can extend this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.ILoggerRepository">
+ <summary>
+ Interface implemented by logger repositories.
+ </summary>
+ <remarks>
+ <para>
+ This interface is implemented by logger repositories. e.g.
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ <para>
+ This interface is used by the <see cref="T:log4net.LogManager"/>
+ to obtain <see cref="T:log4net.ILog"/> interfaces.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Exists(System.String)">
+ <summary>
+ Check if the named logger exists in the repository. If so return
+ its reference, otherwise returns <c>null</c>.
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ If the names logger exists it is returned, otherwise
+ <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers as an Array.
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetLogger(System.String)">
+ <summary>
+ Returns a named logger instance
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Returns a named logger instance.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Shutdown">
+ <summary>Shutdown the repository</summary>
+ <remarks>
+ <para>
+ Shutting down a repository will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </para>
+ <para>
+ Some appenders need to be closed before the
+ application exists. Otherwise, pending logging events might be
+ lost.
+ </para>
+ <para>
+ The <see cref="M:log4net.Repository.ILoggerRepository.Shutdown"/> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.ResetConfiguration">
+ <summary>
+ Reset the repositories configuration to a default state
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this instance to their
+ default state.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the <see cref="T:log4net.Core.LoggingEvent"/> through this repository.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetAppenders">
+ <summary>
+ Returns all the Appenders that are configured as an Array.
+ </summary>
+ <returns>All the Appenders</returns>
+ <remarks>
+ <para>
+ Returns all the Appenders that are configured as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Name">
+ <summary>
+ The name of the repository
+ </summary>
+ <value>
+ The name of the repository
+ </value>
+ <remarks>
+ <para>
+ The name of the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.RendererMap">
+ <summary>
+ RendererMap accesses the object renderer map for this repository.
+ </summary>
+ <value>
+ RendererMap accesses the object renderer map for this repository.
+ </value>
+ <remarks>
+ <para>
+ RendererMap accesses the object renderer map for this repository.
+ </para>
+ <para>
+ The RendererMap holds a mapping between types and
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.PluginMap">
+ <summary>
+ The plugin map for this repository.
+ </summary>
+ <value>
+ The plugin map for this repository.
+ </value>
+ <remarks>
+ <para>
+ The plugin map holds the <see cref="T:log4net.Plugin.IPlugin"/> instances
+ that have been attached to this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.LevelMap">
+ <summary>
+ Get the level map for the Repository.
+ </summary>
+ <remarks>
+ <para>
+ Get the level map for the Repository.
+ </para>
+ <para>
+ The level map defines the mappings between
+ level names and <see cref="T:log4net.Core.Level"/> objects in
+ this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Threshold">
+ <summary>
+ The threshold for all events in this repository
+ </summary>
+ <value>
+ The threshold for all events in this repository
+ </value>
+ <remarks>
+ <para>
+ The threshold for all events in this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Configured">
+ <summary>
+ Flag indicates if this repository has been configured.
+ </summary>
+ <value>
+ Flag indicates if this repository has been configured.
+ </value>
+ <remarks>
+ <para>
+ Flag indicates if this repository has been configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ShutdownEvent">
+ <summary>
+ Event to notify that the repository has been shutdown.
+ </summary>
+ <value>
+ Event to notify that the repository has been shutdown.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository has been shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ConfigurationReset">
+ <summary>
+ Event to notify that the repository has had its configuration reset.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration reset.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been
+ reset to default.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ConfigurationChanged">
+ <summary>
+ Event to notify that the repository has had its configuration changed.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration changed.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Properties">
+ <summary>
+ Repository specific properties
+ </summary>
+ <value>
+ Repository specific properties
+ </value>
+ <remarks>
+ <para>
+ These properties can be specified on a repository specific basis.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes the repository with default (empty) properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.#ctor(log4net.Util.PropertiesDictionary)">
+ <summary>
+ Construct the repository using specific properties
+ </summary>
+ <param name="properties">the properties to set for this repository</param>
+ <remarks>
+ <para>
+ Initializes the repository with specified properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Exists(System.String)">
+ <summary>
+ Test if logger exists
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Check if the named logger exists in the repository. If so return
+ its reference, otherwise returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers in the repository
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers in the repository as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetLogger(System.String)">
+ <summary>
+ Return a new logger instance
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Return a new logger instance.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Shutdown">
+ <summary>
+ Shutdown the repository
+ </summary>
+ <remarks>
+ <para>
+ Shutdown the repository. Can be overridden in a subclass.
+ This base class implementation notifies the <see cref="E:log4net.Repository.LoggerRepositorySkeleton.ShutdownEvent"/>
+ listeners and all attached plugins of the shutdown event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.ResetConfiguration">
+ <summary>
+ Reset the repositories configuration to a default state
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this instance to their
+ default state.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logEvent through this repository.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetAppenders">
+ <summary>
+ Returns all the Appenders that are configured as an Array.
+ </summary>
+ <returns>All the Appenders</returns>
+ <remarks>
+ <para>
+ Returns all the Appenders that are configured as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.AddRenderer(System.Type,log4net.ObjectRenderer.IObjectRenderer)">
+ <summary>
+ Adds an object renderer for a specific class.
+ </summary>
+ <param name="typeToRender">The type that will be rendered by the renderer supplied.</param>
+ <param name="rendererInstance">The object renderer used to render the object.</param>
+ <remarks>
+ <para>
+ Adds an object renderer for a specific class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnShutdown(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository is shutting down
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository is shutting down.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnConfigurationReset(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository has had its configuration reset
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository's configuration has been reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnConfigurationChanged(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository has had its configuration changed
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository's configuration has changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.RaiseConfigurationChanged(System.EventArgs)">
+ <summary>
+ Raise a configuration changed event on this repository
+ </summary>
+ <param name="e">EventArgs.Empty</param>
+ <remarks>
+ <para>
+ Applications that programmatically change the configuration of the repository should
+ raise this event notification to notify listeners.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Name">
+ <summary>
+ The name of the repository
+ </summary>
+ <value>
+ The string name of the repository
+ </value>
+ <remarks>
+ <para>
+ The name of this repository. The name is
+ used to store and lookup the repositories
+ stored by the <see cref="T:log4net.Core.IRepositorySelector"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Threshold">
+ <summary>
+ The threshold for all events in this repository
+ </summary>
+ <value>
+ The threshold for all events in this repository
+ </value>
+ <remarks>
+ <para>
+ The threshold for all events in this repository
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.RendererMap">
+ <summary>
+ RendererMap accesses the object renderer map for this repository.
+ </summary>
+ <value>
+ RendererMap accesses the object renderer map for this repository.
+ </value>
+ <remarks>
+ <para>
+ RendererMap accesses the object renderer map for this repository.
+ </para>
+ <para>
+ The RendererMap holds a mapping between types and
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.PluginMap">
+ <summary>
+ The plugin map for this repository.
+ </summary>
+ <value>
+ The plugin map for this repository.
+ </value>
+ <remarks>
+ <para>
+ The plugin map holds the <see cref="T:log4net.Plugin.IPlugin"/> instances
+ that have been attached to this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.LevelMap">
+ <summary>
+ Get the level map for the Repository.
+ </summary>
+ <remarks>
+ <para>
+ Get the level map for the Repository.
+ </para>
+ <para>
+ The level map defines the mappings between
+ level names and <see cref="T:log4net.Core.Level"/> objects in
+ this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Configured">
+ <summary>
+ Flag indicates if this repository has been configured.
+ </summary>
+ <value>
+ Flag indicates if this repository has been configured.
+ </value>
+ <remarks>
+ <para>
+ Flag indicates if this repository has been configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ShutdownEvent">
+ <summary>
+ Event to notify that the repository has been shutdown.
+ </summary>
+ <value>
+ Event to notify that the repository has been shutdown.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository has been shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ConfigurationReset">
+ <summary>
+ Event to notify that the repository has had its configuration reset.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration reset.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been
+ reset to default.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ConfigurationChanged">
+ <summary>
+ Event to notify that the repository has had its configuration changed.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration changed.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Properties">
+ <summary>
+ Repository specific properties
+ </summary>
+ <value>
+ Repository specific properties
+ </value>
+ <remarks>
+ These properties can be specified on a repository specific basis
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.IBasicRepositoryConfigurator">
+ <summary>
+ Basic Configurator interface for repositories
+ </summary>
+ <remarks>
+ <para>
+ Interface used by basic configurator to configure a <see cref="T:log4net.Repository.ILoggerRepository"/>
+ with a default <see cref="T:log4net.Appender.IAppender"/>.
+ </para>
+ <para>
+ A <see cref="T:log4net.Repository.ILoggerRepository"/> should implement this interface to support
+ configuration by the <see cref="T:log4net.Config.BasicConfigurator"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the repository using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ <remarks>
+ <para>
+ Configure the repository to route all logging events to the
+ specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.IXmlRepositoryConfigurator">
+ <summary>
+ Configure repository using XML
+ </summary>
+ <remarks>
+ <para>
+ Interface used by Xml configurator to configure a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ <para>
+ A <see cref="T:log4net.Repository.ILoggerRepository"/> should implement this interface to support
+ configuration by the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the repository using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ <remarks>
+ <para>
+ The schema for the XML configuration data is defined by
+ the implementation.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Util.PropertiesDictionary)">
+ <summary>
+ Construct with properties
+ </summary>
+ <param name="properties">The properties to pass to this repository.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Construct with a logger factory
+ </summary>
+ <param name="loggerFactory">The factory to use to create new logger instances.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class with
+ the specified <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Util.PropertiesDictionary,log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Construct with properties and a logger factory
+ </summary>
+ <param name="properties">The properties to pass to this repository.</param>
+ <param name="loggerFactory">The factory to use to create new logger instances.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class with
+ the specified <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Exists(System.String)">
+ <summary>
+ Test if a logger exists
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Check if the named logger exists in the hierarchy. If so return
+ its reference, otherwise returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers in the hierarchy as an Array
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers in the hierarchy as an Array.
+ The root logger is <b>not</b> included in the returned
+ enumeration.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String)">
+ <summary>
+ Return a new logger instance named as the first parameter using
+ the default factory.
+ </summary>
+ <remarks>
+ <para>
+ Return a new logger instance named as the first parameter using
+ the default factory.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Shutdown">
+ <summary>
+ Shutting down a hierarchy will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </summary>
+ <remarks>
+ <para>
+ Shutting down a hierarchy will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </para>
+ <para>
+ Some appenders need to be closed before the
+ application exists. Otherwise, pending logging events might be
+ lost.
+ </para>
+ <para>
+ The <c>Shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.ResetConfiguration">
+ <summary>
+ Reset all values contained in this hierarchy instance to their default.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this hierarchy instance to their
+ default. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logEvent through this hierarchy.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetAppenders">
+ <summary>
+ Returns all the Appenders that are currently configured
+ </summary>
+ <returns>An array containing all the currently configured appenders</returns>
+ <remarks>
+ <para>
+ Returns all the <see cref="T:log4net.Appender.IAppender"/> instances that are currently configured.
+ All the loggers are searched for appenders. The appenders may also be containers
+ for appenders and these are also searched for additional loggers.
+ </para>
+ <para>
+ The list returned is unordered but does not contain duplicates.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.CollectAppender(System.Collections.ArrayList,log4net.Appender.IAppender)">
+ <summary>
+ Collect the appenders from an <see cref="T:log4net.Core.IAppenderAttachable"/>.
+ The appender may also be a container.
+ </summary>
+ <param name="appenderList"></param>
+ <param name="appender"></param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.CollectAppenders(System.Collections.ArrayList,log4net.Core.IAppenderAttachable)">
+ <summary>
+ Collect the appenders from an <see cref="T:log4net.Core.IAppenderAttachable"/> container
+ </summary>
+ <param name="appenderList"></param>
+ <param name="container"></param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.log4net#Repository#IBasicRepositoryConfigurator#Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the log4net system using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.BasicRepositoryConfigure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the log4net system using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ <remarks>
+ <para>
+ This method provides the same functionality as the
+ <see cref="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)"/> method implemented
+ on this object, but it is protected and therefore can be called by subclasses.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.log4net#Repository#IXmlRepositoryConfigurator#Configure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the log4net system using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.XmlRepositoryConfigure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the log4net system using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ <remarks>
+ <para>
+ This method provides the same functionality as the
+ <see cref="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)"/> method implemented
+ on this object, but it is protected and therefore can be called by subclasses.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.IsDisabled(log4net.Core.Level)">
+ <summary>
+ Test if this hierarchy is disabled for the specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="level">The level to check against.</param>
+ <returns>
+ <c>true</c> if the repository is disabled for the level argument, <c>false</c> otherwise.
+ </returns>
+ <remarks>
+ <para>
+ If this hierarchy has not been configured then this method will
+ always return <c>true</c>.
+ </para>
+ <para>
+ This method will return <c>true</c> if this repository is
+ disabled for <c>level</c> object passed as parameter and
+ <c>false</c> otherwise.
+ </para>
+ <para>
+ See also the <see cref="P:log4net.Repository.ILoggerRepository.Threshold"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Clear">
+ <summary>
+ Clear all logger definitions from the internal hashtable
+ </summary>
+ <remarks>
+ <para>
+ This call will clear all logger definitions from the internal
+ hashtable. Invoking this method will irrevocably mess up the
+ logger hierarchy.
+ </para>
+ <para>
+ You should <b>really</b> know what you are doing before
+ invoking this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String,log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Return a new logger instance named as the first parameter using
+ <paramref name="factory"/>.
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <param name="factory">The factory that will make the new logger instance</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated by the
+ <paramref name="factory"/> parameter and linked with its existing
+ ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.OnLoggerCreationEvent(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Sends a logger creation event to all registered listeners
+ </summary>
+ <param name="logger">The newly created logger</param>
+ <remarks>
+ Raises the logger creation event.
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.UpdateParents(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Updates all the parents of the specified logger
+ </summary>
+ <param name="log">The logger to update the parents for</param>
+ <remarks>
+ <para>
+ This method loops through all the <i>potential</i> parents of
+ <paramref name="log"/>. There 3 possible cases:
+ </para>
+ <list type="number">
+ <item>
+ <term>No entry for the potential parent of <paramref name="log"/> exists</term>
+ <description>
+ We create a ProvisionNode for this potential
+ parent and insert <paramref name="log"/> in that provision node.
+ </description>
+ </item>
+ <item>
+ <term>The entry is of type Logger for the potential parent.</term>
+ <description>
+ The entry is <paramref name="log"/>'s nearest existing parent. We
+ update <paramref name="log"/>'s parent field with this entry. We also break from
+ he loop because updating our parent's parent is our parent's
+ responsibility.
+ </description>
+ </item>
+ <item>
+ <term>The entry is of type ProvisionNode for this potential parent.</term>
+ <description>
+ We add <paramref name="log"/> to the list of children for this
+ potential parent.
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.UpdateChildren(log4net.Repository.Hierarchy.ProvisionNode,log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Replace a <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> with a <see cref="T:log4net.Repository.Hierarchy.Logger"/> in the hierarchy.
+ </summary>
+ <param name="pn"></param>
+ <param name="log"></param>
+ <remarks>
+ <para>
+ We update the links for all the children that placed themselves
+ in the provision node 'pn'. The second argument 'log' is a
+ reference for the newly created Logger, parent of all the
+ children in 'pn'.
+ </para>
+ <para>
+ We loop on all the children 'c' in 'pn'.
+ </para>
+ <para>
+ If the child 'c' has been already linked to a child of
+ 'log' then there is no need to update 'c'.
+ </para>
+ <para>
+ Otherwise, we set log's parent field to c's parent and set
+ c's parent field to log.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.AddLevel(log4net.Repository.Hierarchy.Hierarchy.LevelEntry)">
+ <summary>
+ Define or redefine a Level using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </summary>
+ <param name="levelEntry">the level values</param>
+ <remarks>
+ <para>
+ Define or redefine a Level using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </para>
+ <para>
+ Supports setting levels via the configuration file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.AddProperty(log4net.Repository.Hierarchy.Hierarchy.PropertyEntry)">
+ <summary>
+ Set a Property using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </summary>
+ <param name="propertyEntry">the property value</param>
+ <remarks>
+ <para>
+ Set a Property using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument.
+ </para>
+ <para>
+ Supports setting property values via the configuration file.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent">
+ <summary>
+ Event used to notify that a logger has been created.
+ </summary>
+ <remarks>
+ <para>
+ Event raised when a logger is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.EmittedNoAppenderWarning">
+ <summary>
+ Has no appender warning been emitted
+ </summary>
+ <remarks>
+ <para>
+ Flag to indicate if we have already issued a warning
+ about not having an appender warning.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.Root">
+ <summary>
+ Get the root of this hierarchy
+ </summary>
+ <remarks>
+ <para>
+ Get the root of this hierarchy.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LoggerFactory">
+ <summary>
+ Gets or sets the default <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/> instance.
+ </summary>
+ <value>The default <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/></value>
+ <remarks>
+ <para>
+ The logger factory is used to create logger instances.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry">
+ <summary>
+ A class to hold the value, name and display name for a level
+ </summary>
+ <remarks>
+ <para>
+ A class to hold the value, name and display name for a level
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.ToString">
+ <summary>
+ Override <c>Object.ToString</c> to return sensible debug info
+ </summary>
+ <returns>string info about this object</returns>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.Value">
+ <summary>
+ Value of the level
+ </summary>
+ <remarks>
+ <para>
+ If the value is not set (defaults to -1) the value will be looked
+ up for the current level with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.Name">
+ <summary>
+ Name of the level
+ </summary>
+ <value>
+ The name of the level
+ </value>
+ <remarks>
+ <para>
+ The name of the level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.DisplayName">
+ <summary>
+ Display name for the level
+ </summary>
+ <value>
+ The display name of the level
+ </value>
+ <remarks>
+ <para>
+ The display name of the level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry">
+ <summary>
+ A class to hold the key and data for a property set in the config file
+ </summary>
+ <remarks>
+ <para>
+ A class to hold the key and data for a property set in the config file
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.ToString">
+ <summary>
+ Override <c>Object.ToString</c> to return sensible debug info
+ </summary>
+ <returns>string info about this object</returns>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.Key">
+ <summary>
+ Property Key
+ </summary>
+ <value>
+ Property Key
+ </value>
+ <remarks>
+ <para>
+ Property Key.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.Value">
+ <summary>
+ Property Value
+ </summary>
+ <value>
+ Property Value
+ </value>
+ <remarks>
+ <para>
+ Property Value.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerKey">
+ <summary>
+ Used internally to accelerate hash table searches.
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to improve performance of
+ string keyed hashtables.
+ </para>
+ <para>
+ The hashcode of the string is cached for reuse.
+ The string is stored as an interned value.
+ When comparing two <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> objects for equality
+ the reference equality of the interned strings is compared.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.#ctor(System.String)">
+ <summary>
+ Construct key with string name
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> class
+ with the specified name.
+ </para>
+ <para>
+ Stores the hashcode of the string and interns
+ the string key to optimize comparisons.
+ </para>
+ <note>
+ The Compact Framework 1.0 the <see cref="M:System.String.Intern(System.String)"/>
+ method does not work. On the Compact Framework
+ the string keys are not interned nor are they
+ compared by reference.
+ </note>
+ </remarks>
+ <param name="name">The name of the logger.</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.GetHashCode">
+ <summary>
+ Returns a hash code for the current instance.
+ </summary>
+ <returns>A hash code for the current instance.</returns>
+ <remarks>
+ <para>
+ Returns the cached hashcode.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.Equals(System.Object)">
+ <summary>
+ Determines whether two <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> instances
+ are equal.
+ </summary>
+ <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/>.</param>
+ <returns>
+ <c>true</c> if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares the references of the interned strings.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.ProvisionNode">
+ <summary>
+ Provision nodes are used where no logger instance has been specified
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> instances are used in the
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> when there is no specified
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> for that node.
+ </para>
+ <para>
+ A provision node holds a list of child loggers on behalf of
+ a logger that does not exist.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.ProvisionNode.#ctor(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Create a new provision node with child node
+ </summary>
+ <param name="log">A child logger to add to this node.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> class
+ with the specified child logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.RootLogger">
+ <summary>
+ The <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> sits at the root of the logger hierarchy tree.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> is a regular <see cref="T:log4net.Repository.Hierarchy.Logger"/> except
+ that it provides several guarantees.
+ </para>
+ <para>
+ First, it cannot be assigned a <c>null</c>
+ level. Second, since the root logger cannot have a parent, the
+ <see cref="P:log4net.Repository.Hierarchy.RootLogger.EffectiveLevel"/> property always returns the value of the
+ level field without walking the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.RootLogger.#ctor(log4net.Core.Level)">
+ <summary>
+ Construct a <see cref="T:log4net.Repository.Hierarchy.RootLogger"/>
+ </summary>
+ <param name="level">The level to assign to the root logger.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> class with
+ the specified logging level.
+ </para>
+ <para>
+ The root logger names itself as "root". However, the root
+ logger cannot be retrieved by name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.RootLogger.EffectiveLevel">
+ <summary>
+ Gets the assigned level value without walking the logger hierarchy.
+ </summary>
+ <value>The assigned level value without walking the logger hierarchy.</value>
+ <remarks>
+ <para>
+ Because the root logger cannot have a parent and its level
+ must not be <c>null</c> this property just returns the
+ value of <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.RootLogger.Level">
+ <summary>
+ Gets or sets the assigned <see cref="P:log4net.Repository.Hierarchy.RootLogger.Level"/> for the root logger.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.RootLogger.Level"/> of the root logger.
+ </value>
+ <remarks>
+ <para>
+ Setting the level of the root logger to a <c>null</c> reference
+ may have catastrophic results. We prevent this here.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.XmlHierarchyConfigurator">
+ <summary>
+ Initializes the log4net environment using an XML DOM.
+ </summary>
+ <remarks>
+ <para>
+ Configures a <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> using an XML DOM.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.#ctor(log4net.Repository.Hierarchy.Hierarchy)">
+ <summary>
+ Construct the configurator for a hierarchy
+ </summary>
+ <param name="hierarchy">The hierarchy to build.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.XmlHierarchyConfigurator"/> class
+ with the specified <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configure the hierarchy by parsing a DOM tree of XML elements.
+ </summary>
+ <param name="element">The root element to parse.</param>
+ <remarks>
+ <para>
+ Configure the hierarchy by parsing a DOM tree of XML elements.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.FindAppenderByReference(System.Xml.XmlElement)">
+ <summary>
+ Parse appenders by IDREF.
+ </summary>
+ <param name="appenderRef">The appender ref element.</param>
+ <returns>The instance of the appender that the ref refers to.</returns>
+ <remarks>
+ <para>
+ Parse an XML element that represents an appender and return
+ the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(System.Xml.XmlElement)">
+ <summary>
+ Parses an appender element.
+ </summary>
+ <param name="appenderElement">The appender element.</param>
+ <returns>The appender instance or <c>null</c> when parsing failed.</returns>
+ <remarks>
+ <para>
+ Parse an XML element that represents an appender and return
+ the appender instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseLogger(System.Xml.XmlElement)">
+ <summary>
+ Parses a logger element.
+ </summary>
+ <param name="loggerElement">The logger element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseRoot(System.Xml.XmlElement)">
+ <summary>
+ Parses the root logger element.
+ </summary>
+ <param name="rootElement">The root element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents the root logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseChildrenOfLoggerElement(System.Xml.XmlElement,log4net.Repository.Hierarchy.Logger,System.Boolean)">
+ <summary>
+ Parses the children of a logger element.
+ </summary>
+ <param name="catElement">The category element.</param>
+ <param name="log">The logger instance.</param>
+ <param name="isRoot">Flag to indicate if the logger is the root logger.</param>
+ <remarks>
+ <para>
+ Parse the child elements of a &lt;logger&gt; element.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseRenderer(System.Xml.XmlElement)">
+ <summary>
+ Parses an object renderer.
+ </summary>
+ <param name="element">The renderer element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a renderer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseLevel(System.Xml.XmlElement,log4net.Repository.Hierarchy.Logger,System.Boolean)">
+ <summary>
+ Parses a level element.
+ </summary>
+ <param name="element">The level element.</param>
+ <param name="log">The logger object to set the level on.</param>
+ <param name="isRoot">Flag to indicate if the logger is the root logger.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.SetParameter(System.Xml.XmlElement,System.Object)">
+ <summary>
+ Sets a parameter on an object.
+ </summary>
+ <param name="element">The parameter element.</param>
+ <param name="target">The object to set the parameter on.</param>
+ <remarks>
+ The parameter name must correspond to a writable property
+ on the object. The value of the parameter is a string,
+ therefore this function will attempt to set a string
+ property first. If unable to set a string property it
+ will inspect the property and its argument type. It will
+ attempt to call a static method called <c>Parse</c> on the
+ type of the property. This method will take a single
+ string argument and return a value that can be used to
+ set the property.
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.HasAttributesOrElements(System.Xml.XmlElement)">
+ <summary>
+ Test if an element has no attributes or child elements
+ </summary>
+ <param name="element">the element to inspect</param>
+ <returns><c>true</c> if the element has any attributes or child elements, <c>false</c> otherwise</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.IsTypeConstructible(System.Type)">
+ <summary>
+ Test if a <see cref="T:System.Type"/> is constructible with <c>Activator.CreateInstance</c>.
+ </summary>
+ <param name="type">the type to inspect</param>
+ <returns><c>true</c> if the type is creatable using a default constructor, <c>false</c> otherwise</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.FindMethodInfo(System.Type,System.String)">
+ <summary>
+ Look for a method on the <paramref name="targetType"/> that matches the <paramref name="name"/> supplied
+ </summary>
+ <param name="targetType">the type that has the method</param>
+ <param name="name">the name of the method</param>
+ <returns>the method info found</returns>
+ <remarks>
+ <para>
+ The method must be a public instance method on the <paramref name="targetType"/>.
+ The method must be named <paramref name="name"/> or "Add" followed by <paramref name="name"/>.
+ The method must take a single parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ConvertStringTo(System.Type,System.String)">
+ <summary>
+ Converts a string value to a target type.
+ </summary>
+ <param name="type">The type of object to convert the string to.</param>
+ <param name="value">The string value to use as the value of the object.</param>
+ <returns>
+ <para>
+ An object of type <paramref name="type"/> with value <paramref name="value"/> or
+ <c>null</c> when the conversion could not be performed.
+ </para>
+ </returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.CreateObjectFromXml(System.Xml.XmlElement,System.Type,System.Type)">
+ <summary>
+ Creates an object as specified in XML.
+ </summary>
+ <param name="element">The XML element that contains the definition of the object.</param>
+ <param name="defaultTargetType">The object type to use if not explicitly specified.</param>
+ <param name="typeConstraint">The type that the returned object must be or must inherit from.</param>
+ <returns>The object or <c>null</c></returns>
+ <remarks>
+ <para>
+ Parse an XML element and create an object instance based on the configuration
+ data.
+ </para>
+ <para>
+ The type of the instance may be specified in the XML. If not
+ specified then the <paramref name="defaultTargetType"/> is used
+ as the type. However the type is specified it must support the
+ <paramref name="typeConstraint"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.m_appenderBag">
+ <summary>
+ key: appenderName, value: appender.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.m_hierarchy">
+ <summary>
+ The Hierarchy being configured.
+ </summary>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryShutdownEventHandler">
+ <summary>
+ Delegate used to handle logger repository shutdown event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that is shutting down.</param>
+ <param name="e">Empty event args</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository shutdown event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryConfigurationResetEventHandler">
+ <summary>
+ Delegate used to handle logger repository configuration reset event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that has had its configuration reset.</param>
+ <param name="e">Empty event args</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository configuration reset event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryConfigurationChangedEventHandler">
+ <summary>
+ Delegate used to handle event notifications for logger repository configuration changes.
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that has had its configuration changed.</param>
+ <param name="e">Empty event arguments.</param>
+ <remarks>
+ <para>
+ Delegate used to handle event notifications for logger repository configuration changes.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.AppDomainPatternConverter">
+ <summary>
+ Write the name of the current AppDomain to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the name of the current AppDomain to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.AppDomainPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the name of the current AppDomain to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes name of the current AppDomain to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.DatePatternConverter">
+ <summary>
+ Write the current date to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the current date and time to the writer as a string.
+ </para>
+ <para>
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the formatting of the date. The following values are allowed:
+ <list type="definition">
+ <listheader>
+ <term>Option value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>ISO8601</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> formatter.
+ Formats using the <c>"yyyy-MM-dd HH:mm:ss,fff"</c> pattern.
+ </description>
+ </item>
+ <item>
+ <term>DATE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> formatter.
+ Formats using the <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example, <c>"06 Nov 1994 15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>ABSOLUTE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/> formatter.
+ Formats using the <c>"HH:mm:ss,fff"</c> for example, <c>"15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ Any other pattern string uses the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> formatter.
+ This formatter passes the pattern string to the <see cref="T:System.DateTime"/>
+ <see cref="M:System.DateTime.ToString(System.String)"/> method.
+ For details on valid patterns see
+ <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">DateTimeFormatInfo Class</a>.
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ The date and time is in the local time zone and is rendered in that zone.
+ To output the time in Universal time see <see cref="T:log4net.Util.PatternStringConverters.UtcDatePatternConverter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.DatePatternConverter.m_dateFormatter">
+ <summary>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.DatePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current date to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Pass the current date and time to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The date and time passed is in the local time zone.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.EnvironmentPatternConverter">
+ <summary>
+ Write an environment variable to the output
+ </summary>
+ <remarks>
+ <para>
+ Write an environment variable to the output writer.
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the name of the variable to output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.EnvironmentPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write an environment variable to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes the environment variable to the output <paramref name="writer"/>.
+ The name of the environment variable to output must be set
+ using the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.IdentityPatternConverter">
+ <summary>
+ Write the current thread identity to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current thread identity to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.IdentityPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current thread identity to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes the current thread identity to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.LiteralPatternConverter">
+ <summary>
+ Pattern converter for literal string instances in the pattern
+ </summary>
+ <remarks>
+ <para>
+ Writes the literal string value specified in the
+ <see cref="P:log4net.Util.PatternConverter.Option"/> property to
+ the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.SetNext(log4net.Util.PatternConverter)">
+ <summary>
+ Set the next converter in the chain
+ </summary>
+ <param name="pc">The next pattern converter in the chain</param>
+ <returns>The next pattern converter</returns>
+ <remarks>
+ <para>
+ Special case the building of the pattern converter chain
+ for <see cref="T:log4net.Util.PatternStringConverters.LiteralPatternConverter"/> instances. Two adjacent
+ literals in the pattern can be represented by a single combined
+ pattern converter. This implementation detects when a
+ <see cref="T:log4net.Util.PatternStringConverters.LiteralPatternConverter"/> is added to the chain
+ after this converter and combines its value with this converter's
+ literal value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.Format(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the literal to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, not set</param>
+ <remarks>
+ <para>
+ Override the formatting behavior to ignore the FormattingInfo
+ because we have a literal instead.
+ </para>
+ <para>
+ Writes the value of <see cref="P:log4net.Util.PatternConverter.Option"/>
+ to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Convert this pattern into the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, not set</param>
+ <remarks>
+ <para>
+ This method is not used.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.NewLinePatternConverter">
+ <summary>
+ Writes a newline to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the system dependent line terminator to the output.
+ This behavior can be overridden by setting the <see cref="P:log4net.Util.PatternConverter.Option"/>:
+ </para>
+ <list type="definition">
+ <listheader>
+ <term>Option Value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>DOS</term>
+ <description>DOS or Windows line terminator <c>"\r\n"</c></description>
+ </item>
+ <item>
+ <term>UNIX</term>
+ <description>UNIX line terminator <c>"\n"</c></description>
+ </item>
+ </list>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.ProcessIdPatternConverter">
+ <summary>
+ Write the current process ID to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current process ID to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.ProcessIdPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current process ID to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write the current process ID to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.PropertyPatternConverter">
+ <summary>
+ Property pattern converter
+ </summary>
+ <remarks>
+ <para>
+ This pattern converter reads the thread and global properties.
+ The thread properties take priority over global properties.
+ See <see cref="P:log4net.ThreadContext.Properties"/> for details of the
+ thread properties. See <see cref="P:log4net.GlobalContext.Properties"/> for
+ details of the global properties.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is specified then that will be used to
+ lookup a single property. If no <see cref="P:log4net.Util.PatternConverter.Option"/> is specified
+ then all properties will be dumped as a list of key value pairs.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.PropertyPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the property value to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.RandomStringPatternConverter">
+ <summary>
+ A Pattern converter that generates a string of random characters
+ </summary>
+ <remarks>
+ <para>
+ The converter generates a string of random characters. By default
+ the string is length 4. This can be changed by setting the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ to the string value of the length required.
+ </para>
+ <para>
+ The random characters in the string are limited to uppercase letters
+ and numbers only.
+ </para>
+ <para>
+ The random number generator used by this class is not cryptographically secure.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.RandomStringPatternConverter.s_random">
+ <summary>
+ Shared random number generator
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.RandomStringPatternConverter.m_length">
+ <summary>
+ Length of random string to generate. Default length 4.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write a randoim string to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write a randoim string to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.UserNamePatternConverter">
+ <summary>
+ Write the current threads username to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current threads username to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.UserNamePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current threads username to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write the current threads username to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.UtcDatePatternConverter">
+ <summary>
+ Write the UTC date time to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the current date and time in Universal time.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/> for details on the date pattern syntax.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.UtcDatePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current date and time to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Pass the current date and time to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The date is in Universal time when it is rendered.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.BooleanConverter">
+ <summary>
+ Type converter for Boolean.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <c>bool</c> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.BooleanConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.BooleanConverter.ConvertFrom(System.Object)">
+ <summary>
+ Convert the source object to the type supported by this object
+ </summary>
+ <param name="source">the object to convert</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Boolean.Parse(System.String)"/> method to convert the
+ <see cref="T:System.String"/> argument to a <see cref="T:System.Boolean"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.BooleanConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ <summary>
+ Exception base type for conversion errors.
+ </summary>
+ <remarks>
+ <para>
+ This type extends <see cref="T:System.ApplicationException"/>. It
+ does not add any new functionality but does differentiate the
+ type of exception being thrown.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with the specified message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.String,System.Exception)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with the specified message and inner exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.Create(System.Type,System.Object)">
+ <summary>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </summary>
+ <param name="destinationType">The conversion destination type.</param>
+ <param name="sourceValue">The value to convert.</param>
+ <returns>An instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/>.</returns>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.Create(System.Type,System.Object,System.Exception)">
+ <summary>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </summary>
+ <param name="destinationType">The conversion destination type.</param>
+ <param name="sourceValue">The value to convert.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <returns>An instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/>.</returns>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.ConverterRegistry">
+ <summary>
+ Register of type converters for specific types.
+ </summary>
+ <remarks>
+ <para>
+ Maintains a registry of type converters used to convert between
+ types.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Object)"/> and
+ <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Type)"/> methods to register new converters.
+ The <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertTo(System.Type,System.Type)"/> and <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertFrom(System.Type)"/> methods
+ lookup appropriate converters to use.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ <remarks>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConverterRegistry"/> class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.#cctor">
+ <summary>
+ Static constructor.
+ </summary>
+ <remarks>
+ <para>
+ This constructor defines the intrinsic type converters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Object)">
+ <summary>
+ Adds a converter for a specific type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <param name="converter">The type converter to use to convert to the destination type.</param>
+ <remarks>
+ <para>
+ Adds a converter instance for a specific type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Type)">
+ <summary>
+ Adds a converter for a specific type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <param name="converterType">The type of the type converter to use to convert to the destination type.</param>
+ <remarks>
+ <para>
+ Adds a converter <see cref="T:System.Type"/> for a specific type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertTo(System.Type,System.Type)">
+ <summary>
+ Gets the type converter to use to convert values to the destination type.
+ </summary>
+ <param name="sourceType">The type being converted from.</param>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ Gets the type converter to use to convert values to the destination type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertFrom(System.Type)">
+ <summary>
+ Gets the type converter to use to convert values to the destination type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ Gets the type converter to use to convert values to the destination type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConverterFromAttribute(System.Type)">
+ <summary>
+ Lookups the type converter to use as specified by the attributes on the
+ destination type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.CreateConverterInstance(System.Type)">
+ <summary>
+ Creates the instance of the type converter.
+ </summary>
+ <param name="converterType">The type of the type converter.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ The type specified for the type converter must implement
+ the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/> or <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces
+ and must have a public default (no argument) constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.ConverterRegistry.s_type2converter">
+ <summary>
+ Mapping from <see cref="T:System.Type"/> to type converter.
+ </summary>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.EncodingConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Text.Encoding"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Text.Encoding"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.EncodingConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.EncodingConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to an encoding</param>
+ <returns>the encoding</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Text.Encoding.GetEncoding(System.String)"/> method to
+ convert the <see cref="T:System.String"/> argument to an <see cref="T:System.Text.Encoding"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.EncodingConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IConvertTo">
+ <summary>
+ Interface supported by type converters
+ </summary>
+ <remarks>
+ <para>
+ This interface supports conversion from a single type to arbitrary types.
+ See <see cref="T:log4net.Util.TypeConverters.TypeConverterAttribute"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertTo.CanConvertTo(System.Type)">
+ <summary>
+ Returns whether this converter can convert the object to the specified type
+ </summary>
+ <param name="targetType">A Type that represents the type you want to convert to</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Test if the type supported by this converter can be converted to the
+ <paramref name="targetType"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertTo.ConvertTo(System.Object,System.Type)">
+ <summary>
+ Converts the given value object to the specified type, using the arguments
+ </summary>
+ <param name="source">the object to convert</param>
+ <param name="targetType">The Type to convert the value parameter to</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Converts the <paramref name="source"/> (which must be of the type supported
+ by this converter) to the <paramref name="targetType"/> specified..
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IPAddressConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Net.IPAddress"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Net.IPAddress"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IPAddressConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IPAddressConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to an IPAddress</param>
+ <returns>the IPAddress</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Net.IPAddress.Parse(System.String)"/> method to convert the
+ <see cref="T:System.String"/> argument to an <see cref="T:System.Net.IPAddress"/>.
+ If that fails then the string is resolved as a DNS hostname.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.IPAddressConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.IPAddressConverter.validIpAddressChars">
+ <summary>
+ Valid characters in an IPv4 or IPv6 address string. (Does not support subnets)
+ </summary>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.PatternLayoutConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:log4net.Layout.PatternLayout"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:log4net.Layout.PatternLayout"/> type.
+ </para>
+ <para>
+ The string is used as the <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/>
+ of the <see cref="T:log4net.Layout.PatternLayout"/>.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternLayoutConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternLayoutConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a PatternLayout</param>
+ <returns>the PatternLayout</returns>
+ <remarks>
+ <para>
+ Creates and returns a new <see cref="T:log4net.Layout.PatternLayout"/> using
+ the <paramref name="source"/> <see cref="T:System.String"/> as the
+ <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.PatternLayoutConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.PatternStringConverter">
+ <summary>
+ Convert between string and <see cref="T:log4net.Util.PatternString"/>
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:log4net.Util.PatternString"/> type,
+ and from a <see cref="T:log4net.Util.PatternString"/> type to a string.
+ </para>
+ <para>
+ The string is used as the <see cref="P:log4net.Util.PatternString.ConversionPattern"/>
+ of the <see cref="T:log4net.Util.PatternString"/>.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertTo(System.Type)">
+ <summary>
+ Can the target type be converted to the type supported by this object
+ </summary>
+ <param name="targetType">A <see cref="T:System.Type"/> that represents the type you want to convert to</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="targetType"/> is
+ assignable from a <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.ConvertTo(System.Object,System.Type)">
+ <summary>
+ Converts the given value object to the specified type, using the arguments
+ </summary>
+ <param name="source">the object to convert</param>
+ <param name="targetType">The Type to convert the value parameter to</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Util.PatternString.Format"/> method to convert the
+ <see cref="T:log4net.Util.PatternString"/> argument to a <see cref="T:System.String"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ <paramref name="targetType"/>. To check for this condition use the
+ <see cref="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertTo(System.Type)"/> method.
+ </exception>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a PatternString</param>
+ <returns>the PatternString</returns>
+ <remarks>
+ <para>
+ Creates and returns a new <see cref="T:log4net.Util.PatternString"/> using
+ the <paramref name="source"/> <see cref="T:System.String"/> as the
+ <see cref="P:log4net.Util.PatternString.ConversionPattern"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.TypeConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Type"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Type"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a Type</param>
+ <returns>the Type</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Type.GetType(System.String,System.Boolean)"/> method to convert the
+ <see cref="T:System.String"/> argument to a <see cref="T:System.Type"/>.
+ Additional effort is made to locate partially specified types
+ by searching the loaded assemblies.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.TypeConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.TypeConverterAttribute">
+ <summary>
+ Attribute used to associate a type converter
+ </summary>
+ <remarks>
+ <para>
+ Class and Interface level attribute that specifies a type converter
+ to use with the associated type.
+ </para>
+ <para>
+ To associate a type converter with a target type apply a
+ <c>TypeConverterAttribute</c> to the target type. Specify the
+ type of the type converter on the attribute.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.TypeConverterAttribute.m_typeName">
+ <summary>
+ The string type name of the type converter
+ </summary>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor(System.String)">
+ <summary>
+ Create a new type converter attribute for the specified type name
+ </summary>
+ <param name="typeName">The string type name of the type converter</param>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor(System.Type)">
+ <summary>
+ Create a new type converter attribute for the specified type
+ </summary>
+ <param name="converterType">The type of the type converter</param>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TypeConverters.TypeConverterAttribute.ConverterTypeName">
+ <summary>
+ The string type name of the type converter
+ </summary>
+ <value>
+ The string type name of the type converter
+ </value>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.AppenderAttachedImpl">
+ <summary>
+ A straightforward implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ This is the default implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/>
+ interface. Implementors of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ should aggregate an instance of this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.AppenderAttachedImpl"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AppendLoopOnAppenders(log4net.Core.LoggingEvent)">
+ <summary>
+ Append on on all attached appenders.
+ </summary>
+ <param name="loggingEvent">The event being logged.</param>
+ <returns>The number of appenders called.</returns>
+ <remarks>
+ <para>
+ Calls the <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method on all
+ attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AppendLoopOnAppenders(log4net.Core.LoggingEvent[])">
+ <summary>
+ Append on on all attached appenders.
+ </summary>
+ <param name="loggingEvents">The array of events being logged.</param>
+ <returns>The number of appenders called.</returns>
+ <remarks>
+ <para>
+ Calls the <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method on all
+ attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.CallAppend(log4net.Appender.IAppender,log4net.Core.LoggingEvent[])">
+ <summary>
+ Calls the DoAppende method on the <see cref="T:log4net.Appender.IAppender"/> with
+ the <see cref="T:log4net.Core.LoggingEvent"/> objects supplied.
+ </summary>
+ <param name="appender">The appender</param>
+ <param name="loggingEvents">The events</param>
+ <remarks>
+ <para>
+ If the <paramref name="appender"/> supports the <see cref="T:log4net.Appender.IBulkAppender"/>
+ interface then the <paramref name="loggingEvents"/> will be passed
+ through using that interface. Otherwise the <see cref="T:log4net.Core.LoggingEvent"/>
+ objects in the array will be passed one at a time.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Attaches an appender.
+ </summary>
+ <param name="newAppender">The appender to add.</param>
+ <remarks>
+ <para>
+ If the appender is already in the list it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.GetAppender(System.String)">
+ <summary>
+ Gets an attached appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to get.</param>
+ <returns>
+ The appender with the name specified, or <c>null</c> if no appender with the
+ specified name is found.
+ </returns>
+ <remarks>
+ <para>
+ Lookup an attached appender by name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAllAppenders">
+ <summary>
+ Removes all attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ Removes and closes all attached appenders
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of attached appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.AppenderAttachedImpl.m_appenderList">
+ <summary>
+ List of appenders
+ </summary>
+ </member>
+ <member name="F:log4net.Util.AppenderAttachedImpl.m_appenderArray">
+ <summary>
+ Array of appenders, used to cache the m_appenderList
+ </summary>
+ </member>
+ <member name="P:log4net.Util.AppenderAttachedImpl.Appenders">
+ <summary>
+ Gets all attached appenders.
+ </summary>
+ <returns>
+ A collection of attached appenders, or <c>null</c> if there
+ are no attached appenders.
+ </returns>
+ <remarks>
+ <para>
+ The read only collection of all currently attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CompositeProperties">
+ <summary>
+ This class aggregates several PropertiesDictionary collections together.
+ </summary>
+ <remarks>
+ <para>
+ Provides a dictionary style lookup over an ordered list of
+ <see cref="T:log4net.Util.PropertiesDictionary"/> collections.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.CompositeProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.Add(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Add a Properties Dictionary to this composite collection
+ </summary>
+ <param name="properties">the properties to add</param>
+ <remarks>
+ <para>
+ Properties dictionaries added first take precedence over dictionaries added
+ later.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.Flatten">
+ <summary>
+ Flatten this composite collection into a single properties dictionary
+ </summary>
+ <returns>the flattened dictionary</returns>
+ <remarks>
+ <para>
+ Reduces the collection of ordered dictionaries to a single dictionary
+ containing the resultant values for the keys.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CompositeProperties.Item(System.String)">
+ <summary>
+ Gets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Looks up the value for the <paramref name="key"/> specified.
+ The <see cref="T:log4net.Util.PropertiesDictionary"/> collections are searched
+ in the order in which they were added to this collection. The value
+ returned is the value held by the first collection that contains
+ the specified key.
+ </para>
+ <para>
+ If none of the collections contain the specified key then
+ <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ContextPropertiesBase">
+ <summary>
+ Base class for Context Properties implementations
+ </summary>
+ <remarks>
+ <para>
+ This class defines a basic property get set accessor
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="P:log4net.Util.ContextPropertiesBase.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the value of a property
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CountingQuietTextWriter">
+ <summary>
+ Subclass of <see cref="T:log4net.Util.QuietTextWriter"/> that maintains a count of
+ the number of bytes written.
+ </summary>
+ <remarks>
+ <para>
+ This writer counts the number of bytes written.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.QuietTextWriter">
+ <summary>
+ <see cref="T:System.IO.TextWriter"/> that does not leak exceptions
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Util.QuietTextWriter"/> does not throw exceptions when things go wrong.
+ Instead, it delegates error handling to its <see cref="T:log4net.Core.IErrorHandler"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.TextWriterAdapter">
+ <summary>
+ Adapter that extends <see cref="T:System.IO.TextWriter"/> and forwards all
+ messages to an instance of <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Adapter that extends <see cref="T:System.IO.TextWriter"/> and forwards all
+ messages to an instance of <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.TextWriterAdapter.m_writer">
+ <summary>
+ The writer to forward messages to
+ </summary>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.#ctor(System.IO.TextWriter)">
+ <summary>
+ Create an instance of <see cref="T:log4net.Util.TextWriterAdapter"/> that forwards all
+ messages to a <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to forward to</param>
+ <remarks>
+ <para>
+ Create an instance of <see cref="T:log4net.Util.TextWriterAdapter"/> that forwards all
+ messages to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Close">
+ <summary>
+ Closes the writer and releases any system resources associated with the writer
+ </summary>
+ <remarks>
+ <para>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Dispose(System.Boolean)">
+ <summary>
+ Dispose this writer
+ </summary>
+ <param name="disposing">flag indicating if we are being disposed</param>
+ <remarks>
+ <para>
+ Dispose this writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Flush">
+ <summary>
+ Flushes any buffered output
+ </summary>
+ <remarks>
+ <para>
+ Clears all buffers for the writer and causes any buffered data to be written
+ to the underlying device
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.Char)">
+ <summary>
+ Writes a character to the wrapped TextWriter
+ </summary>
+ <param name="value">the value to write to the TextWriter</param>
+ <remarks>
+ <para>
+ Writes a character to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a character buffer to the wrapped TextWriter
+ </summary>
+ <param name="buffer">the data buffer</param>
+ <param name="index">the start index</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Writes a character buffer to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.String)">
+ <summary>
+ Writes a string to the wrapped TextWriter
+ </summary>
+ <param name="value">the value to write to the TextWriter</param>
+ <remarks>
+ <para>
+ Writes a string to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.Writer">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.IO.TextWriter"/>.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.Encoding">
+ <summary>
+ The Encoding in which the output is written
+ </summary>
+ <value>
+ The <see cref="P:log4net.Util.TextWriterAdapter.Encoding"/>
+ </value>
+ <remarks>
+ <para>
+ The Encoding in which the output is written
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.FormatProvider">
+ <summary>
+ Gets an object that controls formatting
+ </summary>
+ <value>
+ The format provider
+ </value>
+ <remarks>
+ <para>
+ Gets an object that controls formatting
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.NewLine">
+ <summary>
+ Gets or sets the line terminator string used by the TextWriter
+ </summary>
+ <value>
+ The line terminator to use
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the line terminator string used by the TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.#ctor(System.IO.TextWriter,log4net.Core.IErrorHandler)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">the writer to actually write to</param>
+ <param name="errorHandler">the error handler to report error to</param>
+ <remarks>
+ <para>
+ Create a new QuietTextWriter using a writer and error handler
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.Char)">
+ <summary>
+ Writes a character to the underlying writer
+ </summary>
+ <param name="value">the char to write</param>
+ <remarks>
+ <para>
+ Writes a character to the underlying writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a buffer to the underlying writer
+ </summary>
+ <param name="buffer">the buffer to write</param>
+ <param name="index">the start index to write from</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Writes a buffer to the underlying writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.String)">
+ <summary>
+ Writes a string to the output.
+ </summary>
+ <param name="value">The string data to write to the output.</param>
+ <remarks>
+ <para>
+ Writes a string to the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Close">
+ <summary>
+ Closes the underlying output writer.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying output writer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.QuietTextWriter.m_errorHandler">
+ <summary>
+ The error handler instance to pass all errors to
+ </summary>
+ </member>
+ <member name="F:log4net.Util.QuietTextWriter.m_closed">
+ <summary>
+ Flag to indicate if this writer is closed
+ </summary>
+ </member>
+ <member name="P:log4net.Util.QuietTextWriter.ErrorHandler">
+ <summary>
+ Gets or sets the error handler that all errors are passed to.
+ </summary>
+ <value>
+ The error handler that all errors are passed to.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the error handler that all errors are passed to.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.QuietTextWriter.Closed">
+ <summary>
+ Gets a value indicating whether this writer is closed.
+ </summary>
+ <value>
+ <c>true</c> if this writer is closed, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Gets a value indicating whether this writer is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.#ctor(System.IO.TextWriter,log4net.Core.IErrorHandler)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to actually write to.</param>
+ <param name="errorHandler">The <see cref="T:log4net.Core.IErrorHandler"/> to report errors to.</param>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.CountingQuietTextWriter"/> class
+ with the specified <see cref="T:System.IO.TextWriter"/> and <see cref="T:log4net.Core.IErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.Char)">
+ <summary>
+ Writes a character to the underlying writer and counts the number of bytes written.
+ </summary>
+ <param name="value">the char to write</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a buffer to the underlying writer and counts the number of bytes written.
+ </summary>
+ <param name="buffer">the buffer to write</param>
+ <param name="index">the start index to write from</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.String)">
+ <summary>
+ Writes a string to the output and counts the number of bytes written.
+ </summary>
+ <param name="str">The string data to write to the output.</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.CountingQuietTextWriter.m_countBytes">
+ <summary>
+ Total number of bytes written.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.CountingQuietTextWriter.Count">
+ <summary>
+ Gets or sets the total number of bytes written.
+ </summary>
+ <value>
+ The total number of bytes written.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the total number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CyclicBuffer">
+ <summary>
+ A fixed size rolling buffer of logging events.
+ </summary>
+ <remarks>
+ <para>
+ An array backed fixed size leaky bucket.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.#ctor(System.Int32)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="maxSize">The maximum number of logging events in the buffer.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.CyclicBuffer"/> class with
+ the specified maximum number of buffered logging events.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="maxSize"/> argument is not a positive integer.</exception>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Appends a <paramref name="loggingEvent"/> to the buffer.
+ </summary>
+ <param name="loggingEvent">The event to append to the buffer.</param>
+ <returns>The event discarded from the buffer, if the buffer is full, otherwise <c>null</c>.</returns>
+ <remarks>
+ <para>
+ Append an event to the buffer. If the buffer still contains free space then
+ <c>null</c> is returned. If the buffer is full then an event will be dropped
+ to make space for the new event, the event dropped is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.PopOldest">
+ <summary>
+ Get and remove the oldest event in the buffer.
+ </summary>
+ <returns>The oldest logging event in the buffer</returns>
+ <remarks>
+ <para>
+ Gets the oldest (first) logging event in the buffer and removes it
+ from the buffer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.PopAll">
+ <summary>
+ Pops all the logging events from the buffer into an array.
+ </summary>
+ <returns>An array of all the logging events in the buffer.</returns>
+ <remarks>
+ <para>
+ Get all the events in the buffer and clear the buffer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.Clear">
+ <summary>
+ Clear the buffer
+ </summary>
+ <remarks>
+ <para>
+ Clear the buffer of all events. The events in the buffer are lost.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.Item(System.Int32)">
+ <summary>
+ Gets the <paramref name="i"/>th oldest event currently in the buffer.
+ </summary>
+ <value>The <paramref name="i"/>th oldest event currently in the buffer.</value>
+ <remarks>
+ <para>
+ If <paramref name="i"/> is outside the range 0 to the number of events
+ currently in the buffer, then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.MaxSize">
+ <summary>
+ Gets the maximum size of the buffer.
+ </summary>
+ <value>The maximum size of the buffer.</value>
+ <remarks>
+ <para>
+ Gets the maximum size of the buffer
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.Length">
+ <summary>
+ Gets the number of logging events in the buffer.
+ </summary>
+ <value>The number of logging events in the buffer.</value>
+ <remarks>
+ <para>
+ This number is guaranteed to be in the range 0 to <see cref="P:log4net.Util.CyclicBuffer.MaxSize"/>
+ (inclusive).
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.EmptyCollection">
+ <summary>
+ An always empty <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.ICollection"/>
+ interface that always represents an empty collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.EmptyCollection"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.CopyTo(System.Array,System.Int32)">
+ <summary>
+ Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an
+ <see cref="T:System.Array"/>, starting at a particular Array index.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:System.Array"/>
+ that is the destination of the elements copied from
+ <see cref="T:System.Collections.ICollection"/>. The Array must have zero-based
+ indexing.</param>
+ <param name="index">The zero-based index in array at which
+ copying begins.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values are copied into the array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.EmptyCollection.s_instance">
+ <summary>
+ The singleton instance of the empty collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.Instance">
+ <summary>
+ Gets the singleton instance of the empty collection.
+ </summary>
+ <returns>The singleton instance of the empty collection.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the empty collection.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe).
+ </summary>
+ <value>
+ <b>true</b> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe); otherwise, <b>false</b>.
+ </value>
+ <remarks>
+ <para>
+ For the <see cref="T:log4net.Util.EmptyCollection"/> this property is always <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.Count">
+ <summary>
+ Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="P:log4net.Util.EmptyCollection.Count"/> is always <c>0</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty and thread safe and synchronized this instance is also
+ the <see cref="P:log4net.Util.EmptyCollection.SyncRoot"/> object.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.EmptyDictionary">
+ <summary>
+ An always empty <see cref="T:System.Collections.IDictionary"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IDictionary"/>
+ interface that always represents an empty collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.EmptyDictionary"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.CopyTo(System.Array,System.Int32)">
+ <summary>
+ Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an
+ <see cref="T:System.Array"/>, starting at a particular Array index.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:System.Array"/>
+ that is the destination of the elements copied from
+ <see cref="T:System.Collections.ICollection"/>. The Array must have zero-based
+ indexing.</param>
+ <param name="index">The zero-based index in array at which
+ copying begins.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values are copied into the array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Add(System.Object,System.Object)">
+ <summary>
+ Adds an element with the provided key and value to the
+ <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <param name="key">The <see cref="T:System.Object"/> to use as the key of the element to add.</param>
+ <param name="value">The <see cref="T:System.Object"/> to use as the value of the element to add.</param>
+ <remarks>
+ <para>
+ As the collection is empty no new values can be added. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Clear">
+ <summary>
+ Removes all elements from the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <remarks>
+ <para>
+ As the collection is empty no values can be removed. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Contains(System.Object)">
+ <summary>
+ Determines whether the <see cref="T:log4net.Util.EmptyDictionary"/> contains an element
+ with the specified key.
+ </summary>
+ <param name="key">The key to locate in the <see cref="T:log4net.Util.EmptyDictionary"/>.</param>
+ <returns><c>false</c></returns>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="M:log4net.Util.EmptyDictionary.Contains(System.Object)"/> method always returns <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Remove(System.Object)">
+ <summary>
+ Removes the element with the specified key from the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <param name="key">The key of the element to remove.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values can be removed. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="F:log4net.Util.EmptyDictionary.s_instance">
+ <summary>
+ The singleton instance of the empty dictionary.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Instance">
+ <summary>
+ Gets the singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsSynchronized">
+ <summary>
+ Gets a value indicating if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe).
+ </summary>
+ <value>
+ <b>true</b> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe); otherwise, <b>false</b>.
+ </value>
+ <remarks>
+ <para>
+ For the <see cref="T:log4net.Util.EmptyCollection"/> this property is always <b>true</b>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Count">
+ <summary>
+ Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>
+ </summary>
+ <value>
+ The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="P:log4net.Util.EmptyDictionary.Count"/> is always <c>0</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty and thread safe and synchronized this instance is also
+ the <see cref="P:log4net.Util.EmptyDictionary.SyncRoot"/> object.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the <see cref="T:log4net.Util.EmptyDictionary"/> has a fixed size.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ As the collection is empty <see cref="P:log4net.Util.EmptyDictionary.IsFixedSize"/> always returns <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the <see cref="T:log4net.Util.EmptyDictionary"/> is read-only.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ As the collection is empty <see cref="P:log4net.Util.EmptyDictionary.IsReadOnly"/> always returns <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Keys">
+ <summary>
+ Gets an <see cref="T:System.Collections.ICollection"/> containing the keys of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <value>An <see cref="T:System.Collections.ICollection"/> containing the keys of the <see cref="T:log4net.Util.EmptyDictionary"/>.</value>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Values">
+ <summary>
+ Gets an <see cref="T:System.Collections.ICollection"/> containing the values of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <value>An <see cref="T:System.Collections.ICollection"/> containing the values of the <see cref="T:log4net.Util.EmptyDictionary"/>.</value>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Item(System.Object)">
+ <summary>
+ Gets or sets the element with the specified key.
+ </summary>
+ <param name="key">The key of the element to get or set.</param>
+ <value><c>null</c></value>
+ <remarks>
+ <para>
+ As the collection is empty no values can be looked up or stored.
+ If the index getter is called then <c>null</c> is returned.
+ A <see cref="T:System.InvalidOperationException"/> is thrown if the setter is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="T:log4net.Util.FormattingInfo">
+ <summary>
+ Contain the information obtained when parsing formatting modifiers
+ in conversion modifiers.
+ </summary>
+ <remarks>
+ <para>
+ Holds the formatting information extracted from the format string by
+ the <see cref="T:log4net.Util.PatternParser"/>. This is used by the <see cref="T:log4net.Util.PatternConverter"/>
+ objects when rendering the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.FormattingInfo.#ctor">
+ <summary>
+ Defaut Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.FormattingInfo"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.FormattingInfo.#ctor(System.Int32,System.Int32,System.Boolean)">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.FormattingInfo"/> class
+ with the specified parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.Min">
+ <summary>
+ Gets or sets the minimum value.
+ </summary>
+ <value>
+ The minimum value.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the minimum value.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.Max">
+ <summary>
+ Gets or sets the maximum value.
+ </summary>
+ <value>
+ The maximum value.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the maximum value.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.LeftAlign">
+ <summary>
+ Gets or sets a flag indicating whether left align is enabled
+ or not.
+ </summary>
+ <value>
+ A flag indicating whether left align is enabled or not.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets a flag indicating whether left align is enabled or not.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.GlobalContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.GlobalContext"/>
+ </summary>
+ <remarks>
+ <para>
+ This class implements a properties collection that is thread safe and supports both
+ storing properties and capturing a read only copy of the current propertied.
+ </para>
+ <para>
+ This class is optimized to the scenario where the properties are read frequently
+ and are modified infrequently.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.GlobalContextProperties.m_readOnlyProperties">
+ <summary>
+ The read only copy of the properties.
+ </summary>
+ <remarks>
+ <para>
+ This variable is declared <c>volatile</c> to prevent the compiler and JIT from
+ reordering reads and writes of this thread performed on different threads.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.GlobalContextProperties.m_syncRoot">
+ <summary>
+ Lock object used to synchronize updates within this instance
+ </summary>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.GlobalContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property from the global context
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Removing an entry from the global context properties is relatively expensive compared
+ with reading a value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.Clear">
+ <summary>
+ Clear the global context properties
+ </summary>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.GetReadOnlyProperties">
+ <summary>
+ Get a readonly immutable copy of the properties
+ </summary>
+ <returns>the current global context properties</returns>
+ <remarks>
+ <para>
+ This implementation is fast because the GlobalContextProperties class
+ stores a readonly copy of the properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.GlobalContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Reading the value for a key is faster than setting the value.
+ When the value is written a new read only copy of
+ the properties is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LevelMapping">
+ <summary>
+ Manages a mapping from levels to <see cref="T:log4net.Util.LevelMappingEntry"/>
+ </summary>
+ <remarks>
+ <para>
+ Manages an ordered mapping from <see cref="T:log4net.Core.Level"/> instances
+ to <see cref="T:log4net.Util.LevelMappingEntry"/> subclasses.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initialise a new instance of <see cref="T:log4net.Util.LevelMapping"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.Add(log4net.Util.LevelMappingEntry)">
+ <summary>
+ Add a <see cref="T:log4net.Util.LevelMappingEntry"/> to this mapping
+ </summary>
+ <param name="entry">the entry to add</param>
+ <remarks>
+ <para>
+ If a <see cref="T:log4net.Util.LevelMappingEntry"/> has previously been added
+ for the same <see cref="T:log4net.Core.Level"/> then that entry will be
+ overwritten.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.Lookup(log4net.Core.Level)">
+ <summary>
+ Lookup the mapping for the specified level
+ </summary>
+ <param name="level">the level to lookup</param>
+ <returns>the <see cref="T:log4net.Util.LevelMappingEntry"/> for the level or <c>null</c> if no mapping found</returns>
+ <remarks>
+ <para>
+ Lookup the value for the specified level. Finds the nearest
+ mapping value for the level that is equal to or less than the
+ <paramref name="level"/> specified.
+ </para>
+ <para>
+ If no mapping could be found then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.ActivateOptions">
+ <summary>
+ Initialize options
+ </summary>
+ <remarks>
+ <para>
+ Caches the sorted list of <see cref="T:log4net.Util.LevelMappingEntry"/> in an array
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LogicalThreadContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.LogicalThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Class implements a collection of properties that is specific to each thread.
+ The class is not synchronized as each thread has its own <see cref="T:log4net.Util.PropertiesDictionary"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.LogicalThreadContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove the value for the specified <paramref name="key"/> from the context.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.Clear">
+ <summary>
+ Clear all the context properties
+ </summary>
+ <remarks>
+ <para>
+ Clear all the context properties
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.GetProperties(System.Boolean)">
+ <summary>
+ Get the PropertiesDictionary stored in the LocalDataStoreSlot for this thread.
+ </summary>
+ <param name="create">create the dictionary if it does not exist, otherwise return null if is does not exist</param>
+ <returns>the properties for this thread</returns>
+ <remarks>
+ <para>
+ The collection returned is only to be used on the calling thread. If the
+ caller needs to share the collection between different threads then the
+ caller must clone the collection before doings so.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogicalThreadContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Get or set the property value for the <paramref name="key"/> specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LogLog">
+ <summary>
+ Outputs log statements from within the log4net assembly.
+ </summary>
+ <remarks>
+ <para>
+ Log4net components cannot make log4net logging calls. However, it is
+ sometimes useful for the user to learn about what log4net is
+ doing.
+ </para>
+ <para>
+ All log4net internal debug calls go to the standard output stream
+ whereas internal error messages are sent to the standard error output
+ stream.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.LogLog.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.LogLog"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.#cctor">
+ <summary>
+ Static constructor that initializes logging by reading
+ settings from the application configuration file.
+ </summary>
+ <remarks>
+ <para>
+ The <c>log4net.Internal.Debug</c> application setting
+ controls internal debugging. This setting should be set
+ to <c>true</c> to enable debugging.
+ </para>
+ <para>
+ The <c>log4net.Internal.Quiet</c> application setting
+ suppresses all internal logging including error messages.
+ This setting should be set to <c>true</c> to enable message
+ suppression.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Debug(System.String)">
+ <summary>
+ Writes log4net internal debug messages to the
+ standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net: ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Debug(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal debug messages to the
+ standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net: ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Warn(System.String)">
+ <summary>
+ Writes log4net internal warning messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal warning messages are prepended with
+ the string "log4net:WARN ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Warn(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal warning messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal warning messages are prepended with
+ the string "log4net:WARN ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Error(System.String)">
+ <summary>
+ Writes log4net internal error messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal error messages are prepended with
+ the string "log4net:ERROR ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Error(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal error messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net:ERROR ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.EmitOutLine(System.String)">
+ <summary>
+ Writes output to the standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ Writes to both Console.Out and System.Diagnostics.Trace.
+ Note that the System.Diagnostics.Trace is not supported
+ on the Compact Framework.
+ </para>
+ <para>
+ If the AppDomain is not configured with a config file then
+ the call to System.Diagnostics.Trace may fail. This is only
+ an issue if you are programmatically creating your own AppDomains.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.EmitErrorLine(System.String)">
+ <summary>
+ Writes output to the standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ Writes to both Console.Error and System.Diagnostics.Trace.
+ Note that the System.Diagnostics.Trace is not supported
+ on the Compact Framework.
+ </para>
+ <para>
+ If the AppDomain is not configured with a config file then
+ the call to System.Diagnostics.Trace may fail. This is only
+ an issue if you are programmatically creating your own AppDomains.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.LogLog.s_debugEnabled">
+ <summary>
+ Default debug level
+ </summary>
+ </member>
+ <member name="F:log4net.Util.LogLog.s_quietMode">
+ <summary>
+ In quietMode not even errors generate any output.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.LogLog.InternalDebugging">
+ <summary>
+ Gets or sets a value indicating whether log4net internal logging
+ is enabled or disabled.
+ </summary>
+ <value>
+ <c>true</c> if log4net internal logging is enabled, otherwise
+ <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ When set to <c>true</c>, internal debug level logging will be
+ displayed.
+ </para>
+ <para>
+ This value can be set by setting the application setting
+ <c>log4net.Internal.Debug</c> in the application configuration
+ file.
+ </para>
+ <para>
+ The default value is <c>false</c>, i.e. debugging is
+ disabled.
+ </para>
+ </remarks>
+ <example>
+ <para>
+ The following example enables internal debugging using the
+ application configuration file :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net.Internal.Debug" value="true" />
+ </appSettings>
+ </configuration>
+ </code>
+ </example>
+ </member>
+ <member name="P:log4net.Util.LogLog.QuietMode">
+ <summary>
+ Gets or sets a value indicating whether log4net should generate no output
+ from internal logging, not even for errors.
+ </summary>
+ <value>
+ <c>true</c> if log4net should generate no output at all from internal
+ logging, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ When set to <c>true</c> will cause internal logging at all levels to be
+ suppressed. This means that no warning or error reports will be logged.
+ This option overrides the <see cref="P:log4net.Util.LogLog.InternalDebugging"/> setting and
+ disables all debug also.
+ </para>
+ <para>This value can be set by setting the application setting
+ <c>log4net.Internal.Quiet</c> in the application configuration file.
+ </para>
+ <para>
+ The default value is <c>false</c>, i.e. internal logging is not
+ disabled.
+ </para>
+ </remarks>
+ <example>
+ The following example disables internal logging using the
+ application configuration file :
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net.Internal.Quiet" value="true"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </example>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsDebugEnabled">
+ <summary>
+ Test if LogLog.Debug is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Debug is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Debug is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsWarnEnabled">
+ <summary>
+ Test if LogLog.Warn is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Warn is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Warn is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsErrorEnabled">
+ <summary>
+ Test if LogLog.Error is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Error is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Error is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.NativeError">
+ <summary>
+ Represents a native error code and message.
+ </summary>
+ <remarks>
+ <para>
+ Represents a Win32 platform native error.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NativeError.#ctor(System.Int32,System.String)">
+ <summary>
+ Create an instance of the <see cref="T:log4net.Util.NativeError"/> class with the specified
+ error number and message.
+ </summary>
+ <param name="number">The number of the native error.</param>
+ <param name="message">The message of the native error.</param>
+ <remarks>
+ <para>
+ Create an instance of the <see cref="T:log4net.Util.NativeError"/> class with the specified
+ error number and message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetLastError">
+ <summary>
+ Create a new instance of the <see cref="T:log4net.Util.NativeError"/> class for the last Windows error.
+ </summary>
+ <returns>
+ An instance of the <see cref="T:log4net.Util.NativeError"/> class for the last windows error.
+ </returns>
+ <remarks>
+ <para>
+ The message for the <see cref="M:System.Runtime.InteropServices.Marshal.GetLastWin32Error"/> error number is lookup up using the
+ native Win32 <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetError(System.Int32)">
+ <summary>
+ Create a new instance of the <see cref="T:log4net.Util.NativeError"/> class.
+ </summary>
+ <param name="number">the error number for the native error</param>
+ <returns>
+ An instance of the <see cref="T:log4net.Util.NativeError"/> class for the specified
+ error number.
+ </returns>
+ <remarks>
+ <para>
+ The message for the specified error number is lookup up using the
+ native Win32 <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetErrorMessage(System.Int32)">
+ <summary>
+ Retrieves the message corresponding with a Win32 message identifier.
+ </summary>
+ <param name="messageId">Message identifier for the requested message.</param>
+ <returns>
+ The message corresponding with the specified message identifier.
+ </returns>
+ <remarks>
+ <para>
+ The message will be searched for in system message-table resource(s)
+ using the native <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.ToString">
+ <summary>
+ Return error information string
+ </summary>
+ <returns>error information string</returns>
+ <remarks>
+ <para>
+ Return error information string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.FormatMessage(System.Int32,System.IntPtr@,System.Int32,System.Int32,System.String@,System.Int32,System.IntPtr)">
+ <summary>
+ Formats a message string.
+ </summary>
+ <param name="dwFlags">Formatting options, and how to interpret the <paramref name="lpSource"/> parameter.</param>
+ <param name="lpSource">Location of the message definition.</param>
+ <param name="dwMessageId">Message identifier for the requested message.</param>
+ <param name="dwLanguageId">Language identifier for the requested message.</param>
+ <param name="lpBuffer">If <paramref name="dwFlags"/> includes FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a buffer using the <c>LocalAlloc</c> function, and places the pointer to the buffer at the address specified in <paramref name="lpBuffer"/>.</param>
+ <param name="nSize">If the FORMAT_MESSAGE_ALLOCATE_BUFFER flag is not set, this parameter specifies the maximum number of TCHARs that can be stored in the output buffer. If FORMAT_MESSAGE_ALLOCATE_BUFFER is set, this parameter specifies the minimum number of TCHARs to allocate for an output buffer.</param>
+ <param name="Arguments">Pointer to an array of values that are used as insert values in the formatted message.</param>
+ <remarks>
+ <para>
+ The function requires a message definition as input. The message definition can come from a
+ buffer passed into the function. It can come from a message table resource in an
+ already-loaded module. Or the caller can ask the function to search the system's message
+ table resource(s) for the message definition. The function finds the message definition
+ in a message table resource based on a message identifier and a language identifier.
+ The function copies the formatted message text to an output buffer, processing any embedded
+ insert sequences if requested.
+ </para>
+ <para>
+ To prevent the usage of unsafe code, this stub does not support inserting values in the formatted message.
+ </para>
+ </remarks>
+ <returns>
+ <para>
+ If the function succeeds, the return value is the number of TCHARs stored in the output
+ buffer, excluding the terminating null character.
+ </para>
+ <para>
+ If the function fails, the return value is zero. To get extended error information,
+ call <see cref="M:System.Runtime.InteropServices.Marshal.GetLastWin32Error"/>.
+ </para>
+ </returns>
+ </member>
+ <member name="P:log4net.Util.NativeError.Number">
+ <summary>
+ Gets the number of the native error.
+ </summary>
+ <value>
+ The number of the native error.
+ </value>
+ <remarks>
+ <para>
+ Gets the number of the native error.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NativeError.Message">
+ <summary>
+ Gets the message of the native error.
+ </summary>
+ <value>
+ The message of the native error.
+ </value>
+ <remarks>
+ <para>
+ </para>
+ Gets the message of the native error.
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.NullDictionaryEnumerator">
+ <summary>
+ An always empty <see cref="T:System.Collections.IDictionaryEnumerator"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IDictionaryEnumerator"/> over a collection
+ that is empty and not modifiable.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.MoveNext">
+ <summary>
+ Test if the enumerator can advance, if so advance.
+ </summary>
+ <returns><c>false</c> as the <see cref="T:log4net.Util.NullDictionaryEnumerator"/> cannot advance.</returns>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="M:log4net.Util.NullDictionaryEnumerator.MoveNext"/>
+ will always return <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.Reset">
+ <summary>
+ Resets the enumerator back to the start.
+ </summary>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection <see cref="M:log4net.Util.NullDictionaryEnumerator.Reset"/> does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.NullDictionaryEnumerator.s_instance">
+ <summary>
+ The singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Instance">
+ <summary>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Current">
+ <summary>
+ Gets the current object from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Key">
+ <summary>
+ Gets the current key from the enumerator.
+ </summary>
+ <remarks>
+ Throws an exception because the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>
+ never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Key"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Value">
+ <summary>
+ Gets the current value from the enumerator.
+ </summary>
+ <value>The current value from the enumerator.</value>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Value"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Entry">
+ <summary>
+ Gets the current entry from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current entry.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Entry"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="T:log4net.Util.NullEnumerator">
+ <summary>
+ An always empty <see cref="T:System.Collections.IEnumerator"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IEnumerator"/> over a collection
+ that is empty and not modifiable.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.NullEnumerator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.MoveNext">
+ <summary>
+ Test if the enumerator can advance, if so advance
+ </summary>
+ <returns><c>false</c> as the <see cref="T:log4net.Util.NullEnumerator"/> cannot advance.</returns>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="M:log4net.Util.NullEnumerator.MoveNext"/>
+ will always return <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.Reset">
+ <summary>
+ Resets the enumerator back to the start.
+ </summary>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection <see cref="M:log4net.Util.NullEnumerator.Reset"/> does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.NullEnumerator.s_instance">
+ <summary>
+ The singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.NullEnumerator.Instance">
+ <summary>
+ Get the singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NullEnumerator.Current">
+ <summary>
+ Gets the current object from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="T:log4net.Util.NullSecurityContext">
+ <summary>
+ A SecurityContext used when a SecurityContext is not required
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Util.NullSecurityContext"/> is a no-op implementation of the
+ <see cref="T:log4net.Core.SecurityContext"/> base class. It is used where a <see cref="T:log4net.Core.SecurityContext"/>
+ is required but one has not been provided.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.NullSecurityContext.Instance">
+ <summary>
+ Singleton instance of <see cref="T:log4net.Util.NullSecurityContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Singleton instance of <see cref="T:log4net.Util.NullSecurityContext"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullSecurityContext.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ <remarks>
+ <para>
+ Private constructor for singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullSecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate this SecurityContext
+ </summary>
+ <param name="state">State supplied by the caller</param>
+ <returns><c>null</c></returns>
+ <remarks>
+ <para>
+ No impersonation is done and <c>null</c> is always returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.OnlyOnceErrorHandler">
+ <summary>
+ Implements log4net's default error handling policy which consists
+ of emitting a message for the first error in an appender and
+ ignoring all subsequent errors.
+ </summary>
+ <remarks>
+ <para>
+ The error message is printed on the standard error output stream.
+ </para>
+ <para>
+ This policy aims at protecting an otherwise working application
+ from being flooded with error messages when logging fails.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="prefix">The prefix to use for each message.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/> class
+ with the specified prefix.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)">
+ <summary>
+ Log an Error
+ </summary>
+ <param name="message">The error message.</param>
+ <param name="e">The exception.</param>
+ <param name="errorCode">The internal error code.</param>
+ <remarks>
+ <para>
+ Prints the message and the stack trace of the exception on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String,System.Exception)">
+ <summary>
+ Log an Error
+ </summary>
+ <param name="message">The error message.</param>
+ <param name="e">The exception.</param>
+ <remarks>
+ <para>
+ Prints the message and the stack trace of the exception on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String)">
+ <summary>
+ Log an error
+ </summary>
+ <param name="message">The error message.</param>
+ <remarks>
+ <para>
+ Print a the error message passed as parameter on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.OnlyOnceErrorHandler.m_firstTime">
+ <summary>
+ Flag to indicate if it is the first error
+ </summary>
+ </member>
+ <member name="F:log4net.Util.OnlyOnceErrorHandler.m_prefix">
+ <summary>
+ String to prefix each message with
+ </summary>
+ </member>
+ <member name="P:log4net.Util.OnlyOnceErrorHandler.IsEnabled">
+ <summary>
+ Is error logging enabled
+ </summary>
+ <remarks>
+ <para>
+ Is error logging enabled. Logging is only enabled for the
+ first error delivered to the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.OptionConverter">
+ <summary>
+ A convenience class to convert property values to specific types.
+ </summary>
+ <remarks>
+ <para>
+ Utility functions for converting types and parsing values.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.OptionConverter"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ToBoolean(System.String,System.Boolean)">
+ <summary>
+ Converts a string to a <see cref="T:System.Boolean"/> value.
+ </summary>
+ <param name="argValue">String to convert.</param>
+ <param name="defaultValue">The default value.</param>
+ <returns>The <see cref="T:System.Boolean"/> value of <paramref name="argValue"/>.</returns>
+ <remarks>
+ <para>
+ If <paramref name="argValue"/> is "true", then <c>true</c> is returned.
+ If <paramref name="argValue"/> is "false", then <c>false</c> is returned.
+ Otherwise, <paramref name="defaultValue"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ToFileSize(System.String,System.Int64)">
+ <summary>
+ Parses a file size into a number.
+ </summary>
+ <param name="argValue">String to parse.</param>
+ <param name="defaultValue">The default value.</param>
+ <returns>The <see cref="T:System.Int64"/> value of <paramref name="argValue"/>.</returns>
+ <remarks>
+ <para>
+ Parses a file size of the form: number[KB|MB|GB] into a
+ long value. It is scaled with the appropriate multiplier.
+ </para>
+ <para>
+ <paramref name="defaultValue"/> is returned when <paramref name="argValue"/>
+ cannot be converted to a <see cref="T:System.Int64"/> value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ConvertStringTo(System.Type,System.String)">
+ <summary>
+ Converts a string to an object.
+ </summary>
+ <param name="target">The target type to convert to.</param>
+ <param name="txt">The string to convert to an object.</param>
+ <returns>
+ The object converted from a string or <c>null</c> when the
+ conversion failed.
+ </returns>
+ <remarks>
+ <para>
+ Converts a string to an object. Uses the converter registry to try
+ to convert the string value into the specified target type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.CanConvertTypeTo(System.Type,System.Type)">
+ <summary>
+ Checks if there is an appropriate type conversion from the source type to the target type.
+ </summary>
+ <param name="sourceType">The type to convert from.</param>
+ <param name="targetType">The type to convert to.</param>
+ <returns><c>true</c> if there is a conversion from the source type to the target type.</returns>
+ <remarks>
+ Checks if there is an appropriate type conversion from the source type to the target type.
+ <para>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ConvertTypeTo(System.Object,System.Type)">
+ <summary>
+ Converts an object to the target type.
+ </summary>
+ <param name="sourceInstance">The object to convert to the target type.</param>
+ <param name="targetType">The type to convert to.</param>
+ <returns>The converted object.</returns>
+ <remarks>
+ <para>
+ Converts an object to the target type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.InstantiateByClassName(System.String,System.Type,System.Object)">
+ <summary>
+ Instantiates an object given a class name.
+ </summary>
+ <param name="className">The fully qualified class name of the object to instantiate.</param>
+ <param name="superClass">The class to which the new object should belong.</param>
+ <param name="defaultValue">The object to return in case of non-fulfillment.</param>
+ <returns>
+ An instance of the <paramref name="className"/> or <paramref name="defaultValue"/>
+ if the object could not be instantiated.
+ </returns>
+ <remarks>
+ <para>
+ Checks that the <paramref name="className"/> is a subclass of
+ <paramref name="superClass"/>. If that test fails or the object could
+ not be instantiated, then <paramref name="defaultValue"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.SubstituteVariables(System.String,System.Collections.IDictionary)">
+ <summary>
+ Performs variable substitution in string <paramref name="val"/> from the
+ values of keys found in <paramref name="props"/>.
+ </summary>
+ <param name="value">The string on which variable substitution is performed.</param>
+ <param name="props">The dictionary to use to lookup variables.</param>
+ <returns>The result of the substitutions.</returns>
+ <remarks>
+ <para>
+ The variable substitution delimiters are <b>${</b> and <b>}</b>.
+ </para>
+ <para>
+ For example, if props contains <c>key=value</c>, then the call
+ </para>
+ <para>
+ <code lang="C#">
+ string s = OptionConverter.SubstituteVariables("Value of key is ${key}.");
+ </code>
+ </para>
+ <para>
+ will set the variable <c>s</c> to "Value of key is value.".
+ </para>
+ <para>
+ If no value could be found for the specified key, then substitution
+ defaults to an empty string.
+ </para>
+ <para>
+ For example, if system properties contains no value for the key
+ "nonExistentKey", then the call
+ </para>
+ <para>
+ <code lang="C#">
+ string s = OptionConverter.SubstituteVariables("Value of nonExistentKey is [${nonExistentKey}]");
+ </code>
+ </para>
+ <para>
+ will set <s>s</s> to "Value of nonExistentKey is []".
+ </para>
+ <para>
+ An Exception is thrown if <paramref name="value"/> contains a start
+ delimiter "${" which is not balanced by a stop delimiter "}".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ParseEnum(System.Type,System.String,System.Boolean)">
+ <summary>
+ Converts the string representation of the name or numeric value of one or
+ more enumerated constants to an equivalent enumerated object.
+ </summary>
+ <param name="enumType">The type to convert to.</param>
+ <param name="value">The enum string value.</param>
+ <param name="ignoreCase">If <c>true</c>, ignore case; otherwise, regard case.</param>
+ <returns>An object of type <paramref name="enumType" /> whose value is represented by <paramref name="value" />.</returns>
+ </member>
+ <member name="T:log4net.Util.PatternParser">
+ <summary>
+ Most of the work of the <see cref="T:log4net.Layout.PatternLayout"/> class
+ is delegated to the PatternParser class.
+ </summary>
+ <remarks>
+ <para>
+ The <c>PatternParser</c> processes a pattern string and
+ returns a chain of <see cref="T:log4net.Util.PatternConverter"/> objects.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.PatternParser.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="pattern">The pattern to parse.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PatternParser"/> class
+ with the specified pattern string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.Parse">
+ <summary>
+ Parses the pattern into a chain of pattern converters.
+ </summary>
+ <returns>The head of a chain of pattern converters.</returns>
+ <remarks>
+ <para>
+ Parses the pattern into a chain of pattern converters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.BuildCache">
+ <summary>
+ Build the unified cache of converters from the static and instance maps
+ </summary>
+ <returns>the list of all the converter names</returns>
+ <remarks>
+ <para>
+ Build the unified cache of converters from the static and instance maps
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ParseInternal(System.String,System.String[])">
+ <summary>
+ Internal method to parse the specified pattern to find specified matches
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <param name="matches">the converter names to match in the pattern</param>
+ <remarks>
+ <para>
+ The matches param must be sorted such that longer strings come before shorter ones.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ProcessLiteral(System.String)">
+ <summary>
+ Process a parsed literal
+ </summary>
+ <param name="text">the literal text</param>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ProcessConverter(System.String,System.String,log4net.Util.FormattingInfo)">
+ <summary>
+ Process a parsed converter pattern
+ </summary>
+ <param name="converterName">the name of the converter</param>
+ <param name="option">the optional option for the converter</param>
+ <param name="formattingInfo">the formatting info for the converter</param>
+ </member>
+ <member name="M:log4net.Util.PatternParser.AddConverter(log4net.Util.PatternConverter)">
+ <summary>
+ Resets the internal state of the parser and adds the specified pattern converter
+ to the chain.
+ </summary>
+ <param name="pc">The pattern converter to add.</param>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_head">
+ <summary>
+ The first pattern converter in the chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_tail">
+ <summary>
+ the last pattern converter in the chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_pattern">
+ <summary>
+ The pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_patternConverters">
+ <summary>
+ Internal map of converter identifiers to converter types
+ </summary>
+ <remarks>
+ <para>
+ This map overrides the static s_globalRulesRegistry map.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternParser.PatternConverters">
+ <summary>
+ Get the converter registry used by this parser
+ </summary>
+ <value>
+ The converter registry used by this parser
+ </value>
+ <remarks>
+ <para>
+ Get the converter registry used by this parser
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternParser.StringLengthComparer">
+ <summary>
+ Sort strings by length
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:System.Collections.IComparer"/> that orders strings by string length.
+ The longest strings are placed first
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternString">
+ <summary>
+ This class implements a patterned string.
+ </summary>
+ <remarks>
+ <para>
+ This string has embedded patterns that are resolved and expanded
+ when the string is formatted.
+ </para>
+ <para>
+ This class functions similarly to the <see cref="T:log4net.Layout.PatternLayout"/>
+ in that it accepts a pattern and renders it to a string. Unlike the
+ <see cref="T:log4net.Layout.PatternLayout"/> however the <c>PatternString</c>
+ does not render the properties of a specific <see cref="T:log4net.Core.LoggingEvent"/> but
+ of the process in general.
+ </para>
+ <para>
+ The recognized conversion pattern names are:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Conversion Pattern Name</term>
+ <description>Effect</description>
+ </listheader>
+ <item>
+ <term>appdomain</term>
+ <description>
+ <para>
+ Used to output the friendly name of the current AppDomain.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>date</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in the local time zone.
+ To output the date in universal time use the <c>%utcdate</c> pattern.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
+ <b>%date{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>env</term>
+ <description>
+ <para>
+ Used to output the a specific environment variable. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%env{COMPUTERNAME}</b> would include the value
+ of the <c>COMPUTERNAME</c> environment variable.
+ </para>
+ <para>
+ The <c>env</c> pattern is not supported on the .NET Compact Framework.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>identity</term>
+ <description>
+ <para>
+ Used to output the user name for the currently active user
+ (Principal.Identity.Name).
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>newline</term>
+ <description>
+ <para>
+ Outputs the platform dependent line separator character or
+ characters.
+ </para>
+ <para>
+ This conversion pattern name offers the same performance as using
+ non-portable line separator strings such as "\n", or "\r\n".
+ Thus, it is the preferred way of specifying a line separator.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>processid</term>
+ <description>
+ <para>
+ Used to output the system process ID for the current process.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>property</term>
+ <description>
+ <para>
+ Used to output a specific context property. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%property{user}</b> would include the value
+ from the property that is keyed by the string 'user'. Each property value
+ that is to be included in the log must be specified separately.
+ Properties are stored in logging contexts. By default
+ the <c>log4net:HostName</c> property is set to the name of machine on
+ which the event was originally logged.
+ </para>
+ <para>
+ If no key is specified, e.g. <b>%property</b> then all the keys and their
+ values are printed in a comma separated list.
+ </para>
+ <para>
+ The properties of an event are combined from a number of different
+ contexts. These are listed below in the order in which they are searched.
+ </para>
+ <list type="definition">
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+ </description>
+ </item>
+ <item>
+ <term>random</term>
+ <description>
+ <para>
+ Used to output a random string of characters. The string is made up of
+ uppercase letters and numbers. By default the string is 4 characters long.
+ The length of the string can be specified within braces directly following the
+ pattern specifier, e.g. <b>%random{8}</b> would output an 8 character string.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>username</term>
+ <description>
+ <para>
+ Used to output the WindowsIdentity for the currently
+ active user.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>utcdate</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in universal time.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
+ <b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>%</term>
+ <description>
+ <para>
+ The sequence %% outputs a single percent sign.
+ </para>
+ </description>
+ </item>
+ </list>
+ <para>
+ Additional pattern converters may be registered with a specific <see cref="T:log4net.Util.PatternString"/>
+ instance using <see cref="M:log4net.Util.PatternString.AddConverter(log4net.Util.PatternString.ConverterInfo)"/> or
+ <see cref="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)"/>.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Layout.PatternLayout"/> for details on the
+ <i>format modifiers</i> supported by the patterns.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternString.s_globalRulesRegistry">
+ <summary>
+ Internal map of converter identifiers to converter types.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_pattern">
+ <summary>
+ the pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_head">
+ <summary>
+ the head of the pattern converter chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_instanceRulesRegistry">
+ <summary>
+ patterns defined on this PatternString only
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternString.#cctor">
+ <summary>
+ Initialize the global registry
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternString.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initialize a new instance of <see cref="T:log4net.Util.PatternString"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.#ctor(System.String)">
+ <summary>
+ Constructs a PatternString
+ </summary>
+ <param name="pattern">The pattern to use with this PatternString</param>
+ <remarks>
+ <para>
+ Initialize a new instance of <see cref="T:log4net.Util.PatternString"/> with the pattern specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.ActivateOptions">
+ <summary>
+ Initialize object options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternString.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternString.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternString.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.CreatePatternParser(System.String)">
+ <summary>
+ Create the <see cref="T:log4net.Util.PatternParser"/> used to parse the pattern
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <returns>The <see cref="T:log4net.Util.PatternParser"/></returns>
+ <remarks>
+ <para>
+ Returns PatternParser used to parse the conversion string. Subclasses
+ may override this to return a subclass of PatternParser which recognize
+ custom conversion pattern name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.Format(System.IO.TextWriter)">
+ <summary>
+ Produces a formatted string as specified by the conversion pattern.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Format the pattern to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.Format">
+ <summary>
+ Format the pattern as a string
+ </summary>
+ <returns>the pattern formatted as a string</returns>
+ <remarks>
+ <para>
+ Format the pattern to a string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.AddConverter(log4net.Util.PatternString.ConverterInfo)">
+ <summary>
+ Add a converter to this PatternString
+ </summary>
+ <param name="converterInfo">the converter info</param>
+ <remarks>
+ <para>
+ This version of the method is used by the configurator.
+ Programmatic users should use the alternative <see cref="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)">
+ <summary>
+ Add a converter to this PatternString
+ </summary>
+ <param name="name">the name of the conversion pattern for this converter</param>
+ <param name="type">the type of the converter</param>
+ <remarks>
+ <para>
+ Add a converter to this PatternString
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConversionPattern">
+ <summary>
+ Gets or sets the pattern formatting string
+ </summary>
+ <value>
+ The pattern formatting string
+ </value>
+ <remarks>
+ <para>
+ The <b>ConversionPattern</b> option. This is the string which
+ controls formatting and consists of a mix of literal content and
+ conversion specifiers.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternString.ConverterInfo">
+ <summary>
+ Wrapper class used to map converter names to converter types
+ </summary>
+ <remarks>
+ <para>
+ Wrapper class used to map converter names to converter types
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.ConverterInfo.#ctor">
+ <summary>
+ default constructor
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConverterInfo.Name">
+ <summary>
+ Gets or sets the name of the conversion pattern
+ </summary>
+ <value>
+ The name of the conversion pattern
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the name of the conversion pattern
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConverterInfo.Type">
+ <summary>
+ Gets or sets the type of the converter
+ </summary>
+ <value>
+ The type of the converter
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the type of the converter
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PropertiesDictionary">
+ <summary>
+ String keyed object map.
+ </summary>
+ <remarks>
+ <para>
+ While this collection is serializable only member
+ objects that are serializable will
+ be serialized along with this collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.ReadOnlyPropertiesDictionary">
+ <summary>
+ String keyed object map that is read only.
+ </summary>
+ <remarks>
+ <para>
+ This collection is readonly and cannot be modified.
+ </para>
+ <para>
+ While this collection is serializable only member
+ objects that are serializable will
+ be serialized along with this collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.ReadOnlyPropertiesDictionary.m_hashtable">
+ <summary>
+ The Hashtable used to store the properties data
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Copy Constructor
+ </summary>
+ <param name="propertiesDictionary">properties to copy</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Deserialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.GetKeys">
+ <summary>
+ Gets the key names.
+ </summary>
+ <returns>An array of all the keys.</returns>
+ <remarks>
+ <para>
+ Gets the key names.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.Contains(System.String)">
+ <summary>
+ Test if the dictionary contains a specified key
+ </summary>
+ <param name="key">the key to look for</param>
+ <returns>true if the dictionary contains the specified key</returns>
+ <remarks>
+ <para>
+ Test if the dictionary contains a specified key
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
+ <param name="context">The destination for this serialization.</param>
+ <remarks>
+ <para>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Remove(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Remove(System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Contains(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Contains(System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.Clear">
+ <summary>
+ Remove all properties from the properties collection
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Add(System.Object,System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Add(System.Object,System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ <param name="value"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
+ <summary>
+ See <see cref="M:System.Collections.ICollection.CopyTo(System.Array,System.Int32)"/>
+ </summary>
+ <param name="array"></param>
+ <param name="index"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IEnumerable.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.Item(System.String)">
+ <summary>
+ Gets or sets the value of the property with the specified key.
+ </summary>
+ <value>
+ The value of the property with the specified key.
+ </value>
+ <param name="key">The key of the property to get or set.</param>
+ <remarks>
+ <para>
+ The property value will only be serialized if it is serializable.
+ If it cannot be serialized it will be silently ignored if
+ a serialization operation is performed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.InnerHashtable">
+ <summary>
+ The hashtable used to store the properties
+ </summary>
+ <value>
+ The internal collection used to store the properties
+ </value>
+ <remarks>
+ <para>
+ The hashtable used to store the properties
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#IsReadOnly">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsReadOnly"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Item(System.Object)">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Item(System.Object)"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Values">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Values"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Keys">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Keys"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#IsFixedSize">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsFixedSize"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#IsSynchronized">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.IsSynchronized"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.Count">
+ <summary>
+ The number of properties in this collection
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#SyncRoot">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.SyncRoot"/>
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="propertiesDictionary">properties to copy</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class
+ with serialized data.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Because this class is sealed the serialization constructor is private.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.Remove(System.String)">
+ <summary>
+ Remove the entry with the specified key from this dictionary
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove the entry with the specified key from this dictionary
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.GetEnumerator"/>
+ </summary>
+ <returns>an enumerator</returns>
+ <remarks>
+ <para>
+ Returns a <see cref="T:System.Collections.IDictionaryEnumerator"/> over the contest of this collection.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Remove(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Remove(System.Object)"/>
+ </summary>
+ <param name="key">the key to remove</param>
+ <remarks>
+ <para>
+ Remove the entry with the specified key from this dictionary
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Contains(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Contains(System.Object)"/>
+ </summary>
+ <param name="key">the key to lookup in the collection</param>
+ <returns><c>true</c> if the collection contains the specified key</returns>
+ <remarks>
+ <para>
+ Test if this collection contains a specified key.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.Clear">
+ <summary>
+ Remove all properties from the properties collection
+ </summary>
+ <remarks>
+ <para>
+ Remove all properties from the properties collection
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Add(System.Object,System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Add(System.Object,System.Object)"/>
+ </summary>
+ <param name="key">the key</param>
+ <param name="value">the value to store for the key</param>
+ <remarks>
+ <para>
+ Store a value for the specified <see cref="T:System.String"/> <paramref name="key"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">Thrown if the <paramref name="key"/> is not a string</exception>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
+ <summary>
+ See <see cref="M:System.Collections.ICollection.CopyTo(System.Array,System.Int32)"/>
+ </summary>
+ <param name="array"></param>
+ <param name="index"></param>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IEnumerable.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.Item(System.String)">
+ <summary>
+ Gets or sets the value of the property with the specified key.
+ </summary>
+ <value>
+ The value of the property with the specified key.
+ </value>
+ <param name="key">The key of the property to get or set.</param>
+ <remarks>
+ <para>
+ The property value will only be serialized if it is serializable.
+ If it cannot be serialized it will be silently ignored if
+ a serialization operation is performed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#IsReadOnly">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsReadOnly"/>
+ </summary>
+ <value>
+ <c>false</c>
+ </value>
+ <remarks>
+ <para>
+ This collection is modifiable. This property always
+ returns <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Item(System.Object)">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Item(System.Object)"/>
+ </summary>
+ <value>
+ The value for the key specified.
+ </value>
+ <remarks>
+ <para>
+ Get or set a value for the specified <see cref="T:System.String"/> <paramref name="key"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">Thrown if the <paramref name="key"/> is not a string</exception>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Values">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Values"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Keys">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Keys"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#IsFixedSize">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsFixedSize"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#ICollection#IsSynchronized">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.IsSynchronized"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#ICollection#SyncRoot">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.SyncRoot"/>
+ </summary>
+ </member>
+ <member name="T:log4net.Util.ProtectCloseTextWriter">
+ <summary>
+ A <see cref="T:System.IO.TextWriter"/> that ignores the <see cref="M:log4net.Util.ProtectCloseTextWriter.Close"/> message
+ </summary>
+ <remarks>
+ <para>
+ This writer is used in special cases where it is necessary
+ to protect a writer from being closed by a client.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.#ctor(System.IO.TextWriter)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">the writer to actually write to</param>
+ <remarks>
+ <para>
+ Create a new ProtectCloseTextWriter using a writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.Attach(System.IO.TextWriter)">
+ <summary>
+ Attach this instance to a different underlying <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to attach to</param>
+ <remarks>
+ <para>
+ Attach this instance to a different underlying <see cref="T:System.IO.TextWriter"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.Close">
+ <summary>
+ Does not close the underlying output writer.
+ </summary>
+ <remarks>
+ <para>
+ Does not close the underlying output writer.
+ This method does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ReaderWriterLock">
+ <summary>
+ Defines a lock that supports single writers and multiple readers
+ </summary>
+ <remarks>
+ <para>
+ <c>ReaderWriterLock</c> is used to synchronize access to a resource.
+ At any given time, it allows either concurrent read access for
+ multiple threads, or write access for a single thread. In a
+ situation where a resource is changed infrequently, a
+ <c>ReaderWriterLock</c> provides better throughput than a simple
+ one-at-a-time lock, such as <see cref="T:System.Threading.Monitor"/>.
+ </para>
+ <para>
+ If a platform does not support a <c>System.Threading.ReaderWriterLock</c>
+ implementation then all readers and writers are serialized. Therefore
+ the caller must not rely on multiple simultaneous readers.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReaderWriterLock"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.AcquireReaderLock">
+ <summary>
+ Acquires a reader lock
+ </summary>
+ <remarks>
+ <para>
+ <see cref="M:log4net.Util.ReaderWriterLock.AcquireReaderLock"/> blocks if a different thread has the writer
+ lock, or if at least one thread is waiting for the writer lock.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.ReleaseReaderLock">
+ <summary>
+ Decrements the lock count
+ </summary>
+ <remarks>
+ <para>
+ <see cref="M:log4net.Util.ReaderWriterLock.ReleaseReaderLock"/> decrements the lock count. When the count
+ reaches zero, the lock is released.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.AcquireWriterLock">
+ <summary>
+ Acquires the writer lock
+ </summary>
+ <remarks>
+ <para>
+ This method blocks if another thread has a reader lock or writer lock.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.ReleaseWriterLock">
+ <summary>
+ Decrements the lock count on the writer lock
+ </summary>
+ <remarks>
+ <para>
+ ReleaseWriterLock decrements the writer lock count.
+ When the count reaches zero, the writer lock is released.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ReusableStringWriter">
+ <summary>
+ A <see cref="T:System.IO.StringWriter"/> that can be <see cref="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)"/> and reused
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="T:System.IO.StringWriter"/> that can be <see cref="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)"/> and reused.
+ This uses a single buffer for string operations.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.#ctor(System.IFormatProvider)">
+ <summary>
+ Create an instance of <see cref="T:log4net.Util.ReusableStringWriter"/>
+ </summary>
+ <param name="formatProvider">the format provider to use</param>
+ <remarks>
+ <para>
+ Create an instance of <see cref="T:log4net.Util.ReusableStringWriter"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.Dispose(System.Boolean)">
+ <summary>
+ Override Dispose to prevent closing of writer
+ </summary>
+ <param name="disposing">flag</param>
+ <remarks>
+ <para>
+ Override Dispose to prevent closing of writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)">
+ <summary>
+ Reset this string writer so that it can be reused.
+ </summary>
+ <param name="maxCapacity">the maximum buffer capacity before it is trimmed</param>
+ <param name="defaultSize">the default size to make the buffer</param>
+ <remarks>
+ <para>
+ Reset this string writer so that it can be reused.
+ The internal buffers are cleared and reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.SystemInfo">
+ <summary>
+ Utility class for system specific information.
+ </summary>
+ <remarks>
+ <para>
+ Utility class of static methods for system specific information.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Alexey Solofnenko</author>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.#ctor">
+ <summary>
+ Private constructor to prevent instances.
+ </summary>
+ <remarks>
+ <para>
+ Only static methods are exposed from this type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.#cctor">
+ <summary>
+ Initialize default values for private static fields.
+ </summary>
+ <remarks>
+ <para>
+ Only static methods are exposed from this type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyLocationInfo(System.Reflection.Assembly)">
+ <summary>
+ Gets the assembly location path for the specified assembly.
+ </summary>
+ <param name="myAssembly">The assembly to get the location for.</param>
+ <returns>The location of the assembly.</returns>
+ <remarks>
+ <para>
+ This method does not guarantee to return the correct path
+ to the assembly. If only tries to give an indication as to
+ where the assembly was loaded from.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyQualifiedName(System.Type)">
+ <summary>
+ Gets the fully qualified name of the <see cref="T:System.Type"/>, including
+ the name of the assembly from which the <see cref="T:System.Type"/> was
+ loaded.
+ </summary>
+ <param name="type">The <see cref="T:System.Type"/> to get the fully qualified name for.</param>
+ <returns>The fully qualified name for the <see cref="T:System.Type"/>.</returns>
+ <remarks>
+ <para>
+ This is equivalent to the <c>Type.AssemblyQualifiedName</c> property,
+ but this method works on the .NET Compact Framework 1.0 as well as
+ the full .NET runtime.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyShortName(System.Reflection.Assembly)">
+ <summary>
+ Gets the short name of the <see cref="T:System.Reflection.Assembly"/>.
+ </summary>
+ <param name="myAssembly">The <see cref="T:System.Reflection.Assembly"/> to get the name for.</param>
+ <returns>The short name of the <see cref="T:System.Reflection.Assembly"/>.</returns>
+ <remarks>
+ <para>
+ The short name of the assembly is the <see cref="P:System.Reflection.Assembly.FullName"/>
+ without the version, culture, or public key. i.e. it is just the
+ assembly's file name without the extension.
+ </para>
+ <para>
+ Use this rather than <c>Assembly.GetName().Name</c> because that
+ is not available on the Compact Framework.
+ </para>
+ <para>
+ Because of a FileIOPermission security demand we cannot do
+ the obvious Assembly.GetName().Name. We are allowed to get
+ the <see cref="P:System.Reflection.Assembly.FullName"/> of the assembly so we
+ start from there and strip out just the assembly name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyFileName(System.Reflection.Assembly)">
+ <summary>
+ Gets the file name portion of the <see cref="T:System.Reflection.Assembly"/>, including the extension.
+ </summary>
+ <param name="myAssembly">The <see cref="T:System.Reflection.Assembly"/> to get the file name for.</param>
+ <returns>The file name of the assembly.</returns>
+ <remarks>
+ <para>
+ Gets the file name portion of the <see cref="T:System.Reflection.Assembly"/>, including the extension.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.Type,System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="relativeType">A sibling type to use to load the type.</param>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified, it will be loaded from the assembly
+ containing the specified relative type. If the type is not found in the assembly
+ then all the loaded assemblies will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified it will be loaded from the
+ assembly that is directly calling this method. If the type is not found
+ in the assembly then all the loaded assemblies will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.Reflection.Assembly,System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="relativeAssembly">An assembly to load the type from.</param>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified it will be loaded from the specified
+ assembly. If the type is not found in the assembly then all the loaded assemblies
+ will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.NewGuid">
+ <summary>
+ Generate a new guid
+ </summary>
+ <returns>A new Guid</returns>
+ <remarks>
+ <para>
+ Generate a new guid
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.CreateArgumentOutOfRangeException(System.String,System.Object,System.String)">
+ <summary>
+ Create an <see cref="T:System.ArgumentOutOfRangeException"/>
+ </summary>
+ <param name="parameterName">The name of the parameter that caused the exception</param>
+ <param name="actualValue">The value of the argument that causes this exception</param>
+ <param name="message">The message that describes the error</param>
+ <returns>the ArgumentOutOfRangeException object</returns>
+ <remarks>
+ <para>
+ Create a new instance of the <see cref="T:System.ArgumentOutOfRangeException"/> class
+ with a specified error message, the parameter name, and the value
+ of the argument.
+ </para>
+ <para>
+ The Compact Framework does not support the 3 parameter constructor for the
+ <see cref="T:System.ArgumentOutOfRangeException"/> type. This method provides an
+ implementation that works for all platforms.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.TryParse(System.String,System.Int32@)">
+ <summary>
+ Parse a string into an <see cref="T:System.Int32"/> value
+ </summary>
+ <param name="s">the string to parse</param>
+ <param name="val">out param where the parsed value is placed</param>
+ <returns><c>true</c> if the string was able to be parsed into an integer</returns>
+ <remarks>
+ <para>
+ Attempts to parse the string into an integer. If the string cannot
+ be parsed then this method returns <c>false</c>. The method does not throw an exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.TryParse(System.String,System.Int64@)">
+ <summary>
+ Parse a string into an <see cref="T:System.Int64"/> value
+ </summary>
+ <param name="s">the string to parse</param>
+ <param name="val">out param where the parsed value is placed</param>
+ <returns><c>true</c> if the string was able to be parsed into an integer</returns>
+ <remarks>
+ <para>
+ Attempts to parse the string into an integer. If the string cannot
+ be parsed then this method returns <c>false</c>. The method does not throw an exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetAppSetting(System.String)">
+ <summary>
+ Lookup an application setting
+ </summary>
+ <param name="key">the application settings key to lookup</param>
+ <returns>the value for the key, or <c>null</c></returns>
+ <remarks>
+ <para>
+ Configuration APIs are not supported under the Compact Framework
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified local file path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ <para>
+ The path specified must be a local file path, a URI is not supported.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.CreateCaseInsensitiveHashtable">
+ <summary>
+ Creates a new case-insensitive instance of the <see cref="T:System.Collections.Hashtable"/> class with the default initial capacity.
+ </summary>
+ <returns>A new case-insensitive instance of the <see cref="T:System.Collections.Hashtable"/> class with the default initial capacity</returns>
+ <remarks>
+ <para>
+ The new Hashtable instance uses the default load factor, the CaseInsensitiveHashCodeProvider, and the CaseInsensitiveComparer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.EmptyTypes">
+ <summary>
+ Gets an empty array of types.
+ </summary>
+ <remarks>
+ <para>
+ The <c>Type.EmptyTypes</c> field is not available on
+ the .NET Compact Framework 1.0.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_hostName">
+ <summary>
+ Cache the host name for the current machine
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_appFriendlyName">
+ <summary>
+ Cache the application friendly name
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_nullText">
+ <summary>
+ Text to output when a <c>null</c> is encountered.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_notAvailableText">
+ <summary>
+ Text to output when an unsupported feature is requested.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_processStartTime">
+ <summary>
+ Start time for the current process.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NewLine">
+ <summary>
+ Gets the system dependent line terminator.
+ </summary>
+ <value>
+ The system dependent line terminator.
+ </value>
+ <remarks>
+ <para>
+ Gets the system dependent line terminator.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ApplicationBaseDirectory">
+ <summary>
+ Gets the base directory for this <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The base directory path for the current <see cref="T:System.AppDomain"/>.</value>
+ <remarks>
+ <para>
+ Gets the base directory for this <see cref="T:System.AppDomain"/>.
+ </para>
+ <para>
+ The value returned may be either a local file path or a URI.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ConfigurationFileLocation">
+ <summary>
+ Gets the path to the configuration file for the current <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The path to the configuration file for the current <see cref="T:System.AppDomain"/>.</value>
+ <remarks>
+ <para>
+ The .NET Compact Framework 1.0 does not have a concept of a configuration
+ file. For this runtime, we use the entry assembly location as the root for
+ the configuration file name.
+ </para>
+ <para>
+ The value returned may be either a local file path or a URI.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.EntryAssemblyLocation">
+ <summary>
+ Gets the path to the file that first executed in the current <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The path to the entry assembly.</value>
+ <remarks>
+ <para>
+ Gets the path to the file that first executed in the current <see cref="T:System.AppDomain"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.CurrentThreadId">
+ <summary>
+ Gets the ID of the current thread.
+ </summary>
+ <value>The ID of the current thread.</value>
+ <remarks>
+ <para>
+ On the .NET framework, the <c>AppDomain.GetCurrentThreadId</c> method
+ is used to obtain the thread ID for the current thread. This is the
+ operating system ID for the thread.
+ </para>
+ <para>
+ On the .NET Compact Framework 1.0 it is not possible to get the
+ operating system thread ID for the current thread. The native method
+ <c>GetCurrentThreadId</c> is implemented inline in a header file
+ and cannot be called.
+ </para>
+ <para>
+ On the .NET Framework 2.0 the <c>Thread.ManagedThreadId</c> is used as this
+ gives a stable id unrelated to the operating system thread ID which may
+ change if the runtime is using fibers.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.HostName">
+ <summary>
+ Get the host name or machine name for the current machine
+ </summary>
+ <value>
+ The hostname or machine name
+ </value>
+ <remarks>
+ <para>
+ Get the host name or machine name for the current machine
+ </para>
+ <para>
+ The host name (<see cref="M:System.Net.Dns.GetHostName"/>) or
+ the machine name (<c>Environment.MachineName</c>) for
+ the current machine, or if neither of these are available
+ then <c>NOT AVAILABLE</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ApplicationFriendlyName">
+ <summary>
+ Get this application's friendly name
+ </summary>
+ <value>
+ The friendly name of this application as a string
+ </value>
+ <remarks>
+ <para>
+ If available the name of the application is retrieved from
+ the <c>AppDomain</c> using <c>AppDomain.CurrentDomain.FriendlyName</c>.
+ </para>
+ <para>
+ Otherwise the file name of the entry assembly is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ProcessStartTime">
+ <summary>
+ Get the start time for the current process.
+ </summary>
+ <remarks>
+ <para>
+ This is the time at which the log4net library was loaded into the
+ AppDomain. Due to reports of a hang in the call to <c>System.Diagnostics.Process.StartTime</c>
+ this is not the start time for the current process.
+ </para>
+ <para>
+ The log4net library should be loaded by an application early during its
+ startup, therefore this start time should be a good approximation for
+ the actual start time.
+ </para>
+ <para>
+ Note that AppDomains may be loaded and unloaded within the
+ same process without the process terminating, however this start time
+ will be set per AppDomain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NullText">
+ <summary>
+ Text to output when a <c>null</c> is encountered.
+ </summary>
+ <remarks>
+ <para>
+ Use this value to indicate a <c>null</c> has been encountered while
+ outputting a string representation of an item.
+ </para>
+ <para>
+ The default value is <c>(null)</c>. This value can be overridden by specifying
+ a value for the <c>log4net.NullText</c> appSetting in the application's
+ .config file.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NotAvailableText">
+ <summary>
+ Text to output when an unsupported feature is requested.
+ </summary>
+ <remarks>
+ <para>
+ Use this value when an unsupported feature is requested.
+ </para>
+ <para>
+ The default value is <c>NOT AVAILABLE</c>. This value can be overridden by specifying
+ a value for the <c>log4net.NotAvailableText</c> appSetting in the application's
+ .config file.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.SystemStringFormat">
+ <summary>
+ Utility class that represents a format string.
+ </summary>
+ <remarks>
+ <para>
+ Utility class that represents a format string.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.#ctor(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Initialise the <see cref="T:log4net.Util.SystemStringFormat"/>
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information.</param>
+ <param name="format">A <see cref="T:System.String"/> containing zero or more format items.</param>
+ <param name="args">An <see cref="T:System.Object"/> array containing zero or more objects to format.</param>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.ToString">
+ <summary>
+ Format the string and arguments
+ </summary>
+ <returns>the formatted string</returns>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.StringFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Replaces the format item in a specified <see cref="T:System.String"/> with the text equivalent
+ of the value of a corresponding <see cref="T:System.Object"/> instance in a specified array.
+ A specified parameter supplies culture-specific formatting information.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information.</param>
+ <param name="format">A <see cref="T:System.String"/> containing zero or more format items.</param>
+ <param name="args">An <see cref="T:System.Object"/> array containing zero or more objects to format.</param>
+ <returns>
+ A copy of format in which the format items have been replaced by the <see cref="T:System.String"/>
+ equivalent of the corresponding instances of <see cref="T:System.Object"/> in args.
+ </returns>
+ <remarks>
+ <para>
+ This method does not throw exceptions. If an exception thrown while formatting the result the
+ exception and arguments are returned in the result string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.StringFormatError(System.Exception,System.String,System.Object[])">
+ <summary>
+ Process an error during StringFormat
+ </summary>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.RenderArray(System.Array,System.Text.StringBuilder)">
+ <summary>
+ Dump the contents of an array into a string builder
+ </summary>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.RenderObject(System.Object,System.Text.StringBuilder)">
+ <summary>
+ Dump an object to a string
+ </summary>
+ </member>
+ <member name="T:log4net.Util.ThreadContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Class implements a collection of properties that is specific to each thread.
+ The class is not synchronized as each thread has its own <see cref="T:log4net.Util.PropertiesDictionary"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.ThreadContextProperties.s_threadLocalSlot">
+ <summary>
+ The thread local data slot to use to store a PropertiesDictionary.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.#ctor">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove a property
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.Clear">
+ <summary>
+ Clear all properties
+ </summary>
+ <remarks>
+ <para>
+ Clear all properties
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.GetProperties(System.Boolean)">
+ <summary>
+ Get the <c>PropertiesDictionary</c> for this thread.
+ </summary>
+ <param name="create">create the dictionary if it does not exist, otherwise return null if is does not exist</param>
+ <returns>the properties for this thread</returns>
+ <remarks>
+ <para>
+ The collection returned is only to be used on the calling thread. If the
+ caller needs to share the collection between different threads then the
+ caller must clone the collection before doing so.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the value of a property
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack">
+ <summary>
+ Implementation of Stack for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Implementation of Stack for the <see cref="T:log4net.ThreadContext"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.m_stack">
+ <summary>
+ The stack store.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.#ctor">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Clear">
+ <summary>
+ Clears all the contextual information held in this stack.
+ </summary>
+ <remarks>
+ <para>
+ Clears all the contextual information held in this stack.
+ Only call this if you think that this tread is being reused after
+ a previous call execution which may not have completed correctly.
+ You do not need to use this method if you always guarantee to call
+ the <see cref="M:System.IDisposable.Dispose"/> method of the <see cref="T:System.IDisposable"/>
+ returned from <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> even in exceptional circumstances,
+ for example by using the <c>using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message"))</c>
+ syntax.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Pop">
+ <summary>
+ Removes the top context from this stack.
+ </summary>
+ <returns>The message in the context that was removed from the top of this stack.</returns>
+ <remarks>
+ <para>
+ Remove the top context from this stack, and return
+ it to the caller. If this stack is empty then an
+ empty string (not <see langword="null"/>) is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Push(System.String)">
+ <summary>
+ Pushes a new context message into this stack.
+ </summary>
+ <param name="message">The new context message.</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> that can be used to clean up the context stack.
+ </returns>
+ <remarks>
+ <para>
+ Pushes a new context onto this stack. An <see cref="T:System.IDisposable"/>
+ is returned that can be used to clean up this stack. This
+ can be easily combined with the <c>using</c> keyword to scope the
+ context.
+ </para>
+ </remarks>
+ <example>Simple example of using the <c>Push</c> method with the <c>using</c> keyword.
+ <code lang="C#">
+ using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message"))
+ {
+ log.Warn("This should have an ThreadContext Stack message");
+ }
+ </code>
+ </example>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.GetFullMessage">
+ <summary>
+ Gets the current context information for this stack.
+ </summary>
+ <returns>The current context information.</returns>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.ToString">
+ <summary>
+ Gets the current context information for this stack.
+ </summary>
+ <returns>Gets the current context information</returns>
+ <remarks>
+ <para>
+ Gets the current context information for this stack.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.log4net#Core#IFixingRequired#GetFixedObject">
+ <summary>
+ Get a portable version of this object
+ </summary>
+ <returns>the portable instance of this object</returns>
+ <remarks>
+ <para>
+ Get a cross thread portable version of this object
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.Count">
+ <summary>
+ The number of messages in the stack
+ </summary>
+ <value>
+ The current number of messages in the stack
+ </value>
+ <remarks>
+ <para>
+ The current number of messages in the stack. That is
+ the number of times <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> has been called
+ minus the number of times <see cref="M:log4net.Util.ThreadContextStack.Pop"/> has been called.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.InternalStack">
+ <summary>
+ Gets and sets the internal stack used by this <see cref="T:log4net.Util.ThreadContextStack"/>
+ </summary>
+ <value>The internal storage stack</value>
+ <remarks>
+ <para>
+ This property is provided only to support backward compatability
+ of the <see cref="T:log4net.NDC"/>. Tytpically the internal stack should not
+ be modified.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack.StackFrame">
+ <summary>
+ Inner class used to represent a single context frame in the stack.
+ </summary>
+ <remarks>
+ <para>
+ Inner class used to represent a single context frame in the stack.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.StackFrame.#ctor(System.String,log4net.Util.ThreadContextStack.StackFrame)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">The message for this context.</param>
+ <param name="parent">The parent context in the chain.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack.StackFrame"/> class
+ with the specified message and parent context.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.StackFrame.Message">
+ <summary>
+ Get the message.
+ </summary>
+ <value>The message.</value>
+ <remarks>
+ <para>
+ Get the message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.StackFrame.FullMessage">
+ <summary>
+ Gets the full text of the context down to the root level.
+ </summary>
+ <value>
+ The full text of the context down to the root level.
+ </value>
+ <remarks>
+ <para>
+ Gets the full text of the context down to the root level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack.AutoPopStackFrame">
+ <summary>
+ Struct returned from the <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ This struct implements the <see cref="T:System.IDisposable"/> and is designed to be used
+ with the <see langword="using"/> pattern to remove the stack frame at the end of the scope.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.AutoPopStackFrame.m_frameStack">
+ <summary>
+ The ThreadContextStack internal stack
+ </summary>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.AutoPopStackFrame.m_frameDepth">
+ <summary>
+ The depth to trim the stack to when this instance is disposed
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.AutoPopStackFrame.#ctor(System.Collections.Stack,System.Int32)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="frameStack">The internal stack used by the ThreadContextStack.</param>
+ <param name="frameDepth">The depth to return the stack to when this object is disposed.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack.AutoPopStackFrame"/> class with
+ the specified stack and return depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.AutoPopStackFrame.Dispose">
+ <summary>
+ Returns the stack to the correct depth.
+ </summary>
+ <remarks>
+ <para>
+ Returns the stack to the correct depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStacks">
+ <summary>
+ Implementation of Stacks collection for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Implementation of Stacks collection for the <see cref="T:log4net.ThreadContext"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStacks.#ctor(log4net.Util.ContextPropertiesBase)">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStacks"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStacks.Item(System.String)">
+ <summary>
+ Gets the named thread context stack
+ </summary>
+ <value>
+ The named stack
+ </value>
+ <remarks>
+ <para>
+ Gets the named thread context stack
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.Transform">
+ <summary>
+ Utility class for transforming strings.
+ </summary>
+ <remarks>
+ <para>
+ Utility class for transforming strings.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.Transform.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.Transform"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.WriteEscapedXmlString(System.Xml.XmlWriter,System.String,System.String)">
+ <summary>
+ Write a string to an <see cref="T:System.Xml.XmlWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="textData">the string to write</param>
+ <param name="invalidCharReplacement">The string to replace non XML compliant chars with</param>
+ <remarks>
+ <para>
+ The test is escaped either using XML escape entities
+ or using CDATA sections.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.MaskXmlInvalidCharacters(System.String,System.String)">
+ <summary>
+ Replace invalid XML characters in text string
+ </summary>
+ <param name="textData">the XML text input string</param>
+ <param name="mask">the string to use in place of invalid characters</param>
+ <returns>A string that does not contain invalid XML characters.</returns>
+ <remarks>
+ <para>
+ Certain Unicode code points are not allowed in the XML InfoSet, for
+ details see: <a href="http://www.w3.org/TR/REC-xml/#charsets">http://www.w3.org/TR/REC-xml/#charsets</a>.
+ </para>
+ <para>
+ This method replaces any illegal characters in the input string
+ with the mask string specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.CountSubstrings(System.String,System.String)">
+ <summary>
+ Count the number of times that the substring occurs in the text
+ </summary>
+ <param name="text">the text to search</param>
+ <param name="substring">the substring to find</param>
+ <returns>the number of times the substring occurs in the text</returns>
+ <remarks>
+ <para>
+ The substring is assumed to be non repeating within itself.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext">
+ <summary>
+ Impersonate a Windows Account
+ </summary>
+ <remarks>
+ <para>
+ This <see cref="T:log4net.Core.SecurityContext"/> impersonates a Windows account.
+ </para>
+ <para>
+ How the impersonation is done depends on the value of <see cref="M:log4net.Util.WindowsSecurityContext.Impersonate(System.Object)"/>.
+ This allows the context to either impersonate a set of user credentials specified
+ using username, domain name and password or to revert to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.ActivateOptions">
+ <summary>
+ Initialize the SecurityContext based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The security context will try to Logon the specified user account and
+ capture a primary token for impersonation.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/>,
+ <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> or <see cref="P:log4net.Util.WindowsSecurityContext.Password"/> properties were not specified.</exception>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </summary>
+ <param name="state">caller provided state</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> instance that will revoke the impersonation of this SecurityContext
+ </returns>
+ <remarks>
+ <para>
+ Depending on the <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/> property either
+ impersonate a user using credentials supplied or revert
+ to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.LogonUser(System.String,System.String,System.String)">
+ <summary>
+ Create a <see cref="T:System.Security.Principal.WindowsIdentity"/> given the userName, domainName and password.
+ </summary>
+ <param name="userName">the user name</param>
+ <param name="domainName">the domain name</param>
+ <param name="password">the password</param>
+ <returns>the <see cref="T:System.Security.Principal.WindowsIdentity"/> for the account specified</returns>
+ <remarks>
+ <para>
+ Uses the Windows API call LogonUser to get a principal token for the account. This
+ token is used to initialize the WindowsIdentity.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.Credentials">
+ <summary>
+ Gets or sets the impersonation mode for this security context
+ </summary>
+ <value>
+ The impersonation mode for this security context
+ </value>
+ <remarks>
+ <para>
+ Impersonate either a user with user credentials or
+ revert this thread to the credentials of the process.
+ The value is one of the <see cref="T:log4net.Util.WindowsSecurityContext.ImpersonationMode"/>
+ enum.
+ </para>
+ <para>
+ The default value is <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/>
+ </para>
+ <para>
+ When the mode is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/>
+ the user's credentials are established using the
+ <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/>, <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.Password"/>
+ values.
+ </para>
+ <para>
+ When the mode is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.Process"/>
+ no other properties need to be set. If the calling thread is
+ impersonating then it will be reverted back to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.UserName">
+ <summary>
+ Gets or sets the Windows username for this security context
+ </summary>
+ <value>
+ The Windows username for this security context
+ </value>
+ <remarks>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.DomainName">
+ <summary>
+ Gets or sets the Windows domain name for this security context
+ </summary>
+ <value>
+ The Windows domain name for this security context
+ </value>
+ <remarks>
+ <para>
+ The default value for <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> is the local machine name
+ taken from the <see cref="P:System.Environment.MachineName"/> property.
+ </para>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.Password">
+ <summary>
+ Sets the password for the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </summary>
+ <value>
+ The password for the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </value>
+ <remarks>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext.ImpersonationMode">
+ <summary>
+ The impersonation modes for the <see cref="T:log4net.Util.WindowsSecurityContext"/>
+ </summary>
+ <remarks>
+ <para>
+ See the <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/> property for
+ details.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User">
+ <summary>
+ Impersonate a user using the credentials supplied
+ </summary>
+ </member>
+ <member name="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.Process">
+ <summary>
+ Revert this the thread to the credentials of the process
+ </summary>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext">
+ <summary>
+ Adds <see cref="T:System.IDisposable"/> to <see cref="T:System.Security.Principal.WindowsImpersonationContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Helper class to expose the <see cref="T:System.Security.Principal.WindowsImpersonationContext"/>
+ through the <see cref="T:System.IDisposable"/> interface.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext.#ctor(System.Security.Principal.WindowsImpersonationContext)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="impersonationContext">the impersonation context being wrapped</param>
+ <remarks>
+ <para>
+ Constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext.Dispose">
+ <summary>
+ Revert the impersonation
+ </summary>
+ <remarks>
+ <para>
+ Revert the impersonation
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.GlobalContext">
+ <summary>
+ The log4net Global Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>GlobalContext</c> provides a location for global debugging
+ information to be stored.
+ </para>
+ <para>
+ The global context has a properties map and these properties can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputing these properties.
+ </para>
+ <para>
+ By default the <c>log4net:HostName</c> property is set to the name of
+ the current machine.
+ </para>
+ </remarks>
+ <example>
+ <code lang="C#">
+ GlobalContext.Properties["hostname"] = Environment.MachineName;
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.GlobalContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="F:log4net.GlobalContext.s_properties">
+ <summary>
+ The global context properties instance
+ </summary>
+ </member>
+ <member name="P:log4net.GlobalContext.Properties">
+ <summary>
+ The global properties map.
+ </summary>
+ <value>
+ The global properties map.
+ </value>
+ <remarks>
+ <para>
+ The global properties map.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.LogicalThreadContext">
+ <summary>
+ The log4net Logical Thread Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>LogicalThreadContext</c> provides a location for <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/> specific debugging
+ information to be stored.
+ The <c>LogicalThreadContext</c> properties override any <see cref="T:log4net.ThreadContext"/> or <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ <para>
+ The Logical Thread Context has a properties map and a stack.
+ The properties and stack can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputting these properties.
+ </para>
+ <para>
+ The Logical Thread Context provides a diagnostic context for the current call context.
+ This is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The Logical Thread Context is managed on a per <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/> basis.
+ </para>
+ </remarks>
+ <example>Example of using the thread context properties to store a username.
+ <code lang="C#">
+ LogicalThreadContext.Properties["user"] = userName;
+ log.Info("This log message has a LogicalThreadContext Property called 'user'");
+ </code>
+ </example>
+ <example>Example of how to push a message into the context stack
+ <code lang="C#">
+ using(LogicalThreadContext.Stacks["LDC"].Push("my context message"))
+ {
+ log.Info("This log message has a LogicalThreadContext Stack message that includes 'my context message'");
+
+ } // at the end of the using block the message is automatically popped
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.LogicalThreadContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.LogicalThreadContext.s_properties">
+ <summary>
+ The thread context properties instance
+ </summary>
+ </member>
+ <member name="F:log4net.LogicalThreadContext.s_stacks">
+ <summary>
+ The thread context stacks instance
+ </summary>
+ </member>
+ <member name="P:log4net.LogicalThreadContext.Properties">
+ <summary>
+ The thread properties map
+ </summary>
+ <value>
+ The thread properties map
+ </value>
+ <remarks>
+ <para>
+ The <c>LogicalThreadContext</c> properties override any <see cref="T:log4net.ThreadContext"/>
+ or <see cref="T:log4net.GlobalContext"/> properties with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.LogicalThreadContext.Stacks">
+ <summary>
+ The thread stacks
+ </summary>
+ <value>
+ stack map
+ </value>
+ <remarks>
+ <para>
+ The logical thread stacks.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.LogManager">
+ <summary>
+ This class is used by client applications to request logger instances.
+ </summary>
+ <remarks>
+ <para>
+ This class has static methods that are used by a client to request
+ a logger instance. The <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method is
+ used to retrieve a logger.
+ </para>
+ <para>
+ See the <see cref="T:log4net.ILog"/> interface for more details.
+ </para>
+ </remarks>
+ <example>Simple example of logging messages
+ <code lang="C#">
+ ILog log = LogManager.GetLogger("application-log");
+
+ log.Info("Application Start");
+ log.Debug("This is a debug message");
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is another debug message");
+ }
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <seealso cref="T:log4net.ILog"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.LogManager.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.LogManager"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.String)">
+ <overloads>Returns the named logger if it exists.</overloads>
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the default repository) then it
+ returns a reference to the logger, otherwise it returns <c>null</c>.
+ </para>
+ </remarks>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>The logger found, or <c>null</c> if no logger could be found.</returns>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.String,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the logger doesn't exist in the specified
+ repository.
+ </returns>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.Reflection.Assembly,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the repository for the specified assembly) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger, or <c>null</c> if the logger doesn't exist in the specified
+ assembly's repository.
+ </returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers">
+ <overloads>Get the currently defined loggers.</overloads>
+ <summary>
+ Returns all the currently defined loggers in the default repository.
+ </summary>
+ <remarks>
+ <para>The root logger is <b>not</b> included in the returned array.</para>
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers(System.String)">
+ <summary>
+ Returns all the currently defined loggers in the specified repository.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <remarks>
+ The root logger is <b>not</b> included in the returned array.
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers(System.Reflection.Assembly)">
+ <summary>
+ Returns all the currently defined loggers in the specified assembly's repository.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <remarks>
+ The root logger is <b>not</b> included in the returned array.
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String)">
+ <overloads>Get or create a logger.</overloads>
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieve a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieve a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Get the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Gets the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Gets the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.Shutdown">
+ <summary>
+ Shuts down the log4net system.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in all the
+ default repositories.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository">
+ <overloads>Shutdown a logger repository.</overloads>
+ <summary>
+ Shuts down the default repository.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ default repository.
+ </para>
+ <para>Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository(System.String)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ <paramref name="repository"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ <param name="repository">The repository to shutdown.</param>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository(System.Reflection.Assembly)">
+ <summary>
+ Shuts down the repository specified.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository. The repository is looked up using
+ the <paramref name="repositoryAssembly"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration">
+ <overloads>Reset the configuration of a repository</overloads>
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration(System.String)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ <param name="repository">The repository to reset.</param>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration(System.Reflection.Assembly)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository to reset.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository">
+ <overloads>Get the logger repository.</overloads>
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the callers assembly (<see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> instance for the default repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository(System.String)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repositoryAssembly"/> argument.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository">
+ <overloads>Get a logger repository.</overloads>
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the callers assembly (<see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> instance for the default repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository(System.String)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repositoryAssembly"/> argument.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.Type)">
+ <overloads>Create a domain</overloads>
+ <summary>
+ Creates a repository with the specified repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository"/> will return
+ the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.Type)">
+ <overloads>Create a logger repository.</overloads>
+ <summary>
+ Creates a repository with the specified repository type.
+ </summary>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository"/> will return
+ the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <remarks>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <remarks>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetAllRepositories">
+ <summary>
+ Gets the list of currently defined repositories.
+ </summary>
+ <remarks>
+ <para>
+ Get an array of all the <see cref="T:log4net.Repository.ILoggerRepository"/> objects that have been created.
+ </para>
+ </remarks>
+ <returns>An array of all the known <see cref="T:log4net.Repository.ILoggerRepository"/> objects.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapLogger(log4net.Core.ILogger)">
+ <summary>
+ Looks up the wrapper object for the logger specified.
+ </summary>
+ <param name="logger">The logger to get the wrapper for.</param>
+ <returns>The wrapper for the logger specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapLoggers(log4net.Core.ILogger[])">
+ <summary>
+ Looks up the wrapper objects for the loggers specified.
+ </summary>
+ <param name="loggers">The loggers to get the wrappers for.</param>
+ <returns>The wrapper objects for the loggers specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapperCreationHandler(log4net.Core.ILogger)">
+ <summary>
+ Create the <see cref="T:log4net.Core.ILoggerWrapper"/> objects used by
+ this manager.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <returns>The wrapper for the logger specified.</returns>
+ </member>
+ <member name="F:log4net.LogManager.s_wrapperMap">
+ <summary>
+ The wrapper map to use to hold the <see cref="T:log4net.Core.LogImpl"/> objects.
+ </summary>
+ </member>
+ <member name="T:log4net.MDC">
+ <summary>
+ Implementation of Mapped Diagnostic Contexts.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ The MDC class is similar to the <see cref="T:log4net.NDC"/> class except that it is
+ based on a map instead of a stack. It provides <i>mapped
+ diagnostic contexts</i>. A <i>Mapped Diagnostic Context</i>, or
+ MDC in short, is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The MDC is managed on a per thread basis.
+ </para>
+ </remarks>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.MDC.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.MDC"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Get(System.String)">
+ <summary>
+ Gets the context value identified by the <paramref name="key"/> parameter.
+ </summary>
+ <param name="key">The key to lookup in the MDC.</param>
+ <returns>The string value held for the key, or a <c>null</c> reference if no corresponding value is found.</returns>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ If the <paramref name="key"/> parameter does not look up to a
+ previously defined context then <c>null</c> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Set(System.String,System.String)">
+ <summary>
+ Add an entry to the MDC
+ </summary>
+ <param name="key">The key to store the value under.</param>
+ <param name="value">The value to store.</param>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Puts a context value (the <paramref name="val"/> parameter) as identified
+ with the <paramref name="key"/> parameter into the current thread's
+ context map.
+ </para>
+ <para>
+ If a value is already defined for the <paramref name="key"/>
+ specified then the value will be replaced. If the <paramref name="val"/>
+ is specified as <c>null</c> then the key value mapping will be removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Remove(System.String)">
+ <summary>
+ Removes the key value mapping for the key specified.
+ </summary>
+ <param name="key">The key to remove.</param>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Remove the specified entry from this thread's MDC
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Clear">
+ <summary>
+ Clear all entries in the MDC
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Remove all the entries from this thread's MDC
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.NDC">
+ <summary>
+ Implementation of Nested Diagnostic Contexts.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ A Nested Diagnostic Context, or NDC in short, is an instrument
+ to distinguish interleaved log output from different sources. Log
+ output is typically interleaved when a server handles multiple
+ clients near-simultaneously.
+ </para>
+ <para>
+ Interleaved log output can still be meaningful if each log entry
+ from different contexts had a distinctive stamp. This is where NDCs
+ come into play.
+ </para>
+ <para>
+ Note that NDCs are managed on a per thread basis. The NDC class
+ is made up of static methods that operate on the context of the
+ calling thread.
+ </para>
+ </remarks>
+ <example>How to push a message into the context
+ <code lang="C#">
+ using(NDC.Push("my context message"))
+ {
+ ... all log calls will have 'my context message' included ...
+
+ } // at the end of the using block the message is automatically removed
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.NDC.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.NDC"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Clear">
+ <summary>
+ Clears all the contextual information held on the current thread.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Clears the stack of NDC data held on the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.CloneStack">
+ <summary>
+ Creates a clone of the stack of context information.
+ </summary>
+ <returns>A clone of the context info for this thread.</returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ The results of this method can be passed to the <see cref="M:log4net.NDC.Inherit(System.Collections.Stack)"/>
+ method to allow child threads to inherit the context of their
+ parent thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Inherit(System.Collections.Stack)">
+ <summary>
+ Inherits the contextual information from another thread.
+ </summary>
+ <param name="stack">The context stack to inherit.</param>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ This thread will use the context information from the stack
+ supplied. This can be used to initialize child threads with
+ the same contextual information as their parent threads. These
+ contexts will <b>NOT</b> be shared. Any further contexts that
+ are pushed onto the stack will not be visible to the other.
+ Call <see cref="M:log4net.NDC.CloneStack"/> to obtain a stack to pass to
+ this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Pop">
+ <summary>
+ Removes the top context from the stack.
+ </summary>
+ <returns>
+ The message in the context that was removed from the top
+ of the stack.
+ </returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Remove the top context from the stack, and return
+ it to the caller. If the stack is empty then an
+ empty string (not <c>null</c>) is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Push(System.String)">
+ <summary>
+ Pushes a new context message.
+ </summary>
+ <param name="message">The new context message.</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> that can be used to clean up
+ the context stack.
+ </returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Pushes a new context onto the context stack. An <see cref="T:System.IDisposable"/>
+ is returned that can be used to clean up the context stack. This
+ can be easily combined with the <c>using</c> keyword to scope the
+ context.
+ </para>
+ </remarks>
+ <example>Simple example of using the <c>Push</c> method with the <c>using</c> keyword.
+ <code lang="C#">
+ using(log4net.NDC.Push("NDC_Message"))
+ {
+ log.Warn("This should have an NDC message");
+ }
+ </code>
+ </example>
+ </member>
+ <member name="M:log4net.NDC.Remove">
+ <summary>
+ Removes the context information for this thread. It is
+ not required to call this method.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ This method is not implemented.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.SetMaxDepth(System.Int32)">
+ <summary>
+ Forces the stack depth to be at most <paramref name="maxDepth"/>.
+ </summary>
+ <param name="maxDepth">The maximum depth of the stack</param>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Forces the stack depth to be at most <paramref name="maxDepth"/>.
+ This may truncate the head of the stack. This only affects the
+ stack in the current thread. Also it does not prevent it from
+ growing, it only sets the maximum depth at the time of the
+ call. This can be used to return to a known context depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.NDC.Depth">
+ <summary>
+ Gets the current context depth.
+ </summary>
+ <value>The current context depth.</value>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ The number of context values pushed onto the context stack.
+ </para>
+ <para>
+ Used to record the current depth of the context. This can then
+ be restored using the <see cref="M:log4net.NDC.SetMaxDepth(System.Int32)"/> method.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.NDC.SetMaxDepth(System.Int32)"/>
+ </member>
+ <member name="T:log4net.ThreadContext">
+ <summary>
+ The log4net Thread Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>ThreadContext</c> provides a location for thread specific debugging
+ information to be stored.
+ The <c>ThreadContext</c> properties override any <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ <para>
+ The thread context has a properties map and a stack.
+ The properties and stack can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputting these properties.
+ </para>
+ <para>
+ The Thread Context provides a diagnostic context for the current thread.
+ This is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The Thread Context is managed on a per thread basis.
+ </para>
+ </remarks>
+ <example>Example of using the thread context properties to store a username.
+ <code lang="C#">
+ ThreadContext.Properties["user"] = userName;
+ log.Info("This log message has a ThreadContext Property called 'user'");
+ </code>
+ </example>
+ <example>Example of how to push a message into the context stack
+ <code lang="C#">
+ using(ThreadContext.Stacks["NDC"].Push("my context message"))
+ {
+ log.Info("This log message has a ThreadContext Stack message that includes 'my context message'");
+
+ } // at the end of the using block the message is automatically popped
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.ThreadContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.ThreadContext.s_properties">
+ <summary>
+ The thread context properties instance
+ </summary>
+ </member>
+ <member name="F:log4net.ThreadContext.s_stacks">
+ <summary>
+ The thread context stacks instance
+ </summary>
+ </member>
+ <member name="P:log4net.ThreadContext.Properties">
+ <summary>
+ The thread properties map
+ </summary>
+ <value>
+ The thread properties map
+ </value>
+ <remarks>
+ <para>
+ The <c>ThreadContext</c> properties override any <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.ThreadContext.Stacks">
+ <summary>
+ The thread stacks
+ </summary>
+ <value>
+ stack map
+ </value>
+ <remarks>
+ <para>
+ The thread local stacks.
+ </para>
+ </remarks>
+ </member>
+ </members>
+</doc>
diff --git a/dotnet/Qpid.Common/lib/saxon/saxon-licence.txt b/dotnet/Qpid.Common/lib/saxon/saxon-licence.txt
new file mode 100644
index 0000000000..1bf2b1279d
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/saxon/saxon-licence.txt
@@ -0,0 +1,471 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (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.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
+
diff --git a/dotnet/Qpid.Common/lib/saxon/saxon8.jar b/dotnet/Qpid.Common/lib/saxon/saxon8.jar
new file mode 100644
index 0000000000..197ce75c5b
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/saxon/saxon8.jar
Binary files differ
diff --git a/dotnet/Qpid.Common/lib/seclib-1.0.0/Org.Mentalis.Security.dll b/dotnet/Qpid.Common/lib/seclib-1.0.0/Org.Mentalis.Security.dll
new file mode 100644
index 0000000000..c3b95d71ba
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/seclib-1.0.0/Org.Mentalis.Security.dll
Binary files differ
diff --git a/dotnet/Qpid.Common/lib/seclib-1.0.0/seclib-license.txt b/dotnet/Qpid.Common/lib/seclib-1.0.0/seclib-license.txt
new file mode 100644
index 0000000000..e837183135
--- /dev/null
+++ b/dotnet/Qpid.Common/lib/seclib-1.0.0/seclib-license.txt
@@ -0,0 +1,13 @@
+Source Code License
+
+Copyright © 2002-2006, The Mentalis.org Team
+All rights reserved.
+http://www.mentalis.org/
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+- Neither the name of the Mentalis.org Team, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/dotnet/Qpid.Common/resources/registry.template b/dotnet/Qpid.Common/resources/registry.template
new file mode 100644
index 0000000000..d870ef3866
--- /dev/null
+++ b/dotnet/Qpid.Common/resources/registry.template
@@ -0,0 +1,24 @@
+<?xml version="1.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.
+ -
+ -->
+<registries>
+ <registry name="MainRegistry"/>
+</registries>
diff --git a/dotnet/Qpid.Common/stylesheets/csharp.xsl b/dotnet/Qpid.Common/stylesheets/csharp.xsl
new file mode 100644
index 0000000000..ed04a40403
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/csharp.xsl
@@ -0,0 +1,251 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<!-- this class contains the templates for generating C# source code for a given framing model -->
+<xsl:import href="utils.xsl"/>
+<xsl:output method="text" indent="yes" name="textFormat"/>
+
+<xsl:param name="registry_name"/>
+
+<xsl:template match="/">
+ <xsl:apply-templates mode="generate-multi" select="frames"/>
+ <xsl:apply-templates mode="generate-registry" select="frames"/>
+</xsl:template>
+
+<!-- processes all frames outputting the classes in a single stream -->
+<!-- (useful for debugging etc) -->
+<xsl:template match="frame" mode="generate-single">
+ <xsl:call-template name="generate-class">
+ <xsl:with-param name="f" select="."/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- generates seperate file for each class/frame -->
+<xsl:template match="frame" mode="generate-multi">
+ <xsl:variable name="uri" select="concat(@name, '.cs')"/>
+ wrote <xsl:value-of select="$uri"/>
+ <xsl:result-document href="{$uri}" format="textFormat">
+ <xsl:call-template name="generate-class">
+ <xsl:with-param name="f" select="."/>
+ </xsl:call-template>
+ </xsl:result-document>
+</xsl:template>
+
+<!-- main class generation template -->
+<xsl:template name="generate-class">
+ <xsl:param name="f"/>
+using Apache.Qpid.Buffer;
+using System.Text;
+
+namespace Apache.Qpid.Framing
+{
+ ///
+ /// <summary>This class is autogenerated
+ /// Do not modify.
+ ///</summary>
+ /// @author Code Generator Script by robert.j.greig@jpmorgan.com
+ public class <xsl:value-of select="$f/@name"/> : AMQMethodBody , IEncodableAMQDataBlock
+ {
+ public const int CLASS_ID = <xsl:value-of select="$f/@class-id"/>;
+ public const int METHOD_ID = <xsl:value-of select="$f/@method-id"/>;
+
+ <xsl:for-each select="$f/field">
+ <xsl:text>public </xsl:text><xsl:value-of select="@csharp-type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>;
+ </xsl:for-each>
+
+ protected override ushort Clazz
+ {
+ get
+ {
+ return <xsl:value-of select="$f/@class-id"/>;
+ }
+ }
+
+ protected override ushort Method
+ {
+ get
+ {
+ return <xsl:value-of select="$f/@method-id"/>;
+ }
+ }
+
+ protected override uint BodySize
+ {
+ get
+ {
+ <xsl:choose>
+ <xsl:when test="$f/field">
+ return (uint)
+ <xsl:for-each select="$f/field">
+ <xsl:if test="position() != 1">+
+ </xsl:if>
+ <xsl:value-of select="amq:field-length(.)"/>
+ </xsl:for-each>
+ ;
+ </xsl:when>
+ <xsl:otherwise>return 0;</xsl:otherwise>
+ </xsl:choose>
+ }
+ }
+
+ protected override void WriteMethodPayload(ByteBuffer buffer)
+ {
+ <xsl:for-each select="$f/field">
+ <xsl:if test="@type != 'bit'">
+ <xsl:value-of select="amq:encoder(.)"/>;
+ </xsl:if>
+ <xsl:if test="@type = 'bit' and @boolean-index = 1">
+ <xsl:text>EncodingUtils.WriteBooleans(buffer, new bool[]{</xsl:text>
+ <xsl:value-of select="$f/field[@type='bit']/@name" separator=", "/>});
+ </xsl:if>
+ </xsl:for-each>
+ }
+
+ protected override void PopulateMethodBodyFromBuffer(ByteBuffer buffer)
+ {
+ <xsl:for-each select="$f/field">
+ <xsl:value-of select="amq:decoder(.)"/>;
+ </xsl:for-each>
+ }
+
+ public override string ToString()
+ {
+ StringBuilder buf = new StringBuilder(base.ToString());
+ <xsl:for-each select="$f/field">
+ <xsl:text>buf.Append(" </xsl:text><xsl:value-of select="@name"/>: ").Append(<xsl:value-of select="@name"/>);
+ </xsl:for-each>
+ return buf.ToString();
+ }
+
+ public static AMQFrame CreateAMQFrame(ushort channelId<xsl:if test="$f/field">, </xsl:if><xsl:value-of select="$f/field/concat(@csharp-type, ' ', @name)" separator=", "/>)
+ {
+ <xsl:value-of select="@name"/> body = new <xsl:value-of select="@name"/>();
+ <xsl:for-each select="$f/field">
+ <xsl:value-of select="concat('body.', @name, ' = ', @name)"/>;
+ </xsl:for-each>
+ AMQFrame frame = new AMQFrame();
+ frame.Channel = channelId;
+ frame.BodyFrame = body;
+ return frame;
+ }
+}
+}
+</xsl:template>
+
+<xsl:template match="/" mode="generate-registry">
+ <xsl:text>Matching root for registry mode!</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:apply-templates select="frames" mode="generate-registry"/>
+</xsl:template>
+
+<xsl:template match="registries" mode="generate-registry">
+Wrote MethodBodyDecoderRegistry.cs
+ <xsl:result-document href="MethodBodyDecoderRegistry.cs" format="textFormat">
+using System;
+using System.Collections;
+using log4net;
+
+namespace Apache.Qpid.Framing
+{
+
+
+ ///
+ /// <summary>This class is autogenerated
+ /// Do not modify.
+ /// </summary>
+ /// @author Code Generator Script by robert.j.greig@jpmorgan.com
+
+ public class MethodBodyDecoderRegistry
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(MethodBodyDecoderRegistry));
+
+ private static readonly Hashtable _classMethodProductToMethodBodyMap = new Hashtable();
+
+ static MethodBodyDecoderRegistry()
+ {
+ <xsl:for-each select="registry">
+ <xsl:value-of select="concat(@name, '.Register(_classMethodProductToMethodBodyMap)')"/>;
+ </xsl:for-each>
+ }
+
+ public static AMQMethodBody Get(int clazz, int method)
+ {
+ Type bodyClass = (Type) _classMethodProductToMethodBodyMap[clazz * 1000 + method];
+ if (bodyClass != null)
+ {
+ try
+ {
+ return (AMQMethodBody) Activator.CreateInstance(bodyClass);
+ }
+ catch (Exception e)
+ {
+ throw new AMQFrameDecodingException(_log, "Unable to instantiate body class for class " + clazz + " and method " + method + ": " + e, e);
+ }
+ }
+ else
+ {
+ throw new AMQFrameDecodingException(_log, "Unable to find a suitable decoder for class " + clazz + " and method " + method);
+ }
+ }
+ }
+ }
+ </xsl:result-document>
+</xsl:template>
+
+<xsl:template match="frames" mode="list-registry">
+ <xsl:if test="$registry_name">
+
+ <xsl:variable name="file" select="concat($registry_name, '.cs')"/>
+ wrote <xsl:value-of select="$file"/>
+ <xsl:result-document href="{$file}" format="textFormat">
+
+using System.Collections;
+namespace Apache.Qpid.Framing
+{
+ /**
+ * This class is autogenerated, do not modify. [From <xsl:value-of select="@protocol"/>]
+ */
+ class <xsl:value-of select="$registry_name"/>
+ {
+ internal static void Register(Hashtable map)
+ {
+ <xsl:for-each select="frame">
+ <xsl:text>map[</xsl:text>
+ <xsl:value-of select="@class-id"/>
+ <xsl:text> * 1000 + </xsl:text>
+ <xsl:value-of select="@method-id"/>
+ <xsl:text>] = typeof(</xsl:text>
+ <xsl:value-of select="@name"/>);
+ </xsl:for-each>
+ }
+}
+}
+ </xsl:result-document>
+
+ </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/framing.xsl b/dotnet/Qpid.Common/stylesheets/framing.xsl
new file mode 100644
index 0000000000..119f439599
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/framing.xsl
@@ -0,0 +1,65 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<xsl:import href="prepare1.xsl"/>
+<xsl:import href="prepare2.xsl"/>
+<xsl:import href="prepare3.xsl"/>
+<xsl:import href="csharp.xsl"/>
+
+<xsl:output indent="yes"/>
+<xsl:output method="text" indent="yes" name="textFormat"/>
+
+<xsl:template match="/">
+ <xsl:variable name="prepare1">
+ <xsl:apply-templates mode="prepare1" select="."/>
+ </xsl:variable>
+
+ <xsl:variable name="prepare2">
+ <xsl:apply-templates mode="prepare2" select="$prepare1"/>
+ </xsl:variable>
+
+ <xsl:variable name="model">
+ <xsl:apply-templates mode="prepare3" select="$prepare2"/>
+ </xsl:variable>
+
+ <xsl:apply-templates mode="generate-multi" select="$model"/>
+ <xsl:apply-templates mode="list-registry" select="$model"/>
+
+ <!-- dump out the intermediary files for debugging -->
+ <!--
+ <xsl:result-document href="prepare1.out">
+ <xsl:copy-of select="$prepare1"/>
+ </xsl:result-document>
+
+ <xsl:result-document href="prepare2.out">
+ <xsl:copy-of select="$prepare2"/>
+ </xsl:result-document>
+
+ <xsl:result-document href="model.out">
+ <xsl:copy-of select="$model"/>
+ </xsl:result-document>
+ -->
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/java.xsl b/dotnet/Qpid.Common/stylesheets/java.xsl
new file mode 100644
index 0000000000..7297c6ae62
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/java.xsl
@@ -0,0 +1,230 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<!-- this class contains the templates for generating java source code for a given framing model -->
+<xsl:import href="utils.xsl"/>
+<xsl:output method="text" indent="yes" name="textFormat"/>
+
+<xsl:param name="registry_name"/>
+
+<xsl:template match="/">
+ <xsl:apply-templates mode="generate-multi" select="frames"/>
+ <xsl:apply-templates mode="generate-registry" select="frames"/>
+</xsl:template>
+
+<!-- processes all frames outputting the classes in a single stream -->
+<!-- (useful for debugging etc) -->
+<xsl:template match="frame" mode="generate-single">
+ <xsl:call-template name="generate-class">
+ <xsl:with-param name="f" select="."/>
+ </xsl:call-template>
+</xsl:template>
+
+<!-- generates seperate file for each class/frame -->
+<xsl:template match="frame" mode="generate-multi">
+ <xsl:variable name="uri" select="concat(@name, '.java')"/>
+ wrote <xsl:value-of select="$uri"/>
+ <xsl:result-document href="{$uri}" format="textFormat">
+ <xsl:call-template name="generate-class">
+ <xsl:with-param name="f" select="."/>
+ </xsl:call-template>
+ </xsl:result-document>
+</xsl:template>
+
+<!-- main class generation template -->
+<xsl:template name="generate-class">
+ <xsl:param name="f"/>
+package org.openamq.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+/**
+ * This class is autogenerated, do not modify. [From <xsl:value-of select="$f/parent::frames/@protocol"/>]
+ */
+public class <xsl:value-of select="$f/@name"/> extends AMQMethodBody implements EncodableAMQDataBlock
+{
+ public static final int CLASS_ID = <xsl:value-of select="$f/@class-id"/>;
+ public static final int METHOD_ID = <xsl:value-of select="$f/@method-id"/>;
+
+ <xsl:for-each select="$f/field">
+ <xsl:text>public </xsl:text><xsl:value-of select="@java-type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>;
+ </xsl:for-each>
+
+ protected int getClazz()
+ {
+ return <xsl:value-of select="$f/@class-id"/>;
+ }
+
+ protected int getMethod()
+ {
+ return <xsl:value-of select="$f/@method-id"/>;
+ }
+
+ protected int getBodySize()
+ {
+ <xsl:choose>
+ <xsl:when test="$f/field">
+ return
+ <xsl:for-each select="$f/field">
+ <xsl:if test="position() != 1">+
+ </xsl:if>
+ <xsl:value-of select="amq:field-length(.)"/>
+ </xsl:for-each>
+ ;
+ </xsl:when>
+ <xsl:otherwise>return 0;</xsl:otherwise>
+ </xsl:choose>
+ }
+
+ protected void writeMethodPayload(ByteBuffer buffer)
+ {
+ <xsl:for-each select="$f/field">
+ <xsl:if test="@type != 'bit'">
+ <xsl:value-of select="amq:encoder(.)"/>;
+ </xsl:if>
+ <xsl:if test="@type = 'bit' and @boolean-index = 1">
+ <xsl:text>EncodingUtils.writeBooleans(buffer, new boolean[]{</xsl:text>
+ <xsl:value-of select="$f/field[@type='bit']/@name" separator=", "/>});
+ </xsl:if>
+ </xsl:for-each>
+ }
+
+ public void populateMethodBodyFromBuffer(ByteBuffer buffer) throws AMQFrameDecodingException
+ {
+ <xsl:for-each select="$f/field">
+ <xsl:value-of select="amq:decoder(.)"/>;
+ </xsl:for-each>
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer(super.toString());
+ <xsl:for-each select="$f/field">
+ <xsl:text>buf.append(" </xsl:text><xsl:value-of select="@name"/>: ").append(<xsl:value-of select="@name"/>);
+ </xsl:for-each>
+ return buf.toString();
+ }
+
+ public static AMQFrame createAMQFrame(int channelId<xsl:if test="$f/field">, </xsl:if><xsl:value-of select="$f/field/concat(@java-type, ' ', @name)" separator=", "/>)
+ {
+ <xsl:value-of select="@name"/> body = new <xsl:value-of select="@name"/>();
+ <xsl:for-each select="$f/field">
+ <xsl:value-of select="concat('body.', @name, ' = ', @name)"/>;
+ </xsl:for-each>
+ AMQFrame frame = new AMQFrame();
+ frame.channel = channelId;
+ frame.bodyFrame = body;
+ return frame;
+ }
+}
+</xsl:template>
+
+<xsl:template match="/" mode="generate-registry">
+ <xsl:text>Matching root for registry mode!</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:apply-templates select="frames" mode="generate-registry"/>
+</xsl:template>
+
+<xsl:template match="registries" mode="generate-registry">
+Wrote MethodBodyDecoderRegistry.java
+ <xsl:result-document href="MethodBodyDecoderRegistry.java" format="textFormat">package org.openamq.framing;
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.log4j.Logger;
+import org.openamq.AMQException;
+
+/**
+ * This class is autogenerated, do not modify.
+ */
+public final class MethodBodyDecoderRegistry
+{
+ private static final Logger _log = Logger.getLogger(MethodBodyDecoderRegistry.class);
+
+ private static final Map _classMethodProductToMethodBodyMap = new HashMap();
+
+ static
+ {
+ <xsl:for-each select="registry">
+ <xsl:value-of select="concat(@name, '.register(_classMethodProductToMethodBodyMap)')"/>;
+ </xsl:for-each>
+ }
+
+ public static AMQMethodBody get(int clazz, int method) throws AMQFrameDecodingException
+ {
+ Class bodyClass = (Class) _classMethodProductToMethodBodyMap.get(new Integer(clazz * 1000 + method));
+ if (bodyClass != null)
+ {
+ try
+ {
+ return (AMQMethodBody) bodyClass.newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new AMQFrameDecodingException(_log, "Unable to instantiate body class for class " + clazz + " and method " + method + ": " + e, e);
+ }
+ }
+ else
+ {
+ throw new AMQFrameDecodingException(_log, "Unable to find a suitable decoder for class " + clazz + " and method " + method);
+ }
+ }
+}
+</xsl:result-document>
+</xsl:template>
+
+<xsl:template match="frames" mode="list-registry">
+ <xsl:if test="$registry_name">
+
+ <xsl:variable name="file" select="concat($registry_name, '.java')"/>
+ wrote <xsl:value-of select="$file"/>
+ <xsl:result-document href="{$file}" format="textFormat">package org.openamq.framing;
+
+import java.util.Map;
+
+/**
+ * This class is autogenerated, do not modify. [From <xsl:value-of select="@protocol"/>]
+ */
+class <xsl:value-of select="$registry_name"/>
+{
+ static void register(Map map)
+ {
+ <xsl:for-each select="frame">
+ <xsl:text>map.put(new Integer(</xsl:text>
+ <xsl:value-of select="@class-id"/>
+ <xsl:text> * 1000 + </xsl:text>
+ <xsl:value-of select="@method-id"/>
+ <xsl:text>), </xsl:text>
+ <xsl:value-of select="concat(@name, '.class')"/>);
+ </xsl:for-each>
+ }
+}
+ </xsl:result-document>
+
+ </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/prepare1.xsl b/dotnet/Qpid.Common/stylesheets/prepare1.xsl
new file mode 100644
index 0000000000..e266b0a9cc
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/prepare1.xsl
@@ -0,0 +1,109 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<xsl:import href="utils.xsl"/>
+
+<xsl:output indent="yes"/>
+<xsl:param name="asl_base"/>
+
+<!-- pre-process, phase 1 -->
+
+<xsl:template match="/">
+ <xsl:apply-templates select="protocol" mode="prepare1"/>
+</xsl:template>
+
+<xsl:template match="amqp" mode="prepare1">
+ <frames>
+ <xsl:attribute name="protocol">
+ <xsl:value-of select="@comment"/>
+ <xsl:text> (</xsl:text>
+ <xsl:text>major=</xsl:text><xsl:value-of select="option[@name='protocol_major']/@value"/>
+ <xsl:text>, minor=</xsl:text><xsl:value-of select="option[@name='protocol_minor']/@value"/>
+ <xsl:text>)</xsl:text>
+ </xsl:attribute>
+ <xsl:apply-templates mode="prepare1" select="inherit"/>
+ <xsl:apply-templates mode="prepare1" select="include"/>
+ <xsl:apply-templates mode="prepare1" select="domain"/>
+ <xsl:apply-templates mode="prepare1" select="class"/>
+ </frames>
+</xsl:template>
+
+<xsl:template match="include" mode="prepare1">
+ <xsl:if test="@filename != 'asl_constants.asl'">
+ <!-- skip asl_constants.asl, we don't need it and it is not well formed so causes error warnings -->
+ <xsl:apply-templates select="document(@filename)" mode="prepare1"/>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="inherit" mode="prepare1">
+ <xsl:variable name="ibase" select="concat('file:///', $asl_base, '/', @name, '.asl')"/>
+ <xsl:choose>
+ <xsl:when test="document($ibase)">
+ <xsl:apply-templates select="document($ibase)" mode="prepare1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ Could not inherit from <xsl:value-of select="$ibase"/>; file not found.
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="class[@index]" mode="prepare1">
+ <xsl:apply-templates select="method" mode="prepare1"/>
+</xsl:template>
+
+<xsl:template match="method" mode="prepare1">
+ <xsl:if test="parent::class[@index]"><!-- there is a template class that has no index, which we want to skip -->
+ <frame>
+ <xsl:attribute name="name"><xsl:value-of select="amq:class-name(parent::class/@name, @name)"/></xsl:attribute>
+ <xsl:attribute name="class-id"><xsl:value-of select="parent::class/@index"/></xsl:attribute>
+ <xsl:if test="@index">
+ <xsl:attribute name="method-id"><xsl:value-of select="@index"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(@index)">
+ <xsl:attribute name="method-id"><xsl:number count="method"/></xsl:attribute>
+ </xsl:if>
+
+ <xsl:apply-templates select="field" mode="prepare1"/>
+ </frame>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="domain" mode="prepare1">
+ <domain>
+ <name><xsl:value-of select="@name"/></name>
+ <type><xsl:value-of select="@type"/></type>
+ </domain>
+</xsl:template>
+
+<xsl:template match="field" mode="prepare1">
+ <field>
+ <xsl:copy-of select="@name"/>
+ <xsl:copy-of select="@type"/>
+ <xsl:copy-of select="@domain"/>
+ </field>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/prepare2.xsl b/dotnet/Qpid.Common/stylesheets/prepare2.xsl
new file mode 100644
index 0000000000..0a64eb6f86
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/prepare2.xsl
@@ -0,0 +1,68 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<xsl:import href="utils.xsl"/>
+
+<xsl:output indent="yes"/>
+
+<!-- pre-process, phase 2 -->
+
+<xsl:key name="domain-lookup" match="domain" use="name"/>
+
+<xsl:template match="/">
+ <xsl:apply-templates mode="prepare2" select="frames"/>
+</xsl:template>
+
+<xsl:template match="field[@domain]" mode="prepare2">
+ <field>
+ <xsl:variable name="t1" select="key('domain-lookup', @domain)/type"/>
+ <xsl:attribute name="name"><xsl:value-of select="amq:field-name(@name)"/></xsl:attribute>
+ <xsl:attribute name="type"><xsl:value-of select="$t1"/></xsl:attribute>
+ </field>
+</xsl:template>
+
+<xsl:template match="field[@type]" mode="prepare2">
+ <field>
+ <xsl:attribute name="name"><xsl:value-of select="amq:field-name(@name)"/></xsl:attribute>
+ <xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
+ </field>
+</xsl:template>
+
+<xsl:template match="frames" mode="prepare2">
+ <frames>
+ <xsl:copy-of select="@protocol"/>
+ <xsl:apply-templates mode="prepare2"/>
+ </frames>
+</xsl:template>
+
+<xsl:template match="frame" mode="prepare2">
+ <xsl:element name="{name()}">
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates mode="prepare2" select="field"/>
+ </xsl:element>
+</xsl:template>
+
+<xsl:template match="domain" mode="prepare2"></xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/prepare3.xsl b/dotnet/Qpid.Common/stylesheets/prepare3.xsl
new file mode 100644
index 0000000000..a921160dd0
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/prepare3.xsl
@@ -0,0 +1,64 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<xsl:import href="utils.xsl"/>
+
+<xsl:output indent="yes"/>
+
+<!-- final preparation of the model -->
+
+<xsl:template match="/">
+ <xsl:apply-templates mode="prepare3"/>
+</xsl:template>
+
+<xsl:template match="frames" mode="prepare3">
+ <frames>
+ <xsl:copy-of select="@protocol"/>
+ <xsl:apply-templates mode="prepare3"/>
+ </frames>
+</xsl:template>
+
+<xsl:template match="frame" mode="prepare3">
+ <xsl:element name="frame">
+ <xsl:copy-of select="@*"/>
+ <xsl:if test="field[@type='bit']"><xsl:attribute name="has-bit-field">true</xsl:attribute></xsl:if>
+ <xsl:apply-templates mode="prepare3"/>
+ </xsl:element>
+</xsl:template>
+
+
+<xsl:template match="field" mode="prepare3">
+ <field>
+ <xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
+ <!-- ensure the field name is processed to be a valid java name -->
+ <xsl:attribute name="name"><xsl:value-of select="amq:field-name(@name)"/></xsl:attribute>
+ <!-- add some attributes to make code generation easier -->
+ <xsl:attribute name="csharp-type"><xsl:value-of select="amq:csharp-type(@type)"/></xsl:attribute>
+ <xsl:if test="@type='bit'">
+ <xsl:attribute name="boolean-index"><xsl:number count="field[@type='bit']"/></xsl:attribute>
+ </xsl:if>
+ </field>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/readme.txt b/dotnet/Qpid.Common/stylesheets/readme.txt
new file mode 100644
index 0000000000..c2f98050a6
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/readme.txt
@@ -0,0 +1,52 @@
+This directory contains the xsl stylesheets used to generate the code from the
+OpenAMQ protocol specification. They require an XSLT2.0 processor, currently
+Saxon 8 is used.
+
+The generation process is controlled by the framing.xsl stylesheet. This performs
+several phases of transformation, using the other stylesheets. The transformation
+in each phase is defined in a separate file, and these are designed to also allow
+then to be run individually.
+
+The generation takes the amq.asl as input, it also requires that the path to the
+directory where the base asl definitions reside (those definitions that the main
+amq.asl defintion inherits from) be passed in via a paramter called asl_base.
+
+The files involved are as follows:
+
+ framing.xsl The control file for the entire generation process
+
+ prepare1.xsl Resolves the separate files that make up the protocol
+ definition, building a single tree containing all the
+ information as a set of 'frame' elements, each of which
+ has attributes for its name, and ids for the class and
+ method it refers to and contains zero or more field
+ elements.
+
+ A method id is generated based on the order of the
+ method elements within the class elements in the original
+ specification. The class id is taken from the enclosing
+ class element.
+
+ prepare2.xsl Resolves domains into their corresponding types. (This is
+ much easier when all the information is in a single tree,
+ hence the separate frame).
+
+ prepare3.xsl Converts names into valid java names and augments the
+ tree to include information that makes the subsequent
+ generation phase simpler e.g. the index of boolean
+ fields as several boolean flags are combined into a
+ single byte. (This is easier once the domains have been
+ resolved, hence the separate phase).
+
+ java.xsl Generates java classes for each frame, and a registry of
+ all the frames to a 'magic' number generated from their
+ class and method id.
+
+ utils.xsl Contains some utility methods for e.g. producing valid
+ java names.
+
+For debugging the framing.xsl can output the intermediary files. This can be
+enabled by uncommenting the relevant lines (a comment explaining this is
+provided inline).
+
+ \ No newline at end of file
diff --git a/dotnet/Qpid.Common/stylesheets/registry.xsl b/dotnet/Qpid.Common/stylesheets/registry.xsl
new file mode 100644
index 0000000000..47a2a29069
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/registry.xsl
@@ -0,0 +1,33 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<xsl:import href="csharp.xsl"/>
+
+<xsl:output method="text" indent="yes" name="textFormat"/>
+
+<xsl:template match="/">
+ <xsl:apply-templates mode="generate-registry" select="registries"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Common/stylesheets/utils.xsl b/dotnet/Qpid.Common/stylesheets/utils.xsl
new file mode 100644
index 0000000000..d097bbc4eb
--- /dev/null
+++ b/dotnet/Qpid.Common/stylesheets/utils.xsl
@@ -0,0 +1,185 @@
+<?xml version='1.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.
+
+-->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:amq="http://amq.org">
+
+<!-- This file contains functions that are used in the generation of the java classes for framing -->
+
+<!-- retrieve the java type of a given amq type -->
+<xsl:function name="amq:csharp-type">
+ <xsl:param name="t"/>
+ <xsl:choose>
+ <xsl:when test="$t='char'">char</xsl:when>
+ <xsl:when test="$t='octet'">byte</xsl:when>
+ <xsl:when test="$t='short'">ushort</xsl:when>
+ <xsl:when test="$t='shortstr'">string</xsl:when>
+ <xsl:when test="$t='longstr'">byte[]</xsl:when>
+ <xsl:when test="$t='bit'">bool</xsl:when>
+ <xsl:when test="$t='long'">uint</xsl:when>
+ <xsl:when test="$t='longlong'">ulong</xsl:when>
+ <xsl:when test="$t='table'">FieldTable</xsl:when>
+ <xsl:otherwise>Object /*WARNING: undefined type*/</xsl:otherwise>
+ </xsl:choose>
+</xsl:function>
+
+<!-- retrieve the code to get the field size of a given amq type -->
+<xsl:function name="amq:field-length">
+ <xsl:param name="f"/>
+ <xsl:choose>
+ <xsl:when test="$f/@type='bit' and $f/@boolean-index=1">
+ <xsl:value-of select="concat('1 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='bit' and $f/@boolean-index &gt; 1">
+ <xsl:value-of select="concat('0 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='char'">
+ <xsl:value-of select="concat('1 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='octet'">
+ <xsl:value-of select="concat('1 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='short'">
+ <xsl:value-of select="concat('2 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='long'">
+ <xsl:value-of select="concat('4 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longlong'">
+ <xsl:value-of select="concat('8 /*', $f/@name, '*/')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='shortstr'">
+ <xsl:value-of select="concat('(uint)EncodingUtils.EncodedShortStringLength(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longstr'">
+ <xsl:value-of select="concat('4 + (uint) (', $f/@name, ' == null ? 0 : ', $f/@name, '.Length)')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='table'">
+ <xsl:value-of select="concat('(uint)EncodingUtils.EncodedFieldTableLength(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:otherwise><xsl:text>/* WARNING: COULD NOT DETERMINE FIELD SIZE */</xsl:text></xsl:otherwise>
+ </xsl:choose>
+</xsl:function>
+
+<!-- retrieve the code to encode a field of a given amq type -->
+<!-- Note:
+ This method will not provide an encoder for a bit field.
+ Bit fields should be encoded together separately. -->
+
+<xsl:function name="amq:encoder">
+ <xsl:param name="f"/>
+ <xsl:choose>
+ <xsl:when test="$f/@type='char'">
+ <xsl:value-of select="concat('buffer.Put(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='octet'">
+ <xsl:value-of select="concat('buffer.Put(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='short'">
+ <xsl:value-of select="concat('buffer.Put(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='long'">
+ <xsl:value-of select="concat('buffer.Put(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longlong'">
+ <xsl:value-of select="concat('buffer.Put(', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='shortstr'">
+ <xsl:value-of select="concat('EncodingUtils.WriteShortStringBytes(buffer, ', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longstr'">
+ <xsl:value-of select="concat('EncodingUtils.WriteLongstr(buffer, ', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='table'">
+ <xsl:value-of select="concat('EncodingUtils.WriteFieldTableBytes(buffer, ', $f/@name, ')')"/>
+ </xsl:when>
+ <xsl:otherwise><xsl:text>/* WARNING: COULD NOT DETERMINE ENCODER */</xsl:text></xsl:otherwise>
+ </xsl:choose>
+</xsl:function>
+
+<!-- retrieve the code to decode a field of a given amq type -->
+<xsl:function name="amq:decoder">
+ <xsl:param name="f"/>
+ <xsl:choose>
+ <xsl:when test="$f/@type='bit'">
+ <xsl:if test="$f/@boolean-index = 1">
+ <xsl:text>bool[] bools = EncodingUtils.ReadBooleans(buffer);</xsl:text>
+ </xsl:if>
+ <xsl:value-of select="concat($f/@name, ' = bools[', $f/@boolean-index - 1 , ']')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='char'">
+ <xsl:value-of select="concat($f/@name, ' = buffer.GetChar()')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='octet'">
+ <xsl:value-of select="concat($f/@name, ' = buffer.GetByte()')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='short'">
+ <xsl:value-of select="concat($f/@name, ' = buffer.GetUInt16()')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='long'">
+ <xsl:value-of select="concat($f/@name, ' = buffer.GetUInt32()')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longlong'">
+ <xsl:value-of select="concat($f/@name, ' = buffer.GetUInt64()')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='shortstr'">
+ <xsl:value-of select="concat($f/@name, ' = EncodingUtils.ReadShortString(buffer)')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='longstr'">
+ <xsl:value-of select="concat($f/@name, ' = EncodingUtils.ReadLongstr(buffer)')"/>
+ </xsl:when>
+ <xsl:when test="$f/@type='table'">
+ <xsl:value-of select="concat($f/@name, ' = EncodingUtils.ReadFieldTable(buffer)')"/>
+ </xsl:when>
+ <xsl:otherwise><xsl:text>/* WARNING: COULD NOT DETERMINE DECODER */</xsl:text></xsl:otherwise>
+ </xsl:choose>
+</xsl:function>
+
+<!-- create the class name for a frame, based on class and method (passed in) -->
+<xsl:function name="amq:class-name">
+ <xsl:param name="class"/>
+ <xsl:param name="method"/>
+ <xsl:value-of select="concat(amq:upper-first($class),amq:upper-first(amq:field-name($method)), 'Body')"/>
+</xsl:function>
+
+<!-- get a valid field name, processing spaces and '-'s where appropriate -->
+<xsl:function name="amq:field-name">
+ <xsl:param name="name"/>
+ <xsl:choose>
+ <xsl:when test="contains($name, ' ')">
+ <xsl:value-of select="amq:upper-first(concat(substring-before($name, ' '), amq:upper-first(substring-after($name, ' '))))"/>
+ </xsl:when>
+ <xsl:when test="contains($name, '-')">
+ <xsl:value-of select="amq:upper-first(concat(substring-before($name, '-'), amq:upper-first(substring-after($name, '-'))))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="amq:upper-first($name)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:function>
+
+<!-- convert the first character of the input to upper-case -->
+<xsl:function name="amq:upper-first">
+ <xsl:param name="in"/>
+ <xsl:value-of select="concat(upper-case(substring($in, 1, 1)), substring($in, 2))"/>
+</xsl:function>
+
+</xsl:stylesheet>
diff --git a/dotnet/Qpid.Integration.Tests/Properties/AssemblyInfo.cs b/dotnet/Qpid.Integration.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e19650559f
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.InteropServices;
+using log4net.Config;
+[assembly: XmlConfigurator(ConfigFile="log4net.config")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Integration.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Integration.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7ebdea21-1352-4673-b66e-fdc0beff461f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
diff --git a/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj b/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj
new file mode 100755
index 0000000000..e7d6e59cf5
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj
@@ -0,0 +1,124 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <ProjectGuid>{DE21CEBC-F38C-43EA-B576-38CA9738A00A}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Qpid.Integration.Tests</RootNamespace>
+ <AssemblyName>Qpid.Integration.Tests</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <PublishUrl>http://localhost/Qpid.Integration.Tests/</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Web</InstallFrom>
+ <UpdateEnabled>true</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>true</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <OutputPath>bin\Debug\</OutputPath>
+ <DebugSymbols>True</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DebugSymbols>False</DebugSymbols>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <DefineConstants>TRACE</DefineConstants>
+ </PropertyGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\client-010\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\client-010\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+</Project>
diff --git a/dotnet/Qpid.Integration.Tests/README.txt b/dotnet/Qpid.Integration.Tests/README.txt
new file mode 100644
index 0000000000..389e3b2c6c
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/README.txt
@@ -0,0 +1,3 @@
+This directory contains NUnit tests, which are 'integration' oriented. These differ
+from 'pure unit' tests which run against the code only. The integration tests require
+a broker to be available to connect to, and apply test cases that interact with it.
diff --git a/dotnet/Qpid.Integration.Tests/default.build b/dotnet/Qpid.Integration.Tests/default.build
new file mode 100644
index 0000000000..187aa15894
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/default.build
@@ -0,0 +1,69 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Integration.Tests" default="test">
+
+ <!-- Creates a .dll for this module. -->
+ <target name="build">
+
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="false"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/Apache.Qpid.Common.dll" />
+ <include name="${build.dir}/Apache.Qpid.Messaging.dll" />
+ <include name="${build.dir}/Apache.Qpid.Client.dll" />
+ <include name="${build.dir}/Apache.Qpid.Sasl.dll" />
+ </references>
+ </csc>
+
+ <!--<copy tofile="${build.dir}/${project::get-name()}.dll.config" file="App.config" />-->
+ <copy todir="${build.dir}" file="log4net.config"/>
+
+ </target>
+
+ <!-- Runs all of the tests in this module. -->
+ <target name="test" depends="build">
+ <nunit2 verbose="true">
+ <formatter type="${nant.formatter}" usefile="true" outputdir="${build.dir}/testresults/" extension="txt"/>
+ <formatter type="Plain" usefile="false"/>
+ <test>
+ <assemblies>
+ <include name="${build.dir}/${project::get-name()}.dll"/>
+ </assemblies>
+ <categories>
+ <include name="Integration"/>
+ </categories>
+ </test>
+ </nunit2>
+ </target>
+
+</project>
diff --git a/dotnet/Qpid.Integration.Tests/framework/Assertion.cs b/dotnet/Qpid.Integration.Tests/framework/Assertion.cs
new file mode 100644
index 0000000000..de12de6522
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Assertion.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// Assertion models an assertion on a test <see cref="Circuit"/>.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Indicate whether or not the assertion passes when applied.
+ /// </table>
+ /// </summary>
+ public interface Assertion
+ {
+ /// <summary>
+ /// Applies the assertion.
+ /// </summary>
+ /// <return> <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails. </return>
+ bool apply();
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Assertion.csx b/dotnet/Qpid.Integration.Tests/framework/Assertion.csx
new file mode 100644
index 0000000000..183315fec1
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Assertion.csx
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// Assertion models an assertion on a test <see cref="Circuit"/>.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Indicate whether or not the assertion passes when applied.
+ /// </table>
+ /// </summary>
+ public interface Assertion
+ {
+ /// <summary>
+ /// Applies the assertion.
+ /// </summary>
+ /// <return> <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails. </return>
+ public bool apply();
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/AssertionBase.csx b/dotnet/Qpid.Integration.Tests/framework/AssertionBase.csx
new file mode 100644
index 0000000000..7de3f6c4a5
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/AssertionBase.csx
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// AssertionBase is a base class for implenmenting assertions. It provides a mechanism to store error messages, and
+ /// report all error messages when its <see cref="#ToString()"/> method is called.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Collect error messages.
+ /// </table>
+ /// </summary>
+ public abstract class AssertionBase : Assertion
+ {
+ /// <summary> Holds the error messages. </summary>
+ IList<String> errors = new LinkedList<String>();
+
+ /// <summary>
+ /// Adds an error message to the assertion.
+ /// </summary>
+ /// <param name="error"> An error message to add to the assertion. </param>
+ public void addError(string error)
+ {
+ errors.add(error);
+ }
+
+ /// <summary>
+ /// Prints all of the error messages in the assertion into a string.
+ /// </summary>
+ /// <return> All of the error messages in the assertion as a string. </return>
+ public string ToString()
+ {
+ string result = "";
+
+ for (string error : errors)
+ {
+ result += error;
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/BrokerLifecycleAware.csx b/dotnet/Qpid.Integration.Tests/framework/BrokerLifecycleAware.csx
new file mode 100644
index 0000000000..9ef1f54064
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/BrokerLifecycleAware.csx
@@ -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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of
+ /// the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that
+ /// enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Indicate whether or not a test case is using an in-vm broker.
+ /// <tr><td> Track which in-vm broker is currently in use.
+ /// <tr><td> Accept setting of a failure mechanism. <td> <see cref="CauseFailure"/>.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Need to think about how to present the brokers through this interface. Thinking numbering the available
+ /// brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto
+ /// 1 again? </remarks>
+ public interface BrokerLifecycleAware
+ {
+ public void setInVmBrokers();
+
+ /// <summary>
+ /// Indicates whether or not a test case is using in-vm brokers.
+ /// </summary>
+ /// <return> <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise. </return>
+ public bool usingInVmBroker();
+
+ /// <summary>
+ /// Sets the currently live in-vm broker.
+ /// </summary>
+ /// <param name="i"> The currently live in-vm broker. </param>
+ public void setLiveBroker(int i);
+
+ /// <summary>
+ /// Reports the currently live in-vm broker.
+ /// </summary>
+ /// <return> The currently live in-vm broker. </return>
+ public int getLiveBroker();
+
+ /// <summary>
+ /// Accepts a failure mechanism.
+ /// </summary>
+ /// <param name="failureMechanism"> The failure mechanism. </param>
+ public void setFailureMechanism(CauseFailure failureMechanism);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/CauseFailure.csx b/dotnet/Qpid.Integration.Tests/framework/CauseFailure.csx
new file mode 100644
index 0000000000..1fe8918e60
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/CauseFailure.csx
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over
+ /// or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker,
+ /// or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable
+ /// to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or
+ /// dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract
+ /// the exact cause and nature of a failure out of failure test cases.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Cause messaging broker failure.
+ /// </table>
+ /// </summary>
+ public interface CauseFailure
+ {
+ /// <summary> Causes the active message broker to fail. </summary>
+ void causeFailure();
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/CauseFailureUserPrompt.csx b/dotnet/Qpid.Integration.Tests/framework/CauseFailureUserPrompt.csx
new file mode 100644
index 0000000000..96f4ec53d0
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/CauseFailureUserPrompt.csx
@@ -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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.CauseFailure;
+
+using java.io.IOException;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// Causes a message broker failure by interactively prompting the user to cause it.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Cause messaging broker failure.
+ /// </table>
+ /// </summary>
+ public class CauseFailureUserPrompt : CauseFailure
+ {
+ /// <summary> Causes the active message broker to fail.</summary>
+ public void causeFailure()
+ {
+ waitForUser("Cause a broker failure now, then press Return.");
+ }
+
+ /// <summary>
+ /// Outputs a prompt to the console and waits for the user to press return.
+ /// </summary>
+ /// <param name="prompt"> The prompt to display on the console. </param>
+ private void waitForUser(string prompt)
+ {
+ System.out.println(prompt);
+
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ // Ignored.
+ }
+
+ System.out.println("Continuing.");
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Circuit.cs b/dotnet/Qpid.Integration.Tests/framework/Circuit.cs
new file mode 100644
index 0000000000..aae9ca0496
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Circuit.cs
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections.Generic;//.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Circuit is the basic test unit against which test cases are to be written. A circuit consists of two 'ends', an
+ /// instigating 'publisher' end and a more passive 'receivers' end.
+ ///
+ /// <p/>Once created, the life-cycle of a circuit may be controlled by <see cref="#start()"/>ing it, or <see cref="#close()"/>ing it.
+ /// Once started, the circuit is ready to send messages over. Once closed the circuit can no longer be used.
+ ///
+ /// <p/>The state of the circuit may be taken with the <see cref="#check()"/> method, and asserted against by the
+ /// <see cref="#applyAssertions(System.Collections.Generic.IList)"/> method.
+ ///
+ /// <p/>There is a default test procedure which may be performed against the circuit. The outline of this procedure is:
+ ///
+ /// <p/><pre>
+ /// Start the circuit.
+ /// Send test messages.
+ /// Request a status report.
+ /// Assert conditions on the publishing end of the circuit.
+ /// Assert conditions on the receiving end of the circuit.
+ /// Close the circuit.
+ /// Pass with no failed assertions or fail with a list of failed assertions.
+ /// </pre>
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state.
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedue on the circuit.
+ /// </table>
+ /// </summary>
+ public interface Circuit
+ {
+ /// <summary> Gets the interface on the publishing end of the circuit. </summary>
+ ///
+ /// <return> The publishing end of the circuit. </return>
+ Publisher GetPublisher();
+
+ /// <summary> Gets the interface on the receiving end of the circuit. </summary>
+ ///
+ /// <return> The receiving end of the circuit. </return>
+ Receiver GetReceiver();
+
+ /// <summary> Connects and starts the circuit. After this method is called the circuit is ready to send messages. </summary>
+ void Start();
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ /// </summary>
+ void Check();
+
+ /// <summary> Closes the circuit. All associated resources are closed. </summary>
+ void Close();
+
+ /// <summary>
+ /// Applied a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ ///
+ /// <param name="assertions"> The list of assertions to apply to the circuit. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ IList<Assertion> ApplyAssertions(IList<Assertion> assertions);
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+ /// </summary>
+ ///
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ IList<Assertion> Test(int numMessages, IList<Assertion> assertions);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Circuit.csx b/dotnet/Qpid.Integration.Tests/framework/Circuit.csx
new file mode 100644
index 0000000000..bf2c623cff
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Circuit.csx
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Circuit is the basic test unit against which test cases are to be written. A circuit consists of two 'ends', an
+ /// instigating 'publisher' end and a more passive 'receivers' end.
+ ///
+ /// <p/>Once created, the life-cycle of a circuit may be controlled by <see cref="#start()"/>ing it, or <see cref="#close()"/>ing it.
+ /// Once started, the circuit is ready to send messages over. Once closed the circuit can no longer be used.
+ ///
+ /// <p/>The state of the circuit may be taken with the <see cref="#check()"/> method, and asserted against by the
+ /// <see cref="#applyAssertions(System.Collections.Generic.IList)"/> method.
+ ///
+ /// <p/>There is a default test procedure which may be performed against the circuit. The outline of this procedure is:
+ ///
+ /// <p/><pre>
+ /// Start the circuit.
+ /// Send test messages.
+ /// Request a status report.
+ /// Assert conditions on the publishing end of the circuit.
+ /// Assert conditions on the receiving end of the circuit.
+ /// Close the circuit.
+ /// Pass with no failed assertions or fail with a list of failed assertions.
+ /// </pre>
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state.
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedue on the circuit.
+ /// </table>
+ /// </summary>
+ public interface Circuit
+ {
+ /// <summary>
+ /// Gets the interface on the publishing end of the circuit.
+ /// </summary>
+ /// <return> The publishing end of the circuit. </return>
+ public Publisher getPublisher();
+
+ /// <summary>
+ /// Gets the interface on the receiving end of the circuit.
+ /// </summary>
+ /// <return> The receiving end of the circuit. </return>
+ public Receiver getReceiver();
+
+ /// <summary>
+ /// Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+ public void start();
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ public void check();
+
+ /// <summary>
+ /// Closes the circuit. All associated resources are closed.
+ public void close();
+
+ /// <summary>
+ /// Applied a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ /// <param name="assertions"> The list of assertions to apply to the circuit. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> applyAssertions(List<Assertion> assertions);
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+ /// </summary>
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> test(int numMessages, List<Assertion> assertions);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/CircuitEnd.csx b/dotnet/Qpid.Integration.Tests/framework/CircuitEnd.csx
new file mode 100644
index 0000000000..6edaf428de
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/CircuitEnd.csx
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+//using javax.jms.*;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A CircuitEnd is a pair consisting of one message producer and one message consumer, that represents one end of a
+ /// test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both
+ /// the consumer and producer are instantiated and configured.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Update the <see cref="org.apache.qpid.util.ConversationFactory"/> so that it accepts these as the basic conversation
+ /// connection units.</remarks>
+ public interface CircuitEnd
+ {
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public IMessagePublisher GetProducer();
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public IMessageConsumer GetConsumer();
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void Send(IMessage message);
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public IChannel GetSession();
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ /// </summary>
+ /// <exception cref="JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void Close();
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor GetMessageMonitor();
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor GetExceptionMonitor();
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/CircuitEndBase.csx b/dotnet/Qpid.Integration.Tests/framework/CircuitEndBase.csx
new file mode 100644
index 0000000000..db7fbde6ea
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/CircuitEndBase.csx
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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.
+ *
+ */
+//using javax.jms.*;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A CircuitEndBase is a pair consisting of one message producer and one message consumer, that represents one end of a
+ /// test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both
+ /// the consumer and producer are instantiated and configured.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// </table>
+ /// </summary>
+ public class CircuitEndBase : CircuitEnd
+ {
+ /// <summary> Holds the single message producer. </summary>
+ MessageProducer producer;
+
+ /// <summary> Holds the single message consumer. </summary>
+ MessageConsumer consumer;
+
+ /// <summary> Holds the controlSession for the circuit end. </summary>
+ Session session;
+
+ /// <summary> Holds the message monitor for the circuit end. </summary>
+ MessageMonitor messageMonitor;
+
+ /// <summary> Holds the exception monitor for the circuit end. </summary>
+ ExceptionMonitor exceptionMonitor;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor,
+ ExceptionMonitor exceptionMonitor)
+ {
+ this.producer = producer;
+ this.consumer = consumer;
+ this.session = session;
+
+ this.messageMonitor = messageMonitor;
+ this.exceptionMonitor = exceptionMonitor;
+ }
+
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public IMessagePublisher GetProducer()
+ {
+ return producer;
+ }
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public IMessageConsumer GetConsumer()
+ {
+ return consumer;
+ }
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ /// <exception cref="javax.jms.JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void Send(IMessage message)
+ {
+ producer.send(message);
+ }
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public IChannel GetSession()
+ {
+ return session;
+ }
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ /// </summary>
+ /// <exception cref="javax.jms.JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void Close()
+ {
+ if (producer != null)
+ {
+ producer.Close();
+ }
+
+ if (consumer != null)
+ {
+ consumer.Close();
+ }
+ }
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor GetMessageMonitor()
+ {
+ return messageMonitor;
+ }
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor GetExceptionMonitor()
+ {
+ return exceptionMonitor;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/ExceptionMonitor.csx b/dotnet/Qpid.Integration.Tests/framework/ExceptionMonitor.csx
new file mode 100644
index 0000000000..b2a989b940
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/ExceptionMonitor.csx
@@ -0,0 +1,184 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using javax.jms.ExceptionListener;
+using javax.jms.JMSException;
+
+using java.io.PrintWriter;
+using java.io.StringWriter;
+using java.util.ArrayList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// An exception monitor, listens for JMS exception on a connection or consumer. It record all exceptions that it receives
+ /// and provides methods to test the number and type of exceptions received.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Record all exceptions received.
+ /// </table>
+ /// </summary>
+ public class ExceptionMonitor : ExceptionListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(ExceptionMonitor));
+
+ /// <summary> Holds the received exceptions. </summary>
+ IList<Exception> exceptions = new ArrayList<Exception>();
+
+ /// <summary>
+ /// Receives incoming exceptions.
+ /// </summary>
+ /// <param name="e"> The exception to record. </param>
+ public synchronized void onException(JMSException e)
+ {
+ log.debug("public void onException(JMSException e): called", e);
+
+ exceptions.add(e);
+ }
+
+ /// <summary>
+ /// Checks that no exceptions have been received.
+ /// </summary>
+ /// <return> <tt>true</tt> if no exceptions have been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertNoExceptions()
+ {
+ return exceptions.isEmpty();
+ }
+
+ /// <summary>
+ /// Checks that exactly one exception has been received.
+ /// </summary>
+ /// <return> <tt>true</tt> if exactly one exception been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertOneJMSException()
+ {
+ return exceptions.size() == 1;
+ }
+
+ /// <summary>
+ /// Checks that exactly one exception, with a linked cause of the specified type, has been received.
+ /// </summary>
+ /// <param name="aClass"> The type of the linked cause. </param>
+ ///
+ /// <return> <tt>true</tt> if exactly one exception, with a linked cause of the specified type, been received, </return>
+ /// <tt>false</tt> otherwise.
+ public synchronized bool assertOneJMSExceptionWithLinkedCause(Class aClass)
+ {
+ if (exceptions.size() == 1)
+ {
+ Exception e = exceptions.get(0);
+
+ if (e instanceof JMSException)
+ {
+ JMSException jmse = (JMSException) e;
+
+ Exception linkedCause = jmse.getLinkedException();
+
+ if ((linkedCause != null) && aClass.isInstance(linkedCause))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Checks that at least one exception of the the specified type, has been received.
+ /// </summary>
+ /// <param name="exceptionClass"> The type of the exception. </param>
+ ///
+ /// <return> <tt>true</tt> if at least one exception of the specified type has been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertExceptionOfType(Class exceptionClass)
+ {
+ // Start by assuming that the exception has no been received.
+ bool passed = false;
+
+ // Scan all the exceptions for a match.
+ for (Exception e : exceptions)
+ {
+ if (exceptionClass.isInstance(e))
+ {
+ passed = true;
+
+ break;
+ }
+ }
+
+ return passed;
+ }
+
+ /// <summary>
+ /// Reports the number of exceptions held by this monitor.
+ /// </summary>
+ /// <return> The number of exceptions held by this monitor. </return>
+ public synchronized int size()
+ {
+ return exceptions.size();
+ }
+
+ /// <summary>
+ /// Clears the record of received exceptions.
+ /// </summary>
+ public synchronized void reset()
+ {
+ exceptions = new ArrayList<Exception>();
+ }
+
+ /// <summary>
+ /// Provides a dump of the stack traces of all exceptions that this exception monitor was notified of. Mainly
+ /// use for debugging/test failure reporting purposes.
+ /// </summary>
+ /// <return> A string containing a dump of the stack traces of all exceptions. </return>
+ public synchronized string ToString()
+ {
+ string result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n";
+
+ for (Exception ex : exceptions)
+ {
+ result += getStackTrace(ex) + "\n";
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Prints an exception stack trace into a string.
+ /// </summary>
+ /// <param name="t"> The throwable to get the stack trace from. </param>
+ ///
+ /// <return> A string containing the throwables stack trace. </return>
+ public static string getStackTrace(Throwable t)
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ t.printStackTrace(pw);
+ pw.flush();
+ sw.flush();
+
+ return sw.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.cs b/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.cs
new file mode 100644
index 0000000000..77c1cae0ad
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.cs
@@ -0,0 +1,282 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using NUnit.Framework;
+//using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.sequencers;//.CircuitFactory;
+
+//using uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+//using uk.co.thebadgerset.junit.extensions.SetupTaskAware;
+//using uk.co.thebadgerset.junit.extensions.SetupTaskHandler;
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+//using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+//using java.util.ArrayList;
+using System.Collections.Generic;//.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
+ /// to provide some convenience methods for testing.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create and clean up in-vm brokers on every test case.
+ /// <tr><td> Produce lists of assertions from assertion creation calls.
+ /// <tr><td> Produce JUnit failures from assertion failures.
+ /// <tr><td> Convert failed assertions to error messages.
+ /// </table>
+ /// </summary>
+ public class FrameworkBaseCase //extends AsymptoticTestCase : FrameworkTestContext, SetupTaskAware, BrokerLifecycleAware
+ {
+ /// <summary> Used for debugging purposes. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(FrameworkBaseCase));
+
+ /// <summary> Holds the test sequencer to create and run test circuits with. </summary>
+ protected CircuitFactory circuitFactory;// = new LocalCircuitFactory();
+
+ /// <summary> Used to read the tests configurable properties through. </summary>
+ protected TestModel testProps;
+
+ /// <summary> A default setup task processor to delegate setup tasks to. </summary>
+ //protected SetupTaskHandler taskHandler = new SetupTaskHandler();
+
+ /// <summary> Flag used to track whether the test is in-vm or not. </summary>
+ //protected bool isUsingInVM;
+
+ /// <summary> Holds the failure mechanism. </summary>
+ //protected CauseFailure failureMechanism = new CauseFailureUserPrompt();
+
+ /*
+ /// <summary>
+ /// Creates a new test case with the specified name.
+ /// </summary>
+ /// <param name="name"> The test case name. </param>
+ public FrameworkBaseCase(string name) : base(name)
+ {
+ }
+ */
+
+ /// <summary>
+ /// Returns the test case sequencer that provides test circuit, and test sequence implementations. The sequencer
+ /// that this base case returns by default is suitable for running a test circuit with both circuit ends colocated
+ /// on the same JVM.
+ /// </summary>
+ /// <return> The test case sequencer. </return>
+ protected CircuitFactory GetCircuitFactory()
+ {
+ return circuitFactory;
+ }
+
+ /// <summary>
+ /// Overrides the default test circuit factory. Test decorators can use this to supply distributed test sequencers or
+ /// other test circuit factory specializations.
+ /// </summary>
+ /// <param name="circuitFactory"> The new test circuit factory. </param>
+ public void SetCircuitFactory(CircuitFactory circuitFactory)
+ {
+ this.circuitFactory = circuitFactory;
+ }
+
+ /*
+ /// <summary>
+ /// Reports the current test case name.
+ /// </summary>
+ /// <return> The current test case name. </return>
+ public TestCaseVector GetTestCaseVector()
+ {
+ return new TestCaseVector(this.getName(), 0);
+ }
+ */
+
+ /// <summary>
+ /// Reports the current test case parameters.
+ /// </summary>
+ /// <return> The current test case parameters. </return>
+ public TestModel getTestParameters()
+ {
+ return testProps;
+ }
+
+ /// <summary>
+ /// Creates a list of assertions.
+ /// </summary>
+ /// <param name="asserts"> The assertions to compile in a list. </param>
+ ///
+ /// <return> A list of assertions. </return>
+ protected IList<Assertion> AssertionList(params Assertion[] asserts)
+ {
+ IList<Assertion> result = new List<Assertion>();
+
+ foreach (Assertion assertion in asserts)
+ {
+ result.Add(assertion);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Generates a JUnit assertion exception (failure) if any assertions are passed into this method, also concatenating
+ /// all of the error messages in the assertions together to form an error message to diagnose the test failure with.
+ /// </summary>
+ /// <param name="asserts"> The list of failed assertions. </param>
+ protected static void AssertNoFailures(List<Assertion> asserts)
+ {
+ log.Debug("protected void assertNoFailures(List<Assertion> asserts = " + asserts + "): called");
+
+ // Check if there are no assertion failures, and return without doing anything if so.
+ if ((asserts == null) || (asserts.Count == 0))
+ {
+ return;
+ }
+
+ // Compile all of the assertion failure messages together.
+ string errorMessage = AssertionsToString(asserts);
+
+ // Fail with the error message from all of the assertions.
+ Assert.Fail(errorMessage);
+ }
+
+ /// <summary>
+ /// Converts a list of failed assertions into an error message.
+ /// </summary>
+ /// <param name="asserts"> The failed assertions. </param>
+ ///
+ /// <return> The error message. </return>
+ protected static string AssertionsToString(List<Assertion> asserts)
+ {
+ string errorMessage = "";
+
+ foreach (Assertion assertion in asserts)
+ {
+ errorMessage += assertion.ToString() + "\n";
+ }
+
+ return errorMessage;
+ }
+
+ /// <summary>
+ /// Ensures that the in-vm broker is created and initialized.
+ /// </summary>
+ ///
+ /// <exception cref="Exception"> Any exceptions allowed to fall through and fail the test. </exception>
+ [SetUp]
+ protected void SetUp()
+ {
+ //NDC.Push(Name);
+
+ //testProps = TestContextProperties.getInstance(TestModel.defaults);
+
+ // Process all optional setup tasks. This may include in-vm broker creation, if a decorator has added it.
+ //taskHandler.runSetupTasks();
+ }
+
+ /// <summary> Ensures that the in-vm broker is cleaned up after each test run. </summary>
+ [TearDown]
+ protected void TearDown()
+ {
+ //NDC.Pop();
+
+ // Process all optional tear down tasks. This may include in-vm broker clean up, if a decorator has added it.
+ //taskHandler.runTearDownTasks();
+ }
+
+ /*
+ /// <summary>
+ /// Adds the specified task to the tests setup.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests setup. </param>
+ public void chainSetupTask(Runnable task)
+ {
+ taskHandler.chainSetupTask(task);
+ }
+ */
+
+ /*
+ /// <summary>
+ /// Adds the specified task to the tests tear down.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests tear down. </param>
+ public void chainTearDownTask(Runnable task)
+ {
+ taskHandler.chainTearDownTask(task);
+ }
+ */
+
+ /*
+ /// <summary>
+ /// Should provide a translation from the junit method name of a test to its test case name as known to the test
+ /// clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ /// case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ /// name "TC2_BasicP2P".
+ /// </summary>
+ /// <param name="methodName"> The name of the JUnit test method. </param>
+ ///
+ /// <return> The name of the corresponding interop test case. </return>
+ public string getTestCaseNameForTestMethod(string methodName)
+ {
+ return methodName;
+ }
+
+ public void setInVmBrokers()
+ {
+ isUsingInVM = true;
+ }
+
+ /// <summary>
+ /// Indicates whether or not a test case is using in-vm brokers.
+ /// </summary>
+ /// <return> <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise. </return>
+ public bool usingInVmBroker()
+ {
+ return isUsingInVM;
+ }
+
+ /// <summary>
+ /// Sets the currently live in-vm broker.
+ /// </summary>
+ /// <param name="i"> The currently live in-vm broker. </param>
+ public void setLiveBroker(int i)
+ { }
+
+ /// <summary>
+ /// Reports the currently live in-vm broker.
+ /// </summary>
+ /// <return> The currently live in-vm broker. </return>
+ public int getLiveBroker()
+ {
+ return 0;
+ }
+
+ /// <summary>
+ /// Accepts a failure mechanism.
+ /// </summary>
+ /// <param name="failureMechanism"> The failure mechanism. </param>
+ public void setFailureMechanism(CauseFailure failureMechanism)
+ {
+ this.failureMechanism = failureMechanism;
+ }
+ */
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.csx b/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.csx
new file mode 100644
index 0000000000..00ed572603
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/FrameworkBaseCase.csx
@@ -0,0 +1,272 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.BrokerLifecycleAware;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+
+using uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+using uk.co.thebadgerset.junit.extensions.SetupTaskAware;
+using uk.co.thebadgerset.junit.extensions.SetupTaskHandler;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using java.util.ArrayList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
+ /// to provide some convenience methods for testing.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create and clean up in-vm brokers on every test case.
+ /// <tr><td> Produce lists of assertions from assertion creation calls.
+ /// <tr><td> Produce JUnit failures from assertion failures.
+ /// <tr><td> Convert failed assertions to error messages.
+ /// </table>
+ /// </summary>
+ public class FrameworkBaseCase extends AsymptoticTestCase : FrameworkTestContext, SetupTaskAware,
+ BrokerLifecycleAware
+ {
+ /// <summary> Used for debugging purposes. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(FrameworkBaseCase));
+
+ /// <summary> Holds the test sequencer to create and run test circuits with. </summary>
+ protected CircuitFactory circuitFactory = new LocalCircuitFactory();
+
+ /// <summary> Used to read the tests configurable properties through. </summary>
+ protected ParsedProperties testProps;
+
+ /// <summary> A default setup task processor to delegate setup tasks to. </summary>
+ protected SetupTaskHandler taskHandler = new SetupTaskHandler();
+
+ /// <summary> Flag used to track whether the test is in-vm or not. </summary>
+ protected bool isUsingInVM;
+
+ /// <summary> Holds the failure mechanism. </summary>
+ protected CauseFailure failureMechanism = new CauseFailureUserPrompt();
+
+ /// <summary>
+ /// Creates a new test case with the specified name.
+ /// </summary>
+ /// <param name="name"> The test case name. </param>
+ public FrameworkBaseCase(string name)
+ {
+ super(name);
+ }
+
+ /// <summary>
+ /// Returns the test case sequencer that provides test circuit, and test sequence implementations. The sequencer
+ /// that this base case returns by default is suitable for running a test circuit with both circuit ends colocated
+ /// on the same JVM.
+ /// </summary>
+ /// <return> The test case sequencer. </return>
+ protected CircuitFactory getCircuitFactory()
+ {
+ return circuitFactory;
+ }
+
+ /// <summary>
+ /// Overrides the default test circuit factory. Test decorators can use this to supply distributed test sequencers or
+ /// other test circuit factory specializations.
+ /// </summary>
+ /// <param name="circuitFactory"> The new test circuit factory. </param>
+ public void setCircuitFactory(CircuitFactory circuitFactory)
+ {
+ this.circuitFactory = circuitFactory;
+ }
+
+ /// <summary>
+ /// Reports the current test case name.
+ /// </summary>
+ /// <return> The current test case name. </return>
+ public TestCaseVector getTestCaseVector()
+ {
+ return new TestCaseVector(this.getName(), 0);
+ }
+
+ /// <summary>
+ /// Reports the current test case parameters.
+ /// </summary>
+ /// <return> The current test case parameters. </return>
+ public MessagingTestConfigProperties getTestParameters()
+ {
+ return new MessagingTestConfigProperties(testProps);
+ }
+
+ /// <summary>
+ /// Creates a list of assertions.
+ /// </summary>
+ /// <param name="asserts"> The assertions to compile in a list. </param>
+ ///
+ /// <return> A list of assertions. </return>
+ protected IList<Assertion> assertionList(Assertion... asserts)
+ {
+ IList<Assertion> result = new ArrayList<Assertion>();
+
+ for (Assertion assertion : asserts)
+ {
+ result.add(assertion);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Generates a JUnit assertion exception (failure) if any assertions are passed into this method, also concatenating
+ /// all of the error messages in the assertions together to form an error message to diagnose the test failure with.
+ /// </summary>
+ /// <param name="asserts"> The list of failed assertions. </param>
+ protected static void assertNoFailures(List<Assertion> asserts)
+ {
+ log.debug("protected void assertNoFailures(List<Assertion> asserts = " + asserts + "): called");
+
+ // Check if there are no assertion failures, and return without doing anything if so.
+ if ((asserts == null) || asserts.isEmpty())
+ {
+ return;
+ }
+
+ // Compile all of the assertion failure messages together.
+ string errorMessage = assertionsToString(asserts);
+
+ // Fail with the error message from all of the assertions.
+ fail(errorMessage);
+ }
+
+ /// <summary>
+ /// Converts a list of failed assertions into an error message.
+ /// </summary>
+ /// <param name="asserts"> The failed assertions. </param>
+ ///
+ /// <return> The error message. </return>
+ protected static string assertionsToString(List<Assertion> asserts)
+ {
+ string errorMessage = "";
+
+ for (Assertion assertion : asserts)
+ {
+ errorMessage += assertion.ToString() + "\n";
+ }
+
+ return errorMessage;
+ }
+
+ /// <summary>
+ /// Ensures that the in-vm broker is created and initialized.
+ /// </summary>
+ ///
+ /// <exception cref="Exception"> Any exceptions allowed to fall through and fail the test. </exception>
+ protected void setUp() throws Exception
+ {
+ NDC.push(getName());
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ // Process all optional setup tasks. This may include in-vm broker creation, if a decorator has added it.
+ taskHandler.runSetupTasks();
+ }
+
+ /// <summary> Ensures that the in-vm broker is cleaned up after each test run. </summary>
+ protected void tearDown()
+ {
+ NDC.pop();
+
+ // Process all optional tear down tasks. This may include in-vm broker clean up, if a decorator has added it.
+ taskHandler.runTearDownTasks();
+ }
+
+ /// <summary>
+ /// Adds the specified task to the tests setup.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests setup. </param>
+ public void chainSetupTask(Runnable task)
+ {
+ taskHandler.chainSetupTask(task);
+ }
+
+ /// <summary>
+ /// Adds the specified task to the tests tear down.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests tear down. </param>
+ public void chainTearDownTask(Runnable task)
+ {
+ taskHandler.chainTearDownTask(task);
+ }
+
+ /// <summary>
+ /// Should provide a translation from the junit method name of a test to its test case name as known to the test
+ /// clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ /// case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ /// name "TC2_BasicP2P".
+ /// </summary>
+ /// <param name="methodName"> The name of the JUnit test method. </param>
+ ///
+ /// <return> The name of the corresponding interop test case. </return>
+ public string getTestCaseNameForTestMethod(string methodName)
+ {
+ return methodName;
+ }
+
+ public void setInVmBrokers()
+ {
+ isUsingInVM = true;
+ }
+
+ /// <summary>
+ /// Indicates whether or not a test case is using in-vm brokers.
+ /// </summary>
+ /// <return> <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise. </return>
+ public bool usingInVmBroker()
+ {
+ return isUsingInVM;
+ }
+
+ /// <summary>
+ /// Sets the currently live in-vm broker.
+ /// </summary>
+ /// <param name="i"> The currently live in-vm broker. </param>
+ public void setLiveBroker(int i)
+ { }
+
+ /// <summary>
+ /// Reports the currently live in-vm broker.
+ /// </summary>
+ /// <return> The currently live in-vm broker. </return>
+ public int getLiveBroker()
+ {
+ return 0;
+ }
+
+ /// <summary>
+ /// Accepts a failure mechanism.
+ /// </summary>
+ /// <param name="failureMechanism"> The failure mechanism. </param>
+ public void setFailureMechanism(CauseFailure failureMechanism)
+ {
+ this.failureMechanism = failureMechanism;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/LocalCircuitFactory.csx b/dotnet/Qpid.Integration.Tests/framework/LocalCircuitFactory.csx
new file mode 100644
index 0000000000..45ecf26ffe
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/LocalCircuitFactory.csx
@@ -0,0 +1,301 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.localcircuit;//.LocalCircuitImpl;
+//using Apache.Qpid.Integration.Tests.framework.localcircuit.LocalPublisherImpl;
+//using Apache.Qpid.Integration.Tests.framework.localcircuit.LocalReceiverImpl;
+//using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+//using org.apache.qpid.util.ConversationFactory;
+
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+//using javax.jms.*;
+
+using System.Collections.Generic;//.IList;
+//using java.util.Properties;
+//using java.util.concurrent.atomic.AtomicLong;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
+ /// on the same JVM. The ends of the circuit are presented as <see cref="Publisher"/> and <see cref="Receiver"/> interfaces, which
+ /// in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
+ /// of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
+ /// use messaging features not available in JMS can be written. This provides an extension point for writing tests
+ /// against proprietary features of JMS implementations.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a standard test procedure over a test circuit.
+ /// <tr><td> Construct test circuits appropriate to a tests context.
+ /// </table>
+ /// </summary>
+ public class LocalCircuitFactory : CircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(LocalCircuitFactory));
+
+ /// <summary> Used to create unique destination names for each test. </summary>
+ protected static AtomicLong uniqueDestsId = new AtomicLong();
+
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test and gathering the test reports from the participants.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties)
+ {
+ FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions));
+ }
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ ///
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(TestModel testProperties)
+ {
+ Circuit result;
+
+ // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
+ try
+ {
+ // Get a unique offset to append to destination names to make them unique to the connection.
+ long uniqueId = uniqueDestsId.incrementAndGet();
+
+ // Set up the connection.
+ Connection connection = TestUtils.createConnection(testProperties);
+
+ // Add the connection exception listener to assert on exception conditions with.
+ // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ // connection.setExceptionListener(exceptionMonitor);
+
+ // Set up the publisher.
+ CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, testProps, uniqueId);
+
+ // Set up the receiver.
+ CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, testProps, uniqueId);
+
+ // Start listening for incoming messages.
+ connection.start();
+
+ // Namespace everything up.
+ LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
+ LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
+
+ result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a local <see cref="Receiver"/> from a <see cref="CircuitEnd"/>. Sub-classes may override this to provide more
+ /// specialized receivers if necessary.
+ /// </summary>
+ /// <param name="receiverEnd"> The receiving circuit end. </param>
+ ///
+ /// <return> A <see cref="Receiver"/>. </return>
+ protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
+ {
+ return new LocalReceiverImpl(receiverEnd);
+ }
+
+ /// <summary>
+ /// Creates a local <see cref="Publisher"/> from a <see cref="CircuitEnd"/>. Sub-classes may override this to provide more
+ /// specialized receivers if necessary.
+ /// </summary>
+ /// <param name="publisherEnd"> The publishing circuit end. </param>
+ ///
+ /// <return> A <see cref="Receiver"/>. </return>
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalPublisherImpl(publisherEnd);
+ }
+
+ /// <summary>
+ /// Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ /// </summary>
+ /// <param name="connection"> The connection to build the circuit end on. </param>
+ /// <param name="testProps"> The test parameters to configure the circuit end construction. </param>
+ /// <param name="uniqueId"> A unique number to being numbering destinations from, to make this circuit unique. </param>
+ ///
+ /// <return> A circuit end suitable for the publishing side of a test circuit. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through and fail the creation. </exception>
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, TestModel testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, TestModel testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (testProps.getImmediate() || testProps.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(testProps.getPublisherTransacted(), testProps.getAckMode());
+
+ Destination destination =
+ testProps.getPubsub() ? session.createTopic(testProps.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(testProps.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer = testProps.getPublisherProducerBind() ? session.createProducer(destination) : null;
+
+ MessageConsumer consumer =
+ testProps.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(testProps.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!testProps.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ /// </summary>
+ /// <param name="connection"> The connection to build the circuit end on. </param>
+ /// <param name="testProps"> The test parameters to configure the circuit end construction. </param>
+ /// <param name="uniqueId"> A unique number to being numbering destinations from, to make this circuit unique. </param>
+ ///
+ /// <return> A circuit end suitable for the receiving side of a test circuit. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through and fail the creation. </exception>
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, TestModel testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, TestModel testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (testProps.getImmediate() || testProps.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(testProps.getPublisherTransacted(), testProps.getAckMode());
+
+ MessageProducer producer =
+ testProps.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(testProps.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ testProps.getPubsub() ? session.createTopic(testProps.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(testProps.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ testProps.getReceiverConsumerBind()
+ ? ((testProps.getDurableSubscription() && testProps.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!testProps.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /*
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ */
+
+ /*
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ */
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/MessageMonitor.csx b/dotnet/Qpid.Integration.Tests/framework/MessageMonitor.csx
new file mode 100644
index 0000000000..440d0761e5
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/MessageMonitor.csx
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using Apache.Qpid.Messaging;
+
+//using javax.jms.Message;
+//using javax.jms.MessageListener;
+
+//using java.util.concurrent.atomic.AtomicInteger;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// MessageMonitor is used to record information about messages received. This will provide methods to check various
+ /// properties, such as the type, number and content of messages received in order to verify the correct behaviour of
+ /// tests.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Count incoming messages.
+ /// <tr><td> Record time ellapsed since the arrival of the first message.
+ /// <tr><td> Reset all counts and timings.
+ /// </table>
+ /// </summary>
+ public class MessageMonitor : MessageListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(MessageMonitor));
+
+ /// <summary> Holds the count of messages received since the last query. </summary>
+ protected AtomicInteger numMessages = new AtomicInteger();
+
+ /// <summary> Holds the time of arrival of the first message. </summary>
+ protected Long firstMessageTime = null;
+
+ /// <summary>
+ /// Handles received messages. Does Nothing.
+ /// </summary>
+ /// <param name="message"> The message. Ignored. </param>
+ public void onMessage(Message message)
+ {
+ // log.debug("public void onMessage(Message message): called");
+
+ numMessages.getAndIncrement();
+ }
+
+ /// <summary>
+ /// Gets the count of messages.
+ /// </summary>
+ /// <return> The count of messages. </return>
+ public int getNumMessage()
+ {
+ if (firstMessageTime == null)
+ {
+ firstMessageTime = System.nanoTime();
+ }
+
+ return numMessages.get();
+ }
+
+ /// <summary>
+ /// Gets the time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet.
+ /// </summary>
+ /// <return> The time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. </return>
+ public long getTime()
+ {
+ if (firstMessageTime != null)
+ {
+ return System.nanoTime() - firstMessageTime;
+ }
+ else
+ {
+ return 0L;
+ }
+ }
+
+ /// <summary> Resets the message count and timer to zero. </summary>
+ public void reset()
+ {
+ numMessages.set(0);
+ firstMessageTime = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/MessagingTestConfigProperties.csx b/dotnet/Qpid.Integration.Tests/framework/MessagingTestConfigProperties.csx
new file mode 100644
index 0000000000..db19b5c2e0
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/MessagingTestConfigProperties.csx
@@ -0,0 +1,652 @@
+/*
+ *
+ * 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.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.Session;
+
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
+ /// and test parameters for running a messaging test over that topology. A Properties object holding some of these
+ /// properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
+ ///
+ /// <p/>A complete list of the parameters, default values and comments on their usage is provided here:
+ ///
+ /// <p/><table><caption>Parameters</caption>
+ /// <tr><th> Parameter <th> Default <th> Comments
+ /// <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
+ /// <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
+ /// <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
+ /// <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
+ /// <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ /// <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
+ /// <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ /// <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
+ /// <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
+ /// <tr><td> username <td> guest <td> The username to access the broker with.
+ /// <tr><td> password <td> guest <td> The password to access the broker with.
+ /// <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
+ /// <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
+ /// <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
+ /// <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
+ /// <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
+ /// <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
+ /// <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ /// 0 - SESSION_TRANSACTED
+ /// 1 - AUTO_ACKNOWLEDGE
+ /// 2 - CLIENT_ACKNOWLEDGE
+ /// 3 - DUPS_OK_ACKNOWLEDGE
+ /// 257 - NO_ACKNOWLEDGE
+ /// 258 - PRE_ACKNOWLEDGE
+ /// <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
+ /// Limits the volume of messages currently buffered on the client
+ /// or broker. Can help scale test clients by limiting amount of buffered
+ /// data to avoid out of memory errors.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide the names and defaults of all test parameters.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Put a type-safe wrapper around these properties, but continue to store the parameters as properties. This is
+ /// simply to ensure that it is a simple matter to serialize/deserialize string/string pairs onto messages.</remarks>
+ public class MessagingTestConfigProperties extends ParsedProperties
+ {
+ // ====================== Connection Properties ==================================
+
+ /// <summary> Holds the name of the default connection configuration. </summary>
+ public static final string CONNECTION_NAME = "broker";
+
+ /// <summary> Holds the name of the property to get the initial context factory name from. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
+
+ /// <summary> Defines the class to use as the initial context factory by default. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+ /// <summary> Holds the name of the property to get the test broker url from. </summary>
+ public static final string BROKER_PROPNAME = "qpid.test.broker";
+
+ /// <summary> Holds the default broker url for the test. </summary>
+ public static final string BROKER_DEFAULT = "vm://:1";
+
+ /// <summary> Holds the name of the property to get the test broker virtual path. </summary>
+ public static final string VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+ /// <summary> Holds the default virtual path for the test. </summary>
+ public static final string VIRTUAL_HOST_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the broker access username from. </summary>
+ public static final string USERNAME_PROPNAME = "username";
+
+ /// <summary> Holds the default broker log on username. </summary>
+ public static final string USERNAME_DEFAULT = "guest";
+
+ /// <summary> Holds the name of the property to get the broker access password from. </summary>
+ public static final string PASSWORD_PROPNAME = "password";
+
+ /// <summary> Holds the default broker log on password. </summary>
+ public static final string PASSWORD_DEFAULT = "guest";
+
+ // ====================== Messaging Topology Properties ==========================
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
+
+ /// <summary> Holds the default value of the publisher producer flag. </summary>
+ public static final bool PUBLISHER_PRODUCER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
+
+ /// <summary> Holds the default value of the publisher consumer flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
+
+ /// <summary> Holds the default value of the receivers producer flag. </summary>
+ public static final bool RECEIVER_PRODUCER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
+
+ /// <summary> Holds the default value of the receivers consumer flag. </summary>
+ public static final bool RECEIVER_CONSUMER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the publishers consumer active flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_ACTIVE_PROPNAME = "publisherConsumerActive";
+
+ /// <summary> Holds the default value of the publishers consumer active flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the receivers consumer active flag from. </summary>
+ public static final string RECEIVER_CONSUMER_ACTIVE_PROPNAME = "receiverConsumerActive";
+
+ /// <summary> Holds the default value of the receivers consumer active flag. </summary>
+ public static final bool RECEIVER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
+
+ /// <summary> Holds the name of the proeprty to get the destination count from. </summary>
+ public static final string DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+ /// <summary> Defines the default number of destinations to ping. </summary>
+ public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to get the p2p or pub/sub messaging mode from. </summary>
+ public static final string PUBSUB_PROPNAME = "pubsub";
+
+ /// <summary> Holds the pub/sub mode default, true means ping a topic, false means ping a queue. </summary>
+ public static final bool PUBSUB_DEFAULT = false;
+
+ // ====================== JMS Options and Flags =================================
+
+ /// <summary> Holds the name of the property to get the test delivery mode from. </summary>
+ public static final string PERSISTENT_MODE_PROPNAME = "persistent";
+
+ /// <summary> Holds the message delivery mode to use for the test. </summary>
+ public static final bool PERSISTENT_MODE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_RECEIVER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the no local flag from. </summary>
+ public static final string NO_LOCAL_PROPNAME = "noLocal";
+
+ /// <summary> Defines the default value of the no local flag to use when consuming messages. </summary>
+ public static final bool NO_LOCAL_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the message acknowledgement mode from. </summary>
+ public static final string ACK_MODE_PROPNAME = "ackMode";
+
+ /// <summary> Defines the default message acknowledgement mode. </summary>
+ public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /// <summary> Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. </summary>
+ public static final string DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
+
+ /// <summary> Defines the default value of the durable subscriptions flag. </summary>
+ public static final bool DURABLE_SUBSCRIPTION_DEFAULT = false;
+
+ // ====================== Qpid/AMQP Options and Flags ================================
+
+ /// <summary> Holds the name of the property to set the exclusive flag from. </summary>
+ public static final string EXCLUSIVE_PROPNAME = "exclusive";
+
+ /// <summary> Defines the default value of the exclusive flag to use when consuming messages. </summary>
+ public static final bool EXCLUSIVE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the immediate flag from. </summary>
+ public static final string IMMEDIATE_PROPNAME = "immediate";
+
+ /// <summary> Defines the default value of the immediate flag to use when sending messages. </summary>
+ public static final bool IMMEDIATE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the mandatory flag from. </summary>
+ public static final string MANDATORY_PROPNAME = "mandatory";
+
+ /// <summary> Defines the default value of the mandatory flag to use when sending messages. </summary>
+ public static final bool MANDATORY_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the durable destinations flag from. </summary>
+ public static final string DURABLE_DESTS_PROPNAME = "durableDests";
+
+ /// <summary> Default value for the durable destinations flag. </summary>
+ public static final bool DURABLE_DESTS_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the prefetch size from. </summary>
+ public static final string PREFETCH_PROPNAME = "prefetch";
+
+ /// <summary> Defines the default prefetch size to use when consuming messages. </summary>
+ public static final int PREFETCH_DEFAULT = 100;
+
+ // ====================== Common Test Parameters ================================
+
+ /// <summary> Holds the name of the property to get the test message size from. </summary>
+ public static final string MESSAGE_SIZE_PROPNAME = "messageSize";
+
+ /// <summary> Used to set up a default message size. </summary>
+ public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+ /// <summary> Holds the name of the property to get the message rate from. </summary>
+ public static final string RATE_PROPNAME = "rate";
+
+ /// <summary> Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. </summary>
+ public static final int RATE_DEFAULT = 0;
+
+ /// <summary> Holds the name of the proeprty to get the. </summary>
+ public static final string SELECTOR_PROPNAME = "selector";
+
+ /// <summary> Holds the default message selector. </summary>
+ public static final string SELECTOR_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the waiting timeout for response messages. </summary>
+ public static final string TIMEOUT_PROPNAME = "timeout";
+
+ /// <summary> Default time to wait before assuming that a ping has timed out. </summary>
+ public static final long TIMEOUT_DEFAULT = 30000;
+
+ /// <summary> Holds the name of the property to get the commit batch size from. </summary>
+ public static final string TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+ /// <summary> Defines the default number of pings to send in each transaction when running transactionally. </summary>
+ public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to set the maximum amount of pending message data for a producer to hold. </summary>
+ public static final string MAX_PENDING_PROPNAME = "maxPending";
+
+ /// <summary> Defines the default maximum quantity of pending message data to allow producers to hold. </summary>
+ public static final int MAX_PENDING_DEFAULT = 0;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_RECEIVER_DEFAULT = false;
+
+ // ====================== Options that control the bahviour of the test framework. =========================
+
+ /// <summary> Holds the name of the property to get the behavioural mode of not applicable assertions. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion";
+
+ /// <summary> Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_DEFAULT = "warn";
+
+ /// <summary> Holds the name of the property to get the verbose mode proeprty from. </summary>
+ public static final string VERBOSE_PROPNAME = "verbose";
+
+ /// <summary> Holds the default verbose mode. </summary>
+ public static final bool VERBOSE_DEFAULT = false;
+
+ /// <summary> Holds the default configuration properties. </summary>
+ public static ParsedProperties defaults = new ParsedProperties();
+
+ static
+ {
+ defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+
+ defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_ACTIVE_PROPNAME, PUBLISHER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT);
+ defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+ defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
+
+ defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
+ defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
+ defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
+
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT);
+
+ defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
+ }
+
+ /// <summary> Creates a test configuration based on the defaults. </summary>
+ public MessagingTestConfigProperties()
+ {
+ super(defaults);
+ }
+
+ /// <summary>
+ /// Creates a test configuration based on the supplied properties.
+ /// </summary>
+ /// <param name="properties"> The test configuration. </param>
+ public MessagingTestConfigProperties(Properties properties)
+ {
+ super(properties);
+ }
+
+ /// <summary>
+ /// The size of test messages to send.
+ /// </summary>
+ /// <return> The size of test messages to send. </return>
+ public int getMessageSize()
+ {
+ return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing producer should be set up to publish to a destination. </return>
+ public bool getPublisherProducerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be set up to receive from a destination. </return>
+ public bool getPublisherConsumerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving producer should be set up to publish to a destination. </return>
+ public bool getReceiverProducerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumer should be set up to receive from a destination. </return>
+ public bool getReceiverConsumerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be created. </return>
+ public bool getPublisherConsumerActive()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumers should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumers should be created and actively listening. </return>
+ public bool getReceiverConsumerActive()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all test destination names from.
+ /// </summary>
+ /// <return> A root to create all test destination names from. </return>
+ public string getSendDestinationNameRoot()
+ {
+ return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all receiving destination names from.
+ /// </summary>
+ /// <return> A root to create all receiving destination names from. </return>
+ public string getReceiveDestinationNameRoot()
+ {
+ return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that persistent messages should be used.
+ /// </summary>
+ /// <return> Flag to indicate that persistent messages should be used. </return>
+ public bool getPersistentMode()
+ {
+ return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional messages should be sent by the publisher.
+ /// </summary>
+ /// <return> Flag to indicate that transactional messages should be sent by the publisher. </return>
+ public bool getPublisherTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional receives should be used by the receiver.
+ /// </summary>
+ /// <return> Flag to indicate that transactional receives should be used by the receiver. </return>
+ public bool getReceiverTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// The name of the virtual host to run all tests over.
+ /// </summary>
+ /// <return> The name of the virtual host to run all tests over. </return>
+ public string getVirtualHost()
+ {
+ return getProperty(VIRTUAL_HOST_PROPNAME);
+ }
+
+ /// <summary>
+ /// Limiting rate for each sender in messages per second, or zero for unlimited.
+ /// </summary>
+ /// <return> Limiting rate for each sender in messages per second, or zero for unlimited. </return>
+ public string getRate()
+ {
+ return getProperty(RATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+ /// </summary>
+ /// <return> Flag to indicate that test messages should be received publish/subscribe style by all receivers. </return>
+ public bool getPubsub()
+ {
+ return getPropertyAsBoolean(PUBSUB_PROPNAME);
+ }
+
+ /// <summary>
+ /// The username credentials to run tests with.
+ /// </summary>
+ /// <return> The username credentials to run tests with. </return>
+ public string getUsername()
+ {
+ return getProperty(USERNAME_PROPNAME);
+ }
+
+ /// <summary>
+ /// The password credentials to run tests with.
+ /// </summary>
+ /// <return> The password credentials to run tests with. </return>
+ public string getPassword()
+ {
+ return getProperty(PASSWORD_PROPNAME);
+ }
+
+ /// <summary>
+ /// The timeout duration to fail tests on, should they receive no messages within it.
+ /// </summary>
+ /// <return> The timeout duration to fail tests on, should they receive no messages within it. </return>
+ public long getTimeout()
+ {
+ return getPropertyAsLong(TIMEOUT_PROPNAME);
+ }
+
+ /// <summary>
+ /// The number of messages to batch into each transaction in transational tests.
+ /// </summary>
+ /// <return> The number of messages to batch into each transaction in transational tests. </return>
+ public int getTxBatchSize()
+ {
+ return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable destinations.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable destinations. </return>
+ public bool getDurableDests()
+ {
+ return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
+ }
+
+ /// <summary>
+ /// The ack mode for message receivers to use.
+ /// </summary>
+ /// <return> The ack mode for message receivers to use. </return>
+ public int getAckMode()
+ {
+ return getPropertyAsInteger(ACK_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable subscriptions.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable subscriptions. </return>
+ public bool getDurableSubscription()
+ {
+ return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME);
+ }
+
+ /// <summary>
+ /// The maximum amount of in-flight data, in bytes, that tests should send at any time.
+ /// </summary>
+ /// <return> The maximum amount of in-flight data, in bytes, that tests should send at any time. </return>
+ public int getMaxPending()
+ {
+ return getPropertyAsInteger(MAX_PENDING_PROPNAME);
+ }
+
+ /// <summary>
+ /// The size of the prefetch queue to use.
+ /// </summary>
+ /// <return> The size of the prefetch queue to use. </return>
+ public int getPrefetch()
+ {
+ return getPropertyAsInteger(PREFETCH_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be no-local.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be no-local. </return>
+ public bool getNoLocal()
+ {
+ return getPropertyAsBoolean(NO_LOCAL_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be exclusive.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be exclusive. </return>
+ public bool getExclusive()
+ {
+ return getPropertyAsBoolean(EXCLUSIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be delivered immediately.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be delivered immediately. </return>
+ public bool getImmediate()
+ {
+ return getPropertyAsBoolean(IMMEDIATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be routable.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be routable. </return>
+ public bool getMandatory()
+ {
+ return getPropertyAsBoolean(MANDATORY_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the publisher should rollback all messages sent.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages sent. </return>
+ public bool getRollbackPublisher()
+ {
+ return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them
+ /// again.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages received. </return>
+ public bool getRollbackReceiver()
+ {
+ return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'.
+ /// </summary>
+ /// <return> The behavioural mode of not applicable assertions. </return>
+ public string getNotApplicableAssertionMode()
+ {
+ return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME);
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/NotApplicableAssertion.csx b/dotnet/Qpid.Integration.Tests/framework/NotApplicableAssertion.csx
new file mode 100644
index 0000000000..3e3505725f
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/NotApplicableAssertion.csx
@@ -0,0 +1,111 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
+ /// applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
+ /// being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
+ /// instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
+ /// as warnings to the console, or raise them as test failures.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Quitely pass.
+ /// <tr><td> Log a warning.
+ /// <tr><td> Raise a test failure.
+ /// </table>
+ /// </summary>
+ public class NotApplicableAssertion : Assertion
+ {
+ /// <summary> Used for logging to the console. </summary>
+ private static ILog console = LogManager.GetLogger("CONSOLE." + NotApplicableAssertion.class.getName());
+
+ /// <summary> The possible behavioural modes of this assertion. </summary>
+ private enum Mode
+ {
+ /// <summary> Quietly ignore the assertion by passing. </summary>
+ Quiet,
+
+ /// <summary> Ignore the assertion by passing but log a warning about it. </summary>
+ Warn,
+
+ /// <summary> Fail the assertion. </summary>
+ Fail;
+ }
+
+ /// <summary> The behavioural mode of the assertion. </summary>
+ private Mode mode;
+
+ /// <summary>
+ /// Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
+ /// configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
+ /// read as 'fail'.
+ /// </summary>
+ /// <param name="testProperties"> The test configuration properties. </param>
+ public NotApplicableAssertion(ParsedProperties testProperties)
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ string modeName = props.getNotApplicableAssertionMode();
+
+ if ("quiet".equals(modeName))
+ {
+ mode = Mode.Quiet;
+ }
+ else if ("warn".equals(modeName))
+ {
+ mode = Mode.Warn;
+ }
+ else
+ {
+ mode = Mode.Fail;
+ }
+ }
+
+ /// <summary>
+ /// Applies the assertion.
+ /// </summary>
+ /// <return> <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails. </return>
+ public bool apply()
+ {
+ switch (mode)
+ {
+ case Quiet:
+ return true;
+
+ case Warn:
+ console.warn("Warning: Not applicable assertion being ignored.");
+
+ return true;
+
+ case Fail:
+ default:
+ return false;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Publisher.cs b/dotnet/Qpid.Integration.Tests/framework/Publisher.cs
new file mode 100644
index 0000000000..5fbdc7a907
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Publisher.cs
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using System;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions
+ /// that can be applied to test the behaviour of the publishers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the publishers received no exceptions.
+ /// </table>
+ /// </summary>
+ public interface Publisher
+ {
+ /// <summary>
+ /// Provides an assertion that the publisher encountered no exceptions.
+ /// </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ Assertion NoExceptionsAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ Assertion ChannelClosedAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ Assertion ExceptionAssertion(TestModel testProps, Type exceptionClass);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Publisher.csx b/dotnet/Qpid.Integration.Tests/framework/Publisher.csx
new file mode 100644
index 0000000000..b23b8c1e59
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Publisher.csx
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions
+ /// that can be applied to test the behaviour of the publishers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the publishers received no exceptions.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ /// warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ /// I am tempted to go with the dropping/warning/error approach, that would imply that it makes sense to pull
+ /// the assertions back from AMQPPublisher to here.</remarks>
+ public interface Publisher
+ {
+ // Assertions that are meaningfull to AMQP and to JMS.
+
+ /// <summary>
+ /// Provides an assertion that the publisher encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/README.txt b/dotnet/Qpid.Integration.Tests/framework/README.txt
new file mode 100644
index 0000000000..927c3415e5
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/README.txt
@@ -0,0 +1,3 @@
+What are all these .csx files?
+
+This code is being ported over from the java. Some of the conversion was automated using search/replace/regex under emacs, but that cannot do all of it. The files were saved as .csx files with the 'x' standing for in-cross-over state. They will gradually be copied into .cs files as the conversion is completed and they are able to compile.
diff --git a/dotnet/Qpid.Integration.Tests/framework/Receiver.cs b/dotnet/Qpid.Integration.Tests/framework/Receiver.cs
new file mode 100644
index 0000000000..96820b5980
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Receiver.cs
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.
+ *
+ */
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using System;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Receiver is a <see cref="CircuitEnd"/> that represents the status of the receiving side of a test circuit. Its main
+ /// purpose is to provide assertions that can be applied to check the behaviour of the receivers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ public interface Receiver
+ {
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ Assertion NoExceptionsAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ Assertion AllMessagesReceivedAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ Assertion NoMessagesReceivedAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ Assertion ChannelClosedAssertion(TestModel testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the receiver got a given exception during the test. </return>
+ Assertion ExceptionAssertion(TestModel testProps, Type exceptionClass);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/Receiver.csx b/dotnet/Qpid.Integration.Tests/framework/Receiver.csx
new file mode 100644
index 0000000000..bafa57b34b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/Receiver.csx
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Receiver is a <see cref="CircuitEnd"/> that represents the status of the receiving side of a test circuit. Its main
+ /// purpose is to provide assertions that can be applied to check the behaviour of the receivers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ /// warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ /// I am tempted to go with the dropping/warning/error approach.</remarks>
+ public interface Receiver
+ {
+ // Assertions that are meaningfull to AMQP and to JMS.
+
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the receiver got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.cs b/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.cs
new file mode 100644
index 0000000000..8be8de3d96
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.cs
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// TestClientDetails is used to encapsulate information about an interop test client. It pairs together the unique
+ /// name of the client, and the route on which it listens to its control messages.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Record test clients control addresses together with their names.
+ /// </table>
+ /// </summary>
+ public class TestClientDetails
+ {
+ /// <summary> The test clients name. </summary>
+ public string clientName;
+
+ /// <summary> The routing key of the test clients control topic. </summary>
+ public string privateControlKey;
+
+ /// <summary>
+ /// Two TestClientDetails are considered to be equal, iff they have the same client name.
+ /// </summary>
+ /// <param name="o"> The object to compare to. </param>
+ ///
+ /// <return> <tt>If the object to compare to is a TestClientDetails equal to this one, <tt>false</tt> otherwise. </return>
+ public override bool Equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o is TestClientDetails))
+ {
+ return false;
+ }
+
+ TestClientDetails testClientDetails = (TestClientDetails) o;
+
+ return !((clientName != null) ? (!clientName.Equals(testClientDetails.clientName))
+ : (testClientDetails.clientName != null));
+ }
+
+ /// <summary>
+ /// Computes a hash code compatible with the equals method; based on the client name alone.
+ /// </summary>
+ /// <return> A hash code for this. </return>
+ public override int GetHashCode()
+ {
+ return ((clientName != null) ? clientName.GetHashCode() : 0);
+ }
+
+ /// <summary>
+ /// Outputs the client name and address details. Mostly used for debugging purposes.
+ /// </summary>
+ /// <return> The client name and address. </return>
+ public override string ToString()
+ {
+ return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]";
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.csx b/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.csx
new file mode 100644
index 0000000000..877367c762
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/TestClientDetails.csx
@@ -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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// TestClientDetails is used to encapsulate information about an interop test client. It pairs together the unique
+ /// name of the client, and the route on which it listens to its control messages.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Record test clients control addresses together with their names.
+ /// </table>
+ /// </summary>
+ public class TestClientDetails
+ {
+ /// <summary> The test clients name. </summary>
+ public string clientName;
+
+ /// <summary> The routing key of the test clients control topic. </summary>
+ public string privateControlKey;
+
+ /// <summary>
+ /// Two TestClientDetails are considered to be equal, iff they have the same client name.
+ /// </summary>
+ /// <param name="o"> The object to compare to. </param>
+ ///
+ /// <return> <tt>If the object to compare to is a TestClientDetails equal to this one, <tt>false</tt> otherwise. </return>
+ public bool equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof TestClientDetails))
+ {
+ return false;
+ }
+
+ final TestClientDetails testClientDetails = (TestClientDetails) o;
+
+ return !((clientName != null) ? (!clientName.equals(testClientDetails.clientName))
+ : (testClientDetails.clientName != null));
+ }
+
+ /// <summary>
+ /// Computes a hash code compatible with the equals method; based on the client name alone.
+ /// </summary>
+ /// <return> A hash code for this. </return>
+ public int hashCode()
+ {
+ return ((clientName != null) ? clientName.hashCode() : 0);
+ }
+
+ /// <summary>
+ /// Outputs the client name and address details. Mostly used for debugging purposes.
+ /// </summary>
+ /// <return> The client name and address. </return>
+ public string ToString()
+ {
+ return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]";
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/framework/TestModel.cs b/dotnet/Qpid.Integration.Tests/framework/TestModel.cs
new file mode 100644
index 0000000000..88bea1e5ad
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/TestModel.cs
@@ -0,0 +1,657 @@
+/*
+ *
+ * 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.
+ *
+ */
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+//using javax.jms.Session;
+
+//using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ public class TestModel //extends ParsedProperties
+ {}
+
+ /*
+ /// <summary>
+ /// MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
+ /// and test parameters for running a messaging test over that topology. A Properties object holding some of these
+ /// properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
+ ///
+ /// <p/>A complete list of the parameters, default values and comments on their usage is provided here:
+ ///
+ /// <p/><table><caption>Parameters</caption>
+ /// <tr><th> Parameter <th> Default <th> Comments
+ /// <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
+ /// <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
+ /// <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
+ /// <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
+ /// <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ /// <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
+ /// <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ /// <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
+ /// <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
+ /// <tr><td> username <td> guest <td> The username to access the broker with.
+ /// <tr><td> password <td> guest <td> The password to access the broker with.
+ /// <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
+ /// <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
+ /// <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
+ /// <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
+ /// <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
+ /// <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
+ /// <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ /// 0 - SESSION_TRANSACTED
+ /// 1 - AUTO_ACKNOWLEDGE
+ /// 2 - CLIENT_ACKNOWLEDGE
+ /// 3 - DUPS_OK_ACKNOWLEDGE
+ /// 257 - NO_ACKNOWLEDGE
+ /// 258 - PRE_ACKNOWLEDGE
+ /// <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
+ /// Limits the volume of messages currently buffered on the client
+ /// or broker. Can help scale test clients by limiting amount of buffered
+ /// data to avoid out of memory errors.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide the names and defaults of all test parameters.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Put a type-safe wrapper around these properties, but continue to store the parameters as properties. This is
+ /// simply to ensure that it is a simple matter to serialize/deserialize string/string pairs onto messages.</remarks>
+ public class MessagingTestConfigProperties extends ParsedProperties
+ {
+ // ====================== Connection Properties ==================================
+
+ /// <summary> Holds the name of the default connection configuration. </summary>
+ public static final string CONNECTION_NAME = "broker";
+
+ /// <summary> Holds the name of the property to get the initial context factory name from. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
+
+ /// <summary> Defines the class to use as the initial context factory by default. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+ /// <summary> Holds the name of the property to get the test broker url from. </summary>
+ public static final string BROKER_PROPNAME = "qpid.test.broker";
+
+ /// <summary> Holds the default broker url for the test. </summary>
+ public static final string BROKER_DEFAULT = "vm://:1";
+
+ /// <summary> Holds the name of the property to get the test broker virtual path. </summary>
+ public static final string VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+ /// <summary> Holds the default virtual path for the test. </summary>
+ public static final string VIRTUAL_HOST_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the broker access username from. </summary>
+ public static final string USERNAME_PROPNAME = "username";
+
+ /// <summary> Holds the default broker log on username. </summary>
+ public static final string USERNAME_DEFAULT = "guest";
+
+ /// <summary> Holds the name of the property to get the broker access password from. </summary>
+ public static final string PASSWORD_PROPNAME = "password";
+
+ /// <summary> Holds the default broker log on password. </summary>
+ public static final string PASSWORD_DEFAULT = "guest";
+
+ // ====================== Messaging Topology Properties ==========================
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
+
+ /// <summary> Holds the default value of the publisher producer flag. </summary>
+ public static final bool PUBLISHER_PRODUCER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
+
+ /// <summary> Holds the default value of the publisher consumer flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
+
+ /// <summary> Holds the default value of the receivers producer flag. </summary>
+ public static final bool RECEIVER_PRODUCER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
+
+ /// <summary> Holds the default value of the receivers consumer flag. </summary>
+ public static final bool RECEIVER_CONSUMER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the publishers consumer active flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_ACTIVE_PROPNAME = "publisherConsumerActive";
+
+ /// <summary> Holds the default value of the publishers consumer active flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the receivers consumer active flag from. </summary>
+ public static final string RECEIVER_CONSUMER_ACTIVE_PROPNAME = "receiverConsumerActive";
+
+ /// <summary> Holds the default value of the receivers consumer active flag. </summary>
+ public static final bool RECEIVER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
+
+ /// <summary> Holds the name of the proeprty to get the destination count from. </summary>
+ public static final string DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+ /// <summary> Defines the default number of destinations to ping. </summary>
+ public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to get the p2p or pub/sub messaging mode from. </summary>
+ public static final string PUBSUB_PROPNAME = "pubsub";
+
+ /// <summary> Holds the pub/sub mode default, true means ping a topic, false means ping a queue. </summary>
+ public static final bool PUBSUB_DEFAULT = false;
+
+ // ====================== JMS Options and Flags =================================
+
+ /// <summary> Holds the name of the property to get the test delivery mode from. </summary>
+ public static final string PERSISTENT_MODE_PROPNAME = "persistent";
+
+ /// <summary> Holds the message delivery mode to use for the test. </summary>
+ public static final bool PERSISTENT_MODE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_RECEIVER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the no local flag from. </summary>
+ public static final string NO_LOCAL_PROPNAME = "noLocal";
+
+ /// <summary> Defines the default value of the no local flag to use when consuming messages. </summary>
+ public static final bool NO_LOCAL_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the message acknowledgement mode from. </summary>
+ public static final string ACK_MODE_PROPNAME = "ackMode";
+
+ /// <summary> Defines the default message acknowledgement mode. </summary>
+ public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /// <summary> Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. </summary>
+ public static final string DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
+
+ /// <summary> Defines the default value of the durable subscriptions flag. </summary>
+ public static final bool DURABLE_SUBSCRIPTION_DEFAULT = false;
+
+ // ====================== Qpid/AMQP Options and Flags ================================
+
+ /// <summary> Holds the name of the property to set the exclusive flag from. </summary>
+ public static final string EXCLUSIVE_PROPNAME = "exclusive";
+
+ /// <summary> Defines the default value of the exclusive flag to use when consuming messages. </summary>
+ public static final bool EXCLUSIVE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the immediate flag from. </summary>
+ public static final string IMMEDIATE_PROPNAME = "immediate";
+
+ /// <summary> Defines the default value of the immediate flag to use when sending messages. </summary>
+ public static final bool IMMEDIATE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the mandatory flag from. </summary>
+ public static final string MANDATORY_PROPNAME = "mandatory";
+
+ /// <summary> Defines the default value of the mandatory flag to use when sending messages. </summary>
+ public static final bool MANDATORY_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the durable destinations flag from. </summary>
+ public static final string DURABLE_DESTS_PROPNAME = "durableDests";
+
+ /// <summary> Default value for the durable destinations flag. </summary>
+ public static final bool DURABLE_DESTS_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the prefetch size from. </summary>
+ public static final string PREFETCH_PROPNAME = "prefetch";
+
+ /// <summary> Defines the default prefetch size to use when consuming messages. </summary>
+ public static final int PREFETCH_DEFAULT = 100;
+
+ // ====================== Common Test Parameters ================================
+
+ /// <summary> Holds the name of the property to get the test message size from. </summary>
+ public static final string MESSAGE_SIZE_PROPNAME = "messageSize";
+
+ /// <summary> Used to set up a default message size. </summary>
+ public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+ /// <summary> Holds the name of the property to get the message rate from. </summary>
+ public static final string RATE_PROPNAME = "rate";
+
+ /// <summary> Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. </summary>
+ public static final int RATE_DEFAULT = 0;
+
+ /// <summary> Holds the name of the proeprty to get the. </summary>
+ public static final string SELECTOR_PROPNAME = "selector";
+
+ /// <summary> Holds the default message selector. </summary>
+ public static final string SELECTOR_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the waiting timeout for response messages. </summary>
+ public static final string TIMEOUT_PROPNAME = "timeout";
+
+ /// <summary> Default time to wait before assuming that a ping has timed out. </summary>
+ public static final long TIMEOUT_DEFAULT = 30000;
+
+ /// <summary> Holds the name of the property to get the commit batch size from. </summary>
+ public static final string TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+ /// <summary> Defines the default number of pings to send in each transaction when running transactionally. </summary>
+ public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to set the maximum amount of pending message data for a producer to hold. </summary>
+ public static final string MAX_PENDING_PROPNAME = "maxPending";
+
+ /// <summary> Defines the default maximum quantity of pending message data to allow producers to hold. </summary>
+ public static final int MAX_PENDING_DEFAULT = 0;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_RECEIVER_DEFAULT = false;
+
+ // ====================== Options that control the bahviour of the test framework. =========================
+
+ /// <summary> Holds the name of the property to get the behavioural mode of not applicable assertions. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion";
+
+ /// <summary> Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_DEFAULT = "warn";
+
+ /// <summary> Holds the name of the property to get the verbose mode proeprty from. </summary>
+ public static final string VERBOSE_PROPNAME = "verbose";
+
+ /// <summary> Holds the default verbose mode. </summary>
+ public static final bool VERBOSE_DEFAULT = false;
+
+ /// <summary> Holds the default configuration properties. </summary>
+ public static ParsedProperties defaults = new ParsedProperties();
+
+ static
+ {
+ defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+
+ defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_ACTIVE_PROPNAME, PUBLISHER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT);
+ defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+ defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
+
+ defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
+ defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
+ defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
+
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT);
+
+ defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
+ }
+
+ /// <summary> Creates a test configuration based on the defaults. </summary>
+ public MessagingTestConfigProperties()
+ {
+ super(defaults);
+ }
+
+ /// <summary>
+ /// Creates a test configuration based on the supplied properties.
+ /// </summary>
+ /// <param name="properties"> The test configuration. </param>
+ public MessagingTestConfigProperties(Properties properties)
+ {
+ super(properties);
+ }
+
+ /// <summary>
+ /// The size of test messages to send.
+ /// </summary>
+ /// <return> The size of test messages to send. </return>
+ public int getMessageSize()
+ {
+ return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing producer should be set up to publish to a destination. </return>
+ public bool getPublisherProducerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be set up to receive from a destination. </return>
+ public bool getPublisherConsumerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving producer should be set up to publish to a destination. </return>
+ public bool getReceiverProducerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumer should be set up to receive from a destination. </return>
+ public bool getReceiverConsumerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be created. </return>
+ public bool getPublisherConsumerActive()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumers should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumers should be created and actively listening. </return>
+ public bool getReceiverConsumerActive()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all test destination names from.
+ /// </summary>
+ /// <return> A root to create all test destination names from. </return>
+ public string getSendDestinationNameRoot()
+ {
+ return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all receiving destination names from.
+ /// </summary>
+ /// <return> A root to create all receiving destination names from. </return>
+ public string getReceiveDestinationNameRoot()
+ {
+ return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that persistent messages should be used.
+ /// </summary>
+ /// <return> Flag to indicate that persistent messages should be used. </return>
+ public bool getPersistentMode()
+ {
+ return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional messages should be sent by the publisher.
+ /// </summary>
+ /// <return> Flag to indicate that transactional messages should be sent by the publisher. </return>
+ public bool getPublisherTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional receives should be used by the receiver.
+ /// </summary>
+ /// <return> Flag to indicate that transactional receives should be used by the receiver. </return>
+ public bool getReceiverTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// The name of the virtual host to run all tests over.
+ /// </summary>
+ /// <return> The name of the virtual host to run all tests over. </return>
+ public string getVirtualHost()
+ {
+ return getProperty(VIRTUAL_HOST_PROPNAME);
+ }
+
+ /// <summary>
+ /// Limiting rate for each sender in messages per second, or zero for unlimited.
+ /// </summary>
+ /// <return> Limiting rate for each sender in messages per second, or zero for unlimited. </return>
+ public string getRate()
+ {
+ return getProperty(RATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+ /// </summary>
+ /// <return> Flag to indicate that test messages should be received publish/subscribe style by all receivers. </return>
+ public bool getPubsub()
+ {
+ return getPropertyAsBoolean(PUBSUB_PROPNAME);
+ }
+
+ /// <summary>
+ /// The username credentials to run tests with.
+ /// </summary>
+ /// <return> The username credentials to run tests with. </return>
+ public string getUsername()
+ {
+ return getProperty(USERNAME_PROPNAME);
+ }
+
+ /// <summary>
+ /// The password credentials to run tests with.
+ /// </summary>
+ /// <return> The password credentials to run tests with. </return>
+ public string getPassword()
+ {
+ return getProperty(PASSWORD_PROPNAME);
+ }
+
+ /// <summary>
+ /// The timeout duration to fail tests on, should they receive no messages within it.
+ /// </summary>
+ /// <return> The timeout duration to fail tests on, should they receive no messages within it. </return>
+ public long getTimeout()
+ {
+ return getPropertyAsLong(TIMEOUT_PROPNAME);
+ }
+
+ /// <summary>
+ /// The number of messages to batch into each transaction in transational tests.
+ /// </summary>
+ /// <return> The number of messages to batch into each transaction in transational tests. </return>
+ public int getTxBatchSize()
+ {
+ return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable destinations.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable destinations. </return>
+ public bool getDurableDests()
+ {
+ return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
+ }
+
+ /// <summary>
+ /// The ack mode for message receivers to use.
+ /// </summary>
+ /// <return> The ack mode for message receivers to use. </return>
+ public int getAckMode()
+ {
+ return getPropertyAsInteger(ACK_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable subscriptions.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable subscriptions. </return>
+ public bool getDurableSubscription()
+ {
+ return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME);
+ }
+
+ /// <summary>
+ /// The maximum amount of in-flight data, in bytes, that tests should send at any time.
+ /// </summary>
+ /// <return> The maximum amount of in-flight data, in bytes, that tests should send at any time. </return>
+ public int getMaxPending()
+ {
+ return getPropertyAsInteger(MAX_PENDING_PROPNAME);
+ }
+
+ /// <summary>
+ /// The size of the prefetch queue to use.
+ /// </summary>
+ /// <return> The size of the prefetch queue to use. </return>
+ public int getPrefetch()
+ {
+ return getPropertyAsInteger(PREFETCH_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be no-local.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be no-local. </return>
+ public bool getNoLocal()
+ {
+ return getPropertyAsBoolean(NO_LOCAL_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be exclusive.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be exclusive. </return>
+ public bool getExclusive()
+ {
+ return getPropertyAsBoolean(EXCLUSIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be delivered immediately.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be delivered immediately. </return>
+ public bool getImmediate()
+ {
+ return getPropertyAsBoolean(IMMEDIATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be routable.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be routable. </return>
+ public bool getMandatory()
+ {
+ return getPropertyAsBoolean(MANDATORY_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the publisher should rollback all messages sent.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages sent. </return>
+ public bool getRollbackPublisher()
+ {
+ return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them
+ /// again.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages received. </return>
+ public bool getRollbackReceiver()
+ {
+ return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'.
+ /// </summary>
+ /// <return> The behavioural mode of not applicable assertions. </return>
+ public string getNotApplicableAssertionMode()
+ {
+ return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME);
+ }
+ }
+ */
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/TestUtils.csx b/dotnet/Qpid.Integration.Tests/framework/TestUtils.csx
new file mode 100644
index 0000000000..bb00bf2683
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/TestUtils.csx
@@ -0,0 +1,188 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using static Apache.Qpid.Integration.Tests.framework.MessagingTestConfigProperties.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.*;
+using javax.naming.Context;
+using javax.naming.InitialContext;
+using javax.naming.NamingException;
+
+using System.Collections.Generic.IDictionary;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// TestUtils provides static helper methods that are usefull for writing tests against QPid.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create connections from test properties. <td> <see cref="MessagingTestConfigProperties"/>
+ /// <tr><td> Create test messages.
+ /// <tr><td> Inject a short pause in a test.
+ /// <tr><td> Serialize properties into a message.
+ /// </table>
+ /// </summary>
+ public class TestUtils
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestUtils));
+
+ /// <summary> Some dummy data to stuff all test messages with. </summary>
+ private static final byte[] MESSAGE_DATA_BYTES =
+ "Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- "
+ .getBytes();
+
+ /// <summary>
+ /// Establishes a JMS connection using a set of properties and qpids built in JNDI implementation. This is a simple
+ /// convenience method for code that does not anticipate handling connection failures. All exceptions that indicate
+ /// that the connection has failed, are wrapped as rutime exceptions, presumably handled by a top level failure
+ /// handler.
+ ///
+ /// <p/>This utility makes use of the following test parameters from <see cref="MessagingTestConfigProperties"/> to control
+ /// the connection creation:
+ ///
+ /// <p/><table>
+ /// <tr><td> <see cref="MessagingTestConfigProperties#USERNAME_PROPNAME"/> <td> The username.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#PASSWORD_PROPNAME"/> <td> The password.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#VIRTUAL_HOST_PROPNAME"/> <td> The virtual host name.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#BROKER_PROPNAME"/> <td> The broker URL.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#CONNECTION_NAME"/> <td> The broker name in the initial context.
+ /// </summary>
+ /// <param name="messagingProps"> Connection properties as defined in <see cref="MessagingTestConfigProperties"/>. </param>
+ ///
+ /// <return> A JMS conneciton. </return>
+ public static Connection createConnection(ParsedProperties messagingProps)
+ {
+ log.debug("public static Connection createConnection(ParsedProperties messagingProps = " + messagingProps
+ + "): called");
+
+ try
+ {
+ // Extract the configured connection properties from the test configuration.
+ string conUsername = messagingProps.getProperty(USERNAME_PROPNAME);
+ string conPassword = messagingProps.getProperty(PASSWORD_PROPNAME);
+ string virtualHost = messagingProps.getProperty(VIRTUAL_HOST_PROPNAME);
+ string brokerUrl = messagingProps.getProperty(BROKER_PROPNAME);
+
+ // Create the broker connection url.
+ string connectionstring =
+ "amqp://" + conUsername + ":" + conPassword + "@clientid/" + ((virtualHost != null) ? virtualHost : "")
+ + "?brokerlist='" + brokerUrl + "'";
+
+ // Create properties to create the initial context from, and inject the connection factory configuration
+ // for the defined connection name into it.
+ messagingProps.setProperty("connectionfactory." + CONNECTION_NAME, connectionString);
+
+ Context ctx = new InitialContext(messagingProps);
+
+ ConnectionFactory cf = (ConnectionFactory) ctx.lookup(CONNECTION_NAME);
+
+ return cf.createConnection();
+ }
+ catch (NamingException e)
+ {
+ throw new RuntimeException("Got JNDI NamingException whilst looking up the connection factory.", e);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not establish connection due to JMSException.", e);
+ }
+ }
+
+ /// <summary>
+ /// Creates a test message of the specified size, on the given JMS session.
+ /// </summary>
+ /// <param name="session"> The JMS session. </param>
+ /// <param name="size"> The size of the message in bytes. </param>
+ ///
+ /// <return> A bytes message, of the specified size, filled with dummy data. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through. </exception>
+ public static Message createTestMessageOfSize(Session session, int size) throws JMSException
+ {
+ BytesMessage message = session.createBytesMessage();
+
+ if (size > 0)
+ {
+ int div = MESSAGE_DATA_BYTES.length / size;
+ int mod = MESSAGE_DATA_BYTES.length % size;
+
+ for (int i = 0; i < div; i++)
+ {
+ message.writeBytes(MESSAGE_DATA_BYTES);
+ }
+
+ if (mod != 0)
+ {
+ message.writeBytes(MESSAGE_DATA_BYTES, 0, mod);
+ }
+ }
+
+ return message;
+ }
+
+ /// <summary>
+ /// Pauses for the specified length of time. In the event of failing to pause for at least that length of time
+ /// due to interuption of the thread, a RutimeException is raised to indicate the failure. The interupted status
+ /// of the thread is restores in that case. This method should only be used when it is expected that the pause
+ /// will be succesfull, for example in test code that relies on inejecting a pause.
+ /// </summary>
+ /// <param name="t"> The minimum time to pause for in milliseconds. </param>
+ public static void pause(long t)
+ {
+ try
+ {
+ Thread.sleep(t);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+
+ throw new RuntimeException("Failed to generate the requested pause length.", e);
+ }
+ }
+
+ /// <summary>
+ /// Sets properties of different types on a JMS Message.
+ /// </summary>
+ /// <param name="message"> The message to set properties on. </param>
+ /// <param name="properties"> The property name/value pairs to set. </param>
+ ///
+ /// <exception cref="javax.jms.JMSException"> All underlying JMSExceptions are allowed to fall through. </exception>
+ ///
+ /// <remarks> Move this helper method somewhere else. For example, TestUtils.</remarks>
+ public static void setPropertiesOnMessage(Message message, Map<Object, Object> properties) throws JMSException
+ {
+ for (Map.Entry<Object, Object> entry : properties.entrySet())
+ {
+ string name = entry.getKey().ToString();
+ Object value = entry.getValue();
+
+ message.setObjectProperty(name, value);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/alljava.csx b/dotnet/Qpid.Integration.Tests/framework/alljava.csx
new file mode 100644
index 0000000000..23ebd53a5b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/alljava.csx
@@ -0,0 +1,7851 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// Assertion models an assertion on a test <see cref="Circuit"/>.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Indicate whether or not the assertion passes when applied.
+ /// </table>
+ /// </summary>
+ public interface Assertion
+ {
+ /// <summary>
+ /// Applies the assertion.
+ /// </summary>
+ /// <return> <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails. </return>
+ public bool apply();
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// AssertionBase is a base class for implenmenting assertions. It provides a mechanism to store error messages, and
+ /// report all error messages when its <see cref="#ToString()"/> method is called.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Collect error messages.
+ /// </table>
+ /// </summary>
+ public abstract class AssertionBase : Assertion
+ {
+ /// <summary> Holds the error messages. </summary>
+ IList<String> errors = new LinkedList<String>();
+
+ /// <summary>
+ /// Adds an error message to the assertion.
+ /// </summary>
+ /// <param name="error"> An error message to add to the assertion. </param>
+ public void addError(string error)
+ {
+ errors.add(error);
+ }
+
+ /// <summary>
+ /// Prints all of the error messages in the assertion into a string.
+ /// </summary>
+ /// <return> All of the error messages in the assertion as a string. </return>
+ public string ToString()
+ {
+ string result = "";
+
+ for (string error : errors)
+ {
+ result += error;
+ }
+
+ return result;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of
+ /// the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that
+ /// enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Indicate whether or not a test case is using an in-vm broker.
+ /// <tr><td> Track which in-vm broker is currently in use.
+ /// <tr><td> Accept setting of a failure mechanism. <td> <see cref="CauseFailure"/>.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Need to think about how to present the brokers through this interface. Thinking numbering the available
+ /// brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto
+ /// 1 again? </remarks>
+ public interface BrokerLifecycleAware
+ {
+ public void setInVmBrokers();
+
+ /// <summary>
+ /// Indicates whether or not a test case is using in-vm brokers.
+ /// </summary>
+ /// <return> <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise. </return>
+ public bool usingInVmBroker();
+
+ /// <summary>
+ /// Sets the currently live in-vm broker.
+ /// </summary>
+ /// <param name="i"> The currently live in-vm broker. </param>
+ public void setLiveBroker(int i);
+
+ /// <summary>
+ /// Reports the currently live in-vm broker.
+ /// </summary>
+ /// <return> The currently live in-vm broker. </return>
+ public int getLiveBroker();
+
+ /// <summary>
+ /// Accepts a failure mechanism.
+ /// </summary>
+ /// <param name="failureMechanism"> The failure mechanism. </param>
+ public void setFailureMechanism(CauseFailure failureMechanism);
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over
+ /// or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker,
+ /// or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable
+ /// to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or
+ /// dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract
+ /// the exact cause and nature of a failure out of failure test cases.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Cause messaging broker failure.
+ /// </table>
+ /// </summary>
+ public interface CauseFailure
+ {
+ /// <summary> Causes the active message broker to fail. </summary>
+ void causeFailure();
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.CauseFailure;
+
+using java.io.IOException;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// Causes a message broker failure by interactively prompting the user to cause it.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Cause messaging broker failure.
+ /// </table>
+ /// </summary>
+ public class CauseFailureUserPrompt : CauseFailure
+ {
+ /// <summary> Causes the active message broker to fail.</summary>
+ public void causeFailure()
+ {
+ waitForUser("Cause a broker failure now, then press Return.");
+ }
+
+ /// <summary>
+ /// Outputs a prompt to the console and waits for the user to press return.
+ /// </summary>
+ /// <param name="prompt"> The prompt to display on the console. </param>
+ private void waitForUser(string prompt)
+ {
+ System.out.println(prompt);
+
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ // Ignored.
+ }
+
+ System.out.println("Continuing.");
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Circuit is the basic test unit against which test cases are to be written. A circuit consists of two 'ends', an
+ /// instigating 'publisher' end and a more passive 'receivers' end.
+ ///
+ /// <p/>Once created, the life-cycle of a circuit may be controlled by <see cref="#start()"/>ing it, or <see cref="#close()"/>ing it.
+ /// Once started, the circuit is ready to send messages over. Once closed the circuit can no longer be used.
+ ///
+ /// <p/>The state of the circuit may be taken with the <see cref="#check()"/> method, and asserted against by the
+ /// <see cref="#applyAssertions(System.Collections.Generic.IList)"/> method.
+ ///
+ /// <p/>There is a default test procedure which may be performed against the circuit. The outline of this procedure is:
+ ///
+ /// <p/><pre>
+ /// Start the circuit.
+ /// Send test messages.
+ /// Request a status report.
+ /// Assert conditions on the publishing end of the circuit.
+ /// Assert conditions on the receiving end of the circuit.
+ /// Close the circuit.
+ /// Pass with no failed assertions or fail with a list of failed assertions.
+ /// </pre>
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state.
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedue on the circuit.
+ /// </table>
+ /// </summary>
+ public interface Circuit
+ {
+ /// <summary>
+ /// Gets the interface on the publishing end of the circuit.
+ /// </summary>
+ /// <return> The publishing end of the circuit. </return>
+ public Publisher getPublisher();
+
+ /// <summary>
+ /// Gets the interface on the receiving end of the circuit.
+ /// </summary>
+ /// <return> The receiving end of the circuit. </return>
+ public Receiver getReceiver();
+
+ /// <summary>
+ /// Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+ public void start();
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ public void check();
+
+ /// <summary>
+ /// Closes the circuit. All associated resources are closed.
+ public void close();
+
+ /// <summary>
+ /// Applied a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ /// <param name="assertions"> The list of assertions to apply to the circuit. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> applyAssertions(List<Assertion> assertions);
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+ /// </summary>
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> test(int numMessages, List<Assertion> assertions);
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using javax.jms.*;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A CircuitEnd is a pair consisting of one message producer and one message consumer, that represents one end of a
+ /// test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both
+ /// the consumer and producer are instantiated and configured.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Update the <see cref="org.apache.qpid.util.ConversationFactory"/> so that it accepts these as the basic conversation
+ /// connection units.</remarks>
+ public interface CircuitEnd
+ {
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public MessageProducer getProducer();
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public MessageConsumer getConsumer();
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void send(Message message) throws JMSException;
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public Session getSession();
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ /// </summary>
+ /// <exception cref="JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void close() throws JMSException;
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor getMessageMonitor();
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor getExceptionMonitor();
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using javax.jms.*;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A CircuitEndBase is a pair consisting of one message producer and one message consumer, that represents one end of a
+ /// test circuit. It is a standard unit of connectivity allowing a full-duplex conversation to be held, provided both
+ /// the consumer and producer are instantiated and configured.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// </table>
+ /// </summary>
+ public class CircuitEndBase : CircuitEnd
+ {
+ /// <summary> Holds the single message producer. </summary>
+ MessageProducer producer;
+
+ /// <summary> Holds the single message consumer. </summary>
+ MessageConsumer consumer;
+
+ /// <summary> Holds the controlSession for the circuit end. </summary>
+ Session session;
+
+ /// <summary> Holds the message monitor for the circuit end. </summary>
+ MessageMonitor messageMonitor;
+
+ /// <summary> Holds the exception monitor for the circuit end. </summary>
+ ExceptionMonitor exceptionMonitor;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public CircuitEndBase(MessageProducer producer, MessageConsumer consumer, Session session, MessageMonitor messageMonitor,
+ ExceptionMonitor exceptionMonitor)
+ {
+ this.producer = producer;
+ this.consumer = consumer;
+ this.session = session;
+
+ this.messageMonitor = messageMonitor;
+ this.exceptionMonitor = exceptionMonitor;
+ }
+
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public MessageProducer getProducer()
+ {
+ return producer;
+ }
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public MessageConsumer getConsumer()
+ {
+ return consumer;
+ }
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ /// <exception cref="javax.jms.JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void send(Message message) throws JMSException
+ {
+ producer.send(message);
+ }
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public Session getSession()
+ {
+ return session;
+ }
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ /// </summary>
+ /// <exception cref="javax.jms.JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void close() throws JMSException
+ {
+ if (producer != null)
+ {
+ producer.close();
+ }
+
+ if (consumer != null)
+ {
+ consumer.close();
+ }
+ }
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor getMessageMonitor()
+ {
+ return messageMonitor;
+ }
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor getExceptionMonitor()
+ {
+ return exceptionMonitor;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchFailureException represents failure of a <see cref="ClockSynchronizer"/> to achieve synchronization. For example,
+ /// this could be because a reference signal is not available, or because a desired accurracy cannot be attained.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Represent failure to achieve synchronization.
+ /// </table>
+ /// </summary>
+ public class ClockSynchFailureException extends Exception
+ {
+ /// <summary>
+ /// Creates a clock synch failure exception.
+ /// </summary>
+ /// <param name="message"> The detail message (which is saved for later retrieval by the <see cref="#getMessage()"/> method). </param>
+ /// <param name="cause"> The cause (which is saved for later retrieval by the <see cref="#getCause()"/> method). (A <tt>null</tt>
+ /// value is permitted, and indicates that the cause is nonexistent or unknown.)</param>
+ public ClockSynchFailureException(string message, Throwable cause)
+ {
+ super(message, cause);
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchronizer provides an interface through which two nodes may synchronize their clocks. It is expected that one
+ /// node will act as the reference clock, to which no delta need be applied, and the other node will act as the slave,
+ /// and which must apply a delta to its local clock to get a clock synchronized with the reference.
+ ///
+ /// <p/>The slave side will initiate the computation of a clock delta by calling the <see cref="#synch"/> method. This method
+ /// will not return until the delta has been computed, at which point there is a method to return its value, as well as
+ /// an estimate of the likely error (usually one standard deviation), in the synchronization. For convenience there is a
+ /// <see cref="#nanoTime"/> method to return the value of System.nanoTime() with the delta added in.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Trigger a clock synchronization.
+ /// <tr><td> Compute a clock delta to apply to the local clock.
+ /// <tr><td> Estimate the error in the synchronzation.
+ /// </table>
+ /// </summary>
+ public interface ClockSynchronizer
+ {
+ /// <summary>
+ /// The slave side should call this to copute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved. </exception>
+ public void synch() throws ClockSynchFailureException;
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta();
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon();
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime();
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.ShutdownHookable;
+using uk.co.thebadgerset.junit.extensions.Throttle;
+
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchThread is a convenient utility for running a thread that periodically synchronizes the clock against
+ /// a reference. Supply it with a <see cref="ClockSynchronizer"/> and a <see cref="Throttle"/> and it will continually keep the
+ /// clock up-to-date at a rate determined by the throttle.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Continually sychronize the clock at a throttled rate.
+ /// </table>
+ /// </summary>
+ public class ClockSynchThread extends Thread : ShutdownHookable
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(ClockSynchThread));
+
+ /// <summary> Holds the clock syncher for the synch thread. </summary>
+ private ClockSynchronizer clockSyncher;
+
+ /// <summary> Holds the throttle to limit the synch rate. </summary>
+ private Throttle throttle;
+
+ /// <summary> Flag to indicate that the periodic clock syncher should keep running. </summary>
+ bool doSynch = true;
+
+ /// <summary>
+ /// Creates a clock synchronizer thread from a clock synchronizer and a throttle.
+ /// </summary>
+ /// <param name="syncher"> The clock synchronizer. </param>
+ /// <param name="throttle"> The throttle. </param>
+ public ClockSynchThread(ClockSynchronizer syncher, Throttle throttle)
+ {
+ this.clockSyncher = syncher;
+ this.throttle = throttle;
+ }
+
+ /// <summary> Terminates the synchronization thread. </summary>
+ public void terminate()
+ {
+ doSynch = false;
+ }
+
+ /// <summary> Continually updates the clock, until <see cref="#terminate()"/> is called. </summary>
+ public void run()
+ {
+ while (doSynch)
+ {
+ // Perform a clock clockSynch.
+ try
+ {
+ // Wait controlled by the throttle before doing the next synch.
+ throttle.throttle();
+
+ clockSyncher.synch();
+ log.debug("Clock synched, delta = " + clockSyncher.getDelta() + ", epsilon = " + clockSyncher.getEpsilon()
+ + ".");
+ }
+ // Terminate the synch thread if the synchronization cannot be achieved.
+ catch (ClockSynchFailureException e)
+ {
+ log.debug("Cannot synchronize the clock (reference service may be down). Terminating the synch thread.");
+ doSynch = false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the clock synchronizer that is kept continually up to date.
+ /// </summary>
+ /// <return> The clock synchronizer that is kept continually up to date. </return>
+ public ClockSynchronizer getClockSyncher()
+ {
+ return clockSyncher;
+ }
+
+ /// <summary>
+ /// Supplies a shutdown hook, that terminates the synching thread.
+ /// </summary>
+ /// <return> The shut down hook. </return>
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doSynch = false;
+ }
+ });
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+
+ /// <summary>
+ /// LocalClockSynchronizer is a fake <see cref="ClockSynchronizer"/> that simply calls System.nanoTime(). It exists so that
+ /// the same tests can be run distributed or locally, taking timings against the ClockSynchronizer interface without
+ /// being aware of how they are being run.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the local clock with no delta.
+ /// </table>
+ /// </summary>
+ public class LocalClockSynchronizer : ClockSynchronizer
+ {
+ /// <summary>
+ /// The slave side should call this to copute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="Apache.Qpid.Integration.Tests.framework.clocksynch.ClockSynchFailureException"> If synchronization cannot be achieved. </exception>
+ public void synch() throws ClockSynchFailureException
+ { }
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta()
+ {
+ return 0L;
+ }
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon()
+ {
+ return 0L;
+ }
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime()
+ {
+ return System.nanoTime();
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.ShutdownHookable;
+
+using java.io.IOException;
+using java.net.*;
+using java.nio.ByteBuffer;
+
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// UDPClockReference supplies a refernce clock signal (generated from System.nanoTime()).
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply a reference clock signal.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Port hard coded. Make configurable.</remarks>
+ ///
+ /// <remarks> Errors rethrown as runtimes, or silently terminate the service. Could add better error handling if needed.</remarks>
+ public class UDPClockReference : Runnable, ShutdownHookable
+ {
+ /// <summary> Used for debugging. </summary>
+ // private static ILog log = LogManager.GetLogger(typeof(UDPClockReference));
+
+ /// <summary> Defines the timeout to use when polling the socket for time requests. </summary>
+ private static final int TIMEOUT = 200;
+
+ /// <summary> Defines the port to run the clock reference on. </summary>
+ public static final int REFERENCE_PORT = 4444;
+
+ /// <summary> Holds the socket to receive clock reference requests on. </summary>
+ protected DatagramSocket socket = null;
+
+ /// <summary> Flag used to indicate that the time server should keep running. Set to false to terminate. </summary>
+ protected bool publish = true;
+
+ /// <summary> Creates a clock reference service on the standard port. </summary>
+ public UDPClockReference()
+ {
+ try
+ {
+ socket = new DatagramSocket(REFERENCE_PORT);
+ socket.setSoTimeout(TIMEOUT);
+ }
+ catch (SocketException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// Implements the run loop for this reference time server. This waits for incoming time requests, and replies to
+ /// any, with a message with the local time stamp in it. Periodically (controlled by <see cref="#TIMEOUT"/>), the run
+ /// loop will check if the <see cref="#publish"/> flag has been cleared, and terminate the reference time service if so.
+ /// </summary>
+ public void run()
+ {
+ byte[] buf = new byte[256];
+ ByteBuffer bbuf = ByteBuffer.wrap(buf);
+
+ while (publish)
+ {
+ try
+ {
+ // Wait for a reference time request.
+ DatagramPacket packet = new DatagramPacket(buf, buf.length);
+ bool timedOut = false;
+
+ try
+ {
+ socket.receive(packet);
+ }
+ catch (SocketTimeoutException e)
+ {
+ timedOut = true;
+ }
+
+ if (!timedOut)
+ {
+ // Work out from the received packet, where to reply to.
+ InetAddress address = packet.getAddress();
+ int port = packet.getPort();
+
+ // Respond to the time request by sending back the local clock as the reference time.
+ bbuf.putLong(System.nanoTime());
+ bbuf.flip();
+ packet = new DatagramPacket(bbuf.array(), bbuf.capacity(), address, port);
+
+ socket.send(packet);
+ }
+ }
+ catch (IOException e)
+ {
+ publish = false;
+ }
+ }
+
+ socket.close();
+ }
+
+ /// <summary>
+ /// Supplies a shutdown hook.
+ /// </summary>
+ /// <return> The shut down hook. </return>
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ publish = false;
+ }
+ });
+ }
+
+ /// <summary>
+ /// For testing purposes. Runs a reference clock on the default port.
+ /// </summary>
+ /// <param name="args"> None. </param>
+ public static void main(String[] args)
+ {
+ try
+ {
+ // Create the clock reference service.
+ UDPClockReference clock = new UDPClockReference();
+
+ // Set up a shutdown hook for it.
+ Runtime.getRuntime().addShutdownHook(clock.getShutdownHook());
+
+ // Start the service.
+ clock.run();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.util.CommandLineParser;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using java.io.IOException;
+using java.net.*;
+using java.nio.ByteBuffer;
+using java.util.Arrays;
+
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// UDPClockSynchronizer is a <see cref="ClockSynchronizer"/> that sends pings as UDP datagrams, and uses the following simple
+ /// algorithm to perform clock synchronization:
+ ///
+ /// <ol>
+ /// <li>Slave initiates synchronization with a Reference clock.</li>
+ /// <li>Slave stamps current local time on a "time request" message and sends to the Reference.</li>
+ /// <li>Upon receipt by Reference, Reference stamps Reference-time and returns.</li>
+ /// <li>Upon receipt by Slave, Slave subtracts current time from sent time and divides by two to compute latency. It
+ /// subtracts current time from Reference time to determine Slave-Reference time delta and adds in the
+ /// half-latency to get the correct clock delta.</li>
+ /// <li>The first result is immediately used to update the clock since it will get the local clock into at least
+ /// the right ballpark.</li>
+ /// <li>The Slave repeats steps 2 through 4, 15 more times.</li>
+ /// <li>The results of the packet receipts are accumulated and sorted in lowest-latency to highest-latency order. The
+ /// median latency is determined by picking the mid-point sample from this ordered list.</li>
+ /// <li>All samples outside 1 standard-deviation from the median are discarded and the remaining samples
+ /// are averaged using an arithmetic mean.</li>
+ /// </ol>
+ ///
+ /// <p/>The use of UDP datagrams, instead of TCP based communication eliminates the hidden delays that TCP can introduce,
+ /// as it can transparently re-order or re-send packets, or introduce delays as packets are naggled.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Trigger a clock synchronziation.
+ /// <tr><td> Compute a clock delta to apply to the local clock.
+ /// <tr><td> Estimate the error in the synchronzation.
+ /// </table>
+ /// </summary>
+ public class UDPClockSynchronizer : ClockSynchronizer
+ {
+ /// <summary> Used for debugging. </summary>
+ // private static ILog log = LogManager.GetLogger(typeof(UDPClockSynchronizer));
+
+ /// <summary> Defines the timeout to use when waiting for responses to time requests. </summary>
+ private static final int TIMEOUT = 50;
+
+ /// <summary> The clock delta. </summary>
+ private long delta = 0L;
+
+ /// <summary> Holds an estimate of the clock error relative to the reference clock. </summary>
+ private long epsilon = 0L;
+
+ /// <summary> Holds the address of the reference clock. </summary>
+ private InetAddress referenceAddress;
+
+ /// <summary> Holds the socket to communicate with the reference service over. </summary>
+ private DatagramSocket socket;
+
+ /// <summary> Used to control the shutdown in the main test loop. </summary>
+ private static bool doSynch = true;
+
+ /// <summary>
+ /// Creates a clock synchronizer against the specified address for the reference.
+ /// </summary>
+ /// <param name="address"> The address of the reference service. </param>
+ public UDPClockSynchronizer(string address)
+ {
+ try
+ {
+ referenceAddress = InetAddress.getByName(address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// The slave side should call this to compute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved, due to unavailability of the reference
+ /// time service. </exception>
+ public void synch() throws ClockSynchFailureException
+ {
+ try
+ {
+ socket = new DatagramSocket();
+ socket.setSoTimeout(TIMEOUT);
+
+ // Synchronize on a single ping, to get the clock into the right ball-park.
+ synch(1);
+
+ // Synchronize on 15 pings.
+ synch(15);
+
+ // And again, for greater accuracy, on 31.
+ synch(31);
+
+ socket.close();
+ }
+ catch (SocketException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// Updates the synchronization delta by performing the specified number of reference clock requests.
+ /// </summary>
+ /// <param name="n"> The number of reference clock request cycles to perform. </param>
+ ///
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved, due to unavailability of the reference
+ /// time service. </exception>
+ protected void synch(int n) throws ClockSynchFailureException
+ {
+ // log.debug("protected void synch(int n = " + n + "): called");
+
+ // Create an array of deltas by performing n reference pings.
+ long[] delta = new long[n];
+
+ for (int i = 0; i < n; i++)
+ {
+ delta[i] = ping();
+ }
+
+ // Reject any deltas that are larger than 1 s.d. above the median.
+ long median = median(delta);
+ long sd = standardDeviation(delta);
+
+ // log.debug("median = " + median);
+ // log.debug("sd = " + sd);
+
+ long[] tempDeltas = new long[n];
+ int count = 0;
+
+ for (int i = 0; i < n; i++)
+ {
+ if ((delta[i] <= (median + sd)) && (delta[i] >= (median - sd)))
+ {
+ tempDeltas[count] = delta[i];
+ count++;
+ }
+ else
+ {
+ // log.debug("Rejected: " + delta[i]);
+ }
+ }
+
+ System.arraycopy(tempDeltas, 0, delta, 0, count);
+
+ // Estimate the delta as the mean of the remaining deltas.
+ this.delta += mean(delta);
+
+ // Estimate the error as the standard deviation of the remaining deltas.
+ this.epsilon = standardDeviation(delta);
+
+ // log.debug("this.delta = " + this.delta);
+ // log.debug("this.epsilon = " + this.epsilon);
+ }
+
+ /// <summary>
+ /// Performs a single reference clock request cycle and returns the estimated delta relative to the local clock.
+ /// This is computed as the half-latency of the requst cycle, plus the reference clock, minus the local clock.
+ /// </summary>
+ /// <return> The estimated clock delta. </return>
+ ///
+ /// <exception cref="ClockSynchFailureException"> If the reference service is not responding. </exception>
+ protected long ping() throws ClockSynchFailureException
+ {
+ // log.debug("protected long ping(): called");
+
+ try
+ {
+ byte[] buf = new byte[256];
+
+ bool timedOut = false;
+ long start = 0L;
+ long refTime = 0L;
+ long localTime = 0L;
+ long latency = 0L;
+ int failCount = 0;
+
+ // Keep trying the ping until it gets a response, or 10 tries in a row all time out.
+ do
+ {
+ // Start timing the request latency.
+ start = nanoTime();
+
+ // Get the reference time.
+ DatagramPacket packet =
+ new DatagramPacket(buf, buf.length, referenceAddress, UDPClockReference.REFERENCE_PORT);
+ socket.send(packet);
+ packet = new DatagramPacket(buf, buf.length);
+
+ timedOut = false;
+
+ try
+ {
+ socket.receive(packet);
+ }
+ catch (SocketTimeoutException e)
+ {
+ timedOut = true;
+ failCount++;
+
+ continue;
+ }
+
+ ByteBuffer bbuf = ByteBuffer.wrap(packet.getData());
+ refTime = bbuf.getLong();
+
+ // Stop timing the request latency.
+ localTime = nanoTime();
+ latency = localTime - start;
+
+ // log.debug("refTime = " + refTime);
+ // log.debug("localTime = " + localTime);
+ // log.debug("start = " + start);
+ // log.debug("latency = " + latency);
+ // log.debug("delta = " + ((latency / 2) + (refTime - localTime)));
+
+ }
+ while (timedOut && (failCount < 10));
+
+ // Fail completely if the fail count is too high.
+ if (failCount >= 10)
+ {
+ throw new ClockSynchFailureException("Clock reference not responding.", null);
+ }
+
+ // Estimate delta as (ref clock + half-latency) - local clock.
+ return (latency / 2) + (refTime - localTime);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta()
+ {
+ return delta;
+ }
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon()
+ {
+ return epsilon;
+ }
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime()
+ {
+ return System.nanoTime() + delta;
+ }
+
+ /// <summary>
+ /// Computes the median of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The median. </return>
+ public static long median(long[] values)
+ {
+ // log.debug("public static long median(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long median;
+
+ // Order the list of values.
+ long[] orderedValues = new long[values.length];
+ System.arraycopy(values, 0, orderedValues, 0, values.length);
+ Arrays.sort(orderedValues);
+
+ // Check if the median is computed from a pair of middle value.
+ if ((orderedValues.length % 2) == 0)
+ {
+ int middle = orderedValues.length / 2;
+
+ median = (orderedValues[middle] + orderedValues[middle - 1]) / 2;
+ }
+ // The median is computed from a single middle value.
+ else
+ {
+ median = orderedValues[orderedValues.length / 2];
+ }
+
+ // log.debug("median = " + median);
+
+ return median;
+ }
+
+ /// <summary>
+ /// Computes the mean of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The mean. </return>
+ public static long mean(long[] values)
+ {
+ // log.debug("public static long mean(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long total = 0L;
+
+ for (long value : values)
+ {
+ total += value;
+ }
+
+ long mean = total / values.length;
+
+ // log.debug("mean = " + mean);
+
+ return mean;
+ }
+
+ /// <summary>
+ /// Computes the variance of series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The variance of the values. </return>
+ public static long variance(long[] values)
+ {
+ // log.debug("public static long variance(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long mean = mean(values);
+
+ long totalVariance = 0;
+
+ for (long value : values)
+ {
+ long diff = (value - mean);
+ totalVariance += diff/// diff;
+ }
+
+ long variance = totalVariance / values.length;
+
+ // log.debug("variance = " + variance);
+
+ return variance;
+ }
+
+ /// <summary>
+ /// Computes the standard deviation of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The standard deviation. </return>
+ public static long standardDeviation(long[] values)
+ {
+ // log.debug("public static long standardDeviation(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long sd = Double.valueOf(Math.sqrt(variance(values))).longValue();
+
+ // log.debug("sd = " + sd);
+
+ return sd;
+ }
+
+ /// <summary>
+ /// For testing purposes. Supply address of reference clock as arg 1.
+ /// </summary>
+ /// <param name="args"> Address of reference clock as arg 1. </param>
+ public static void main(String[] args)
+ {
+ ParsedProperties options =
+ new ParsedProperties(CommandLineParser.processCommandLine(args,
+ new CommandLineParser(
+ new String[][]
+ {
+ { "1", "Address of clock reference service.", "address", "true" }
+ }), System.getProperties()));
+
+ string address = options.getProperty("1");
+
+ // Create a clock synchronizer.
+ UDPClockSynchronizer clockSyncher = new UDPClockSynchronizer(address);
+
+ // Set up a shutdown hook for it.
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doSynch = false;
+ }
+ }));
+
+ // Repeat the clock synching until the user kills the progam.
+ while (doSynch)
+ {
+ // Perform a clock clockSynch.
+ try
+ {
+ clockSyncher.synch();
+
+ // Print out the clock delta and estimate of the error.
+ System.out.println("Delta = " + clockSyncher.getDelta());
+ System.out.println("Epsilon = " + clockSyncher.getEpsilon());
+
+ try
+ {
+ Thread.sleep(250);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted status and terminate the loop.
+ Thread.currentThread().interrupt();
+ doSynch = false;
+ }
+ }
+ // Terminate if the reference time service is unavailable.
+ catch (ClockSynchFailureException e)
+ {
+ doSynch = false;
+ }
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.*;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.TimingController;
+using uk.co.thebadgerset.junit.extensions.TimingControllerAware;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.Destination;
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.Session;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedcircuit
+{
+ /// <summary>
+ /// DistributedCircuitImpl is a distributed implementation of the test <see cref="Circuit"/>. Many publishers and receivers
+ /// accross multiple machines may be combined to form a single test circuit. The test circuit extracts reports from
+ /// all of its publishers and receivers, and applies its assertions to these reports.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state.
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedue on the circuit.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> There is a short pause after receiving sender reports before asking for receiver reports, because receivers may
+ /// not have finished receiving all their test messages before the report request arrives. This is going to be a
+ /// problem for taking test timings and needs to be eliminiated. Suggested solution: have receiver send back reports
+ /// asynchronously, on test batch size boundaries, and do so automatically rather than having to have the report
+ /// request sent to them. Number each test run, or otherwise uniquely identify it, when a receiver does not get
+ /// any more messages on a test run for more than a timeout, it can assume the test is complete and send a final
+ /// report. On the coordinator end a future will need to be created to wait for all final reports to come in, and
+ /// to register results and timings for the test. This must work in such a way that a new test cycle can be started
+ /// without waiting for the results of the old one to come in.</remarks>
+ ///
+ /// <remarks> Add in setting of timing controller, from timing aware test cases.</remarks>
+ public class DistributedCircuitImpl : Circuit, TimingControllerAware
+ {
+ /// <summary> Used for debugging purposes. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(DistributedCircuitImpl));
+
+ /// <summary> Holds the conversation factory over which to coordinate the test. </summary>
+ protected ConversationFactory conversationFactory;
+
+ /// <summary> Holds the controlSession over which to hold the control conversation. </summary>
+ protected Session controlSession;
+
+ /// <summary> Holds the sender nodes in the test circuit. </summary>
+ protected IList<TestClientDetails> senders;
+
+ /// <summary> Holds the receiver nodes in the test circuit. </summary>
+ protected IList<TestClientDetails> receivers;
+
+ /// <summary> Holds the sender control conversations. </summary>
+ protected ConversationFactory.Conversation[] senderConversation;
+
+ /// <summary> Holds the receiver control conversations. </summary>
+ protected ConversationFactory.Conversation[] receiverConversation;
+
+ /// <summary> Holds the control topics for the senders in the test circuit. </summary>
+ protected Destination[] senderControlTopic;
+
+ /// <summary> Holds the control topics for the receivers in the test circuit. </summary>
+ protected Destination[] receiverControlTopic;
+
+ /// <summary> Holds the number of messages to send per test run. </summary>
+ protected int numMessages;
+
+ /// <summary>
+ /// Holds the timing controller for the circuit. This is used to log test times asynchronously, when reciever nodes
+ /// return their reports after senders have completed a test case.
+ TimingController timingController;
+
+ /// <summary>
+ /// Creates a distributed test circuit on the specified senders and receivers.
+ /// </summary>
+ /// <param name="session"> The controlSession for all control conversations. </param>
+ /// <param name="senders"> The senders. </param>
+ /// <param name="receivers"> The receivers. </param>
+ /// <param name="senderConversation"> A control conversation with the senders. </param>
+ /// <param name="receiverConversation"> A control conversation with the receivers. </param>
+ /// <param name="senderControlTopic"> The senders control topic. </param>
+ /// <param name="receiverControlTopic"> The receivers control topic. </param>
+ protected DistributedCircuitImpl(Session session, IList<TestClientDetails> senders, List<TestClientDetails> receivers,
+ ConversationFactory.Conversation[] senderConversation, ConversationFactory.Conversation[] receiverConversation,
+ Destination[] senderControlTopic, Destination[] receiverControlTopic)
+ {
+ this.controlSession = session;
+ this.senders = senders;
+ this.receivers = receivers;
+ this.senderConversation = senderConversation;
+ this.receiverConversation = receiverConversation;
+ this.senderControlTopic = senderControlTopic;
+ this.receiverControlTopic = receiverControlTopic;
+ }
+
+ /// <summary>
+ /// Creates a distributed test circuit from the specified test parameters, on the senders and receivers
+ /// given.
+ /// </summary>
+ /// <param name="testProps"> The test parameters. </param>
+ /// <param name="senders"> The sender ends in the test circuit. </param>
+ /// <param name="receivers"> The receiver ends in the test circuit. </param>
+ /// <param name="conversationFactory"> A conversation factory for creating the control conversations with senders and receivers. </param>
+ ///
+ /// <return> A connected and ready to start, test circuit. </return>
+ public static Circuit createCircuit(ParsedProperties testProps, IList<TestClientDetails> senders,
+ IList<TestClientDetails> receivers, ConversationFactory conversationFactory)
+ {
+ log.debug("public static Circuit createCircuit(ParsedProperties testProps, IList<TestClientDetails> senders, "
+ + " IList<TestClientDetails> receivers, ConversationFactory conversationFactory)");
+
+ try
+ {
+ Session session = conversationFactory.getSession();
+
+ // Create control conversations with each of the senders.
+ ConversationFactory.Conversation[] senderConversation = new ConversationFactory.Conversation[senders.size()];
+ Destination[] senderControlTopic = new Destination[senders.size()];
+
+ for (int i = 0; i < senders.size(); i++)
+ {
+ TestClientDetails sender = senders.get(i);
+
+ senderControlTopic[i] = session.createTopic(sender.privateControlKey);
+ senderConversation[i] = conversationFactory.startConversation();
+ }
+
+ log.debug("Sender conversations created.");
+
+ // Create control conversations with each of the receivers.
+ ConversationFactory.Conversation[] receiverConversation = new ConversationFactory.Conversation[receivers.size()];
+ Destination[] receiverControlTopic = new Destination[receivers.size()];
+
+ for (int i = 0; i < receivers.size(); i++)
+ {
+ TestClientDetails receiver = receivers.get(i);
+
+ receiverControlTopic[i] = session.createTopic(receiver.privateControlKey);
+ receiverConversation[i] = conversationFactory.startConversation();
+ }
+
+ log.debug("Receiver conversations created.");
+
+ // Assign the sender role to each of the sending test clients.
+ for (int i = 0; i < senders.size(); i++)
+ {
+ TestClientDetails sender = senders.get(i);
+
+ Message assignSender = conversationFactory.getSession().createMessage();
+ TestUtils.setPropertiesOnMessage(assignSender, testProps);
+ assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignSender.setStringProperty("ROLE", "SENDER");
+
+ senderConversation[i].send(senderControlTopic[i], assignSender);
+ }
+
+ log.debug("Sender role assignments sent.");
+
+ // Assign the receivers role to each of the receiving test clients.
+ for (int i = 0; i < receivers.size(); i++)
+ {
+ TestClientDetails receiver = receivers.get(i);
+
+ Message assignReceiver = session.createMessage();
+ TestUtils.setPropertiesOnMessage(assignReceiver, testProps);
+ assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignReceiver.setStringProperty("ROLE", "RECEIVER");
+
+ receiverConversation[i].send(receiverControlTopic[i], assignReceiver);
+ }
+
+ log.debug("Receiver role assignments sent.");
+
+ // Wait for the senders and receivers to confirm their roles.
+ for (int i = 0; i < senders.size(); i++)
+ {
+ senderConversation[i].receive();
+ }
+
+ log.debug("Got all sender role confirmations");
+
+ for (int i = 0; i < receivers.size(); i++)
+ {
+ receiverConversation[i].receive();
+ }
+
+ log.debug("Got all receiver role confirmations");
+
+ // Package everything up as a circuit.
+ return new DistributedCircuitImpl(session, senders, receivers, senderConversation, receiverConversation,
+ senderControlTopic, receiverControlTopic);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("JMSException not handled.");
+ }
+ }
+
+ /// <summary>
+ /// Used by tests cases that can supply a <see cref="uk.co.thebadgerset.junit.extensions.TimingController"/> to set the
+ /// controller on an aware test.
+ /// </summary>
+ /// <param name="controller"> The timing controller. </param>
+ public void setTimingController(TimingController controller)
+ {
+ this.timingController = controller;
+ }
+
+ /// <summary>
+ /// Gets the interface on the publishing end of the circuit.
+ /// </summary>
+ /// <return> The publishing end of the circuit. </return>
+ public Publisher getPublisher()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /// <summary>
+ /// Gets the interface on the receiving end of the circuit.
+ /// </summary>
+ /// <return> The receiving end of the circuit. </return>
+ public Receiver getReceiver()
+ {
+ throw new RuntimeException("Not Implemented.");
+ }
+
+ /// <summary>
+ /// Connects and starts the circuit. After this method is called the circuit is ready to send messages.
+ public void start()
+ {
+ log.debug("public void start(): called");
+
+ try
+ {
+ // Start the test on each of the senders.
+ Message start = controlSession.createMessage();
+ start.setStringProperty("CONTROL_TYPE", "START");
+ start.setIntProperty("MESSAGE_COUNT", numMessages);
+
+ for (int i = 0; i < senders.size(); i++)
+ {
+ senderConversation[i].send(senderControlTopic[i], start);
+ }
+
+ log.debug("All senders told to start their tests.");
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unhandled JMSException.", e);
+ }
+ }
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ /// </summary>
+ /// <remarks> Replace the asynch receiver report thread with a choice of direct or asynch executor, so that asynch
+ /// or synch logging of test timings is optional. Also need to provide an onMessage method that is capable
+ /// of receiving timing reports that receivers will generate during an ongoing test, on the test sample
+ /// size boundaries. The message timing logging code should be factored out as a common method that can
+ /// be called in response to the final report responses, or the onMessage method. Another alternative is
+ /// to abandon the final report request altogether and just use the onMessage method? I think the two
+ /// differ though, as the final report is used to apply assertions, and the ongoing report is just for
+ /// periodic timing results... In which case, maybe there needs to be a way for the onMessage method
+ /// to process just some of the incoming messages, and forward the rest on to the conversion helper, as
+ /// a sort of pre-conversation helper filter? Make conversation expose its onMessage method (it should
+ /// already) and allow another delivery thread to filter the incoming messages to the conversation.</remarks>
+ public void check()
+ {
+ log.debug("public void check(): called");
+
+ try
+ {
+ // Wait for all the test senders to return their reports.
+ for (int i = 0; i < senders.size(); i++)
+ {
+ Message senderReport = senderConversation[i].receive();
+ log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message count: "
+ + senderReport.getIntProperty("MESSAGE_COUNT"));
+ log.debug("Sender " + senderReport.getStringProperty("CLIENT_NAME") + " reports message time: "
+ + senderReport.getLongProperty("TEST_TIME"));
+ }
+
+ log.debug("Got all sender test reports.");
+
+ // Apply sender assertions to pass/fail the tests.
+
+ // Inject a short pause to give the receivers time to finish receiving their test messages.
+ TestUtils.pause(500);
+
+ // Ask the receivers for their reports.
+ Message statusRequest = controlSession.createMessage();
+ statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+ for (int i = 0; i < receivers.size(); i++)
+ {
+ receiverConversation[i].send(receiverControlTopic[i], statusRequest);
+ }
+
+ log.debug("All receiver test reports requested.");
+
+ // Wait for all receiver reports to come in, but do so asynchronously.
+ Runnable gatherAllReceiverReports =
+ new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ // Wait for all the receivers to send their reports.
+ for (int i = 0; i < receivers.size(); i++)
+ {
+ Message receiverReport = receiverConversation[i].receive();
+
+ string clientName = receiverReport.getStringProperty("CLIENT_NAME");
+ int messageCount = receiverReport.getIntProperty("MESSAGE_COUNT");
+ long testTime = receiverReport.getLongProperty("TEST_TIME");
+
+ log.debug("Receiver " + clientName + " reports message count: " + messageCount);
+ log.debug("Receiver " + receiverReport.getStringProperty("CLIENT_NAME")
+ + " reports message time: " + testTime);
+
+ // Apply receiver assertions to pass/fail the tests.
+
+ // Log the test timings on the asynchronous test timing controller.
+ /*try
+ {
+ timingController.completeTest(true, messageCount, testTime);
+ }
+ // The timing controll can throw InterruptedException is the current test is to be
+ // interrupted.
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }*/
+ }
+
+ log.debug("All receiver test reports received.");
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ Thread receiverReportsThread = new Thread(gatherAllReceiverReports);
+ receiverReportsThread.start();
+
+ // return new Message[] { senderReport, receiverReport };
+
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unhandled JMSException.", e);
+ }
+ }
+
+ /// <summary> Closes the circuit. All associated resources are closed. </summary>
+ public void close()
+ {
+ log.debug("public void close(): called");
+
+ // End the current test on all senders and receivers.
+ }
+
+ /// <summary>
+ /// Applies a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> applyAssertions(List<Assertion> assertions)
+ {
+ log.debug("public IList<Assertion> applyAssertions(List<Assertion> assertions = " + assertions + "): called");
+
+ IList<Assertion> failures = new LinkedList<Assertion>();
+
+ for (Assertion assertion : assertions)
+ {
+ if (!assertion.apply())
+ {
+ failures.add(assertion);
+ }
+ }
+
+ return failures;
+ }
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold.
+ /// </summary>
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ ///
+ /// <return> Any assertions that failed. </return>
+ ///
+ /// <remarks> From check onwards needs to be handled as a future. The future must call back onto the test case to
+ /// report results asynchronously.</remarks>
+ public IList<Assertion> test(int numMessages, List<Assertion> assertions)
+ {
+ log.debug("public IList<Assertion> test(int numMessages = " + numMessages + ", List<Assertion> assertions = "
+ + assertions + "): called");
+
+ // Keep the number of messages to send per test run, where the send method can reference it.
+ this.numMessages = numMessages;
+
+ // Start the test running on all sender circuit ends.
+ start();
+
+ // Request status reports to be handed in.
+ check();
+
+ // Assert conditions on the publishing end of the circuit.
+ // Assert conditions on the receiving end of the circuit.
+ IList<Assertion> failures = applyAssertions(assertions);
+
+ // Close the circuit ending the current test case.
+ close();
+
+ // Pass with no failed assertions or fail with a list of failed assertions.
+ return failures;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Publisher;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedcircuit
+{
+ /// <summary>
+ /// DistributedPublisherImpl represents the status of the publishing side of a test circuit. Its main purpose is to
+ /// provide assertions that can be applied to verify the behaviour of a non-local publisher.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide assertion that the publishers received no exceptions.
+ /// <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
+ /// <tr><td> Provide assertion that the publishers received a no route error code on every message.
+ /// </table>
+ /// </summary>
+ public class DistributedPublisherImpl : Publisher
+ {
+ /// <summary>
+ /// Provides an assertion that the publisher encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a no consumers exception on every message.
+ /// </summary>
+ /// <return> An assertion that the publisher got a no consumers exception on every message. </return>
+ public Assertion noConsumersAssertion()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a no rout exception on every message.
+ /// </summary>
+ /// <return> An assertion that the publisher got a no rout exception on every message. </return>
+ public Assertion noRouteAssertion()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Receiver;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedcircuit
+{
+ /// <summary>
+ /// DistributedReceiverImpl represents the status of the receiving side of a test circuit. Its main purpose is to
+ /// provide assertions that can be applied to verify the behaviour of a non-local receiver.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ public class DistributedReceiverImpl : Receiver
+ {
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. <return> An assertion that the receiver got a given exception during the test. </return> </param>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.*;
+using Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClientControlledTest;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using javax.jms.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedcircuit
+{
+ /// <summary>
+ /// A TestClientCircuitEnd is a <see cref="CircuitEnd"/> that may be controlled from a
+ /// <see cref="Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClient"/>, and that forms a single publishing or
+ /// receiving end point in a distributed test <see cref="Apache.Qpid.Integration.Tests.framework.Circuit"/>.
+ ///
+ /// <p/>When operating in the SENDER role, this circuit end is capable of acting as part of the default circuit test
+ /// procedure (described in the class comment for <see cref="Apache.Qpid.Integration.Tests.framework.Circuit"/>). That is, it will
+ /// send the number of test messages required, using the test configuration parameters given in the test invite, and
+ /// return a report on its activities to the circuit controller.
+ ///
+ /// <p/>When operation in the RECEIVER role, this circuit end acts as part of the default circuit test procedure. It will
+ /// receive test messages, on the setup specified in the test configuration parameters, and keep count of the messages
+ /// received, and time taken to receive them. When requested by the circuit controller to provide a report, it will
+ /// return this report of its activities.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <td> <see cref="CircuitEnd"/>, <see cref="LocalCircuitFactory"/>, <see cref="TestUtils"/>
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <td> <see cref="CircuitEnd"/>, <see cref="LocalCircuitFactory"/>, <see cref="TestUtils"/>
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters. <td> <see cref="MessagingTestConfigProperties"/>
+ /// <tr><td> Adapt to assigned roles. <td> <see cref="TestClientControlledTest.Roles"/>
+ /// <tr><td> Perform test case actions. <td> <see cref="MessageMonitor"/>
+ /// <tr><td> Generate test reports. <td> <see cref="MessageMonitor"/>
+ /// </table>
+ /// </summary>
+ public class TestClientCircuitEnd : CircuitEnd, TestClientControlledTest
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestClientCircuitEnd));
+
+ /// <summary> Holds the test parameters. </summary>
+ ParsedProperties testProps;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The connection to send the test messages on. </summary>
+ private Connection connection;
+
+ /// <summary> Holds the circuit end for this test. </summary>
+ CircuitEnd circuitEnd;
+
+ /// <summary>
+ /// Holds a message monitor for this circuit end, either the monitor on the consumer when in RECEIVER more, or
+ /// a monitor updated on every message sent, when acting as a SENDER.
+ MessageMonitor messageMonitor;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ /// <return> The name of the test case that this implements. </return>
+ public string getName()
+ {
+ return "DEFAULT_CIRCUIT_TEST";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ /// <return> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </return>
+ /// </summary>
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public bool acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public bool acceptInvite(Message inviteMessage): called");
+
+ // Populate the test parameters from the invitation.
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ for (Object key : testProps.keySet())
+ {
+ string propName = (String) key;
+
+ // If the test parameters is overridden by the invitation, use it instead.
+ string inviteValue = inviteMessage.getStringProperty(propName);
+
+ if (inviteValue != null)
+ {
+ testProps.setProperty(propName, inviteValue);
+ log.debug("Test invite supplied override to " + propName + " of " + inviteValue);
+ }
+
+ }
+
+ // Accept the invitation.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ /// <param name="role"> The role to be played; sender or receivers. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role, Message assignRoleMessage): called");
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = 1; // assignRoleMessage.getIntProperty("NUM_MESSAGES");
+
+ // Connect using the test parameters.
+ connection = TestUtils.createConnection(testProps);
+
+ // Create a circuit end that matches the assigned role and test parameters.
+ LocalCircuitFactory circuitFactory = new LocalCircuitFactory();
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a message producer if so.
+ case SENDER:
+
+ // Set up the publisher.
+ circuitEnd = circuitFactory.createPublisherCircuitEnd(connection, testProps, 0L);
+
+ // Create a custom message monitor that will be updated on every message sent.
+ messageMonitor = new MessageMonitor();
+
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages.
+ case RECEIVER:
+
+ // Set up the receiver.
+ circuitEnd = circuitFactory.createReceiverCircuitEnd(connection, testProps, 0L);
+
+ // Use the message monitor from the consumer for stats.
+ messageMonitor = getMessageMonitor();
+
+ break;
+ }
+
+ // Reset all messaging stats for the report.
+ messageMonitor.reset();
+
+ connection.start();
+ }
+
+ /// <summary>
+ /// Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ /// </summary>
+ /// <param name="numMessages"> The number of test messages to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ ///
+ /// <remarks> Add round robin on destinations where multiple destinations being used.</remarks>
+ ///
+ /// <remarks> Add rate limiting when rate limit specified on publishers.</remarks>
+ ///
+ /// <remarks> Add Max pending message size protection. The receiver will have to send back some acks once in a while,
+ /// to notify the publisher that its messages are being consumed. This makes the safety valve harder to
+ /// implement than in the single VM case. For example, if the limit is 1000 messages, might want to get back
+ /// an ack every 500, to notify the publisher that it can keep sending. What about pub/sub tests? Will it be
+ /// necessary to wait for an ack from every receiver? This will have the effect of rate limiting to slow
+ /// consumers too.</remarks>
+ ///
+ /// <remarks> Add commits on every commit batch size boundary.</remarks>
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // If in the SENDER role, send the specified number of test messages to the circuit destinations.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = getSession().createMessage();
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ getProducer().send(testMessage);
+
+ // Increment the message count and timings.
+ messageMonitor.onMessage(testMessage);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ /// <param name="session"> The controlSession to create the report message in. </param>
+ /// <return> The report message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions resulting from creating the report are allowed to fall through. </exception>
+ public Message getReport(Session session) throws JMSException
+ {
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+
+ // Add the count of messages sent/received to the report.
+ report.setIntProperty("MESSAGE_COUNT", messageMonitor.getNumMessage());
+
+ // Add the time to send/receive messages to the report.
+ report.setLongProperty("TEST_TIME", messageMonitor.getTime());
+
+ // Add any exceptions detected to the report.
+
+ return report;
+ }
+
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public MessageProducer getProducer()
+ {
+ return circuitEnd.getProducer();
+ }
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public MessageConsumer getConsumer()
+ {
+ return circuitEnd.getConsumer();
+ }
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void send(Message message) throws JMSException
+ {
+ // Send the message on the circuit ends producer.
+ circuitEnd.send(message);
+ }
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public Session getSession()
+ {
+ return circuitEnd.getSession();
+ }
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void close() throws JMSException
+ {
+ // Close the producer and consumer.
+ circuitEnd.close();
+ }
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor getMessageMonitor()
+ {
+ return circuitEnd.getMessageMonitor();
+ }
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor getExceptionMonitor()
+ {
+ return circuitEnd.getExceptionMonitor();
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using junit.framework.Test;
+using junit.framework.TestResult;
+using junit.framework.TestSuite;
+
+using log4net;
+using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase;
+using Apache.Qpid.Integration.Tests.framework.MessagingTestConfigProperties;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.TestUtils;
+using Apache.Qpid.Integration.Tests.framework.clocksynch.UDPClockReference;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.TKTestRunner;
+using uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+using uk.co.thebadgerset.junit.extensions.util.CommandLineParser;
+using uk.co.thebadgerset.junit.extensions.util.MathUtils;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using javax.jms.*;
+
+using java.net.InetAddress;
+using java.util.*;
+using java.util.concurrent.LinkedBlockingQueue;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// <p/>Implements the coordinator client described in the interop testing specification
+ /// (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). This coordinator is built on
+ /// top of the JUnit testing framework.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Find out what test clients are available. <td> <see cref="ConversationFactory"/>
+ /// <tr><td> Decorate available tests to run on all available clients. <td> <see cref="DistributedTestDecorator"/>
+ /// <tr><td> Attach XML test result logger.
+ /// <tr><td> Terminate the interop testing framework.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Should accumulate failures over all tests, and return with success or fail code based on all results. May need
+ /// to write a special TestResult to do this properly. At the moment only the last one used will be tested for
+ /// errors, as the start method creates a fresh one for each test case run.</remarks>
+ public class Coordinator extends TKTestRunner
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(Coordinator));
+
+ /// <summary> Used for reporting to the console. </summary>
+ private static ILog console = LogManager.GetLogger("CONSOLE");
+
+ /// <summary> Defines the possible distributed test engines available to run coordinated test cases with. </summary>
+ public enum TestEngine
+ {
+ /// <summary> Specifies the interop test engine. This tests all available clients in pairs. </summary>
+ INTEROP,
+
+ /// <summary> Specifies the fanout test engine. This sets up one publisher role, and many reciever roles. </summary>
+ FANOUT
+ }
+
+ /// <summary>
+ /// Holds the test context properties that provides the default test parameters, plus command line overrides.
+ /// This is initialized with the default test parameters, to which command line overrides may be applied.
+ protected static ParsedProperties testContextProperties =
+ TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /// <summary> Holds the URL of the broker to coordinate the tests on. </summary>
+ protected string brokerUrl;
+
+ /// <summary> Holds the virtual host to coordinate the tests on. If <tt>null</tt>, then the default virtual host is used. </summary>
+ protected string virtualHost;
+
+ /// <summary> Holds the list of all clients that enlisted, when the compulsory invite was issued. </summary>
+ protected Set<TestClientDetails> enlistedClients = new HashSet<TestClientDetails>();
+
+ /// <summary> Holds the conversation helper for the control conversation. </summary>
+ protected ConversationFactory conversationFactory;
+
+ /// <summary> Holds the connection that the coordinating messages are sent over. </summary>
+ protected Connection connection;
+
+ /// <summary> Holds the path of the directory to output test results too, if one is defined. </summary>
+ protected string reportDir;
+
+ /// <summary> Holds the coordinating test engine type to run the tests through. </summary>
+ protected TestEngine engine;
+
+ /// <summary> Flag that indicates that all test clients should be terminated upon completion of the test cases. </summary>
+ protected bool terminate;
+
+ /// <summary>
+ /// Creates an interop test coordinator on the specified broker and virtual host.
+ /// </summary>
+ /// <param name="repetitions"> The number of times to repeat the test, or test batch size. </param>
+ /// <param name="duration"> The length of time to run the tests for. -1 means no duration has been set. </param>
+ /// <param name="threads"> The concurrency levels to ramp up to. </param>
+ /// <param name="delay"> A delay in milliseconds between test runs. </param>
+ /// <param name="params"> The sets of 'size' parameters to pass to test. </param>
+ /// <param name="testCaseName"> The name of the test case to run. </param>
+ /// <param name="reportDir"> The directory to output the test results to. </param>
+ /// <param name="runName"> The name of the test run; used to name the output file. </param>
+ /// <param name="verbose"> Whether to print comments during test run. </param>
+ /// <param name="brokerUrl"> The URL of the broker to connect to. </param>
+ /// <param name="virtualHost"> The virtual host to run all tests on. Optional, may be <tt>null</tt>. </param>
+ /// <param name="engine"> The distributed test engine type to run the tests with. </param>
+ /// <param name="terminate"> <tt>true</tt> if test client nodes should be terminated at the end of the tests. </param>
+ /// <param name="csv"> <tt>true</tt> if the CSV results listener should be attached. </param>
+ /// <param name="xml"> <tt>true</tt> if the XML results listener should be attached. </param>
+ /// <param name="decoratorFactories"> List of factories for user specified decorators. </param>
+ public Coordinator(Integer repetitions, Long duration, int[] threads, int delay, int[] params, string testCaseName,
+ string reportDir, string runName, bool verbose, string brokerUrl, string virtualHost, TestEngine engine,
+ bool terminate, bool csv, bool xml, IList<TestDecoratorFactory> decoratorFactories)
+ {
+ super(repetitions, duration, threads, delay, params, testCaseName, reportDir, runName, csv, xml, verbose,
+ decoratorFactories);
+
+ log.debug("public Coordinator(Integer repetitions = " + repetitions + " , Long duration = " + duration
+ + ", int[] threads = " + Arrays.ToString(threads) + ", int delay = " + delay + ", int[] params = "
+ + Arrays.ToString(params) + ", string testCaseName = " + testCaseName + ", string reportDir = " + reportDir
+ + ", string runName = " + runName + ", bool verbose = " + verbose + ", string brokerUrl = " + brokerUrl
+ + ", string virtualHost =" + virtualHost + ", TestEngine engine = " + engine + ", bool terminate = "
+ + terminate + ", bool csv = " + csv + ", bool xml = " + xml + "): called");
+
+ // Retain the connection parameters.
+ this.brokerUrl = brokerUrl;
+ this.virtualHost = virtualHost;
+ this.reportDir = reportDir;
+ this.engine = engine;
+ this.terminate = terminate;
+ }
+
+ /// <summary>
+ /// The entry point for the interop test coordinator. This client accepts the following command line arguments:
+ ///
+ /// <p/><table>
+ /// <tr><td> -b <td> The broker URL. <td> Mandatory.
+ /// <tr><td> -h <td> The virtual host. <td> Optional.
+ /// <tr><td> -o <td> The directory to output test results to. <td> Optional.
+ /// <tr><td> -e <td> The type of test distribution engine to use. <td> Optional. One of: interop, fanout.
+ /// <tr><td> ... <td> Free arguments. The distributed test cases to run.
+ /// <td> Mandatory. At least one must be defined.
+ /// <tr><td> name=value <td> Trailing argument define name/value pairs. Added to the test contenxt properties.
+ /// <td> Optional.
+ /// </table>
+ /// </summary>
+ /// <param name="args"> The command line arguments. </param>
+ public static void main(String[] args)
+ {
+ NDC.push("coordinator");
+ log.debug("public static void main(String[] args = " + Arrays.ToString(args) + "): called");
+ console.info("Qpid Distributed Test Coordinator.");
+
+ // Override the default broker url to be localhost:5672.
+ testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
+
+ try
+ {
+ // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+ // and usage then exist if there are errors).
+ // Any options and trailing name=value pairs are also injected into the test context properties object,
+ // to override any defaults that may have been set up.
+ ParsedProperties options =
+ new ParsedProperties(CommandLineParser.processCommandLine(args,
+ new CommandLineParser(
+ new String[][]
+ {
+ { "b", "The broker URL.", "broker", "false" },
+ { "h", "The virtual host to use.", "virtual host", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ {
+ "e", "The test execution engine to use. Default is interop.", "engine", "interop",
+ "^interop$|^fanout$", "true"
+ },
+ { "t", "Terminate test clients on completion of tests.", null, "false" },
+ { "-csv", "Output test results in CSV format.", null, "false" },
+ { "-xml", "Output test results in XML format.", null, "false" },
+ {
+ "-trefaddr", "To specify an alternative to hostname for time singal reference.",
+ "address", "false"
+ },
+ {
+ "c", "The number of tests to run concurrently.", "num", "false",
+ MathUtils.SEQUENCE_REGEXP
+ },
+ { "r", "The number of times to repeat each test.", "num", "false" },
+ {
+ "d", "The length of time to run the tests for.", "duration", "false",
+ MathUtils.DURATION_REGEXP
+ },
+ {
+ "f", "The maximum rate to call the tests at.", "frequency", "false",
+ "^([1-9][0-9]*)/([1-9][0-9]*)$"
+ },
+ { "s", "The size parameter to run tests with.", "size", "false", MathUtils.SEQUENCE_REGEXP },
+ { "v", "Verbose mode.", null, "false" },
+ { "n", "A name for this test run, used to name the output file.", "name", "true" },
+ {
+ "X:decorators", "A list of additional test decorators to wrap the tests in.",
+ "\"class.name[:class.name]*\"", "false"
+ }
+ }), testContextProperties));
+
+ // Extract the command line options.
+ string brokerUrl = options.getProperty("b");
+ string virtualHost = options.getProperty("h");
+ string reportDir = options.getProperty("o");
+ reportDir = (reportDir == null) ? "." : reportDir;
+ string testEngine = options.getProperty("e");
+ TestEngine engine = "fanout".equals(testEngine) ? TestEngine.FANOUT : TestEngine.INTEROP;
+ bool terminate = options.getPropertyAsBoolean("t");
+ bool csvResults = options.getPropertyAsBoolean("-csv");
+ bool xmlResults = options.getPropertyAsBoolean("-xml");
+ string threadsstring = options.getProperty("c");
+ Integer repetitions = options.getPropertyAsInteger("r");
+ string durationstring = options.getProperty("d");
+ string paramsstring = options.getProperty("s");
+ bool verbose = options.getPropertyAsBoolean("v");
+ string testRunName = options.getProperty("n");
+ string decorators = options.getProperty("X:decorators");
+
+ int[] threads = (threadsstring == null) ? null : MathUtils.parseSequence(threadsString);
+ int[] params = (paramsstring == null) ? null : MathUtils.parseSequence(paramsString);
+ Long duration = (durationstring == null) ? null : MathUtils.parseDuration(durationString);
+
+ // If broker or virtual host settings were specified as command line options, override the defaults in the
+ // test context properties with them.
+
+ // Collection all of the test cases to be run.
+ Collection<Class<? extends FrameworkBaseCase>> testCaseClasses =
+ new ArrayList<Class<? extends FrameworkBaseCase>>();
+
+ // Create a list of test decorator factories for use specified decorators to be applied.
+ IList<TestDecoratorFactory> decoratorFactories = parseDecorators(decorators);
+
+ // Scan for available test cases using a classpath scanner.
+ // ClasspathScanner.getMatches(DistributedTestCase.class, "^Test.*", true);
+
+ // Hard code the test classes till the classpath scanner is fixed.
+ // Collections.addAll(testCaseClasses, InteropTestCase1DummyRun.class, InteropTestCase2BasicP2P.class,
+ // InteropTestCase3BasicPubSub.class);
+
+ // Parse all of the free arguments as test cases to run.
+ for (int i = 1; true; i++)
+ {
+ string nextFreeArg = options.getProperty(Integer.ToString(i));
+
+ // Terminate the loop once all free arguments have been consumed.
+ if (nextFreeArg == null)
+ {
+ break;
+ }
+
+ try
+ {
+ Class nextClass = Class.forName(nextFreeArg);
+
+ if (FrameworkBaseCase.class.isAssignableFrom(nextClass))
+ {
+ testCaseClasses.add(nextClass);
+ console.info("Found distributed test case: " + nextFreeArg);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ console.info("Unable to instantiate the test case: " + nextFreeArg + ".");
+ }
+ }
+
+ // Check that some test classes were actually found.
+ if (testCaseClasses.isEmpty())
+ {
+ throw new RuntimeException(
+ "No test cases implementing FrameworkBaseCase were specified on the command line.");
+ }
+
+ // Extract the names of all the test classes, to pass to the start method.
+ int i = 0;
+ String[] testClassNames = new String[testCaseClasses.size()];
+
+ for (Class testClass : testCaseClasses)
+ {
+ testClassNames[i++] = testClass.getName();
+ }
+
+ // Create a coordinator and begin its test procedure.
+ Coordinator coordinator =
+ new Coordinator(repetitions, duration, threads, 0, params, null, reportDir, testRunName, verbose, brokerUrl,
+ virtualHost, engine, terminate, csvResults, xmlResults, decoratorFactories);
+
+ TestResult testResult = coordinator.start(testClassNames);
+
+ // Return different error codes, depending on whether or not there were test failures.
+ if (testResult.failureCount() > 0)
+ {
+ System.exit(FAILURE_EXIT);
+ }
+ else
+ {
+ System.exit(SUCCESS_EXIT);
+ }
+ }
+ catch (Exception e)
+ {
+ log.debug("Top level handler caught execption.", e);
+ console.info(e.getMessage());
+ e.printStackTrace();
+ System.exit(EXCEPTION_EXIT);
+ }
+ }
+
+ /// <summary>
+ /// Starts all of the test classes to be run by this coordinator.
+ /// </summary>
+ /// <param name="testClassNames"> An array of all the coordinating test case implementations. </param>
+ ///
+ /// <return> A JUnit TestResult to run the tests with. </return>
+ ///
+ /// <exception cref="Exception"> Any underlying exceptions are allowed to fall through, and fail the test process. </exception>
+ public TestResult start(String[] testClassNames) throws Exception
+ {
+ log.debug("public TestResult start(String[] testClassNames = " + Arrays.ToString(testClassNames) + ": called");
+
+ // Connect to the broker.
+ connection = TestUtils.createConnection(TestContextProperties.getInstance());
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Destination controlTopic = session.createTopic("iop.control");
+ Destination responseQueue = session.createQueue("coordinator");
+
+ conversationFactory = new ConversationFactory(connection, responseQueue, LinkedBlockingQueue.class);
+ ConversationFactory.Conversation conversation = conversationFactory.startConversation();
+
+ connection.start();
+
+ // Broadcast the compulsory invitation to find out what clients are available to test.
+ Message invite = session.createMessage();
+ invite.setStringProperty("CONTROL_TYPE", "INVITE");
+ invite.setJMSReplyTo(responseQueue);
+
+ conversation.send(controlTopic, invite);
+
+ // Wait for a short time, to give test clients an opportunity to reply to the invitation.
+ Collection<Message> enlists = conversation.receiveAll(0, 500);
+ enlistedClients = extractEnlists(enlists);
+
+ for (TestClientDetails client : enlistedClients)
+ {
+ log.debug("Got enlisted test client: " + client);
+ console.info("Test node " + client.clientName + " available.");
+ }
+
+ // Start the clock reference service running.
+ UDPClockReference clockReference = new UDPClockReference();
+ Thread clockRefThread = new Thread(clockReference);
+ registerShutdownHook(clockReference);
+ clockRefThread.start();
+
+ // Broadcast to all clients to synchronize their clocks against the coordinators clock reference.
+ Message clockSynchRequest = session.createMessage();
+ clockSynchRequest.setStringProperty("CONTROL_TYPE", "CLOCK_SYNCH");
+
+ string localAddress = InetAddress.getByName(InetAddress.getLocalHost().getHostName()).getHostAddress();
+ clockSynchRequest.setStringProperty("ADDRESS", localAddress);
+
+ conversation.send(controlTopic, clockSynchRequest);
+
+ // Run the test in the suite using JUnit.
+ TestResult result = null;
+
+ for (string testClassName : testClassNames)
+ {
+ // Record the current test class, so that the test results can be output to a file incorporating this name.
+ this.currentTestClassName = testClassName;
+
+ result = super.start(new String[] { testClassName });
+ }
+
+ // At this point in time, all tests have completed. Broadcast the shutdown message, if the termination option
+ // was set on the command line.
+ if (terminate)
+ {
+ Message terminate = session.createMessage();
+ terminate.setStringProperty("CONTROL_TYPE", "TERMINATE");
+
+ conversation.send(controlTopic, terminate);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// For a collection of enlist messages, this method pulls out of the client details for the enlisting clients.
+ /// </summary>
+ /// <param name="enlists"> The enlist messages. </param>
+ ///
+ /// <return> A set of enlisting clients, extracted from the enlist messages. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSException is allowed to fall through. </exception>
+ public static Set<TestClientDetails> extractEnlists(Collection<Message> enlists) throws JMSException
+ {
+ log.debug("public static Set<TestClientDetails> extractEnlists(Collection<Message> enlists = " + enlists
+ + "): called");
+
+ Set<TestClientDetails> enlistedClients = new HashSet<TestClientDetails>();
+
+ // Retain the list of all available clients.
+ for (Message enlist : enlists)
+ {
+ TestClientDetails clientDetails = new TestClientDetails();
+ clientDetails.clientName = enlist.getStringProperty("CLIENT_NAME");
+ clientDetails.privateControlKey = enlist.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
+
+ string replyType = enlist.getStringProperty("CONTROL_TYPE");
+
+ if ("ENLIST".equals(replyType))
+ {
+ enlistedClients.add(clientDetails);
+ }
+ else if ("DECLINE".equals(replyType))
+ {
+ log.debug("Test client " + clientDetails.clientName + " declined the invite.");
+ }
+ else
+ {
+ log.warn("Got an unknown reply type, " + replyType + ", to the invite.");
+ }
+ }
+
+ return enlistedClients;
+ }
+
+ /// <summary>
+ /// Runs a test or suite of tests, using the super class implemenation. This method wraps the test to be run
+ /// in any test decorators needed to add in the coordinators ability to invite test clients to participate in
+ /// tests.
+ /// </summary>
+ /// <param name="test"> The test to run. </param>
+ /// <param name="wait"> Undocumented. Nothing in the JUnit javadocs to say what this is for. </param>
+ ///
+ /// <return> The results of the test run. </return>
+ public TestResult doRun(Test test, bool wait)
+ {
+ log.debug("public TestResult doRun(Test \"" + test + "\", bool " + wait + "): called");
+
+ // Wrap all tests in the test suite with WrappedSuiteTestDecorators. This is quite ugly and a bit baffling,
+ // but the reason it is done is because the JUnit implementation of TestDecorator has some bugs in it.
+ WrappedSuiteTestDecorator targetTest = null;
+
+ if (test instanceof TestSuite)
+ {
+ log.debug("targetTest is a TestSuite");
+
+ TestSuite suite = (TestSuite) test;
+
+ int numTests = suite.countTestCases();
+ log.debug("There are " + numTests + " in the suite.");
+
+ for (int i = 0; i < numTests; i++)
+ {
+ Test nextTest = suite.testAt(i);
+ log.debug("suite.testAt(" + i + ") = " + nextTest);
+
+ if (nextTest instanceof FrameworkBaseCase)
+ {
+ log.debug("nextTest is a FrameworkBaseCase");
+ }
+ }
+
+ targetTest = new WrappedSuiteTestDecorator(suite);
+ log.debug("Wrapped with a WrappedSuiteTestDecorator.");
+ }
+
+ // Apply any optional user specified decorators.
+ targetTest = applyOptionalUserDecorators(targetTest);
+
+ // Wrap the tests in a suitable distributed test decorator, to perform the invite/test cycle.
+ targetTest = newTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
+
+ // TestSuite suite = new TestSuite();
+ // suite.addTest(targetTest);
+
+ // Wrap the tests in a scaled test decorator to them them as a 'batch' in one thread.
+ // targetTest = new ScaledTestDecorator(targetTest, new int[] { 1 });
+
+ return super.doRun(targetTest, wait);
+ }
+
+ /// <summary>
+ /// Creates a wrapped test decorator, that is capable of inviting enlisted clients to participate in a specified
+ /// test. This is the test engine that sets up the roles and sequences a distributed test case.
+ /// </summary>
+ /// <param name="targetTest"> The test decorator to wrap. </param>
+ /// <param name="enlistedClients"> The enlisted clients available to run the test. </param>
+ /// <param name="conversationFactory"> The conversation factory used to build conversation helper over the specified connection. </param>
+ /// <param name="connection"> The connection to talk to the enlisted clients over. </param>
+ ///
+ /// <return> An invititing test decorator, that invites all the enlisted clients to participate in tests, in pairs. </return>
+ protected DistributedTestDecorator newTestDecorator(WrappedSuiteTestDecorator targetTest,
+ Set<TestClientDetails> enlistedClients, ConversationFactory conversationFactory, Connection connection)
+ {
+ switch (engine)
+ {
+ case FANOUT:
+ return new FanOutTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
+ case INTEROP:
+ default:
+ return new InteropTestDecorator(targetTest, enlistedClients, conversationFactory, connection);
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using junit.framework.TestResult;
+
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+using javax.jms.Connection;
+using javax.jms.Destination;
+using javax.jms.JMSException;
+using javax.jms.Message;
+
+using java.util.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// DistributedTestDecorator is a base class for writing test decorators that invite test clients to participate in
+ /// distributed test cases. It provides a helper method, <see cref="#signupClients"/>, that broadcasts an invitation and
+ /// returns the set of test clients that are available to particiapte in the test.
+ ///
+ /// <p/>When used to wrap a <see cref="FrameworkBaseCase"/> test, it replaces the default <see cref="CircuitFactory"/> implementations
+ /// with a suitable circuit factory for distributed tests. Concrete implementations can use this to configure the sending
+ /// and receiving roles on the test.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Broadcast test invitations and collect enlists. <td> <see cref="ConversationFactory"/>.
+ /// </table>
+ /// </summary>
+ public abstract class DistributedTestDecorator extends WrappedSuiteTestDecorator
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(DistributedTestDecorator));
+
+ /// <summary> Holds the contact information for all test clients that are available and that may take part in the test. </summary>
+ Set<TestClientDetails> allClients;
+
+ /// <summary> Holds the conversation helper for the control level conversation for coordinating the test through. </summary>
+ ConversationFactory conversationFactory;
+
+ /// <summary> Holds the connection that the control conversation is held over. </summary>
+ Connection connection;
+
+ /// <summary> Holds the underlying test suite that this decorator wraps. </summary>
+ WrappedSuiteTestDecorator testSuite;
+
+ /// <summary> Holds the control topic, on which test invitations are broadcast. </summary>
+ protected Destination controlTopic;
+
+ /// <summary>
+ /// Creates a wrapped suite test decorator from another one.
+ /// </summary>
+ /// <param name="suite"> The test suite. </param>
+ /// <param name="availableClients"> The list of all clients that responded to the compulsory invite. </param>
+ /// <param name="controlConversation"> The conversation helper for the control level, test coordination conversation. </param>
+ /// <param name="controlConnection"> The connection that the coordination messages are sent over. </param>
+ public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+ ConversationFactory controlConversation, Connection controlConnection)
+ {
+ super(suite);
+
+ log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
+
+ testSuite = suite;
+ allClients = availableClients;
+ conversationFactory = controlConversation;
+ connection = controlConnection;
+
+ // Set up the test control topic.
+ try
+ {
+ controlTopic = conversationFactory.getSession().createTopic("iop.control");
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unable to create the coordinating control topic to broadcast test invites on.", e);
+ }
+ }
+
+ /// <summary>
+ /// Should run all of the tests in the wrapped test suite.
+ /// </summary>
+ /// <param name="testResult"> The the results object to monitor the test results with. </param>
+ public abstract void run(TestResult testResult);
+
+ /// <summary>
+ /// Should provide the distributed test sequencer to pass to <see cref="Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase"/>
+ /// tests.
+ /// </summary>
+ /// <return> A distributed test sequencer. </return>
+ public abstract CircuitFactory getTestSequencer();
+
+ /// <summary>
+ /// Broadcasts an invitation to participate in a coordinating test case to find out what clients are available to
+ /// run the test case.
+ /// </summary>
+ /// <param name="coordTest"> The coordinating test case to broadcast an inviate for. </param>
+ ///
+ /// <return> A set of test clients that accepted the invitation. </return>
+ protected Set<TestClientDetails> signupClients(FrameworkBaseCase coordTest)
+ {
+ // Broadcast the invitation to find out what clients are available to test.
+ Set<TestClientDetails> enlists;
+ try
+ {
+ Message invite = conversationFactory.getSession().createMessage();
+
+ ConversationFactory.Conversation conversation = conversationFactory.startConversation();
+
+ invite.setStringProperty("CONTROL_TYPE", "INVITE");
+ invite.setStringProperty("TEST_NAME", coordTest.getTestCaseNameForTestMethod(coordTest.getName()));
+
+ conversation.send(controlTopic, invite);
+
+ // Wait for a short time, to give test clients an opportunity to reply to the invitation.
+ Collection<Message> replies = conversation.receiveAll(allClients.size(), 500);
+ enlists = Coordinator.extractEnlists(replies);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("There was a JMSException during the invite/enlist conversation.", e);
+ }
+
+ return enlists;
+ }
+
+ /// <summary>
+ /// Prints a string summarizing this test decorator, mainly for debugging purposes.
+ /// </summary>
+ /// <return> string representation for debugging purposes. </return>
+ public string ToString()
+ {
+ return "DistributedTestDecorator: [ testSuite = " + testSuite + " ]";
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using junit.framework.Test;
+using junit.framework.TestResult;
+
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.DropInTest;
+using Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+using Apache.Qpid.Integration.Tests.framework.sequencers.FanOutCircuitFactory;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+using javax.jms.Connection;
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.MessageListener;
+
+using System.Collections.Generic.Collection;
+using java.util.Iterator;
+using java.util.Set;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// FanOutTestDecorator is an <see cref="DistributedTestDecorator"/> that runs one test client in the sender role, and the remainder
+ /// in the receivers role. It also has the capability to listen for new test cases joining the test beyond the initial start
+ /// point. This feature can be usefull when experimenting with adding more load, in the form of more test clients, to assess
+ /// its impact on a running test.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Execute coordinated test cases. <td> <see cref="FrameworkBaseCase"/>
+ /// <tr><td> Accept test clients joining a running test.
+ /// </table>
+ /// </summary>
+ public class FanOutTestDecorator extends DistributedTestDecorator : MessageListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(FanOutTestDecorator));
+
+ /// <summary> Holds the currently running test case. </summary>
+ FrameworkBaseCase currentTest = null;
+
+ /// <summary>
+ /// Creates a wrapped suite test decorator from another one.
+ /// </summary>
+ /// <param name="suite"> The test suite. </param>
+ /// <param name="availableClients"> The list of all clients that responded to the compulsory invite. </param>
+ /// <param name="controlConversation"> The conversation helper for the control level, test coordination conversation. </param>
+ /// <param name="controlConnection"> The connection that the coordination messages are sent over. </param>
+ public FanOutTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+ ConversationFactory controlConversation, Connection controlConnection)
+ {
+ super(suite, availableClients, controlConversation, controlConnection);
+
+ log.debug("public DistributedTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> allClients = "
+ + availableClients + ", ConversationHelper controlConversation = " + controlConversation + "): called");
+
+ testSuite = suite;
+ allClients = availableClients;
+ conversationFactory = controlConversation;
+ connection = controlConnection;
+
+ // Sign available clients up to the test.
+ for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase coordTest = (FrameworkBaseCase) test;
+
+ // Get all of the clients able to participate in the test.
+ Set<TestClientDetails> enlists = signupClients(coordTest);
+
+ // Check that there were some clients available.
+ if (enlists.size() == 0)
+ {
+ throw new RuntimeException("No clients to test with");
+ }
+
+ // Create a distributed test circuit factory for the test.
+ CircuitFactory circuitFactory = getTestSequencer();
+
+ // Set up the first client in the sender role, and the remainder in the receivers role.
+ Iterator<TestClientDetails> clients = enlists.iterator();
+ circuitFactory.setSender(clients.next());
+
+ while (clients.hasNext())
+ {
+ // Set the sending and receiving client details on the test case.
+ circuitFactory.setReceiver(clients.next());
+ }
+
+ // Pass down the connection to hold the coordinating conversation over.
+ circuitFactory.setConversationFactory(conversationFactory);
+
+ // If the current test case is a drop-in test, set it up as the currently running test for late joiners to
+ // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed.
+ currentTest = (coordTest instanceof DropInTest) ? coordTest : null;
+
+ // Execute the test case.
+ coordTest.setCircuitFactory(circuitFactory);
+ }
+ }
+
+ /// <summary>
+ /// Broadcasts a test invitation and accepts enlists from participating clients. The wrapped test cases are run
+ /// with one test client in the sender role, and the remaining test clients in the receiving role.
+ ///
+ /// <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime
+ /// exceptions, resulting in the non-completion of the test run.
+ /// </summary>
+ /// <param name="testResult"> The the results object to monitor the test results with. </param>
+ ///
+ /// <remarks> Better error recovery for failure of the invite/enlist conversation could be added.</remarks>
+ public void run(TestResult testResult)
+ {
+ log.debug("public void run(TestResult testResult): called");
+
+ // Listen for late joiners on the control topic.
+ try
+ {
+ conversationFactory.getSession().createConsumer(controlTopic).setMessageListener(this);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unable to set up the message listener on the control topic.", e);
+ }
+
+ // Run all of the test cases in the test suite.
+ /*for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase coordTest = (FrameworkBaseCase) test;
+
+ // Get all of the clients able to participate in the test.
+ Set<TestClientDetails> enlists = signupClients(coordTest);
+
+ // Check that there were some clients available.
+ if (enlists.size() == 0)
+ {
+ throw new RuntimeException("No clients to test with");
+ }
+
+ // Create a distributed test circuit factory for the test.
+ CircuitFactory circuitFactory = getTestSequencer();
+
+ // Set up the first client in the sender role, and the remainder in the receivers role.
+ Iterator<TestClientDetails> clients = enlists.iterator();
+ circuitFactory.setSender(clients.next());
+
+ while (clients.hasNext())
+ {
+ // Set the sending and receiving client details on the test case.
+ circuitFactory.setReceiver(clients.next());
+ }
+
+ // Pass down the connection to hold the coordinating conversation over.
+ circuitFactory.setConversationFactory(conversationFactory);
+
+ // If the current test case is a drop-in test, set it up as the currently running test for late joiners to
+ // add in to. Otherwise the current test field is set to null, to indicate that late joiners are not allowed.
+ currentTest = (coordTest instanceof DropInTest) ? coordTest : null;
+
+ // Execute the test case.
+ coordTest.setCircuitFactory(circuitFactory);
+ }*/
+
+ // Run all of the test cases in the test suite.
+ for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase coordTest = (FrameworkBaseCase) test;
+
+ coordTest.run(testResult);
+
+ currentTest = null;
+ }
+ }
+
+ /// <summary>
+ /// Should provide the distributed test sequencer to pass to <see cref="Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase"/>
+ /// tests.
+ /// </summary>
+ /// <return> A distributed test sequencer. </return>
+ public CircuitFactory getTestSequencer()
+ {
+ return new FanOutCircuitFactory();
+ }
+
+ /// <summary>
+ /// Listens to incoming messages on the control topic. If the messages are 'join' messages, signalling a new
+ /// test client wishing to join the current test, then the new client will be added to the current test in the
+ /// receivers role.
+ /// </summary>
+ /// <param name="message"> The incoming control message. </param>
+ public void onMessage(Message message)
+ {
+ try
+ {
+ // Check if the message is from a test client attempting to join a running test, and join it to the current
+ // test case if so.
+ if (message.getStringProperty("CONTROL_TYPE").equals("JOIN") && (currentTest != null))
+ {
+ ((DropInTest) currentTest).lateJoin(message);
+ }
+ }
+ // There is not a lot can be done with this error, so it is deliberately ignored.
+ catch (JMSException e)
+ {
+ log.debug("Unable to process message:" + message);
+ }
+ }
+
+ /// <summary>
+ /// Prints a string summarizing this test decorator, mainly for debugging purposes.
+ /// </summary>
+ /// <return> string representation for debugging purposes. </return>
+ public string ToString()
+ {
+ return "FanOutTestDecorator: [ testSuite = " + testSuite + " ]";
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using junit.framework.Test;
+using junit.framework.TestResult;
+
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+using Apache.Qpid.Integration.Tests.framework.sequencers.InteropCircuitFactory;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.WrappedSuiteTestDecorator;
+
+using javax.jms.Connection;
+
+using java.util.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// DistributedTestDecorator is a test decorator, written to implement the interop test specification. Given a list
+ /// of enlisted test clients, that are available to run interop tests, this decorator invites them to participate
+ /// in each test in the wrapped test suite. Amongst all the clients that respond to the invite, all pairs are formed,
+ /// and each pairing (in both directions, but excluding the reflexive pairings) is split into a sender and receivers
+ /// role and a test case run between them. Any enlisted combinations that do not accept a test invite are automatically
+ /// failed.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Broadcast test invitations and collect enlists. <td> <see cref="org.apache.qpid.util.ConversationFactory"/>.
+ /// <tr><td> Output test failures for clients unwilling to run the test case. <td> <see cref="Coordinator"/>
+ /// <tr><td> Execute distributed test cases. <td> <see cref="FrameworkBaseCase"/>
+ /// <tr><td> Fail non-participating pairings. <td> <see cref="OptOutTestCase"/>
+ /// </table>
+ /// </summary>
+ public class InteropTestDecorator extends DistributedTestDecorator
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(InteropTestDecorator));
+
+ /// <summary>
+ /// Creates a wrapped suite test decorator from another one.
+ /// </summary>
+ /// <param name="suite"> The test suite. </param>
+ /// <param name="availableClients"> The list of all clients that responded to the compulsory invite. </param>
+ /// <param name="controlConversation"> The conversation helper for the control level, test coordination conversation. </param>
+ /// <param name="controlConnection"> The connection that the coordination messages are sent over. </param>
+ public InteropTestDecorator(WrappedSuiteTestDecorator suite, Set<TestClientDetails> availableClients,
+ ConversationFactory controlConversation, Connection controlConnection)
+ {
+ super(suite, availableClients, controlConversation, controlConnection);
+ }
+
+ /// <summary>
+ /// Broadcasts a test invitation and accetps enlisting from participating clients. The wrapped test case is
+ /// then repeated for every combination of test clients (provided the wrapped test case extends
+ /// <see cref="FrameworkBaseCase"/>.
+ ///
+ /// <p/>Any JMSExceptions during the invite/enlist conversation will be allowed to fall through as runtime exceptions,
+ /// resulting in the non-completion of the test run.
+ /// </summary>
+ /// <remarks> Better error recovery for failure of the invite/enlist conversation could be added.</remarks>
+ /// <param name="testResult"> The the results object to monitor the test results with. </param>
+ public void run(TestResult testResult)
+ {
+ log.debug("public void run(TestResult testResult): called");
+
+ Collection<Test> tests = testSuite.getAllUnderlyingTests();
+
+ for (Test test : getAllUnderlyingTests())
+ {
+ FrameworkBaseCase coordTest = (FrameworkBaseCase) test;
+
+ // Broadcast the invitation to find out what clients are available to test.
+ Set<TestClientDetails> enlists = signupClients(coordTest);
+
+ // Compare the list of willing clients to the list of all available.
+ Set<TestClientDetails> optOuts = new HashSet<TestClientDetails>(allClients);
+ optOuts.removeAll(enlists);
+
+ // Output test failures for clients that will not particpate in the test.
+ Set<List<TestClientDetails>> failPairs = allPairs(optOuts, allClients);
+
+ for (List<TestClientDetails> failPair : failPairs)
+ {
+ // Create a distributed test circuit factory for the test.
+ CircuitFactory circuitFactory = getTestSequencer();
+
+ // Create an automatic failure test for the opted out test pair.
+ FrameworkBaseCase failTest = new OptOutTestCase("testOptOut");
+ circuitFactory.setSender(failPair.get(0));
+ circuitFactory.setReceiver(failPair.get(1));
+ failTest.setCircuitFactory(circuitFactory);
+
+ failTest.run(testResult);
+ }
+
+ // Loop over all combinations of clients, willing to run the test.
+ Set<List<TestClientDetails>> enlistedPairs = allPairs(enlists, enlists);
+
+ for (List<TestClientDetails> enlistedPair : enlistedPairs)
+ {
+ // Create a distributed test circuit factory for the test.
+ CircuitFactory circuitFactory = getTestSequencer();
+
+ // Set the sending and receiving client details on the test circuitFactory.
+ circuitFactory.setSender(enlistedPair.get(0));
+ circuitFactory.setReceiver(enlistedPair.get(1));
+
+ // Pass down the connection to hold the coordination conversation over.
+ circuitFactory.setConversationFactory(conversationFactory);
+
+ // Execute the test case.
+ coordTest.setCircuitFactory(circuitFactory);
+ coordTest.run(testResult);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Should provide the distributed test sequencer to pass to <see cref="Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase"/>
+ /// tests.
+ /// </summary>
+ /// <return> A distributed test sequencer. </return>
+ public CircuitFactory getTestSequencer()
+ {
+ return new InteropCircuitFactory();
+ }
+
+ /// <summary>
+ /// Produces all pairs of combinations of elements from two sets. The ordering of the elements in the pair is
+ /// important, that is the pair <l, r> is distinct from <r, l>; both pairs are generated. For any element, i, in
+ /// both the left and right sets, the reflexive pair <i, i> is not generated.
+ /// </summary>
+ /// <param name="left"> The left set. </param>
+ /// <param name="right"> The right set. </param>
+ /// @param <E> The type of the content of the pairs.
+ /// </summary>
+ /// <return> All pairs formed from the permutations of all elements of the left and right sets. </return>
+ private <E> Set<List<E>> allPairs(Set<E> left, Set<E> right)
+ {
+ log.debug("private <E> Set<List<E>> allPairs(Set<E> left = " + left + ", Set<E> right = " + right + "): called");
+
+ Set<List<E>> results = new HashSet<List<E>>();
+
+ // Form all pairs from left to right.
+ // Form all pairs from right to left.
+ for (E le : left)
+ {
+ for (E re : right)
+ {
+ if (!le.equals(re))
+ {
+ results.add(new Pair<E>(le, re));
+ results.add(new Pair<E>(re, le));
+ }
+ }
+ }
+
+ log.debug("results = " + results);
+
+ return results;
+ }
+
+ /// <summary> A simple implementation of a pair, using a list. </summary>
+ private class Pair<T> extends ArrayList<T>
+ {
+ /// <summary>
+ /// Creates a new pair of elements.
+ /// </summary>
+ /// <param name="first"> The first element. </param>
+ /// <param name="second"> The second element. </param>
+ public Pair(T first, T second)
+ {
+ super();
+ super.add(first);
+ super.add(second);
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+using Apache.Qpid.Integration.Tests.framework.FrameworkBaseCase;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// An OptOutTestCase is a test case that automatically fails. It is used when a list of test clients has been generated
+ /// from a compulsory invite, but only some of those clients have responded to a specific test case invite. The clients
+ /// that did not respond, may automatically be given a fail for some tests.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Fail the test with a suitable reason.
+ /// </table>
+ /// </summary>
+ public class OptOutTestCase extends FrameworkBaseCase
+ {
+ /// <summary>
+ /// Creates a new coordinating test case with the specified name.
+ /// </summary>
+ /// <param name="name"> The test case name. </param>
+ public OptOutTestCase(string name)
+ {
+ super(name);
+ }
+
+ /// <summary> Generates an appropriate test failure assertion. </summary>
+ public void testOptOut()
+ {
+ CircuitFactory circuitFactory = getCircuitFactory();
+
+ fail("One of " + circuitFactory.getSender() + " and " + getCircuitFactory().getReceivers()
+ + " opted out of the test.");
+ }
+
+ /// <summary>
+ /// Should provide a translation from the junit method name of a test to its test case name as defined in the
+ /// interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ /// "TC2_BasicP2P".
+ /// </summary>
+ /// <param name="methodName"> The name of the JUnit test method. </param>
+ /// <return> The name of the corresponding interop test case. </return>
+ public string getTestCaseNameForTestMethod(string methodName)
+ {
+ return "OptOutTest";
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.MessagingTestConfigProperties;
+using Apache.Qpid.Integration.Tests.framework.TestUtils;
+using Apache.Qpid.Integration.Tests.framework.clocksynch.ClockSynchThread;
+using Apache.Qpid.Integration.Tests.framework.clocksynch.UDPClockSynchronizer;
+using org.apache.qpid.util.ReflectionUtils;
+using org.apache.qpid.util.ReflectionUtilsException;
+
+using uk.co.thebadgerset.junit.extensions.SleepThrottle;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using javax.jms.*;
+
+using java.util.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// Implements a test client as described in the interop testing spec
+ /// (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
+ /// reacts to control message sequences send by the test <see cref="Coordinator"/>.
+ ///
+ /// <p/><table><caption>Messages Handled by TestClient</caption>
+ /// <tr><th> Message <th> Action
+ /// <tr><td> Invite(compulsory) <td> Reply with Enlist.
+ /// <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
+ /// <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches an enlisted test. Keep test parameters.
+ /// <tr><td> Start <td> Send test messages defined by test parameters. Send report on messages sent.
+ /// <tr><td> Status Request <td> Send report on messages received.
+ /// <tr><td> Terminate <td> Terminate the test client.
+ /// <tr><td> ClockSynch <td> Synch clock against the supplied UDP address.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Handle all incoming control messages. <td> <see cref="TestClientControlledTest"/>
+ /// <tr><td> Configure and look up test cases by name. <td> <see cref="TestClientControlledTest"/>
+ /// </table>
+ /// </summary>
+ public class TestClient : MessageListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestClient));
+
+ /// <summary> Used for reporting to the console. </summary>
+ private static ILog console = LogManager.GetLogger("CONSOLE");
+
+ /// <summary> Holds the default identifying name of the test client. </summary>
+ public static final string CLIENT_NAME = "java";
+
+ /// <summary> Holds the URL of the broker to run the tests on. </summary>
+ public static string brokerUrl;
+
+ /// <summary> Holds the virtual host to run the tests on. If <tt>null</tt>, then the default virtual host is used. </summary>
+ public static string virtualHost;
+
+ /// <summary>
+ /// Holds the test context properties that provides the default test parameters, plus command line overrides.
+ /// This is initialized with the default test parameters, to which command line overrides may be applied.
+ /// </summary>
+ public static ParsedProperties testContextProperties =
+ TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /// <summary> Holds all the test cases loaded from the classpath. </summary>
+ Map<String, TestClientControlledTest> testCases = new HashMap<String, TestClientControlledTest>();
+
+ /// <summary> Holds the test case currently being run by this client. </summary>
+ protected TestClientControlledTest currentTestCase;
+
+ /// <summary> Holds the connection to the broker that the test is being coordinated on. </summary>
+ protected Connection connection;
+
+ /// <summary> Holds the message producer to hold the test coordination over. </summary>
+ protected MessageProducer producer;
+
+ /// <summary> Holds the JMS controlSession for the test coordination. </summary>
+ protected Session session;
+
+ /// <summary> Holds the name of this client, with a default value. </summary>
+ protected string clientName = CLIENT_NAME;
+
+ /// <summary> This flag indicates that the test client should attempt to join the currently running test case on start up. </summary>
+ protected bool join;
+
+ /// <summary> Holds the clock synchronizer for the test node. </summary>
+ ClockSynchThread clockSynchThread;
+
+ /// <summary>
+ /// Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client
+ /// identifying name.
+ /// </summary>
+ /// <param name="pBrokerUrl"> The url of the broker to connect to. </param>
+ /// <param name="pVirtualHost"> The virtual host to conect to. </param>
+ /// <param name="clientName"> The client name to use. </param>
+ /// <param name="join"> Flag to indicate that this client should attempt to join running tests. </param>
+ public TestClient(string pBrokerUrl, string pVirtualHost, string clientName, bool join)
+ {
+ log.debug("public TestClient(string pBrokerUrl = " + pBrokerUrl + ", string pVirtualHost = " + pVirtualHost
+ + ", string clientName = " + clientName + ", bool join = " + join + "): called");
+
+ // Retain the connection parameters.
+ brokerUrl = pBrokerUrl;
+ virtualHost = pVirtualHost;
+ this.clientName = clientName;
+ this.join = join;
+ }
+
+ /// <summary>
+ /// The entry point for the interop test coordinator. This client accepts the following command line arguments:
+ ///
+ /// <p/><table>
+ /// <tr><td> -b <td> The broker URL. <td> Optional.
+ /// <tr><td> -h <td> The virtual host. <td> Optional.
+ /// <tr><td> -n <td> The test client name. <td> Optional.
+ /// <tr><td> name=value <td> Trailing argument define name/value pairs. Added to system properties. <td> Optional.
+ /// </table>
+ /// </summary>
+ /// <param name="args"> The command line arguments. </param>
+ public static void main(String[] args)
+ {
+ log.debug("public static void main(String[] args = " + Arrays.ToString(args) + "): called");
+ console.info("Qpid Distributed Test Client.");
+
+ // Override the default broker url to be localhost:5672.
+ testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
+
+ // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+ // and usage then exist if there are errors).
+ // Any options and trailing name=value pairs are also injected into the test context properties object,
+ // to override any defaults that may have been set up.
+ ParsedProperties options =
+ new ParsedProperties(uk.co.thebadgerset.junit.extensions.util.CommandLineParser.processCommandLine(args,
+ new uk.co.thebadgerset.junit.extensions.util.CommandLineParser(
+ new String[][]
+ {
+ { "b", "The broker URL.", "broker", "false" },
+ { "h", "The virtual host to use.", "virtual host", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ { "n", "The name of the test client.", "name", "false" },
+ { "j", "Join this test client to running test.", "false" }
+ }), testContextProperties));
+
+ // Extract the command line options.
+ string brokerUrl = options.getProperty("b");
+ string virtualHost = options.getProperty("h");
+ string clientName = options.getProperty("n");
+ clientName = (clientName == null) ? CLIENT_NAME : clientName;
+ bool join = options.getPropertyAsBoolean("j");
+
+ // To distinguish logging output set up an NDC on the client name.
+ NDC.push(clientName);
+
+ // Create a test client and start it running.
+ TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join);
+
+ // Use a class path scanner to find all the interop test case implementations.
+ // Hard code the test classes till the classpath scanner is fixed.
+ Collection<Class<? extends TestClientControlledTest>> testCaseClasses =
+ new ArrayList<Class<? extends TestClientControlledTest>>();
+ // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true);
+ testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun",
+ "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P",
+ "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub",
+ "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize",
+ "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize",
+ "Apache.Qpid.Integration.Tests.framework.distributedcircuit.TestClientCircuitEnd"));
+
+ try
+ {
+ client.start(testCaseClasses);
+ }
+ catch (Exception e)
+ {
+ log.error("The test client was unable to start.", e);
+ console.info(e.getMessage());
+ System.exit(1);
+ }
+ }
+
+ /// <summary>
+ /// Parses a list of class names, and loads them if they are available on the class path.
+ /// </summary>
+ /// <param name="classNames"> The names of the classes to load. </param>
+ ///
+ /// <return> A list of the loaded test case classes. </return>
+ public static IList<Class<? extends TestClientControlledTest>> loadTestCases(String... classNames)
+ {
+ IList<Class<? extends TestClientControlledTest>> testCases =
+ new LinkedList<Class<? extends TestClientControlledTest>>();
+
+ for (string className : classNames)
+ {
+ try
+ {
+ Class<?> cls = ReflectionUtils.forName(className);
+ testCases.add((Class<? extends TestClientControlledTest>) cls);
+ }
+ catch (ReflectionUtilsException e)
+ {
+ // Ignore, class could not be found, so test not available.
+ console.warn("Requested class " + className + " cannot be found, ignoring it.");
+ }
+ catch (ClassCastException e)
+ {
+ // Ignore, class was not of correct type to be a test case.
+ console.warn("Requested class " + className + " is not an instance of TestClientControlledTest.");
+ }
+ }
+
+ return testCases;
+ }
+
+ /// <summary>
+ /// Starts the interop test client running. This causes it to start listening for incoming test invites.
+ /// </summary>
+ /// <param name="testCaseClasses"> The classes of the available test cases. The test case names from these are used to </param>
+ /// matchin incoming test invites against.
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through. </exception>
+ protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses) throws JMSException
+ {
+ log.debug("protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses = "
+ + testCaseClasses + "): called");
+
+ // Create all the test case implementations and index them by the test names.
+ for (Class<? extends TestClientControlledTest> nextClass : testCaseClasses)
+ {
+ try
+ {
+ TestClientControlledTest testCase = nextClass.newInstance();
+ testCases.put(testCase.getName(), testCase);
+ }
+ catch (InstantiationException e)
+ {
+ log.warn("Could not instantiate test case class: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ catch (IllegalAccessException e)
+ {
+ log.warn("Could not instantiate test case class due to illegal access: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ }
+
+ // Open a connection to communicate with the coordinator on.
+ connection = TestUtils.createConnection(testContextProperties);
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Set this up to listen for control messages.
+ Topic privateControlTopic = session.createTopic("iop.control." + clientName);
+ MessageConsumer consumer = session.createConsumer(privateControlTopic);
+ consumer.setMessageListener(this);
+
+ Topic controlTopic = session.createTopic("iop.control");
+ MessageConsumer consumer2 = session.createConsumer(controlTopic);
+ consumer2.setMessageListener(this);
+
+ // Create a producer to send replies with.
+ producer = session.createProducer(null);
+
+ // If the join flag was set, then broadcast a join message to notify the coordinator that a new test client
+ // is available to join the current test case, if it supports it. This message may be ignored, or it may result
+ // in this test client receiving a test invite.
+ if (join)
+ {
+ Message joinMessage = session.createMessage();
+
+ joinMessage.setStringProperty("CONTROL_TYPE", "JOIN");
+ joinMessage.setStringProperty("CLIENT_NAME", clientName);
+ joinMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ producer.send(controlTopic, joinMessage);
+ }
+
+ // Start listening for incoming control messages.
+ connection.start();
+ }
+
+ /// <summary>
+ /// Handles all incoming control messages.
+ /// </summary>
+ /// <param name="message"> The incoming message. </param>
+ public void onMessage(Message message)
+ {
+ NDC.push(clientName);
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ try
+ {
+ string controlType = message.getStringProperty("CONTROL_TYPE");
+ string testName = message.getStringProperty("TEST_NAME");
+
+ log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'");
+
+ // Check if the message is a test invite.
+ if ("INVITE".equals(controlType))
+ {
+ // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites
+ // for which test cases exist.
+ bool enlist = false;
+
+ if (testName != null)
+ {
+ log.debug("Got an invite to test: " + testName);
+
+ // Check if the requested test case is available.
+ TestClientControlledTest testCase = testCases.get(testName);
+
+ if (testCase != null)
+ {
+ log.debug("Found implementing class for test '" + testName + "', enlisting for it.");
+
+ // Check if the test case will accept the invitation.
+ enlist = testCase.acceptInvite(message);
+
+ log.debug("The test case "
+ + (enlist ? " accepted the invite, enlisting for it."
+ : " did not accept the invite, not enlisting."));
+
+ // Make the requested test case the current test case.
+ currentTestCase = testCase;
+ }
+ else
+ {
+ log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
+ }
+ }
+ else
+ {
+ log.debug("Got a compulsory invite, enlisting for it.");
+
+ enlist = true;
+ }
+
+ if (enlist)
+ {
+ // Reply with the client name in an Enlist message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending enlist message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ else
+ {
+ // Reply with the client name in an Decline message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending decline message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ }
+ else if ("ASSIGN_ROLE".equals(controlType))
+ {
+ // Assign the role to the current test case.
+ string roleName = message.getStringProperty("ROLE");
+
+ log.debug("Got a role assignment to role: " + roleName);
+
+ TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName);
+
+ currentTestCase.assignRole(role, message);
+
+ // Reply by accepting the role in an Accept Role message.
+ Message acceptRoleMessage = session.createMessage();
+ acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName);
+ acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE");
+ acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending accept role message '" + acceptRoleMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), acceptRoleMessage);
+ }
+ else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType))
+ {
+ if ("START".equals(controlType))
+ {
+ log.debug("Got a start notification.");
+
+ // Extract the number of test messages to send from the start notification.
+ int numMessages;
+
+ try
+ {
+ numMessages = message.getIntProperty("MESSAGE_COUNT");
+ }
+ catch (NumberFormatException e)
+ {
+ // If the number of messages is not specified, use the default of one.
+ numMessages = 1;
+ }
+
+ // Start the current test case.
+ currentTestCase.start(numMessages);
+ }
+ else
+ {
+ log.debug("Got a status request.");
+ }
+
+ // Generate the report from the test case and reply with it as a Report message.
+ Message reportMessage = currentTestCase.getReport(session);
+ reportMessage.setStringProperty("CLIENT_NAME", clientName);
+ reportMessage.setStringProperty("CONTROL_TYPE", "REPORT");
+ reportMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending report message '" + reportMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), reportMessage);
+ }
+ else if ("TERMINATE".equals(controlType))
+ {
+ console.info("Received termination instruction from coordinator.");
+
+ // Is a cleaner shutdown needed?
+ connection.close();
+ System.exit(0);
+ }
+ else if ("CLOCK_SYNCH".equals(controlType))
+ {
+ log.debug("Received clock synch command.");
+ string address = message.getStringProperty("ADDRESS");
+
+ log.debug("address = " + address);
+
+ // Re-create (if necessary) and start the clock synch thread to synch the clock every ten seconds.
+ if (clockSynchThread != null)
+ {
+ clockSynchThread.terminate();
+ }
+
+ SleepThrottle throttle = new SleepThrottle();
+ throttle.setRate(0.1f);
+
+ clockSynchThread = new ClockSynchThread(new UDPClockSynchronizer(address), throttle);
+ clockSynchThread.start();
+ }
+ else
+ {
+ // Log a warning about this but otherwise ignore it.
+ log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message);
+ }
+ }
+ catch (JMSException e)
+ {
+ // Log a warning about this, but otherwise ignore it.
+ log.warn("Got JMSException whilst handling message: " + message, e);
+ }
+ // Log any runtimes that fall through this message handler. These are fatal errors for the test client.
+ catch (RuntimeException e)
+ {
+ log.error("The test client message handler got an unhandled exception: ", e);
+ console.info("The message handler got an unhandled exception, terminating the test client.");
+ System.exit(1);
+ }
+ finally
+ {
+ NDC.pop();
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.MessageListener;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// TestClientControlledTest provides an interface that classes implementing test cases to run on a <see cref="TestClient"/>
+ /// node can use. Implementations must be Java beans, that is, to provide a default constructor and to implement the
+ /// <see cref="#getName"/> method.
+ ///
+ /// <p/>The methods specified in this interface are called when the <see cref="TestClient"/> receives control instructions to
+ /// apply to the test. There are control instructions to present the test case with the test invite, so that it may
+ /// choose whether or not to participate in the test, assign the test to play the sender or receiver role, start the
+ /// test and obtain the test status report.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public interface TestClientControlledTest
+ {
+ /// <summary> Defines the possible test case roles that an interop test case can take on. </summary>
+ public enum Roles
+ {
+ /// <summary> Specifies the sender role. </summary>
+ SENDER,
+
+ /// <summary> Specifies the receivers role. </summary>
+ RECEIVER
+ }
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ /// <return> The name of the test case that this implements. </return>
+ public string getName();
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <return> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public bool acceptInvite(Message inviteMessage) throws JMSException;
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ /// <param name="role"> The role to be played; sender or receivers. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException;
+
+ /// <summary>
+ /// Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ /// </summary>
+ /// <param name="numMessages"> The number of test messages to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void start(int numMessages) throws JMSException;
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ /// <param name="session"> The controlSession to create the report message in. </param>
+ ///
+ /// <return> The report message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions resulting from creating the report are allowed to fall through. </exception>
+ public Message getReport(Session session) throws JMSException;
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using javax.jms.JMSException;
+using javax.jms.Message;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A DropIn test is a test case that can accept late joining test clients into a running test. This can be usefull,
+ /// for interactive experimentation.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Accept late joining test clients.
+ /// </table>
+ /// </summary>
+ public interface DropInTest
+ {
+ /// <summary>
+ /// Should accept a late joining client into a running test case. The client will be enlisted with a control message
+ /// with the 'CONTROL_TYPE' field set to the value 'LATEJOIN'. It should also provide values for the fields:
+ ///
+ /// <p/><table>
+ /// <tr><td> CLIENT_NAME <td> A unique name for the new client.
+ /// <tr><td> CLIENT_PRIVATE_CONTROL_KEY <td> The key for the route on which the client receives its control messages.
+ /// </table>
+ /// </summary>
+ /// <param name="message"> The late joiners join message. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMS Exception are allowed to fall through, indicating that the join failed. </exception>
+ public void lateJoin(Message message) throws JMSException;
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using javax.jms.ExceptionListener;
+using javax.jms.JMSException;
+
+using java.io.PrintWriter;
+using java.io.StringWriter;
+using java.util.ArrayList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// An exception monitor, listens for JMS exception on a connection or consumer. It record all exceptions that it receives
+ /// and provides methods to test the number and type of exceptions received.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Record all exceptions received.
+ /// </table>
+ /// </summary>
+ public class ExceptionMonitor : ExceptionListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(ExceptionMonitor));
+
+ /// <summary> Holds the received exceptions. </summary>
+ IList<Exception> exceptions = new ArrayList<Exception>();
+
+ /// <summary>
+ /// Receives incoming exceptions.
+ /// </summary>
+ /// <param name="e"> The exception to record. </param>
+ public synchronized void onException(JMSException e)
+ {
+ log.debug("public void onException(JMSException e): called", e);
+
+ exceptions.add(e);
+ }
+
+ /// <summary>
+ /// Checks that no exceptions have been received.
+ /// </summary>
+ /// <return> <tt>true</tt> if no exceptions have been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertNoExceptions()
+ {
+ return exceptions.isEmpty();
+ }
+
+ /// <summary>
+ /// Checks that exactly one exception has been received.
+ /// </summary>
+ /// <return> <tt>true</tt> if exactly one exception been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertOneJMSException()
+ {
+ return exceptions.size() == 1;
+ }
+
+ /// <summary>
+ /// Checks that exactly one exception, with a linked cause of the specified type, has been received.
+ /// </summary>
+ /// <param name="aClass"> The type of the linked cause. </param>
+ ///
+ /// <return> <tt>true</tt> if exactly one exception, with a linked cause of the specified type, been received, </return>
+ /// <tt>false</tt> otherwise.
+ public synchronized bool assertOneJMSExceptionWithLinkedCause(Class aClass)
+ {
+ if (exceptions.size() == 1)
+ {
+ Exception e = exceptions.get(0);
+
+ if (e instanceof JMSException)
+ {
+ JMSException jmse = (JMSException) e;
+
+ Exception linkedCause = jmse.getLinkedException();
+
+ if ((linkedCause != null) && aClass.isInstance(linkedCause))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Checks that at least one exception of the the specified type, has been received.
+ /// </summary>
+ /// <param name="exceptionClass"> The type of the exception. </param>
+ ///
+ /// <return> <tt>true</tt> if at least one exception of the specified type has been received, <tt>false</tt> otherwise. </return>
+ public synchronized bool assertExceptionOfType(Class exceptionClass)
+ {
+ // Start by assuming that the exception has no been received.
+ bool passed = false;
+
+ // Scan all the exceptions for a match.
+ for (Exception e : exceptions)
+ {
+ if (exceptionClass.isInstance(e))
+ {
+ passed = true;
+
+ break;
+ }
+ }
+
+ return passed;
+ }
+
+ /// <summary>
+ /// Reports the number of exceptions held by this monitor.
+ /// </summary>
+ /// <return> The number of exceptions held by this monitor. </return>
+ public synchronized int size()
+ {
+ return exceptions.size();
+ }
+
+ /// <summary>
+ /// Clears the record of received exceptions.
+ /// </summary>
+ public synchronized void reset()
+ {
+ exceptions = new ArrayList<Exception>();
+ }
+
+ /// <summary>
+ /// Provides a dump of the stack traces of all exceptions that this exception monitor was notified of. Mainly
+ /// use for debugging/test failure reporting purposes.
+ /// </summary>
+ /// <return> A string containing a dump of the stack traces of all exceptions. </return>
+ public synchronized string ToString()
+ {
+ string result = "ExceptionMonitor: holds " + exceptions.size() + " exceptions.\n\n";
+
+ for (Exception ex : exceptions)
+ {
+ result += getStackTrace(ex) + "\n";
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Prints an exception stack trace into a string.
+ /// </summary>
+ /// <param name="t"> The throwable to get the stack trace from. </param>
+ ///
+ /// <return> A string containing the throwables stack trace. </return>
+ public static string getStackTrace(Throwable t)
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ t.printStackTrace(pw);
+ pw.flush();
+ sw.flush();
+
+ return sw.ToString();
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.BrokerLifecycleAware;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+
+using uk.co.thebadgerset.junit.extensions.AsymptoticTestCase;
+using uk.co.thebadgerset.junit.extensions.SetupTaskAware;
+using uk.co.thebadgerset.junit.extensions.SetupTaskHandler;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using java.util.ArrayList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// FrameworkBaseCase provides a starting point for writing test cases against the test framework. Its main purpose is
+ /// to provide some convenience methods for testing.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create and clean up in-vm brokers on every test case.
+ /// <tr><td> Produce lists of assertions from assertion creation calls.
+ /// <tr><td> Produce JUnit failures from assertion failures.
+ /// <tr><td> Convert failed assertions to error messages.
+ /// </table>
+ /// </summary>
+ public class FrameworkBaseCase extends AsymptoticTestCase : FrameworkTestContext, SetupTaskAware,
+ BrokerLifecycleAware
+ {
+ /// <summary> Used for debugging purposes. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(FrameworkBaseCase));
+
+ /// <summary> Holds the test sequencer to create and run test circuits with. </summary>
+ protected CircuitFactory circuitFactory = new LocalCircuitFactory();
+
+ /// <summary> Used to read the tests configurable properties through. </summary>
+ protected ParsedProperties testProps;
+
+ /// <summary> A default setup task processor to delegate setup tasks to. </summary>
+ protected SetupTaskHandler taskHandler = new SetupTaskHandler();
+
+ /// <summary> Flag used to track whether the test is in-vm or not. </summary>
+ protected bool isUsingInVM;
+
+ /// <summary> Holds the failure mechanism. </summary>
+ protected CauseFailure failureMechanism = new CauseFailureUserPrompt();
+
+ /// <summary>
+ /// Creates a new test case with the specified name.
+ /// </summary>
+ /// <param name="name"> The test case name. </param>
+ public FrameworkBaseCase(string name)
+ {
+ super(name);
+ }
+
+ /// <summary>
+ /// Returns the test case sequencer that provides test circuit, and test sequence implementations. The sequencer
+ /// that this base case returns by default is suitable for running a test circuit with both circuit ends colocated
+ /// on the same JVM.
+ /// </summary>
+ /// <return> The test case sequencer. </return>
+ protected CircuitFactory getCircuitFactory()
+ {
+ return circuitFactory;
+ }
+
+ /// <summary>
+ /// Overrides the default test circuit factory. Test decorators can use this to supply distributed test sequencers or
+ /// other test circuit factory specializations.
+ /// </summary>
+ /// <param name="circuitFactory"> The new test circuit factory. </param>
+ public void setCircuitFactory(CircuitFactory circuitFactory)
+ {
+ this.circuitFactory = circuitFactory;
+ }
+
+ /// <summary>
+ /// Reports the current test case name.
+ /// </summary>
+ /// <return> The current test case name. </return>
+ public TestCaseVector getTestCaseVector()
+ {
+ return new TestCaseVector(this.getName(), 0);
+ }
+
+ /// <summary>
+ /// Reports the current test case parameters.
+ /// </summary>
+ /// <return> The current test case parameters. </return>
+ public MessagingTestConfigProperties getTestParameters()
+ {
+ return new MessagingTestConfigProperties(testProps);
+ }
+
+ /// <summary>
+ /// Creates a list of assertions.
+ /// </summary>
+ /// <param name="asserts"> The assertions to compile in a list. </param>
+ ///
+ /// <return> A list of assertions. </return>
+ protected IList<Assertion> assertionList(Assertion... asserts)
+ {
+ IList<Assertion> result = new ArrayList<Assertion>();
+
+ for (Assertion assertion : asserts)
+ {
+ result.add(assertion);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Generates a JUnit assertion exception (failure) if any assertions are passed into this method, also concatenating
+ /// all of the error messages in the assertions together to form an error message to diagnose the test failure with.
+ /// </summary>
+ /// <param name="asserts"> The list of failed assertions. </param>
+ protected static void assertNoFailures(List<Assertion> asserts)
+ {
+ log.debug("protected void assertNoFailures(List<Assertion> asserts = " + asserts + "): called");
+
+ // Check if there are no assertion failures, and return without doing anything if so.
+ if ((asserts == null) || asserts.isEmpty())
+ {
+ return;
+ }
+
+ // Compile all of the assertion failure messages together.
+ string errorMessage = assertionsToString(asserts);
+
+ // Fail with the error message from all of the assertions.
+ fail(errorMessage);
+ }
+
+ /// <summary>
+ /// Converts a list of failed assertions into an error message.
+ /// </summary>
+ /// <param name="asserts"> The failed assertions. </param>
+ ///
+ /// <return> The error message. </return>
+ protected static string assertionsToString(List<Assertion> asserts)
+ {
+ string errorMessage = "";
+
+ for (Assertion assertion : asserts)
+ {
+ errorMessage += assertion.ToString() + "\n";
+ }
+
+ return errorMessage;
+ }
+
+ /// <summary>
+ /// Ensures that the in-vm broker is created and initialized.
+ /// </summary>
+ ///
+ /// <exception cref="Exception"> Any exceptions allowed to fall through and fail the test. </exception>
+ protected void setUp() throws Exception
+ {
+ NDC.push(getName());
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ // Process all optional setup tasks. This may include in-vm broker creation, if a decorator has added it.
+ taskHandler.runSetupTasks();
+ }
+
+ /// <summary> Ensures that the in-vm broker is cleaned up after each test run. </summary>
+ protected void tearDown()
+ {
+ NDC.pop();
+
+ // Process all optional tear down tasks. This may include in-vm broker clean up, if a decorator has added it.
+ taskHandler.runTearDownTasks();
+ }
+
+ /// <summary>
+ /// Adds the specified task to the tests setup.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests setup. </param>
+ public void chainSetupTask(Runnable task)
+ {
+ taskHandler.chainSetupTask(task);
+ }
+
+ /// <summary>
+ /// Adds the specified task to the tests tear down.
+ /// </summary>
+ /// <param name="task"> The task to add to the tests tear down. </param>
+ public void chainTearDownTask(Runnable task)
+ {
+ taskHandler.chainTearDownTask(task);
+ }
+
+ /// <summary>
+ /// Should provide a translation from the junit method name of a test to its test case name as known to the test
+ /// clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ /// case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ /// name "TC2_BasicP2P".
+ /// </summary>
+ /// <param name="methodName"> The name of the JUnit test method. </param>
+ ///
+ /// <return> The name of the corresponding interop test case. </return>
+ public string getTestCaseNameForTestMethod(string methodName)
+ {
+ return methodName;
+ }
+
+ public void setInVmBrokers()
+ {
+ isUsingInVM = true;
+ }
+
+ /// <summary>
+ /// Indicates whether or not a test case is using in-vm brokers.
+ /// </summary>
+ /// <return> <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise. </return>
+ public bool usingInVmBroker()
+ {
+ return isUsingInVM;
+ }
+
+ /// <summary>
+ /// Sets the currently live in-vm broker.
+ /// </summary>
+ /// <param name="i"> The currently live in-vm broker. </param>
+ public void setLiveBroker(int i)
+ { }
+
+ /// <summary>
+ /// Reports the currently live in-vm broker.
+ /// </summary>
+ /// <return> The currently live in-vm broker. </return>
+ public int getLiveBroker()
+ {
+ return 0;
+ }
+
+ /// <summary>
+ /// Accepts a failure mechanism.
+ /// </summary>
+ /// <param name="failureMechanism"> The failure mechanism. </param>
+ public void setFailureMechanism(CauseFailure failureMechanism)
+ {
+ this.failureMechanism = failureMechanism;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+
+ /// <summary>
+ /// A FrameworkTestContext provides context information to test code about the current test case being run; its name, its
+ /// parameters.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide the name of the current test case.
+ /// <tr><td> Provide the test parameters.
+ /// </table>
+ /// </summary>
+ public interface FrameworkTestContext
+ {
+ /// <summary>
+ /// Reports the current test case name.
+ /// </summary>
+ /// <return> The current test case name. </return>
+ TestCaseVector getTestCaseVector();
+
+ /// <summary>
+ /// Reports the current test case parameters.
+ /// </summary>
+ /// <return> The current test case parameters. </return>
+ MessagingTestConfigProperties getTestParameters();
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.*;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// LocalCircuitImpl provides an implementation of the test circuit. This is a local only circuit implementation that
+ /// supports a single producer/consumer on each end of the circuit, with both ends of the circuit on the same JVM.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <td> <see cref="LocalPublisherImpl"/>, <see cref="LocalReceiverImpl"/>
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state. <td> <see cref="Assertion"/>
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedure on the circuit.
+ /// <tr><td> Provide access to connection and controlSession exception monitors. <td> <see cref="ExceptionMonitor"/>
+ /// </table>
+ /// </summary>
+ public class LocalCircuitImpl : Circuit
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(LocalCircuitImpl));
+
+ /// <summary> Holds the test configuration for the circuit. </summary>
+ private ParsedProperties testProps;
+
+ /// <summary> Holds the publishing end of the circuit. </summary>
+ private LocalPublisherImpl publisher;
+
+ /// <summary> Holds the receiving end of the circuit. </summary>
+ private LocalReceiverImpl receiver;
+
+ /// <summary> Holds the connection for the publishing end of the circuit. </summary>
+ private Connection connection;
+
+ /// <summary> Holds the exception listener for the connection on the publishing end of the circuit. </summary>
+ private ExceptionMonitor connectionExceptionMonitor;
+
+ /// <summary> Holds the exception listener for the controlSession on the publishing end of the circuit. </summary>
+ private ExceptionMonitor exceptionMonitor;
+
+ /// <summary>
+ /// Creates a test circuit using the specified test parameters. The publisher, receivers, connection and
+ /// connection monitor must already have been created, to assemble the circuit.
+ /// </summary>
+ /// <param name="testProps"> The test parameters. </param>
+ /// <param name="publisher"> The test publisher. </param>
+ /// <param name="receiver"> The test receivers. </param>
+ /// <param name="connection"> The connection. </param>
+ /// <param name="connectionExceptionMonitor"> The connection exception monitor. </param>
+ public LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver,
+ Connection connection, ExceptionMonitor connectionExceptionMonitor)
+ {
+ this.testProps = testProps;
+ this.publisher = publisher;
+ this.receiver = receiver;
+ this.connection = connection;
+ this.connectionExceptionMonitor = connectionExceptionMonitor;
+ this.exceptionMonitor = new ExceptionMonitor();
+
+ // Set this as the parent circuit on the publisher and receivers.
+ publisher.setCircuit(this);
+ receiver.setCircuit(this);
+ }
+
+ /// <summary>
+ /// Gets the interface on the publishing end of the circuit.
+ /// </summary>
+ /// <return> The publishing end of the circuit. </return>
+ public Publisher getPublisher()
+ {
+ return publisher;
+ }
+
+ /// <summary>
+ /// Gets the local publishing circuit end, for direct manipulation.
+ /// </summary>
+ /// <return> The local publishing circuit end. </return>
+ public CircuitEnd getLocalPublisherCircuitEnd()
+ {
+ return publisher;
+ }
+
+ /// <summary>
+ /// Gets the interface on the receiving end of the circuit.
+ /// </summary>
+ /// <return> The receiving end of the circuit. </return>
+ public Receiver getReceiver()
+ {
+ return receiver;
+ }
+
+ /// <summary>
+ /// Gets the local receiving circuit end, for direct manipulation.
+ /// </summary>
+ /// <return> The local receiving circuit end. </return>
+ public CircuitEnd getLocalReceiverCircuitEnd()
+ {
+ return receiver;
+ }
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ /// </summary>
+ public void check()
+ { }
+
+ /// <summary>
+ /// Applied a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> applyAssertions(List<Assertion> assertions)
+ {
+ IList<Assertion> failures = new LinkedList<Assertion>();
+
+ for (Assertion assertion : assertions)
+ {
+ if (!assertion.apply())
+ {
+ failures.add(assertion);
+ }
+ }
+
+ return failures;
+ }
+
+ /// <summary> Connects and starts the circuit. After this method is called the circuit is ready to send messages. </summary>
+ public void start()
+ { }
+
+ /// <summary> Closes the circuit. All associated resources are closed. </summary>
+ public void close()
+ {
+ try
+ {
+ publisher.close();
+ receiver.close();
+ connection.close();
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Got JMSException during close:" + e.getMessage(), e);
+ }
+ }
+
+ /// <summary> Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters. </summary>
+ protected void send()
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ bool transactional = props.getPublisherTransacted();
+ bool rollback = props.getRollbackPublisher();
+
+ // Send a message through the publisher and log any exceptions raised.
+ try
+ {
+ CircuitEnd end = getLocalPublisherCircuitEnd();
+
+ end.send(createTestMessage(end));
+
+ if (rollback)
+ {
+ end.getSession().rollback();
+ }
+ else if (transactional)
+ {
+ end.getSession().commit();
+ }
+ }
+ catch (JMSException e)
+ {
+ exceptionMonitor.onException(e);
+ }
+ }
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The
+ /// outline of the default test procedure is:
+ ///
+ /// <p/><pre>
+ /// Start the circuit.
+ /// Send test messages.
+ /// Request a status report.
+ /// Assert conditions on the publishing end of the circuit.
+ /// Assert conditions on the receiving end of the circuit.
+ /// Close the circuit.
+ /// Pass with no failed assertions or fail with a list of failed assertions.
+ /// </pre>
+ /// </summary>
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> test(int numMessages, List<Assertion> assertions)
+ {
+ // Start the test circuit.
+ start();
+
+ // Send the requested number of test messages.
+ for (int i = 0; i < numMessages; i++)
+ {
+ send();
+ }
+
+ // Inject a short pause to allow time for exceptions to come back asynchronously.
+ TestUtils.pause(500L);
+
+ // Request a status report.
+ check();
+
+ // Clean up the publisher/receivers/controlSession/connections.
+ close();
+
+ // Apply all of the requested assertions, keeping record of any that fail.
+ IList<Assertion> failures = applyAssertions(assertions);
+
+ // Return any failed assertions to the caller.
+ return failures;
+ }
+
+ /// <summary>
+ /// Creates a message with the properties defined as per the test parameters.
+ /// </summary>
+ /// <param name="client"> The circuit end to create the message on. </param>
+ ///
+ /// <return> The test message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSException occurring during creation of the message is allowed to fall through. </exception>
+ private Message createTestMessage(CircuitEnd client) throws JMSException
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ return TestUtils.createTestMessageOfSize(client.getSession(), props.getMessageSize());
+ }
+
+ /// <summary>
+ /// Gets the exception monitor for the publishing ends connection.
+ /// </summary>
+ /// <return> The exception monitor for the publishing ends connection. </return>
+ public ExceptionMonitor getConnectionExceptionMonitor()
+ {
+ return connectionExceptionMonitor;
+ }
+
+ /// <summary>
+ /// Gets the exception monitor for the publishing ends controlSession.
+ /// </summary>
+ /// <return> The exception monitor for the publishing ends controlSession. </return>
+ public ExceptionMonitor getExceptionMonitor()
+ {
+ return exceptionMonitor;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.MessageConsumer;
+using javax.jms.MessageProducer;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// Provides an implementation of the <see cref="Publisher"/> interface and wraps a single message producer and consumer on
+ /// a single controlSession, as a <see cref="CircuitEnd"/>. A local publisher also acts as a circuit end, because for a locally
+ /// located circuit the assertions may be applied directly, there does not need to be any inter-process messaging
+ /// between the publisher and its single circuit end, in order to ascertain its status.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <tr><td> Provide assertion that the publisher received no exceptions.
+ /// <tr><td> Provide assertion that the publisher received a no consumers error code.
+ /// <tr><td> Provide assertion that the publisher received a no route error code.
+ /// </table>
+ /// </summary>
+ public class LocalPublisherImpl extends CircuitEndBase : Publisher
+ {
+ /// <summary> Holds a reference to the containing circuit. </summary>
+ protected LocalCircuitImpl circuit;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public LocalPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ /// </summary>
+ /// <param name="end"> The circuit end base implementation to take producers and consumers from. </param>
+ public LocalPublisherImpl(CircuitEndBase end)
+ {
+ super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor());
+ }
+
+ /// <summary> Provides an assertion that the publisher encountered no exceptions. </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public bool apply()
+ {
+ bool passed = true;
+ ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor();
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertNoExceptions())
+ {
+ passed = false;
+
+ addError("Was expecting no exceptions.\n");
+ addError("Got the following exceptions on the connection, "
+ + circuit.getConnectionExceptionMonitor());
+ }
+
+ if (!sessionExceptionMonitor.assertNoExceptions())
+ {
+ passed = false;
+
+ addError("Was expecting no exceptions.\n");
+ addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor());
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, final Class<? extends Exception> exceptionClass)
+ {
+ return new AssertionBase()
+ {
+ public bool apply()
+ {
+ bool passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertExceptionOfType(exceptionClass))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + exceptionClass.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /// <summary>
+ /// Sets the contianing circuit.
+ /// </summary>
+ /// <param name="circuit"> The containing circuit. </param>
+ public void setCircuit(LocalCircuitImpl circuit)
+ {
+ this.circuit = circuit;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.MessageConsumer;
+using javax.jms.MessageProducer;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// Provides an implementation of the <see cref="Receiver"/> interface that wraps a single message producer and consumer on
+ /// a single controlSession, as a <see cref="CircuitEnd"/>. A local receiver also acts as a circuit end, because for a locally
+ /// located circuit the assertions may be applied directly, there does not need to be any inter process messaging
+ /// between the publisher and its single circuit end, in order to ascertain its status.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ public class LocalReceiverImpl extends CircuitEndBase : Receiver
+ {
+ /// <summary> Holds a reference to the containing circuit. </summary>
+ private LocalCircuitImpl circuit;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public LocalReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ /// </summary>
+ /// <param name="end"> The circuit end base implementation to take producers and consumers from. </param>
+ public LocalReceiverImpl(CircuitEndBase end)
+ {
+ super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor());
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. <return> An assertion that the receiver got a given exception during the test. </return> </param>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Sets the contianing circuit.
+ /// </summary>
+ /// <param name="circuit"> The containing circuit. </param>
+ public void setCircuit(LocalCircuitImpl circuit)
+ {
+ this.circuit = circuit;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.localcircuit.LocalCircuitImpl;
+using Apache.Qpid.Integration.Tests.framework.localcircuit.LocalPublisherImpl;
+using Apache.Qpid.Integration.Tests.framework.localcircuit.LocalReceiverImpl;
+using Apache.Qpid.Integration.Tests.framework.sequencers.CircuitFactory;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.*;
+
+using System.Collections.Generic.IList;
+using java.util.Properties;
+using java.util.concurrent.atomic.AtomicLong;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
+ /// on the same JVM. The ends of the circuit are presented as <see cref="Publisher"/> and <see cref="Receiver"/> interfaces, which
+ /// in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
+ /// of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
+ /// use messaging features not available in JMS can be written. This provides an extension point for writing tests
+ /// against proprietary features of JMS implementations.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a standard test procedure over a test circuit.
+ /// <tr><td> Construct test circuits appropriate to a tests context.
+ /// </table>
+ /// </summary>
+ public class LocalCircuitFactory : CircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(LocalCircuitFactory));
+
+ /// <summary> Used to create unique destination names for each test. </summary>
+ protected static AtomicLong uniqueDestsId = new AtomicLong();
+
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test and gathering the test reports from the participants.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties)
+ {
+ FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions));
+ }
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ ///
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ Circuit result;
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
+ try
+ {
+ // Get a unique offset to append to destination names to make them unique to the connection.
+ long uniqueId = uniqueDestsId.incrementAndGet();
+
+ // Set up the connection.
+ Connection connection = TestUtils.createConnection(testProperties);
+
+ // Add the connection exception listener to assert on exception conditions with.
+ // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ // connection.setExceptionListener(exceptionMonitor);
+
+ // Set up the publisher.
+ CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
+
+ // Set up the receiver.
+ CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
+
+ // Start listening for incoming messages.
+ connection.start();
+
+ // Namespace everything up.
+ LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
+ LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
+
+ result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a local <see cref="Receiver"/> from a <see cref="CircuitEnd"/>. Sub-classes may override this to provide more
+ /// specialized receivers if necessary.
+ /// </summary>
+ /// <param name="receiverEnd"> The receiving circuit end. </param>
+ ///
+ /// <return> A <see cref="Receiver"/>. </return>
+ protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
+ {
+ return new LocalReceiverImpl(receiverEnd);
+ }
+
+ /// <summary>
+ /// Creates a local <see cref="Publisher"/> from a <see cref="CircuitEnd"/>. Sub-classes may override this to provide more
+ /// specialized receivers if necessary.
+ /// </summary>
+ /// <param name="publisherEnd"> The publishing circuit end. </param>
+ ///
+ /// <return> A <see cref="Receiver"/>. </return>
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalPublisherImpl(publisherEnd);
+ }
+
+ /// <summary>
+ /// Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ /// </summary>
+ /// <param name="connection"> The connection to build the circuit end on. </param>
+ /// <param name="testProps"> The test parameters to configure the circuit end construction. </param>
+ /// <param name="uniqueId"> A unique number to being numbering destinations from, to make this circuit unique. </param>
+ ///
+ /// <return> A circuit end suitable for the publishing side of a test circuit. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through and fail the creation. </exception>
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null;
+
+ MessageConsumer consumer =
+ props.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!props.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ /// </summary>
+ /// <param name="connection"> The connection to build the circuit end on. </param>
+ /// <param name="testProps"> The test parameters to configure the circuit end construction. </param>
+ /// <param name="uniqueId"> A unique number to being numbering destinations from, to make this circuit unique. </param>
+ ///
+ /// <return> A circuit end suitable for the receiving side of a test circuit. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through and fail the creation. </exception>
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ MessageProducer producer =
+ props.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ props.getReceiverConsumerBind()
+ ? ((props.getDurableSubscription() && props.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!props.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// MessageIdentityVector provides a message identification scheme, that matches individual messages with test cases.
+ /// Test messages are being sent by a number of test clients, sending messages over a set of routes, and being received
+ /// by another set of test clients. Each test is itself, being run within a test cycle, of which there could be many. It
+ /// is the job of the test coordinator to request and receive reports from the available test clients, on what has been
+ /// sent, what has been received, and what errors may have occurred, and to reconcile this information against the
+ /// assertions being applied by the test case. In order to be able to figure out which messages belong to which test,
+ /// there needs to be an identification scheme, that the coordinator can use to correlate messages in senders and
+ /// receiver reports. Every message sent in a test can be associated with this information.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Identify a test case, a handling client id, a circuit end within the client, and a test cycle number.
+ /// </table>
+ /// </summary>
+ public class MessageIdentityVector
+ {
+ /// <summary> Holds the test case vector component of the message identity vector. </summary>
+ private TestCaseVector testCaseVector;
+
+ /// <summary> The unique client id. </summary>
+ private string clientId;
+
+ /// <summary> The unique circuit end number within the client id. </summary>
+ private int circuitEndId;
+
+ /// <summary>
+ /// Creates a new identity vector for test messages.
+ /// </summary>
+ /// <param name="testCase"> The name of the test case generating the messages. </param>
+ /// <param name="clientId"> The unique id of the client implementing a circuit end that is handling the messages. </param>
+ /// <param name="circuitEndId"> The unique id number of the circuit end within the client. </param>
+ /// <param name="testCycleNumber"> The cycle iteration number of the test case. </param>
+ public MessageIdentityVector(string testCase, string clientId, int circuitEndId, int testCycleNumber)
+ {
+ this.testCaseVector = new TestCaseVector(testCase, testCycleNumber);
+ this.clientId = clientId;
+ this.circuitEndId = circuitEndId;
+ }
+
+ /// <summary>
+ /// Reports the test case vector component of the message identity vector.
+ /// </summary>
+ /// <return> The test case vector component of the message identity vector. </return>
+ public TestCaseVector getTestCaseVector()
+ {
+ return testCaseVector;
+ }
+
+ /// <summary>
+ /// Reports the name of the test case.
+ /// </summary>
+ /// <return> The name of the test case. </return>
+ public string getTestCase()
+ {
+ return testCaseVector.getTestCase();
+ }
+
+ /// <summary>
+ /// Reports the test iteration cycle number within the test case.
+ /// </summary>
+ /// <return> The test iteration cycle number within the test case. </return>
+ public int getTestCycleNumber()
+ {
+ return testCaseVector.getTestCycleNumber();
+ }
+
+ /// <summary>
+ /// Resports the client id.
+ /// </summary>
+ /// <return> The client id. </return>
+ public string getClientId()
+ {
+ return clientId;
+ }
+
+ /// <summary>
+ /// Reports the circuit end number within the test client.
+ /// </summary>
+ /// <return> The circuit end number within the test client. </return>
+ public int getCircuitEndId()
+ {
+ return circuitEndId;
+ }
+
+ /// <summary>
+ /// Compares this identity vector with another for equality. All fields must match.
+ /// </summary>
+ /// <param name="o"> The identity vector to compare with. </param>
+ ///
+ /// <return> <tt>true</tt> if the identity vector is identical to this one by all fields, <tt>false</tt> otherwise. </return>
+ public bool equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if ((o == null) || (getClass() != o.getClass()))
+ {
+ return false;
+ }
+
+ MessageIdentityVector that = (MessageIdentityVector) o;
+
+ if (circuitEndId != that.circuitEndId)
+ {
+ return false;
+ }
+
+ if ((clientId != null) ? (!clientId.equals(that.clientId)) : (that.clientId != null))
+ {
+ return false;
+ }
+
+ if ((testCaseVector != null) ? (!testCaseVector.equals(that.testCaseVector)) : (that.testCaseVector != null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Computes a hash code for this identity vector based on all fields.
+ /// </summary>
+ /// <return> A hash code for this identity vector based on all fields. </return>
+ public int hashCode()
+ {
+ int result;
+ result = ((testCaseVector != null) ? testCaseVector.hashCode() : 0);
+ result = (31 * result) + ((clientId != null) ? clientId.hashCode() : 0);
+ result = (31 * result) + circuitEndId;
+
+ return result;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using javax.jms.Message;
+using javax.jms.MessageListener;
+
+using java.util.concurrent.atomic.AtomicInteger;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// MessageMonitor is used to record information about messages received. This will provide methods to check various
+ /// properties, such as the type, number and content of messages received in order to verify the correct behaviour of
+ /// tests.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Count incoming messages.
+ /// <tr><td> Record time ellapsed since the arrival of the first message.
+ /// <tr><td> Reset all counts and timings.
+ /// </table>
+ /// </summary>
+ public class MessageMonitor : MessageListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(MessageMonitor));
+
+ /// <summary> Holds the count of messages received since the last query. </summary>
+ protected AtomicInteger numMessages = new AtomicInteger();
+
+ /// <summary> Holds the time of arrival of the first message. </summary>
+ protected Long firstMessageTime = null;
+
+ /// <summary>
+ /// Handles received messages. Does Nothing.
+ /// </summary>
+ /// <param name="message"> The message. Ignored. </param>
+ public void onMessage(Message message)
+ {
+ // log.debug("public void onMessage(Message message): called");
+
+ numMessages.getAndIncrement();
+ }
+
+ /// <summary>
+ /// Gets the count of messages.
+ /// </summary>
+ /// <return> The count of messages. </return>
+ public int getNumMessage()
+ {
+ if (firstMessageTime == null)
+ {
+ firstMessageTime = System.nanoTime();
+ }
+
+ return numMessages.get();
+ }
+
+ /// <summary>
+ /// Gets the time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet.
+ /// </summary>
+ /// <return> The time elapsed since the first message arrived, in nanos, or zero if no messages have arrived yet. </return>
+ public long getTime()
+ {
+ if (firstMessageTime != null)
+ {
+ return System.nanoTime() - firstMessageTime;
+ }
+ else
+ {
+ return 0L;
+ }
+ }
+
+ /// <summary> Resets the message count and timer to zero. </summary>
+ public void reset()
+ {
+ numMessages.set(0);
+ firstMessageTime = null;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.Session;
+
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
+ /// and test parameters for running a messaging test over that topology. A Properties object holding some of these
+ /// properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
+ ///
+ /// <p/>A complete list of the parameters, default values and comments on their usage is provided here:
+ ///
+ /// <p/><table><caption>Parameters</caption>
+ /// <tr><th> Parameter <th> Default <th> Comments
+ /// <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
+ /// <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
+ /// <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
+ /// <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
+ /// <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ /// <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
+ /// <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ /// <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
+ /// <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
+ /// <tr><td> username <td> guest <td> The username to access the broker with.
+ /// <tr><td> password <td> guest <td> The password to access the broker with.
+ /// <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
+ /// <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
+ /// <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
+ /// <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
+ /// <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
+ /// <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
+ /// <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ /// 0 - SESSION_TRANSACTED
+ /// 1 - AUTO_ACKNOWLEDGE
+ /// 2 - CLIENT_ACKNOWLEDGE
+ /// 3 - DUPS_OK_ACKNOWLEDGE
+ /// 257 - NO_ACKNOWLEDGE
+ /// 258 - PRE_ACKNOWLEDGE
+ /// <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
+ /// Limits the volume of messages currently buffered on the client
+ /// or broker. Can help scale test clients by limiting amount of buffered
+ /// data to avoid out of memory errors.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide the names and defaults of all test parameters.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Put a type-safe wrapper around these properties, but continue to store the parameters as properties. This is
+ /// simply to ensure that it is a simple matter to serialize/deserialize string/string pairs onto messages.</remarks>
+ public class MessagingTestConfigProperties extends ParsedProperties
+ {
+ // ====================== Connection Properties ==================================
+
+ /// <summary> Holds the name of the default connection configuration. </summary>
+ public static final string CONNECTION_NAME = "broker";
+
+ /// <summary> Holds the name of the property to get the initial context factory name from. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
+
+ /// <summary> Defines the class to use as the initial context factory by default. </summary>
+ public static final string INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+ /// <summary> Holds the name of the property to get the test broker url from. </summary>
+ public static final string BROKER_PROPNAME = "qpid.test.broker";
+
+ /// <summary> Holds the default broker url for the test. </summary>
+ public static final string BROKER_DEFAULT = "vm://:1";
+
+ /// <summary> Holds the name of the property to get the test broker virtual path. </summary>
+ public static final string VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+ /// <summary> Holds the default virtual path for the test. </summary>
+ public static final string VIRTUAL_HOST_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the broker access username from. </summary>
+ public static final string USERNAME_PROPNAME = "username";
+
+ /// <summary> Holds the default broker log on username. </summary>
+ public static final string USERNAME_DEFAULT = "guest";
+
+ /// <summary> Holds the name of the property to get the broker access password from. </summary>
+ public static final string PASSWORD_PROPNAME = "password";
+
+ /// <summary> Holds the default broker log on password. </summary>
+ public static final string PASSWORD_DEFAULT = "guest";
+
+ // ====================== Messaging Topology Properties ==========================
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
+
+ /// <summary> Holds the default value of the publisher producer flag. </summary>
+ public static final bool PUBLISHER_PRODUCER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the bind publisher procuder flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
+
+ /// <summary> Holds the default value of the publisher consumer flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
+
+ /// <summary> Holds the default value of the receivers producer flag. </summary>
+ public static final bool RECEIVER_PRODUCER_BIND_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the bind receivers procuder flag from. </summary>
+ public static final string RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
+
+ /// <summary> Holds the default value of the receivers consumer flag. </summary>
+ public static final bool RECEIVER_CONSUMER_BIND_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the publishers consumer active flag from. </summary>
+ public static final string PUBLISHER_CONSUMER_ACTIVE_PROPNAME = "publisherConsumerActive";
+
+ /// <summary> Holds the default value of the publishers consumer active flag. </summary>
+ public static final bool PUBLISHER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the receivers consumer active flag from. </summary>
+ public static final string RECEIVER_CONSUMER_ACTIVE_PROPNAME = "receiverConsumerActive";
+
+ /// <summary> Holds the default value of the receivers consumer active flag. </summary>
+ public static final bool RECEIVER_CONSUMER_ACTIVE_DEFAULT = true;
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
+
+ /// <summary> Holds the name of the property to get the destination name root from. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
+
+ /// <summary> Holds the root of the name of the default destination to send to. </summary>
+ public static final string RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
+
+ /// <summary> Holds the name of the proeprty to get the destination count from. </summary>
+ public static final string DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+ /// <summary> Defines the default number of destinations to ping. </summary>
+ public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to get the p2p or pub/sub messaging mode from. </summary>
+ public static final string PUBSUB_PROPNAME = "pubsub";
+
+ /// <summary> Holds the pub/sub mode default, true means ping a topic, false means ping a queue. </summary>
+ public static final bool PUBSUB_DEFAULT = false;
+
+ // ====================== JMS Options and Flags =================================
+
+ /// <summary> Holds the name of the property to get the test delivery mode from. </summary>
+ public static final string PERSISTENT_MODE_PROPNAME = "persistent";
+
+ /// <summary> Holds the message delivery mode to use for the test. </summary>
+ public static final bool PERSISTENT_MODE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_PUBLISHER_PROPNAME = "transactedPublisher";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the test transactional mode from. </summary>
+ public static final string TRANSACTED_RECEIVER_PROPNAME = "transactedReceiver";
+
+ /// <summary> Holds the transactional mode to use for the test. </summary>
+ public static final bool TRANSACTED_RECEIVER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the no local flag from. </summary>
+ public static final string NO_LOCAL_PROPNAME = "noLocal";
+
+ /// <summary> Defines the default value of the no local flag to use when consuming messages. </summary>
+ public static final bool NO_LOCAL_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the message acknowledgement mode from. </summary>
+ public static final string ACK_MODE_PROPNAME = "ackMode";
+
+ /// <summary> Defines the default message acknowledgement mode. </summary>
+ public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /// <summary> Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. </summary>
+ public static final string DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
+
+ /// <summary> Defines the default value of the durable subscriptions flag. </summary>
+ public static final bool DURABLE_SUBSCRIPTION_DEFAULT = false;
+
+ // ====================== Qpid/AMQP Options and Flags ================================
+
+ /// <summary> Holds the name of the property to set the exclusive flag from. </summary>
+ public static final string EXCLUSIVE_PROPNAME = "exclusive";
+
+ /// <summary> Defines the default value of the exclusive flag to use when consuming messages. </summary>
+ public static final bool EXCLUSIVE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the immediate flag from. </summary>
+ public static final string IMMEDIATE_PROPNAME = "immediate";
+
+ /// <summary> Defines the default value of the immediate flag to use when sending messages. </summary>
+ public static final bool IMMEDIATE_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the mandatory flag from. </summary>
+ public static final string MANDATORY_PROPNAME = "mandatory";
+
+ /// <summary> Defines the default value of the mandatory flag to use when sending messages. </summary>
+ public static final bool MANDATORY_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the durable destinations flag from. </summary>
+ public static final string DURABLE_DESTS_PROPNAME = "durableDests";
+
+ /// <summary> Default value for the durable destinations flag. </summary>
+ public static final bool DURABLE_DESTS_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to set the prefetch size from. </summary>
+ public static final string PREFETCH_PROPNAME = "prefetch";
+
+ /// <summary> Defines the default prefetch size to use when consuming messages. </summary>
+ public static final int PREFETCH_DEFAULT = 100;
+
+ // ====================== Common Test Parameters ================================
+
+ /// <summary> Holds the name of the property to get the test message size from. </summary>
+ public static final string MESSAGE_SIZE_PROPNAME = "messageSize";
+
+ /// <summary> Used to set up a default message size. </summary>
+ public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+ /// <summary> Holds the name of the property to get the message rate from. </summary>
+ public static final string RATE_PROPNAME = "rate";
+
+ /// <summary> Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. </summary>
+ public static final int RATE_DEFAULT = 0;
+
+ /// <summary> Holds the name of the proeprty to get the. </summary>
+ public static final string SELECTOR_PROPNAME = "selector";
+
+ /// <summary> Holds the default message selector. </summary>
+ public static final string SELECTOR_DEFAULT = "";
+
+ /// <summary> Holds the name of the property to get the waiting timeout for response messages. </summary>
+ public static final string TIMEOUT_PROPNAME = "timeout";
+
+ /// <summary> Default time to wait before assuming that a ping has timed out. </summary>
+ public static final long TIMEOUT_DEFAULT = 30000;
+
+ /// <summary> Holds the name of the property to get the commit batch size from. </summary>
+ public static final string TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+ /// <summary> Defines the default number of pings to send in each transaction when running transactionally. </summary>
+ public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+ /// <summary> Holds the name of the property to set the maximum amount of pending message data for a producer to hold. </summary>
+ public static final string MAX_PENDING_PROPNAME = "maxPending";
+
+ /// <summary> Defines the default maximum quantity of pending message data to allow producers to hold. </summary>
+ public static final int MAX_PENDING_DEFAULT = 0;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_PUBLISHER_PROPNAME = "rollbackPublisher";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_PUBLISHER_DEFAULT = false;
+
+ /// <summary> Holds the name of the property to get the publisher rollback flag from. </summary>
+ public static final string ROLLBACK_RECEIVER_PROPNAME = "rollbackReceiver";
+
+ /// <summary> Holds the default publisher roll back setting. </summary>
+ public static final bool ROLLBACK_RECEIVER_DEFAULT = false;
+
+ // ====================== Options that control the bahviour of the test framework. =========================
+
+ /// <summary> Holds the name of the property to get the behavioural mode of not applicable assertions. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_PROPNAME = "notApplicableAssertion";
+
+ /// <summary> Holds the default behavioral mode of not applicable assertions, which is logging them as a warning. </summary>
+ public static final string NOT_APPLICABLE_ASSERTION_DEFAULT = "warn";
+
+ /// <summary> Holds the name of the property to get the verbose mode proeprty from. </summary>
+ public static final string VERBOSE_PROPNAME = "verbose";
+
+ /// <summary> Holds the default verbose mode. </summary>
+ public static final bool VERBOSE_DEFAULT = false;
+
+ /// <summary> Holds the default configuration properties. </summary>
+ public static ParsedProperties defaults = new ParsedProperties();
+
+ static
+ {
+ defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+
+ defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_ACTIVE_PROPNAME, PUBLISHER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_ACTIVE_PROPNAME, RECEIVER_CONSUMER_ACTIVE_DEFAULT);
+ defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PUBLISHER_PROPNAME, TRANSACTED_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_RECEIVER_PROPNAME, TRANSACTED_RECEIVER_DEFAULT);
+ defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+ defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
+
+ defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
+ defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
+ defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(PREFETCH_PROPNAME, PREFETCH_DEFAULT);
+
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_PUBLISHER_PROPNAME, ROLLBACK_PUBLISHER_DEFAULT);
+ defaults.setPropertyIfNull(ROLLBACK_RECEIVER_PROPNAME, ROLLBACK_RECEIVER_DEFAULT);
+
+ defaults.setPropertyIfNull(NOT_APPLICABLE_ASSERTION_PROPNAME, NOT_APPLICABLE_ASSERTION_DEFAULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
+ }
+
+ /// <summary> Creates a test configuration based on the defaults. </summary>
+ public MessagingTestConfigProperties()
+ {
+ super(defaults);
+ }
+
+ /// <summary>
+ /// Creates a test configuration based on the supplied properties.
+ /// </summary>
+ /// <param name="properties"> The test configuration. </param>
+ public MessagingTestConfigProperties(Properties properties)
+ {
+ super(properties);
+ }
+
+ /// <summary>
+ /// The size of test messages to send.
+ /// </summary>
+ /// <return> The size of test messages to send. </return>
+ public int getMessageSize()
+ {
+ return getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing producer should be set up to publish to a destination. </return>
+ public bool getPublisherProducerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be set up to receive from a destination. </return>
+ public bool getPublisherConsumerBind()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving producer should be set up to publish to a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving producer should be set up to publish to a destination. </return>
+ public bool getReceiverProducerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_PRODUCER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumer should be set up to receive from a destination.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumer should be set up to receive from a destination. </return>
+ public bool getReceiverConsumerBind()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_BIND_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the publishing consumer should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the publishing consumer should be created. </return>
+ public bool getPublisherConsumerActive()
+ {
+ return getPropertyAsBoolean(PUBLISHER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that the receiving consumers should be created and actively listening.
+ /// </summary>
+ /// <return> Flag to indicate that the receiving consumers should be created and actively listening. </return>
+ public bool getReceiverConsumerActive()
+ {
+ return getPropertyAsBoolean(RECEIVER_CONSUMER_ACTIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all test destination names from.
+ /// </summary>
+ /// <return> A root to create all test destination names from. </return>
+ public string getSendDestinationNameRoot()
+ {
+ return getProperty(SEND_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// A root to create all receiving destination names from.
+ /// </summary>
+ /// <return> A root to create all receiving destination names from. </return>
+ public string getReceiveDestinationNameRoot()
+ {
+ return getProperty(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that persistent messages should be used.
+ /// </summary>
+ /// <return> Flag to indicate that persistent messages should be used. </return>
+ public bool getPersistentMode()
+ {
+ return getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional messages should be sent by the publisher.
+ /// </summary>
+ /// <return> Flag to indicate that transactional messages should be sent by the publisher. </return>
+ public bool getPublisherTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that transactional receives should be used by the receiver.
+ /// </summary>
+ /// <return> Flag to indicate that transactional receives should be used by the receiver. </return>
+ public bool getReceiverTransacted()
+ {
+ return getPropertyAsBoolean(TRANSACTED_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// The name of the virtual host to run all tests over.
+ /// </summary>
+ /// <return> The name of the virtual host to run all tests over. </return>
+ public string getVirtualHost()
+ {
+ return getProperty(VIRTUAL_HOST_PROPNAME);
+ }
+
+ /// <summary>
+ /// Limiting rate for each sender in messages per second, or zero for unlimited.
+ /// </summary>
+ /// <return> Limiting rate for each sender in messages per second, or zero for unlimited. </return>
+ public string getRate()
+ {
+ return getProperty(RATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that test messages should be received publish/subscribe style by all receivers.
+ /// </summary>
+ /// <return> Flag to indicate that test messages should be received publish/subscribe style by all receivers. </return>
+ public bool getPubsub()
+ {
+ return getPropertyAsBoolean(PUBSUB_PROPNAME);
+ }
+
+ /// <summary>
+ /// The username credentials to run tests with.
+ /// </summary>
+ /// <return> The username credentials to run tests with. </return>
+ public string getUsername()
+ {
+ return getProperty(USERNAME_PROPNAME);
+ }
+
+ /// <summary>
+ /// The password credentials to run tests with.
+ /// </summary>
+ /// <return> The password credentials to run tests with. </return>
+ public string getPassword()
+ {
+ return getProperty(PASSWORD_PROPNAME);
+ }
+
+ /// <summary>
+ /// The timeout duration to fail tests on, should they receive no messages within it.
+ /// </summary>
+ /// <return> The timeout duration to fail tests on, should they receive no messages within it. </return>
+ public long getTimeout()
+ {
+ return getPropertyAsLong(TIMEOUT_PROPNAME);
+ }
+
+ /// <summary>
+ /// The number of messages to batch into each transaction in transational tests.
+ /// </summary>
+ /// <return> The number of messages to batch into each transaction in transational tests. </return>
+ public int getTxBatchSize()
+ {
+ return getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable destinations.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable destinations. </return>
+ public bool getDurableDests()
+ {
+ return getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
+ }
+
+ /// <summary>
+ /// The ack mode for message receivers to use.
+ /// </summary>
+ /// <return> The ack mode for message receivers to use. </return>
+ public int getAckMode()
+ {
+ return getPropertyAsInteger(ACK_MODE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that tests should use durable subscriptions.
+ /// </summary>
+ /// <return> Flag to indicate that tests should use durable subscriptions. </return>
+ public bool getDurableSubscription()
+ {
+ return getPropertyAsBoolean(DURABLE_SUBSCRIPTION_PROPNAME);
+ }
+
+ /// <summary>
+ /// The maximum amount of in-flight data, in bytes, that tests should send at any time.
+ /// </summary>
+ /// <return> The maximum amount of in-flight data, in bytes, that tests should send at any time. </return>
+ public int getMaxPending()
+ {
+ return getPropertyAsInteger(MAX_PENDING_PROPNAME);
+ }
+
+ /// <summary>
+ /// The size of the prefetch queue to use.
+ /// </summary>
+ /// <return> The size of the prefetch queue to use. </return>
+ public int getPrefetch()
+ {
+ return getPropertyAsInteger(PREFETCH_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be no-local.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be no-local. </return>
+ public bool getNoLocal()
+ {
+ return getPropertyAsBoolean(NO_LOCAL_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that subscriptions should be exclusive.
+ /// </summary>
+ /// <return> Flag to indicate that subscriptions should be exclusive. </return>
+ public bool getExclusive()
+ {
+ return getPropertyAsBoolean(EXCLUSIVE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be delivered immediately.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be delivered immediately. </return>
+ public bool getImmediate()
+ {
+ return getPropertyAsBoolean(IMMEDIATE_PROPNAME);
+ }
+
+ /// <summary>
+ /// Flag to indicate that messages must be routable.
+ /// </summary>
+ /// <return> Flag to indicate that messages must be routable. </return>
+ public bool getMandatory()
+ {
+ return getPropertyAsBoolean(MANDATORY_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the publisher should rollback all messages sent.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages sent. </return>
+ public bool getRollbackPublisher()
+ {
+ return getPropertyAsBoolean(ROLLBACK_PUBLISHER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the value of a flag to indicate that the receiver should rollback all messages received, then receive them
+ /// again.
+ /// </summary>
+ /// <return> A flag to indicate that the publisher should rollback all messages received. </return>
+ public bool getRollbackReceiver()
+ {
+ return getPropertyAsBoolean(ROLLBACK_RECEIVER_PROPNAME);
+ }
+
+ /// <summary>
+ /// Gets the behavioural mode of not applicable assertions. Should be one of 'quiet', 'warn' or 'fail'.
+ /// </summary>
+ /// <return> The behavioural mode of not applicable assertions. </return>
+ public string getNotApplicableAssertionMode()
+ {
+ return getProperty(NOT_APPLICABLE_ASSERTION_PROPNAME);
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
+ /// applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
+ /// being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
+ /// instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
+ /// as warnings to the console, or raise them as test failures.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Quitely pass.
+ /// <tr><td> Log a warning.
+ /// <tr><td> Raise a test failure.
+ /// </table>
+ /// </summary>
+ public class NotApplicableAssertion : Assertion
+ {
+ /// <summary> Used for logging to the console. </summary>
+ private static ILog console = LogManager.GetLogger("CONSOLE." + NotApplicableAssertion.class.getName());
+
+ /// <summary> The possible behavioural modes of this assertion. </summary>
+ private enum Mode
+ {
+ /// <summary> Quietly ignore the assertion by passing. </summary>
+ Quiet,
+
+ /// <summary> Ignore the assertion by passing but log a warning about it. </summary>
+ Warn,
+
+ /// <summary> Fail the assertion. </summary>
+ Fail;
+ }
+
+ /// <summary> The behavioural mode of the assertion. </summary>
+ private Mode mode;
+
+ /// <summary>
+ /// Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
+ /// configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
+ /// read as 'fail'.
+ /// </summary>
+ /// <param name="testProperties"> The test configuration properties. </param>
+ public NotApplicableAssertion(ParsedProperties testProperties)
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ string modeName = props.getNotApplicableAssertionMode();
+
+ if ("quiet".equals(modeName))
+ {
+ mode = Mode.Quiet;
+ }
+ else if ("warn".equals(modeName))
+ {
+ mode = Mode.Warn;
+ }
+ else
+ {
+ mode = Mode.Fail;
+ }
+ }
+
+ /// <summary>
+ /// Applies the assertion.
+ /// </summary>
+ /// <return> <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails. </return>
+ public bool apply()
+ {
+ switch (mode)
+ {
+ case Quiet:
+ return true;
+
+ case Warn:
+ console.warn("Warning: Not applicable assertion being ignored.");
+
+ return true;
+
+ case Fail:
+ default:
+ return false;
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Publisher represents the status of the publishing side of a test circuit. Its main purpose is to provide assertions
+ /// that can be applied to test the behaviour of the publishers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the publishers received no exceptions.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ /// warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ /// I am tempted to go with the dropping/warning/error approach, that would imply that it makes sense to pull
+ /// the assertions back from AMQPPublisher to here.</remarks>
+ public interface Publisher
+ {
+ // Assertions that are meaningfull to AMQP and to JMS.
+
+ /// <summary>
+ /// Provides an assertion that the publisher encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// A Receiver is a <see cref="CircuitEnd"/> that represents the status of the receiving side of a test circuit. Its main
+ /// purpose is to provide assertions that can be applied to check the behaviour of the receivers.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> There are mixtures of AMQP and JMS assertions in this interface. Either keep them here, but quietly (or with a
+ /// warning or error) drop them from test cases where they are not relevant, or push them down into sub-classes.
+ /// I am tempted to go with the dropping/warning/error approach.</remarks>
+ public interface Receiver
+ {
+ // Assertions that are meaningfull to AMQP and to JMS.
+
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps);
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to AMQP.
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps);
+
+ // Assertions that are meaningfull only to Java/JMS.
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the receiver got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass);
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using org.apache.qpid.util.ConversationFactory;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// BaseCircuitFactory provides some functionality common to all <see cref="CircuitFactory"/>s, such as the details of
+ /// all <see cref="Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClient"/>s that make up the end-points of
+ /// the circuits that the factory creates, and an active <see cref="ConversationFactory"/> that can be used to generate
+ /// control conversations with those circuit end-points.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Hold the details of the sending and receiving end-points to create circuits from.
+ /// <tr><td> Provide a conversation factory to create control conversations with the end-points.
+ /// </table>
+ /// </summary>
+ public abstract class BaseCircuitFactory : CircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(BaseCircuitFactory));
+
+ /// <summary> Holds the contact details for the sending test client. </summary>
+ protected TestClientDetails sender;
+
+ /// <summary> Holds the contact details for the receving test client. </summary>
+ protected IList<TestClientDetails> receivers = new LinkedList<TestClientDetails>();
+
+ /// <summary> Holds the conversation factory over which to coordinate the test. </summary>
+ protected ConversationFactory conversationFactory;
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(Properties testProperties)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender)
+ {
+ log.debug("public void setSender(TestClientDetails sender = " + sender + "): called");
+
+ this.sender = sender;
+ }
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver)
+ {
+ log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called");
+
+ this.receivers.add(receiver);
+ }
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender()
+ {
+ return sender;
+ }
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers()
+ {
+ return receivers;
+ }
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ this.conversationFactory = conversationFactory;
+ }
+
+ /// <summary>
+ /// Provides the conversation factory for providing the distributed test sequencing conversations over the test
+ /// connection.
+ /// </summary>
+ /// <return> The conversation factory to create test sequencing conversations with. </return>
+ public ConversationFactory getConversationFactory()
+ {
+ return conversationFactory;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.JMSException;
+using javax.jms.Message;
+
+using System.Collections.Generic.IList;
+using System.Collections.Generic.IDictionary;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// A CircuitFactory is responsibile for creating test circuits appropriate to the context that a test case is
+ /// running in, and providing an implementation of a standard test procedure over a test circuit.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a standard test procedure over a test circuit.
+ /// <tr><td> Construct test circuits appropriate to a tests context.
+ /// </table>
+ /// </summary>
+ public interface CircuitFactory
+ {
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ /// the test reports.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ ///
+ /// @deprecated Use test circuits and Circuit.test instead.
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties);
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ ///
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(ParsedProperties testProperties);
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender);
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver);
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender();
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers();
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory);
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.TestUtils;
+using Apache.Qpid.Integration.Tests.framework.distributedcircuit.DistributedCircuitImpl;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.Destination;
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.Session;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// FanOutCircuitFactory is a circuit factory that creates distributed test circuits. Given a set of participating
+ /// test client nodes, it assigns one node to the SENDER role and the remainder to the RECEIVER role.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create distributed circuits from one to many test nodes, for fanout style testing.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> Adapt this to be an n*m topology circuit factory. Need to add circuit topology definitions to the test
+ /// parameters. Place n senders onto the available test clients, and m receivers. Where n or m is larger than
+ /// the available nodes, start stacking multiple test clients on each node. There will also be an option that
+ /// indicates whether nodes can play both roles, and how many nodes out of all available may be assigned to
+ /// each role.</remarks>
+ ///
+ /// <remarks> The createCircuit methods on this and InteropCircuitFactory are going to be identical. This is because the
+ /// partitioning into senders and receivers is already done by the test decorators. Either eliminate these factories
+ /// as unnesesary, or move the partitioning functionality into the factories, in which case the test decorators
+ /// can probably be merged or eliminated. There is confusion over the placement of responsibilities between the
+ /// factories and the test decorators... although the test decorators may well do more than just circuit creation
+ /// in the future. For example, there may have to be a special decorator for test repetition that does one circuit
+ /// creation, but the runs many tests over it, in which case the handling of responsibilities becomes clearer.</remarks>
+ public class FanOutCircuitFactory extends BaseCircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(FanOutCircuitFactory));
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ log.debug("public Circuit createCircuit(ParsedProperties testProperties): called");
+
+ IList<TestClientDetails> senders = new LinkedList<TestClientDetails>();
+ senders.add(getSender());
+ IList<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory);
+ }
+
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ /// the test reports.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ ///
+ /// @deprecated Scheduled for removal once existing tests converted over to use test circuits.
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties)
+ {
+ log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+ TestClientDetails sender = getSender();
+ IList<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ try
+ {
+ // Create a conversation on the sender clients private control route.
+ Session session = conversationFactory.getSession();
+ Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+ ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+
+ // Assign the sender role to the sending test client.
+ Message assignSender = conversationFactory.getSession().createMessage();
+ TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+ assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignSender.setStringProperty("ROLE", "SENDER");
+ assignSender.setStringProperty("CLIENT_NAME", "Sustained_SENDER");
+
+ senderConversation.send(senderControlTopic, assignSender);
+
+ // Wait for the sender to confirm its role.
+ senderConversation.receive();
+
+ // Assign the receivers roles.
+ for (TestClientDetails receiver : receivers)
+ {
+ assignReceiverRole(receiver, testProperties, true);
+ }
+
+ // Start the test on the sender.
+ Message start = session.createMessage();
+ start.setStringProperty("CONTROL_TYPE", "START");
+
+ senderConversation.send(senderControlTopic, start);
+
+ // Wait for the test sender to return its report.
+ Message senderReport = senderConversation.receive();
+ TestUtils.pause(500);
+
+ // Ask the receivers for their reports.
+ Message statusRequest = session.createMessage();
+ statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+ // Gather the reports from all of the receiving clients.
+
+ // Return all of the test reports, the senders report first.
+ // return new Message[] { senderReport };
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Unhandled JMSException.");
+ }
+ }
+
+ /// <summary>
+ /// Assigns the receivers role to the specified test client that is to act as a receivers during the test. This method
+ /// does not always wait for the receiving clients to confirm their role assignments. This is because this method
+ /// may be called from an 'onMessage' method, when a client is joining the test at a later point in time, and it
+ /// is not possible to do a synchronous receive during an 'onMessage' method. There is a flag to indicate whether
+ /// or not to wait for role confirmations.
+ /// </summary>
+ /// <param name="receiver"> The test client to assign the receivers role to. </param>
+ /// <param name="testProperties"> The test parameters. </param>
+ /// <param name="confirm"> Indicates whether role confirmation should be waited for. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions occurring during the conversation are allowed to fall through. </exception>
+ ///
+ /// @deprecated Scheduled for removal once existing tests converted over to use test circuits.
+ protected void assignReceiverRole(TestClientDetails receiver, Properties testProperties, bool confirm)
+ throws JMSException
+ {
+ log.info("assignReceiverRole(TestClientDetails receivers = " + receiver + ", Map<String, Object> testProperties = "
+ + testProperties + "): called");
+
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ // Create a conversation with the receiving test client.
+ Session session = conversationFactory.getSession();
+ Destination receiverControlTopic = session.createTopic(receiver.privateControlKey);
+ ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+ // Assign the receivers role to the receiving client.
+ Message assignReceiver = session.createMessage();
+ TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+ assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignReceiver.setStringProperty("ROLE", "RECEIVER");
+ assignReceiver.setStringProperty("CLIENT_NAME", receiver.clientName);
+
+ receiverConversation.send(receiverControlTopic, assignReceiver);
+
+ // Wait for the role confirmation to come back.
+ if (confirm)
+ {
+ receiverConversation.receive();
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using Apache.Qpid.Integration.Tests.framework.TestUtils;
+using Apache.Qpid.Integration.Tests.framework.distributedcircuit.DistributedCircuitImpl;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.Destination;
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.Session;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// InteropCircuitFactory is a circuit factory that creates distributed test circuits. Given a set of participating
+ /// test client nodes, it assigns one node to the SENDER role and one the RECEIVER role.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create distributed circuits from pairs of test nodes, for interop style testing.
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks> The partitioning of a set of nodes into sender and receiver roles is actually done by the interop test
+ /// decorator. See the todo comment in FanOutCircuitFactory about merging the factories with the decorators, or
+ /// more carefully dividing up responsibilities between them.</remarks>
+ ///
+ /// <remarks> The squenceTest code is deprecated, but currently still used by the interop tests. It will be removed once it
+ /// have been fully replaced by the default test procedure.</remarks>
+ public class InteropCircuitFactory extends BaseCircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(InteropCircuitFactory));
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ log.debug("public Circuit createCircuit(ParsedProperties testProperties): called");
+
+ IList<TestClientDetails> senders = new LinkedList<TestClientDetails>();
+ senders.add(getSender());
+ IList<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ return DistributedCircuitImpl.createCircuit(testProperties, senders, receivers, conversationFactory);
+ }
+
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ /// the test reports.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties)
+ {
+ log.debug("protected Message[] sequenceTest(Object... testProperties = " + testProperties + "): called");
+
+ TestClientDetails sender = getSender();
+ IList<TestClientDetails> receivers = getReceivers();
+ ConversationFactory conversationFactory = getConversationFactory();
+
+ try
+ {
+ Session session = conversationFactory.getSession();
+ Destination senderControlTopic = session.createTopic(sender.privateControlKey);
+ Destination receiverControlTopic = session.createTopic(receivers.get(0).privateControlKey);
+
+ ConversationFactory.Conversation senderConversation = conversationFactory.startConversation();
+ ConversationFactory.Conversation receiverConversation = conversationFactory.startConversation();
+
+ Message assignSender = conversationFactory.getSession().createMessage();
+ TestUtils.setPropertiesOnMessage(assignSender, testProperties);
+ assignSender.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignSender.setStringProperty("ROLE", "SENDER");
+
+ senderConversation.send(senderControlTopic, assignSender);
+
+ // Assign the receivers role the receiving client.
+ Message assignReceiver = session.createMessage();
+ TestUtils.setPropertiesOnMessage(assignReceiver, testProperties);
+ assignReceiver.setStringProperty("CONTROL_TYPE", "ASSIGN_ROLE");
+ assignReceiver.setStringProperty("ROLE", "RECEIVER");
+
+ receiverConversation.send(receiverControlTopic, assignReceiver);
+
+ // Wait for the senders and receivers to confirm their roles.
+ senderConversation.receive();
+ receiverConversation.receive();
+
+ // Start the test.
+ Message start = session.createMessage();
+ start.setStringProperty("CONTROL_TYPE", "START");
+
+ senderConversation.send(senderControlTopic, start);
+
+ // Wait for the test sender to return its report.
+ Message senderReport = senderConversation.receive();
+ TestUtils.pause(500);
+
+ // Ask the receivers for its report.
+ Message statusRequest = session.createMessage();
+ statusRequest.setStringProperty("CONTROL_TYPE", "STATUS_REQUEST");
+
+ receiverConversation.send(receiverControlTopic, statusRequest);
+
+ // Wait for the receivers to send its report.
+ Message receiverReport = receiverConversation.receive();
+
+ // return new Message[] { senderReport, receiverReport };
+
+ // Apply assertions.
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("JMSException not handled.");
+ }
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td>
+ /// </table>
+ /// </summary>
+ public class TestCaseVector
+ {
+ /// <summary> The test case name. </summary>
+ private string testCase;
+
+ /// <summary> The test cycle number within the test case. </summary>
+ private int testCycleNumber;
+
+ public TestCaseVector(string testCase, int testCycleNumber)
+ {
+ this.testCase = testCase;
+ this.testCycleNumber = testCycleNumber;
+ }
+
+ public string getTestCase()
+ {
+ return testCase;
+ }
+
+ public int getTestCycleNumber()
+ {
+ return testCycleNumber;
+ }
+
+ public bool equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if ((o == null) || (getClass() != o.getClass()))
+ {
+ return false;
+ }
+
+ TestCaseVector that = (TestCaseVector) o;
+
+ if (testCycleNumber != that.testCycleNumber)
+ {
+ return false;
+ }
+
+ if ((testCase != null) ? (!testCase.equals(that.testCase)) : (that.testCase != null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = ((testCase != null) ? testCase.hashCode() : 0);
+ result = (31 * result) + testCycleNumber;
+
+ return result;
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// TestClientDetails is used to encapsulate information about an interop test client. It pairs together the unique
+ /// name of the client, and the route on which it listens to its control messages.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Record test clients control addresses together with their names.
+ /// </table>
+ /// </summary>
+ public class TestClientDetails
+ {
+ /// <summary> The test clients name. </summary>
+ public string clientName;
+
+ /// <summary> The routing key of the test clients control topic. </summary>
+ public string privateControlKey;
+
+ /// <summary>
+ /// Two TestClientDetails are considered to be equal, iff they have the same client name.
+ /// </summary>
+ /// <param name="o"> The object to compare to. </param>
+ ///
+ /// <return> <tt>If the object to compare to is a TestClientDetails equal to this one, <tt>false</tt> otherwise. </return>
+ public bool equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof TestClientDetails))
+ {
+ return false;
+ }
+
+ final TestClientDetails testClientDetails = (TestClientDetails) o;
+
+ return !((clientName != null) ? (!clientName.equals(testClientDetails.clientName))
+ : (testClientDetails.clientName != null));
+ }
+
+ /// <summary>
+ /// Computes a hash code compatible with the equals method; based on the client name alone.
+ /// </summary>
+ /// <return> A hash code for this. </return>
+ public int hashCode()
+ {
+ return ((clientName != null) ? clientName.hashCode() : 0);
+ }
+
+ /// <summary>
+ /// Outputs the client name and address details. Mostly used for debugging purposes.
+ /// </summary>
+ /// <return> The client name and address. </return>
+ public string ToString()
+ {
+ return "TestClientDetails: [ clientName = " + clientName + ", privateControlKey = " + privateControlKey + " ]";
+ }
+ }
+}
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using static Apache.Qpid.Integration.Tests.framework.MessagingTestConfigProperties.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.*;
+using javax.naming.Context;
+using javax.naming.InitialContext;
+using javax.naming.NamingException;
+
+using System.Collections.Generic.IDictionary;
+
+namespace Apache.Qpid.Integration.Tests.framework
+{
+ /// <summary>
+ /// TestUtils provides static helper methods that are usefull for writing tests against QPid.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create connections from test properties. <td> <see cref="MessagingTestConfigProperties"/>
+ /// <tr><td> Create test messages.
+ /// <tr><td> Inject a short pause in a test.
+ /// <tr><td> Serialize properties into a message.
+ /// </table>
+ /// </summary>
+ public class TestUtils
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestUtils));
+
+ /// <summary> Some dummy data to stuff all test messages with. </summary>
+ private static final byte[] MESSAGE_DATA_BYTES =
+ "Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- "
+ .getBytes();
+
+ /// <summary>
+ /// Establishes a JMS connection using a set of properties and qpids built in JNDI implementation. This is a simple
+ /// convenience method for code that does not anticipate handling connection failures. All exceptions that indicate
+ /// that the connection has failed, are wrapped as rutime exceptions, presumably handled by a top level failure
+ /// handler.
+ ///
+ /// <p/>This utility makes use of the following test parameters from <see cref="MessagingTestConfigProperties"/> to control
+ /// the connection creation:
+ ///
+ /// <p/><table>
+ /// <tr><td> <see cref="MessagingTestConfigProperties#USERNAME_PROPNAME"/> <td> The username.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#PASSWORD_PROPNAME"/> <td> The password.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#VIRTUAL_HOST_PROPNAME"/> <td> The virtual host name.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#BROKER_PROPNAME"/> <td> The broker URL.
+ /// <tr><td> <see cref="MessagingTestConfigProperties#CONNECTION_NAME"/> <td> The broker name in the initial context.
+ /// </summary>
+ /// <param name="messagingProps"> Connection properties as defined in <see cref="MessagingTestConfigProperties"/>. </param>
+ ///
+ /// <return> A JMS conneciton. </return>
+ public static Connection createConnection(ParsedProperties messagingProps)
+ {
+ log.debug("public static Connection createConnection(ParsedProperties messagingProps = " + messagingProps
+ + "): called");
+
+ try
+ {
+ // Extract the configured connection properties from the test configuration.
+ string conUsername = messagingProps.getProperty(USERNAME_PROPNAME);
+ string conPassword = messagingProps.getProperty(PASSWORD_PROPNAME);
+ string virtualHost = messagingProps.getProperty(VIRTUAL_HOST_PROPNAME);
+ string brokerUrl = messagingProps.getProperty(BROKER_PROPNAME);
+
+ // Create the broker connection url.
+ string connectionstring =
+ "amqp://" + conUsername + ":" + conPassword + "@clientid/" + ((virtualHost != null) ? virtualHost : "")
+ + "?brokerlist='" + brokerUrl + "'";
+
+ // Create properties to create the initial context from, and inject the connection factory configuration
+ // for the defined connection name into it.
+ messagingProps.setProperty("connectionfactory." + CONNECTION_NAME, connectionString);
+
+ Context ctx = new InitialContext(messagingProps);
+
+ ConnectionFactory cf = (ConnectionFactory) ctx.lookup(CONNECTION_NAME);
+
+ return cf.createConnection();
+ }
+ catch (NamingException e)
+ {
+ throw new RuntimeException("Got JNDI NamingException whilst looking up the connection factory.", e);
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not establish connection due to JMSException.", e);
+ }
+ }
+
+ /// <summary>
+ /// Creates a test message of the specified size, on the given JMS session.
+ /// </summary>
+ /// <param name="session"> The JMS session. </param>
+ /// <param name="size"> The size of the message in bytes. </param>
+ ///
+ /// <return> A bytes message, of the specified size, filled with dummy data. </return>
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through. </exception>
+ public static Message createTestMessageOfSize(Session session, int size) throws JMSException
+ {
+ BytesMessage message = session.createBytesMessage();
+
+ if (size > 0)
+ {
+ int div = MESSAGE_DATA_BYTES.length / size;
+ int mod = MESSAGE_DATA_BYTES.length % size;
+
+ for (int i = 0; i < div; i++)
+ {
+ message.writeBytes(MESSAGE_DATA_BYTES);
+ }
+
+ if (mod != 0)
+ {
+ message.writeBytes(MESSAGE_DATA_BYTES, 0, mod);
+ }
+ }
+
+ return message;
+ }
+
+ /// <summary>
+ /// Pauses for the specified length of time. In the event of failing to pause for at least that length of time
+ /// due to interuption of the thread, a RutimeException is raised to indicate the failure. The interupted status
+ /// of the thread is restores in that case. This method should only be used when it is expected that the pause
+ /// will be succesfull, for example in test code that relies on inejecting a pause.
+ /// </summary>
+ /// <param name="t"> The minimum time to pause for in milliseconds. </param>
+ public static void pause(long t)
+ {
+ try
+ {
+ Thread.sleep(t);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+
+ throw new RuntimeException("Failed to generate the requested pause length.", e);
+ }
+ }
+
+ /// <summary>
+ /// Sets properties of different types on a JMS Message.
+ /// </summary>
+ /// <param name="message"> The message to set properties on. </param>
+ /// <param name="properties"> The property name/value pairs to set. </param>
+ ///
+ /// <exception cref="javax.jms.JMSException"> All underlying JMSExceptions are allowed to fall through. </exception>
+ ///
+ /// <remarks> Move this helper method somewhere else. For example, TestUtils.</remarks>
+ public static void setPropertiesOnMessage(Message message, Map<Object, Object> properties) throws JMSException
+ {
+ for (Map.Entry<Object, Object> entry : properties.entrySet())
+ {
+ string name = entry.getKey().ToString();
+ Object value = entry.getValue();
+
+ message.setObjectProperty(name, value);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchFailureException.csx b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchFailureException.csx
new file mode 100644
index 0000000000..a2bcc49b97
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchFailureException.csx
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchFailureException represents failure of a <see cref="ClockSynchronizer"/> to achieve synchronization. For example,
+ /// this could be because a reference signal is not available, or because a desired accurracy cannot be attained.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Represent failure to achieve synchronization.
+ /// </table>
+ /// </summary>
+ public class ClockSynchFailureException extends Exception
+ {
+ /// <summary>
+ /// Creates a clock synch failure exception.
+ /// </summary>
+ /// <param name="message"> The detail message (which is saved for later retrieval by the <see cref="#getMessage()"/> method). </param>
+ /// <param name="cause"> The cause (which is saved for later retrieval by the <see cref="#getCause()"/> method). (A <tt>null</tt>
+ /// value is permitted, and indicates that the cause is nonexistent or unknown.)</param>
+ public ClockSynchFailureException(string message, Throwable cause)
+ {
+ super(message, cause);
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchThread.csx b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchThread.csx
new file mode 100644
index 0000000000..7d2fcae058
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchThread.csx
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.ShutdownHookable;
+using uk.co.thebadgerset.junit.extensions.Throttle;
+
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchThread is a convenient utility for running a thread that periodically synchronizes the clock against
+ /// a reference. Supply it with a <see cref="ClockSynchronizer"/> and a <see cref="Throttle"/> and it will continually keep the
+ /// clock up-to-date at a rate determined by the throttle.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Continually sychronize the clock at a throttled rate.
+ /// </table>
+ /// </summary>
+ public class ClockSynchThread extends Thread : ShutdownHookable
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(ClockSynchThread));
+
+ /// <summary> Holds the clock syncher for the synch thread. </summary>
+ private ClockSynchronizer clockSyncher;
+
+ /// <summary> Holds the throttle to limit the synch rate. </summary>
+ private Throttle throttle;
+
+ /// <summary> Flag to indicate that the periodic clock syncher should keep running. </summary>
+ bool doSynch = true;
+
+ /// <summary>
+ /// Creates a clock synchronizer thread from a clock synchronizer and a throttle.
+ /// </summary>
+ /// <param name="syncher"> The clock synchronizer. </param>
+ /// <param name="throttle"> The throttle. </param>
+ public ClockSynchThread(ClockSynchronizer syncher, Throttle throttle)
+ {
+ this.clockSyncher = syncher;
+ this.throttle = throttle;
+ }
+
+ /// <summary> Terminates the synchronization thread. </summary>
+ public void terminate()
+ {
+ doSynch = false;
+ }
+
+ /// <summary> Continually updates the clock, until <see cref="#terminate()"/> is called. </summary>
+ public void run()
+ {
+ while (doSynch)
+ {
+ // Perform a clock clockSynch.
+ try
+ {
+ // Wait controlled by the throttle before doing the next synch.
+ throttle.throttle();
+
+ clockSyncher.synch();
+ log.debug("Clock synched, delta = " + clockSyncher.getDelta() + ", epsilon = " + clockSyncher.getEpsilon()
+ + ".");
+ }
+ // Terminate the synch thread if the synchronization cannot be achieved.
+ catch (ClockSynchFailureException e)
+ {
+ log.debug("Cannot synchronize the clock (reference service may be down). Terminating the synch thread.");
+ doSynch = false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the clock synchronizer that is kept continually up to date.
+ /// </summary>
+ /// <return> The clock synchronizer that is kept continually up to date. </return>
+ public ClockSynchronizer getClockSyncher()
+ {
+ return clockSyncher;
+ }
+
+ /// <summary>
+ /// Supplies a shutdown hook, that terminates the synching thread.
+ /// </summary>
+ /// <return> The shut down hook. </return>
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doSynch = false;
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchronizer.csx b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchronizer.csx
new file mode 100644
index 0000000000..665b804b21
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/clocksynch/ClockSynchronizer.csx
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// ClockSynchronizer provides an interface through which two nodes may synchronize their clocks. It is expected that one
+ /// node will act as the reference clock, to which no delta need be applied, and the other node will act as the slave,
+ /// and which must apply a delta to its local clock to get a clock synchronized with the reference.
+ ///
+ /// <p/>The slave side will initiate the computation of a clock delta by calling the <see cref="#synch"/> method. This method
+ /// will not return until the delta has been computed, at which point there is a method to return its value, as well as
+ /// an estimate of the likely error (usually one standard deviation), in the synchronization. For convenience there is a
+ /// <see cref="#nanoTime"/> method to return the value of System.nanoTime() with the delta added in.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Trigger a clock synchronization.
+ /// <tr><td> Compute a clock delta to apply to the local clock.
+ /// <tr><td> Estimate the error in the synchronzation.
+ /// </table>
+ /// </summary>
+ public interface ClockSynchronizer
+ {
+ /// <summary>
+ /// The slave side should call this to copute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved. </exception>
+ public void synch() throws ClockSynchFailureException;
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta();
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon();
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime();
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/clocksynch/LocalClockSynchronizer.csx b/dotnet/Qpid.Integration.Tests/framework/clocksynch/LocalClockSynchronizer.csx
new file mode 100644
index 0000000000..1d19b92d90
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/clocksynch/LocalClockSynchronizer.csx
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+
+ /// <summary>
+ /// LocalClockSynchronizer is a fake <see cref="ClockSynchronizer"/> that simply calls System.nanoTime(). It exists so that
+ /// the same tests can be run distributed or locally, taking timings against the ClockSynchronizer interface without
+ /// being aware of how they are being run.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the local clock with no delta.
+ /// </table>
+ /// </summary>
+ public class LocalClockSynchronizer : ClockSynchronizer
+ {
+ /// <summary>
+ /// The slave side should call this to copute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="Apache.Qpid.Integration.Tests.framework.clocksynch.ClockSynchFailureException"> If synchronization cannot be achieved. </exception>
+ public void synch() throws ClockSynchFailureException
+ { }
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta()
+ {
+ return 0L;
+ }
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon()
+ {
+ return 0L;
+ }
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime()
+ {
+ return System.nanoTime();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/clocksynch/UDPClockSynchronizer.csx b/dotnet/Qpid.Integration.Tests/framework/clocksynch/UDPClockSynchronizer.csx
new file mode 100644
index 0000000000..98b02a043b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/clocksynch/UDPClockSynchronizer.csx
@@ -0,0 +1,453 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using uk.co.thebadgerset.junit.extensions.util.CommandLineParser;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using java.io.IOException;
+using java.net.*;
+using java.nio.ByteBuffer;
+using java.util.Arrays;
+
+namespace Apache.Qpid.Integration.Tests.framework.clocksynch
+{
+ /// <summary>
+ /// UDPClockSynchronizer is a <see cref="ClockSynchronizer"/> that sends pings as UDP datagrams, and uses the following simple
+ /// algorithm to perform clock synchronization:
+ ///
+ /// <ol>
+ /// <li>Slave initiates synchronization with a Reference clock.</li>
+ /// <li>Slave stamps current local time on a "time request" message and sends to the Reference.</li>
+ /// <li>Upon receipt by Reference, Reference stamps Reference-time and returns.</li>
+ /// <li>Upon receipt by Slave, Slave subtracts current time from sent time and divides by two to compute latency. It
+ /// subtracts current time from Reference time to determine Slave-Reference time delta and adds in the
+ /// half-latency to get the correct clock delta.</li>
+ /// <li>The first result is immediately used to update the clock since it will get the local clock into at least
+ /// the right ballpark.</li>
+ /// <li>The Slave repeats steps 2 through 4, 15 more times.</li>
+ /// <li>The results of the packet receipts are accumulated and sorted in lowest-latency to highest-latency order. The
+ /// median latency is determined by picking the mid-point sample from this ordered list.</li>
+ /// <li>All samples outside 1 standard-deviation from the median are discarded and the remaining samples
+ /// are averaged using an arithmetic mean.</li>
+ /// </ol>
+ ///
+ /// <p/>The use of UDP datagrams, instead of TCP based communication eliminates the hidden delays that TCP can introduce,
+ /// as it can transparently re-order or re-send packets, or introduce delays as packets are naggled.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Trigger a clock synchronziation.
+ /// <tr><td> Compute a clock delta to apply to the local clock.
+ /// <tr><td> Estimate the error in the synchronzation.
+ /// </table>
+ /// </summary>
+ public class UDPClockSynchronizer : ClockSynchronizer
+ {
+ /// <summary> Used for debugging. </summary>
+ // private static ILog log = LogManager.GetLogger(typeof(UDPClockSynchronizer));
+
+ /// <summary> Defines the timeout to use when waiting for responses to time requests. </summary>
+ private static final int TIMEOUT = 50;
+
+ /// <summary> The clock delta. </summary>
+ private long delta = 0L;
+
+ /// <summary> Holds an estimate of the clock error relative to the reference clock. </summary>
+ private long epsilon = 0L;
+
+ /// <summary> Holds the address of the reference clock. </summary>
+ private InetAddress referenceAddress;
+
+ /// <summary> Holds the socket to communicate with the reference service over. </summary>
+ private DatagramSocket socket;
+
+ /// <summary> Used to control the shutdown in the main test loop. </summary>
+ private static bool doSynch = true;
+
+ /// <summary>
+ /// Creates a clock synchronizer against the specified address for the reference.
+ /// </summary>
+ /// <param name="address"> The address of the reference service. </param>
+ public UDPClockSynchronizer(string address)
+ {
+ try
+ {
+ referenceAddress = InetAddress.getByName(address);
+ }
+ catch (UnknownHostException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// The slave side should call this to compute a clock delta with the reference.
+ /// </summary>
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved, due to unavailability of the reference
+ /// time service. </exception>
+ public void synch() throws ClockSynchFailureException
+ {
+ try
+ {
+ socket = new DatagramSocket();
+ socket.setSoTimeout(TIMEOUT);
+
+ // Synchronize on a single ping, to get the clock into the right ball-park.
+ synch(1);
+
+ // Synchronize on 15 pings.
+ synch(15);
+
+ // And again, for greater accuracy, on 31.
+ synch(31);
+
+ socket.close();
+ }
+ catch (SocketException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// Updates the synchronization delta by performing the specified number of reference clock requests.
+ /// </summary>
+ /// <param name="n"> The number of reference clock request cycles to perform. </param>
+ ///
+ /// <exception cref="ClockSynchFailureException"> If synchronization cannot be achieved, due to unavailability of the reference
+ /// time service. </exception>
+ protected void synch(int n) throws ClockSynchFailureException
+ {
+ // log.debug("protected void synch(int n = " + n + "): called");
+
+ // Create an array of deltas by performing n reference pings.
+ long[] delta = new long[n];
+
+ for (int i = 0; i < n; i++)
+ {
+ delta[i] = ping();
+ }
+
+ // Reject any deltas that are larger than 1 s.d. above the median.
+ long median = median(delta);
+ long sd = standardDeviation(delta);
+
+ // log.debug("median = " + median);
+ // log.debug("sd = " + sd);
+
+ long[] tempDeltas = new long[n];
+ int count = 0;
+
+ for (int i = 0; i < n; i++)
+ {
+ if ((delta[i] <= (median + sd)) && (delta[i] >= (median - sd)))
+ {
+ tempDeltas[count] = delta[i];
+ count++;
+ }
+ else
+ {
+ // log.debug("Rejected: " + delta[i]);
+ }
+ }
+
+ System.arraycopy(tempDeltas, 0, delta, 0, count);
+
+ // Estimate the delta as the mean of the remaining deltas.
+ this.delta += mean(delta);
+
+ // Estimate the error as the standard deviation of the remaining deltas.
+ this.epsilon = standardDeviation(delta);
+
+ // log.debug("this.delta = " + this.delta);
+ // log.debug("this.epsilon = " + this.epsilon);
+ }
+
+ /// <summary>
+ /// Performs a single reference clock request cycle and returns the estimated delta relative to the local clock.
+ /// This is computed as the half-latency of the requst cycle, plus the reference clock, minus the local clock.
+ /// </summary>
+ /// <return> The estimated clock delta. </return>
+ ///
+ /// <exception cref="ClockSynchFailureException"> If the reference service is not responding. </exception>
+ protected long ping() throws ClockSynchFailureException
+ {
+ // log.debug("protected long ping(): called");
+
+ try
+ {
+ byte[] buf = new byte[256];
+
+ bool timedOut = false;
+ long start = 0L;
+ long refTime = 0L;
+ long localTime = 0L;
+ long latency = 0L;
+ int failCount = 0;
+
+ // Keep trying the ping until it gets a response, or 10 tries in a row all time out.
+ do
+ {
+ // Start timing the request latency.
+ start = nanoTime();
+
+ // Get the reference time.
+ DatagramPacket packet =
+ new DatagramPacket(buf, buf.length, referenceAddress, UDPClockReference.REFERENCE_PORT);
+ socket.send(packet);
+ packet = new DatagramPacket(buf, buf.length);
+
+ timedOut = false;
+
+ try
+ {
+ socket.receive(packet);
+ }
+ catch (SocketTimeoutException e)
+ {
+ timedOut = true;
+ failCount++;
+
+ continue;
+ }
+
+ ByteBuffer bbuf = ByteBuffer.wrap(packet.getData());
+ refTime = bbuf.getLong();
+
+ // Stop timing the request latency.
+ localTime = nanoTime();
+ latency = localTime - start;
+
+ // log.debug("refTime = " + refTime);
+ // log.debug("localTime = " + localTime);
+ // log.debug("start = " + start);
+ // log.debug("latency = " + latency);
+ // log.debug("delta = " + ((latency / 2) + (refTime - localTime)));
+
+ }
+ while (timedOut && (failCount < 10));
+
+ // Fail completely if the fail count is too high.
+ if (failCount >= 10)
+ {
+ throw new ClockSynchFailureException("Clock reference not responding.", null);
+ }
+
+ // Estimate delta as (ref clock + half-latency) - local clock.
+ return (latency / 2) + (refTime - localTime);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /// <summary>
+ /// Gets the clock delta in nano seconds.
+ /// </summary>
+ /// <return> The clock delta in nano seconds. </return>
+ public long getDelta()
+ {
+ return delta;
+ }
+
+ /// <summary>
+ /// Gets an estimate of the clock error in nan seconds.
+ /// </summary>
+ /// <return> An estimate of the clock error in nan seconds. </return>
+ public long getEpsilon()
+ {
+ return epsilon;
+ }
+
+ /// <summary>
+ /// Gets the local clock time with any computed delta added in.
+ /// </summary>
+ /// <return> The local clock time with any computed delta added in. </return>
+ public long nanoTime()
+ {
+ return System.nanoTime() + delta;
+ }
+
+ /// <summary>
+ /// Computes the median of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The median. </return>
+ public static long median(long[] values)
+ {
+ // log.debug("public static long median(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long median;
+
+ // Order the list of values.
+ long[] orderedValues = new long[values.length];
+ System.arraycopy(values, 0, orderedValues, 0, values.length);
+ Arrays.sort(orderedValues);
+
+ // Check if the median is computed from a pair of middle value.
+ if ((orderedValues.length % 2) == 0)
+ {
+ int middle = orderedValues.length / 2;
+
+ median = (orderedValues[middle] + orderedValues[middle - 1]) / 2;
+ }
+ // The median is computed from a single middle value.
+ else
+ {
+ median = orderedValues[orderedValues.length / 2];
+ }
+
+ // log.debug("median = " + median);
+
+ return median;
+ }
+
+ /// <summary>
+ /// Computes the mean of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The mean. </return>
+ public static long mean(long[] values)
+ {
+ // log.debug("public static long mean(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long total = 0L;
+
+ for (long value : values)
+ {
+ total += value;
+ }
+
+ long mean = total / values.length;
+
+ // log.debug("mean = " + mean);
+
+ return mean;
+ }
+
+ /// <summary>
+ /// Computes the variance of series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The variance of the values. </return>
+ public static long variance(long[] values)
+ {
+ // log.debug("public static long variance(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long mean = mean(values);
+
+ long totalVariance = 0;
+
+ for (long value : values)
+ {
+ long diff = (value - mean);
+ totalVariance += diff/// diff;
+ }
+
+ long variance = totalVariance / values.length;
+
+ // log.debug("variance = " + variance);
+
+ return variance;
+ }
+
+ /// <summary>
+ /// Computes the standard deviation of a series of values.
+ /// </summary>
+ /// <param name="values"> The values. </param>
+ ///
+ /// <return> The standard deviation. </return>
+ public static long standardDeviation(long[] values)
+ {
+ // log.debug("public static long standardDeviation(long[] values = " + Arrays.ToString(values) + "): called");
+
+ long sd = Double.valueOf(Math.sqrt(variance(values))).longValue();
+
+ // log.debug("sd = " + sd);
+
+ return sd;
+ }
+
+ /// <summary>
+ /// For testing purposes. Supply address of reference clock as arg 1.
+ /// </summary>
+ /// <param name="args"> Address of reference clock as arg 1. </param>
+ public static void main(String[] args)
+ {
+ ParsedProperties options =
+ new ParsedProperties(CommandLineParser.processCommandLine(args,
+ new CommandLineParser(
+ new String[][]
+ {
+ { "1", "Address of clock reference service.", "address", "true" }
+ }), System.getProperties()));
+
+ string address = options.getProperty("1");
+
+ // Create a clock synchronizer.
+ UDPClockSynchronizer clockSyncher = new UDPClockSynchronizer(address);
+
+ // Set up a shutdown hook for it.
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
+ {
+ public void run()
+ {
+ doSynch = false;
+ }
+ }));
+
+ // Repeat the clock synching until the user kills the progam.
+ while (doSynch)
+ {
+ // Perform a clock clockSynch.
+ try
+ {
+ clockSyncher.synch();
+
+ // Print out the clock delta and estimate of the error.
+ System.out.println("Delta = " + clockSyncher.getDelta());
+ System.out.println("Epsilon = " + clockSyncher.getEpsilon());
+
+ try
+ {
+ Thread.sleep(250);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted status and terminate the loop.
+ Thread.currentThread().interrupt();
+ doSynch = false;
+ }
+ }
+ // Terminate if the reference time service is unavailable.
+ catch (ClockSynchFailureException e)
+ {
+ doSynch = false;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClient.csx b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClient.csx
new file mode 100644
index 0000000000..1126fec520
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClient.csx
@@ -0,0 +1,493 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+using org.apache.log4j.NDC;
+
+using Apache.Qpid.Integration.Tests.framework.MessagingTestConfigProperties;
+using Apache.Qpid.Integration.Tests.framework.TestUtils;
+using Apache.Qpid.Integration.Tests.framework.clocksynch.ClockSynchThread;
+using Apache.Qpid.Integration.Tests.framework.clocksynch.UDPClockSynchronizer;
+using org.apache.qpid.util.ReflectionUtils;
+using org.apache.qpid.util.ReflectionUtilsException;
+
+using uk.co.thebadgerset.junit.extensions.SleepThrottle;
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using javax.jms.*;
+
+using java.util.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// Implements a test client as described in the interop testing spec
+ /// (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
+ /// reacts to control message sequences send by the test <see cref="Coordinator"/>.
+ ///
+ /// <p/><table><caption>Messages Handled by TestClient</caption>
+ /// <tr><th> Message <th> Action
+ /// <tr><td> Invite(compulsory) <td> Reply with Enlist.
+ /// <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
+ /// <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches an enlisted test. Keep test parameters.
+ /// <tr><td> Start <td> Send test messages defined by test parameters. Send report on messages sent.
+ /// <tr><td> Status Request <td> Send report on messages received.
+ /// <tr><td> Terminate <td> Terminate the test client.
+ /// <tr><td> ClockSynch <td> Synch clock against the supplied UDP address.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Handle all incoming control messages. <td> <see cref="TestClientControlledTest"/>
+ /// <tr><td> Configure and look up test cases by name. <td> <see cref="TestClientControlledTest"/>
+ /// </table>
+ /// </summary>
+ public class TestClient : MessageListener
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestClient));
+
+ /// <summary> Used for reporting to the console. </summary>
+ private static ILog console = LogManager.GetLogger("CONSOLE");
+
+ /// <summary> Holds the default identifying name of the test client. </summary>
+ public static final string CLIENT_NAME = "java";
+
+ /// <summary> Holds the URL of the broker to run the tests on. </summary>
+ public static string brokerUrl;
+
+ /// <summary> Holds the virtual host to run the tests on. If <tt>null</tt>, then the default virtual host is used. </summary>
+ public static string virtualHost;
+
+ /// <summary>
+ /// Holds the test context properties that provides the default test parameters, plus command line overrides.
+ /// This is initialized with the default test parameters, to which command line overrides may be applied.
+ /// </summary>
+ public static ParsedProperties testContextProperties =
+ TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /// <summary> Holds all the test cases loaded from the classpath. </summary>
+ Map<String, TestClientControlledTest> testCases = new HashMap<String, TestClientControlledTest>();
+
+ /// <summary> Holds the test case currently being run by this client. </summary>
+ protected TestClientControlledTest currentTestCase;
+
+ /// <summary> Holds the connection to the broker that the test is being coordinated on. </summary>
+ protected Connection connection;
+
+ /// <summary> Holds the message producer to hold the test coordination over. </summary>
+ protected MessageProducer producer;
+
+ /// <summary> Holds the JMS controlSession for the test coordination. </summary>
+ protected Session session;
+
+ /// <summary> Holds the name of this client, with a default value. </summary>
+ protected string clientName = CLIENT_NAME;
+
+ /// <summary> This flag indicates that the test client should attempt to join the currently running test case on start up. </summary>
+ protected bool join;
+
+ /// <summary> Holds the clock synchronizer for the test node. </summary>
+ ClockSynchThread clockSynchThread;
+
+ /// <summary>
+ /// Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client
+ /// identifying name.
+ /// </summary>
+ /// <param name="pBrokerUrl"> The url of the broker to connect to. </param>
+ /// <param name="pVirtualHost"> The virtual host to conect to. </param>
+ /// <param name="clientName"> The client name to use. </param>
+ /// <param name="join"> Flag to indicate that this client should attempt to join running tests. </param>
+ public TestClient(string pBrokerUrl, string pVirtualHost, string clientName, bool join)
+ {
+ log.debug("public TestClient(string pBrokerUrl = " + pBrokerUrl + ", string pVirtualHost = " + pVirtualHost
+ + ", string clientName = " + clientName + ", bool join = " + join + "): called");
+
+ // Retain the connection parameters.
+ brokerUrl = pBrokerUrl;
+ virtualHost = pVirtualHost;
+ this.clientName = clientName;
+ this.join = join;
+ }
+
+ /// <summary>
+ /// The entry point for the interop test coordinator. This client accepts the following command line arguments:
+ ///
+ /// <p/><table>
+ /// <tr><td> -b <td> The broker URL. <td> Optional.
+ /// <tr><td> -h <td> The virtual host. <td> Optional.
+ /// <tr><td> -n <td> The test client name. <td> Optional.
+ /// <tr><td> name=value <td> Trailing argument define name/value pairs. Added to system properties. <td> Optional.
+ /// </table>
+ /// </summary>
+ /// <param name="args"> The command line arguments. </param>
+ public static void main(String[] args)
+ {
+ log.debug("public static void main(String[] args = " + Arrays.ToString(args) + "): called");
+ console.info("Qpid Distributed Test Client.");
+
+ // Override the default broker url to be localhost:5672.
+ testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
+
+ // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+ // and usage then exist if there are errors).
+ // Any options and trailing name=value pairs are also injected into the test context properties object,
+ // to override any defaults that may have been set up.
+ ParsedProperties options =
+ new ParsedProperties(uk.co.thebadgerset.junit.extensions.util.CommandLineParser.processCommandLine(args,
+ new uk.co.thebadgerset.junit.extensions.util.CommandLineParser(
+ new String[][]
+ {
+ { "b", "The broker URL.", "broker", "false" },
+ { "h", "The virtual host to use.", "virtual host", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ { "n", "The name of the test client.", "name", "false" },
+ { "j", "Join this test client to running test.", "false" }
+ }), testContextProperties));
+
+ // Extract the command line options.
+ string brokerUrl = options.getProperty("b");
+ string virtualHost = options.getProperty("h");
+ string clientName = options.getProperty("n");
+ clientName = (clientName == null) ? CLIENT_NAME : clientName;
+ bool join = options.getPropertyAsBoolean("j");
+
+ // To distinguish logging output set up an NDC on the client name.
+ NDC.push(clientName);
+
+ // Create a test client and start it running.
+ TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join);
+
+ // Use a class path scanner to find all the interop test case implementations.
+ // Hard code the test classes till the classpath scanner is fixed.
+ Collection<Class<? extends TestClientControlledTest>> testCaseClasses =
+ new ArrayList<Class<? extends TestClientControlledTest>>();
+ // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true);
+ testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun",
+ "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P",
+ "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub",
+ "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize",
+ "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize",
+ "Apache.Qpid.Integration.Tests.framework.distributedcircuit.TestClientCircuitEnd"));
+
+ try
+ {
+ client.start(testCaseClasses);
+ }
+ catch (Exception e)
+ {
+ log.error("The test client was unable to start.", e);
+ console.info(e.getMessage());
+ System.exit(1);
+ }
+ }
+
+ /// <summary>
+ /// Parses a list of class names, and loads them if they are available on the class path.
+ /// </summary>
+ /// <param name="classNames"> The names of the classes to load. </param>
+ ///
+ /// <return> A list of the loaded test case classes. </return>
+ public static IList<Class<? extends TestClientControlledTest>> loadTestCases(String... classNames)
+ {
+ IList<Class<? extends TestClientControlledTest>> testCases =
+ new LinkedList<Class<? extends TestClientControlledTest>>();
+
+ for (string className : classNames)
+ {
+ try
+ {
+ Class<?> cls = ReflectionUtils.forName(className);
+ testCases.add((Class<? extends TestClientControlledTest>) cls);
+ }
+ catch (ReflectionUtilsException e)
+ {
+ // Ignore, class could not be found, so test not available.
+ console.warn("Requested class " + className + " cannot be found, ignoring it.");
+ }
+ catch (ClassCastException e)
+ {
+ // Ignore, class was not of correct type to be a test case.
+ console.warn("Requested class " + className + " is not an instance of TestClientControlledTest.");
+ }
+ }
+
+ return testCases;
+ }
+
+ /// <summary>
+ /// Starts the interop test client running. This causes it to start listening for incoming test invites.
+ /// </summary>
+ /// <param name="testCaseClasses"> The classes of the available test cases. The test case names from these are used to </param>
+ /// matchin incoming test invites against.
+ ///
+ /// <exception cref="JMSException"> Any underlying JMSExceptions are allowed to fall through. </exception>
+ protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses) throws JMSException
+ {
+ log.debug("protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses = "
+ + testCaseClasses + "): called");
+
+ // Create all the test case implementations and index them by the test names.
+ for (Class<? extends TestClientControlledTest> nextClass : testCaseClasses)
+ {
+ try
+ {
+ TestClientControlledTest testCase = nextClass.newInstance();
+ testCases.put(testCase.getName(), testCase);
+ }
+ catch (InstantiationException e)
+ {
+ log.warn("Could not instantiate test case class: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ catch (IllegalAccessException e)
+ {
+ log.warn("Could not instantiate test case class due to illegal access: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ }
+
+ // Open a connection to communicate with the coordinator on.
+ connection = TestUtils.createConnection(testContextProperties);
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Set this up to listen for control messages.
+ Topic privateControlTopic = session.createTopic("iop.control." + clientName);
+ MessageConsumer consumer = session.createConsumer(privateControlTopic);
+ consumer.setMessageListener(this);
+
+ Topic controlTopic = session.createTopic("iop.control");
+ MessageConsumer consumer2 = session.createConsumer(controlTopic);
+ consumer2.setMessageListener(this);
+
+ // Create a producer to send replies with.
+ producer = session.createProducer(null);
+
+ // If the join flag was set, then broadcast a join message to notify the coordinator that a new test client
+ // is available to join the current test case, if it supports it. This message may be ignored, or it may result
+ // in this test client receiving a test invite.
+ if (join)
+ {
+ Message joinMessage = session.createMessage();
+
+ joinMessage.setStringProperty("CONTROL_TYPE", "JOIN");
+ joinMessage.setStringProperty("CLIENT_NAME", clientName);
+ joinMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ producer.send(controlTopic, joinMessage);
+ }
+
+ // Start listening for incoming control messages.
+ connection.start();
+ }
+
+ /// <summary>
+ /// Handles all incoming control messages.
+ /// </summary>
+ /// <param name="message"> The incoming message. </param>
+ public void onMessage(Message message)
+ {
+ NDC.push(clientName);
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ try
+ {
+ string controlType = message.getStringProperty("CONTROL_TYPE");
+ string testName = message.getStringProperty("TEST_NAME");
+
+ log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'");
+
+ // Check if the message is a test invite.
+ if ("INVITE".equals(controlType))
+ {
+ // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites
+ // for which test cases exist.
+ bool enlist = false;
+
+ if (testName != null)
+ {
+ log.debug("Got an invite to test: " + testName);
+
+ // Check if the requested test case is available.
+ TestClientControlledTest testCase = testCases.get(testName);
+
+ if (testCase != null)
+ {
+ log.debug("Found implementing class for test '" + testName + "', enlisting for it.");
+
+ // Check if the test case will accept the invitation.
+ enlist = testCase.acceptInvite(message);
+
+ log.debug("The test case "
+ + (enlist ? " accepted the invite, enlisting for it."
+ : " did not accept the invite, not enlisting."));
+
+ // Make the requested test case the current test case.
+ currentTestCase = testCase;
+ }
+ else
+ {
+ log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
+ }
+ }
+ else
+ {
+ log.debug("Got a compulsory invite, enlisting for it.");
+
+ enlist = true;
+ }
+
+ if (enlist)
+ {
+ // Reply with the client name in an Enlist message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending enlist message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ else
+ {
+ // Reply with the client name in an Decline message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending decline message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ }
+ else if ("ASSIGN_ROLE".equals(controlType))
+ {
+ // Assign the role to the current test case.
+ string roleName = message.getStringProperty("ROLE");
+
+ log.debug("Got a role assignment to role: " + roleName);
+
+ TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName);
+
+ currentTestCase.assignRole(role, message);
+
+ // Reply by accepting the role in an Accept Role message.
+ Message acceptRoleMessage = session.createMessage();
+ acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName);
+ acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE");
+ acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending accept role message '" + acceptRoleMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), acceptRoleMessage);
+ }
+ else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType))
+ {
+ if ("START".equals(controlType))
+ {
+ log.debug("Got a start notification.");
+
+ // Extract the number of test messages to send from the start notification.
+ int numMessages;
+
+ try
+ {
+ numMessages = message.getIntProperty("MESSAGE_COUNT");
+ }
+ catch (NumberFormatException e)
+ {
+ // If the number of messages is not specified, use the default of one.
+ numMessages = 1;
+ }
+
+ // Start the current test case.
+ currentTestCase.start(numMessages);
+ }
+ else
+ {
+ log.debug("Got a status request.");
+ }
+
+ // Generate the report from the test case and reply with it as a Report message.
+ Message reportMessage = currentTestCase.getReport(session);
+ reportMessage.setStringProperty("CLIENT_NAME", clientName);
+ reportMessage.setStringProperty("CONTROL_TYPE", "REPORT");
+ reportMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending report message '" + reportMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), reportMessage);
+ }
+ else if ("TERMINATE".equals(controlType))
+ {
+ console.info("Received termination instruction from coordinator.");
+
+ // Is a cleaner shutdown needed?
+ connection.close();
+ System.exit(0);
+ }
+ else if ("CLOCK_SYNCH".equals(controlType))
+ {
+ log.debug("Received clock synch command.");
+ string address = message.getStringProperty("ADDRESS");
+
+ log.debug("address = " + address);
+
+ // Re-create (if necessary) and start the clock synch thread to synch the clock every ten seconds.
+ if (clockSynchThread != null)
+ {
+ clockSynchThread.terminate();
+ }
+
+ SleepThrottle throttle = new SleepThrottle();
+ throttle.setRate(0.1f);
+
+ clockSynchThread = new ClockSynchThread(new UDPClockSynchronizer(address), throttle);
+ clockSynchThread.start();
+ }
+ else
+ {
+ // Log a warning about this but otherwise ignore it.
+ log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message);
+ }
+ }
+ catch (JMSException e)
+ {
+ // Log a warning about this, but otherwise ignore it.
+ log.warn("Got JMSException whilst handling message: " + message, e);
+ }
+ // Log any runtimes that fall through this message handler. These are fatal errors for the test client.
+ catch (RuntimeException e)
+ {
+ log.error("The test client message handler got an unhandled exception: ", e);
+ console.info("The message handler got an unhandled exception, terminating the test client.");
+ System.exit(1);
+ }
+ finally
+ {
+ NDC.pop();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientCircuitEnd.csx b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientCircuitEnd.csx
new file mode 100644
index 0000000000..5ac2c4bf5b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientCircuitEnd.csx
@@ -0,0 +1,312 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.*;
+using Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClientControlledTest;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+using uk.co.thebadgerset.junit.extensions.util.TestContextProperties;
+
+using javax.jms.*;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedcircuit
+{
+ /// <summary>
+ /// A TestClientCircuitEnd is a <see cref="CircuitEnd"/> that may be controlled from a
+ /// <see cref="Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClient"/>, and that forms a single publishing or
+ /// receiving end point in a distributed test <see cref="Apache.Qpid.Integration.Tests.framework.Circuit"/>.
+ ///
+ /// <p/>When operating in the SENDER role, this circuit end is capable of acting as part of the default circuit test
+ /// procedure (described in the class comment for <see cref="Apache.Qpid.Integration.Tests.framework.Circuit"/>). That is, it will
+ /// send the number of test messages required, using the test configuration parameters given in the test invite, and
+ /// return a report on its activities to the circuit controller.
+ ///
+ /// <p/>When operation in the RECEIVER role, this circuit end acts as part of the default circuit test procedure. It will
+ /// receive test messages, on the setup specified in the test configuration parameters, and keep count of the messages
+ /// received, and time taken to receive them. When requested by the circuit controller to provide a report, it will
+ /// return this report of its activities.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <td> <see cref="CircuitEnd"/>, <see cref="LocalCircuitFactory"/>, <see cref="TestUtils"/>
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <td> <see cref="CircuitEnd"/>, <see cref="LocalCircuitFactory"/>, <see cref="TestUtils"/>
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters. <td> <see cref="MessagingTestConfigProperties"/>
+ /// <tr><td> Adapt to assigned roles. <td> <see cref="TestClientControlledTest.Roles"/>
+ /// <tr><td> Perform test case actions. <td> <see cref="MessageMonitor"/>
+ /// <tr><td> Generate test reports. <td> <see cref="MessageMonitor"/>
+ /// </table>
+ /// </summary>
+ public class TestClientCircuitEnd : CircuitEnd, TestClientControlledTest
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestClientCircuitEnd));
+
+ /// <summary> Holds the test parameters. </summary>
+ ParsedProperties testProps;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The connection to send the test messages on. </summary>
+ private Connection connection;
+
+ /// <summary> Holds the circuit end for this test. </summary>
+ CircuitEnd circuitEnd;
+
+ /// <summary>
+ /// Holds a message monitor for this circuit end, either the monitor on the consumer when in RECEIVER more, or
+ /// a monitor updated on every message sent, when acting as a SENDER.
+ MessageMonitor messageMonitor;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ /// <return> The name of the test case that this implements. </return>
+ public string getName()
+ {
+ return "DEFAULT_CIRCUIT_TEST";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ /// <return> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </return>
+ /// </summary>
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public bool acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public bool acceptInvite(Message inviteMessage): called");
+
+ // Populate the test parameters from the invitation.
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ for (Object key : testProps.keySet())
+ {
+ string propName = (String) key;
+
+ // If the test parameters is overridden by the invitation, use it instead.
+ string inviteValue = inviteMessage.getStringProperty(propName);
+
+ if (inviteValue != null)
+ {
+ testProps.setProperty(propName, inviteValue);
+ log.debug("Test invite supplied override to " + propName + " of " + inviteValue);
+ }
+
+ }
+
+ // Accept the invitation.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ /// <param name="role"> The role to be played; sender or receivers. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role, Message assignRoleMessage): called");
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = 1; // assignRoleMessage.getIntProperty("NUM_MESSAGES");
+
+ // Connect using the test parameters.
+ connection = TestUtils.createConnection(testProps);
+
+ // Create a circuit end that matches the assigned role and test parameters.
+ LocalCircuitFactory circuitFactory = new LocalCircuitFactory();
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a message producer if so.
+ case SENDER:
+
+ // Set up the publisher.
+ circuitEnd = circuitFactory.createPublisherCircuitEnd(connection, testProps, 0L);
+
+ // Create a custom message monitor that will be updated on every message sent.
+ messageMonitor = new MessageMonitor();
+
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages.
+ case RECEIVER:
+
+ // Set up the receiver.
+ circuitEnd = circuitFactory.createReceiverCircuitEnd(connection, testProps, 0L);
+
+ // Use the message monitor from the consumer for stats.
+ messageMonitor = getMessageMonitor();
+
+ break;
+ }
+
+ // Reset all messaging stats for the report.
+ messageMonitor.reset();
+
+ connection.start();
+ }
+
+ /// <summary>
+ /// Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ /// </summary>
+ /// <param name="numMessages"> The number of test messages to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ ///
+ /// <remarks> Add round robin on destinations where multiple destinations being used.</remarks>
+ ///
+ /// <remarks> Add rate limiting when rate limit specified on publishers.</remarks>
+ ///
+ /// <remarks> Add Max pending message size protection. The receiver will have to send back some acks once in a while,
+ /// to notify the publisher that its messages are being consumed. This makes the safety valve harder to
+ /// implement than in the single VM case. For example, if the limit is 1000 messages, might want to get back
+ /// an ack every 500, to notify the publisher that it can keep sending. What about pub/sub tests? Will it be
+ /// necessary to wait for an ack from every receiver? This will have the effect of rate limiting to slow
+ /// consumers too.</remarks>
+ ///
+ /// <remarks> Add commits on every commit batch size boundary.</remarks>
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // If in the SENDER role, send the specified number of test messages to the circuit destinations.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = getSession().createMessage();
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ getProducer().send(testMessage);
+
+ // Increment the message count and timings.
+ messageMonitor.onMessage(testMessage);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ /// <param name="session"> The controlSession to create the report message in. </param>
+ /// <return> The report message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions resulting from creating the report are allowed to fall through. </exception>
+ public Message getReport(Session session) throws JMSException
+ {
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+
+ // Add the count of messages sent/received to the report.
+ report.setIntProperty("MESSAGE_COUNT", messageMonitor.getNumMessage());
+
+ // Add the time to send/receive messages to the report.
+ report.setLongProperty("TEST_TIME", messageMonitor.getTime());
+
+ // Add any exceptions detected to the report.
+
+ return report;
+ }
+
+ /// <summary>
+ /// Gets the message producer at this circuit end point.
+ /// </summary>
+ /// <return> The message producer at with this circuit end point. </return>
+ public MessageProducer getProducer()
+ {
+ return circuitEnd.getProducer();
+ }
+
+ /// <summary>
+ /// Gets the message consumer at this circuit end point.
+ /// </summary>
+ /// <return> The message consumer at this circuit end point. </return>
+ public MessageConsumer getConsumer()
+ {
+ return circuitEnd.getConsumer();
+ }
+
+ /// <summary>
+ /// Send the specified message over the producer at this end point.
+ /// </summary>
+ /// <param name="message"> The message to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMS exception occuring during the send is allowed to fall through. </exception>
+ public void send(Message message) throws JMSException
+ {
+ // Send the message on the circuit ends producer.
+ circuitEnd.send(message);
+ }
+
+ /// <summary>
+ /// Gets the JMS Session associated with this circuit end point.
+ /// </summary>
+ /// <return> The JMS Session associated with this circuit end point. </return>
+ public Session getSession()
+ {
+ return circuitEnd.getSession();
+ }
+
+ /// <summary>
+ /// Closes the message producers and consumers and the sessions, associated with this circuit end point.
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions occurring during the close are allowed to fall through. </exception>
+ public void close() throws JMSException
+ {
+ // Close the producer and consumer.
+ circuitEnd.close();
+ }
+
+ /// <summary>
+ /// Returns the message monitor for reporting on received messages on this circuit end.
+ /// </summary>
+ /// <return> The message monitor for this circuit end. </return>
+ public MessageMonitor getMessageMonitor()
+ {
+ return circuitEnd.getMessageMonitor();
+ }
+
+ /// <summary>
+ /// Returns the exception monitor for reporting on exceptions received on this circuit end.
+ /// </summary>
+ /// <return> The exception monitor for this circuit end. </return>
+ public ExceptionMonitor getExceptionMonitor()
+ {
+ return circuitEnd.getExceptionMonitor();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientControlledTest.csx b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientControlledTest.csx
new file mode 100644
index 0000000000..cfb06aa642
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/distributedcircuit/TestClientControlledTest.csx
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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.
+ *
+ */
+using javax.jms.JMSException;
+using javax.jms.Message;
+using javax.jms.MessageListener;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.distributedtesting
+{
+ /// <summary>
+ /// TestClientControlledTest provides an interface that classes implementing test cases to run on a <see cref="TestClient"/>
+ /// node can use. Implementations must be Java beans, that is, to provide a default constructor and to implement the
+ /// <see cref="#getName"/> method.
+ ///
+ /// <p/>The methods specified in this interface are called when the <see cref="TestClient"/> receives control instructions to
+ /// apply to the test. There are control instructions to present the test case with the test invite, so that it may
+ /// choose whether or not to participate in the test, assign the test to play the sender or receiver role, start the
+ /// test and obtain the test status report.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public interface TestClientControlledTest
+ {
+ /// <summary> Defines the possible test case roles that an interop test case can take on. </summary>
+ public enum Roles
+ {
+ /// <summary> Specifies the sender role. </summary>
+ SENDER,
+
+ /// <summary> Specifies the receivers role. </summary>
+ RECEIVER
+ }
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ /// <return> The name of the test case that this implements. </return>
+ public string getName();
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <return> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public bool acceptInvite(Message inviteMessage) throws JMSException;
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ /// <param name="role"> The role to be played; sender or receivers. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException;
+
+ /// <summary>
+ /// Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ /// </summary>
+ /// <param name="numMessages"> The number of test messages to send. </param>
+ ///
+ /// <exception cref="JMSException"> Any JMSException resulting from reading the message are allowed to fall through. </exception>
+ public void start(int numMessages) throws JMSException;
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ /// <param name="session"> The controlSession to create the report message in. </param>
+ ///
+ /// <return> The report message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSExceptions resulting from creating the report are allowed to fall through. </exception>
+ public Message getReport(Session session) throws JMSException;
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalCircuitImpl.csx b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalCircuitImpl.csx
new file mode 100644
index 0000000000..0594e4d781
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalCircuitImpl.csx
@@ -0,0 +1,290 @@
+/*
+ *
+ * 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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.*;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// LocalCircuitImpl provides an implementation of the test circuit. This is a local only circuit implementation that
+ /// supports a single producer/consumer on each end of the circuit, with both ends of the circuit on the same JVM.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the publishing and receiving ends of a test messaging circuit.
+ /// <td> <see cref="LocalPublisherImpl"/>, <see cref="LocalReceiverImpl"/>
+ /// <tr><td> Start the circuit running.
+ /// <tr><td> Close the circuit down.
+ /// <tr><td> Take a reading of the circuits state.
+ /// <tr><td> Apply assertions against the circuits state. <td> <see cref="Assertion"/>
+ /// <tr><td> Send test messages over the circuit.
+ /// <tr><td> Perform the default test procedure on the circuit.
+ /// <tr><td> Provide access to connection and controlSession exception monitors. <td> <see cref="ExceptionMonitor"/>
+ /// </table>
+ /// </summary>
+ public class LocalCircuitImpl : Circuit
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(LocalCircuitImpl));
+
+ /// <summary> Holds the test configuration for the circuit. </summary>
+ private ParsedProperties testProps;
+
+ /// <summary> Holds the publishing end of the circuit. </summary>
+ private LocalPublisherImpl publisher;
+
+ /// <summary> Holds the receiving end of the circuit. </summary>
+ private LocalReceiverImpl receiver;
+
+ /// <summary> Holds the connection for the publishing end of the circuit. </summary>
+ private Connection connection;
+
+ /// <summary> Holds the exception listener for the connection on the publishing end of the circuit. </summary>
+ private ExceptionMonitor connectionExceptionMonitor;
+
+ /// <summary> Holds the exception listener for the controlSession on the publishing end of the circuit. </summary>
+ private ExceptionMonitor exceptionMonitor;
+
+ /// <summary>
+ /// Creates a test circuit using the specified test parameters. The publisher, receivers, connection and
+ /// connection monitor must already have been created, to assemble the circuit.
+ /// </summary>
+ /// <param name="testProps"> The test parameters. </param>
+ /// <param name="publisher"> The test publisher. </param>
+ /// <param name="receiver"> The test receivers. </param>
+ /// <param name="connection"> The connection. </param>
+ /// <param name="connectionExceptionMonitor"> The connection exception monitor. </param>
+ public LocalCircuitImpl(ParsedProperties testProps, LocalPublisherImpl publisher, LocalReceiverImpl receiver,
+ Connection connection, ExceptionMonitor connectionExceptionMonitor)
+ {
+ this.testProps = testProps;
+ this.publisher = publisher;
+ this.receiver = receiver;
+ this.connection = connection;
+ this.connectionExceptionMonitor = connectionExceptionMonitor;
+ this.exceptionMonitor = new ExceptionMonitor();
+
+ // Set this as the parent circuit on the publisher and receivers.
+ publisher.setCircuit(this);
+ receiver.setCircuit(this);
+ }
+
+ /// <summary>
+ /// Gets the interface on the publishing end of the circuit.
+ /// </summary>
+ /// <return> The publishing end of the circuit. </return>
+ public Publisher getPublisher()
+ {
+ return publisher;
+ }
+
+ /// <summary>
+ /// Gets the local publishing circuit end, for direct manipulation.
+ /// </summary>
+ /// <return> The local publishing circuit end. </return>
+ public CircuitEnd getLocalPublisherCircuitEnd()
+ {
+ return publisher;
+ }
+
+ /// <summary>
+ /// Gets the interface on the receiving end of the circuit.
+ /// </summary>
+ /// <return> The receiving end of the circuit. </return>
+ public Receiver getReceiver()
+ {
+ return receiver;
+ }
+
+ /// <summary>
+ /// Gets the local receiving circuit end, for direct manipulation.
+ /// </summary>
+ /// <return> The local receiving circuit end. </return>
+ public CircuitEnd getLocalReceiverCircuitEnd()
+ {
+ return receiver;
+ }
+
+ /// <summary>
+ /// Checks the test circuit. The effect of this is to gather the circuits state, for both ends of the circuit,
+ /// into a report, against which assertions may be checked.
+ /// </summary>
+ public void check()
+ { }
+
+ /// <summary>
+ /// Applied a list of assertions against the test circuit. The <see cref="#check()"/> method should be called before doing
+ /// this, to ensure that the circuit has gathered its state into a report to assert against.
+ /// </summary>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> applyAssertions(List<Assertion> assertions)
+ {
+ IList<Assertion> failures = new LinkedList<Assertion>();
+
+ for (Assertion assertion : assertions)
+ {
+ if (!assertion.apply())
+ {
+ failures.add(assertion);
+ }
+ }
+
+ return failures;
+ }
+
+ /// <summary> Connects and starts the circuit. After this method is called the circuit is ready to send messages. </summary>
+ public void start()
+ { }
+
+ /// <summary> Closes the circuit. All associated resources are closed. </summary>
+ public void close()
+ {
+ try
+ {
+ publisher.close();
+ receiver.close();
+ connection.close();
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Got JMSException during close:" + e.getMessage(), e);
+ }
+ }
+
+ /// <summary> Sends a message on the test circuit. The exact nature of the message sent is controlled by the test parameters. </summary>
+ protected void send()
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ bool transactional = props.getPublisherTransacted();
+ bool rollback = props.getRollbackPublisher();
+
+ // Send a message through the publisher and log any exceptions raised.
+ try
+ {
+ CircuitEnd end = getLocalPublisherCircuitEnd();
+
+ end.send(createTestMessage(end));
+
+ if (rollback)
+ {
+ end.getSession().rollback();
+ }
+ else if (transactional)
+ {
+ end.getSession().commit();
+ }
+ }
+ catch (JMSException e)
+ {
+ exceptionMonitor.onException(e);
+ }
+ }
+
+ /// <summary>
+ /// Runs the default test procedure against the circuit, and checks that all of the specified assertions hold. The
+ /// outline of the default test procedure is:
+ ///
+ /// <p/><pre>
+ /// Start the circuit.
+ /// Send test messages.
+ /// Request a status report.
+ /// Assert conditions on the publishing end of the circuit.
+ /// Assert conditions on the receiving end of the circuit.
+ /// Close the circuit.
+ /// Pass with no failed assertions or fail with a list of failed assertions.
+ /// </pre>
+ /// </summary>
+ /// <param name="numMessages"> The number of messages to send using the default test procedure. </param>
+ /// <param name="assertions"> The list of assertions to apply. </param>
+ /// <return> Any assertions that failed. </return>
+ public IList<Assertion> test(int numMessages, List<Assertion> assertions)
+ {
+ // Start the test circuit.
+ start();
+
+ // Send the requested number of test messages.
+ for (int i = 0; i < numMessages; i++)
+ {
+ send();
+ }
+
+ // Inject a short pause to allow time for exceptions to come back asynchronously.
+ TestUtils.pause(500L);
+
+ // Request a status report.
+ check();
+
+ // Clean up the publisher/receivers/controlSession/connections.
+ close();
+
+ // Apply all of the requested assertions, keeping record of any that fail.
+ IList<Assertion> failures = applyAssertions(assertions);
+
+ // Return any failed assertions to the caller.
+ return failures;
+ }
+
+ /// <summary>
+ /// Creates a message with the properties defined as per the test parameters.
+ /// </summary>
+ /// <param name="client"> The circuit end to create the message on. </param>
+ ///
+ /// <return> The test message. </return>
+ ///
+ /// <exception cref="JMSException"> Any JMSException occurring during creation of the message is allowed to fall through. </exception>
+ private Message createTestMessage(CircuitEnd client) throws JMSException
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ return TestUtils.createTestMessageOfSize(client.getSession(), props.getMessageSize());
+ }
+
+ /// <summary>
+ /// Gets the exception monitor for the publishing ends connection.
+ /// </summary>
+ /// <return> The exception monitor for the publishing ends connection. </return>
+ public ExceptionMonitor getConnectionExceptionMonitor()
+ {
+ return connectionExceptionMonitor;
+ }
+
+ /// <summary>
+ /// Gets the exception monitor for the publishing ends controlSession.
+ /// </summary>
+ /// <return> The exception monitor for the publishing ends controlSession. </return>
+ public ExceptionMonitor getExceptionMonitor()
+ {
+ return exceptionMonitor;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalPublisherImpl.csx b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalPublisherImpl.csx
new file mode 100644
index 0000000000..ecc94067ae
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalPublisherImpl.csx
@@ -0,0 +1,164 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.MessageConsumer;
+using javax.jms.MessageProducer;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// Provides an implementation of the <see cref="Publisher"/> interface and wraps a single message producer and consumer on
+ /// a single controlSession, as a <see cref="CircuitEnd"/>. A local publisher also acts as a circuit end, because for a locally
+ /// located circuit the assertions may be applied directly, there does not need to be any inter-process messaging
+ /// between the publisher and its single circuit end, in order to ascertain its status.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <tr><td> Provide assertion that the publisher received no exceptions.
+ /// <tr><td> Provide assertion that the publisher received a no consumers error code.
+ /// <tr><td> Provide assertion that the publisher received a no route error code.
+ /// </table>
+ /// </summary>
+ public class LocalPublisherImpl extends CircuitEndBase : Publisher
+ {
+ /// <summary> Holds a reference to the containing circuit. </summary>
+ protected LocalCircuitImpl circuit;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public LocalPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ /// </summary>
+ /// <param name="end"> The circuit end base implementation to take producers and consumers from. </param>
+ public LocalPublisherImpl(CircuitEndBase end)
+ {
+ super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor());
+ }
+
+ /// <summary> Provides an assertion that the publisher encountered no exceptions. </summary>
+ ///
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the publisher encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public bool apply()
+ {
+ bool passed = true;
+ ExceptionMonitor sessionExceptionMonitor = circuit.getExceptionMonitor();
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertNoExceptions())
+ {
+ passed = false;
+
+ addError("Was expecting no exceptions.\n");
+ addError("Got the following exceptions on the connection, "
+ + circuit.getConnectionExceptionMonitor());
+ }
+
+ if (!sessionExceptionMonitor.assertNoExceptions())
+ {
+ passed = false;
+
+ addError("Was expecting no exceptions.\n");
+ addError("Got the following exceptions on the producer, " + circuit.getExceptionMonitor());
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the publisher got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. </param>
+ ///
+ /// <return> An assertion that the publisher got a given exception during the test. </return>
+ public Assertion exceptionAssertion(ParsedProperties testProps, final Class<? extends Exception> exceptionClass)
+ {
+ return new AssertionBase()
+ {
+ public bool apply()
+ {
+ bool passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertExceptionOfType(exceptionClass))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + exceptionClass.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /// <summary>
+ /// Sets the contianing circuit.
+ /// </summary>
+ /// <param name="circuit"> The containing circuit. </param>
+ public void setCircuit(LocalCircuitImpl circuit)
+ {
+ this.circuit = circuit;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalReceiverImpl.csx b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalReceiverImpl.csx
new file mode 100644
index 0000000000..b174a4c912
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/localcircuit/LocalReceiverImpl.csx
@@ -0,0 +1,137 @@
+/*
+ *
+ * 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.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.*;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.MessageConsumer;
+using javax.jms.MessageProducer;
+using javax.jms.Session;
+
+namespace Apache.Qpid.Integration.Tests.framework.localcircuit
+{
+ /// <summary>
+ /// Provides an implementation of the <see cref="Receiver"/> interface that wraps a single message producer and consumer on
+ /// a single controlSession, as a <see cref="CircuitEnd"/>. A local receiver also acts as a circuit end, because for a locally
+ /// located circuit the assertions may be applied directly, there does not need to be any inter process messaging
+ /// between the publisher and its single circuit end, in order to ascertain its status.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Provide a message producer for sending messages.
+ /// <tr><td> Provide a message consumer for receiving messages.
+ /// <tr><td> Provide assertion that the receivers received no exceptions.
+ /// <tr><td> Provide assertion that the receivers received all test messages sent to it.
+ /// </table>
+ /// </summary>
+ public class LocalReceiverImpl extends CircuitEndBase : Receiver
+ {
+ /// <summary> Holds a reference to the containing circuit. </summary>
+ private LocalCircuitImpl circuit;
+
+ /// <summary>
+ /// Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ /// for messages and exceptions received by the circuit end.
+ /// </summary>
+ /// <param name="producer"> The message producer for the circuit end point. </param>
+ /// <param name="consumer"> The message consumer for the circuit end point. </param>
+ /// <param name="session"> The controlSession for the circuit end point. </param>
+ /// <param name="messageMonitor"> The monitor to notify of all messages received by the circuit end. </param>
+ /// <param name="exceptionMonitor"> The monitor to notify of all exceptions received by the circuit end. </param>
+ public LocalReceiverImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /// <summary>
+ /// Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ /// </summary>
+ /// <param name="end"> The circuit end base implementation to take producers and consumers from. </param>
+ public LocalReceiverImpl(CircuitEndBase end)
+ {
+ super(end.getProducer(), end.getConsumer(), end.getSession(), end.getMessageMonitor(), end.getExceptionMonitor());
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers encountered no exceptions.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers encountered no exceptions. </return>
+ public Assertion noExceptionsAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the AMQP channel was forcibly closed by an error condition.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the AMQP channel was forcibly closed by an error condition. </return>
+ public Assertion channelClosedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got all messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got all messages that were sent to it. </return>
+ public Assertion allMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receivers got none of the messages that were sent to it.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ ///
+ /// <return> An assertion that the receivers got none of the messages that were sent to it. </return>
+ public Assertion noMessagesReceivedAssertion(ParsedProperties testProps)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Provides an assertion that the receiver got a given exception during the test.
+ /// </summary>
+ /// <param name="testProps"> The test configuration properties. </param>
+ /// <param name="exceptionClass"> The exception class to check for. <return> An assertion that the receiver got a given exception during the test. </return> </param>
+ public Assertion exceptionAssertion(ParsedProperties testProps, Class<? extends Exception> exceptionClass)
+ {
+ return new NotApplicableAssertion(testProps);
+ }
+
+ /// <summary>
+ /// Sets the contianing circuit.
+ /// </summary>
+ /// <param name="circuit"> The containing circuit. </param>
+ public void setCircuit(LocalCircuitImpl circuit)
+ {
+ this.circuit = circuit;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/sequencers/BaseCircuitFactory.csx b/dotnet/Qpid.Integration.Tests/framework/sequencers/BaseCircuitFactory.csx
new file mode 100644
index 0000000000..79ddfd878f
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/sequencers/BaseCircuitFactory.csx
@@ -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.
+ *
+ */
+using log4net;
+
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using org.apache.qpid.util.ConversationFactory;
+
+using System.Collections.Generic.LinkedList;
+using System.Collections.Generic.IList;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// BaseCircuitFactory provides some functionality common to all <see cref="CircuitFactory"/>s, such as the details of
+ /// all <see cref="Apache.Qpid.Integration.Tests.framework.distributedtesting.TestClient"/>s that make up the end-points of
+ /// the circuits that the factory creates, and an active <see cref="ConversationFactory"/> that can be used to generate
+ /// control conversations with those circuit end-points.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Hold the details of the sending and receiving end-points to create circuits from.
+ /// <tr><td> Provide a conversation factory to create control conversations with the end-points.
+ /// </table>
+ /// </summary>
+ public abstract class BaseCircuitFactory : CircuitFactory
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(BaseCircuitFactory));
+
+ /// <summary> Holds the contact details for the sending test client. </summary>
+ protected TestClientDetails sender;
+
+ /// <summary> Holds the contact details for the receving test client. </summary>
+ protected IList<TestClientDetails> receivers = new LinkedList<TestClientDetails>();
+
+ /// <summary> Holds the conversation factory over which to coordinate the test. </summary>
+ protected ConversationFactory conversationFactory;
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(Properties testProperties)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender)
+ {
+ log.debug("public void setSender(TestClientDetails sender = " + sender + "): called");
+
+ this.sender = sender;
+ }
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver)
+ {
+ log.debug("public void setReceiver(TestClientDetails receivers = " + receiver + "): called");
+
+ this.receivers.add(receiver);
+ }
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender()
+ {
+ return sender;
+ }
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers()
+ {
+ return receivers;
+ }
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ this.conversationFactory = conversationFactory;
+ }
+
+ /// <summary>
+ /// Provides the conversation factory for providing the distributed test sequencing conversations over the test
+ /// connection.
+ /// </summary>
+ /// <return> The conversation factory to create test sequencing conversations with. </return>
+ public ConversationFactory getConversationFactory()
+ {
+ return conversationFactory;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.cs b/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.cs
new file mode 100644
index 0000000000..4be08c3f38
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.cs
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework;
+//using org.apache.qpid.util.ConversationFactory;
+
+//using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+//using javax.jms.JMSException;
+//using javax.jms.Message;
+
+using System.Collections.Generic;//.IList;
+//using System.Collections.Generic.IDictionary;
+//using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// A CircuitFactory is responsibile for creating test circuits appropriate to the context that a test case is
+ /// running in, and providing an implementation of a standard test procedure over a test circuit.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a standard test procedure over a test circuit.
+ /// <tr><td> Construct test circuits appropriate to a tests context.
+ /// </table>
+ /// </summary>
+ public interface CircuitFactory
+ {
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ ///
+ /// <return> A test circuit. </return>
+ Circuit CreateCircuit(TestModel testProperties);
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ void SetSender(TestClientDetails sender);
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ void SetReceiver(TestClientDetails receiver);
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ TestClientDetails GetSender();
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ IList<TestClientDetails> GetReceivers();
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ //void setConversationFactory(ConversationFactory conversationFactory);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.csx b/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.csx
new file mode 100644
index 0000000000..26632266a4
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/framework/sequencers/CircuitFactory.csx
@@ -0,0 +1,99 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using Apache.Qpid.Integration.Tests.framework.Assertion;
+using Apache.Qpid.Integration.Tests.framework.Circuit;
+using Apache.Qpid.Integration.Tests.framework.TestClientDetails;
+using org.apache.qpid.util.ConversationFactory;
+
+using uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
+
+using javax.jms.JMSException;
+using javax.jms.Message;
+
+using System.Collections.Generic.IList;
+using System.Collections.Generic.IDictionary;
+using java.util.Properties;
+
+namespace Apache.Qpid.Integration.Tests.framework.sequencers
+{
+ /// <summary>
+ /// A CircuitFactory is responsibile for creating test circuits appropriate to the context that a test case is
+ /// running in, and providing an implementation of a standard test procedure over a test circuit.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Provide a standard test procedure over a test circuit.
+ /// <tr><td> Construct test circuits appropriate to a tests context.
+ /// </table>
+ /// </summary>
+ public interface CircuitFactory
+ {
+ /// <summary>
+ /// Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ /// begining the test, gathering the test reports from the participants, and checking for assertion failures against
+ /// the test reports.
+ /// </summary>
+ /// <param name="testCircuit"> The test circuit. </param>
+ /// <param name="assertions"> The list of assertions to apply to the test circuit. </param>
+ /// <param name="testProperties"> The test case definition. </param>
+ ///
+ /// @deprecated Use test circuits and Circuit.test instead.
+ public void sequenceTest(Circuit testCircuit, IList<Assertion> assertions, Properties testProperties);
+
+ /// <summary>
+ /// Creates a test circuit for the test, configered by the test parameters specified.
+ /// </summary>
+ /// <param name="testProperties"> The test parameters. </param>
+ ///
+ /// <return> A test circuit. </return>
+ public Circuit createCircuit(ParsedProperties testProperties);
+
+ /// <summary>
+ /// Sets the sender test client to coordinate the test with.
+ /// </summary>
+ /// <param name="sender"> The contact details of the sending client in the test. </param>
+ public void setSender(TestClientDetails sender);
+
+ /// <summary>
+ /// Sets the receiving test client to coordinate the test with.
+ /// </summary>
+ /// <param name="receiver"> The contact details of the sending client in the test. </param>
+ public void setReceiver(TestClientDetails receiver);
+
+ /// <summary>
+ /// Supplies the sending test client.
+ /// </summary>
+ /// <return> The sending test client. </return>
+ public TestClientDetails getSender();
+
+ /// <summary>
+ /// Supplies the receiving test client.
+ /// </summary>
+ /// <return> The receiving test client. </return>
+ public IList<TestClientDetails> getReceivers();
+
+ /// <summary>
+ /// Accepts the conversation factory over which to hold the test coordinating conversation.
+ /// </summary>
+ /// <param name="conversationFactory"> The conversation factory to coordinate the test over. </param>
+ public void setConversationFactory(ConversationFactory conversationFactory);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/interactive/FailoverTest.cs b/dotnet/Qpid.Integration.Tests/interactive/FailoverTest.cs
new file mode 100644
index 0000000000..142ac40b27
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interactive/FailoverTest.cs
@@ -0,0 +1,397 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interactive
+{
+ [TestFixture, Category("Interactive")]
+ public class FailoverTest : IConnectionListener
+ {
+ private static readonly ILog _log = LogManager.GetLogger(typeof(FailoverTest));
+
+ /// <summary>Specifies the number of times to run the test cycle.</summary>
+ const int NUM_MESSAGES = 10;
+
+ /// <summary>Determines how many messages to send within each commit.</summary>
+ const int COMMIT_BATCH_SIZE = 1;
+
+ /// <summary>Specifies the duration of the pause to place between each message sent in the test.</summary>
+ //const int SLEEP_MILLIS = 1;
+
+ /// <summary>Specified the maximum time in milliseconds to wait for the test to complete.</summary>
+ const int TIMEOUT = 10000;
+
+ /// <summary>Defines the number of test messages to send, before prompting the user to fail a broker.</summary>
+ const int FAIL_POINT = 5;
+
+ /// <summary>Specified the ack mode to use for the test.</summary>
+ AcknowledgeMode _acknowledgeMode = AcknowledgeMode.AutoAcknowledge;
+
+ /// <summary>Determines whether this test runs transactionally or not. </summary>
+ bool transacted = false;
+
+ /// <summary>Holds the connection to run the test over.</summary>
+ AMQConnection _connection;
+
+ /// <summary>Holds the channel for the test message publisher. </summary>
+ IChannel publishingChannel;
+
+ /// <summary>Holds the test message publisher. </summary>
+ IMessagePublisher publisher;
+
+ /// <summary>Used to keep count of the number of messages sent. </summary>
+ int messagesSent;
+
+ /// <summary>Used to keep count of the number of messages received. </summary>
+ int messagesReceived;
+
+ /// <summary>Used to wait for test completion on. </summary>
+ private static object testComplete = new Object();
+
+ /// <summary>Used to wait for failover completion on. </summary>
+ private static object failoverComplete = new Object();
+
+ bool failedOver=false;
+
+ /// <summary>Used to record the extra message count (1) if the message sent right after failover actually made it to the new broker.</summary>
+ int _extraMessage = 0;
+
+ /// <summary>
+ /// Creates the test connection with a fail-over set up, and a producer/consumer pair on that connection.
+ /// </summary>
+ /// [SetUp]
+ public void Init(IConnectionInfo connectionInfo)
+ {
+ //log4net.Config.BasicConfigurator.Configure();
+ // Reset all counts.
+ messagesSent = 0;
+ messagesReceived = 0;
+ failedOver=false;
+ _extraMessage = 0;
+
+ PromptAndWait("Ensure both brokers are running, then press Enter");
+
+ // Create a connection for the test.
+ _connection = new AMQConnection(connectionInfo);
+ _connection.ConnectionListener = this;
+
+ // Create a consumer to receive the test messages.
+ IChannel receivingChannel = _connection.CreateChannel(false, _acknowledgeMode);
+
+ string queueName = receivingChannel.GenerateUniqueName();
+ receivingChannel.DeclareQueue(queueName, false, true, true);
+ receivingChannel.Bind(queueName, "amq.direct", queueName);
+
+ IMessageConsumer consumer = receivingChannel.CreateConsumerBuilder(queueName)
+ .WithPrefetchLow(30)
+ .WithPrefetchHigh(60).Create();
+
+ consumer.OnMessage = new MessageReceivedDelegate(OnMessage);
+ _connection.Start();
+
+ // Create a publisher to send the test messages.
+ publishingChannel = _connection.CreateChannel(transacted, AcknowledgeMode.NoAcknowledge);
+ publisher = publishingChannel.CreatePublisherBuilder()
+ .WithRoutingKey(queueName)
+ .Create();
+
+ _log.Debug("connection = " + _connection);
+ _log.Debug("connectionInfo = " + connectionInfo);
+ _log.Debug("connection.AsUrl = " + _connection.toURL());
+ _log.Debug("AcknowledgeMode is " + _acknowledgeMode);
+ }
+
+ /// <summary>
+ /// Clean up the test connection.
+ /// </summary>
+ [TearDown]
+ public virtual void Shutdown()
+ {
+ if (!failedOver)
+ {
+ Assert.Fail("The failover callback never occured.");
+ }
+
+ Console.WriteLine("Test done shutting down");
+ Thread.Sleep(2000);
+ _connection.Close();
+ }
+
+ /// <summary>
+ /// Runs a failover test, building up the connection information from its component parts. In particular the brokers
+ /// to fail between are seperately added into the connection info.
+ /// </summary>
+ /*[Test]
+ public void TestWithBasicInfo()
+ {
+ _log.Debug("public void TestWithBasicInfo(): called");
+
+ // Manually create the connection parameters.
+ QpidConnectionInfo connectionInfo = new QpidConnectionInfo();
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo("amqp", "localhost", 5672, false));
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo("amqp", "localhost", 5673, false));
+
+ Init(connectionInfo);
+ DoFailoverTest();
+ }*/
+
+ /// <summary>
+ /// Runs a failover test, with the failover configuration specified in the Qpid connection URL format.
+ /// </summary>
+ [Test]
+ public void TestWithUrl()
+ {
+ _log.Debug("public void runTestWithUrl(): called");
+
+ // Parse the connection parameters from a URL.
+ String clientId = "failover" + DateTime.Now.Ticks;
+ string defaultUrl = "amqp://guest:guest@" + clientId + "/test" +
+ "?brokerlist='tcp://localhost:9672;tcp://localhost:9673'&failover='roundrobin'";
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(defaultUrl);
+
+ Init(connectionInfo);
+ DoFailoverTest(0);
+ }
+
+ /// <summary>
+ /// Send the test messages, prompting at the fail point for the user to cause a broker failure. The test checks that all messages sent
+ /// are received within the test time limit.
+ /// </summary>
+ ///
+ /// <param name="connectionInfo">The connection parameters, specifying the brokers to fail between.</param>
+ void DoFailoverTest(int delay)
+ {
+ _log.Debug("void DoFailoverTest(IConnectionInfo connectionInfo): called");
+
+ // Wait for all of the test messages to be received, checking that this occurs within the test time limit.
+ bool withinTimeout = false;
+
+ for (int i = 1; i <= NUM_MESSAGES; ++i)
+ {
+ SendMessage();
+
+ // Prompt the user to cause a failure if at the fail point.
+ if (i == FAIL_POINT)
+ {
+ for( int min = delay ; min > 0 ; min--)
+ {
+ Console.WriteLine("Waiting for "+min+" minutes to test connection time bug.");
+ Thread.Sleep(60*1000);
+ }
+
+ PromptAndWait("Cause a broker failure now, then press return.");
+ Console.WriteLine("NOTE: ensure that the delay between killing the broker and continuing here is less than 20 second");
+
+ Console.WriteLine("Sending a message to ensure send right after works");
+
+ SendMessage();
+
+ Console.WriteLine("Waiting for fail-over to complete before continuing...");
+
+
+ lock(failoverComplete)
+ {
+ if (!failedOver)
+ {
+ withinTimeout = Monitor.Wait(failoverComplete, TIMEOUT);
+ }
+ else
+ {
+ withinTimeout=true;
+ }
+ }
+
+ if (!withinTimeout)
+ {
+ PromptAndWait("Failover has not yet occured. Press enter to give up waiting.");
+ }
+ }
+ }
+
+ lock(testComplete)
+ {
+ withinTimeout = Monitor.Wait(testComplete, TIMEOUT);
+ }
+
+ if (!withinTimeout)
+ {
+ Assert.Fail("Test timed out, before all messages received.");
+ }
+
+ _log.Debug("void DoFailoverTest(IConnectionInfo connectionInfo): exiting");
+ }
+
+ [Test]
+ public void Test5MinuteWait()
+ {
+ String clientId = "failover" + DateTime.Now.Ticks;
+
+ QpidConnectionInfo connectionInfo = new QpidConnectionInfo();
+ connectionInfo.Username = "guest";
+ connectionInfo.Password = "guest";
+ connectionInfo.ClientName = clientId;
+ connectionInfo.VirtualHost = "/test";
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo("amqp", "localhost", 9672, false));
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo("amqp", "localhost", 9673, false));
+
+ Init(connectionInfo);
+ DoFailoverTest(5);
+ }
+
+ void SendMessage()
+ {
+ ITextMessage msg = publishingChannel.CreateTextMessage("message=" + messagesSent);
+
+ publisher.Send(msg);
+ messagesSent++;
+
+ if (transacted)
+ {
+ publishingChannel.Commit();
+ }
+
+ Console.WriteLine("messagesSent = " + messagesSent);
+ }
+
+ /// <summary>
+ /// Receives all of the test messages.
+ /// </summary>
+ ///
+ /// <param name="message">The newly arrived test message.</param>
+ public void OnMessage(IMessage message)
+ {
+ try
+ {
+ if (_acknowledgeMode == AcknowledgeMode.ClientAcknowledge)
+ {
+ message.Acknowledge();
+ }
+
+ messagesReceived++;
+
+ _log.Debug("messagesReceived = " + messagesReceived);
+
+ // Check if all of the messages in the test have been received, in which case notify the message producer that the test has
+ // succesfully completed.
+ if (messagesReceived == NUM_MESSAGES + _extraMessage)
+ {
+ lock (testComplete)
+ {
+ failedOver = true;
+ Monitor.Pulse(testComplete);
+ }
+ }
+ }
+ catch (QpidException e)
+ {
+ _log.Fatal("Exception received. About to stop.", e);
+ Stop();
+ }
+ }
+
+ /// <summary>Prompts the user on stdout and waits for a reply on stdin, using the specified prompt message.</summary>
+ ///
+ /// <param name="message">The message to prompt the user with.</param>
+ private void PromptAndWait(string message)
+ {
+ Console.WriteLine("\n" + message);
+ Console.ReadLine();
+ }
+
+ // <summary>Closes the test connection.</summary>
+ private void Stop()
+ {
+ _log.Debug("Stopping...");
+ try
+ {
+ _connection.Close();
+ }
+ catch (QpidException e)
+ {
+ _log.Debug("Failed to shutdown: ", e);
+ }
+ }
+
+ /// <summary>
+ /// Called when bytes have been transmitted to the server
+ /// </summary>
+ ///
+ /// <param>count the number of bytes sent in total since the connection was opened</param>
+ public void BytesSent(long count) {}
+
+ /// <summary>
+ /// Called when some bytes have been received on a connection
+ /// </summary>
+ ///
+ /// <param>count the number of bytes received in total since the connection was opened</param>
+ public void BytesReceived(long count) {}
+
+ /// <summary>
+ /// Called after the infrastructure has detected that failover is required but before attempting failover.
+ /// </summary>
+ ///
+ /// <param>redirect true if the broker requested redirect. false if failover is occurring due to a connection error.</param>
+ ///
+ /// <return>true to continue failing over, false to veto failover and raise a connection exception</return>
+ public bool PreFailover(bool redirect)
+ {
+ _log.Debug("public bool PreFailover(bool redirect): called");
+ return true;
+ }
+
+ /// <summary>
+ /// Called after connection has been made to another broker after failover has been started but before
+ /// any resubscription has been done.
+ /// </summary>
+ ///
+ /// <return> true to continue with resubscription, false to prevent automatic resubscription. This is useful in
+ /// cases where the application wants to handle resubscription. Note that in the latter case all sessions, producers
+ /// and consumers are invalidated.
+ /// </return>
+ public bool PreResubscribe()
+ {
+ _log.Debug("public bool PreResubscribe(): called");
+ return true;
+ }
+
+ /// <summary>
+ /// Called once failover has completed successfully. This is called irrespective of whether the client has
+ /// vetoed automatic resubscription.
+ /// </summary>
+ public void FailoverComplete()
+ {
+ failedOver = true;
+ _log.Debug("public void FailoverComplete(): called");
+ Console.WriteLine("public void FailoverComplete(): called");
+ lock (failoverComplete)
+ {
+ Monitor.Pulse(failoverComplete);
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interactive/SendReceiveTest.cs b/dotnet/Qpid.Integration.Tests/interactive/SendReceiveTest.cs
new file mode 100644
index 0000000000..68d7a2ae68
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interactive/SendReceiveTest.cs
@@ -0,0 +1,181 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Integration.Tests.testcases;
+
+namespace Apache.Qpid.Integration.Tests.interactive
+{
+ /// <summary>
+ /// SendReceiveTest provides a quick interactive send-receive test, where the user is prompted to trigger each send or receive.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Run an interactive send-receive loop prompting user to trigger each event.
+ /// </table>
+ /// </summary>
+ [TestFixture, Category("Interactive")]
+ public class SendReceiveTest : BaseMessagingTestFixture
+ {
+ /// <summary>Used for debugging purposes.</summary>
+ private static ILog log = LogManager.GetLogger(typeof(SendReceiveTest));
+
+ /// <summary>Defines the name of the test topic to use with the tests.</summary>
+ public const string TEST_ROUTING_KEY = "quicktestkey";
+
+ /// <summary>The number of consumers to test.</summary>
+ private const int CONSUMER_COUNT = 5;
+
+ /// <summary>The number of test messages to send.</summary>
+ private const int MESSAGE_COUNT = 10;
+
+ /// <summary>Monitor used to signal succesfull receipt of all test messages.</summary>
+ AutoResetEvent _finishedEvent;
+
+ /// <summary>Used to count test messages received so far.</summary>
+ private int _messageReceivedCount;
+
+ /// <summary>Used to hold the expected number of messages to receive.</summary>
+ private int expectedMessageCount;
+
+ /// <summary>Flag used to indicate that all messages really were received, and that the test did not just time out. </summary>
+ private bool allReceived;
+
+ /// <summary> Creates one producing end-point and many consuming end-points connected on a topic. </summary>
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+
+ // Reset all test counts and flags.
+ _messageReceivedCount = 0;
+ allReceived = false;
+ _finishedEvent = new AutoResetEvent(false);
+ }
+
+ /// <summary> Cleans up all test end-points. </summary>
+ [TearDown]
+ public override void Shutdown()
+ {
+ try
+ {
+ // Close all end points for producer and consumers.
+ // Producer is on 0, and consumers on 1 .. n, so loop is from 0 to n inclusive.
+ for (int i = 0; i <= CONSUMER_COUNT; i++)
+ {
+ CloseEndPoint(i);
+ }
+ }
+ finally
+ {
+ base.Shutdown();
+ }
+ }
+
+ /// <summary> Check that all consumers on a topic each receive all message on it. </summary>
+ [Test]
+ public void AllConsumerReceiveAllMessagesOnTopic()
+ {
+ // Create end-points for all the consumers in the test.
+ for (int i = 1; i <= CONSUMER_COUNT; i++)
+ {
+ SetUpEndPoint(i, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+ testConsumer[i].OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ // Create an end-point to publish to the test topic.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+
+ expectedMessageCount = (MESSAGE_COUNT * CONSUMER_COUNT);
+
+ PromptAndWait("Press to send...");
+
+ for (int i = 0; i < MESSAGE_COUNT; i++)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+ }
+
+ _finishedEvent.WaitOne(new TimeSpan(0, 0, 0, 10), false);
+
+ PromptAndWait("Press to complete test...");
+
+ // Check that all messages really were received.
+ Assert.IsTrue(allReceived, "All messages were not received, only got " + _messageReceivedCount + " but wanted " + expectedMessageCount);
+ }
+
+ /// <summary> Check that consumers on the same queue receive each message once accross all consumers. </summary>
+ //[Test]
+ public void AllConsumerReceiveAllMessagesOnDirect()
+ {
+ // Create end-points for all the consumers in the test.
+ for (int i = 1; i <= CONSUMER_COUNT; i++)
+ {
+ SetUpEndPoint(i, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+ testConsumer[i].OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ // Create an end-point to publish to the test topic.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+
+ expectedMessageCount = MESSAGE_COUNT;
+
+ for (int i = 0; i < MESSAGE_COUNT; i++)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+ }
+
+ _finishedEvent.WaitOne(new TimeSpan(0, 0, 0, 10), false);
+
+ // Check that all messages really were received.
+ Assert.IsTrue(allReceived, "All messages were not received, only got: " + _messageReceivedCount + " but wanted " + expectedMessageCount);
+ }
+
+ /// <summary> Atomically increments the message count on every message, and signals once all messages in the test are received. </summary>
+ public void OnMessage(IMessage m)
+ {
+ int newCount = Interlocked.Increment(ref _messageReceivedCount);
+
+ if (newCount >= expectedMessageCount)
+ {
+ allReceived = true;
+ _finishedEvent.Set();
+ }
+ }
+
+ /// <summary>Prompts the user on stdout and waits for a reply on stdin, using the specified prompt message.</summary>
+ ///
+ /// <param name="message">The message to prompt the user with.</param>
+ private void PromptAndWait(string message)
+ {
+ Console.WriteLine("\n" + message);
+ Console.ReadLine();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Integration.Tests/interop/InteropClientTestCase.cs b/dotnet/Qpid.Integration.Tests/interop/InteropClientTestCase.cs
new file mode 100644
index 0000000000..09361b33e8
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/InteropClientTestCase.cs
@@ -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.
+ *
+ */
+using System;
+using System.Text;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop
+{
+ /// <summary> Defines the possible test case roles that an interop test case can take on. </summary>
+ public enum Roles { SENDER, RECEIVER };
+
+ /// <summary>
+ /// InteropClientTestCase provides an interface that classes implementing test cases from the interop testing spec
+ /// (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification) should implement.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ interface InteropClientTestCase
+ {
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements. </returns>
+ string GetName();
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </returns>
+ ///
+ /// @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ bool AcceptInvite(IMessage inviteMessage);
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ void AssignRole(Roles role, IMessage assignRoleMessage);
+
+ /// <summary>
+ /// Performs the test case actions.
+ /// </summary>
+ void Start();
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ IMessage GetReport(IChannel channel);
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase1DummyRun.cs b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase1DummyRun.cs
new file mode 100644
index 0000000000..d908b7af0b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase1DummyRun.cs
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements tet case 1, dummy run. This test case sends no test messages, it exists to confirm that the test harness
+ /// is interacting with the coordinator correctly.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Perform test case actions.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase1DummyRun : InteropClientTestCase
+ {
+ private static ILog log = LogManager.GetLogger(typeof(TestCase1DummyRun));
+
+ public String GetName()
+ {
+ log.Debug("public String getName(): called");
+
+ return "TC1_DummyRun";
+ }
+
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean acceptInvite(Message inviteMessage): called");
+
+ // Test parameters don't matter, accept all invites.
+ return true;
+ }
+
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Debug("public void assignRole(Roles role, Message assignRoleMessage): called");
+
+ // Do nothing, both roles are the same.
+ }
+
+ public void Start()
+ {
+ log.Debug("public void start(): called");
+
+ // Do nothing.
+ }
+
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public Message getReport(Session session): called");
+
+ // Generate a dummy report, the coordinator expects a report but doesn't care what it is.
+ return channel.CreateTextMessage("Dummy Run, Ok.");
+ }
+
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void onMessage(Message message = " + message + "): called");
+
+ // Ignore any messages.
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase2BasicP2P.cs b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase2BasicP2P.cs
new file mode 100644
index 0000000000..8993da832e
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase2BasicP2P.cs
@@ -0,0 +1,205 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements test case 2, basic P2P. Sends/receives a specified number of messages to a specified route on the
+ /// default direct exchange. Produces reports on the actual number of messages sent/received.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Send required number of test messages.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase2BasicP2P : InteropClientTestCase
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestCase2BasicP2P));
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The routing key to send them to on the default direct exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connection to send the test messages on. </summary>
+ private IConnection connection;
+
+ /// <summary> The session to send the test messages on. </summary>
+ private IChannel channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ private IMessagePublisher publisher;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements. </returns>
+ public String GetName()
+ {
+ log.Debug("public String GetName(): called");
+
+ return "TC2_BasicP2P";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean AcceptInvite(Message inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Debug("public void AssignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Create a new connection to pass the test messages on.
+ connection =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel = connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.Headers.GetInt("P2P_NUM_MESSAGES");
+ string queueAndKeyName = assignRoleMessage.Headers.GetString("P2P_QUEUE_AND_KEY_NAME");
+ channel.DeclareQueue(queueAndKeyName, false, true, true);
+ channel.Bind(queueAndKeyName, ExchangeNameDefaults.DIRECT, queueAndKeyName);
+ sendDestination = queueAndKeyName;
+
+ log.Debug("numMessages = " + numMessages);
+ log.Debug("sendDestination = " + sendDestination);
+ log.Debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a message producer if so.
+ case Roles.SENDER:
+ publisher = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.DIRECT)
+ .WithRoutingKey(sendDestination)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up to listen for messages.
+ case Roles.RECEIVER:
+ IMessageConsumer consumer = channel.CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ break;
+ }
+
+ connection.Start();
+ }
+
+ /// <summary> Performs the test case actions. </summary>
+ public void Start()
+ {
+ log.Debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = channel.CreateTextMessage("test");
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public Message GetReport(IChannel channel): called");
+
+ // Close the test connection.
+ //connection.Stop();
+
+ // Generate a report message containing the count of the number of messages passed.
+ IMessage report = channel.CreateMessage();
+ //report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void OnMessage(IMessage message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase3BasicPubSub.cs b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase3BasicPubSub.cs
new file mode 100644
index 0000000000..79c0322bcd
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase3BasicPubSub.cs
@@ -0,0 +1,244 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop.TestCases
+{
+ /// <summary>
+ /// Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
+ /// default topic exchange, using the specified number of receiver connections. Produces reports on the actual number of
+ /// messages sent/received.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Supply the name of the test case that this implements.
+ /// <tr><td> Accept/Reject invites based on test parameters.
+ /// <tr><td> Adapt to assigned roles.
+ /// <tr><td> Send required number of test messages using pub/sub.
+ /// <tr><td> Generate test reports.
+ /// </table>
+ /// </summary>
+ public class TestCase3BasicPubSub : InteropClientTestCase
+ {
+ /// <summary> Used for debugging. </summary>
+ private static ILog log = LogManager.GetLogger(typeof(TestCase3BasicPubSub));
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The number of receiver connection to use. </summary>
+ private int numReceivers;
+
+ /// <summary> The routing key to send them to on the default direct exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connections to send/receive the test messages on. </summary>
+ private IConnection[] connection;
+
+ /// <summary> The sessions to send/receive the test messages on. </summary>
+ private IChannel[] channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ IMessagePublisher publisher;
+
+ /// <summary>
+ /// Should provide the name of the test case that this class implements. The exact names are defined in the
+ /// interop testing spec.
+ /// </summary>
+ ///
+ /// <returns> The name of the test case that this implements. </returns>
+ public String GetName()
+ {
+ log.Debug("public String GetName(): called");
+
+ return "TC3_BasicPubSub";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Debug("public boolean AcceptInvite(IMessage inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /// <summary>
+ /// Assigns the role to be played by this test case. The test parameters are fully specified in the
+ /// assignment message. When this method return the test case will be ready to execute.
+ /// </summary>
+ ///
+ /// <param name="role"> The role to be played; sender or receiver. </param>
+ /// <param name="assignRoleMessage"> The role assingment message, contains the full test parameters. </param>
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Debug("public void assignRole(Roles role = " + role + ", IMessage assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.Headers.GetInt("PUBSUB_NUM_MESSAGES");
+ numReceivers = assignRoleMessage.Headers.GetInt("PUBSUB_NUM_RECEIVERS");
+ string sendKey = assignRoleMessage.Headers.GetString("PUBSUB_KEY");
+ sendDestination = sendKey;
+
+ log.Debug("numMessages = " + numMessages);
+ log.Debug("numReceivers = " + numReceivers);
+ log.Debug("sendKey = " + sendKey);
+ log.Debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case Roles.SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new IConnection[1];
+ channel = new IChannel[1];
+
+ connection[0] =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[0] = connection[0].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ publisher = channel[0].CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(sendDestination)
+ .WithMandatory(false)
+ .WithImmediate(false)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
+ // of receiver connections.
+ case Roles.RECEIVER:
+ // Create the required number of receiver connections.
+ connection = new IConnection[numReceivers];
+ channel = new IChannel[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[i] = connection[i].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ IMessageConsumer consumer = channel[i].CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ foreach (IConnection con in connection)
+ {
+ con.Start();
+ }
+ }
+
+ /// <summary>
+ /// Performs the test case actions.
+ /// </summary>
+ public void Start()
+ {
+ log.Debug("public void Start(): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = channel[0].CreateTextMessage("test");
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a report on the actions performed by the test case in its assigned role.
+ /// </summary>
+ ///
+ /// <param name="session"> The session to create the report message in. </param>
+ ///
+ /// <returns> The report message. </returns>
+ public IMessage GetReport(IChannel channel)
+ {
+ log.Debug("public IMessage getReport(IChannel channel): called");
+
+ // Close the test connections.
+ /*foreach (IConnection con in connection)
+ {
+ try
+ {
+ con.Stop();
+ }
+ catch (AMQConnectionClosedException e)
+ {
+ // The connection has already died due to an error. Log this as a warning.
+ log.Warn("Connection already closed.");
+ }
+ }*/
+
+ // Generate a report message containing the count of the number of messages passed.
+ IMessage report = channel.CreateMessage();
+ //report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Debug("public void onMessage(IMessage message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase4P2PMessageSize.cs b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase4P2PMessageSize.cs
new file mode 100644
index 0000000000..fd83825a61
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase4P2PMessageSize.cs
@@ -0,0 +1,244 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop.TestCases
+{
+ ///
+ /// Implements test case 4, from the interop test specification. This test sets up the TC2_P2PMessageSize test for 50
+ /// messages, and a variety of message sizes. It checks that the sender and receivers reports both indicate that all
+ /// the test messages were transmitted successfully.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ /// </table>
+ ///
+ public class TestCase4P2PMessageSize : InteropClientTestCase
+ {
+ /// Used for debugging.
+ private static ILog log = LogManager.GetLogger(typeof(TestCase4P2PMessageSize));
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ ///<summary>The size of the message to be sent </summary>
+ private int messageSize;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The number of receiver connection to use. </summary>
+ private int numReceivers;
+
+ /// <summary> The routing key to send them to on the default direct exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connections to send/receive the test messages on. </summary>
+ private IConnection[] connection;
+
+ /// <summary> The sessions to send/receive the test messages on. </summary>
+ private IChannel[] channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ IMessagePublisher publisher;
+
+ /// <summary>
+ /// Creates a new coordinating test case with the specified name.
+ ///</summary>
+ /// <returns>The test case name.</returns>
+ ///
+ public String GetName()
+ {
+ log.Info("public String GetName(): called");
+ return "TC4_P2PMessageSize";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Info("public boolean AcceptInvite(IMessage inviteMessage = " + inviteMessage + "): called");
+ // All invites are acceptable.
+ return true;
+ }
+
+ public void Start()
+ {
+ log.Info("public void start(): called");
+ // Assuming numMessages = 1
+ Start(1);
+ }
+
+ public void Start(int numMessages)
+ {
+ log.Info("public void start("+numMessages+"): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = createMessageOfSize(messageSize);
+
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+
+ }
+
+ private IMessage createMessageOfSize(int size)
+ {
+ IBytesMessage message = channel[0].CreateBytesMessage();
+ string messageStr = "Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- ";
+ System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
+ byte[] messageBytes = encoding.GetBytes(messageStr);
+
+ if (size > 0)
+ {
+ int div = size / messageBytes.Length;
+ int mod = size % messageBytes.Length;
+
+ for (int i = 0; i < div; i++)
+ {
+ message.WriteBytes(messageBytes);
+ }
+ if (mod != 0)
+ {
+ message.WriteBytes(messageBytes, 0, mod);
+ }
+ }
+ return message;
+ }
+
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Info("public void assignRole(Roles role = " + role + ", IMessage assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.Headers.GetInt("P2P_NUM_MESSAGES");
+ messageSize = assignRoleMessage.Headers.GetInt("messageSize");
+
+ string sendKey = assignRoleMessage.Headers.GetString("P2P_QUEUE_AND_KEY_NAME");
+ sendDestination = sendKey;
+
+ log.Info("numMessages = " + numMessages);
+ log.Info("messageSize = " + messageSize);
+ log.Info("sendKey = " + sendKey);
+ log.Info("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case Roles.SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new IConnection[1];
+ channel = new IChannel[1];
+
+ connection[0] =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[0] = connection[0].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ publisher = channel[0].CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(sendDestination)
+ .WithMandatory(false)
+ .WithImmediate(false)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
+ // of receiver connections.
+ case Roles.RECEIVER:
+ // Create the required number of receiver connections.
+ connection = new IConnection[1];
+ channel = new IChannel[1];
+ connection[0] = TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[0] = connection[0].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+ IMessageConsumer consumer = channel[0].CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ foreach (IConnection con in connection)
+ {
+ con.Start();
+ }
+
+ }
+
+ public IMessage GetReport(IChannel channel)
+ {
+
+ log.Info("public Message GetReport(IChannel channel): called");
+
+ // Close the test connection.
+ //connection.Stop();
+
+ // Generate a report message containing the count of the number of messages passed.
+ IMessage report = channel.CreateMessage();
+ //report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Info("public void onMessage(IMessage message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase5PubSubMessageSize.cs b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase5PubSubMessageSize.cs
new file mode 100644
index 0000000000..8fddaeafa2
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestCases/TestCase5PubSubMessageSize.cs
@@ -0,0 +1,252 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Text;
+using log4net;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.interop.TestCases
+{
+ ///
+ /// Implements test case 4, from the interop test specification. This test sets up the TC2_P2PMessageSize test for 50
+ /// messages, and a variety of message sizes. It checks that the sender and receivers reports both indicate that all
+ /// the test messages were transmitted successfully.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ /// </table>
+ ///
+ public class TestCase5PubSubMessageSize : InteropClientTestCase
+ {
+ /// Used for debugging.
+ private static ILog log = LogManager.GetLogger(typeof(TestCase5PubSubMessageSize));
+
+ /// <summary> The role to be played by the test. </summary>
+ private Roles role;
+
+ /// <summary> Holds the count of test messages received. </summary>
+ private int messageCount;
+
+ ///<summary>The size of the message to be sent </summary>
+ private int messageSize;
+
+ /// <summary> The number of test messages to send. </summary>
+ private int numMessages;
+
+ /// <summary> The number of receiver connection to use. </summary>
+ private int numReceivers;
+
+ /// <summary> The routing key to send them to on the default direct exchange. </summary>
+ private string sendDestination;
+
+ /// <summary> The connections to send/receive the test messages on. </summary>
+ private IConnection[] connection;
+
+ /// <summary> The sessions to send/receive the test messages on. </summary>
+ private IChannel[] channel;
+
+ /// <summary> The producer to send the test messages with. </summary>
+ IMessagePublisher publisher;
+
+ /// <summary>
+ /// Creates a new coordinating test case with the specified name.
+ ///</summary>
+ /// <returns>The test case name.</returns>
+ ///
+ public String GetName()
+ {
+ log.Info("public String GetName(): called");
+ return "TC5_PubSubMessageSize";
+ }
+
+ /// <summary>
+ /// Determines whether the test invite that matched this test case is acceptable.
+ /// </summary>
+ ///
+ /// <param name="inviteMessage"> The invitation to accept or reject. </param>
+ ///
+ /// <returns> <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it. </returns>
+ public bool AcceptInvite(IMessage inviteMessage)
+ {
+ log.Info("public boolean AcceptInvite(IMessage inviteMessage = " + inviteMessage + "): called");
+ // All invites are acceptable.
+ return true;
+ }
+
+ public void Start()
+ {
+ log.Info("public void start(): called");
+ // Assuming numMessages = 1
+ Start(1);
+ }
+
+ public void Start(int numMessages)
+ {
+ log.Info("public void start("+numMessages+"): called");
+
+ // Check that the sender role is being performed.
+ if (role == Roles.SENDER)
+ {
+ IMessage testMessage = createMessageOfSize(messageSize);
+
+
+ for (int i = 0; i < numMessages; i++)
+ {
+ publisher.Send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+
+ }
+
+ private IMessage createMessageOfSize(int size)
+ {
+ IBytesMessage message = channel[0].CreateBytesMessage();
+ string messageStr = "Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- Test Message -- ";
+ System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
+ byte[] messageBytes = encoding.GetBytes(messageStr);
+
+ if (size > 0)
+ {
+ int div = size / messageBytes.Length;
+ int mod = size % messageBytes.Length;
+
+ for (int i = 0; i < div; i++)
+ {
+ message.WriteBytes(messageBytes);
+ }
+ if (mod != 0)
+ {
+ message.WriteBytes(messageBytes, 0, mod);
+ }
+ }
+ return message;
+ }
+
+ public void AssignRole(Roles role, IMessage assignRoleMessage)
+ {
+ log.Info("public void assignRole(Roles role = " + role + ", IMessage assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.Headers.GetInt("PUBSUB_NUM_MESSAGES");
+ messageSize = assignRoleMessage.Headers.GetInt("messageSize");
+ numReceivers = assignRoleMessage.Headers.GetInt("PUBSUB_NUM_RECEIVERS");
+
+ string sendKey = assignRoleMessage.Headers.GetString("PUBSUB_KEY");
+ sendDestination = sendKey;
+
+ log.Info("numMessages = " + numMessages);
+ log.Info("messageSize = " + messageSize);
+ log.Info("sendKey = " + sendKey);
+ log.Info("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case Roles.SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new IConnection[1];
+ channel = new IChannel[1];
+
+ connection[0] =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[0] = connection[0].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ // Extract and retain the test parameters.
+ publisher = channel[0].CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(sendDestination)
+ .WithMandatory(false)
+ .WithImmediate(false)
+ .Create();
+ break;
+
+ // Otherwise the receiver role is being assigned, so set this up to listen for messages on the required number
+ // of receiver connections.
+ case Roles.RECEIVER:
+ // Create the required number of receiver connections.
+ connection = new IConnection[numReceivers];
+ channel = new IChannel[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] =
+ TestClient.CreateConnection(TestClient.brokerUrl, TestClient.virtualHost);
+ channel[i] = connection[i].CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ IMessageConsumer consumer = channel[i].CreateConsumerBuilder(sendDestination).Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ foreach (IConnection con in connection)
+ {
+ con.Start();
+ }
+
+ }
+
+ public IMessage GetReport(IChannel channel)
+ {
+
+ log.Info("public Message GetReport(IChannel channel): called");
+
+ // Close the test connection.
+ //connection.Stop();
+
+ // Generate a report message containing the count of the number of messages passed.
+ IMessage report = channel.CreateMessage();
+ //report.Headers.SetString("CONTROL_TYPE", "REPORT");
+ report.Headers.SetInt("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+
+ /// <summary>
+ /// Counts incoming test messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming test message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Info("public void onMessage(IMessage message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/interop/TestClient.cs b/dotnet/Qpid.Integration.Tests/interop/TestClient.cs
new file mode 100644
index 0000000000..0def89c6da
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/interop/TestClient.cs
@@ -0,0 +1,381 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Collections;
+using System.Text;
+using System.Threading;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using log4net;
+using Apache.Qpid.Integration.Tests.interop.TestCases;
+
+namespace Apache.Qpid.Integration.Tests.interop
+{
+ /// <summary>
+ /// Implements a test client as described in the interop testing spec
+ /// (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
+ /// reacts to control message sequences send by the test coordinator.
+ ///
+ /// <p/><table><caption>Messages Handled by TestClient</caption>
+ /// <tr><th> Message <th> Action
+ /// <tr><td> Invite(compulsory) <td> Reply with Enlist.
+ /// <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
+ /// <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches an enlisted test. Keep test parameters.
+ /// <tr><td> Start <td> Send test messages defined by test parameters. Send report on messages sent.
+ /// <tr><td> Status Request <td> Send report on messages received.
+ /// </table>
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Handle all incoming control messages. <td> {@link InteropClientTestCase}
+ /// <tr><td> Configure and look up test cases by name. <td> {@link InteropClientTestCase}
+ /// </table>
+ /// </summary>
+ public class TestClient
+ {
+ private static ILog log = LogManager.GetLogger(typeof(TestClient));
+
+ /// <summary> Defines the default broker for the tests, localhost, default port. </summary>
+ public static string DEFAULT_BROKER_URL = "amqp://guest:guest@clientid/?brokerlist='tcp://localhost:5672'";
+
+ /// <summary> Defines the default virtual host to use for the tests, none. </summary>
+ public static string DEFAULT_VIRTUAL_HOST = "";
+
+ /// <summary> Defines the default identifying name of this test client. </summary>
+ public static string DEFAULT_CLIENT_NAME = "dotnet";
+
+ /// <summary> Holds the URL of the broker to run the tests on. </summary>
+ public static string brokerUrl;
+
+ /// <summary> Holds the virtual host to run the tests on. If <tt>null</tt>, then the default virtual host is used. </summary>
+ public static string virtualHost;
+
+ /// <summary> The clients identifying name to print in test results and to distinguish from other clients. </summary>
+ private string clientName;
+
+ /// <summary> Holds all the test cases. </summary>
+ private IDictionary testCases = new Hashtable();
+
+ InteropClientTestCase currentTestCase;
+
+ private MessagePublisherBuilder publisherBuilder;
+
+ private IChannel channel;
+
+ /// <summary> Monitor to wait for termination events on. </summary>
+ private static object terminationMonitor = new Object();
+
+ /// <summary>
+ /// Creates a new interop test client, listenting to the specified broker and virtual host, with the specified
+ /// client identifying name.
+ /// </summary>
+ ///
+ /// <param name="brokerUrl"> The url of the broker to connect to. </param>
+ /// <param name="virtualHost"> The virtual host to conect to. </param>
+ /// <param name="clientName"> The client name to use. </param>
+ public TestClient(string brokerUrl, string virtualHost, string clientName)
+ {
+ log.Info("public TestClient(string brokerUrl = " + brokerUrl + ", string virtualHost = " + virtualHost
+ + ", string clientName = " + clientName + "): called");
+
+ // Retain the connection parameters.
+ TestClient.brokerUrl = brokerUrl;
+ TestClient.virtualHost = virtualHost;
+ this.clientName = clientName;
+ }
+
+
+ /// <summary>
+ /// The entry point for the interop test coordinator. This client accepts the following command line arguments:
+ /// </summary>
+ ///
+ /// <p/><table>
+ /// <tr><td> -b <td> The broker URL. <td> Optional.
+ /// <tr><td> -h <td> The virtual host. <td> Optional.
+ /// <tr><td> -n <td> The test client name. <td> Optional.
+ /// <tr><td> name=value <td> Trailing argument define name/value pairs. Added to system properties. <td> Optional.
+ /// </table>
+ ///
+ /// <param name="args"> The command line arguments. </param>
+ public static void Main(string[] args)
+ {
+ // Extract the command line options (Not exactly Posix but it will do for now...).
+ string brokerUrl = DEFAULT_BROKER_URL;
+ string virtualHost = DEFAULT_VIRTUAL_HOST;
+ string clientName = DEFAULT_CLIENT_NAME;
+
+ foreach (string nextArg in args)
+ {
+ if (nextArg.StartsWith("-b"))
+ {
+ brokerUrl = nextArg.Substring(2);
+ }
+ else if (nextArg.StartsWith("-h"))
+ {
+ virtualHost = nextArg.Substring(2);
+ }
+ else if (nextArg.StartsWith("-n"))
+ {
+ clientName = nextArg.Substring(2);
+ }
+ }
+
+ NDC.Push(clientName);
+
+ // Create a test client and start it running.
+ TestClient client = new TestClient(brokerUrl, virtualHost, clientName);
+
+ try
+ {
+ client.Start();
+ }
+ catch (Exception e)
+ {
+ log.Error("The test client was unable to start.", e);
+ System.Environment.Exit(1);
+ }
+
+ // Wait for a signal on the termination monitor before quitting.
+ lock (terminationMonitor)
+ {
+ Monitor.Wait(terminationMonitor);
+ }
+
+ NDC.Pop();
+ }
+
+ /// <summary>
+ /// Starts the interop test client running. This causes it to start listening for incoming test invites.
+ /// </summary>
+ private void Start()
+ {
+ log.Info("private void Start(): called");
+
+ // Use a class path scanner to find all the interop test case implementations.
+ ArrayList testCaseClasses = new ArrayList();
+
+ // ClasspathScanner.getMatches(InteropClientTestCase.class, "^TestCase.*", true);
+ // Hard code the test classes till the classpath scanner is fixed.
+ testCaseClasses.Add(typeof(TestCase1DummyRun));
+ testCaseClasses.Add(typeof(TestCase2BasicP2P));
+ testCaseClasses.Add(typeof(TestCase3BasicPubSub));
+ testCaseClasses.Add(typeof(TestCase4P2PMessageSize));
+ testCaseClasses.Add(typeof(TestCase5PubSubMessageSize));
+
+ // Create all the test case implementations and index them by the test names.
+ foreach (Type testClass in testCaseClasses)
+ {
+ InteropClientTestCase testCase = (InteropClientTestCase)Activator.CreateInstance(testClass);
+ testCases.Add(testCase.GetName(), testCase);
+
+ log.Info("Found test case: " + testClass);
+ }
+
+ // Open a connection to communicate with the coordinator on.
+ log.Info("brokerUrl = " + brokerUrl);
+ IConnection connection = CreateConnection(brokerUrl, virtualHost);
+
+ channel = connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+
+ // Set this up to listen for control messages.
+ string responseQueueName = channel.GenerateUniqueName();
+ channel.DeclareQueue(responseQueueName, false, true, true);
+
+ channel.Bind(responseQueueName, ExchangeNameDefaults.TOPIC, "iop.control." + clientName);
+ channel.Bind(responseQueueName, ExchangeNameDefaults.TOPIC, "iop.control");
+
+ IMessageConsumer consumer = channel.CreateConsumerBuilder(responseQueueName)
+ .Create();
+ consumer.OnMessage += new MessageReceivedDelegate(OnMessage);
+
+ // Create a publisher to send replies with.
+ publisherBuilder = channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.DIRECT);
+
+
+ // Start listening for incoming control messages.
+ connection.Start();
+ Console.WriteLine("Test client " + clientName + " ready to receive test control messages...");
+ }
+
+ /// <summary>
+ /// Establishes an AMQ connection. This is a simple convenience method for code that does not anticipate handling connection failures.
+ /// All exceptions that indicate that the connection has failed, are allowed to fall through.
+ /// </summary>
+ ///
+ /// <param name="brokerUrl"> The broker url to connect to, <tt>null</tt> to use the default from the properties. </param>
+ /// <param name="virtualHost"> The virtual host to connectio to, <tt>null</tt> to use the default. </param>
+ ///
+ /// <returns> A JMS conneciton. </returns>
+ public static IConnection CreateConnection(string brokerUrl, string virtualHost)
+ {
+ log.Info("public static Connection createConnection(string brokerUrl = " + brokerUrl + ", string virtualHost = "
+ + virtualHost + "): called");
+
+ // Create a connection to the broker.
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(brokerUrl);
+ connectionInfo.VirtualHost = virtualHost;
+ IConnection connection = new AMQConnection(connectionInfo);
+
+ return connection;
+ }
+
+ /// <summary>
+ /// Handles all incoming control messages.
+ /// </summary>
+ ///
+ /// <param name="message"> The incoming message. </param>
+ public void OnMessage(IMessage message)
+ {
+ log.Info("public void OnMessage(IMessage message = " + message + "): called");
+
+ try
+ {
+ string controlType = message.Headers.GetString("CONTROL_TYPE");
+ string testName = message.Headers.GetString("TEST_NAME");
+
+ // Check if the message is a test invite.
+ if ("INVITE" == controlType)
+ {
+ string testCaseName = message.Headers.GetString("TEST_NAME");
+
+ // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites
+ // for which test cases exist.
+ bool enlist = false;
+
+ if (testCaseName != null)
+ {
+ log.Info("Got an invite to test: " + testCaseName);
+
+ // Check if the requested test case is available.
+ InteropClientTestCase testCase = (InteropClientTestCase)testCases[testCaseName];
+
+ if (testCase != null)
+ {
+ // Make the requested test case the current test case.
+ currentTestCase = testCase;
+ enlist = true;
+ }
+ }
+ else
+ {
+ log.Info("Got a compulsory invite.");
+
+ enlist = true;
+ }
+
+ log.Info("enlist = " + enlist);
+
+ if (enlist)
+ {
+ // Reply with the client name in an Enlist message.
+ IMessage enlistMessage = channel.CreateMessage();
+ enlistMessage.Headers.SetString("CONTROL_TYPE", "ENLIST");
+ enlistMessage.Headers.SetString("CLIENT_NAME", clientName);
+ enlistMessage.Headers.SetString("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.CorrelationId = message.CorrelationId;
+
+ Send(enlistMessage, message.ReplyToRoutingKey);
+ }
+ }
+ else if ("ASSIGN_ROLE" == controlType)
+ {
+ // Assign the role to the current test case.
+ string roleName = message.Headers.GetString("ROLE");
+
+ log.Info("Got a role assignment to role: " + roleName);
+
+ Roles role;
+
+ if (roleName == "SENDER")
+ {
+ role = Roles.SENDER;
+ }
+ else
+ {
+ role = Roles.RECEIVER;
+ }
+
+ currentTestCase.AssignRole(role, message);
+
+ // Reply by accepting the role in an Accept Role message.
+ IMessage acceptRoleMessage = channel.CreateMessage();
+ acceptRoleMessage.Headers.SetString("CONTROL_TYPE", "ACCEPT_ROLE");
+ acceptRoleMessage.CorrelationId = message.CorrelationId;
+
+ Send(acceptRoleMessage, message.ReplyToRoutingKey);
+ }
+ else if ("START" == controlType || "STATUS_REQUEST" == controlType)
+ {
+ if ("START" == controlType)
+ {
+ log.Info("Got a start notification.");
+
+ // Start the current test case.
+ currentTestCase.Start();
+ }
+ else
+ {
+ log.Info("Got a status request.");
+ }
+
+ // Generate the report from the test case and reply with it as a Report message.
+ IMessage reportMessage = currentTestCase.GetReport(channel);
+ reportMessage.Headers.SetString("CONTROL_TYPE", "REPORT");
+ reportMessage.CorrelationId = message.CorrelationId;
+
+ Send(reportMessage, message.ReplyToRoutingKey);
+ }
+ else if ("TERMINATE" == controlType)
+ {
+ Console.WriteLine("Received termination instruction from coordinator.");
+
+ // Is a cleaner shutdown needed?
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ // Log a warning about this but otherwise ignore it.
+ log.Warn("Got an unknown control message, controlType = " + controlType + ", message = " + message);
+ }
+ }
+ catch (QpidException e)
+ {
+ // Log a warning about this, but otherwise ignore it.
+ log.Warn("A QpidException occurred whilst handling a message.");
+ log.Info("Got QpidException whilst handling message: " + message, e);
+ }
+ }
+
+ /// <summary>
+ /// Send the specified message using the specified routing key on the direct exchange.
+ /// </summary>
+ ///
+ /// <param name="message"> The message to send.</param>
+ /// <param name="routingKey"> The routing key to send the message with.</param>
+ public void Send(IMessage message, string routingKey)
+ {
+ IMessagePublisher publisher = publisherBuilder.WithRoutingKey(routingKey).Create();
+ publisher.Send(message);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/log4net.config b/dotnet/Qpid.Integration.Tests/log4net.config
new file mode 100644
index 0000000000..73bfc77a3e
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/log4net.config
@@ -0,0 +1,69 @@
+<!--
+
+ 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.
+
+-->
+
+<log4net>
+
+ <!-- ============================== -->
+ <!-- Append messages to the console -->
+ <!-- ============================== -->
+
+ <appender name="console" type="log4net.Appender.ConsoleAppender" >
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%m%n"/>
+ </layout>
+ <threshold value="info"/>
+ </appender>
+
+ <!-- ====================================== -->
+ <!-- Append messages to the socket appender -->
+ <!-- ====================================== -->
+
+ <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
+ <remoteAddress value="127.0.0.1"/>
+ <remotePort value="4445"/>
+ <layout type="log4net.Layout.XmlLayoutSchemaLog4j">
+ <locationInfo value="true"/>
+ </layout>
+ <threshold value="debug"/>
+ </appender>
+
+ <!-- ================ -->
+ <!-- Limit categories -->
+ <!-- ================ -->
+
+ <logger name="Qpid">
+ <level value="debug"/>
+ </logger>
+
+ <logger name="CONSOLE">
+ <level value="info"/>
+ <appender-ref ref="console"/>
+ </logger>
+
+ <!-- ======================= -->
+ <!-- Setup the Root category -->
+ <!-- ======================= -->
+
+ <root>
+ <appender-ref ref="UdpAppender"/>
+ </root>
+
+</log4net>
diff --git a/dotnet/Qpid.Integration.Tests/old/ServiceProvidingClient.tmp b/dotnet/Qpid.Integration.Tests/old/ServiceProvidingClient.tmp
new file mode 100644
index 0000000000..b1e7a50aaa
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/old/ServiceProvidingClient.tmp
@@ -0,0 +1,150 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ [TestFixture, Category("Integration")]
+ public class ServiceProvidingClient : BaseMessagingTestFixture
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(ServiceProvidingClient));
+
+ private int _messageCount;
+
+ private string _replyToExchangeName;
+ private string _replyToRoutingKey;
+ const int PACK = 100;
+
+ private IMessagePublisher _destinationPublisher;
+ private IMessageConsumer _consumer;
+
+ private string _serviceName = "ServiceQ1";
+
+ private string _selector = null;
+
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+
+ _logger.Info("Starting...");
+ _logger.Info("Service (queue) name is '" + _serviceName + "'...");
+
+ _connection.ExceptionListener = new ExceptionListenerDelegate(OnConnectionException);
+
+ _logger.Info("Message selector is <" + _selector + ">...");
+
+ _channel.DeclareQueue(_serviceName, false, false, false);
+
+ _consumer = _channel.CreateConsumerBuilder(_serviceName)
+ .WithPrefetchLow(100)
+ .WithPrefetchHigh(500)
+ .WithNoLocal(true)
+ .Create();
+ _consumer.OnMessage = new MessageReceivedDelegate(OnMessage);
+ }
+
+ public override void Shutdown()
+ {
+ _consumer.Dispose();
+ base.Shutdown();
+ }
+
+ private void OnConnectionException(Exception e)
+ {
+ _logger.Info("Connection exception occurred", e);
+ // XXX: Test still doesn't shutdown when broker terminates. Is there no heartbeat?
+ }
+
+ [Test]
+ public void Test()
+ {
+ _connection.Start();
+ _logger.Info("Waiting...");
+
+ ServiceRequestingClient client = new ServiceRequestingClient();
+ client.Init();
+ client.SendMessages();
+ }
+
+ private void OnMessage(IMessage message)
+ {
+// _logger.Info("Got message '" + message + "'");
+
+ ITextMessage tm = (ITextMessage)message;
+
+ try
+ {
+ string replyToExchangeName = tm.ReplyToExchangeName;
+ string replyToRoutingKey = tm.ReplyToRoutingKey;
+
+ _replyToExchangeName = replyToExchangeName;
+ _replyToRoutingKey = replyToRoutingKey;
+ _logger.Debug("About to create a producer");
+
+// Console.WriteLine("ReplyTo.ExchangeName = " + _replyToExchangeName);
+// Console.WriteLine("ReplyTo.RoutingKey = " + _replyToRoutingKey);
+
+ _destinationPublisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(_replyToExchangeName)
+ .WithRoutingKey(_replyToRoutingKey)
+ .WithDeliveryMode(DeliveryMode.NonPersistent)
+ .Create();
+ _destinationPublisher.DisableMessageTimestamp = true;
+ _logger.Debug("After create a producer");
+ }
+ catch (QpidException e)
+ {
+ _logger.Error("Error creating destination", e);
+ throw e;
+ }
+ _messageCount++;
+ if (_messageCount % PACK == 0)
+ {
+ _logger.Info("Received message total: " + _messageCount);
+ _logger.Info(string.Format("Sending response to '{0}:{1}'",
+ _replyToExchangeName, _replyToRoutingKey));
+ }
+
+ try
+ {
+ String payload = "This is a response: sing together: 'Mahnah mahnah...'" + tm.Text;
+ ITextMessage msg = _channel.CreateTextMessage(payload);
+ if ( tm.Headers.Contains("timeSent") )
+ {
+ msg.Headers["timeSent"] = tm.Headers["timeSent"];
+ }
+ _destinationPublisher.Send(msg);
+ } catch ( QpidException e )
+ {
+ _logger.Error("Error sending message: " + e, e);
+ throw e;
+ } finally
+ {
+ _destinationPublisher.Dispose();
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/old/ServiceRequestingClient.tmp b/dotnet/Qpid.Integration.Tests/old/ServiceRequestingClient.tmp
new file mode 100644
index 0000000000..da0f764bcd
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/old/ServiceRequestingClient.tmp
@@ -0,0 +1,182 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ public class ServiceRequestingClient : BaseMessagingTestFixture
+ {
+ private const int MESSAGE_SIZE = 1024;
+ private static string MESSAGE_DATA = new string('x', MESSAGE_SIZE);
+
+ private const int PACK = 100;
+ private const int NUM_MESSAGES = PACK*10; // increase when in standalone
+
+ private static ILog _log = LogManager.GetLogger(typeof(ServiceRequestingClient));
+
+ ManualResetEvent _finishedEvent = new ManualResetEvent(false);
+
+ private int _expectedMessageCount = NUM_MESSAGES;
+
+ private long _startTime = 0;
+
+ private string _commandQueueName = "ServiceQ1";
+
+ private IMessagePublisher _publisher;
+
+ Avergager averager = new Avergager();
+
+ private void InitialiseProducer()
+ {
+ try
+ {
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithRoutingKey(_commandQueueName)
+ .WithDeliveryMode(DeliveryMode.NonPersistent)
+ .Create();
+ _publisher.DisableMessageTimestamp = true; // XXX: need a "with" for this in builder?
+ }
+ catch (QpidException e)
+ {
+ _log.Error("Error: " + e, e);
+ }
+ }
+
+ [Test]
+ public void SendMessages()
+ {
+ InitialiseProducer();
+
+ string replyQueueName = _channel.GenerateUniqueName();
+
+ _channel.DeclareQueue(replyQueueName, false, true, true);
+
+ IMessageConsumer messageConsumer = _channel.CreateConsumerBuilder(replyQueueName)
+ .WithPrefetchLow(100)
+ .WithPrefetchHigh(200)
+ .WithNoLocal(true)
+ .WithExclusive(true).Create();
+
+ _startTime = DateTime.Now.Ticks;
+
+ messageConsumer.OnMessage = new MessageReceivedDelegate(OnMessage);
+ _connection.Start();
+ for (int i = 0; i < _expectedMessageCount; i++)
+ {
+ ITextMessage msg;
+ try
+ {
+ msg = _channel.CreateTextMessage(MESSAGE_DATA + i);
+ }
+ catch (Exception e)
+ {
+ _log.Error("Error creating message: " + e, e);
+ break;
+ }
+ msg.ReplyToRoutingKey = replyQueueName;
+
+ // Added timestamp.
+ long timeNow = DateTime.Now.Ticks;
+ string timeSentString = String.Format("{0:G}", timeNow);
+ msg.Headers.SetLong("timeSent", timeNow);
+
+ _publisher.Send(msg);
+ }
+
+ // Assert that the test finishes within a reasonable amount of time.
+ const int waitSeconds = 40;
+ const int waitMilliseconds = waitSeconds * 1000;
+ _log.Info("Finished sending " + _expectedMessageCount + " messages");
+ _log.Info(String.Format("Waiting {0} seconds to receive last message...", waitSeconds));
+ Assert.IsTrue(_finishedEvent.WaitOne(waitMilliseconds, false),
+ String.Format("Expected to finish in {0} seconds", waitSeconds));
+ }
+
+ public void OnMessage(IMessage m)
+ {
+ if (_log.IsDebugEnabled)
+ {
+ _log.Debug("Message received: " + m);
+ }
+
+ if (!m.Headers.Contains("timeSent"))
+ {
+ throw new Exception("Set timeSent!");
+ }
+
+ long sentAt = m.Headers.GetLong("timeSent");
+ long now = DateTime.Now.Ticks;
+ long latencyTicks = now - sentAt;
+ long latencyMilliseconds = latencyTicks / TimeSpan.TicksPerMillisecond;
+
+ averager.Add(latencyMilliseconds);
+
+ if (averager.Num % PACK == 0)
+ {
+ _log.Info("Ticks per millisecond = " + TimeSpan.TicksPerMillisecond);
+ _log.Info(String.Format("Average latency (ms) = {0}", averager));
+ _log.Info("Received message count: " + averager.Num);
+ }
+
+ if (averager.Num == _expectedMessageCount)
+ {
+ _log.Info(String.Format("Final average latency (ms) = {0}", averager));
+
+ double timeTakenSeconds = (DateTime.Now.Ticks - _startTime) * 1.0 / (TimeSpan.TicksPerMillisecond * 1000);
+ _log.Info("Total time taken to receive " + _expectedMessageCount + " messages was " +
+ timeTakenSeconds + "s, equivalent to " +
+ (_expectedMessageCount/timeTakenSeconds) + " messages per second");
+
+ _finishedEvent.Set(); // Notify main thread to quit.
+ }
+ }
+ }
+
+ class Avergager
+ {
+ long num = 0;
+ long sum = 0;
+
+ long min = long.MaxValue;
+ long max = long.MinValue;
+
+ public void Add(long item)
+ {
+ ++num;
+ sum += item;
+ if (item < min) min = item;
+ if (item > max) max = item;
+ }
+
+ public long Average { get { return sum/num; }}
+
+ public long Num { get { return num; } }
+
+ public override string ToString()
+ {
+ return String.Format("average={0} min={1} max={2}", Average, min, max);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/BaseMessagingTestFixture.cs b/dotnet/Qpid.Integration.Tests/testcases/BaseMessagingTestFixture.cs
new file mode 100644
index 0000000000..e67d96f188
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/BaseMessagingTestFixture.cs
@@ -0,0 +1,280 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// Provides a basis for writing Unit tests that communicate with an AMQ protocol broker. By default it creates a connection
+ /// to a message broker running on localhost on the standard AMQ port, 5672, using guest:guest login credentials. It also
+ /// creates a standard auto-ack channel on this connection.
+ /// </summary>
+ public class BaseMessagingTestFixture
+ {
+ private static ILog log = LogManager.GetLogger(typeof(BaseMessagingTestFixture));
+
+ /// <summary> Used to build dummy data to fill test messages with. </summary>
+ private const string MESSAGE_DATA_BYTES = "-- Test Message -- Test Message -- Test Message -- Test Message -- Test Message ";
+
+ /// <summary> The default timeout in milliseconds to use on receives. </summary>
+ private const long RECEIVE_WAIT = 2000;
+
+ /// <summary> The default AMQ connection URL to use for tests. </summary>
+ public const string connectionUri = "amqp://guest:guest@test/test?brokerlist='tcp://localhost:5672'";
+
+ /// <summary> The default AMQ connection URL parsed as a connection info. </summary>
+ protected IConnectionInfo connectionInfo;
+
+ /// <summary> Holds an array of connections for building mutiple test end-points. </summary>
+ protected IConnection[] testConnection = new IConnection[10];
+
+ /// <summary> Holds an array of channels for building mutiple test end-points. </summary>
+ protected IChannel[] testChannel = new IChannel[10];
+
+ /// <summary> Holds an array of queues for building mutiple test end-points. </summary>
+ protected String[] testQueue = new String[10];
+
+ /// <summary> Holds an array of producers for building mutiple test end-points. </summary>
+ protected IMessagePublisher[] testProducer = new IMessagePublisher[10];
+
+ /// <summary> Holds an array of consumers for building mutiple test end-points. </summary>
+ protected IMessageConsumer[] testConsumer = new IMessageConsumer[10];
+
+ /// <summary> A counter used to supply unique ids. </summary>
+ private static int uniqueId = 0;
+
+ /// <summary> Used to hold unique ids per test. </summary>
+ protected Guid testId;
+
+ /// <summary> Creates the test connection and channel. </summary>
+ [SetUp]
+ public virtual void Init()
+ {
+ log.Debug("public virtual void Init(): called");
+
+ // Set up a unique id for this test.
+ testId = System.Guid.NewGuid();
+ }
+
+ /// <summary>
+ /// Disposes of the test connection. This is called manually because the connection is a field so dispose will not be automatically
+ /// called on it.
+ /// </summary>
+ [TearDown]
+ public virtual void Shutdown()
+ {
+ log.Debug("public virtual void Shutdown(): called");
+ }
+
+ /// <summary> Sets up the nth test end-point. </summary>
+ ///
+ /// <param name="n">The index of the test end-point to set up.</param>
+ /// <param name="producer"><tt>true</tt> to set up a producer on the end-point.</param>
+ /// <param name="consumer"><tt>true</tt> to set up a consumer on the end-point.</param>
+ /// <param name="routingKey">The routing key for the producer to send on.</param>
+ /// <param name="ackMode">The ack mode for the end-points channel.</param>
+ /// <param name="transacted"><tt>true</tt> to use transactions on the end-points channel.</param>
+ /// <param name="exchangeName">The exchange to produce or consume on.</param>
+ /// <param name="declareBind"><tt>true</tt> if the consumers queue should be declared and bound, <tt>false</tt> if it has already been.</param>
+ /// <param name="durable"><tt>true</tt> to declare the consumers queue as durable.</param>
+ /// <param name="subscriptionName">If durable is true, the fixed unique queue name to use.</param>
+ public void SetUpEndPoint(int n, bool producer, bool consumer, string routingKey, AcknowledgeMode ackMode, bool transacted,
+ string exchangeName, bool declareBind, bool durable, string subscriptionName)
+ {
+ SetUpEndPoint(n, producer, consumer, routingKey, ackMode, transacted, exchangeName, declareBind, durable, subscriptionName, true, false);
+ }
+ /// <summary> Sets up the nth test end-point. </summary>
+ ///
+ /// <param name="n">The index of the test end-point to set up.</param>
+ /// <param name="producer"><tt>true</tt> to set up a producer on the end-point.</param>
+ /// <param name="consumer"><tt>true</tt> to set up a consumer on the end-point.</param>
+ /// <param name="routingKey">The routing key for the producer to send on.</param>
+ /// <param name="ackMode">The ack mode for the end-points channel.</param>
+ /// <param name="transacted"><tt>true</tt> to use transactions on the end-points channel.</param>
+ /// <param name="exchangeName">The exchange to produce or consume on.</param>
+ /// <param name="declareBind"><tt>true</tt> if the consumers queue should be declared and bound, <tt>false</tt> if it has already been.</param>
+ /// <param name="durable"><tt>true</tt> to declare the consumers queue as durable.</param>
+ /// <param name="subscriptionName">If durable is true, the fixed unique queue name to use.</param>
+ /// <param name="exclusive"><tt>true</tt> declare queue as exclusive.</param>
+ /// <param name="browse"><tt>true</tt> only browse, don''t consume.</param>
+ public void SetUpEndPoint(int n, bool producer, bool consumer, string routingKey, AcknowledgeMode ackMode, bool transacted,
+ string exchangeName, bool declareBind, bool durable, string subscriptionName, bool exclusive, bool browse)
+ {
+ // Allow client id to be fixed, or undefined.
+ {
+ // Use unique id for end point.
+ connectionInfo = QpidConnectionInfo.FromUrl(connectionUri);
+
+ connectionInfo.ClientName = "test" + n;
+ }
+
+ testConnection[n] = new AMQConnection(connectionInfo);
+ testConnection[n].Start();
+ testChannel[n] = testConnection[n].CreateChannel(transacted, ackMode);
+
+ if (producer)
+ {
+ testProducer[n] = testChannel[n].CreatePublisherBuilder()
+ .WithExchangeName(exchangeName)
+ .WithRoutingKey(routingKey)
+ .Create();
+ }
+
+ if (consumer)
+ {
+ string queueName;
+
+ // Use the subscription name as the queue name if the subscription is durable, otherwise use a generated name.
+ if (durable)
+ {
+ // The durable queue is declared without auto-delete, and passively, in case it has already been declared.
+ queueName = subscriptionName;
+
+ if (declareBind)
+ {
+ testChannel[n].DeclareQueue(queueName, durable, exclusive, false);
+ testChannel[n].Bind(queueName, exchangeName, routingKey);
+ }
+ }
+ else
+ {
+ queueName = testChannel[n].GenerateUniqueName();
+
+ if (declareBind)
+ {
+ if (durable)
+ {
+ testQueue[n] = queueName;
+ }
+ testChannel[n].DeclareQueue(queueName, durable, true, true);
+ testChannel[n].Bind(queueName, exchangeName, routingKey);
+ }
+ }
+
+ testConsumer[n] = testChannel[n].CreateConsumerBuilder(queueName).WithBrowse(browse).Create();
+ }
+ }
+
+ /// <summary> Closes down the nth test end-point. </summary>
+ public void CloseEndPoint(int n)
+ {
+ log.Debug("public void CloseEndPoint(int n): called");
+
+ if (testProducer[n] != null)
+ {
+ testProducer[n].Close();
+ testProducer[n].Dispose();
+ testProducer[n] = null;
+ }
+
+ if (testConsumer[n] != null)
+ {
+ if (testQueue[n] != null)
+ {
+ testChannel[n].DeleteQueue(testQueue[n], false, false, true);
+ }
+ testConsumer[n].Close();
+ testConsumer[n].Dispose();
+ testConsumer[n] = null;
+ }
+
+ if (testConnection[n] != null)
+ {
+ testConnection[n].Stop();
+ testConnection[n].Close();
+ testConnection[n].Dispose();
+ testConnection[n] = null;
+ }
+ }
+
+ /// <summary>
+ /// Consumes n messages, checking that the n+1th is not available within a timeout, and that the consumed messages
+ /// are text messages with contents equal to the specified message body.
+ /// </summary>
+ ///
+ /// <param name="n">The number of messages to consume.</param>
+ /// <param name="body">The body text to match against all messages.</param>
+ /// <param name="consumer">The message consumer to recieve the messages on.</param>
+ public static void ConsumeNMessagesOnly(int n, string body, IMessageConsumer consumer)
+ {
+ ConsumeNMessages(n, body, consumer);
+
+ // Check that one more than n cannot be received.
+ IMessage msg = consumer.Receive(RECEIVE_WAIT);
+ Assert.IsNull(msg, "Consumer got more messages than the number requested (" + n + ").");
+ }
+
+ /// <summary>
+ /// Consumes n messages, checking that the n+1th is not available within a timeout, and that the consumed messages
+ /// are text messages with contents equal to the specified message body.
+ /// </summary>
+ ///
+ /// <param name="n">The number of messages to consume.</param>
+ /// <param name="body">The body text to match against all messages.</param>
+ /// <param name="consumer">The message consumer to recieve the messages on.</param>
+ public static void ConsumeNMessages(int n, string body, IMessageConsumer consumer)
+ {
+ IMessage msg;
+
+ // Try to receive n messages.
+ for (int i = 0; i < n; i++)
+ {
+ msg = consumer.Receive(RECEIVE_WAIT);
+ Assert.IsNotNull(msg, "Consumer did not receive message number: " + i);
+ Assert.AreEqual(body, ((ITextMessage)msg).Text, "Incorrect Message recevied on consumer1.");
+ }
+ }
+
+ /// <summary>Creates the requested number of bytes of dummy text. Usually used for filling test messages. </summary>
+ ///
+ /// <param name="size">The number of bytes of dummy text to generate.</param>
+ ///
+ /// <return>The requested number of bytes of dummy text.</return>
+ public static String GetData(int size)
+ {
+ StringBuilder buf = new StringBuilder(size);
+
+ if (size > 0)
+ {
+ int div = MESSAGE_DATA_BYTES.Length / size;
+ int mod = MESSAGE_DATA_BYTES.Length % size;
+
+ for (int i = 0; i < div; i++)
+ {
+ buf.Append(MESSAGE_DATA_BYTES);
+ }
+
+ if (mod != 0)
+ {
+ buf.Append(MESSAGE_DATA_BYTES, 0, mod);
+ }
+ }
+
+ return buf.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/ChannelQueueTest.cs b/dotnet/Qpid.Integration.Tests/testcases/ChannelQueueTest.cs
new file mode 100644
index 0000000000..4692e7ecb1
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/ChannelQueueTest.cs
@@ -0,0 +1,237 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Net;
+using System.Threading;
+using log4net;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Messaging;
+using NUnit.Framework;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// Test the queue methods
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class ChannelQueueTest
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(ChannelQueueTest));
+
+ /// <summary> The default AMQ connection URL to use for tests. </summary>
+ const string DEFAULT_URI = "amqp://guest:guest@default/test?brokerlist='tcp://localhost:5672'";
+ const string _routingKey = "ServiceQ1";
+
+ private ExceptionListenerDelegate _exceptionDelegate;
+ private AutoResetEvent _evt = new AutoResetEvent(false);
+ private Exception _lastException = null;
+
+ private IMessageConsumer _consumer;
+ private IMessagePublisher _publisher;
+ private IChannel _channel;
+ private IConnection _connection;
+
+ private string _queueName;
+
+ [SetUp]
+ public virtual void Init()
+ {
+ _logger.Info("public virtual void Init(): called");
+
+ // Create a connection to the broker.
+ IConnectionInfo connectionInfo = QpidConnectionInfo.FromUrl(DEFAULT_URI);
+ _connection = new AMQConnection(connectionInfo);
+ _logger.Info("Starting...");
+
+ // Register this to listen for exceptions on the test connection.
+ _exceptionDelegate = new ExceptionListenerDelegate(OnException);
+ _connection.ExceptionListener += _exceptionDelegate;
+
+ // Establish a session on the broker.
+ _channel = _connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge, 1);
+
+ // Create a durable, non-temporary, non-exclusive queue.
+ _queueName = _channel.GenerateUniqueName();
+ _channel.DeclareQueue(_queueName, true, false, false);
+
+ _channel.Bind(_queueName, ExchangeNameDefaults.TOPIC, _routingKey);
+
+ // Clear the most recent message and exception.
+ _lastException = null;
+ }
+
+ [TearDown]
+ public virtual void ShutDown()
+ {
+ _logger.Info("public virtual void Shutdown(): called");
+
+ if (_connection != null)
+ {
+ _logger.Info("Disposing connection.");
+ _connection.Dispose();
+ _logger.Info("Connection disposed.");
+ }
+ }
+
+ [Test]
+ public void DeleteUsedQueue()
+ {
+ // Create the consumer
+ _consumer = _channel.CreateConsumerBuilder(_queueName)
+ .WithPrefetchLow(100)
+ .Create();
+ _logger.Info("Consumer was created...");
+
+ // delete the queue
+ _channel.DeleteQueue(_queueName, false, true, true);
+ _logger.InfoFormat("Queue {0} was delete", _queueName);
+
+ Assert.IsNull(_lastException);
+ }
+
+ [Test]
+ public void DeleteUnusedQueue()
+ {
+ // delete the queue
+ _channel.DeleteQueue(_queueName, true, true, true);
+ _logger.InfoFormat("Queue {0} was delete", _queueName);
+
+ Assert.IsNull(_lastException);
+ }
+
+ [Test]
+ public void DeleteNonEmptyQueue()
+ {
+ // Create the publisher
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(_routingKey)
+ .Create();
+ _logger.Info("Publisher created...");
+ SendTestMessage("DeleteNonEmptyQueue Message 1");
+
+ try
+ {
+ _channel.DeleteQueue(_queueName, true, false, true);
+ }
+ catch (AMQException)
+ {
+ Assert.Fail("The test fails");
+ }
+ }
+
+ [Test]
+ public void DeleteEmptyQueue()
+ {
+ // Create the publisher
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(_routingKey)
+ .Create();
+ _logger.Info("Publisher created...");
+
+ // delete an empty queue with ifEmpty = true
+ _channel.DeleteQueue(_queueName, false, true, true);
+
+ Assert.IsNull(_lastException);
+ }
+
+ [Test]
+ public void DeleteQueueWithResponse()
+ {
+ // Create the publisher
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(_routingKey)
+ .Create();
+ _logger.Info("Publisher created...");
+
+ SendTestMessage("DeleteQueueWithResponse Message 1");
+ SendTestMessage("DeleteQueueWithResponse Message 2");
+
+ // delete the queue, the server must respond
+ _channel.DeleteQueue(_queueName, false, false, false);
+ }
+
+ [Test]
+ public void PurgeQueueWithResponse()
+ {
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(_routingKey)
+ .Create();
+ _logger.Info("Pubisher created");
+
+ SendTestMessage("Message 1");
+ SendTestMessage("Message 2");
+
+ _channel.PurgeQueue(_queueName, false);
+ }
+
+ [Test]
+ public void PurgeQueueWithOutResponse()
+ {
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(ExchangeNameDefaults.TOPIC)
+ .WithRoutingKey(_routingKey)
+ .Create();
+ _logger.Info("Pubisher created");
+
+ SendTestMessage("Message 1");
+ SendTestMessage("Message 2");
+
+ _channel.PurgeQueue(_queueName, true);
+ }
+
+
+ /// <summary>
+ /// Callback method to handle any exceptions raised by the test connection.</summary> ///
+ /// <param name="e">The connection exception.</param>
+ public void OnException(Exception e)
+ {
+ // Preserve the most recent exception in case test cases need to examine it.
+ _lastException = e;
+
+ // Notify any waiting threads that an exception event has occurred.
+ _evt.Set();
+ }
+
+ /// <summary>
+ /// Sends the specified message to the test publisher, and confirms that it was received by the test consumer or not
+ /// depending on whether or not the message should be received by the consumer.
+ ///
+ /// Any exceptions raised by the connection will cause an Assert failure exception to be raised.
+ /// </summary>
+ ///
+ /// <param name="msgSend">The message to send.</param>
+ private void SendTestMessage(string msg)
+ {
+ // create the IMessage object
+ IMessage msgSend = _channel.CreateTextMessage(msg);
+
+ // send the message
+ _publisher.Send(msgSend);
+ _logger.InfoFormat("The messages \"{0}\" was sent", msg);
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/CommitRollbackTest.cs b/dotnet/Qpid.Integration.Tests/testcases/CommitRollbackTest.cs
new file mode 100644
index 0000000000..dbb3f70aec
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/CommitRollbackTest.cs
@@ -0,0 +1,261 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// CommitRollbackTest
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Check that an uncommitted send cannot be received.
+ /// <tr><td> Check that a committed send can be received.
+ /// <tr><td> Check that a rolled back send cannot be received.
+ /// <tr><td> Check that an uncommitted receive can be re-received.
+ /// <tr><td> Check that a committed receive cannot be re-received.
+ /// <tr><td> Check that a rolled back receive can be re-received.
+ /// </table>
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class CommitRollbackTest : BaseMessagingTestFixture
+ {
+ /// <summary>Used for debugging purposes.</summary>
+ private static ILog log = LogManager.GetLogger(typeof(CommitRollbackTest));
+
+ /// <summary>Defines the name of the test topic to use with the tests.</summary>
+ public const string TEST_ROUTING_KEY = "commitrollbacktestkey";
+
+ /// <summary>Used to count test messages received so far.</summary>
+ private int messageReceivedCount;
+
+ /// <summary>Used to hold the expected number of messages to receive.</summary>
+ private int expectedMessageCount;
+
+ /// <summary>Monitor used to signal succesfull receipt of all test messages.</summary>
+ AutoResetEvent finishedEvent;
+
+ /// <summary>Flag used to indicate that all messages really were received, and that the test did not just time out. </summary>
+ private bool allReceived;
+
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+
+ // Create one producer and one consumer, p2p, tx, consumer with queue bound to producers routing key.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+ SetUpEndPoint(1, true, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+
+ // Clear counts
+ messageReceivedCount = 0;
+ expectedMessageCount = 0;
+ finishedEvent = new AutoResetEvent(false);
+ allReceived = false;
+ }
+
+ [TearDown]
+ public override void Shutdown()
+ {
+ try
+ {
+ // Clean up after the test.
+ CloseEndPoint(0);
+ CloseEndPoint(1);
+ }
+ finally
+ {
+ base.Shutdown();
+ }
+ }
+
+ /// <summary> Check that an uncommitted send cannot be received. </summary>
+ [Test]
+ public void TestUncommittedSendNotReceived()
+ {
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(0, "A", testConsumer[1]);
+ testChannel[1].Commit();
+ }
+
+ /// <summary> Check that a committed send can be received. </summary>
+ [Test]
+ public void TestCommittedSendReceived()
+ {
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("B"));
+ testChannel[0].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "B", testConsumer[1]);
+ testChannel[1].Commit();
+ }
+
+ /// <summary> Check that a rolled back send cannot be received. </summary>
+ [Test]
+ public void TestRolledBackSendNotReceived()
+ {
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("B"));
+ testChannel[0].Rollback();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(0, "B", testConsumer[1]);
+ testChannel[1].Commit();
+ }
+
+ /// <summary> Check that an uncommitted receive can be re-received. </summary>
+ [Test]
+ public void TestUncommittedReceiveCanBeRereceived()
+ {
+ // Create a third end-point as an alternative delivery route for the message.
+ SetUpEndPoint(2, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("C"));
+ testChannel[0].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "C", testConsumer[1]);
+
+ // Close end-point 1 without committing the message, then re-open to consume again.
+ CloseEndPoint(1);
+
+ // Check that the message was released from the rolled back end-point an can be received on the alternative one instead.
+ ConsumeNMessagesOnly(1, "C", testConsumer[2]);
+
+ CloseEndPoint(2);
+ }
+
+ /// <summary> Check that a committed receive cannot be re-received. </summary>
+ [Test]
+ public void TestCommittedReceiveNotRereceived()
+ {
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("D"));
+ testChannel[0].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "D", testConsumer[1]);
+ testChannel[1].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(0, "D", testConsumer[1]);
+ }
+
+ /// <summary> Check that a rolled back receive can be re-received. </summary>
+ [Test]
+ public void TestRolledBackReceiveCanBeRereceived()
+ {
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("E"));
+ testChannel[0].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "E", testConsumer[1]);
+
+ testChannel[1].Rollback();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "E", testConsumer[1]);
+
+ }
+
+ [Test]
+ public void TestReceiveAndSendRollback()
+ {
+ // Send messages
+ testProducer[0].Send(testChannel[0].CreateTextMessage("F"));
+ testChannel[0].Commit();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "F", testConsumer[1]);
+ testProducer[1].Send(testChannel[1].CreateTextMessage("G"));
+ testChannel[1].Rollback();
+
+ // Try to receive messages.
+ ConsumeNMessagesOnly(1, "F", testConsumer[1]);
+
+ }
+
+ [Test]
+ public void TestReceivePrePublished()
+ {
+ // Send messages
+ for (int i = 0; i < 10; ++i)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("G"+i));
+ testChannel[0].Commit();
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ ConsumeNMessages(1, "G"+i, testConsumer[1]);
+ }
+ testChannel[1].Commit();
+ }
+
+ [Test]
+ public void TestReceivePrePublishedOnMessageHandler()
+ {
+ testConsumer[1].OnMessage += new MessageReceivedDelegate(OnMessage);
+ // Send messages
+ for (int i = 0; i < 10; ++i)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("G"+i));
+ testChannel[0].Commit();
+ }
+ expectedMessageCount = 10;
+
+ finishedEvent.WaitOne(new TimeSpan(0, 0, 0, 30), false);
+
+ // Check that all messages really were received.
+ Assert.IsTrue(allReceived, "All messages were not received, only got: " + messageReceivedCount + " but wanted " + expectedMessageCount);
+
+ testChannel[1].Commit();
+ }
+
+ /// <summary> Atomically increments the message count on every message, and signals once all messages in the test are received. </summary>
+ public void OnMessage(IMessage m)
+ {
+ int newCount = Interlocked.Increment(ref messageReceivedCount);
+
+ if (newCount >= expectedMessageCount)
+ {
+ allReceived = true;
+ finishedEvent.Set();
+ }
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/ConnectionTest.cs b/dotnet/Qpid.Integration.Tests/testcases/ConnectionTest.cs
new file mode 100644
index 0000000000..d7b4a4ddd2
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/ConnectionTest.cs
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ [TestFixture, Category("Integration")]
+ public class ConnectionTest
+ {
+ private AmqBrokerInfo _broker =
+ new AmqBrokerInfo("amqp", "localhost", 5672, false);
+
+ [Test]
+ public void SimpleConnection()
+ {
+ IConnectionInfo connectionInfo = new QpidConnectionInfo();
+ connectionInfo.VirtualHost = "test";
+ connectionInfo.AddBrokerInfo(_broker);
+ using (IConnection connection = new AMQConnection(connectionInfo))
+ {
+ Console.WriteLine("connection = " + connection);
+ }
+ }
+
+ [Test]
+ [ExpectedException(typeof(AMQAuthenticationException))]
+ public void PasswordFailureConnection()
+ {
+ IConnectionInfo connectionInfo = new QpidConnectionInfo();
+ connectionInfo.VirtualHost = "test";
+ connectionInfo.Password = "rubbish";
+ connectionInfo.AddBrokerInfo(_broker);
+
+ using (IConnection connection = new AMQConnection(connectionInfo))
+ {
+ Console.WriteLine("connection = " + connection);
+ // wrong
+ Assert.Fail("Authentication succeeded but should've failed");
+ }
+ }
+
+ [Test]
+ [ExpectedException(typeof(AMQConnectionException))]
+ public void ConnectionFailure()
+ {
+ string url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5673?retries='0''";
+ new AMQConnection(QpidConnectionInfo.FromUrl(url));
+ Assert.Fail("Connection should not be established");
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/DurableSubscriptionTest.cs b/dotnet/Qpid.Integration.Tests/testcases/DurableSubscriptionTest.cs
new file mode 100644
index 0000000000..b7973ae3f5
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/DurableSubscriptionTest.cs
@@ -0,0 +1,166 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// DurableSubscriptionTest checks that durable subscriptions work, by sending messages that can be picked up by
+ /// a subscription that is currently off-line, and checking that the subscriber gets all of its messages when it
+ /// does come on-line.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td>
+ /// </table>
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class DurableSubscriptionTest : BaseMessagingTestFixture
+ {
+ /// <summary>Used for debugging purposes.</summary>
+ private static ILog log = LogManager.GetLogger(typeof(DurableSubscriptionTest));
+
+ /// <summary>Defines the name of the test topic to use with the tests.</summary>
+ public const string TEST_ROUTING_KEY = "durablesubtestkey";
+
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+ }
+
+ [TearDown]
+ public override void Shutdown()
+ {
+ base.Shutdown();
+ }
+
+ [Test]
+ public void TestDurableSubscriptionNoAck()
+ {
+ TestDurableSubscription(AcknowledgeMode.NoAcknowledge);
+ }
+
+ [Test]
+ public void TestDurableSubscriptionAutoAck()
+ {
+ TestDurableSubscription(AcknowledgeMode.AutoAcknowledge);
+ }
+
+ private void TestDurableSubscription(AcknowledgeMode ackMode)
+ {
+ // Create a topic with one producer and two consumers.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, ackMode, false, ExchangeNameDefaults.TOPIC, true, false, null);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, ackMode, false, ExchangeNameDefaults.TOPIC, true, false, null);
+ SetUpEndPoint(2, false, true, TEST_ROUTING_KEY + testId, ackMode, false, ExchangeNameDefaults.TOPIC, true,
+ true, "TestSubscription" + testId);
+
+ Thread.Sleep(500);
+
+ // Send messages and receive on both consumers.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+
+ ConsumeNMessagesOnly(1, "A", testConsumer[1]);
+ ConsumeNMessagesOnly(1, "A", testConsumer[2]);
+
+ // Detach one consumer.
+ CloseEndPoint(2);
+
+ // Send message and receive on one consumer.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("B"));
+
+ ConsumeNMessagesOnly(1, "B", testConsumer[1]);
+
+ // Re-attach consumer, check that it gets the messages that it missed.
+ SetUpEndPoint(2, false, true, TEST_ROUTING_KEY + testId, ackMode, false, ExchangeNameDefaults.TOPIC, true,
+ true, "TestSubscription" + testId);
+
+ ConsumeNMessagesOnly(1, "B", testConsumer[2]);
+
+ // Clean up any open consumers at the end of the test.
+ CloseEndPoint(2);
+ CloseEndPoint(1);
+ CloseEndPoint(0);
+ }
+
+ /// <summary> Check that an uncommitted receive can be re-received, on re-consume from the same durable subscription. </summary>
+ [Test]
+ public void TestUncommittedReceiveCanBeRereceivedNewConnection()
+ {
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, true, "foo"+testId);
+
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("C"));
+ testChannel[0].Commit();
+
+ // Try to receive messages, but don't commit them.
+ ConsumeNMessagesOnly(1, "C", testConsumer[1]);
+
+ // Close end-point 1 without committing the message, then re-open the subscription to consume again.
+ CloseEndPoint(1);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, true, "foo"+testId);
+
+ // Check that the message was released from the rolled back end-point an can be received on the alternative one instead.
+ ConsumeNMessagesOnly(1, "C", testConsumer[1]);
+ testChannel[1].Commit();
+ CloseEndPoint(1);
+ CloseEndPoint(0);
+ }
+
+ /// <summary> Check that a rolled back receive can be re-received, on re-consume from the same durable subscription. </summary>
+ [Test]
+ public void TestRolledBackReceiveCanBeRereceivedNewConnection()
+ {
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, true, "foo"+testId);
+
+ // Send messages.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("D"));
+ testChannel[0].Commit();
+
+ // Try to receive messages, but roll them back.
+ ConsumeNMessagesOnly(1, "D", testConsumer[1]);
+ testChannel[1].Rollback();
+
+ // Close end-point 1 without committing the message, then re-open the subscription to consume again.
+ CloseEndPoint(1);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, true, ExchangeNameDefaults.TOPIC,
+ true, true, "foo"+testId);
+
+ // Check that the message was released from the rolled back end-point an can be received on the alternative one instead.
+ ConsumeNMessagesOnly(1, "D", testConsumer[1]);
+ testChannel[1].Commit();
+ CloseEndPoint(1);
+ CloseEndPoint(0);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/HeadersExchangeTest.cs b/dotnet/Qpid.Integration.Tests/testcases/HeadersExchangeTest.cs
new file mode 100644
index 0000000000..2094aa3b1b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/HeadersExchangeTest.cs
@@ -0,0 +1,282 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Framing;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// Sets up a producer/consumer pair to send test messages through a header exchange. The header exchange matching pattern is tested to
+ /// verify that it correctly matches or filters out messages based on their headers.
+ ///
+ /// Check that a message matching all fields of a headers exchange is passed by the exchange.
+ /// Check that a message containing values for empty fields of a headers exchange is passed by the exchange.
+ /// Check that a message matching only some fields of a headers exhcnage is not passed by the exchange.
+ /// Check that a message with additional fields to the correct matching fields of a headers exchange is passed by the exchange.
+ /// </summary>
+ ///
+ /// <todo>Remove the HeadersMatchingProducer class and rename this to HeaderExchangeTest. The producer and consumer are implemented
+ /// in a single test class to make running this as part of an automated test suite possible.</todo>
+ ///
+ /// <todo>Consider not using a delegate to callback the OnMessage method. Easier to just call receive on the consumer but using the
+ /// callback does demonstrate how to do so.</todo>
+ [TestFixture, Category("Integration")]
+ public class HeadersExchangeTest : BaseMessagingTestFixture
+ {
+ private static ILog _logger = LogManager.GetLogger(typeof(HeadersExchangeTest));
+
+ /// <summary> Holds the default test timeout for broker communications before tests give up. </summary>
+ private static readonly int TIMEOUT = 2000;
+
+ /// <summary> Holds the name of the headers exchange to create to send test messages on. </summary>
+ private string _exchangeName = "ServiceQ1";
+
+ /// <summary> Used to preserve the most recent exception in case test cases need to examine it. </summary>
+ private Exception _lastException = null;
+
+ /// <summary> Used to preserve the most recent message from the test consumer. </summary>
+ private IMessage _lastMessage = null;
+
+ /// <summary> The test consumer to get messages from the broker with. </summary>
+ private IMessageConsumer _consumer;
+
+ private IMessagePublisher _publisher;
+
+ private AutoResetEvent _evt = new AutoResetEvent(false);
+
+ private MessageReceivedDelegate _msgRecDelegate;
+ private ExceptionListenerDelegate _exceptionDelegate;
+
+ /// <summary> Holds the test connection. </summary>
+ protected IConnection _connection;
+
+ /// <summary> Holds the test channel. </summary>
+ protected IChannel _channel;
+
+ [SetUp]
+ public override void Init()
+ {
+ // Ensure that the base init method is called. It establishes a connection with the broker.
+ base.Init();
+
+ connectionInfo = QpidConnectionInfo.FromUrl(connectionUri);
+ _connection = new AMQConnection(connectionInfo);
+ _channel = _connection.CreateChannel(false, AcknowledgeMode.AutoAcknowledge, 500, 300);
+
+ _logger.Info("Starting...");
+ _logger.Info("Exchange name is '" + _exchangeName + "'...");
+
+ // Register this to listen for exceptions on the test connection.
+ _exceptionDelegate = new ExceptionListenerDelegate(OnException);
+ _connection.ExceptionListener += _exceptionDelegate;
+
+ // Declare a new headers exchange with the name of the test service.
+ _channel.DeclareExchange(_exchangeName, ExchangeClassConstants.HEADERS);
+
+ // Create a non-durable, temporary (aka auto-delete), exclusive queue.
+ string queueName = _channel.GenerateUniqueName();
+ _channel.DeclareQueue(queueName, false, true, true);
+
+ // Bind the queue to the new headers exchange, setting up some header patterns for the exchange to match.
+ _channel.Bind(queueName, _exchangeName, null, CreatePatternAsFieldTable());
+
+ // Create a test consumer to consume messages from the test exchange.
+ _consumer = _channel.CreateConsumerBuilder(queueName)
+ .WithPrefetchLow(100)
+ .WithPrefetchHigh(500)
+ .WithNoLocal(false) // make sure we get our own messages
+ .Create();
+
+ // Register this to listen for messages on the consumer.
+ _msgRecDelegate = new MessageReceivedDelegate(OnMessage);
+ _consumer.OnMessage += _msgRecDelegate;
+
+ // Clear the most recent message and exception.
+ _lastException = null;
+ _lastMessage = null;
+
+ _publisher = _channel.CreatePublisherBuilder()
+ .WithExchangeName(_exchangeName)
+ .WithMandatory(true)
+ .Create();
+
+ _publisher.DeliveryMode = DeliveryMode.NonPersistent;
+
+ // Start all channel
+ _connection.Start();
+ }
+
+ /// <summary>
+ /// Deregisters the on message delegate before closing the connection.
+ /// </summary>
+ [TearDown]
+ public override void Shutdown()
+ {
+ _logger.Info("public void Shutdown(): called");
+
+ //_consumer.OnMessage -= _msgRecDelegate;
+ //_connection.ExceptionListener -= _exceptionDelegate;
+
+ _connection.Stop();
+ _connection.Close();
+ _connection.Dispose();
+
+ base.Shutdown();
+ }
+
+ /// <summary>
+ /// Callback method that is passed any messages received on the test channel.
+ /// </summary>
+ ///
+ /// <param name="message">The received message.</param>
+ public void OnMessage(IMessage message)
+ {
+ _logger.Debug(string.Format("message.Type = {0}", message.GetType()));
+ _logger.Debug("Got message '" + message + "'");
+
+ // Preserve the most recent exception so that test cases can examine it.
+ _lastMessage = message;
+
+ // Notify any waiting threads that a message has been received.
+ _evt.Set();
+ }
+
+ /// <summary>Callback method to handle any exceptions raised by the test connection.</summary>
+ ///
+ /// <param name="e">The connection exception.</param>
+ public void OnException(Exception e)
+ {
+ // Preserve the most recent exception in case test cases need to examine it.
+ _lastException = e;
+
+ // Notify any waiting threads that an exception event has occurred.
+ _evt.Set();
+ }
+
+ /// <summary>Check that a message matching all fields of a headers exchange is passed by the exchange.</summary>
+ [Test]
+ public void TestMatchAll()
+ {
+ IMessage msg = _channel.CreateTextMessage("matches match2=''");
+ msg.Headers["match1"] = "foo";
+ msg.Headers["match2"] = "";
+
+ // Use the SendTestMessage helper method to verify that the message was sent and received.
+ SendTestMessage(msg, true);
+ }
+
+ /// <summary>Check that a message containing values for empty fields of a headers exchange is passed by the exchange.</summary>
+ [Test]
+ public void TestMatchEmptyMatchesAnything()
+ {
+ // Send a test message that matches the headers exchange.
+ IMessage msg = _channel.CreateTextMessage("matches match1='foo' and match2='bar'");
+ msg.Headers["match1"] = "foo";
+ msg.Headers["match2"] = "bar";
+
+ // Use the SendTestMessage helper method to verify that the message was sent and received.
+ SendTestMessage(msg, true);
+ }
+
+ /// <summary>Check that a message matching only some fields of a headers exchange is not passed by the exchange.</summary>
+ [Test]
+ public void TestMatchOneFails()
+ {
+ IMessage msg = _channel.CreateTextMessage("not match - only match1");
+ msg.Headers["match1"] = "foo";
+
+ // Use the SendTestMessage helper method to verify that the message was sent and not received.
+ SendTestMessage(msg, false);
+ }
+
+ /// <summary>
+ /// Check that a message with additional fields to the correct matching fields of a headers exchange is passed by
+ /// the exchange.
+ /// </summary>
+ [Test]
+ public void TestMatchExtraFields()
+ {
+ IMessage msg = _channel.CreateTextMessage("matches - extra headers");
+ msg.Headers["match1"] = "foo";
+ msg.Headers["match2"] = "bar";
+ msg.Headers["match3"] = "not required";
+
+ // Use the SendTestMessage helper method to verify that the message was sent and received.
+ SendTestMessage(msg, true);
+ }
+
+ /// <summary>
+ /// Sends the specified message to the test publisher, and confirms that it was received by the test consumer or not
+ /// depending on whether or not the message should be received by the consumer.
+ ///
+ /// Any exceptions raised by the connection will cause an Assert failure exception to be raised.
+ /// </summary>
+ ///
+ /// <param name="msgSend">The message to send.</param>
+ /// <param name="shouldPass">A flag to indicate whether or not the message should be received by the consumer.</param>
+ private void SendTestMessage(IMessage msgSend, bool shouldPass)
+ {
+ _publisher.Send(msgSend);
+ _evt.WaitOne(TIMEOUT, true);
+
+ // Check that an exception other than not routable was raised in which case re-raise it as a test error.
+ if (_lastException != null && !(_lastException.InnerException is AMQUndeliveredException))
+ {
+ Assert.Fail("Exception {0} was raised by the broker connection.", _lastException);
+ }
+ // Check that a message was returned if the test is expecting the message to pass.
+ else if (shouldPass)
+ {
+ Assert.IsNotNull(_lastMessage, "Did not get a matching message from the headers exchange.");
+ }
+ // Check that a not routable exception was raised if the test is expecting the message to fail.
+ else if (_lastException != null && _lastException.InnerException is AMQUndeliveredException)
+ {
+ Assert.IsNull(_lastMessage, "Message could not be routed so consumer should not have received it.");
+ }
+ // The broker did not respond within the test timeout so fail the test.
+ else
+ {
+ Assert.Fail("The test timed out without a response from the broker.");
+ }
+ }
+
+ /// <summary> Returns a field table containing patterns to match the test header exchange against. </summary>
+ ///
+ /// <returns> A field table containing test patterns. </returns>
+ private FieldTable CreatePatternAsFieldTable()
+ {
+ FieldTable matchTable = new FieldTable();
+
+ matchTable["match1"] = "foo";
+ matchTable["match2"] = "";
+ matchTable["x-match"] = "all";
+
+ return matchTable;
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/MandatoryMessageTest.cs b/dotnet/Qpid.Integration.Tests/testcases/MandatoryMessageTest.cs
new file mode 100644
index 0000000000..4abc56905f
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/MandatoryMessageTest.cs
@@ -0,0 +1,149 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// MandatoryMessageTest checks that messages sent with the 'mandatory' flag, must either be routed to a valid
+ /// queue or returned to the sender when no route is available.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Check default exchange returns unroutable mandatory messages.
+ /// <tr><td> Check direct exchange returns unroutable mandatory messages.
+ /// <tr><td> Check headers exchange returns unroutable mandatory messages.
+ /// <tr><td> Check topic exchange returns unroutable mandatory messages.
+ /// </table>
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class MandatoryMessageTest : BaseMessagingTestFixture
+ {
+ /// <summary>Used for debugging purposes.</summary>
+ private static ILog log = LogManager.GetLogger(typeof(MandatoryMessageTest));
+
+ /// <summary>Defines the maximum time in milliseconds, to wait for redelivery to occurr.</summary>
+ public const int TIMEOUT = 1000;
+
+ /// <summary>Defines the name of the routing key to use with the tests.</summary>
+ public const string TEST_ROUTING_KEY = "unboundkey";
+
+ /// <summary>Condition used to coordinate receipt of redelivery exception to the sending thread.</summary>
+ private ManualResetEvent errorEvent;
+
+ /// <summary>Holds the last received error condition, for examination by the tests sending thread.</summary>
+ private Exception lastErrorException;
+
+ /// <summary> Holds the test connection. </summary>
+ protected IConnection _connection;
+
+ /// <summary> Holds the test channel. </summary>
+ protected IChannel _channel;
+
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+
+ errorEvent = new ManualResetEvent(false);
+ lastErrorException = null;
+ }
+
+ [TearDown]
+ public override void Shutdown()
+ {
+ base.Shutdown();
+ }
+
+ /// <summary>
+ /// Handles all exception conditions on the connection. The error event is notified and the exception recorded as the last seen.
+ /// </summary>
+ ///
+ /// <param name="e">The asynchronous exception on the connection.</param>
+ public void OnException(Exception e)
+ {
+ lastErrorException = e;
+ errorEvent.Set();
+ }
+
+ [Test]
+ public void SendUndeliverableMessageOnDirectExchange()
+ {
+ SendOne(ExchangeNameDefaults.DIRECT);
+ }
+
+ [Test]
+ public void SendUndeliverableMessageOnTopicExchange()
+ {
+ SendOne(ExchangeNameDefaults.TOPIC);
+ }
+
+ [Test]
+ public void SendUndeliverableMessageOnHeadersExchange()
+ {
+ SendOne(ExchangeNameDefaults.HEADERS);
+ }
+
+ /// <summary>
+ /// Sends a single message to the specified exchange with the routing key 'unboundkey', marked as mandatory.
+ /// A check is performed to assert that a redelivery error is returned from the broker for the message.
+ /// </summary>
+ ///
+ /// <param name="exchangeName">The name of the exchange to send to.</param>
+ private void SendOne(string exchangeName)
+ {
+ log.Debug("private void SendOne(string exchangeName = " + exchangeName + "): called");
+
+ // Send a test message to a unbound key on the specified exchange.
+ SetUpEndPoint(0, false, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, exchangeName,
+ true, false, null);
+ testProducer[0] = testChannel[0].CreatePublisherBuilder()
+ .WithRoutingKey(TEST_ROUTING_KEY + testId)
+ .WithMandatory(true)
+ .WithExchangeName(exchangeName)
+ .Create();
+
+ // Set up the exception listener on the connection.
+ testConnection[0].ExceptionListener = new ExceptionListenerDelegate(OnException);
+
+ // Send message that should fail.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("Test Message"));
+
+ // Wait for up to the timeout for a redelivery exception to be returned.
+ errorEvent.WaitOne(TIMEOUT, true);
+
+ // Asserts that a redelivery exception was returned, and is of the correct type.
+ Type expectedException = typeof(AMQUndeliveredException);
+ Exception ex = lastErrorException;
+
+ Assert.IsNotNull(ex, "No exception was thrown by the test. Expected " + expectedException);
+ Assert.IsInstanceOfType(expectedException, ex.InnerException);
+
+ CloseEndPoint(0);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/ProducerMultiConsumerTest.cs b/dotnet/Qpid.Integration.Tests/testcases/ProducerMultiConsumerTest.cs
new file mode 100644
index 0000000000..bae6c76818
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/ProducerMultiConsumerTest.cs
@@ -0,0 +1,167 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Text;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// ProducerMultiConsumerTest provides some tests for one producer and multiple consumers.
+ ///
+ /// <p><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Check that all consumers on a topic each receive all message on it.
+ /// <tr><td> Check that consumers on the same queue receive each message once accross all consumers.
+ /// </table>
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class ProducerMultiConsumerTest : BaseMessagingTestFixture
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(ProducerMultiConsumerTest));
+
+ /// <summary>Base name for the routing key used for this test (made unique by adding in test id).</summary>
+ private const string TEST_ROUTING_KEY = "ProducerMultiConsumerTest";
+
+ /// <summary>The number of consumers to test.</summary>
+ private const int CONSUMER_COUNT = 5;
+
+ /// <summary>The number of test messages to send.</summary>
+ private const int MESSAGE_COUNT = 10;
+
+ /// <summary>Monitor used to signal succesfull receipt of all test messages.</summary>
+ AutoResetEvent _finishedEvent;
+
+ /// <summary>Used to count test messages received so far.</summary>
+ private int _messageReceivedCount;
+
+ /// <summary>Used to hold the expected number of messages to receive.</summary>
+ private int expectedMessageCount;
+
+ /// <summary>Flag used to indicate that all messages really were received, and that the test did not just time out. </summary>
+ private bool allReceived;
+
+ /// <summary> Creates one producing end-point and many consuming end-points connected on a topic. </summary>
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+
+ // Reset all test counts and flags.
+ _messageReceivedCount = 0;
+ allReceived = false;
+ _finishedEvent = new AutoResetEvent(false);
+ }
+
+ /// <summary> Cleans up all test end-points. </summary>
+ [TearDown]
+ public override void Shutdown()
+ {
+ try
+ {
+ // Close all end points for producer and consumers.
+ // Producer is on 0, and consumers on 1 .. n, so loop is from 0 to n inclusive.
+ for (int i = 0; i <= CONSUMER_COUNT; i++)
+ {
+ CloseEndPoint(i);
+ }
+ }
+ finally
+ {
+ base.Shutdown();
+ }
+ }
+
+ /// <summary> Check that all consumers on a topic each receive all message on it. </summary>
+ [Test]
+ public void AllConsumerReceiveAllMessagesOnTopic()
+ {
+ // Create end-points for all the consumers in the test.
+ for (int i = 1; i <= CONSUMER_COUNT; i++)
+ {
+ SetUpEndPoint(i, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+ testConsumer[i].OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ // Create an end-point to publish to the test topic.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.TOPIC,
+ true, false, null);
+
+ expectedMessageCount = (MESSAGE_COUNT * CONSUMER_COUNT);
+
+ for (int i = 0; i < MESSAGE_COUNT; i++)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+ }
+
+ _finishedEvent.WaitOne(new TimeSpan(0, 0, 0, 30), false);
+
+ // Check that all messages really were received.
+ Assert.IsTrue(allReceived, "All messages were not received, only got " + _messageReceivedCount + " but wanted " + expectedMessageCount);
+ }
+
+ /// <summary> Check that consumers on the same queue receive each message once accross all consumers. </summary>
+ [Test]
+ public void AllConsumerReceiveAllMessagesOnDirect()
+ {
+ // Create end-points for all the consumers in the test.
+ for (int i = 1; i <= CONSUMER_COUNT; i++)
+ {
+ SetUpEndPoint(i, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+ testConsumer[i].OnMessage += new MessageReceivedDelegate(OnMessage);
+ }
+
+ // Create an end-point to publish to the test topic.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+
+ expectedMessageCount = (MESSAGE_COUNT * CONSUMER_COUNT);
+
+ for (int i = 0; i < MESSAGE_COUNT; i++)
+ {
+ testProducer[0].Send(testChannel[0].CreateTextMessage("A"));
+ }
+
+ _finishedEvent.WaitOne(new TimeSpan(0, 0, 0, 30), false);
+
+ // Check that all messages really were received.
+ Assert.IsTrue(allReceived, "All messages were not received, only got: " + _messageReceivedCount + " but wanted " + expectedMessageCount);
+ }
+
+ /// <summary> Atomically increments the message count on every message, and signals once all messages in the test are received. </summary>
+ public void OnMessage(IMessage m)
+ {
+ int newCount = Interlocked.Increment(ref _messageReceivedCount);
+
+ if (newCount >= expectedMessageCount)
+ {
+ allReceived = true;
+ _finishedEvent.Set();
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/Qpid.Integration.Tests.csproj b/dotnet/Qpid.Integration.Tests/testcases/Qpid.Integration.Tests.csproj
new file mode 100755
index 0000000000..01ca2cc5bd
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/Qpid.Integration.Tests.csproj
@@ -0,0 +1,64 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ProjectGuid>{EFEB9E41-B66E-4674-85F7-18FAD056AD67}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Qpid.Integration.Tests</RootNamespace>
+ <AssemblyName>Qpid.Integration.Tests</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <OutputPath>bin\Debug\</OutputPath>
+ <DebugSymbols>True</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DebugSymbols>False</DebugSymbols>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <DefineConstants>TRACE</DefineConstants>
+ </PropertyGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BaseMessagingTestFixture.cs" />
+ <Compile Include="ChannelQueueTest.cs" />
+ <Compile Include="CommitRollbackTest.cs" />
+ <Compile Include="ConnectionTest.cs" />
+ <Compile Include="DurableSubscriptionTest.cs" />
+ <Compile Include="HeadersExchangeTest.cs" />
+ <Compile Include="MandatoryMessageTest.cs" />
+ <Compile Include="ProducerMultiConsumerTest.cs" />
+ <Compile Include="SslConnectionTest.cs" />
+ <Compile Include="QueueBrowsingTest.cs" />
+ </ItemGroup>
+</Project>
diff --git a/dotnet/Qpid.Integration.Tests/testcases/QueueBrowsingTest.cs b/dotnet/Qpid.Integration.Tests/testcases/QueueBrowsingTest.cs
new file mode 100644
index 0000000000..536439a44b
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/QueueBrowsingTest.cs
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Threading;
+using log4net;
+using NUnit.Framework;
+using Apache.Qpid.Messaging;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Framing;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ [TestFixture, Category("Integration")]
+ public class QueueBrowsingTest : BaseMessagingTestFixture
+ {
+ /// <summary>Used for debugging purposes.</summary>
+ private static ILog log = LogManager.GetLogger(typeof(QueueBrowsingTest));
+
+ public const string TEST_ROUTING_KEY = "queuebrowsingkey";
+ public const string TEST_ROUTING_KEY2 = "lvqbrowsingkey";
+
+
+ [SetUp]
+ public override void Init()
+ {
+ base.Init();
+ }
+
+ [TearDown]
+ public override void Shutdown()
+ {
+ base.Shutdown();
+ }
+
+ [Test]
+ public void TestQueueBrowsing()
+ {
+ // Create a topic with one producer and two consumers.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, null, false, false);
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.NoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, TEST_ROUTING_KEY + testId, false, true);
+ SetUpEndPoint(2, false, true, TEST_ROUTING_KEY + testId, AcknowledgeMode.NoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, TEST_ROUTING_KEY + testId, false, true);
+
+ Thread.Sleep(500);
+
+ // Send messages and receive on both consumers.
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+ testProducer[0].Send(testChannel[0].CreateTextMessage("msg"));
+
+ Thread.Sleep(2000);
+
+
+ ConsumeNMessagesOnly(6, "msg", testConsumer[1]);
+ ConsumeNMessagesOnly(6, "msg", testConsumer[2]);
+
+ // Clean up any open consumers at the end of the test.
+ CloseEndPoint(2);
+ CloseEndPoint(1);
+ CloseEndPoint(0);
+ }
+
+ [Test]
+ public void TestQueueBrowsingLVQ()
+ {
+ // Create a topic with one producer and two consumers.
+ SetUpEndPoint(0, true, false, TEST_ROUTING_KEY2 + testId, AcknowledgeMode.AutoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, TEST_ROUTING_KEY2 + testId, false, false);
+ FieldTable args = new FieldTable();
+ args.SetBoolean("qpid.last_value_queue", true);
+ args.SetString("qpid.last_value_queue_key", "key");
+ testChannel[0].DeclareQueue(TEST_ROUTING_KEY2 + testId, true, false, false, args);
+ testChannel[0].Bind(TEST_ROUTING_KEY2 + testId, ExchangeNameDefaults.DIRECT, TEST_ROUTING_KEY2 + testId);
+ Thread.Sleep(500);
+
+
+ for (int i = 0; i < 12; i++)
+ {
+ ITextMessage msg = testChannel[0].CreateTextMessage("msg");
+ msg.Headers.SetInt("key", i%6);
+ testProducer[0].Send(msg);
+ }
+
+ Thread.Sleep(2000);
+
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY2 + testId, AcknowledgeMode.NoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, TEST_ROUTING_KEY2 + testId, false, true);
+ SetUpEndPoint(2, false, true, TEST_ROUTING_KEY2 + testId, AcknowledgeMode.NoAcknowledge, false, ExchangeNameDefaults.DIRECT, true, true, TEST_ROUTING_KEY2 + testId, false, true);
+
+ Thread.Sleep(500);
+
+
+ ConsumeNMessagesOnly(6, "msg", testConsumer[1]);
+ ConsumeNMessagesOnly(6, "msg", testConsumer[2]);
+
+ // Clean up any open consumers at the end of the test.
+ CloseEndPoint(2);
+ CloseEndPoint(1);
+ CloseEndPoint(0);
+ }
+
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/SslConnectionTest.cs b/dotnet/Qpid.Integration.Tests/testcases/SslConnectionTest.cs
new file mode 100644
index 0000000000..5f953e1470
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/SslConnectionTest.cs
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.IO;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Messaging;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// Test SSL/TLS connections to the broker
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class SslConnectionTest
+ {
+ /// <summary>
+ /// Make a test TLS connection to the broker
+ /// without using client-certificates
+ /// </summary>
+ //[Test]
+ public void DoSslConnection()
+ {
+ // because for tests we don't usually trust the server certificate
+ // we need here to tell the client to ignore certificate validation errors
+ SslOptions sslConfig = new SslOptions(null, true);
+
+ MakeBrokerConnection(sslConfig);
+ }
+
+ private static void MakeBrokerConnection(SslOptions options)
+ {
+ IConnectionInfo connectionInfo = new QpidConnectionInfo();
+ connectionInfo.VirtualHost = "test";
+ connectionInfo.AddBrokerInfo(new AmqBrokerInfo("amqp", "localhost", 8672, options));
+
+ using ( IConnection connection = new AMQConnection(connectionInfo) )
+ {
+ Console.WriteLine("connection = " + connection);
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Integration.Tests/testcases/SustainedTest.cs b/dotnet/Qpid.Integration.Tests/testcases/SustainedTest.cs
new file mode 100644
index 0000000000..4074055eba
--- /dev/null
+++ b/dotnet/Qpid.Integration.Tests/testcases/SustainedTest.cs
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using NUnit.Framework;
+using Apache.Qpid.Client.Qms;
+using Apache.Qpid.Client;
+using Apache.Qpid.Messaging;
+using log4net;
+
+namespace Apache.Qpid.Integration.Tests.testcases
+{
+ /// <summary>
+ /// Runs through the range of ack modes for each test case, sending and recieving a large number of messages
+ /// </summary>
+ [TestFixture, Category("Integration")]
+ public class SustainedTest : BaseMessagingTestFixture
+ {
+ /// <summary>The number of test messages to send.</summary>
+ private const int MESSAGE_COUNT = 50;//00;
+
+ /// <summary>Base name for the routing key used for this test (made unique by adding in test id).</summary>
+ private const string TEST_ROUTING_KEY = "MessageOrderTest";
+
+ /// <summary>
+ /// The logger
+ /// </summary>
+ private static ILog _logger = LogManager.GetLogger(typeof(SustainedTest));
+
+ [Test]
+ public void MessageOrderTestAutoAck()
+ {
+ MessageOrderTest(AcknowledgeMode.AutoAcknowledge);
+ }
+
+ [Test]
+ public void MessageOrderTestNoAck()
+ {
+ MessageOrderTest(AcknowledgeMode.NoAcknowledge);
+ }
+
+ public void MessageOrderTest(AcknowledgeMode consumerMode)
+ {
+
+ // Consumer
+ SetUpEndPoint(1, false, true, TEST_ROUTING_KEY, consumerMode, false, ExchangeNameDefaults.DIRECT,
+ true, false, null);
+
+
+ Console.WriteLine("Starting producer thread");
+ Thread prodThread = new Thread(new ThreadStart(SendMessages));
+ prodThread.Start();
+
+ Thread.Sleep(2000);
+ Console.WriteLine("Starting consuming");
+ for (int i = 0; i < MESSAGE_COUNT; i++)
+ {
+ if ((i % 10) == 0)
+ {
+ Console.WriteLine("Consuming message "+i);
+ }
+ ConsumeNMessages(1, "Msg"+i, testConsumer[1]);
+ }
+ prodThread.Join();
+ CloseEndPoint(0);
+ CloseEndPoint(1);
+ }
+
+ private static void SendMessages()
+ {
+ AMQConnection conn = new AMQConnection(QpidConnectionInfo.FromUrl(BaseMessagingTestFixture.connectionUri));
+ conn.Start();
+ IChannel channel = conn.CreateChannel(false, AcknowledgeMode.AutoAcknowledge);
+ IMessagePublisher producer = channel.CreatePublisherBuilder().
+ WithExchangeName(ExchangeNameDefaults.DIRECT).
+ WithRoutingKey(TEST_ROUTING_KEY).
+ Create();
+
+ for (int i = 0; i < MESSAGE_COUNT ; i++)
+ {
+ if ((i % 10) == 0)
+ {
+ Console.WriteLine("Sending message "+i);
+ }
+ producer.Send(channel.CreateTextMessage("Msg" + i));
+ }
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/AcknowledgeMode.cs b/dotnet/Qpid.Messaging/AcknowledgeMode.cs
new file mode 100644
index 0000000000..4896b64f68
--- /dev/null
+++ b/dotnet/Qpid.Messaging/AcknowledgeMode.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public enum AcknowledgeMode
+ {
+ AutoAcknowledge,
+ ClientAcknowledge,
+ DupsOkAcknowledge,
+ SessionTransacted,
+
+ /// <summary>
+ /// Indicates that no client acknowledgements are required. Broker assumes that once it has
+ /// delivered a message packet successfully it is acknowledged.
+ /// </summary>
+ NoAcknowledge,
+
+ /// <summary>
+ /// Pre acknowledge means that an ack is sent per message but sent before user code has processed
+ /// the message (i.e. before the onMessage() call or the receive() method has returned).
+ /// </summary>
+ PreAcknowledge
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ChannelLimitReachedException.cs b/dotnet/Qpid.Messaging/ChannelLimitReachedException.cs
new file mode 100644
index 0000000000..8b43422f5c
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ChannelLimitReachedException.cs
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Messaging
+{
+ [Serializable]
+ public class ChannelLimitReachedException : ResourceAllocationException
+ {
+ private long _limit;
+
+ public ChannelLimitReachedException(long limit)
+ : base("Unable to create session since maximum number of sessions per connection is " +
+ limit + ". Either close one or more sessions or increase the " +
+ "maximum number of sessions per connection (or contact your OpenAMQ administrator.")
+ {
+ _limit = limit;
+ }
+
+ protected ChannelLimitReachedException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ _limit = info.GetInt64("Limit");
+ }
+
+ public long Limit
+ {
+ get
+ {
+ return _limit;
+ }
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+ info.AddValue("Limit", _limit);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/DeliveryMode.cs b/dotnet/Qpid.Messaging/DeliveryMode.cs
new file mode 100644
index 0000000000..3c4713ee2a
--- /dev/null
+++ b/dotnet/Qpid.Messaging/DeliveryMode.cs
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public enum DeliveryMode
+ {
+ NonPersistent,
+ Persistent
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ExchangeClassConstants.cs b/dotnet/Qpid.Messaging/ExchangeClassConstants.cs
new file mode 100644
index 0000000000..984e8b0f17
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ExchangeClassConstants.cs
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public class ExchangeClassConstants
+ {
+ public readonly static string TOPIC = "topic";
+ public readonly static string DIRECT = "direct";
+ public readonly static string HEADERS = "headers";
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ExchangeNameDefaults.cs b/dotnet/Qpid.Messaging/ExchangeNameDefaults.cs
new file mode 100644
index 0000000000..2689fb5e46
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ExchangeNameDefaults.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public class ExchangeNameDefaults
+ {
+ public readonly static string TOPIC = "amq.topic";
+ public readonly static string DIRECT = "amq.direct";
+ public readonly static string HEADERS = "amq.match";
+ public readonly static string FANOUT = "amq.fanout";
+
+ /// <summary> Defines the identifying type name of topic exchanges. </summary>
+ public readonly static string TOPIC_EXCHANGE_CLASS = "topic";
+
+ /// <summary> Defines the identifying type name of direct exchanges. </summary>
+ public readonly static string DIRECT_EXCHANGE_CLASS = "direct";
+
+ /// <summary> Defines the identifying type name of headers exchanges. </summary>
+ public readonly static string HEADERS_EXCHANGE_CLASS = "headers";
+
+ /// <summary> Defines the identifying type name of fanout exchanges. </summary>
+ public readonly static string FANOUT_EXCHANGE_CLASS = "fanout";
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IBytesMessage.cs b/dotnet/Qpid.Messaging/IBytesMessage.cs
new file mode 100644
index 0000000000..5be942423d
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IBytesMessage.cs
@@ -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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public interface IBytesMessage : IMessage
+ {
+ long BodyLength { get; }
+
+ bool ReadBoolean();
+ void WriteBoolean(bool value);
+
+ byte ReadByte();
+ int ReadBytes(byte[] array);
+ int ReadBytes(byte[] array, int length);
+ void WriteByte(byte value);
+ void WriteBytes(byte[] value);
+ void WriteBytes(byte[] value, int offset, int length);
+
+ char ReadChar();
+ void WriteChar(char value);
+
+ double ReadDouble();
+ void WriteDouble(double value);
+
+ float ReadFloat();
+ void WriteFloat(float value);
+
+ int ReadInt();
+ void WriteInt(int value);
+
+ long ReadLong();
+ void WriteLong(long value);
+
+ short ReadShort();
+ void WriteShort(short value);
+
+ short ReadSignedByte();
+ void WriteSignedByte(short value);
+
+ string ReadUTF();
+ void WriteUTF(string value);
+
+ void Reset();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IChannel.cs b/dotnet/Qpid.Messaging/IChannel.cs
new file mode 100644
index 0000000000..1db8b5fbdb
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IChannel.cs
@@ -0,0 +1,280 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Messaging
+{
+ public delegate void MessageReceivedDelegate(IMessage msg);
+
+ /// <summary>
+ /// IChannel provides methods to access the commands in AMQP that operate at the channel level. This can be summarized as
+ /// the ability to declare queues and exchanges, bind queues to exchanges, create messages of various types, declare transaction
+ /// boundaries (commit and rollback), and to set up producers and consumers on the channel.
+ ///
+ /// <p/>You can create a channel by using the CreateChannel() method
+ /// of the connection object.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities
+ /// <tr><td> Declare queues.
+ /// <tr><td> Declare exchanges.
+ /// <tr><td> Bind queues to exchanges.
+ /// <tr><td> Create messages.
+ /// <tr><td> Set up message consumers on the channel.
+ /// <tr><td> Set up message producers on the channel.
+ /// <tr><td> Commit the current transaction.
+ /// <tr><td> Roll-back the current transaction.
+ /// <tr><td> Close the channel.
+ /// </table>
+ /// </summary>
+ public interface IChannel : IDisposable, ICloseable
+ {
+ /// <summary>
+ /// Acknowledge mode for messages received.
+ /// </summary>
+ AcknowledgeMode AcknowledgeMode { get; }
+
+ /// <summary>
+ /// True if the channel should use transactions.
+ /// </summary>
+ bool Transacted { get; }
+
+ /// <summary>
+ /// Prefetch value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ int DefaultPrefetch { get; }
+
+ /// <summary>
+ /// Prefetch low value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ int DefaultPrefetchLow { get; }
+
+ /// <summary>
+ /// Prefetch high value to be used as the default for
+ /// consumers created on this channel.
+ /// </summary>
+ int DefaultPrefetchHigh { get; }
+
+ /// <summary>
+ /// Declare a new exchange.
+ /// </summary>
+ /// <param name="exchangeName">Name of the exchange</param>
+ /// <param name="exchangeClass">Class of the exchange, from <see cref="ExchangeClassConstants"/></param>
+ void DeclareExchange(string exchangeName, string exchangeClass);
+
+ /// <summary>
+ /// Declare a new exchange using the default exchange class.
+ /// </summary>
+ /// <param name="exchangeName">Name of the exchange</param>
+ void DeleteExchange(string exchangeName);
+
+ /// <summary>
+ /// Declare a new queue with the specified set of arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue</param>
+ /// <param name="isDurable">True if the queue should be durable</param>
+ /// <param name="isExclusive">True if the queue should be exclusive to this channel</param>
+ /// <param name="isAutoDelete">True if the queue should be deleted when the channel closes</param>
+ void DeclareQueue(string queueName, bool isDurable, bool isExclusive, bool isAutoDelete);
+
+
+ /// <summary>
+ /// Declare a new queue with the specified set of arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue</param>
+ /// <param name="isDurable">True if the queue should be durable</param>
+ /// <param name="isExclusive">True if the queue should be exclusive to this channel</param>
+ /// <param name="isAutoDelete">True if the queue should be deleted when the channel closes</param>
+ /// <param name="args">Optional arguments to Queue.Declare</param>
+ void DeclareQueue(string queueName, bool isDurable, bool isExclusive, bool isAutoDelete, IFieldTable args);
+
+ /// <summary>
+ /// Delete a queue with the specifies arguments.
+ /// </summary>
+ /// <param name="queueName">Name of the queue to delete</param>
+ /// <param name="ifUnused">If true, the queue will not deleted if it has no consumers</param>
+ /// <param name="ifEmpty">If true, the queue will not deleted if it has no messages</param>
+ /// <param name="noWait">If true, the server will not respond to the method</param>
+ void DeleteQueue(string queueName, bool ifUnused, bool ifEmpty, bool noWait);
+
+ /// <summary>
+ /// Generate a new Unique name to use for a queue.
+ /// </summary>
+ /// <returns>A unique name to this channel</returns>
+ string GenerateUniqueName();
+
+ /// <summary>
+ /// Removes all messages from a queue.
+ /// </summary>
+ /// <param name="queueName">Name of the queue to delete</param>
+ /// <param name="noWait">If true, the server will not respond to the method</param>
+ void PurgeQueue(string queueName, bool noWait);
+
+ /// <summary>
+ /// Bind a queue to the specified exchange.
+ /// </summary>
+ /// <param name="queueName">Name of queue to bind</param>
+ /// <param name="exchangeName">Name of exchange to bind to</param>
+ /// <param name="routingKey">Routing key</param>
+ void Bind(string queueName, string exchangeName, string routingKey);
+
+ /// <summary>
+ /// Bind a queue to the specified exchange.
+ /// </summary>
+ /// <param name="queueName">Name of queue to bind</param>
+ /// <param name="exchangeName">Name of exchange to bind to</param>
+ /// <param name="routingKey">Routing key</param>
+ /// <param name="args">Table of arguments for the binding. Used to bind with a Headers Exchange</param>
+ void Bind(string queueName, string exchangeName, string routingKey, IFieldTable args);
+
+ /// <summary>
+ /// Create a new empty message with no body.
+ /// </summary>
+ /// <returns>The new message</returns>
+ IMessage CreateMessage();
+
+ /// <summary>
+ /// Create a new message of the specified MIME type.
+ /// </summary>
+ /// <param name="mimeType">The mime type to create</param>
+ /// <returns>The new message</returns>
+ IMessage CreateMessage(string mimeType);
+
+ /// <summary>
+ /// Creates a new message for bytes (application/octet-stream).
+ /// </summary>
+ /// <returns>The new message</returns>
+ IBytesMessage CreateBytesMessage();
+
+ /// <summary>
+ /// Creates a new text message (text/plain) with empty content.
+ /// </summary>
+ /// <returns>The new message</returns>
+ ITextMessage CreateTextMessage();
+
+ /// <summary>
+ /// Creates a new text message (text/plain) with a body.
+ /// </summary>
+ /// <param name="initialValue">Initial body of the message</param>
+ /// <returns>The new message</returns>
+ ITextMessage CreateTextMessage(string initialValue);
+
+ #region Consuming
+
+ /// <summary>
+ /// Creates a new Consumer using the builder pattern.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <returns>The builder object</returns>
+ MessageConsumerBuilder CreateConsumerBuilder(string queueName);
+
+ /// <summary>
+ /// Creates a new consumer.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <param name="prefetchLow">Low prefetch value</param>
+ /// <param name="prefetchHigh">High prefetch value</param>
+ /// <param name="noLocal">If true, messages sent on this channel will not be received by this consumer</param>
+ /// <param name="exclusive">If true, the consumer opens the queue in exclusive mode</param>
+ /// <returns>The new consumer</returns>
+ IMessageConsumer CreateConsumer(string queueName,
+ int prefetchLow,
+ int prefetchHigh,
+ bool noLocal,
+ bool exclusive);
+
+ /// <summary>
+ /// Creates a new consumer.
+ /// </summary>
+ /// <param name="queueName">Name of queue to receive messages from</param>
+ /// <param name="prefetchLow">Low prefetch value</param>
+ /// <param name="prefetchHigh">High prefetch value</param>
+ /// <param name="noLocal">If true, messages sent on this channel will not be received by this consumer</param>
+ /// <param name="exclusive">If true, the consumer opens the queue in exclusive mode</param>
+ /// <param name="browse">If true, the consumer only browses and does not consume</param>
+ /// <returns>The new consumer</returns>
+ IMessageConsumer CreateConsumer(string queueName,
+ int prefetchLow,
+ int prefetchHigh,
+ bool noLocal,
+ bool exclusive,
+ bool browse);
+
+ /// <summary>
+ /// Unsubscribe from a queue.
+ /// </summary>
+ /// <param name="subscriptionName">Subscription name</param>
+ void Unsubscribe(string subscriptionName);
+
+ #endregion
+
+ #region Publishing
+
+ /// <summary>
+ /// Create a new message publisher using the builder pattern.
+ /// </summary>
+ /// <returns>The builder object</returns>
+ MessagePublisherBuilder CreatePublisherBuilder();
+
+ /// <summary>
+ /// Create a new message publisher.
+ /// </summary>
+ /// <param name="exchangeName">Name of exchange to publish to</param>
+ /// <param name="routingKey">Routing key</param>
+ /// <param name="deliveryMode">Default delivery mode</param>
+ /// <param name="timeToLive">Default TTL time of messages</param>
+ /// <param name="immediate">If true, sent immediately</param>
+ /// <param name="mandatory">If true, the broker will return an error
+ /// (as a connection exception) if the message cannot be delivered</param>
+ /// <param name="priority">Default message priority</param>
+ /// <returns>The new message publisher</returns>
+ IMessagePublisher CreatePublisher(string exchangeName,
+ string routingKey,
+ DeliveryMode deliveryMode,
+ long timeToLive,
+ bool immediate,
+ bool mandatory,
+ int priority);
+
+ #endregion
+
+ #region Transactions
+
+ /// <summary>
+ /// Recover after transaction failure.
+ /// </summary>
+ void Recover();
+
+ /// <summary>
+ /// Commit the transaction.
+ /// </summary>
+ void Commit();
+
+ /// <summary>
+ /// Rollback the transaction.
+ /// </summary>
+ void Rollback();
+
+ #endregion
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ICloseable.cs b/dotnet/Qpid.Messaging/ICloseable.cs
new file mode 100644
index 0000000000..658a5ed5a4
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ICloseable.cs
@@ -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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Messaging
+{
+ /// <summary>An ICloseable is a resource that can be explicitly closed. Generally speaking a closed resource can no longer be used, and the
+ /// act of closing a resource is usually interpreted as a signal that the closed item can have its resource cleaned up and de-allocated.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Close (and clean-up) a resource.
+ /// </table>
+ /// </summary>
+ public interface ICloseable
+ {
+ /// <summary> Close the resource. </summary>
+ void Close();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IConnection.cs b/dotnet/Qpid.Messaging/IConnection.cs
new file mode 100644
index 0000000000..f664137e02
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IConnection.cs
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Messaging
+{
+ public delegate void ExceptionListenerDelegate(Exception ex);
+
+ public interface IConnection : IDisposable, ICloseable
+ {
+ /// <summary>
+ /// The connection listener that has been registered with this connection.
+ /// </summary>
+ IConnectionListener ConnectionListener
+ {
+ get;
+ set;
+ }
+
+ ExceptionListenerDelegate ExceptionListener { get; set; }
+
+ string ClientID { get; set; }
+
+ /// <return>the maximum number of sessions supported by this Connection</return>
+ int MaximumChannelCount
+ {
+ get;
+ }
+
+ IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode);
+ IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode, int prefetch);
+ IChannel CreateChannel(bool transacted, AcknowledgeMode acknowledgeMode, int prefetchHigh, int prefetchLow);
+
+ void Start();
+ void Stop();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IConnectionFactory.cs b/dotnet/Qpid.Messaging/IConnectionFactory.cs
new file mode 100644
index 0000000000..f141d509be
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IConnectionFactory.cs
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public interface IConnectionFactory
+ {
+ IConnection CreateConnection();
+ IConnection CreateConnection(string userId, string password);
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IConnectionListener.cs b/dotnet/Qpid.Messaging/IConnectionListener.cs
new file mode 100644
index 0000000000..02d9eb38da
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IConnectionListener.cs
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public interface IConnectionListener
+ {
+ /// <summary>
+ /// Called when bytes have been transmitted to the server
+ /// </summary>
+ /// <param>count the number of bytes sent in total since the connection was opened</param>
+ void BytesSent(long count);
+
+ /// <summary>
+ /// Called when some bytes have been received on a connection
+ /// </summary>
+ /// <param>count the number of bytes received in total since the connection was opened</param>
+ void BytesReceived(long count);
+
+ /// <summary>
+ /// Called after the infrastructure has detected that failover is required but before attempting failover.
+ /// </summary>
+ /// <param>redirect true if the broker requested redirect. false if failover is occurring due to a connection error.</param>
+ /// <return>true to continue failing over, false to veto failover and raise a connection exception</return>
+ bool PreFailover(bool redirect);
+
+ /// <summary>
+ /// Called after connection has been made to another broker after failover has been started but before
+ /// any resubscription has been done.
+ /// <return> true to continue with resubscription, false to prevent automatic resubscription. This is useful in
+ /// cases where the application wants to handle resubscription. Note that in the latter case all sessions, producers
+ /// and consumers are invalidated.
+ /// </return
+ bool PreResubscribe();
+
+ /// <summary>
+ /// Called once failover has completed successfully. This is called irrespective of whether the client has
+ /// vetoed automatic resubscription.
+ /// </summary>
+ void FailoverComplete();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IFieldTable.cs b/dotnet/Qpid.Messaging/IFieldTable.cs
new file mode 100644
index 0000000000..730ce399d4
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IFieldTable.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System.Collections;
+
+namespace Apache.Qpid.Messaging
+{
+ public interface IFieldTable : IEnumerable
+ {
+ int Count { get; }
+
+ object this[string key] { get; set; }
+
+ /// <summary>
+ /// Adds all the items from another field table in this one.
+ /// Will overwrite any items in the current table with the same key.
+ /// </summary>
+ /// <param name="source">the source field table</param>
+ void AddAll(IFieldTable source);
+
+ bool Contains(string s);
+ void Clear();
+ void Remove(string key);
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IHeaders.cs b/dotnet/Qpid.Messaging/IHeaders.cs
new file mode 100644
index 0000000000..7fdf26ebda
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IHeaders.cs
@@ -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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ /// <summary>
+ /// IHeaders represents the header fields of an AMQ message and provides methods to access those fields. There are accessor methods to
+ /// get and set each header field for each supported header field data type.
+ ///
+ /// <para/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th>Responsibilities</th></tr>
+ /// <tr><td>Provide accessors for all supported header field types.</td></tr>
+ /// <tr><td>Check if a set of headers contains a named property.</td></tr>
+ /// </table>
+ ///
+ /// </summary>
+ public interface IHeaders
+ {
+ bool Contains(string name);
+
+ object this[string name] { get; set; }
+
+ bool GetBoolean(string name);
+ void SetBoolean(string name, bool value);
+
+ byte GetByte(string name);
+ void SetByte(string name, byte value);
+
+ //sbyte GetSByte(string name);
+ //void SetSByte(string name, sbyte value);
+
+ short GetShort(string name);
+ void SetShort(string name, short value);
+
+ int GetInt(string name);
+ void SetInt(string name, int value);
+
+ long GetLong(string name);
+ void SetLong(string name, long value);
+
+ float GetFloat(string name);
+ void SetFloat(string name, float value);
+
+ double GetDouble(string name);
+ void SetDouble(string name, double value);
+
+ string GetString(string name);
+ void SetString(string name, string value);
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IMessage.cs b/dotnet/Qpid.Messaging/IMessage.cs
new file mode 100644
index 0000000000..20ae5ee130
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IMessage.cs
@@ -0,0 +1,97 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public interface IMessage
+ {
+ /// <summary>
+ /// The MIME Content Type
+ /// </summary>
+ string ContentType { get; set;}
+ /// <summary>
+ /// The MIME Content Encoding
+ /// </summary>
+ string ContentEncoding { get; set; }
+ /// <summary>
+ /// The application correlation identifier
+ /// </summary>
+ string CorrelationId { get; set; }
+ /// <summary>
+ /// The application correlation identifier, as an array of bytes
+ /// </summary>
+ byte[] CorrelationIdAsBytes { get; set; }
+ /// <summary>
+ /// Non-persistent (1) or persistent (2)
+ /// </summary>
+ DeliveryMode DeliveryMode { get; set; }
+ /// <summary>
+ /// Message expiration specification
+ /// </summary>
+ long Expiration { get; set; }
+ /// <summary>
+ /// The application message identifier
+ /// </summary>
+ string MessageId { get; set; }
+ /// <summary>
+ /// The message priority, 0 to 9
+ /// </summary>
+ byte Priority { get; set; }
+ /// <summary>
+ /// True if the message has been redelivered
+ /// </summary>
+ bool Redelivered { get; set; }
+ /// <summary>
+ /// Exchange name of the reply-to address
+ /// </summary>
+ string ReplyToExchangeName { get; set; }
+ /// <summary>
+ /// Routing key of the reply-to address
+ /// </summary>
+ string ReplyToRoutingKey { get; set; }
+ /// <summary>
+ /// The message timestamp
+ /// </summary>
+ long Timestamp { get; set; }
+ /// <summary>
+ /// The message type name
+ /// </summary>
+ string Type { get; set; }
+ /// <summary>
+ /// Message headers
+ /// </summary>
+ IHeaders Headers { get; }
+ /// <summary>
+ /// The creating user id
+ /// </summary>
+ string UserId { get; set; }
+ /// <summary>
+ /// The creating application id
+ /// </summary>
+ string AppId { get; set; }
+ /// <summary>
+ /// Intra-cluster routing identifier
+ /// </summary>
+ string ClusterId { get; set; }
+
+ void Acknowledge();
+ void ClearBody();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IMessageConsumer.cs b/dotnet/Qpid.Messaging/IMessageConsumer.cs
new file mode 100644
index 0000000000..86b5405707
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IMessageConsumer.cs
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Messaging
+{
+ /// <summary>
+ /// Describes an object that can be used to receive (consume)
+ /// messages from an AMQP queue.
+ /// </summary>
+ /// <remarks>
+ /// Consumers are created using either
+ /// <see cref="IChannel.CreateConsumer"/> or using
+ /// the builder pattern (preferred) with
+ /// <see cref="IChannel.CreateConsumerBuilder"/>.
+ ///
+ /// <para>
+ /// Consumers offer two different ways of receiving messages:
+ /// You can attach a delegate to the <see cref="OnMessage"/>
+ /// event and be notified when a message arrives, or you can
+ /// use the <see cref="Receive"/> and <see cref="ReceiveNoWait"/>
+ /// methods to control when you receive messages. Be aware that you can use
+ /// one or the other, but not both at the same time.
+ /// </para>
+ /// <para>
+ /// Regardless of which method you choose, the prefetch settings
+ /// specified when creating the channel will still control when messages
+ /// are actually received from the AMQP broker. Any messages that arrive
+ /// between the prefetch window will be queued by the channel
+ /// until they can be delivered to the consumer (either though the event
+ /// or until the consumer actively calls <see cref="Receive"/>).
+ /// </para>
+ /// </remarks>
+ public interface IMessageConsumer : IDisposable, ICloseable
+ {
+ /// <summary>
+ /// Fired when a message is received from the broker by the consumer
+ /// </summary>
+ MessageReceivedDelegate OnMessage { get; set; }
+
+ /// <summary>
+ /// Wait infinitely for a message to be received from the broker
+ /// </summary>
+ /// <returns>The message received</returns>
+ IMessage Receive();
+
+ /// <summary>
+ /// Wait the specified time until a message is receive from the broker
+ /// </summary>
+ /// <param name="delay">Maximum number of milliseconds to wait for a message</param>
+ /// <returns>The message received, or null if the timeout expires</returns>
+ IMessage Receive(long delay);
+
+ /// <summary>
+ /// Return a message if one is already available in the channel.
+ /// Does not wait for one to be received from the broker.
+ /// </summary>
+ /// <returns>The message, if it was available, otherwise null</returns>
+ IMessage ReceiveNoWait();
+ }
+}
diff --git a/dotnet/Qpid.Messaging/IMessagePublisher.cs b/dotnet/Qpid.Messaging/IMessagePublisher.cs
new file mode 100644
index 0000000000..d895a9749b
--- /dev/null
+++ b/dotnet/Qpid.Messaging/IMessagePublisher.cs
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+
+namespace Apache.Qpid.Messaging
+{
+ /// <summary>
+ /// Defines an object capable of publishing messages
+ /// to an AMQP broker.
+ /// </summary>
+ /// <remarks>
+ /// A publisher can be created using either
+ /// <see cref="IChannel.CreatePublisher"/> or
+ /// using the builder pattern (preferred) with
+ /// <see cref="IChannel.CreatePublisherBuilder"/>
+ /// </remarks>
+ public interface IMessagePublisher : IDisposable, ICloseable
+ {
+ /// <summary>
+ /// Default delivery mode to use with this publisher
+ /// </summary>
+ DeliveryMode DeliveryMode { get; set; }
+ /// <summary>
+ /// Name of exchange messages are published to
+ /// </summary>
+ string ExchangeName { get; }
+ /// <summary>
+ /// Routing key used when publishing messages
+ /// </summary>
+ string RoutingKey { get; }
+ /// <summary>
+ /// If true, a message ID will not be generated by the publisher
+ /// when sending the message
+ /// </summary>
+ bool DisableMessageID { get; set; }
+ /// <summary>
+ /// If true, no timestamp will be added to the message
+ /// when publishing it
+ /// </summary>
+ bool DisableMessageTimestamp { get; set; }
+ /// <summary>
+ /// Default priority used when publishing messages
+ /// </summary>
+ int Priority { get; set; }
+ /// <summary>
+ /// Default time to live used when publishing messages
+ /// </summary>
+ long TimeToLive { get; set; }
+ /// <summary>
+ /// Set the default MIME type for messages produced by this producer.
+ /// This reduces the overhead of each message.
+ /// </summary>
+ string MimeType { get; set; }
+ /// <summary>
+ /// Set the default encoding for messages produced by this producer.
+ /// This reduces the overhead of each message.
+ /// </summary>
+ string Encoding { get; set; }
+
+ /// <summary>
+ /// Publish a message, using any default values configured
+ /// </summary>
+ /// <param name="msg">Message to publish</param>
+ void Send(IMessage msg);
+ /// <summary>
+ /// Publish a message with the specified options
+ /// </summary>
+ /// <param name="msg">Message to publish</param>
+ /// <param name="deliveryMode">Delivery mode to use</param>
+ /// <param name="priority">Priority of the message</param>
+ /// <param name="timeToLive">Time to live of the message</param>
+ void Send(IMessage msg, DeliveryMode deliveryMode, int priority, long timeToLive);
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ITextMessage.cs b/dotnet/Qpid.Messaging/ITextMessage.cs
new file mode 100644
index 0000000000..902beb70f8
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ITextMessage.cs
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public interface ITextMessage : IMessage
+ {
+ string Text { get; set; }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/MessageConsumerBuilder.cs b/dotnet/Qpid.Messaging/MessageConsumerBuilder.cs
new file mode 100644
index 0000000000..91a2371788
--- /dev/null
+++ b/dotnet/Qpid.Messaging/MessageConsumerBuilder.cs
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ /// <summary>
+ /// MessageConsumerBuilder provides a builder with a fluent interface to assist with creating message consumers on a channel.
+ ///
+ /// <p/><table id="crc"><caption>CRC Card</caption>
+ /// <tr><th> Responsibilities <th> Collaborations
+ /// <tr><td> Create message consumers from consume parameters. <td> <see cref="IChannel">
+ /// </table>
+ /// </summary>
+ ///
+ /// <remarks>It may be better to replace the Create method with a DeclareBindAndCreate method, that declares and binds the consumers queue,
+ /// as well as creating the consumer. This is a common use case, so the method will generally be usefull. Need to consider situations where
+ /// the declare and bind is not to be done, for example when resubscribing to a durable subscription. There may be others too.</remarks>
+ public class MessageConsumerBuilder
+ {
+ private bool _noLocal = false;
+
+ private bool _exclusive = false;
+
+ private bool _browse = false;
+
+ //private bool _durable = false;
+ //private string _subscriptionName = null;
+
+ private IChannel _channel;
+
+ private readonly string _queueName;
+
+ private int _prefetchLow;
+
+ private int _prefetchHigh;
+
+ public MessageConsumerBuilder(IChannel channel, string queueName)
+ {
+ _channel = channel;
+ _queueName = queueName;
+ _prefetchHigh = _channel.DefaultPrefetchHigh;
+ _prefetchLow = _channel.DefaultPrefetchLow;
+ }
+
+ public MessageConsumerBuilder WithPrefetchLow(int prefetchLow)
+ {
+ _prefetchLow = prefetchLow;
+ return this;
+ }
+
+ public MessageConsumerBuilder WithPrefetchHigh(int prefetchHigh)
+ {
+ _prefetchHigh = prefetchHigh;
+ return this;
+ }
+
+ public MessageConsumerBuilder WithNoLocal(bool noLocal)
+ {
+ _noLocal = noLocal;
+ return this;
+ }
+
+ public MessageConsumerBuilder WithExclusive(bool exclusive)
+ {
+ _exclusive = exclusive;
+ return this;
+ }
+
+ public MessageConsumerBuilder WithBrowse(bool browse)
+ {
+ _browse = browse;
+ return this;
+ }
+
+ /*
+ public MessageConsumerBuilder WithDurable(bool durable)
+ {
+ _durable = durable;
+ return this;
+ }
+ */
+
+ /*
+ public MessageConsumerBuilder WithSubscriptionName(string subscriptionName)
+ {
+ _subscriptionName = subscriptionName;
+ return this;
+ }
+ */
+
+ public IMessageConsumer Create()
+ {
+ return _channel.CreateConsumer(_queueName, _prefetchLow, _prefetchHigh, _noLocal, _exclusive, _browse);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/MessageNotReadableException.cs b/dotnet/Qpid.Messaging/MessageNotReadableException.cs
new file mode 100644
index 0000000000..2afcffd531
--- /dev/null
+++ b/dotnet/Qpid.Messaging/MessageNotReadableException.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Messaging
+{
+ [Serializable]
+ public class MessageNotReadableException : QpidException
+ {
+ public MessageNotReadableException(string reason) : base(reason)
+ {
+ }
+
+ protected MessageNotReadableException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/MessageNotWritableException.cs b/dotnet/Qpid.Messaging/MessageNotWritableException.cs
new file mode 100644
index 0000000000..9b00f01948
--- /dev/null
+++ b/dotnet/Qpid.Messaging/MessageNotWritableException.cs
@@ -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.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Messaging
+{
+ [Serializable]
+ public class MessageNotWriteableException : QpidException
+ {
+ public MessageNotWriteableException(string reason) : base(reason)
+ {
+ }
+
+ protected MessageNotWriteableException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/MessagePublisherBuilder.cs b/dotnet/Qpid.Messaging/MessagePublisherBuilder.cs
new file mode 100644
index 0000000000..79c7575d0a
--- /dev/null
+++ b/dotnet/Qpid.Messaging/MessagePublisherBuilder.cs
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace Apache.Qpid.Messaging
+{
+ public class MessagePublisherBuilder
+ {
+ /// <summary>
+ /// Default value for immediate flag is false, i.e. a consumer does not need to be attached to a queue
+ /// </summary>
+ const bool DEFAULT_IMMEDIATE = false;
+
+ /// <summary>
+ /// Default value for mandatory flag is true, i.e. server will not silently drop messages where no queue is
+ /// connected to the exchange for the message
+ /// </summary>
+ const bool DEFAULT_MANDATORY = true;
+
+ IChannel _channel;
+ string _exchangeName = null;
+ string _routingKey = null;
+ DeliveryMode _deliveryMode = DeliveryMode.Persistent;
+ long _timeToLive;
+ bool _immediate = DEFAULT_IMMEDIATE;
+ bool _mandatory = DEFAULT_MANDATORY;
+ int _priority = 0;
+
+ public MessagePublisherBuilder(IChannel channel)
+ {
+ _channel = channel;
+ }
+
+ public MessagePublisherBuilder WithRoutingKey(string routingKey)
+ {
+ _routingKey = routingKey;
+ return this;
+ }
+
+ public MessagePublisherBuilder WithExchangeName(string exchangeName)
+ {
+ _exchangeName = exchangeName;
+ return this;
+ }
+
+ public MessagePublisherBuilder WithDeliveryMode(DeliveryMode deliveryMode)
+ {
+ _deliveryMode = deliveryMode;
+ return this;
+ }
+
+ public MessagePublisherBuilder WithTimeToLive(long timeToLive)
+ {
+ _timeToLive = timeToLive;
+ return this;
+ }
+
+ public MessagePublisherBuilder WithImmediate(bool immediate)
+ {
+ _immediate = immediate;
+ return this;
+ }
+
+ public MessagePublisherBuilder WithMandatory(bool mandatory)
+ {
+ _mandatory = mandatory;
+ return this;
+ }
+
+ public IMessagePublisher Create()
+ {
+ return _channel.CreatePublisher(_exchangeName, _routingKey, _deliveryMode, _timeToLive, _immediate, _mandatory, _priority);
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/Properties/AssemblyInfo.cs b/dotnet/Qpid.Messaging/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..d9dff07f3f
--- /dev/null
+++ b/dotnet/Qpid.Messaging/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Messaging")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Messaging")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e74f1805-b355-42e0-ba70-afc7c8570f03")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: CLSCompliant(true)]
diff --git a/dotnet/Qpid.Messaging/Qpid.Messaging.csproj b/dotnet/Qpid.Messaging/Qpid.Messaging.csproj
new file mode 100644
index 0000000000..37b80d1515
--- /dev/null
+++ b/dotnet/Qpid.Messaging/Qpid.Messaging.csproj
@@ -0,0 +1,115 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Messaging</RootNamespace>
+ <AssemblyName>Apache.Qpid.Messaging</AssemblyName>
+ <SignAssembly>true</SignAssembly>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <PublishUrl>http://localhost/Apache.Qpid.Messaging/</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Web</InstallFrom>
+ <UpdateEnabled>true</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>true</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Messaging/QpidException.cs b/dotnet/Qpid.Messaging/QpidException.cs
new file mode 100644
index 0000000000..3e39f2293d
--- /dev/null
+++ b/dotnet/Qpid.Messaging/QpidException.cs
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Messaging
+{
+ [Serializable]
+ public class QpidException : Exception
+ {
+ public QpidException(string reason) : base(reason)
+ {
+ }
+
+ public QpidException(string reason, Exception e)
+ : base(reason, e)
+ {
+ }
+
+ protected QpidException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/ResourceAllocationException.cs b/dotnet/Qpid.Messaging/ResourceAllocationException.cs
new file mode 100644
index 0000000000..954dcdd94c
--- /dev/null
+++ b/dotnet/Qpid.Messaging/ResourceAllocationException.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Apache.Qpid.Messaging
+{
+ [Serializable]
+ public class ResourceAllocationException : QpidException
+ {
+ public ResourceAllocationException(string reason) : base(reason)
+ {
+ }
+
+ protected ResourceAllocationException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+ }
+}
diff --git a/dotnet/Qpid.Messaging/default.build b/dotnet/Qpid.Messaging/default.build
new file mode 100644
index 0000000000..e351def886
--- /dev/null
+++ b/dotnet/Qpid.Messaging/default.build
@@ -0,0 +1,45 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Messaging" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.NET.FxCop b/dotnet/Qpid.NET.FxCop
new file mode 100644
index 0000000000..ba6b3e3ac5
--- /dev/null
+++ b/dotnet/Qpid.NET.FxCop
@@ -0,0 +1,16775 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<FxCopProject Version="1.35" Name="My FxCop Project">
+ <ProjectOptions>
+ <SharedProject>True</SharedProject>
+ <Stylesheet Apply="False">http://www.gotdotnet.com/team/fxcop//xsl/1.35/FxCopReport.xsl</Stylesheet>
+ <SaveMessages>
+ <Project Status="Active, Excluded" NewOnly="False" />
+ <Report Status="Active" NewOnly="False" />
+ </SaveMessages>
+ <ProjectFile Compress="True" DefaultTargetCheck="True" DefaultRuleCheck="True" SaveByRuleGroup="" Deterministic="True" />
+ <EnableMultithreadedLoad>True</EnableMultithreadedLoad>
+ <EnableMultithreadedAnalysis>True</EnableMultithreadedAnalysis>
+ <SourceLookup>True</SourceLookup>
+ <AnalysisExceptionsThreshold>10</AnalysisExceptionsThreshold>
+ <RuleExceptionsThreshold>1</RuleExceptionsThreshold>
+ <Spelling Locale="en-us" />
+ <VersionAware>False</VersionAware>
+ <OverrideRuleVisibilities>False</OverrideRuleVisibilities>
+ <CustomDictionaries SearchFxCopDir="True" SearchUserProfile="True" SearchProjectDir="True" />
+ <SearchGlobalAssemblyCache>False</SearchGlobalAssemblyCache>
+ <DeadlockDetectionTimeout>120</DeadlockDetectionTimeout>
+ </ProjectOptions>
+ <Targets>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Buffer.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.Tests.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.Transport.Socket.Blocking.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Codec.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Common.dll" Analyze="True" AnalyzeAllChildren="True" />
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Messaging.dll" Analyze="True" AnalyzeAllChildren="True" />
+ </Targets>
+ <Rules>
+ <RuleFiles>
+ <RuleFile Name="$(FxCopDir)\Rules\DesignRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\GlobalizationRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\InteroperabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\MobilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\NamingRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\PerformanceRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\PortabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\SecurityRules.dll" Enabled="True" AllRulesEnabled="True" />
+ <RuleFile Name="$(FxCopDir)\Rules\UsageRules.dll" Enabled="True" AllRulesEnabled="True" />
+ </RuleFiles>
+ <Groups />
+ <Settings />
+ </Rules>
+ <FxCopReport Version="1.35">
+ <Namespaces>
+ <Namespace Name="Qpid">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Buffer">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Buffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Failover">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Failover</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Failover</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Handler">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Handler</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Message">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Message</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Protocol">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Protocol</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Protocol.Listener">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Protocol.Listener</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Protocol.Listener</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.qms">
+ <Messages>
+ <Message TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.qms</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.qms</Item>
+ </Issue>
+ </Message>
+ <Message Id="qms" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>qms</Item>
+ <Item>Qpid.Client.qms</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.qms.failover">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.qms.failover</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.qms.failover</Item>
+ </Issue>
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.qms.failover</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.qms.failover</Item>
+ </Issue>
+ </Message>
+ <Message Id="qms" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>qms</Item>
+ <Item>Qpid.Client.qms.failover</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.State">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.State</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Tests</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests.connection">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Tests.connection</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.Tests.connection</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Tests.connection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests.failover">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Tests.failover</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.Tests.failover</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Tests.failover</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests.url">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Tests.url</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid.Client.Tests.url</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Tests.url</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Transport">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Transport</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Transport.Socket.Blocking">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Transport.Socket.Blocking</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Codec">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Codec</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Codec.Demux">
+ <Messages>
+ <Message Id="Demux" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Demux</Item>
+ <Item>Qpid.Codec.Demux</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Codec.Demux</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Codec.Support">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Codec.Support</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Codec.Support</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Collections">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Collections</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Collections</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Common">
+ <Messages>
+ <Message TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Common</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Common</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Framing">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Framing</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ <Namespace Name="Qpid.Messaging">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Namespace">
+ <Item>Qpid</Item>
+ <Item>Qpid.Messaging</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Namespace>
+ </Namespaces>
+ <Targets>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Buffer.dll">
+ <Modules>
+ <Module Name="qpid.buffer.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Buffer</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Buffer</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Buffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Buffer">
+ <Types>
+ <Type Name="BufferOverflowException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Buffer.BufferOverflowException</Item>
+ <Item>protected BufferOverflowException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Buffer.BufferOverflowException</Item>
+ <Item>public BufferOverflowException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Buffer.BufferOverflowException</Item>
+ <Item>public BufferOverflowException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>BufferOverflowException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="BufferUnderflowException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Buffer.BufferUnderflowException</Item>
+ <Item>protected BufferUnderflowException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Buffer.BufferUnderflowException</Item>
+ <Item>public BufferUnderflowException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Buffer.BufferUnderflowException</Item>
+ <Item>public BufferUnderflowException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>BufferUnderflowException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="ByteBuffer">
+ <Members>
+ <Member Name="_containerStack">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_containerStack</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="NonConstantFieldsShouldNotBeVisible" Category="Microsoft.Usage" CheckId="CA2211" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_containerStack</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_heapBufferStacks">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_heapBufferStacks</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="NonConstantFieldsShouldNotBeVisible" Category="Microsoft.Usage" CheckId="CA2211" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_heapBufferStacks</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Allocate0(System.Int32,System.Boolean):Qpid.Buffer.ByteBuffer">
+ <Messages>
+ <Message Id="System.NotSupportedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ByteBuffer.Allocate0(Int32, Boolean):ByteBuffer</Item>
+ <Item>1</Item>
+ <Item>NotSupportedException.NotSupportedException(String)</Item>
+ <Item>Direct buffers not currently implemented</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Equals(System.Object):System.Boolean">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>obj</Item>
+ <Item>Qpid.Buffer.ByteBuffer</Item>
+ <Item>ByteBuffer.Equals(Object):Boolean</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetBufferStackIndex(System.Collections.Stack[],System.Int32):System.Int32">
+ <Messages>
+ <Message Id="System.ArgumentOutOfRangeException.#ctor(System.String,System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ByteBuffer.GetBufferStackIndex(Stack[], Int32):Int32</Item>
+ <Item>2</Item>
+ <Item>ArgumentOutOfRangeException.ArgumentOutOfRangeException(String, String)</Item>
+ <Item>Buffer size is too big: __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetUnsignedInt():System.UInt32">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetUnsignedInt</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetUnsignedLong():System.UInt64">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetUnsignedLong</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetUnsignedShort():System.UInt16">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetUnsignedShort</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MINIMUM_CAPACITY">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>MINIMUM_CAPACITY</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ByteBuffer.MINIMUM_CAPACITY</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Put(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="0#buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ByteBuffer.Put(ByteBuffer):Void</Item>
+ <Item>buf</Item>
+ <Item>buf</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Release0(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="0#buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ByteBuffer.Release0(ByteBuffer):Void</Item>
+ <Item>buf</Item>
+ <Item>buf</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buf'</Item>
+ <Item>ByteBuffer.Release0(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ByteBufferHexDumper">
+ <Messages>
+ <Message TypeName="StaticHolderTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1053" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ByteBufferHexDumper</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".cctor()">
+ <Messages>
+ <Message TypeName="InitializeReferenceTypeStaticFieldsInline" Category="Microsoft.Performance" CheckId="CA1810" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Buffer.ByteBufferHexDumper</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetHexDump(Qpid.Buffer.ByteBuffer):System.String">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'input'</Item>
+ <Item>ByteBufferHexDumper.GetHexDump(ByteBuffer):String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ByteBufferProxy">
+ <Members>
+ <Member Name=".ctor(Qpid.Buffer.ByteBuffer)">
+ <Messages>
+ <Message Id="0#buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ByteBufferProxy.ByteBufferProxy(ByteBuffer)</Item>
+ <Item>buf</Item>
+ <Item>buf</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_buf">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_buf</Item>
+ </Issue>
+ </Message>
+ <Message Id="_buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_buf</Item>
+ <Item>ByteBufferProxy._buf</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_buf</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="HeapByteBuffer">
+ <Members>
+ <Member Name="CheckSpace(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Qpid.Buffer.BufferOverflowException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeapByteBuffer.CheckSpace(Int32):Void</Item>
+ <Item>1</Item>
+ <Item>BufferOverflowException.BufferOverflowException(String)</Item>
+ <Item>Attempt to write ____ byte(s) to buffer where position is ____ and limit is __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckSpaceForReading(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Qpid.Buffer.BufferUnderflowException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeapByteBuffer.CheckSpaceForReading(Int32):Void</Item>
+ <Item>1</Item>
+ <Item>BufferUnderflowException.BufferUnderflowException(String)</Item>
+ <Item>Attempt to read ____ byte(s) to buffer where position is ____ and limit is __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetString(System.UInt32,System.Text.Encoding):System.String">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'encoder'</Item>
+ <Item>HeapByteBuffer.GetString(UInt32, Encoding):String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Limit">
+ <Accessors>
+ <Accessor Name="set_Limit(System.Int32):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeapByteBuffer.set_Limit(Int32):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Limit must not be greater than Capacity</Item>
+ </Issue>
+ <Issue>
+ <Item>HeapByteBuffer.set_Limit(Int32):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Limit must not be negative</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="Mark():System.Void">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>HeapByteBuffer.Mark():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Put(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>src</Item>
+ <Item>Qpid.Buffer.HeapByteBuffer</Item>
+ <Item>HeapByteBuffer.Put(ByteBuffer):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.Buffer.BufferOverflowException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeapByteBuffer.Put(ByteBuffer):Void</Item>
+ <Item>1</Item>
+ <Item>BufferOverflowException.BufferOverflowException(String)</Item>
+ <Item>Not enought capacity in this buffer for ____ elements - only ____ remaining</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeapByteBuffer.Put(ByteBuffer):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Cannot copy self into self!</Item>
+ </Issue>
+ </Message>
+ <Message Id="enought" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>enought</Item>
+ <Item>Not enought capacity in this buffer for ____ elements - only ____ remaining</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>src</Item>
+ <Item>HeapByteBuffer.Put(ByteBuffer):Void</Item>
+ <Item>buf</Item>
+ <Item>ByteBuffer.Put(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'src'</Item>
+ <Item>HeapByteBuffer.Put(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Put(System.Byte[]):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'data'</Item>
+ <Item>HeapByteBuffer.Put(Byte[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Reset():System.Void">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>HeapByteBuffer.Reset():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="wrap(System.Byte[]):Qpid.Buffer.HeapByteBuffer">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>wrap</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'bytes'</Item>
+ <Item>HeapByteBuffer.wrap(Byte[]):HeapByteBuffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="wrap(System.Byte[],System.Int32):Qpid.Buffer.HeapByteBuffer">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>wrap</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="RefCountingByteBuffer">
+ <Members>
+ <Member Name="Acquire():System.Void">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RefCountingByteBuffer.Acquire():Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Already released buffer</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>RefCountingByteBuffer.Acquire():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Buf">
+ <Messages>
+ <Message Id="Buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Buf</Item>
+ <Item>RefCountingByteBuffer.Buf:ByteBuffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Init(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="0#buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RefCountingByteBuffer.Init(ByteBuffer):Void</Item>
+ <Item>buf</Item>
+ <Item>buf</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buf'</Item>
+ <Item>RefCountingByteBuffer.Init(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Put(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buf'</Item>
+ <Item>RefCountingByteBuffer.Put(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Put(System.Byte[]):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'data'</Item>
+ <Item>RefCountingByteBuffer.Put(Byte[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Release():System.Void">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RefCountingByteBuffer.Release():Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Already released buffer. Release called too many times</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>RefCountingByteBuffer.Release():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.dll">
+ <Modules>
+ <Module Name="qpid.client.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Client</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Client</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Client">
+ <Types>
+ <Type Name="AmqBrokerInfo">
+ <Messages>
+ <Message Id="Amq" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Amq</Item>
+ <Item>Qpid.Client.AmqBrokerInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.String)">
+ <Messages>
+ <Message Id="url" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>url</Item>
+ <Item>AmqBrokerInfo.AmqBrokerInfo(String)</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#" TypeName="UriParametersShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1054" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>url</Item>
+ <Item>AmqBrokerInfo.AmqBrokerInfo(String)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_CONNECT_TIMEOUT">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AmqBrokerInfo.DEFAULT_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Equals(System.Object):System.Boolean">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>obj</Item>
+ <Item>Qpid.Client.qms.BrokerInfo</Item>
+ <Item>AmqBrokerInfo.Equals(Object):Boolean</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetHashCode():System.Int32">
+ <Messages>
+ <Message Id="System.String.ToLower" TypeName="SpecifyCultureInfo" Category="Microsoft.Globalization" CheckId="CA1304" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqBrokerInfo.GetHashCode():Int32</Item>
+ <Item>System.String.ToLower</Item>
+ <Item>System.String.ToLower(System.Globalization.CultureInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getTimeout():System.Int64">
+ <Messages>
+ <Message Id="System.Int64.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqBrokerInfo.getTimeout():Int64</Item>
+ <Item>System.Int64.Parse(System.String)</Item>
+ <Item>System.Int64.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setHost(System.String):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_host</Item>
+ <Item>AmqBrokerInfo.setHost(String):Void</Item>
+ <Item>host</Item>
+ <Item>BrokerInfo.setHost(String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setPort(System.Int32):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_port</Item>
+ <Item>AmqBrokerInfo.setPort(Int32):Void</Item>
+ <Item>port</Item>
+ <Item>BrokerInfo.setPort(Int32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setTimeout(System.Int64):System.Void">
+ <Messages>
+ <Message Id="System.Int64.ToString" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqBrokerInfo.setTimeout(Int64):Void</Item>
+ <Item>System.Int64.ToString</Item>
+ <Item>System.Int64.ToString(System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setTransport(System.String):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_transport</Item>
+ <Item>AmqBrokerInfo.setTransport(String):Void</Item>
+ <Item>transport</Item>
+ <Item>BrokerInfo.setTransport(String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StringEqualsIgnoreCase(System.String,System.String):System.Boolean">
+ <Messages>
+ <Message Id="one" TypeName="AvoidUnnecessaryStringCreation" Category="Microsoft.Performance" CheckId="CA1807" Created="2006-12-04 13:11:47Z">
+ <Issue Name="UseStringCompareParameter">
+ <Item>AmqBrokerInfo.StringEqualsIgnoreCase(String, String):Boolean</Item>
+ <Item>String.Equals(String):Boolean</Item>
+ <Item>one</Item>
+ </Issue>
+ </Message>
+ <Message Id="two" TypeName="AvoidUnnecessaryStringCreation" Category="Microsoft.Performance" CheckId="CA1807" Created="2006-12-04 13:11:47Z">
+ <Issue Name="UseStringCompareParameter">
+ <Item>AmqBrokerInfo.StringEqualsIgnoreCase(String, String):Boolean</Item>
+ <Item>String.Equals(String):Boolean</Item>
+ <Item>two</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>AmqBrokerInfo.StringEqualsIgnoreCase(String, String):Boolean</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.ToLower" TypeName="SpecifyCultureInfo" Category="Microsoft.Globalization" CheckId="CA1304" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqBrokerInfo.StringEqualsIgnoreCase(String, String):Boolean</Item>
+ <Item>System.String.ToLower</Item>
+ <Item>System.String.ToLower(System.Globalization.CultureInfo)</Item>
+ </Issue>
+ <Issue>
+ <Item>AmqBrokerInfo.StringEqualsIgnoreCase(String, String):Boolean</Item>
+ <Item>System.String.ToLower</Item>
+ <Item>System.String.ToLower(System.Globalization.CultureInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message Id="this._transport" TypeName="AvoidUnnecessaryStringCreation" Category="Microsoft.Performance" CheckId="CA1807" Created="2006-12-04 13:11:47Z">
+ <Issue Name="UseStringCompareLocal">
+ <Item>AmqBrokerInfo.ToString():String</Item>
+ <Item>String.Equals(String):Boolean</Item>
+ <Item>this._transport</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.ToLower" TypeName="SpecifyCultureInfo" Category="Microsoft.Globalization" CheckId="CA1304" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqBrokerInfo.ToString():String</Item>
+ <Item>System.String.ToLower</Item>
+ <Item>System.String.ToLower(System.Globalization.CultureInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="URL_FORMAT_EXAMPLE">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>URL_FORMAT_EXAMPLE</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>URL_FORMAT_EXAMPLE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AmqChannel">
+ <Messages>
+ <Message Id="Amq" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Amq</Item>
+ <Item>Qpid.Client.AmqChannel</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ProvideDisposeBool">
+ <Item>Qpid.Client.AmqChannel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".cctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.AmqChannel()</Item>
+ <Item>_nextSessionNumber</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(Qpid.Client.AMQConnection,System.UInt16,System.Boolean,Qpid.Messaging.AcknowledgeMode,Qpid.Client.Message.MessageFactoryRegistry,System.Int32)">
+ <Messages>
+ <Message Id="defaultPrefetch" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>defaultPrefetch</Item>
+ <Item>AmqChannel.AmqChannel(AMQConnection, UInt16, Boolean, AcknowledgeMode, MessageFactoryRegistry, Int32)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckNotTransacted():System.Void">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.CheckNotTransacted():Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Channel is transacted</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckTransacted():System.Void">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.CheckTransacted():Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Channel is not transacted</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClosedWithException(System.Exception):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>e</Item>
+ <Item>Qpid.AMQException</Item>
+ <Item>AmqChannel.ClosedWithException(Exception):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.AMQException.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.ClosedWithException(Exception):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String, Exception)</Item>
+ <Item>Closing session forcibly</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>AmqChannel.ClosedWithException(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumeFromQueue(System.String,System.Boolean,System.Boolean,Qpid.Messaging.AcknowledgeMode):System.String">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.ConsumeFromQueue(String, Boolean, Boolean, AcknowledgeMode):String</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateConsumer(System.String,System.Int32,System.Int32,System.Boolean,System.Boolean,System.Boolean,System.String):Qpid.Messaging.IMessageConsumer">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.CreateConsumer(String, Int32, Int32, Boolean, Boolean, Boolean, String):IMessageConsumer</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreatePublisher(System.String,System.String,Qpid.Messaging.DeliveryMode,System.Int64,System.Boolean,System.Boolean,System.Int32):Qpid.Messaging.IMessagePublisher">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.CreatePublisher(String, String, DeliveryMode, Int64, Boolean, Boolean, Int32):IMessagePublisher</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateTextMessage(System.String):Qpid.Messaging.ITextMessage">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>text</Item>
+ <Item>AmqChannel.CreateTextMessage(String):ITextMessage</Item>
+ <Item>initialValue</Item>
+ <Item>IChannel.CreateTextMessage(String):ITextMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeclareExchange(System.String,System.String):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DeclareExchange(String, String):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeclareExchange(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.Boolean,Qpid.Framing.FieldTable):System.Void">
+ <Messages>
+ <Message Id="System.NotImplementedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DeclareExchange(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):Void</Item>
+ <Item>1</Item>
+ <Item>NotImplementedException.NotImplementedException(String)</Item>
+ <Item>Don't use nowait=false with DeclareExchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="nowait" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>nowait</Item>
+ <Item>Don't use nowait=false with DeclareExchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DeclareExchange(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Dispose():System.Void">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="DisposeImplementation">
+ <Item>AmqChannel.Dispose():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DoBasicPublish(System.String,System.String,System.Boolean,System.Boolean,Qpid.Client.Message.AbstractQmsMessage,Qpid.Messaging.DeliveryMode,System.UInt32,System.Int32,System.Boolean):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DoBasicPublish(String, String, Boolean, Boolean, AbstractQmsMessage, DeliveryMode, UInt32, Int32, Boolean):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>AmqChannel.DoBasicPublish(String, String, Boolean, Boolean, AbstractQmsMessage, DeliveryMode, UInt32, Int32, Boolean):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DoBind(System.String,System.String,System.String,Qpid.Framing.FieldTable):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DoBind(String, String, String, FieldTable):Void</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DoQueueDeclare(System.String,System.Boolean,System.Boolean,System.Boolean):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.DoQueueDeclare(String, Boolean, Boolean, Boolean):Void</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplayOnFailOver():System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqChannel.ReplayOnFailOver():Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>AmqChannel.ReplayOnFailOver():Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Run():System.Void">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>AmqChannel.Run():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Unsubscribe(System.String):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>name</Item>
+ <Item>AmqChannel.Unsubscribe(String):Void</Item>
+ <Item>subscriptionName</Item>
+ <Item>IChannel.Unsubscribe(String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AmqChannel+Dispatcher">
+ <Members>
+ <Member Name=".ctor(Qpid.Client.AmqChannel)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Dispatcher.Dispatcher(AmqChannel)</Item>
+ <Item>_stopped</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DispatchMessage(Qpid.Client.Message.UnprocessedMessage):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Dispatcher.DispatchMessage(UnprocessedMessage):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQConnection">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ProvideDisposeBool">
+ <Item>Qpid.Client.AMQConnection</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(Qpid.Client.qms.ConnectionInfo)">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>_connected</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>_lastAMQException</Item>
+ <Item>Qpid.AMQException</Item>
+ <Item>null</Item>
+ </Issue>
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>_nextChannelId</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.Client.AMQConnectionException.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>1</Item>
+ <Item>AMQConnectionException.AMQConnectionException(String, Exception)</Item>
+ <Item>Unable to connect</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AMQConnection(ConnectionInfo)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>ConnectionInfo must be specified</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AttemptReconnection():System.Boolean">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AttemptReconnection():Boolean</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AttemptReconnection(System.String,System.Int32,System.Boolean):System.Boolean">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.AttemptReconnection(String, Int32, Boolean):Boolean</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>useSSL</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CloseSession(Qpid.Client.AmqChannel):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'channel'</Item>
+ <Item>AMQConnection.CloseSession(AmqChannel):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Dispose():System.Void">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="DisposeImplementation">
+ <Item>AMQConnection.Dispose():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ExceptionReceived(System.Exception):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>cause</Item>
+ <Item>Qpid.Messaging.QpidException</Item>
+ <Item>AMQConnection.ExceptionReceived(Exception):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FireFailoverComplete():System.Void">
+ <Messages>
+ <Message TypeName="UseEventsWhereAppropriate" Category="Microsoft.Design" CheckId="CA1030" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FireFailoverComplete</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FirePreFailover(System.Boolean):System.Boolean">
+ <Messages>
+ <Message TypeName="UseEventsWhereAppropriate" Category="Microsoft.Design" CheckId="CA1030" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FirePreFailover</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FirePreResubscribe():System.Boolean">
+ <Messages>
+ <Message Id="Resubscribe" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Resubscribe</Item>
+ <Item>AMQConnection.FirePreResubscribe():Boolean</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseEventsWhereAppropriate" Category="Microsoft.Design" CheckId="CA1030" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FirePreResubscribe</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="LoadTransportFromAssembly(System.String,System.Int32,System.String,System.String):Qpid.Client.Transport.ITransport">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.LoadTransportFromAssembly(String, Int32, String, String):ITransport</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.LoadTransportFromAssembly(String, Int32, String, String):ITransport</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MakeBrokerConnection(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.MakeBrokerConnection(BrokerInfo):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReopenChannel(System.UInt16,System.UInt16,System.Boolean):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.ReopenChannel(UInt16, UInt16, Boolean):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Error reopening channel ____ after failover: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.ReopenChannel(UInt16, UInt16, Boolean):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ResubscribeChannels():System.Void">
+ <Messages>
+ <Message Id="Resubscribe" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Resubscribe</Item>
+ <Item>AMQConnection.ResubscribeChannels():Void</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQConnection.ResubscribeChannels():Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StartHeartBeatThread(System.Int32):System.Void">
+ <Messages>
+ <Message Id="HeartBeat" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeDiscreteTerm">
+ <Item>HeartBeat</Item>
+ <Item>method</Item>
+ <Item>StartHeartBeatThread</Item>
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ <Message Id="heartbeatSeconds*1000" TypeName="OperationsShouldNotOverflow" Category="Microsoft.Usage" CheckId="CA2233" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>heartbeatSeconds*1000</Item>
+ <Item>AMQConnection.StartHeartBeatThread(Int32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StopHeartBeatThread():System.Void">
+ <Messages>
+ <Message Id="HeartBeat" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeDiscreteTerm">
+ <Item>HeartBeat</Item>
+ <Item>method</Item>
+ <Item>StopHeartBeatThread</Item>
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="toURL():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>toURL</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQConnection.toURL():String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Username">
+ <Messages>
+ <Message Id="Username" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeCompoundWord">
+ <Item>Username</Item>
+ <Item>property</Item>
+ <Item>Username</Item>
+ <Item>UserName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQConnectionException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.AMQConnectionException</Item>
+ <Item>protected AMQConnectionException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.AMQConnectionException</Item>
+ <Item>public AMQConnectionException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.AMQConnectionException</Item>
+ <Item>public AMQConnectionException(String)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQConnectionException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.String,System.Exception)">
+ <Messages>
+ <Message Id="1#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>AMQConnectionException.AMQConnectionException(String, Exception)</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQDestination">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQDestination</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="_destinationName">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_destinationName</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_destinationName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_exchangeClass">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_exchangeClass</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_exchangeClass</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_exchangeName">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_exchangeName</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_exchangeName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_isAutoDelete">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_isAutoDelete</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_isAutoDelete</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_isDurable">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_isDurable</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_isDurable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_isExclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_isExclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_isExclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_queueName">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_queueName</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_queueName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Equals(System.Object):System.Boolean">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>o</Item>
+ <Item>AMQDestination.Equals(Object):Boolean</Item>
+ <Item>obj</Item>
+ <Item>Object.Equals(Object):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StringsNotEqualNullSafe(System.String,System.String):System.Boolean">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>AMQDestination.StringsNotEqualNullSafe(String, String):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicMessageConsumer">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ProvideDisposeBool">
+ <Item>Qpid.Client.BasicMessageConsumer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Dispose():System.Void">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="DisposeImplementation">
+ <Item>BasicMessageConsumer.Dispose():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NotifyMessage(Qpid.Client.Message.UnprocessedMessage,System.Int32):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageConsumer.NotifyMessage(UnprocessedMessage, Int32):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="channelId" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>channelId</Item>
+ <Item>BasicMessageConsumer.NotifyMessage(UnprocessedMessage, Int32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage">
+ <Accessors>
+ <Accessor Name="set_OnMessage(Qpid.Messaging.MessageReceivedDelegate):System.Void">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageConsumer.set_OnMessage(MessageReceivedDelegate):Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Another thread is already receiving...</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="Receive(System.Int64):Qpid.Messaging.IMessage">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageConsumer.Receive(Int64):IMessage</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Another thread is already receiving (possibly asynchronously)...</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.NotImplementedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageConsumer.Receive(Int64):IMessage</Item>
+ <Item>1</Item>
+ <Item>NotImplementedException.NotImplementedException(String)</Item>
+ <Item>Need to implement synchronousQueue.Poll(timeout</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReceiveNoWait():Qpid.Messaging.IMessage">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageConsumer.ReceiveNoWait():IMessage</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Another thread is already receiving (possibly asynchronously)...</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReturnMessageOrThrow(System.Object):Qpid.Messaging.IMessage">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>o</Item>
+ <Item>System.Exception</Item>
+ <Item>BasicMessageConsumer.ReturnMessageOrThrow(Object):IMessage</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>BasicMessageConsumer.ReturnMessageOrThrow(Object):IMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicMessageProducer">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ProvideDisposeBool">
+ <Item>Qpid.Client.BasicMessageProducer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.String,System.String,System.Boolean,System.UInt16,Qpid.Client.AmqChannel,System.Int64,Qpid.Messaging.DeliveryMode,System.Int64,System.Boolean,System.Boolean,System.Int32)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'channel'</Item>
+ <Item>BasicMessageProducer.BasicMessageProducer(String, String, Boolean, UInt16, AmqChannel, Int64, DeliveryMode, Int64, Boolean, Boolean, Int32)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_channelId">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._channelId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_encoding">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._encoding</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_immediate">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._immediate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_logger">
+ <Messages>
+ <Message TypeName="DoNotDeclareReadOnlyMutableReferenceTypes" Category="Microsoft.Security" CheckId="CA2104" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._logger</Item>
+ <Item>log4net.ILog</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_logger</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_logger</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_mandatory">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._mandatory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_mimeType">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._mimeType</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_transacted">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer._transacted</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_IMMEDIATE">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_IMMEDIATE</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicMessageProducer.DEFAULT_IMMEDIATE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_MANDATORY">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_MANDATORY</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicMessageProducer.DEFAULT_MANDATORY</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DisableMessageID">
+ <Accessors>
+ <Accessor Name="get_DisableMessageID():System.Boolean">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer.get_DisableMessageID():Boolean</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>The method or operation is not implemented.</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>BasicMessageProducer.get_DisableMessageID():Boolean</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ <Accessor Name="set_DisableMessageID(System.Boolean):System.Void">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicMessageProducer.set_DisableMessageID(Boolean):Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>The method or operation is not implemented.</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>BasicMessageProducer.set_DisableMessageID(Boolean):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="Dispose():System.Void">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="DisposeImplementation">
+ <Item>BasicMessageProducer.Dispose():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Encoding">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Encoding</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MimeType">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MimeType</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Priority">
+ <Accessors>
+ <Accessor Name="set_Priority(System.Int32):System.Void">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentOutOfRangeException</Item>
+ <Item>ArgumentOutOfRangeException.ArgumentOutOfRangeException(String)</Item>
+ <Item>Priority of ____ is illegal. Value must be in range 0 to 9</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="TimeToLive">
+ <Accessors>
+ <Accessor Name="set_TimeToLive(System.Int64):System.Void">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentOutOfRangeException</Item>
+ <Item>ArgumentOutOfRangeException.ArgumentOutOfRangeException(String)</Item>
+ <Item>Time to live must be non-negative - supplied value was __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="Closeable">
+ <Messages>
+ <Message TypeName="IdentifiersShouldDifferByMoreThanCase" Category="Microsoft.Naming" CheckId="CA1708" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>'CLOSED'</Item>
+ <Item>Closed</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="_closed">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_closed</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_closed</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_closingLock">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_closingLock</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_closingLock</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckNotClosed():System.Void">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Closeable.CheckNotClosed():Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Object ____ has been closed</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLOSED">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Closeable.CLOSED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NOT_CLOSED">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>NOT_CLOSED</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Closeable.NOT_CLOSED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionTuneParameters">
+ <Members>
+ <Member Name="TxnLimit">
+ <Messages>
+ <Message Id="Txn" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Txn</Item>
+ <Item>ConnectionTuneParameters.TxnLimit:UInt32</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidConnectionInfo">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.QpidConnectionInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionInfo.QpidConnectionInfo()</Item>
+ <Item>_failoverMethod</Item>
+ <Item>System.String</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionInfo.QpidConnectionInfo()</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_logger">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionInfo._logger</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AddBrokerInfo(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>brokerInfo</Item>
+ <Item>QpidConnectionInfo.AddBrokerInfo(BrokerInfo):Void</Item>
+ <Item>broker</Item>
+ <Item>ConnectionInfo.AddBrokerInfo(BrokerInfo):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AsUrl():System.String">
+ <Messages>
+ <Message TypeName="DoNotConcatenateStringsInsideLoops" Category="Microsoft.Performance" CheckId="CA1818" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionInfo.AsUrl():String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FromUrl(System.String):Qpid.Client.qms.ConnectionInfo">
+ <Messages>
+ <Message Id="0#" TypeName="UriParametersShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1054" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>url</Item>
+ <Item>QpidConnectionInfo.FromUrl(String):ConnectionInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidConnectionUrl">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.QpidConnectionUrl</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="StaticHolderTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1053" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionUrl</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="FromUri(System.Uri):Qpid.Client.qms.ConnectionInfo">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidConnectionUrl.FromUri(Uri):ConnectionInfo</Item>
+ </Issue>
+ </Message>
+ <Message Id="uri" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>uri</Item>
+ <Item>QpidConnectionUrl.FromUri(Uri):ConnectionInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FromUrl(System.String):Qpid.Client.qms.ConnectionInfo">
+ <Messages>
+ <Message Id="url" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>url</Item>
+ <Item>QpidConnectionUrl.FromUrl(String):ConnectionInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Failover">
+ <Types>
+ <Type Name="FailoverException">
+ <Messages>
+ <Message TypeName="ExceptionsShouldBePublic" Category="Microsoft.Design" CheckId="CA1064" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Failover.FailoverException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="FailoverHandler">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Failover.FailoverHandler</Item>
+ <Item>System.Threading.ManualResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="getHost():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getPort():System.Int32">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getPort</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Run():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.AMQDisconnectedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>1</Item>
+ <Item>AMQDisconnectedException.AMQDisconnectedException(String)</Item>
+ <Item>Redirect was vetoed by client</Item>
+ </Issue>
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>1</Item>
+ <Item>AMQDisconnectedException.AMQDisconnectedException(String)</Item>
+ <Item>Server closed connection and no failover was successful</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.Client.Failover.FailoverException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>1</Item>
+ <Item>FailoverException.FailoverException(String)</Item>
+ <Item>Failing over about to start</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverHandler.Run():Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>FailoverHandler must Run on a non-background thread.</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setHost(System.String):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setPort(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setPort</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverSupport">
+ <Members>
+ <Member Name="execute(Qpid.Client.AMQConnection):System.Object">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>execute</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'con'</Item>
+ <Item>FailoverSupport.execute(AMQConnection):Object</Item>
+ </Issue>
+ <Issue>
+ <Item>'con'</Item>
+ <Item>FailoverSupport.execute(AMQConnection):Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="operation():System.Object">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>operation</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Handler">
+ <Types>
+ <Type Name="BasicDeliverMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>BasicDeliverMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicReturnMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>BasicReturnMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelCloseMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQChannelClosedException.#ctor(System.Int32,System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ChannelCloseMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>2</Item>
+ <Item>AMQChannelClosedException.AMQChannelClosedException(Int32, String)</Item>
+ <Item>Error: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ChannelCloseMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionCloseMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQConnectionClosedException.#ctor(System.Int32,System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionCloseMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>2</Item>
+ <Item>AMQConnectionClosedException.AMQConnectionClosedException(Int32, String)</Item>
+ <Item>Error: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ConnectionCloseMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'stateManager'</Item>
+ <Item>ConnectionCloseMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionCloseOkHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="method" TypeName="RemoveUnusedLocals" Category="Microsoft.Performance" CheckId="CA1804" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionCloseOkHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>method</Item>
+ <Item>Qpid.Framing.ConnectionCloseOkBody</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ConnectionCloseOkHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'stateManager'</Item>
+ <Item>ConnectionCloseOkHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionOpenOkMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'stateManager'</Item>
+ <Item>ConnectionOpenOkMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionRedirectMethodHandler">
+ <Members>
+ <Member Name="_logger">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionRedirectMethodHandler._logger</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetInstance():Qpid.Client.Handler.ConnectionRedirectMethodHandler">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionSecureMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ConnectionSecureMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionStartMethodHandler">
+ <Members>
+ <Member Name="GetFullSystemInfo():System.String">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>ConnectionStartMethodHandler.GetFullSystemInfo():String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionStartMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>No locales sent from server, passed: __</Item>
+ </Issue>
+ <Issue>
+ <Item>ConnectionStartMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>No supported security mechanism found, passed: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.AMQException.#ctor(log4net.ILog,System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionStartMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>2</Item>
+ <Item>AMQException.AMQException(ILog, String, Exception)</Item>
+ <Item>Unable to decode data: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ConnectionStartMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'stateManager'</Item>
+ <Item>ConnectionStartMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionTuneMethodHandler">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionTuneMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>ConnectionTuneMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'stateManager'</Item>
+ <Item>ConnectionTuneMethodHandler.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Message">
+ <Types>
+ <Type Name="AbstractQmsMessage">
+ <Messages>
+ <Message Id="Qms" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qms</Item>
+ <Item>Qpid.Client.Message.AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="_data">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_data</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_data</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_redelivered">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_redelivered</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_redelivered</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetExchangeName(System.String,System.String&amp;):System.String">
+ <Messages>
+ <Message TypeName="ProvideCorrectArgumentsToFormattingMethods" Category="Microsoft.Usage" CheckId="CA2241" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MissingSpecifier">
+ <Item>String.Format(String, Object[]):String</Item>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>'stack2'</Item>
+ <Item>split = {0}</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>AbstractQmsMessage.GetExchangeName(String, String&amp;):String</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AbstractQmsMessage.ToString():String</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteReplyToHeader(Qpid.Client.Message.AbstractQmsMessage+Dest):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AbstractQmsMessage.WriteReplyToHeader(Dest):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AbstractQmsMessageFactory">
+ <Messages>
+ <Message Id="Qms" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qms</Item>
+ <Item>Qpid.Client.Message.AbstractQmsMessageFactory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CreateMessage(System.Int64,Qpid.Buffer.ByteBuffer,Qpid.Framing.ContentHeaderBody):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="0#Nbr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>AbstractQmsMessageFactory.CreateMessage(Int64, ByteBuffer, ContentHeaderBody):AbstractQmsMessage</Item>
+ <Item>Nbr</Item>
+ <Item>messageNbr</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateMessage(System.Int64,System.Boolean,Qpid.Framing.ContentHeaderBody,System.Collections.IList):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>messageNbr</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessage(Int64, Boolean, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ <Item>deliverTag</Item>
+ <Item>IMessageFactory.CreateMessage(Int64, Boolean, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateMessageWithBody(System.Int64,Qpid.Framing.ContentHeaderBody,System.Collections.IList):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="0#Nbr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>AbstractQmsMessageFactory.CreateMessageWithBody(Int64, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ <Item>Nbr</Item>
+ <Item>messageNbr</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'bodies'</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessageWithBody(Int64, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ <Issue>
+ <Item>'bodies'</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessageWithBody(Int64, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ <Issue>
+ <Item>'contentHeader'</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessageWithBody(Int64, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ <Issue>
+ <Item>'contentHeader'</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessageWithBody(Int64, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQMessage">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="_channel">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_channel</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_channel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_contentHeaderProperties">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_contentHeaderProperties</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_contentHeaderProperties</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="MessageFactoryRegistry">
+ <Members>
+ <Member Name="CreateMessage(System.Int64,System.Boolean,Qpid.Framing.ContentHeaderBody,System.Collections.IList):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageFactoryRegistry.CreateMessage(Int64, Boolean, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Unsupport MIME type of __</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#Nbr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageFactoryRegistry.CreateMessage(Int64, Boolean, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ <Item>Nbr</Item>
+ <Item>messageNbr</Item>
+ </Issue>
+ </Message>
+ <Message Id="Unsupport" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Unsupport</Item>
+ <Item>Unsupport MIME type of __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'contentHeader'</Item>
+ <Item>MessageFactoryRegistry.CreateMessage(Int64, Boolean, ContentHeaderBody, IList):AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateMessage(System.String):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageFactoryRegistry.CreateMessage(String):AbstractQmsMessage</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Unsupport MIME type of __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentNullException</Item>
+ <Item>ArgumentNullException.ArgumentNullException(String)</Item>
+ <Item>Mime type must not be null</Item>
+ </Issue>
+ </Message>
+ <Message Id="Unsupport" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Unsupport</Item>
+ <Item>Unsupport MIME type of __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RegisterFactory(System.String,Qpid.Client.Message.IMessageFactory):System.Void">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentNullException</Item>
+ <Item>ArgumentNullException.ArgumentNullException(String)</Item>
+ <Item>Message factory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidBytesMessage">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Message.QpidBytesMessage</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Message.QpidBytesMessage</Item>
+ <Item>System.IO.MemoryStream, System.IO.BinaryWriter, System.IO.BinaryReader</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="ReadBytes(System.Byte[]):System.Int32">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>bytes</Item>
+ <Item>QpidBytesMessage.ReadBytes(Byte[]):Int32</Item>
+ <Item>array</Item>
+ <Item>IBytesMessage.ReadBytes(Byte[]):Int32</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadBytes(System.Byte[],System.Int32):System.Int32">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentOutOfRangeException</Item>
+ <Item>ArgumentOutOfRangeException.ArgumentOutOfRangeException(String)</Item>
+ <Item>count must be &gt;= 0</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>bytes</Item>
+ <Item>QpidBytesMessage.ReadBytes(Byte[], Int32):Int32</Item>
+ <Item>array</Item>
+ <Item>IBytesMessage.ReadBytes(Byte[], Int32):Int32</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>count</Item>
+ <Item>QpidBytesMessage.ReadBytes(Byte[], Int32):Int32</Item>
+ <Item>length</Item>
+ <Item>IBytesMessage.ReadBytes(Byte[], Int32):Int32</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(System.Double):System.Void">
+ <Messages>
+ <Message Id="0#v" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>QpidBytesMessage.Write(Double):Void</Item>
+ <Item>v</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(System.Int32):System.Void">
+ <Messages>
+ <Message Id="0#i" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>QpidBytesMessage.Write(Int32):Void</Item>
+ <Item>i</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(System.Int64):System.Void">
+ <Messages>
+ <Message Id="0#l" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>QpidBytesMessage.Write(Int64):Void</Item>
+ <Item>l</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(System.Single):System.Void">
+ <Messages>
+ <Message Id="0#v" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>QpidBytesMessage.Write(Single):Void</Item>
+ <Item>v</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteBoolean(System.Boolean):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>b</Item>
+ <Item>QpidBytesMessage.WriteBoolean(Boolean):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteBoolean(Boolean):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteByte(System.Byte):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>b</Item>
+ <Item>QpidBytesMessage.WriteByte(Byte):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteByte(Byte):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteBytes(System.Byte[]):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>bytes</Item>
+ <Item>QpidBytesMessage.WriteBytes(Byte[]):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteBytes(Byte[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteBytes(System.Byte[],System.Int32,System.Int32):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>bytes</Item>
+ <Item>QpidBytesMessage.WriteBytes(Byte[], Int32, Int32):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteBytes(Byte[], Int32, Int32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteChar(System.Char):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>c</Item>
+ <Item>QpidBytesMessage.WriteChar(Char):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteChar(Char):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteShort(System.Int16):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>i</Item>
+ <Item>QpidBytesMessage.WriteShort(Int16):Void</Item>
+ <Item>value</Item>
+ <Item>IBytesMessage.WriteShort(Int16):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidBytesMessageFactory">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Message.QpidBytesMessageFactory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CreateMessage(System.Int64,Qpid.Buffer.ByteBuffer,Qpid.Framing.ContentHeaderBody):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>deliveryTag</Item>
+ <Item>QpidBytesMessageFactory.CreateMessage(Int64, ByteBuffer, ContentHeaderBody):AbstractQmsMessage</Item>
+ <Item>messageNbr</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessage(Int64, ByteBuffer, ContentHeaderBody):AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidHeaders">
+ <Members>
+ <Member Name="CheckPropertyName(System.String):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidHeaders.CheckPropertyName(String):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Property name must not be the empty string</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="TestForEmptyStringsUsingStringLength" Category="Microsoft.Performance" CheckId="CA1820" Created="2006-12-04 13:11:47Z">
+ <Issue Name="IsNullOrEmpty">
+ <Item>Equals</Item>
+ <Item>""</Item>
+ <Item>QpidHeaders.CheckPropertyName(String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Clear():System.Void">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidHeaders.Clear():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidTextMessage">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Message.QpidTextMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(Qpid.Buffer.ByteBuffer)">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidTextMessage.QpidTextMessage(ByteBuffer)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(System.String)">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>QpidTextMessage.QpidTextMessage(String)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QpidTextMessageFactory">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Client.Message.QpidTextMessageFactory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CreateMessage(System.Int64,Qpid.Buffer.ByteBuffer,Qpid.Framing.ContentHeaderBody):Qpid.Client.Message.AbstractQmsMessage">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>deliveryTag</Item>
+ <Item>QpidTextMessageFactory.CreateMessage(Int64, ByteBuffer, ContentHeaderBody):AbstractQmsMessage</Item>
+ <Item>messageNbr</Item>
+ <Item>AbstractQmsMessageFactory.CreateMessage(Int64, ByteBuffer, ContentHeaderBody):AbstractQmsMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="UnexpectedBodyReceivedException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Message.UnexpectedBodyReceivedException</Item>
+ <Item>protected UnexpectedBodyReceivedException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.Message.UnexpectedBodyReceivedException</Item>
+ <Item>public UnexpectedBodyReceivedException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.Message.UnexpectedBodyReceivedException</Item>
+ <Item>public UnexpectedBodyReceivedException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.Message.UnexpectedBodyReceivedException</Item>
+ <Item>public UnexpectedBodyReceivedException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(log4net.ILog,System.String,System.Exception)">
+ <Messages>
+ <Message Id="2#t" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>UnexpectedBodyReceivedException.UnexpectedBodyReceivedException(ILog, String, Exception)</Item>
+ <Item>t</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="UnprocessedMessage">
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>UnprocessedMessage.UnprocessedMessage()</Item>
+ <Item>_bytesReceived</Item>
+ <Item>System.UInt64</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Bodies">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Bodies</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="BounceBody">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BounceBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ChannelId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ChannelId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ContentHeader">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentHeader</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliverBody">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliverBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReceiveBody(Qpid.Framing.ContentBody):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'body'</Item>
+ <Item>UnprocessedMessage.ReceiveBody(ContentBody):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Protocol">
+ <Types>
+ <Type Name="AMQMethodEvent">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQMethodEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQProtocolListener">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQProtocolListener</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(Qpid.Client.AMQConnection,Qpid.Client.State.AMQStateManager)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.AMQProtocolListener(AMQConnection, AMQStateManager)</Item>
+ <Item>_protocolSession</Item>
+ <Item>Qpid.Client.Protocol.AMQProtocolSession</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnException(System.Exception):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.OnException(Exception):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String, Exception)</Item>
+ <Item>Protocol handler error: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>cause</Item>
+ <Item>AMQProtocolListener.OnException(Exception):Void</Item>
+ <Item>e</Item>
+ <Item>IProtocolListener.OnException(Exception):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Framing.IDataBlock):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.OnMessage(IDataBlock):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.OnMessage(IDataBlock):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>AMQMethodEvent ____ was not processed by any listener.</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.OnMessage(IDataBlock):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'message'</Item>
+ <Item>AMQProtocolListener.OnMessage(IDataBlock):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PropagateExceptionToWaiters(System.Exception):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>AMQProtocolListener.PropagateExceptionToWaiters(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ProtocolSession">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolSession</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RemoveFrameListener(Qpid.Client.Protocol.Listener.IAMQMethodListener):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'listener'</Item>
+ <Item>AMQProtocolListener.RemoveFrameListener(IAMQMethodListener):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WhenClosed():System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQDisconnectedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolListener.WhenClosed():Void</Item>
+ <Item>1</Item>
+ <Item>AMQDisconnectedException.AMQDisconnectedException(String)</Item>
+ <Item>Server closed connection and reconnection not permitted.</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQProtocolSession">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQProtocolSession</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="AddSessionByChannel(System.UInt16,Qpid.Client.AmqChannel):System.Void">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentNullException</Item>
+ <Item>ArgumentNullException.ArgumentNullException(String)</Item>
+ <Item>Attempt to register a null channel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AMQConnection">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQProtocolSession.AMQConnection:AMQConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CloseSession(Qpid.Client.AmqChannel):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'channel'</Item>
+ <Item>AMQProtocolSession.CloseSession(AmqChannel):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConnectionTuneParameters">
+ <Accessors>
+ <Accessor Name="set_ConnectionTuneParameters(Qpid.Client.ConnectionTuneParameters):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'value'</Item>
+ <Item>AMQProtocolSession.set_ConnectionTuneParameters(ConnectionTuneParameters):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="MessageContentBodyReceived(System.UInt16,Qpid.Framing.ContentBody):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolSession.MessageContentBodyReceived(UInt16, ContentBody):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Error: received content body without having received a BasicDeliver frame first</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolSession.MessageContentBodyReceived(UInt16, ContentBody):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageContentHeaderReceived(System.UInt16,Qpid.Framing.ContentHeaderBody):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQProtocolSession.MessageContentHeaderReceived(UInt16, ContentHeaderBody):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Error: received content header without having received a JMSDeliver frame first</Item>
+ </Issue>
+ <Issue>
+ <Item>AMQProtocolSession.MessageContentHeaderReceived(UInt16, ContentHeaderBody):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Error: received duplicate content header or did not receive correct number of content body frames</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="UnprocessedMessageReceived(Qpid.Client.Message.UnprocessedMessage):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'message'</Item>
+ <Item>AMQProtocolSession.UnprocessedMessageReceived(UnprocessedMessage):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Username">
+ <Messages>
+ <Message Id="Username" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeCompoundWord">
+ <Item>Username</Item>
+ <Item>property</Item>
+ <Item>Username</Item>
+ <Item>UserName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IProtocolListener">
+ <Members>
+ <Member Name="OnException(System.Exception):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>IProtocolListener.OnException(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProtocolWriter">
+ <Members>
+ <Member Name="SyncWrite(Qpid.Framing.AMQFrame,System.Type):Qpid.Client.Protocol.AMQMethodEvent">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'frame'</Item>
+ <Item>ProtocolWriter.SyncWrite(AMQFrame, Type):AMQMethodEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Protocol.Listener">
+ <Types>
+ <Type Name="BlockingMethodFrameListener">
+ <Messages>
+ <Message TypeName="AbstractTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1012" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BlockingMethodFrameListener</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Protocol.Listener.BlockingMethodFrameListener</Item>
+ <Item>System.Threading.ManualResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.UInt16)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BlockingMethodFrameListener.BlockingMethodFrameListener(UInt16)</Item>
+ <Item>_doneEvt</Item>
+ <Item>Qpid.Client.Protocol.AMQMethodEvent</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_channelId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_channelId</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_channelId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_doneEvt">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_doneEvt</Item>
+ </Issue>
+ </Message>
+ <Message Id="Evt" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Evt</Item>
+ <Item>BlockingMethodFrameListener._doneEvt</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_doneEvt</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodReceived(Qpid.Client.Protocol.AMQMethodEvent):System.Boolean">
+ <Messages>
+ <Message TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BlockingMethodFrameListener.MethodReceived(AMQMethodEvent):Boolean</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>BlockingMethodFrameListener.MethodReceived(AMQMethodEvent):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IAMQMethodListener">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>IAMQMethodListener</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Error(System.Exception):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>IAMQMethodListener.Error(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodReceived(Qpid.Client.Protocol.AMQMethodEvent):System.Boolean">
+ <Messages>
+ <Message Id="0#evt" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IAMQMethodListener.MethodReceived(AMQMethodEvent):Boolean</Item>
+ <Item>evt</Item>
+ <Item>evt</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.qms">
+ <Types>
+ <Type Name="BrokerInfo">
+ <Messages>
+ <Message TypeName="IdentifiersShouldHaveCorrectPrefix" Category="Microsoft.Naming" CheckId="CA1715" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BrokerInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="getHost():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getOption(System.String):System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getOption</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getPort():System.Int32">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getPort</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getTimeout():System.Int64">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getTimeout</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getTransport():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getTransport</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setHost(System.String):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setOption(System.String,System.String):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setOption</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setPort(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setPort</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setTimeout(System.Int64):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setTimeout</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setTransport(System.String):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setTransport</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="useSSL():System.Boolean">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>useSSL</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfo.useSSL():Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="useSSL(System.Boolean):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>useSSL</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfo.useSSL(Boolean):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BrokerInfoConstants">
+ <Members>
+ <Member Name="DEFAULT_CONNECT_TIMEOUT">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.DEFAULT_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_PORT">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_PORT</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.DEFAULT_PORT</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_TRANSPORT">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_TRANSPORT</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.DEFAULT_TRANSPORT</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OPTIONS_CONNECT_TIMEOUT">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>OPTIONS_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.OPTIONS_CONNECT_TIMEOUT</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OPTIONS_RETRY">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>OPTIONS_RETRY</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.OPTIONS_RETRY</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OPTIONS_SSL">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>OPTIONS_SSL</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BrokerInfoConstants.OPTIONS_SSL</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="URL_FORMAT_EXAMPLE">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>URL_FORMAT_EXAMPLE</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>URL_FORMAT_EXAMPLE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionInfo">
+ <Messages>
+ <Message TypeName="IdentifiersShouldHaveCorrectPrefix" Category="Microsoft.Naming" CheckId="CA1715" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="AsUrl():System.String">
+ <Messages>
+ <Message TypeName="UriReturnValuesShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1055" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConnectionInfo.AsUrl():String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetAllBrokerInfos():System.Collections.IList">
+ <Messages>
+ <Message Id="Infos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Infos</Item>
+ <Item>ConnectionInfo.GetAllBrokerInfos():IList</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetAllBrokerInfos</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetBrokerCount():System.Int32">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetBrokerCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetClientName():System.String">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetClientName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetFailoverMethod():System.String">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetFailoverMethod</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetPassword():System.String">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetPassword</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetUsername():System.String">
+ <Messages>
+ <Message Id="Username" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeCompoundWord">
+ <Item>Username</Item>
+ <Item>method</Item>
+ <Item>GetUsername</Item>
+ <Item>UserName</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetUsername</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetVirtualHost():System.String">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetVirtualHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setUsername(System.String):System.Void">
+ <Messages>
+ <Message Id="Username" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeCompoundWord">
+ <Item>Username</Item>
+ <Item>method</Item>
+ <Item>setUsername</Item>
+ <Item>UserName</Item>
+ </Issue>
+ </Message>
+ <Message Id="username" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeCompoundWord">
+ <Item>username</Item>
+ <Item>parameter</Item>
+ <Item>username</Item>
+ <Item>userName</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setUsername</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionUrlConstants">
+ <Messages>
+ <Message TypeName="AvoidUninstantiatedInternalClasses" Category="Microsoft.Performance" CheckId="CA1812" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.qms.ConnectionUrlConstants</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="FailoverPolicy">
+ <Members>
+ <Member Name=".ctor(Qpid.Client.qms.ConnectionInfo)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverPolicy.FailoverPolicy(ConnectionInfo)</Item>
+ <Item>_methodsRetries</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.NotImplementedException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverPolicy.FailoverPolicy(ConnectionInfo)</Item>
+ <Item>1</Item>
+ <Item>NotImplementedException.NotImplementedException(String)</Item>
+ <Item>Dynamic loading of FailoverMethods not yet implemented.</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'connectionInfo'</Item>
+ <Item>FailoverPolicy.FailoverPolicy(ConnectionInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="addMethod(Qpid.Client.qms.failover.FailoverMethod):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>addMethod</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="attainedConnection():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>attainedConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetCurrentBrokerInfo():Qpid.Client.qms.BrokerInfo">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetCurrentBrokerInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getCurrentMethod():Qpid.Client.qms.failover.FailoverMethod">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getCurrentMethod</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetNextBrokerInfo():Qpid.Client.qms.BrokerInfo">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetNextBrokerInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setBroker(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setBroker</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setMethodRetries(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setMethodRetries</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="toString():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>toString</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="UrlSyntaxException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.qms.UrlSyntaxException</Item>
+ <Item>protected UrlSyntaxException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.qms.UrlSyntaxException</Item>
+ <Item>public UrlSyntaxException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.qms.UrlSyntaxException</Item>
+ <Item>public UrlSyntaxException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.qms.UrlSyntaxException</Item>
+ <Item>public UrlSyntaxException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>UrlSyntaxException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.String,System.String,System.Int32,System.Int32)">
+ <Messages>
+ <Message Id="0#" TypeName="UriParametersShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1054" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>url</Item>
+ <Item>UrlSyntaxException.UrlSyntaxException(String, String, Int32, Int32)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetIndex():System.Int32">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>GetIndex</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetReason():System.String">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>UrlSyntaxException.GetReason():String</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetReason</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="toString():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>toString</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.qms.failover">
+ <Types>
+ <Type Name="FailoverMethod">
+ <Messages>
+ <Message TypeName="IdentifiersShouldHaveCorrectPrefix" Category="Microsoft.Naming" CheckId="CA1715" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverMethod</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="attainedConnection():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>attainedConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="failoverAllowed():System.Boolean">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>failoverAllowed</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetCurrentBrokerInfo():Qpid.Client.qms.BrokerInfo">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetCurrentBrokerInfo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="getNextBrokerDetails():Qpid.Client.qms.BrokerInfo">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getNextBrokerDetails</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="methodName():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>methodName</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="reset():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>reset</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setBroker(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setBroker</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setRetries(System.Int32):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>setRetries</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverMethodConstants">
+ <Members>
+ <Member Name="RANDOM">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FailoverMethodConstants.RANDOM</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ROUND_ROBIN">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ROUND_ROBIN</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FailoverMethodConstants.ROUND_ROBIN</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverRoundRobin">
+ <Members>
+ <Member Name=".ctor(Qpid.Client.qms.ConnectionInfo)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ <Item>_currentCycleRetries</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ <Issue>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ <Item>_cycleRetries</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ <Issue>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ <Item>_serverRetries</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>At least one broker details must be specified.</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Int32.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ <Item>System.Int32.Parse(System.String)</Item>
+ <Item>System.Int32.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'connectionDetails'</Item>
+ <Item>FailoverRoundRobin.FailoverRoundRobin(ConnectionInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_CYCLE_RETRIES">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_CYCLE_RETRIES</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FailoverRoundRobin.DEFAULT_CYCLE_RETRIES</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_SERVER_RETRIES">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_SERVER_RETRIES</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FailoverRoundRobin.DEFAULT_SERVER_RETRIES</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setBroker(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message Id="System.Int32.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverRoundRobin.setBroker(BrokerInfo):Void</Item>
+ <Item>System.Int32.Parse(System.String)</Item>
+ <Item>System.Int32.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'broker'</Item>
+ <Item>FailoverRoundRobin.setBroker(BrokerInfo):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverSingleServer">
+ <Members>
+ <Member Name=".ctor(Qpid.Client.qms.ConnectionInfo)">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverSingleServer.FailoverSingleServer(ConnectionInfo)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>BrokerInfo details required for connection.</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'connectionDetails'</Item>
+ <Item>FailoverSingleServer.FailoverSingleServer(ConnectionInfo)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_SERVER_RETRIES">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_SERVER_RETRIES</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FailoverSingleServer.DEFAULT_SERVER_RETRIES</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setBroker(Qpid.Client.qms.BrokerInfo):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverSingleServer.setBroker(BrokerInfo):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>BrokerInfo details cannot be null</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Int32.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverSingleServer.setBroker(BrokerInfo):Void</Item>
+ <Item>System.Int32.Parse(System.String)</Item>
+ <Item>System.Int32.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="setRetries(System.Int32):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>retries</Item>
+ <Item>FailoverSingleServer.setRetries(Int32):Void</Item>
+ <Item>maxRetries</Item>
+ <Item>FailoverMethod.setRetries(Int32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="toString():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>toString</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.State">
+ <Types>
+ <Type Name="AMQState">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQState</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="ALL">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.ALL</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_CLOSED">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_CLOSED</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_CLOSED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_CLOSING">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_CLOSING</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_CLOSING</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_NOT_OPENED">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_NOT_OPENED</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_NOT_OPENED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_NOT_STARTED">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_NOT_STARTED</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_NOT_STARTED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_NOT_TUNED">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_NOT_TUNED</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_NOT_TUNED</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CONNECTION_OPEN">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CONNECTION_OPEN</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQState.CONNECTION_OPEN</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQStateChangedEvent">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQStateChangedEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQStateManager">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQStateManager</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="AttainState(Qpid.Client.State.AMQState):System.Void">
+ <Messages>
+ <Message Id="0#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>AMQStateManager.AttainState(AMQState):Void</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodReceived(Qpid.Client.Protocol.AMQMethodEvent):System.Boolean">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQStateManager.MethodReceived(AMQMethodEvent):Boolean</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'evt'</Item>
+ <Item>AMQStateManager.MethodReceived(AMQMethodEvent):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IAMQStateListener">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>IAMQStateListener</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="StateChanged(Qpid.Client.State.AMQStateChangedEvent):System.Void">
+ <Messages>
+ <Message Id="0#evt" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IAMQStateListener.StateChanged(AMQStateChangedEvent):Void</Item>
+ <Item>evt</Item>
+ <Item>evt</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IllegalStateTransitionException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.State.IllegalStateTransitionException</Item>
+ <Item>protected IllegalStateTransitionException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.State.IllegalStateTransitionException</Item>
+ <Item>public IllegalStateTransitionException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.State.IllegalStateTransitionException</Item>
+ <Item>public IllegalStateTransitionException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Client.State.IllegalStateTransitionException</Item>
+ <Item>public IllegalStateTransitionException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(Qpid.Client.State.AMQState,System.Type)">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IllegalStateTransitionException.IllegalStateTransitionException(AMQState, Type)</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>No valid state transition defined for receiving frame ____ from state __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IStateAwareMethodListener">
+ <Members>
+ <Member Name="MethodReceived(Qpid.Client.State.AMQStateManager,Qpid.Client.Protocol.AMQMethodEvent):System.Void">
+ <Messages>
+ <Message Id="1#evt" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IStateAwareMethodListener.MethodReceived(AMQStateManager, AMQMethodEvent):Void</Item>
+ <Item>evt</Item>
+ <Item>evt</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IStateListener">
+ <Members>
+ <Member Name="Error(System.Exception):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>IStateListener.Error(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StateWaiter">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.State.StateWaiter</Item>
+ <Item>System.Threading.ManualResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="WaituntilStateHasChanged():System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>StateWaiter.WaituntilStateHasChanged():Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String, Exception)</Item>
+ <Item>Error: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="Waituntil" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Waituntil</Item>
+ <Item>StateWaiter.WaituntilStateHasChanged():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Transport">
+ <Types>
+ <Type Name="AmqpChannel">
+ <Messages>
+ <Message Id="Amqp" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Amqp</Item>
+ <Item>Qpid.Client.Transport.AmqpChannel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(Qpid.Client.Transport.IByteChannel)">
+ <Messages>
+ <Message Id="0#" TypeName="AvoidTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1720" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>byteChannel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Read():System.Collections.Queue">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqpChannel.Read():Queue</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(Qpid.Framing.IDataBlock):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AmqpChannel.Write(IDataBlock):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQProtocolProvider">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQProtocolProvider</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="IProtocolWriter">
+ <Members>
+ <Member Name="Write(Qpid.Framing.IDataBlock):System.Void">
+ <Messages>
+ <Message Id="0#o" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>IProtocolWriter.Write(IDataBlock):Void</Item>
+ <Item>o</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ITransport">
+ <Members>
+ <Member Name="getLocalEndPoint():System.String">
+ <Messages>
+ <Message Id="EndPoint" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeDiscreteTerm">
+ <Item>EndPoint</Item>
+ <Item>method</Item>
+ <Item>getLocalEndPoint</Item>
+ <Item>Endpoint</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>getLocalEndPoint</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="SingleProtocolEncoderOutput">
+ <Members>
+ <Member Name="buffer">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>buffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>SingleProtocolEncoderOutput.Write(ByteBuffer):Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>{0} does not allow the writing of more than one buffer</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.Tests.dll">
+ <Modules>
+ <Module Name="qpid.client.tests.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Tests</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Client.Tests</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Client.Tests</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Client.Tests">
+ <Types>
+ <Type Name="Avergager">
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Avergager.Avergager()</Item>
+ <Item>num</Item>
+ <Item>System.Int64</Item>
+ <Item>0</Item>
+ </Issue>
+ <Issue>
+ <Item>Avergager.Avergager()</Item>
+ <Item>sum</Item>
+ <Item>System.Int64</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Avergager.ToString():String</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BaseMessagingTestFixture">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.BaseMessagingTestFixture</Item>
+ <Item>Qpid.Client.AMQConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="_channel">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_channel</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_channel</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_connection">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>_connection</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>_connection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Init():System.Void">
+ <Messages>
+ <Message TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BaseMessagingTestFixture.Init():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="HeadersMatchingConsumer">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.HeadersMatchingConsumer</Item>
+ <Item>System.Threading.AutoResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CreatePatternAsFieldTable():Qpid.Framing.FieldTable">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>HeadersMatchingConsumer.CreatePatternAsFieldTable():FieldTable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnException(System.Exception):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>HeadersMatchingConsumer.OnException(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'e'</Item>
+ <Item>HeadersMatchingConsumer.OnException(Exception):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HeadersMatchingConsumer.OnMessage(IMessage):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'message'</Item>
+ <Item>HeadersMatchingConsumer.OnMessage(IMessage):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProducerMultiConsumer">
+ <Messages>
+ <Message Id="Multi" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Multi</Item>
+ <Item>Qpid.Client.Tests.ProducerMultiConsumer</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.ProducerMultiConsumer</Item>
+ <Item>System.Threading.AutoResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProducerMultiConsumer.ProducerMultiConsumer()</Item>
+ <Item>_messageReceivedCount</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message Id="0#m" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>ProducerMultiConsumer.OnMessage(IMessage):Void</Item>
+ <Item>m</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RunTest():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProducerMultiConsumer.RunTest():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ServiceProvidingClient">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.ServiceProvidingClient</Item>
+ <Item>System.Threading.AutoResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceProvidingClient.ServiceProvidingClient()</Item>
+ <Item>_selector</Item>
+ <Item>System.String</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceProvidingClient.OnMessage(IMessage):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceProvidingClient.OnMessage(IMessage):Void</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceProvidingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceProvidingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ServiceRequestingClient">
+ <Messages>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.ServiceRequestingClient</Item>
+ <Item>System.Threading.AutoResetEvent</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Main(System.String[]):System.Void">
+ <Messages>
+ <Message Id="args" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>args</Item>
+ <Item>ServiceRequestingClient.Main(String[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Set timeSent!</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#m" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>m</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Int64.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.Int64.Parse(System.String)</Item>
+ <Item>System.Int64.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'m'</Item>
+ <Item>ServiceRequestingClient.OnMessage(IMessage):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="SendMessages():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ <Issue>
+ <Item>ServiceRequestingClient.SendMessages():Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="UndeliverableTest">
+ <Members>
+ <Member Name="OnException(System.Exception):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>e</Item>
+ <Item>Qpid.Messaging.QpidException</Item>
+ <Item>UndeliverableTest.OnException(Exception):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>UndeliverableTest.OnException(Exception):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>UndeliverableTest.OnException(Exception):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests.connection">
+ <Types>
+ <Type Name="ConnectionTest">
+ <Members>
+ <Member Name="passwordFailureConnection():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>passwordFailureConnection</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>ConnectionTest.passwordFailureConnection():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="simpleConnection():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>simpleConnection</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>ConnectionTest.simpleConnection():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Tests.failover">
+ <Types>
+ <Type Name="FailoverTest">
+ <Members>
+ <Member Name="DoFailoverTest(Qpid.Messaging.IConnection):System.Void">
+ <Messages>
+ <Message Id="Qpid.Client.Tests.failover.FailoverTest+MsgListener" TypeName="DoNotIgnoreMethodResults" Category="Microsoft.Usage" CheckId="CA1806" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ObjectCreation">
+ <Item>FailoverTest.DoFailoverTest(IConnection):Void</Item>
+ <Item>Qpid.Client.Tests.failover.FailoverTest+MsgListener</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverTest.DoFailoverTest(IConnection):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'message'</Item>
+ <Item>FailoverTest.OnMessage(IMessage):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TestWithBasicInfo():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverTest.TestWithBasicInfo():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverTest+MsgListener">
+ <Members>
+ <Member Name="init(Qpid.Messaging.IMessage):Qpid.Messaging.IMessagePublisher">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MsgListener.init(IMessage):IMessagePublisher</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FailoverTxTest">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Client.Tests.failover.FailoverTxTest</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>Qpid.Client.Tests.failover.FailoverTxTest</Item>
+ <Item>Qpid.Client.AMQConnection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="OnMessage(Qpid.Messaging.IMessage):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'message'</Item>
+ <Item>FailoverTxTest.OnMessage(IMessage):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TestWithBasicInfo():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FailoverTxTest.TestWithBasicInfo():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Client.Transport">
+ <Types>
+ <Type Name="BlockingIo">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Io</Item>
+ <Item>Qpid.Client.Transport.BlockingIo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="connectFromOutside():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>connectFromOutside</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>BlockingIo.connectFromOutside():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="connectionAndSleepForHeartbeats():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>connectionAndSleepForHeartbeats</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>BlockingIo.connectionAndSleepForHeartbeats():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="regularConnection():System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>regularConnection</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>BlockingIo.regularConnection():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Client.Transport.Socket.Blocking.dll">
+ <Modules>
+ <Module Name="qpid.client.transport.socket.blocking.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Client.Transport.Socket.Blocking</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Client.Transport.Socket.Blocking</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Client.Transport.Socket.Blocking</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Client.Transport.Socket.Blocking">
+ <Types>
+ <Type Name="BlockingSocketProcessor">
+ <Members>
+ <Member Name="Write(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BlockingSocketProcessor.Write(ByteBuffer):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BlockingSocketTransport">
+ <Members>
+ <Member Name=".ctor(System.String,System.Int32,Qpid.Client.AMQConnection)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'connection'</Item>
+ <Item>BlockingSocketTransport.BlockingSocketTransport(String, Int32, AMQConnection)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_log">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BlockingSocketTransport._log</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BlockingSocketTransport+ReaderRunner">
+ <Members>
+ <Member Name="Run():System.Void">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReaderRunner.Run():Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ByteChannel">
+ <Members>
+ <Member Name="Read():Qpid.Buffer.ByteBuffer">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ByteChannel.Read():ByteBuffer</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ByteChannel.Write(ByteBuffer):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Codec.dll">
+ <Modules>
+ <Module Name="qpid.codec.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Codec</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Codec</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Codec</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Codec">
+ <Types>
+ <Type Name="CumulativeProtocolDecoder">
+ <Members>
+ <Member Name="DecodeAll(Qpid.Buffer.ByteBuffer,Qpid.Codec.IProtocolDecoderOutput):System.Void">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>CumulativeProtocolDecoder.DecodeAll(ByteBuffer, IProtocolDecoderOutput):Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>doDecode() can't return true when buffer is not consumed.</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>CumulativeProtocolDecoder.DecodeAll(ByteBuffer, IProtocolDecoderOutput):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Dispose():System.Void">
+ <Messages>
+ <Message TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063" Created="2006-12-04 13:11:47Z">
+ <Issue Name="DisposeImplementation">
+ <Item>CumulativeProtocolDecoder.Dispose():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IProtocolEncoderOutput">
+ <Members>
+ <Member Name="Write(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="0#buf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IProtocolEncoderOutput.Write(ByteBuffer):Void</Item>
+ <Item>buf</Item>
+ <Item>buf</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProtocolCodecException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Codec.ProtocolCodecException</Item>
+ <Item>protected ProtocolCodecException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Codec.ProtocolCodecException</Item>
+ <Item>public ProtocolCodecException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>ProtocolCodecException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.Exception)">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolCodecException.ProtocolCodecException(Exception)</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String, Exception)</Item>
+ <Item>Codec Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProtocolDecoderException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Codec.ProtocolDecoderException</Item>
+ <Item>protected ProtocolDecoderException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Codec.ProtocolDecoderException</Item>
+ <Item>public ProtocolDecoderException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="ProtocolEncoderException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Codec.ProtocolEncoderException</Item>
+ <Item>protected ProtocolEncoderException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Codec.ProtocolEncoderException</Item>
+ <Item>public ProtocolEncoderException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Codec.Demux">
+ <Types>
+ <Type Name="DemuxingProtocolCodecFactory">
+ <Messages>
+ <Message Id="Demuxing" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Demuxing</Item>
+ <Item>Qpid.Codec.Demux.DemuxingProtocolCodecFactory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="DisposeCodecResources():System.Void">
+ <Messages>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>DemuxingProtocolCodecFactory.DisposeCodecResources():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Register(System.Type):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DemuxingProtocolCodecFactory.Register(Type):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Unregisterable type: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="Unregisterable" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Unregisterable</Item>
+ <Item>Unregisterable type: __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DemuxingProtocolCodecFactory+DefaultConstructorMessageDecoderFactory">
+ <Members>
+ <Member Name=".ctor(System.Type)">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DefaultConstructorMessageDecoderFactory.DefaultConstructorMessageDecoderFactory(Type)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>decoderClass is not assignable to MessageDecoder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NewDecoder():Qpid.Codec.Demux.IMessageDecoder">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DefaultConstructorMessageDecoderFactory.NewDecoder():IMessageDecoder</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String, Exception)</Item>
+ <Item>Failed to create a new instance of __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>DefaultConstructorMessageDecoderFactory.NewDecoder():IMessageDecoder</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DemuxingProtocolCodecFactory+DefaultConstructorMessageEncoderFactory">
+ <Members>
+ <Member Name=".ctor(System.Type)">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DefaultConstructorMessageEncoderFactory.DefaultConstructorMessageEncoderFactory(Type)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>encoderClass is not assignable to MessageEncoder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NewEncoder():Qpid.Codec.Demux.IMessageEncoder">
+ <Messages>
+ <Message Id="System.Exception.#ctor(System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DefaultConstructorMessageEncoderFactory.NewEncoder():IMessageEncoder</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String, Exception)</Item>
+ <Item>Failed to create a new instance of __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>DefaultConstructorMessageEncoderFactory.NewEncoder():IMessageEncoder</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DemuxingProtocolCodecFactory+ProtocolDecoderImpl">
+ <Members>
+ <Member Name="DoDecode(Qpid.Buffer.ByteBuffer,Qpid.Codec.IProtocolDecoderOutput):System.Boolean">
+ <Messages>
+ <Message Id="Qpid.Codec.ProtocolDecoderException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolDecoderImpl.DoDecode(ByteBuffer, IProtocolDecoderOutput):Boolean</Item>
+ <Item>1</Item>
+ <Item>ProtocolDecoderException.ProtocolDecoderException(String)</Item>
+ <Item>Message decoder returned NOT_OK.</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolDecoderImpl.DoDecode(ByteBuffer, IProtocolDecoderOutput):Boolean</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Unexpected decode result (see your decode()): __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>ProtocolDecoderImpl.DoDecode(ByteBuffer, IProtocolDecoderOutput):Boolean</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ <Issue Name="TooGeneric">
+ <Item>ProtocolDecoderImpl.DoDecode(ByteBuffer, IProtocolDecoderOutput):Boolean</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="MessageDecoderResult">
+ <Members>
+ <Member Name="NEED_DATA">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>NEED_DATA</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>MessageDecoderResult.NEED_DATA</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NOT_OK">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>NOT_OK</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberOk">
+ <Item>MessageDecoderResult.NOT_OK</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OK">
+ <Messages>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberOk">
+ <Item>MessageDecoderResult.OK</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Common.dll">
+ <Modules>
+ <Module Name="qpid.common.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Common</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Common</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoAttr">
+ <Item>Qpid.Common</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid">
+ <Types>
+ <Type Name="AMQChannelClosedException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.AMQChannelClosedException</Item>
+ <Item>protected AMQChannelClosedException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQChannelClosedException</Item>
+ <Item>public AMQChannelClosedException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQChannelClosedException</Item>
+ <Item>public AMQChannelClosedException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQChannelClosedException</Item>
+ <Item>public AMQChannelClosedException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQChannelClosedException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQConnectionClosedException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.AMQConnectionClosedException</Item>
+ <Item>protected AMQConnectionClosedException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQConnectionClosedException</Item>
+ <Item>public AMQConnectionClosedException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQConnectionClosedException</Item>
+ <Item>public AMQConnectionClosedException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQConnectionClosedException</Item>
+ <Item>public AMQConnectionClosedException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQConnectionClosedException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQDisconnectedException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.AMQDisconnectedException</Item>
+ <Item>protected AMQDisconnectedException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQDisconnectedException</Item>
+ <Item>public AMQDisconnectedException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQDisconnectedException</Item>
+ <Item>public AMQDisconnectedException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQDisconnectedException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.AMQException</Item>
+ <Item>protected AMQException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQException</Item>
+ <Item>public AMQException()</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQException</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>AMQException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(log4net.ILog,System.Int32,System.String)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'logger'</Item>
+ <Item>AMQException.AMQException(ILog, Int32, String)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(log4net.ILog,System.Int32,System.String,System.Exception)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'logger'</Item>
+ <Item>AMQException.AMQException(ILog, Int32, String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(log4net.ILog,System.String)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'logger'</Item>
+ <Item>AMQException.AMQException(ILog, String)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(log4net.ILog,System.String,System.Exception)">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'logger'</Item>
+ <Item>AMQException.AMQException(ILog, String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQUndeliveredException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.AMQUndeliveredException</Item>
+ <Item>protected AMQUndeliveredException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQUndeliveredException</Item>
+ <Item>public AMQUndeliveredException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQUndeliveredException</Item>
+ <Item>public AMQUndeliveredException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.AMQUndeliveredException</Item>
+ <Item>public AMQUndeliveredException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQUndeliveredException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="GetUndeliveredMessage():System.Object">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="50">
+ <Item>GetUndeliveredMessage</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Collections">
+ <Types>
+ <Type Name="BlockingQueue">
+ <Members>
+ <Member Name="EnqueueBlocking(System.Object):System.Void">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>BlockingQueue.EnqueueBlocking(Object):Void</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="EnqueueNoThrow(System.Object):System.Boolean">
+ <Messages>
+ <Message Id="0#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>BlockingQueue.EnqueueNoThrow(Object):Boolean</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="LinkedBlockingQueue">
+ <Messages>
+ <Message TypeName="ICollectionImplementationsHaveStronglyTypedMembers" Category="Microsoft.Design" CheckId="CA1035" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedBlockingQueue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.Int32)">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedBlockingQueue.LinkedBlockingQueue(Int32)</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Capacity must be positive, was passed __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="EnqueueBlocking(System.Object):System.Void">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentNullException</Item>
+ <Item>ArgumentNullException.ArgumentNullException(String)</Item>
+ <Item>Object must not be null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="EnqueueNoThrow(System.Object):System.Boolean">
+ <Messages>
+ <Message TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208" Created="2006-12-04 13:11:47Z">
+ <Issue Name="OneArgumentShouldBeParameterName">
+ <Item>System.ArgumentNullException</Item>
+ <Item>ArgumentNullException.ArgumentNullException(String)</Item>
+ <Item>e must not be null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="LinkedHashtable">
+ <Messages>
+ <Message TypeName="ICollectionImplementationsHaveStronglyTypedMembers" Category="Microsoft.Design" CheckId="CA1035" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedHashtable</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldHaveCorrectSuffix" Category="Microsoft.Naming" CheckId="CA1710" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Collections.LinkedHashtable</Item>
+ <Item>Dictionary</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Add(System.Object,System.Object):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedHashtable.Add(Object, Object):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>LinkedHashtable already contains key. key=__</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MoveToHead(System.Object):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedHashtable.MoveToHead(Object):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>Key ____ not found</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Tail">
+ <Accessors>
+ <Accessor Name="get_Tail():Qpid.Collections.LinkedHashtable+LinkedDictionaryEntry">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LinkedHashtable.get_Tail():LinkedDictionaryEntry</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="LinkedHashtable+LHTEnumerator">
+ <Members>
+ <Member Name=".ctor(Qpid.Collections.LinkedHashtable)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>LHTEnumerator.LHTEnumerator(LinkedHashtable)</Item>
+ <Item>_needsReset</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Current">
+ <Accessors>
+ <Accessor Name="get_Current():System.Object">
+ <Messages>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>LHTEnumerator.get_Current():Object</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="SynchronousQueue">
+ <Messages>
+ <Message TypeName="ICollectionImplementationsHaveStronglyTypedMembers" Category="Microsoft.Design" CheckId="CA1035" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>SynchronousQueue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.Boolean)">
+ <Messages>
+ <Message Id="strict" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>strict</Item>
+ <Item>SynchronousQueue.SynchronousQueue(Boolean)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_qlock">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>SynchronousQueue._qlock</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_waitingConsumers">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>SynchronousQueue._waitingConsumers</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="_waitingProducers">
+ <Messages>
+ <Message TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>SynchronousQueue._waitingProducers</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="SynchronousQueue+FifoWaitQueue">
+ <Messages>
+ <Message TypeName="AvoidUninstantiatedInternalClasses" Category="Microsoft.Performance" CheckId="CA1812" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Collections.SynchronousQueue+FifoWaitQueue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="SynchronousQueue+LifoWaitQueue">
+ <Messages>
+ <Message TypeName="AvoidUninstantiatedInternalClasses" Category="Microsoft.Performance" CheckId="CA1812" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Collections.SynchronousQueue+LifoWaitQueue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="SynchronousQueue+Node">
+ <Members>
+ <Member Name=".ctor(System.Object)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.Node(Object)</Item>
+ <Item>state</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(System.Object,Qpid.Collections.SynchronousQueue+Node)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.Node(Object, Node)</Item>
+ <Item>state</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Attempt(System.Int64):System.Boolean">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.Attempt(Int64):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Extract():System.Object">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.Extract():Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetItem():System.Object">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.GetItem():Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="SetItem(System.Object):System.Boolean">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.SetItem(Object):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WaitForPut():System.Object">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.WaitForPut():Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WaitForPut(System.Int64):System.Object">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.WaitForPut(Int64):Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WaitForTake():System.Void">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.WaitForTake():Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WaitForTake(System.Int64):System.Boolean">
+ <Messages>
+ <Message TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Node.WaitForTake(Int64):Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Common">
+ <Types>
+ <Type Name="AssemblySettings">
+ <Members>
+ <Member Name="GetConfig(System.Reflection.Assembly):System.Collections.IDictionary">
+ <Messages>
+ <Message TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AssemblySettings.GetConfig(Assembly):IDictionary</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'asm'</Item>
+ <Item>AssemblySettings.GetConfig(Assembly):IDictionary</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ <Namespace Name="Qpid.Framing">
+ <Types>
+ <Type Name="AccessRequestBody">
+ <Members>
+ <Member Name="Active">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>AccessRequestBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Realm</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Write</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Read</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestBody.CreateAMQFrame(UInt16, String, Boolean, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>AccessRequestBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Passive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Read">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Read</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Realm">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Realm</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Write">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Write</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AccessRequestOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>AccessRequestOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestOkBody.CreateAMQFrame(UInt16, UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AccessRequestOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>AccessRequestOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQDataBlockDecoder">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQDataBlockDecoder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQDataBlockDecoder.AMQDataBlockDecoder()</Item>
+ <Item>_disabled</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAndPopulateFrame(Qpid.Buffer.ByteBuffer):System.Object">
+ <Messages>
+ <Message Id="Qpid.Framing.AMQFrameDecodingException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQDataBlockDecoder.CreateAndPopulateFrame(ByteBuffer):Object</Item>
+ <Item>1</Item>
+ <Item>AMQFrameDecodingException.AMQFrameDecodingException(String)</Item>
+ <Item>Unsupported body type: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="marker" TypeName="RemoveUnusedLocals" Category="Microsoft.Performance" CheckId="CA1804" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQDataBlockDecoder.CreateAndPopulateFrame(ByteBuffer):Object</Item>
+ <Item>marker</Item>
+ <Item>System.Byte</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'input'</Item>
+ <Item>AMQDataBlockDecoder.CreateAndPopulateFrame(ByteBuffer):Object</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Decodable(Qpid.Buffer.ByteBuffer):Qpid.Codec.Demux.MessageDecoderResult">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>input</Item>
+ <Item>AMQDataBlockDecoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ <Item>buffer</Item>
+ <Item>IMessageDecoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQDataBlockDecoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'input'</Item>
+ <Item>AMQDataBlockDecoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Decode(Qpid.Buffer.ByteBuffer,Qpid.Codec.IProtocolDecoderOutput):Qpid.Codec.Demux.MessageDecoderResult">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>input</Item>
+ <Item>AMQDataBlockDecoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ <Item>buffer</Item>
+ <Item>IMessageDecoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'output'</Item>
+ <Item>AMQDataBlockDecoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Disabled">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Disabled</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQDataBlockEncoder">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQDataBlockEncoder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Encode(System.Object,Qpid.Codec.IProtocolEncoderOutput):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'output'</Item>
+ <Item>AMQDataBlockEncoder.Encode(Object, IProtocolEncoderOutput):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQFrame">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="PopulateFromBuffer(Qpid.Buffer.ByteBuffer,System.UInt16,System.UInt32,Qpid.Framing.IBodyFactory):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'bodyFactory'</Item>
+ <Item>AMQFrame.PopulateFromBuffer(ByteBuffer, UInt16, UInt32, IBodyFactory):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>AMQFrame.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQFrameDecodingException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.AMQFrameDecodingException</Item>
+ <Item>protected AMQFrameDecodingException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Framing.AMQFrameDecodingException</Item>
+ <Item>public AMQFrameDecodingException()</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQFrameDecodingException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="AMQMethodBody">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQMethodBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Clazz">
+ <Messages>
+ <Message Id="Clazz" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Clazz</Item>
+ <Item>AMQMethodBody.Clazz:UInt16</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object,System.Object,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AMQMethodBody.ToString():String</Item>
+ <Item>System.String.Format(System.String,System.Object,System.Object,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TYPE">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>AMQMethodBody.TYPE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>AMQMethodBody.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQMethodBodyFactory">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQMethodBodyFactory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CreateBody(Qpid.Buffer.ByteBuffer):Qpid.Framing.IBody">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'inbuf'</Item>
+ <Item>AMQMethodBodyFactory.CreateBody(ByteBuffer):IBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetInstance():Qpid.Framing.AMQMethodBodyFactory">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>GetInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="AMQProtocolHeaderException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.AMQProtocolHeaderException</Item>
+ <Item>protected AMQProtocolHeaderException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Framing.AMQProtocolHeaderException</Item>
+ <Item>public AMQProtocolHeaderException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Framing.AMQProtocolHeaderException</Item>
+ <Item>public AMQProtocolHeaderException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>AMQProtocolHeaderException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="BasicAckBody">
+ <Messages>
+ <Message Id="Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Ack</Item>
+ <Item>Qpid.Framing.BasicAckBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicAckBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicAckBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Multiple</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicAckBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicAckBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicAckBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Multiple">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Multiple</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicCancelBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>BasicCancelBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicCancelOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicConsumeBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Ack</Item>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoAck">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Ack</Item>
+ <Item>BasicConsumeBody.NoAck</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoLocal">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>BasicConsumeBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicConsumeOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicContentHeaderProperties">
+ <Members>
+ <Member Name="AppId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AppId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClusterId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClusterId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ContentType">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentType</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CorrelationId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>CorrelationId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryMode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryMode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Encoding">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Encoding</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Expiration">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Expiration</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Headers">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Headers</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PopulatePropertiesFromBuffer(Qpid.Buffer.ByteBuffer,System.UInt16):System.Void">
+ <Messages>
+ <Message Id="System.UInt32.Parse(System.String)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicContentHeaderProperties.PopulatePropertiesFromBuffer(ByteBuffer, UInt16):Void</Item>
+ <Item>System.UInt32.Parse(System.String)</Item>
+ <Item>System.UInt32.Parse(System.String,System.IFormatProvider)</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>BasicContentHeaderProperties.PopulatePropertiesFromBuffer(ByteBuffer, UInt16):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>BasicContentHeaderProperties.PopulatePropertiesFromBuffer(ByteBuffer, UInt16):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>BasicContentHeaderProperties.PopulatePropertiesFromBuffer(ByteBuffer, UInt16):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Priority">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Priority</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PropertyListSize">
+ <Accessors>
+ <Accessor Name="get_PropertyListSize():System.UInt32">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicContentHeaderProperties.get_PropertyListSize():UInt32</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Accessor>
+ </Accessors>
+ </Member>
+ <Member Name="ReplyTo">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyTo</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Timestamp">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Timestamp</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Type">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Type</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="UserId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>UserId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePropertyListPayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object)" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BasicContentHeaderProperties.WritePropertyListPayload(ByteBuffer):Void</Item>
+ <Item>System.String.Format(System.String,System.Object)</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>BasicContentHeaderProperties.WritePropertyListPayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicDeliverBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.UInt64,System.Boolean,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicDeliverBody.CreateAMQFrame(UInt16, String, UInt64, Boolean, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Redelivered">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicGetBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicGetBody.CreateAMQFrame(UInt16, UInt16, String, Boolean):AMQFrame</Item>
+ <Item>Ack</Item>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetBody.CreateAMQFrame(UInt16, UInt16, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoAck">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Ack</Item>
+ <Item>BasicGetBody.NoAck</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicGetEmptyBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetEmptyBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetEmptyBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClusterId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClusterId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ClusterId</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetEmptyBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetEmptyBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetEmptyBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicGetOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Boolean,System.String,System.String,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetOkBody.CreateAMQFrame(UInt16, UInt64, Boolean, String, String, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicGetOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicGetOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Redelivered">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicPublishBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicPublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicPublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicPublishBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Immediate">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Mandatory">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicPublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicPublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicQosBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.BasicQosBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32,System.UInt16,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Global">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>BasicQosBody.PrefetchCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchSize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>BasicQosBody.PrefetchSize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicQosOkBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.BasicQosOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicRecoverBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRecoverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicRecoverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicRecoverBody.CreateAMQFrame(UInt16, Boolean):AMQFrame</Item>
+ <Item>Requeue</Item>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRecoverBody.CreateAMQFrame(UInt16, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRecoverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicRecoverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Requeue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Requeue</Item>
+ <Item>BasicRecoverBody.Requeue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicRejectBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRejectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicRejectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>BasicRejectBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ <Item>Requeue</Item>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRejectBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicRejectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicRejectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Requeue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Requeue</Item>
+ <Item>BasicRejectBody.Requeue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="BasicReturnBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicReturnBody.CreateAMQFrame(UInt16, UInt16, String, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>BasicReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>BasicReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelAlertBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelAlertBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelAlertBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,Qpid.Framing.FieldTable):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Details</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelAlertBody.CreateAMQFrame(UInt16, UInt16, String, FieldTable):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Details">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Details</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelAlertBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelAlertBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelCloseBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelCloseBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClassId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClassId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.UInt16,System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ClassId</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MethodId</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseBody.CreateAMQFrame(UInt16, UInt16, String, UInt16, UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelCloseBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MethodId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelCloseOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelCloseOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelCloseOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelCloseOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelFlowBody">
+ <Members>
+ <Member Name="Active">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelFlowBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowBody.CreateAMQFrame(UInt16, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelFlowBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelFlowOkBody">
+ <Members>
+ <Member Name="Active">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelFlowOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Active</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowOkBody.CreateAMQFrame(UInt16, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelFlowOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelFlowOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelOpenBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>OutOfBand</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="OutOfBand">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>OutOfBand</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelOpenOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ChannelOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ChannelOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="CompositeAMQDataBlock">
+ <Messages>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>CompositeAMQDataBlock</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Blocks">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotReturnArrays" Category="Microsoft.Performance" CheckId="CA1819" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>CompositeAMQDataBlock.Blocks:IDataBlock[]</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionCloseBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionCloseBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClassId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClassId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.UInt16,System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ClassId</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MethodId</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseBody.CreateAMQFrame(UInt16, UInt16, String, UInt16, UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionCloseBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MethodId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MethodId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionCloseOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionCloseOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionCloseOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionCloseOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionOpenBody">
+ <Members>
+ <Member Name="Capabilities">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Capabilities</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>VirtualHost</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Capabilities</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Insist</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenBody.CreateAMQFrame(UInt16, String, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Insist">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Insist</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="VirtualHost">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>VirtualHost</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionOpenOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>KnownHosts</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="KnownHosts">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>KnownHosts</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionRedirectBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionRedirectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionRedirectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Host</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>KnownHosts</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionRedirectBody.CreateAMQFrame(UInt16, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Host">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Host</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="KnownHosts">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>KnownHosts</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionRedirectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionRedirectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionSecureBody">
+ <Members>
+ <Member Name="Challenge">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Challenge</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionSecureBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Byte[]):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Challenge</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureBody.CreateAMQFrame(UInt16, Byte[]):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionSecureBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionSecureOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionSecureOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Byte[]):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Response</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureOkBody.CreateAMQFrame(UInt16, Byte[]):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionSecureOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionSecureOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Response">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Response</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionStartBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionStartBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Byte,System.Byte,Qpid.Framing.FieldTable,System.Byte[],System.Byte[]):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>VersionMajor</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>VersionMinor</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ServerProperties</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Mechanisms</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Locales</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartBody.CreateAMQFrame(UInt16, Byte, Byte, FieldTable, Byte[], Byte[]):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Locales">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Locales</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Mechanisms">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Mechanisms</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionStartBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ServerProperties">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ServerProperties</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="VersionMajor">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>VersionMajor</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="VersionMinor">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>VersionMinor</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionStartOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionStartOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClientProperties">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClientProperties</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,Qpid.Framing.FieldTable,System.String,System.Byte[],System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ClientProperties</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Mechanism</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Response</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Locale</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartOkBody.CreateAMQFrame(UInt16, FieldTable, String, Byte[], String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Locale">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Locale</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Mechanism">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Mechanism</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionStartOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionStartOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Response">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Response</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionTuneBody">
+ <Members>
+ <Member Name="ChannelMax">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ChannelMax</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionTuneBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.UInt32,System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ChannelMax</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FrameMax</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneBody.CreateAMQFrame(UInt16, UInt16, UInt32, UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FrameMax">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FrameMax</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Heartbeat">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionTuneBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ConnectionTuneOkBody">
+ <Members>
+ <Member Name="ChannelMax">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ChannelMax</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionTuneOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.UInt32,System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ChannelMax</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FrameMax</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneOkBody.CreateAMQFrame(UInt16, UInt16, UInt32, UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="FrameMax">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FrameMax</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Heartbeat">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Heartbeat</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ConnectionTuneOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ConnectionTuneOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ContentBody">
+ <Members>
+ <Member Name="CreateAMQFrame(System.UInt16,Qpid.Framing.ContentBody):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message TypeName="ConsiderPassingBaseTypesAsParameters" Category="Microsoft.Design" CheckId="CA1011" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>body</Item>
+ <Item>ContentBody.CreateAMQFrame(UInt16, ContentBody):AMQFrame</Item>
+ <Item>Qpid.Framing.ContentBody</Item>
+ <Item>Qpid.Framing.IBody</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ContentBody.CreateAMQFrame(UInt16, ContentBody):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Payload">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Payload</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PopulateFromBuffer(Qpid.Buffer.ByteBuffer,System.UInt32):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ContentBody.PopulateFromBuffer(ByteBuffer, UInt32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TYPE">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ContentBody.TYPE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ContentBody.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ContentBodyFactory">
+ <Members>
+ <Member Name="GetInstance():Qpid.Framing.ContentBodyFactory">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>GetInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ContentHeaderBody">
+ <Members>
+ <Member Name="BodySize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>BodySize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ClassId">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ClassId</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,Qpid.Framing.ContentHeaderBody):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message TypeName="ConsiderPassingBaseTypesAsParameters" Category="Microsoft.Design" CheckId="CA1011" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>body</Item>
+ <Item>ContentHeaderBody.CreateAMQFrame(UInt16, ContentHeaderBody):AMQFrame</Item>
+ <Item>Qpid.Framing.ContentHeaderBody</Item>
+ <Item>Qpid.Framing.IBody</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ContentHeaderBody.CreateAMQFrame(UInt16, ContentHeaderBody):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.UInt16,Qpid.Framing.BasicContentHeaderProperties,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message TypeName="ConsiderPassingBaseTypesAsParameters" Category="Microsoft.Design" CheckId="CA1011" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>properties</Item>
+ <Item>ContentHeaderBody.CreateAMQFrame(UInt16, UInt16, UInt16, BasicContentHeaderProperties, UInt32):AMQFrame</Item>
+ <Item>Qpid.Framing.BasicContentHeaderProperties</Item>
+ <Item>Qpid.Framing.IContentHeaderProperties</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ContentHeaderBody.CreateAMQFrame(UInt16, UInt16, UInt16, BasicContentHeaderProperties, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PopulateFromBuffer(Qpid.Buffer.ByteBuffer,System.UInt32):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ContentHeaderBody.PopulateFromBuffer(ByteBuffer, UInt32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Properties">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Properties</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentHeaderBody.ToString():String</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TYPE">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ContentHeaderBody.TYPE</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>TYPE</Item>
+ <Item>2</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Weight">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Weight</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ContentHeaderBody.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ContentHeaderBodyFactory">
+ <Members>
+ <Member Name="GetInstance():Qpid.Framing.ContentHeaderBodyFactory">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>GetInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ContentHeaderPropertiesFactory">
+ <Members>
+ <Member Name="CreateContentHeaderProperties(System.UInt16,System.UInt16,Qpid.Buffer.ByteBuffer):Qpid.Framing.IContentHeaderProperties">
+ <Messages>
+ <Message Id="Qpid.Framing.AMQFrameDecodingException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentHeaderPropertiesFactory.CreateContentHeaderProperties(UInt16, UInt16, ByteBuffer):IContentHeaderProperties</Item>
+ <Item>1</Item>
+ <Item>AMQFrameDecodingException.AMQFrameDecodingException(String)</Item>
+ <Item>Unsupport content header class id: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="Unsupport" TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Unsupport</Item>
+ <Item>Unsupport content header class id: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>ContentHeaderPropertiesFactory.CreateContentHeaderProperties(UInt16, UInt16, ByteBuffer):IContentHeaderProperties</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="GetInstance():Qpid.Framing.ContentHeaderPropertiesFactory">
+ <Messages>
+ <Message TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>GetInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DtxSelectBody">
+ <Messages>
+ <Message Id="Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Dtx</Item>
+ <Item>Qpid.Framing.DtxSelectBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxSelectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxSelectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DtxSelectOkBody">
+ <Messages>
+ <Message Id="Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Dtx</Item>
+ <Item>Qpid.Framing.DtxSelectOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxSelectOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxSelectOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxSelectOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DtxStartBody">
+ <Messages>
+ <Message Id="Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Dtx</Item>
+ <Item>Qpid.Framing.DtxStartBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxStartBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DtxIdentifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DtxStartBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ <Item>Dtx</Item>
+ <Item>DtxIdentifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DtxIdentifier">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DtxIdentifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Dtx</Item>
+ <Item>DtxStartBody.DtxIdentifier</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxStartBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="DtxStartOkBody">
+ <Messages>
+ <Message Id="Dtx" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Dtx</Item>
+ <Item>Qpid.Framing.DtxStartOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxStartOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DtxStartOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>DtxStartOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="EncodingUtils">
+ <Messages>
+ <Message Id="Utils" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Utils</Item>
+ <Item>Qpid.Framing.EncodingUtils</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="StaticHolderTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1053" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>EncodingUtils</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="EncodedLongStringLength(System.String):System.UInt32">
+ <Messages>
+ <Message Id="0#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>EncodingUtils.EncodedLongStringLength(String):UInt32</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="EncodedLongstrLength(System.Byte[]):System.Int32">
+ <Messages>
+ <Message Id="Longstr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Longstr</Item>
+ <Item>EncodingUtils.EncodedLongstrLength(Byte[]):Int32</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="EncodedShortStringLength(System.String):System.UInt16">
+ <Messages>
+ <Message Id="0#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>EncodingUtils.EncodedShortStringLength(String):UInt16</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadBooleans(Qpid.Buffer.ByteBuffer):System.Boolean[]">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.ReadBooleans(ByteBuffer):Boolean[]</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadFieldTable(Qpid.Buffer.ByteBuffer):Qpid.Framing.FieldTable">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.ReadFieldTable(ByteBuffer):FieldTable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadLongstr(Qpid.Buffer.ByteBuffer):System.Byte[]">
+ <Messages>
+ <Message Id="Longstr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Longstr</Item>
+ <Item>EncodingUtils.ReadLongstr(ByteBuffer):Byte[]</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.ReadLongstr(ByteBuffer):Byte[]</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadLongString(Qpid.Buffer.ByteBuffer):System.String">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.ReadLongString(ByteBuffer):String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReadShortString(Qpid.Buffer.ByteBuffer):System.String">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.ReadShortString(ByteBuffer):String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteBooleans(Qpid.Buffer.ByteBuffer,System.Boolean[]):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteBooleans(ByteBuffer, Boolean[]):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'values'</Item>
+ <Item>EncodingUtils.WriteBooleans(ByteBuffer, Boolean[]):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'values'</Item>
+ <Item>EncodingUtils.WriteBooleans(ByteBuffer, Boolean[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteFieldTableBytes(Qpid.Buffer.ByteBuffer,Qpid.Framing.FieldTable):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteFieldTableBytes(ByteBuffer, FieldTable):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteLongstr(Qpid.Buffer.ByteBuffer,System.Byte[]):System.Void">
+ <Messages>
+ <Message Id="Longstr" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Longstr</Item>
+ <Item>EncodingUtils.WriteLongstr(ByteBuffer, Byte[]):Void</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteLongstr(ByteBuffer, Byte[]):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteLongstr(ByteBuffer, Byte[]):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteLongStringBytes(Qpid.Buffer.ByteBuffer,System.String):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>EncodingUtils.WriteLongStringBytes(ByteBuffer, String):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>String too long</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>EncodingUtils.WriteLongStringBytes(ByteBuffer, String):Void</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteLongStringBytes(ByteBuffer, String):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteLongStringBytes(ByteBuffer, String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteShortStringBytes(Qpid.Buffer.ByteBuffer,System.String):System.Void">
+ <Messages>
+ <Message Id="1#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>EncodingUtils.WriteShortStringBytes(ByteBuffer, String):Void</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteShortStringBytes(ByteBuffer, String):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>EncodingUtils.WriteShortStringBytes(ByteBuffer, String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ExchangeDeclareBody">
+ <Members>
+ <Member Name="Arguments">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AutoDelete">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AutoDelete</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeclareBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.Boolean,Qpid.Framing.FieldTable):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Type</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Durable</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>AutoDelete</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Internal</Item>
+ </Issue>
+ </Message>
+ <Message Id="8#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="9#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ <Message Id="8#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ExchangeDeclareBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Durable">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Durable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Internal">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Internal</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeclareBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>ExchangeDeclareBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Passive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Type">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Type</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ExchangeDeclareOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeclareOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeclareOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeclareOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ExchangeDeleteBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeleteBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IfUnused</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ExchangeDeleteBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="IfUnused">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IfUnused</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeleteBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>ExchangeDeleteBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ExchangeDeleteOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeleteOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeDeleteOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>ExchangeDeleteOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FieldTable">
+ <Messages>
+ <Message TypeName="CollectionsShouldImplementGenericInterface" Category="Microsoft.Design" CheckId="CA1010" Created="2006-12-04 13:11:47Z">
+ <Issue Certainty="60">
+ <Item>FieldTable</Item>
+ <Item>IEnumerable</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="IdentifiersShouldHaveCorrectSuffix" Category="Microsoft.Naming" CheckId="CA1710" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.FieldTable</Item>
+ <Item>Collection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.FieldTable()</Item>
+ <Item>_encodedSize</Item>
+ <Item>System.UInt32</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor(Qpid.Buffer.ByteBuffer,System.UInt32)">
+ <Messages>
+ <Message Id="Qpid.Framing.AMQFrameDecodingException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.FieldTable(ByteBuffer, UInt32)</Item>
+ <Item>1</Item>
+ <Item>AMQFrameDecodingException.AMQFrameDecodingException(String)</Item>
+ <Item>Unsupported field table type: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>FieldTable.FieldTable(ByteBuffer, UInt32)</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>FieldTable.FieldTable(ByteBuffer, UInt32)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AddAll(Qpid.Messaging.IFieldTable):System.Void">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ft</Item>
+ <Item>FieldTable.AddAll(IFieldTable):Void</Item>
+ <Item>source</Item>
+ <Item>IFieldTable.AddAll(IFieldTable):Void</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'ft'</Item>
+ <Item>FieldTable.AddAll(IFieldTable):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AdjustEncodingSizeWhenAdding(System.Object,System.Object):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>value</Item>
+ <Item>System.String</Item>
+ <Item>FieldTable.AdjustEncodingSizeWhenAdding(Object, Object):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.AdjustEncodingSizeWhenAdding(Object, Object):Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Unsupported value type: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>FieldTable.AdjustEncodingSizeWhenAdding(Object, Object):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AdjustEncodingSizeWhenRemoving(System.Object,System.Object):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>value</Item>
+ <Item>System.String</Item>
+ <Item>FieldTable.AdjustEncodingSizeWhenRemoving(Object, Object):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.Exception.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.AdjustEncodingSizeWhenRemoving(Object, Object):Void</Item>
+ <Item>1</Item>
+ <Item>Exception.Exception(String)</Item>
+ <Item>Illegal value type: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201" Created="2006-12-04 13:11:47Z">
+ <Issue Name="TooGeneric">
+ <Item>FieldTable.AdjustEncodingSizeWhenRemoving(Object, Object):Void</Item>
+ <Item>System.Exception</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckKey(System.Object):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.CheckKey(Object):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>All keys must be Strings - was passed: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>FieldTable.CheckKey(Object):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CheckValue(System.Object):System.Void">
+ <Messages>
+ <Message Id="System.ArgumentException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.CheckValue(Object):Void</Item>
+ <Item>1</Item>
+ <Item>ArgumentException.ArgumentException(String)</Item>
+ <Item>All values must be type string or int or long or uint, was passed: __</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="NonBreaking">
+ <Issue>
+ <Item>FieldTable.CheckValue(Object):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Local">
+ <Item>value</Item>
+ <Item>System.Byte[]</Item>
+ <Item>FieldTable.WritePayload(ByteBuffer):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ <Issue Name="Local">
+ <Item>value</Item>
+ <Item>System.String</Item>
+ <Item>FieldTable.WritePayload(ByteBuffer):Void</Item>
+ <Item>castclass</Item>
+ </Issue>
+ </Message>
+ <Message Id="System.InvalidOperationException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FieldTable.WritePayload(ByteBuffer):Void</Item>
+ <Item>1</Item>
+ <Item>InvalidOperationException.InvalidOperationException(String)</Item>
+ <Item>Unsupported type in FieldTable: __</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteToBuffer(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>FieldTable.WriteToBuffer(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileAckBody">
+ <Messages>
+ <Message Id="Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Ack</Item>
+ <Item>Qpid.Framing.FileAckBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileAckBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileAckBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Multiple</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileAckBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileAckBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileAckBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Multiple">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Multiple</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileCancelBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>FileCancelBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileCancelOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileConsumeBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Ack</Item>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoAck">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoAck</Item>
+ </Issue>
+ </Message>
+ <Message Id="Ack" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Ack</Item>
+ <Item>FileConsumeBody.NoAck</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoLocal">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>FileConsumeBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileConsumeOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileDeliverBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.UInt64,System.Boolean,System.String,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileDeliverBody.CreateAMQFrame(UInt16, String, UInt64, Boolean, String, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Identifier">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Redelivered">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Redelivered</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileOpenBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileOpenBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ContentSize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentSize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.UInt64):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ContentSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenBody.CreateAMQFrame(UInt16, String, UInt64):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Identifier">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileOpenBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileOpenOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileOpenOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StagedSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenOkBody.CreateAMQFrame(UInt16, UInt64):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileOpenOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StagedSize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>StagedSize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FilePublishBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FilePublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FilePublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FilePublishBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Identifier">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Identifier</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Immediate">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Mandatory">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FilePublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FilePublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileQosBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.FileQosBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32,System.UInt16,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Global">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>FileQosBody.PrefetchCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchSize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>FileQosBody.PrefetchSize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileQosOkBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.FileQosOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileRejectBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileRejectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileRejectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>FileRejectBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ <Item>Requeue</Item>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileRejectBody.CreateAMQFrame(UInt16, UInt64, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileRejectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileRejectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Requeue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Requeue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Requeue" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Requeue</Item>
+ <Item>FileRejectBody.Requeue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileReturnBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileReturnBody.CreateAMQFrame(UInt16, UInt16, String, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="FileStageBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileStageBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileStageBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileStageBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>FileStageBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>FileStageBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="HeartbeatBody">
+ <Members>
+ <Member Name="FRAME">
+ <Messages>
+ <Message TypeName="NonConstantFieldsShouldNotBeVisible" Category="Microsoft.Usage" CheckId="CA2211" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>FRAME</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PopulateFromBuffer(Qpid.Buffer.ByteBuffer,System.UInt32):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>HeartbeatBody.PopulateFromBuffer(ByteBuffer, UInt32):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TYPE">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>HeartbeatBody.TYPE</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="HeartbeatBodyFactory">
+ <Members>
+ <Member Name="CreateBody(Qpid.Buffer.ByteBuffer):Qpid.Framing.IBody">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>input</Item>
+ <Item>HeartbeatBodyFactory.CreateBody(ByteBuffer):IBody</Item>
+ <Item>inbuf</Item>
+ <Item>IBodyFactory.CreateBody(ByteBuffer):IBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IBodyFactory">
+ <Members>
+ <Member Name="CreateBody(Qpid.Buffer.ByteBuffer):Qpid.Framing.IBody">
+ <Messages>
+ <Message Id="0#inbuf" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IBodyFactory.CreateBody(ByteBuffer):IBody</Item>
+ <Item>inbuf</Item>
+ <Item>inbuf</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IEncodableAMQDataBlock">
+ <Messages>
+ <Message TypeName="AvoidEmptyInterfaces" Category="Microsoft.Design" CheckId="CA1040" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IEncodableAMQDataBlock</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>IEncodableAMQDataBlock</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="MainRegistry">
+ <Messages>
+ <Message TypeName="AvoidUninstantiatedInternalClasses" Category="Microsoft.Performance" CheckId="CA1812" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.MainRegistry</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="MethodBodyDecoderRegistry">
+ <Messages>
+ <Message TypeName="StaticHolderTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1053" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MethodBodyDecoderRegistry</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".cctor()">
+ <Messages>
+ <Message TypeName="InitializeReferenceTypeStaticFieldsInline" Category="Microsoft.Performance" CheckId="CA1810" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.MethodBodyDecoderRegistry</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Get(System.Int32,System.Int32):Qpid.Framing.AMQMethodBody">
+ <Messages>
+ <Message Id="Qpid.Framing.AMQFrameDecodingException.#ctor(log4net.ILog,System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MethodBodyDecoderRegistry.Get(Int32, Int32):AMQMethodBody</Item>
+ <Item>2</Item>
+ <Item>AMQFrameDecodingException.AMQFrameDecodingException(ILog, String)</Item>
+ <Item>Unable to find a suitable decoder for class ____ and method __</Item>
+ </Issue>
+ </Message>
+ <Message Id="Qpid.Framing.AMQFrameDecodingException.#ctor(log4net.ILog,System.String,System.Exception)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MethodBodyDecoderRegistry.Get(Int32, Int32):AMQMethodBody</Item>
+ <Item>2</Item>
+ <Item>AMQFrameDecodingException.AMQFrameDecodingException(ILog, String, Exception)</Item>
+ <Item>Unable to instantiate body class for class ____ and method ____: __</Item>
+ </Issue>
+ </Message>
+ <Message Id="0#clazz" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MethodBodyDecoderRegistry.Get(Int32, Int32):AMQMethodBody</Item>
+ <Item>clazz</Item>
+ <Item>clazz</Item>
+ </Issue>
+ </Message>
+ <Message Id="clazz*1000" TypeName="OperationsShouldNotOverflow" Category="Microsoft.Usage" CheckId="CA2233" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>clazz*1000</Item>
+ <Item>MethodBodyDecoderRegistry.Get(Int32, Int32):AMQMethodBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProtocolInitiation">
+ <Members>
+ <Member Name=".cctor()">
+ <Messages>
+ <Message TypeName="InitializeReferenceTypeStaticFieldsInline" Category="Microsoft.Performance" CheckId="CA1810" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.ProtocolInitiation</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolInitiation.ProtocolInitiation()</Item>
+ <Item>ProtocolMinor</Item>
+ <Item>System.Byte</Item>
+ <Item>0</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CURRENT_PROTOCOL_VERSION_MAJOR">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CURRENT_PROTOCOL_VERSION_MAJOR</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="NonConstantFieldsShouldNotBeVisible" Category="Microsoft.Usage" CheckId="CA2211" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>CURRENT_PROTOCOL_VERSION_MAJOR</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Header">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Header</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PopulateFromBuffer(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message Id="Qpid.AMQException.#ctor(System.String)" TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolInitiation.PopulateFromBuffer(ByteBuffer):Void</Item>
+ <Item>1</Item>
+ <Item>AMQException.AMQException(String)</Item>
+ <Item>Method not implemented</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>ProtocolInitiation.PopulateFromBuffer(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ <Message Id="buffer" TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801" Created="2006-12-04 13:11:47Z" FixCategory="Breaking">
+ <Issue>
+ <Item>buffer</Item>
+ <Item>ProtocolInitiation.PopulateFromBuffer(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ProtocolClass">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolClass</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ProtocolInstance">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolInstance</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ProtocolMajor">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolMajor</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ProtocolMinor">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolMinor</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ToString():System.String">
+ <Messages>
+ <Message Id="System.String.Format(System.String,System.Object[])" TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ProtocolInitiation.ToString():String</Item>
+ <Item>System.String.Format(System.String,System.Object[])</Item>
+ <Item>System.String.Format(System.IFormatProvider,System.String,System.Object[])</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WritePayload(Qpid.Buffer.ByteBuffer):System.Void">
+ <Messages>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ProtocolInitiation.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ProtocolInitiation.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ <Issue>
+ <Item>'buffer'</Item>
+ <Item>ProtocolInitiation.WritePayload(ByteBuffer):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ProtocolInitiation+Decoder">
+ <Messages>
+ <Message TypeName="NestedTypesShouldNotBeVisible" Category="Microsoft.Design" CheckId="CA1034" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Framing.ProtocolInitiation+Decoder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor()">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Decoder.Decoder()</Item>
+ <Item>_disabled</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Decodable(Qpid.Buffer.ByteBuffer):Qpid.Codec.Demux.MessageDecoderResult">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>inbuf</Item>
+ <Item>Decoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ <Item>buffer</Item>
+ <Item>IMessageDecoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'inbuf'</Item>
+ <Item>Decoder.Decodable(ByteBuffer):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Decode(Qpid.Buffer.ByteBuffer,Qpid.Codec.IProtocolDecoderOutput):Qpid.Codec.Demux.MessageDecoderResult">
+ <Messages>
+ <Message Id="0#" TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>inbuf</Item>
+ <Item>Decoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ <Item>buffer</Item>
+ <Item>IMessageDecoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>'inbuf'</Item>
+ <Item>Decoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ </Issue>
+ <Issue>
+ <Item>'output'</Item>
+ <Item>Decoder.Decode(ByteBuffer, IProtocolDecoderOutput):MessageDecoderResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Disabled">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Disabled</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueBindBody">
+ <Members>
+ <Member Name="Arguments">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueBindBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.String,System.Boolean,Qpid.Framing.FieldTable):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>QueueBindBody.CreateAMQFrame(UInt16, UInt16, String, String, String, Boolean, FieldTable):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindBody.CreateAMQFrame(UInt16, UInt16, String, String, String, Boolean, FieldTable):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueBindBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>QueueBindBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueBindOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueBindOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueBindOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueBindOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueDeclareBody">
+ <Members>
+ <Member Name="Arguments">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="AutoDelete">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>AutoDelete</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeclareBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.Boolean,Qpid.Framing.FieldTable):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Durable</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>AutoDelete</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="8#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Arguments</Item>
+ </Issue>
+ </Message>
+ <Message Id="7#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>QueueDeclareBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean, Boolean, Boolean, Boolean, FieldTable):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Durable">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Durable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeclareBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>QueueDeclareBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Passive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Passive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueDeclareOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeclareOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.UInt32,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareOkBody.CreateAMQFrame(UInt16, String, UInt32, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeclareOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeclareOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueDeleteBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeleteBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.Boolean,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IfUnused</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IfEmpty</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>QueueDeleteBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteBody.CreateAMQFrame(UInt16, UInt16, String, Boolean, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="IfEmpty">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IfEmpty</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="IfUnused">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IfUnused</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeleteBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>QueueDeleteBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueueDeleteOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeleteOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteOkBody.CreateAMQFrame(UInt16, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueueDeleteOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueueDeleteOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueuePurgeBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueuePurgeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>QueuePurgeBody.CreateAMQFrame(UInt16, UInt16, String, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeBody.CreateAMQFrame(UInt16, UInt16, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueuePurgeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>QueuePurgeBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="QueuePurgeOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueuePurgeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeOkBody.CreateAMQFrame(UInt16, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MessageCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>QueuePurgeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>QueuePurgeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamCancelBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamCancelBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StreamCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelBody.CreateAMQFrame(UInt16, String, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamCancelBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>StreamCancelBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamCancelOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamCancelOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamCancelOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamConsumeBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamConsumeBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="6#Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StreamConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean):AMQFrame</Item>
+ <Item>Nowait</Item>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exclusive">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exclusive</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamConsumeBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="NoLocal">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>NoLocal</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Nowait">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Nowait</Item>
+ </Issue>
+ </Message>
+ <Message Id="Nowait" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Nowait</Item>
+ <Item>StreamConsumeBody.Nowait</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamConsumeOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamConsumeOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeOkBody.CreateAMQFrame(UInt16, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamConsumeOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamDeliverBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamDeliverBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumerTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.UInt64,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumerTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamDeliverBody.CreateAMQFrame(UInt16, String, UInt64, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DeliveryTag">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DeliveryTag</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamDeliverBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Queue">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Queue</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamPublishBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamPublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamPublishBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.Boolean,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamPublishBody.CreateAMQFrame(UInt16, UInt16, String, String, Boolean, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Immediate">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Immediate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Mandatory">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Mandatory</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamPublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamPublishBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Ticket">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Ticket</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamQosBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.StreamQosBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamQosBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ConsumeRate">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ConsumeRate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32,System.UInt16,System.UInt32,System.Boolean):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ConsumeRate</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StreamQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, UInt32, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StreamQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, UInt32, Boolean):AMQFrame</Item>
+ <Item>Prefetch</Item>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosBody.CreateAMQFrame(UInt16, UInt32, UInt16, UInt32, Boolean):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Global">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Global</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamQosBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchCount">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchCount</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>StreamQosBody.PrefetchCount</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="PrefetchSize">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>PrefetchSize</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>StreamQosBody.PrefetchSize</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamQosOkBody">
+ <Messages>
+ <Message Id="Qos" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qos</Item>
+ <Item>Qpid.Framing.StreamQosOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamQosOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamQosOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="StreamReturnBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamReturnBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt16,System.String,System.String,System.String):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamReturnBody.CreateAMQFrame(UInt16, UInt16, String, String, String):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Exchange">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Exchange</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>StreamReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>StreamReturnBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyCode">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyCode</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ReplyText">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ReplyText</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="RoutingKey">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>RoutingKey</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestContentBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestContentBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestContentBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestContentOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestContentOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="ContentChecksum">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>ContentChecksum</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt32):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>ContentChecksum</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentOkBody.CreateAMQFrame(UInt16, UInt32):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestContentOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestContentOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestIntegerBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestIntegerBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Byte,System.UInt16,System.UInt32,System.UInt64,System.Byte):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Integer1</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Integer2</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Integer3</Item>
+ </Issue>
+ </Message>
+ <Message Id="4#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Integer4</Item>
+ </Issue>
+ </Message>
+ <Message Id="5#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Operation</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerBody.CreateAMQFrame(UInt16, Byte, UInt16, UInt32, UInt64, Byte):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Integer1">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Integer1</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Integer2">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Integer2</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Integer3">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Integer3</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Integer4">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Integer4</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestIntegerBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Operation">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Operation</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestIntegerOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestIntegerOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Result</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerOkBody.CreateAMQFrame(UInt16, UInt64):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestIntegerOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestIntegerOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Result">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Result</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestStringBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestStringBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.String,System.Byte[],System.Byte):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>String1</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>String2</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Operation</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringBody.CreateAMQFrame(UInt16, String, Byte[], Byte):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestStringBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Operation">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Operation</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="String1">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>String1</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="String2">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>String2</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestStringOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestStringOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.Byte[]):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Result</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringOkBody.CreateAMQFrame(UInt16, Byte[]):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestStringOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestStringOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Result">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Result</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestTableBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestTableBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,Qpid.Framing.FieldTable,System.Byte,System.Byte):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="2#" TypeName="AvoidLanguageSpecificTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1718" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerOp</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="AvoidTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1720" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerOp</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Table</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IntegerOp</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StringOp</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableBody.CreateAMQFrame(UInt16, FieldTable, Byte, Byte):AMQFrame</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Op</Item>
+ <Item>IntegerOp</Item>
+ </Issue>
+ </Message>
+ <Message Id="3#" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>Op</Item>
+ <Item>StringOp</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="IntegerOp">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerOp</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestTableBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StringOp">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>StringOp</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Table">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Table</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TestTableOkBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestTableOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,System.UInt64,System.Byte[]):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="1#" TypeName="AvoidLanguageSpecificTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1718" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerResult</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#" TypeName="AvoidTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1720" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerResult</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IntegerResult</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>StringResult</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableOkBody.CreateAMQFrame(UInt16, UInt64, Byte[]):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="IntegerResult">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IntegerResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TestTableOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TestTableOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="StringResult">
+ <Messages>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>StringResult</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TunnelRequestBody">
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TunnelRequestBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TunnelRequestBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16,Qpid.Framing.FieldTable):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="MetaData" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeDiscreteTerm">
+ <Item>MetaData</Item>
+ <Item>parameter</Item>
+ <Item>MetaData</Item>
+ <Item>Metadata</Item>
+ </Issue>
+ </Message>
+ <Message Id="1#" TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MetaData</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TunnelRequestBody.CreateAMQFrame(UInt16, FieldTable):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MetaData">
+ <Messages>
+ <Message Id="MetaData" TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ShouldBeDiscreteTerm">
+ <Item>MetaData</Item>
+ <Item>field</Item>
+ <Item>MetaData</Item>
+ <Item>Metadata</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MetaData</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TunnelRequestBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TunnelRequestBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxCommitBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxCommitBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxCommitBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxCommitBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxCommitOkBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxCommitOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxCommitOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxCommitOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxCommitOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxRollbackBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxRollbackBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxRollbackBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxRollbackBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxRollbackOkBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxRollbackOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxRollbackOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxRollbackOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxRollbackOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxSelectBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxSelectBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxSelectBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxSelectBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="TxSelectOkBody">
+ <Messages>
+ <Message TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Tx</Item>
+ <Item>Qpid.Framing.TxSelectOkBody</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="CLASS_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxSelectOkBody.CLASS_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateAMQFrame(System.UInt16):Qpid.Framing.AMQFrame">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectOkBody.CreateAMQFrame(UInt16):AMQFrame</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="METHOD_ID">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>TxSelectOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>TxSelectOkBody.METHOD_ID</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ <Target Name="$(ProjectDir)/Qpid.Client.Tests/bin/Debug/Qpid.Messaging.dll">
+ <Modules>
+ <Module Name="qpid.messaging.dll">
+ <Messages>
+ <Message TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210" Created="2006-12-04 13:11:47Z">
+ <Issue Name="NoStrongName">
+ <Item>Qpid.Messaging</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Namespaces>
+ <Namespace Name="Qpid.Messaging">
+ <Types>
+ <Type Name="AcknowledgeMode">
+ <Members>
+ <Member Name="DupsOkAcknowledge">
+ <Messages>
+ <Message Id="Dups" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Dups</Item>
+ <Item>AcknowledgeMode.DupsOkAcknowledge</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ChannelLimitReachedException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.ChannelLimitReachedException</Item>
+ <Item>protected ChannelLimitReachedException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.ChannelLimitReachedException</Item>
+ <Item>public ChannelLimitReachedException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.ChannelLimitReachedException</Item>
+ <Item>public ChannelLimitReachedException(String)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.ChannelLimitReachedException</Item>
+ <Item>public ChannelLimitReachedException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="ExceptionListenerDelegate">
+ <Messages>
+ <Message TypeName="IdentifiersShouldNotHaveIncorrectSuffix" Category="Microsoft.Naming" CheckId="CA1711" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.ExceptionListenerDelegate</Item>
+ <Item>Delegate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="ExchangeClassConstants">
+ <Members>
+ <Member Name="DIRECT">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeClassConstants.DIRECT</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DIRECT</Item>
+ <Item>direct</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="HEADERS">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeClassConstants.HEADERS</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HEADERS</Item>
+ <Item>headers</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TOPIC">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeClassConstants.TOPIC</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>TOPIC</Item>
+ <Item>topic</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ExchangeNameDefaults">
+ <Members>
+ <Member Name="DIRECT">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeNameDefaults.DIRECT</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>DIRECT</Item>
+ <Item>amq.direct</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="HEADERS">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeNameDefaults.HEADERS</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>HEADERS</Item>
+ <Item>amq.match</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="TOPIC">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>ExchangeNameDefaults.TOPIC</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>TOPIC</Item>
+ <Item>amq.topic</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IBytesMessage">
+ <Members>
+ <Member Name="ReadUTF():System.String">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>IBytesMessage.ReadUTF():String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WriteUTF(System.String):System.Void">
+ <Messages>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>IBytesMessage.WriteUTF(String):Void</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IChannel">
+ <Members>
+ <Member Name="CreateConsumer(System.String,System.Int32,System.Int32,System.Boolean,System.Boolean,System.Boolean,System.String):Qpid.Messaging.IMessageConsumer">
+ <Messages>
+ <Message Id="1#prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IChannel.CreateConsumer(String, Int32, Int32, Boolean, Boolean, Boolean, String):IMessageConsumer</Item>
+ <Item>prefetch</Item>
+ <Item>prefetchLow</Item>
+ </Issue>
+ </Message>
+ <Message Id="2#prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IChannel.CreateConsumer(String, Int32, Int32, Boolean, Boolean, Boolean, String):IMessageConsumer</Item>
+ <Item>prefetch</Item>
+ <Item>prefetchHigh</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DefaultPrefetch">
+ <Messages>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>IChannel.DefaultPrefetch:Int32</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IConnection">
+ <Members>
+ <Member Name="ClientID">
+ <Messages>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>IConnection.ClientID:String</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="CreateChannel(System.Boolean,Qpid.Messaging.AcknowledgeMode,System.Int32):Qpid.Messaging.IChannel">
+ <Messages>
+ <Message Id="2#prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>IConnection.CreateChannel(Boolean, AcknowledgeMode, Int32):IChannel</Item>
+ <Item>prefetch</Item>
+ <Item>prefetch</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IConnectionListener">
+ <Members>
+ <Member Name="PreResubscribe():System.Boolean">
+ <Messages>
+ <Message Id="Resubscribe" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Resubscribe</Item>
+ <Item>IConnectionListener.PreResubscribe():Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IFieldTable">
+ <Messages>
+ <Message TypeName="IdentifiersShouldHaveCorrectSuffix" Category="Microsoft.Naming" CheckId="CA1710" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.IFieldTable</Item>
+ <Item>Collection</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name="Contains(System.String):System.Boolean">
+ <Messages>
+ <Message Id="0#s" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>IFieldTable.Contains(String):Boolean</Item>
+ <Item>s</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IMessage">
+ <Members>
+ <Member Name="CorrelationIdAsBytes">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotReturnArrays" Category="Microsoft.Performance" CheckId="CA1819" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>IMessage.CorrelationIdAsBytes:Byte[]</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="IMessagePublisher">
+ <Members>
+ <Member Name="DisableMessageID">
+ <Messages>
+ <Message Id="Member" TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706" Created="2006-12-04 13:11:47Z">
+ <Issue Name="MemberId">
+ <Item>IMessagePublisher.DisableMessageID:Boolean</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="Encoding">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Encoding</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="MimeType">
+ <Messages>
+ <Message TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MimeType</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="MessageConsumerBuilder">
+ <Members>
+ <Member Name=".ctor(Qpid.Messaging.IChannel,System.String)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessageConsumerBuilder.MessageConsumerBuilder(IChannel, String)</Item>
+ <Item>_durable</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ <Issue>
+ <Item>MessageConsumerBuilder.MessageConsumerBuilder(IChannel, String)</Item>
+ <Item>_exclusive</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ <Issue>
+ <Item>MessageConsumerBuilder.MessageConsumerBuilder(IChannel, String)</Item>
+ <Item>_noLocal</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ <Issue>
+ <Item>MessageConsumerBuilder.MessageConsumerBuilder(IChannel, String)</Item>
+ <Item>_subscriptionName</Item>
+ <Item>System.String</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="DEFAULT_PREFETCH_HIGH">
+ <Messages>
+ <Message Id="Member" TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>DEFAULT_PREFETCH_HIGH</Item>
+ </Issue>
+ </Message>
+ <Message Id="Member" TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>MessageConsumerBuilder.DEFAULT_PREFETCH_HIGH</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WithPrefetchHigh(System.Int32):Qpid.Messaging.MessageConsumerBuilder">
+ <Messages>
+ <Message Id="0#prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageConsumerBuilder.WithPrefetchHigh(Int32):MessageConsumerBuilder</Item>
+ <Item>prefetch</Item>
+ <Item>prefetchHigh</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>MessageConsumerBuilder.WithPrefetchHigh(Int32):MessageConsumerBuilder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ <Member Name="WithPrefetchLow(System.Int32):Qpid.Messaging.MessageConsumerBuilder">
+ <Messages>
+ <Message Id="0#prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Parameter">
+ <Item>MessageConsumerBuilder.WithPrefetchLow(Int32):MessageConsumerBuilder</Item>
+ <Item>prefetch</Item>
+ <Item>prefetchLow</Item>
+ </Issue>
+ </Message>
+ <Message Id="Prefetch" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Member">
+ <Item>Prefetch</Item>
+ <Item>MessageConsumerBuilder.WithPrefetchLow(Int32):MessageConsumerBuilder</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="MessageNotReadableException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotReadableException</Item>
+ <Item>protected MessageNotReadableException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotReadableException</Item>
+ <Item>public MessageNotReadableException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotReadableException</Item>
+ <Item>public MessageNotReadableException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="MessageNotWriteableException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotWriteableException</Item>
+ <Item>protected MessageNotWriteableException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotWriteableException</Item>
+ <Item>public MessageNotWriteableException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.MessageNotWriteableException</Item>
+ <Item>public MessageNotWriteableException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ <Message Id="Writeable" TypeName="UsePreferredTerms" Category="Microsoft.Naming" CheckId="CA1726" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Writeable</Item>
+ <Item>MessageNotWriteableException</Item>
+ <Item>Writable</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="MessagePublisherBuilder">
+ <Members>
+ <Member Name=".ctor(Qpid.Messaging.IChannel)">
+ <Messages>
+ <Message TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>MessagePublisherBuilder.MessagePublisherBuilder(IChannel)</Item>
+ <Item>_exchangeName</Item>
+ <Item>System.String</Item>
+ <Item>null</Item>
+ </Issue>
+ <Issue>
+ <Item>MessagePublisherBuilder.MessagePublisherBuilder(IChannel)</Item>
+ <Item>_immediate</Item>
+ <Item>System.Boolean</Item>
+ <Item>false</Item>
+ </Issue>
+ <Issue>
+ <Item>MessagePublisherBuilder.MessagePublisherBuilder(IChannel)</Item>
+ <Item>_priority</Item>
+ <Item>System.Int32</Item>
+ <Item>0</Item>
+ </Issue>
+ <Issue>
+ <Item>MessagePublisherBuilder.MessagePublisherBuilder(IChannel)</Item>
+ <Item>_routingKey</Item>
+ <Item>System.String</Item>
+ <Item>null</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="MessageReceivedDelegate">
+ <Messages>
+ <Message TypeName="IdentifiersShouldNotHaveIncorrectSuffix" Category="Microsoft.Naming" CheckId="CA1711" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.MessageReceivedDelegate</Item>
+ <Item>Delegate</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ <Type Name="QpidException">
+ <Messages>
+ <Message Id="Qpid" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="Type">
+ <Item>Qpid</Item>
+ <Item>Qpid.Messaging.QpidException</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.QpidException</Item>
+ <Item>protected QpidException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.QpidException</Item>
+ <Item>public QpidException()</Item>
+ </Issue>
+ </Message>
+ <Message TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237" Created="2006-12-04 13:11:47Z">
+ <Issue Level="Error">
+ <Item>QpidException</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ <Members>
+ <Member Name=".ctor(System.String,System.Exception)">
+ <Messages>
+ <Message Id="1#e" TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704" Created="2006-12-04 13:11:47Z">
+ <Issue Name="ParameterOneLetter">
+ <Item>QpidException.QpidException(String, Exception)</Item>
+ <Item>e</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Member>
+ </Members>
+ </Type>
+ <Type Name="ResourceAllocationException">
+ <Messages>
+ <Message TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032" Created="2006-12-04 13:11:47Z">
+ <Issue>
+ <Item>Qpid.Messaging.ResourceAllocationException</Item>
+ <Item>protected ResourceAllocationException(SerializationInfo, StreamingContext)</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.ResourceAllocationException</Item>
+ <Item>public ResourceAllocationException()</Item>
+ </Issue>
+ <Issue>
+ <Item>Qpid.Messaging.ResourceAllocationException</Item>
+ <Item>public ResourceAllocationException(String, Exception)</Item>
+ </Issue>
+ </Message>
+ </Messages>
+ </Type>
+ </Types>
+ </Namespace>
+ </Namespaces>
+ </Module>
+ </Modules>
+ </Target>
+ </Targets>
+ <Rules>
+ <Rule TypeName="AbstractTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1012">
+ <Resolution Name="Default">Change the accessibility of all public constructors in '{0}' to protected.</Resolution>
+ </Rule>
+ <Rule TypeName="AssembliesShouldDeclareMinimumSecurity" Category="Microsoft.Usage" CheckId="CA2209">
+ <Resolution Name="Default">No valid permission requests were found for assembly '{0}'. You should always specify the minimum security permissions using SecurityAction.RequestMinimum.</Resolution>
+ </Rule>
+ <Rule TypeName="AssembliesShouldHaveValidStrongNames" Category="Microsoft.Design" CheckId="CA2210">
+ <Resolution Name="NoStrongName">Sign '{0}' with a strong name key.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidEmptyInterfaces" Category="Microsoft.Design" CheckId="CA1040">
+ <Resolution Name="Default">Define a custom attribute to replace '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidLanguageSpecificTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1718">
+ <Resolution Name="Default">Use a generic name for parameter '{0}'. If this is not possible, replace the type identifier with a universal type name.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidNamespacesWithFewTypes" Category="Microsoft.Design" CheckId="CA1020">
+ <Resolution Name="Default">Consider merging the types defined in '{0}' with another namespace.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidTypeNamesInParameters" Category="Microsoft.Naming" CheckId="CA1720">
+ <Resolution Name="Default">Remove the type identifier from parameter name '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidUncalledPrivateCode" Category="Microsoft.Performance" CheckId="CA1811">
+ <Resolution Name="Default">'{0}' appears to have no upstream public or protected callers.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidUninstantiatedInternalClasses" Category="Microsoft.Performance" CheckId="CA1812">
+ <Resolution Name="Default">'{0}' is an internal class that is apparently never instantiated. If so, remove the code from the assembly. If this class is intended to contain only static methods, consider adding a private constructor to prevent the compiler from generating a default constructor.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidUnnecessaryStringCreation" Category="Microsoft.Performance" CheckId="CA1807">
+ <Resolution Name="UseStringCompareLocal">{0} calls {1} after converting '{2}', a local, to upper or lowercase. If possible, eliminate the string creation and call the overload of String.Compare that performs a case-insensitive comparison.</Resolution>
+ <Resolution Name="UseStringCompareParameter">{0} calls {1} after converting '{2}', a parameter, to upper or lowercase. If possible, eliminate the string creation and call the overload of String.Compare that performs a case-insensitive comparison.</Resolution>
+ </Rule>
+ <Rule TypeName="AvoidUnusedPrivateFields" Category="Microsoft.Performance" CheckId="CA1823">
+ <Resolution Name="Default">It appears that field '{0}' is never used or is only ever assigned to. Use this field or remove it.</Resolution>
+ </Rule>
+ <Rule TypeName="CollectionsShouldImplementGenericInterface" Category="Microsoft.Design" CheckId="CA1010">
+ <Resolution Name="Default">'{0}' appears to be a non-generic, strongly typed collection. Add an implementation to the instance of {1}&lt;T&gt; where T is {0}'s underlying element type.</Resolution>
+ </Rule>
+ <Rule TypeName="CompoundWordsShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1702">
+ <Resolution Name="ShouldBeCompoundWord">The discrete term '{0}' in {1} '{2}' should be expressed as a compound term, '{3}'.</Resolution>
+ <Resolution Name="ShouldBeDiscreteTerm">The compound word '{0}' in {1} '{2}' exists as a discrete term. If your usage is intended to be single word, case it as '{3}'.</Resolution>
+ </Rule>
+ <Rule TypeName="ConsiderPassingBaseTypesAsParameters" Category="Microsoft.Design" CheckId="CA1011">
+ <Resolution Name="Default">Consider changing the type of parameter '{0}' in {1} from {2} to its base type {3}. This method appears to only require base class members in its implementation. Suppress this violation if there is a compelling reason to require the more derived type in the method signature.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800">
+ <Resolution Name="Local">'{0}', a local, is cast to type '{1}' multiple times in method {2}. Cache the result of the 'as' operator or direct cast in order to eliminate the redundant {3} instruction.</Resolution>
+ <Resolution Name="Parameter">'{0}', a parameter, is cast to type '{1}' multiple times in method {2}. Cache the result of the 'as' operator or direct cast in order to eliminate the redundant {3} instruction.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotCatchGeneralExceptionTypes" Category="Microsoft.Design" CheckId="CA1031">
+ <Resolution Name="Default">Modify '{0}' to catch a more specific exception than '{1}' or rethrow the exception.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotConcatenateStringsInsideLoops" Category="Microsoft.Performance" CheckId="CA1818">
+ <Resolution Name="Default">Change {0} to use StringBuilder instead of String.Concat or +=</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotDeclareReadOnlyMutableReferenceTypes" Category="Microsoft.Security" CheckId="CA2104">
+ <Resolution Name="Default">Remove the readonly declaration from '{0}' or change the field to one that is an immutable reference type. If the reference type '{1}' is, in fact, immutable, exclude this message.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotDeclareVisibleInstanceFields" Category="Microsoft.Design" CheckId="CA1051">
+ <Resolution Name="Default">Make '{0}' private or internal (Friend in VB, public private in C++) and provide a public or protected property to access it.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotIgnoreMethodResults" Category="Microsoft.Usage" CheckId="CA1806">
+ <Resolution Name="ObjectCreation">{0} creates an instance of {1} which is either not assigned to a variable or is never used. Remove the object creation if it is unnecessary or use it within the method.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotInitializeUnnecessarily" Category="Microsoft.Performance" CheckId="CA1805">
+ <Resolution Name="Default">{0} initializes field {1} of type {2} to {3}. Remove this initialization as it will be done automatically by the runtime.</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotPassLiteralsAsLocalizedParameters" Category="Microsoft.Globalization" CheckId="CA1303">
+ <Resolution Name="Default">{0} passes a literal as parameter {1} of a call to {2}. Retrieve the following string argument from a resource table instead: '{3}'</Resolution>
+ </Rule>
+ <Rule TypeName="DoNotRaiseReservedExceptionTypes" Category="Microsoft.Usage" CheckId="CA2201">
+ <Resolution Name="TooGeneric">{0} creates an exception of type '{1}', an exception type that is not sufficiently specific and should never be raised by user code. If this exception instance might be thrown, use a different exception type.</Resolution>
+ </Rule>
+ <Rule TypeName="ExceptionsShouldBePublic" Category="Microsoft.Design" CheckId="CA1064">
+ <Resolution Name="Default">Make exception class {0} public.</Resolution>
+ </Rule>
+ <Rule TypeName="ICollectionImplementationsHaveStronglyTypedMembers" Category="Microsoft.Design" CheckId="CA1035">
+ <Resolution Name="Default">'{0}' should provide a strongly typed implementation of ICollection.CopyTo.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldBeCasedCorrectly" Category="Microsoft.Naming" CheckId="CA1709">
+ <Resolution Name="Member">Correct the casing of member name '{0}'.</Resolution>
+ <Resolution Name="Namespace">Correct the casing of namespace name '{0}'.</Resolution>
+ <Resolution Name="Parameter">Correct the casing of parameter name '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldBeSpelledCorrectly" Category="Microsoft.Naming" CheckId="CA1704">
+ <Resolution Name="Member">Correct the spelling of the unrecognized token '{0}' in member name '{1}'.</Resolution>
+ <Resolution Name="Namespace">Correct the spelling of the unrecognized token '{0}' in namespace '{1}'.</Resolution>
+ <Resolution Name="Parameter">In method {0}, correct the spelling of the unrecognized token '{1}' in parameter name '{2}' or strip it entirely if it represents any sort of hungarian notation.</Resolution>
+ <Resolution Name="ParameterOneLetter">In method {0}, consider providing a more meaningful name than the one-letter parameter name '{1}'.</Resolution>
+ <Resolution Name="Type">Correct the spelling of the unrecognized token '{0}' in type name '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldDifferByMoreThanCase" Category="Microsoft.Naming" CheckId="CA1708">
+ <Resolution Name="Member">Change member names {0} and '{1}' so that they differ by more than case.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldHaveCorrectPrefix" Category="Microsoft.Naming" CheckId="CA1715">
+ <Resolution Name="Default">Prefix interface name '{0}' with 'I'.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldHaveCorrectSuffix" Category="Microsoft.Naming" CheckId="CA1710">
+ <Resolution Name="Default">Rename '{0}' to end in '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldNotContainUnderscores" Category="Microsoft.Naming" CheckId="CA1707">
+ <Resolution Name="Member">Remove all underscores from member '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="IdentifiersShouldNotHaveIncorrectSuffix" Category="Microsoft.Naming" CheckId="CA1711">
+ <Resolution Name="Default">Rename '{0}' so that it does not end in '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="ImplementIDisposableCorrectly" Category="Microsoft.Design" CheckId="CA1063">
+ <Resolution Name="DisposeImplementation">Modify {0} so that it calls Dispose(true), then calls GC.SuppressFinalize on the current object instance ('this' or 'Me' in VB), and then returns.</Resolution>
+ <Resolution Name="ProvideDisposeBool">Provide an overridable implementation of Dispose(bool) on {0} or mark the type as sealed. A call to Dispose(false) should only clean up native resources. A call to Dispose(true) should clean up both managed and native resources.</Resolution>
+ </Rule>
+ <Rule TypeName="ImplementStandardExceptionConstructors" Category="Microsoft.Design" CheckId="CA1032">
+ <Resolution Name="Default">Add the following constructor to {0}: {1}.</Resolution>
+ </Rule>
+ <Rule TypeName="InitializeReferenceTypeStaticFieldsInline" Category="Microsoft.Performance" CheckId="CA1810">
+ <Resolution Name="Default">Initialize all static fields in {0} when those fields are declared and remove the explicit static constructor.</Resolution>
+ </Rule>
+ <Rule TypeName="InstantiateArgumentExceptionsCorrectly" Category="Microsoft.Usage" CheckId="CA2208">
+ <Resolution Name="OneArgumentShouldBeParameterName">Calls to {0}'s constructor '{1}' should contain one of the method's parameter names instead of '{2}'. Note that the provided parameter name should have the exact casing as declared on the method.</Resolution>
+ </Rule>
+ <Rule TypeName="LiteralsShouldBeSpelledCorrectly" Category="Microsoft.Usage" CheckId="CA2204">
+ <Resolution Name="Default">Correct the spelling of the unrecognized token '{0}' in the literal '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="LongAcronymsShouldBePascalCased" Category="Microsoft.Naming" CheckId="CA1705">
+ <Resolution Name="Member">Correct the capitalization of member name '{0}'.</Resolution>
+ <Resolution Name="Parameter">Correct the capitalization of parameter name '{0}'.</Resolution>
+ <Resolution Name="Type">Correct the capitalization of type name '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="MarkAssembliesWithClsCompliant" Category="Microsoft.Design" CheckId="CA1014">
+ <Resolution Name="NoAttr">'{0}' should be marked with CLSCompliantAttribute and its value should be true.</Resolution>
+ </Rule>
+ <Rule TypeName="MarkISerializableTypesWithSerializable" Category="Microsoft.Usage" CheckId="CA2237">
+ <Resolution Name="Default">Add [Serializable] to '{0}' as this type implements ISerializable.</Resolution>
+ </Rule>
+ <Rule TypeName="MarkMembersAsStatic" Category="Microsoft.Performance" CheckId="CA1822">
+ <Resolution Name="Default">The 'this' parameter (or 'Me' in VB) of {0} is never used. Mark the member as static (or Shared in VB) or use 'this'/'Me' in the method body or at least one property accessor, if appropriate.</Resolution>
+ </Rule>
+ <Rule TypeName="NestedTypesShouldNotBeVisible" Category="Microsoft.Design" CheckId="CA1034">
+ <Resolution Name="Default">Do not nest type '{0}'. Alternatively, change its accessibility so that it is not externally visible.</Resolution>
+ </Rule>
+ <Rule TypeName="NonConstantFieldsShouldNotBeVisible" Category="Microsoft.Usage" CheckId="CA2211">
+ <Resolution Name="Default">Consider making '{0}' non-public or a constant.</Resolution>
+ </Rule>
+ <Rule TypeName="OperationsShouldNotOverflow" Category="Microsoft.Usage" CheckId="CA2233">
+ <Resolution Name="Default">Correct the potential overflow in the operation '{0}' in '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="ParameterNamesShouldMatchBaseDeclaration" Category="Microsoft.Naming" CheckId="CA1725">
+ <Resolution Name="Default">Change parameter name '{0}' of method {1} to '{2}' in order to match the identifier as it has been declared in {3}.</Resolution>
+ </Rule>
+ <Rule TypeName="PropertiesShouldNotBeWriteOnly" Category="Microsoft.Design" CheckId="CA1044">
+ <Resolution Name="Default">Add a property getter to '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="PropertiesShouldNotReturnArrays" Category="Microsoft.Performance" CheckId="CA1819">
+ <Resolution Name="Default">Change {0} to return a collection or make it a method.</Resolution>
+ </Rule>
+ <Rule TypeName="ProvideCorrectArgumentsToFormattingMethods" Category="Microsoft.Usage" CheckId="CA2241">
+ <Resolution Name="MissingSpecifier">A call to {0} in {1} does not appear to provide a format specifier for argument {2}. The complete format string provided is '{3}'.</Resolution>
+ </Rule>
+ <Rule TypeName="RemoveUnusedLocals" Category="Microsoft.Performance" CheckId="CA1804">
+ <Resolution Name="Default">{0} declares a local, '{1}', of type {2}, which is never used or is only assigned to. Use this local or remove it.</Resolution>
+ </Rule>
+ <Rule TypeName="RethrowToPreserveStackDetails" Category="Microsoft.Usage" CheckId="CA2200">
+ <Resolution Name="Default">{0} rethrows a caught exception and specifies it explicitly as an argument. Use 'throw' without an argument instead, in order to preserve the stack location where the exception was initially raised.</Resolution>
+ </Rule>
+ <Rule TypeName="ReviewUnusedParameters" Category="Microsoft.Usage" CheckId="CA1801">
+ <Resolution Name="Default">Parameter '{0}' of {1} is never used. Remove the parameter or use it in the method body.</Resolution>
+ </Rule>
+ <Rule TypeName="ShortAcronymsShouldBeUppercase" Category="Microsoft.Naming" CheckId="CA1706">
+ <Resolution Name="MemberId">'Id' is an abbreviation and therefore is not subject to acronym casing guidelines. Correct the capitalization of 'ID' in member name '{0}' by changing it to 'Id'.</Resolution>
+ <Resolution Name="MemberOk">To insure consistency with legacy api, 'OK' is not subject to acronym casing guidelines. Correct the capitalization of 'OK' in member name '{0}' by changing it to 'Ok'.</Resolution>
+ <Resolution Name="Parameter">Correct the capitalization of '{0}' in parameter name '{1}'.</Resolution>
+ <Resolution Name="Type">Correct the capitalization of '{0}' in type name '{1}'.</Resolution>
+ </Rule>
+ <Rule TypeName="SpecifyCultureInfo" Category="Microsoft.Globalization" CheckId="CA1304">
+ <Resolution Name="Default">{0} makes a call to {1} that does not explicitly provide a CultureInfo. This should be replaced with a call to {2}.</Resolution>
+ </Rule>
+ <Rule TypeName="SpecifyIFormatProvider" Category="Microsoft.Globalization" CheckId="CA1305">
+ <Resolution Name="Default">{0} makes a call to {1} that does not explicitly provide an IFormatProvider. This should be replaced with a call to {2}.</Resolution>
+ </Rule>
+ <Rule TypeName="StaticHolderTypesShouldNotHaveConstructors" Category="Microsoft.Design" CheckId="CA1053">
+ <Resolution Name="Default">Remove the public constructors from '{0}'.</Resolution>
+ </Rule>
+ <Rule TypeName="TestForEmptyStringsUsingStringLength" Category="Microsoft.Performance" CheckId="CA1820">
+ <Resolution Name="IsNullOrEmpty">Replace the call to String.{0}({1}) in '{2}' with a call to String.IsNullOrEmpty.</Resolution>
+ </Rule>
+ <Rule TypeName="TypesThatOwnDisposableFieldsShouldBeDisposable" Category="Microsoft.Design" CheckId="CA1001">
+ <Resolution Name="Default">Implement IDisposable on '{0}' as it instantiates members of the following IDisposable types: {1}</Resolution>
+ </Rule>
+ <Rule TypeName="UriParametersShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1054">
+ <Resolution Name="Default">Change the type of parameter '{0}' of method {1} from string to System.Uri, or provide an overload of {1}, that allows '{0}' to be passed as a System.Uri object.</Resolution>
+ </Rule>
+ <Rule TypeName="UriReturnValuesShouldNotBeStrings" Category="Microsoft.Design" CheckId="CA1055">
+ <Resolution Name="Default">Change the return type of {0} from string to System.Uri.</Resolution>
+ </Rule>
+ <Rule TypeName="UseEventsWhereAppropriate" Category="Microsoft.Design" CheckId="CA1030">
+ <Resolution Name="Default">Consider making '{0}' an event.</Resolution>
+ </Rule>
+ <Rule TypeName="UseLiteralsWhereAppropriate" Category="Microsoft.Performance" CheckId="CA1802">
+ <Resolution Name="Default">Field '{0}' is declared as 'static readonly' but is initialized with a constant value '{1}'. Mark this field as 'const' instead.</Resolution>
+ </Rule>
+ <Rule TypeName="UsePreferredTerms" Category="Microsoft.Naming" CheckId="CA1726">
+ <Resolution Name="Type">Replace the term '{0}' in type name '{1}' with the preferred alternate '{2}'.</Resolution>
+ </Rule>
+ <Rule TypeName="UsePropertiesWhereAppropriate" Category="Microsoft.Design" CheckId="CA1024">
+ <Resolution Name="Default">Change '{0}' to a property if appropriate.</Resolution>
+ </Rule>
+ <Rule TypeName="ValidateArgumentsOfPublicMethods" Category="Microsoft.Design" CheckId="CA1062">
+ <Resolution Name="Default">Validate parameter {0} passed to externally visible method {1}.</Resolution>
+ </Rule>
+ </Rules>
+ </FxCopReport>
+</FxCopProject>
diff --git a/dotnet/Qpid.NET.sln b/dotnet/Qpid.NET.sln
new file mode 100644
index 0000000000..a6417aaad1
--- /dev/null
+++ b/dotnet/Qpid.NET.sln
@@ -0,0 +1,116 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+
+#
+# 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.
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Messaging", "Qpid.Messaging\Qpid.Messaging.csproj", "{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Common.Tests", "Qpid.Common.Tests\Qpid.Common.Tests.csproj", "{F83624B0-762B-4D82-900D-FF4C1B36E36E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Buffer", "Qpid.Buffer\Qpid.Buffer.csproj", "{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Codec", "Qpid.Codec\Qpid.Codec.csproj", "{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Client", "Qpid.Client\Qpid.Client.csproj", "{68987C05-3768-452C-A6FC-6BA1D372852F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Common", "Qpid.Common\Qpid.Common.csproj", "{77064C42-24D2-4CEB-9EA2-0EF481A43205}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Client.Tests", "Qpid.Client.Tests\Qpid.Client.Tests.csproj", "{BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Sasl", "Qpid.Sasl\Qpid.Sasl.csproj", "{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Sasl.Tests", "Qpid.Sasl.Tests\Qpid.Sasl.Tests.csproj", "{587B3520-EBB9-41ED-B019-E96116B651CE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Buffer.Tests", "Qpid.Buffer.Tests\Qpid.Buffer.Tests.csproj", "{74640962-99D0-4D06-B57A-9CD66517CF52}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopicPublisher", "TopicPublisher\TopicPublisher.csproj", "{A06C9FFD-22FF-4654-856D-897C230978AF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopicListener", "TopicListener\TopicListener.csproj", "{9A112DF2-146F-4CF4-919B-9D3BE7D088E9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{6E0374D9-99BE-4D4F-B41D-B227E37E04C6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Integration.Tests", "Qpid.Integration.Tests\Qpid.Integration.Tests.csproj", "{DE21CEBC-F38C-43EA-B576-38CA9738A00A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F83624B0-762B-4D82-900D-FF4C1B36E36E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F83624B0-762B-4D82-900D-FF4C1B36E36E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F83624B0-762B-4D82-900D-FF4C1B36E36E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F83624B0-762B-4D82-900D-FF4C1B36E36E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {44384DF2-B0A4-4580-BDBC-EE4BAA87D995}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {44384DF2-B0A4-4580-BDBC-EE4BAA87D995}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {44384DF2-B0A4-4580-BDBC-EE4BAA87D995}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {44384DF2-B0A4-4580-BDBC-EE4BAA87D995}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}.Release|Any CPU.Build.0 = Release|Any CPU
+ {68987C05-3768-452C-A6FC-6BA1D372852F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {68987C05-3768-452C-A6FC-6BA1D372852F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {68987C05-3768-452C-A6FC-6BA1D372852F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {68987C05-3768-452C-A6FC-6BA1D372852F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77064C42-24D2-4CEB-9EA2-0EF481A43205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77064C42-24D2-4CEB-9EA2-0EF481A43205}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77064C42-24D2-4CEB-9EA2-0EF481A43205}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77064C42-24D2-4CEB-9EA2-0EF481A43205}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1465B0EE-6452-42A6-AB73-B2F9EABEEE75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1465B0EE-6452-42A6-AB73-B2F9EABEEE75}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1465B0EE-6452-42A6-AB73-B2F9EABEEE75}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1465B0EE-6452-42A6-AB73-B2F9EABEEE75}.Release|Any CPU.Build.0 = Release|Any CPU
+ {587B3520-EBB9-41ED-B019-E96116B651CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {587B3520-EBB9-41ED-B019-E96116B651CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {587B3520-EBB9-41ED-B019-E96116B651CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {587B3520-EBB9-41ED-B019-E96116B651CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {74640962-99D0-4D06-B57A-9CD66517CF52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {74640962-99D0-4D06-B57A-9CD66517CF52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {74640962-99D0-4D06-B57A-9CD66517CF52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {74640962-99D0-4D06-B57A-9CD66517CF52}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A06C9FFD-22FF-4654-856D-897C230978AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A06C9FFD-22FF-4654-856D-897C230978AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A06C9FFD-22FF-4654-856D-897C230978AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A06C9FFD-22FF-4654-856D-897C230978AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6E0374D9-99BE-4D4F-B41D-B227E37E04C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6E0374D9-99BE-4D4F-B41D-B227E37E04C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/Qpid.Sasl.Tests/App.config b/dotnet/Qpid.Sasl.Tests/App.config
new file mode 100644
index 0000000000..021399939e
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/App.config
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <configSections>
+ <section name="qpid.sasl" type="Apache.Qpid.Sasl.Configuration.SaslConfigurationSectionHandler, Apache.Qpid.Sasl"/>
+ </configSections>
+
+ <qpid.sasl>
+ <clientFactories>
+ <add type="Apache.Qpid.Sasl.Tests.TestClientFactory, Apache.Qpid.Sasl.Tests"/>
+ </clientFactories>
+ </qpid.sasl>
+</configuration>
diff --git a/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs b/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs
new file mode 100644
index 0000000000..5839f310e1
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class AnonymousSaslClientTests : ISaslCallbackHandler
+ {
+ private const string AUTHID = "nobody@nowhere.com";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new AnonymousSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("ANONYMOUS", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new AnonymousSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+ ISaslClient client = new AnonymousSaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ Assert.AreEqual(AUTHID, Encoding.UTF8.GetString(response));
+
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class AnonymousSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs b/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs
new file mode 100644
index 0000000000..baeeafb2d2
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class CramMD5SaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "testuser";
+ private const string PASSWORD = "tanstaaftanstaaf";
+ private const string AUTHID = "test";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new CramMD5SaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("CRAM-MD5", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsFalse()
+ {
+ ISaslClient client = new CramMD5SaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsFalse(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+
+ ISaslClient client = new CramMD5SaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+
+ byte[] challenge =
+ Encoding.UTF8.GetBytes("<1896.697170952@postoffice.reston.mci.net>");
+ byte[] response = client.EvaluateChallenge(challenge);
+ string[] parts = Encoding.UTF8.GetString(response).Split(' ');
+
+ Assert.AreEqual(2, parts.Length);
+ Assert.AreEqual(USERNAME, parts[0]);
+ Assert.AreEqual("b913a602c7eda7a495b4e6e7334d3890", parts[1]);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ }
+ }
+ }
+ } // class CramMD5SaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs b/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs
new file mode 100644
index 0000000000..5a18ebaefd
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs
@@ -0,0 +1,249 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class DigestSaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "chris";
+ private const string PASSWORD = "secret";
+ private const string AUTHID = null;
+ private const string PROTOCOL = "IMAP";
+ private const string SERVERNAME = "elwood.innosoft.com";
+
+ #region Digest Challenge Parsing Tests
+ //
+ // Digest Challenge Parsing Tests
+ //
+
+ [Test]
+ public void CanParseSimpleString()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood.innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParseEscapedQuotes()
+ {
+ string challenge = "realm=\"elwood\\\".innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood\\\".innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParseEmbeddedDelimiter()
+ {
+ string challenge = "realm=\"elwood,innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood,innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParse1()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestChallenge parsed = DigestChallenge.Parse(challenge);
+
+ Assert.AreEqual("elwood.innosoft.com", parsed.Realm);
+ Assert.AreEqual("OA6MG9tEQGm2hh", parsed.Nonce);
+ Assert.Contains("auth", parsed.QopOptions);
+ Assert.AreEqual("md5-sess", parsed.Algorithm);
+ Assert.AreEqual("utf-8", parsed.Charset);
+ }
+
+ #endregion // Digest Challenge Parsing Tests
+
+
+ #region Digest Response Tests
+ //
+ // Digest Response Tests
+ //
+
+ [Test]
+ public void CanWriteResponse()
+ {
+ DigestResponse resp = new DigestResponse();
+ resp.Username = "user";
+ resp.Realm = "nowhere.com";
+ resp.Nonce = "OA9BSXrbuRhWay";
+ resp.Cnonce = "OA9BSuZWMSpW8m";
+ resp.NonceCount = 16;
+ resp.DigestUri = "acap/elwood.innosoft.com";
+ resp.Response = "6084c6db3fede7352c551284490fd0fc";
+ resp.Qop = "auth";
+ resp.MaxBuffer = 65536;
+ resp.Cipher = "3des";
+ resp.Authzid = "user2";
+ resp.AuthParam = "ap";
+ resp.Charset = "utf-8";
+
+ string expected = "username=\"user\",realm=\"nowhere.com\",nonce=\"OA9BSXrbuRhWay\",cnonce=\"OA9BSuZWMSpW8m\",nc=00000010,qop=auth,digest-uri=\"acap/elwood.innosoft.com\",response=\"6084c6db3fede7352c551284490fd0fc\",maxbuf=65536,charset=utf-8,cipher=3des,authzid=\"user2\",auth-param=\"ap\"";
+ Assert.AreEqual(expected, resp.ToString());
+ }
+
+ [Test]
+ public void CanWriteEscapedSecuence()
+ {
+ DigestResponse resp = new DigestResponse();
+ resp.Username = "us\"er";
+
+ string expected = "username=\"us\\\"er\",nc=00000000,maxbuf=0";
+ Assert.AreEqual(expected, resp.ToString());
+ }
+
+ #endregion // Digest Response Tests
+
+
+ #region Authentication Tests
+ //
+ // Authentication Tests
+ //
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = CreateClient();
+
+ Assert.AreEqual("DIGEST-MD5", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsFalse()
+ {
+ ISaslClient client = CreateClient();
+
+ Assert.IsFalse(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanAuthenticate()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestSaslClient client = CreateClient();
+ client.Cnonce = "OA6MHXh6VqTrRk";
+
+ byte[] bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ string response = Encoding.UTF8.GetString(bresp);
+ string expectedResp = "username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",cnonce=\"" +
+ client.Cnonce + "\",nc=00000001,qop=auth,digest-uri=\"imap/elwood.innosoft.com\",response=\"d388dad90d4bbd760a152321f2143af7\",maxbuf=65536,charset=utf-8";
+
+ Assert.AreEqual(expectedResp, response);
+ Assert.IsFalse(client.IsComplete);
+
+ string challenge2 = "rspauth=ea40f60335c427b5527b84dbabcdfffd";
+ bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge2));
+ // client responds with zero-length array
+ Assert.AreEqual(0, bresp.Length);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ThrowsExceptionWhenChallengeIsMissing()
+ {
+ DigestSaslClient client = CreateClient();
+ client.EvaluateChallenge(null);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenNonceMissing()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\"";
+ DigestSaslClient client = CreateClient();
+
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenAlgorithmMissing()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"asdasadsad\"";
+ DigestSaslClient client = CreateClient();
+
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenSecondChallengeInvalid()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestSaslClient client = CreateClient();
+
+ byte[] bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ Encoding.UTF8.GetString(bresp);
+
+ // repeat challenge 1, which is incorrect
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ private DigestSaslClient CreateClient()
+ {
+ return new DigestSaslClient(
+ AUTHID, SERVERNAME, PROTOCOL,
+ new Hashtable(), this
+ );
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ } else if ( cb is RealmCallback )
+ {
+ ((RealmCallback)cb).Text = SERVERNAME;
+ }
+ }
+ }
+
+ #endregion // Authentication Tests
+
+
+ } // class DigestSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs b/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs
new file mode 100644
index 0000000000..57efcf7614
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class ExternalSaslClientTests : ISaslCallbackHandler
+ {
+ private const string AUTHID = "nobody@nowhere.com";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("EXTERNAL", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ Assert.AreEqual(AUTHID, Encoding.UTF8.GetString(response));
+
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class AnonymousSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs b/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs
new file mode 100644
index 0000000000..f4fc00e038
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class PlainSaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "testuser";
+ private const string PASSWORD = "thepasswd";
+ private const string AUTHID = "theauth";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new PlainSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("PLAIN", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new PlainSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+ ISaslClient client = new PlainSaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ string[] parts = Encoding.UTF8.GetString(response).Split('\0');
+
+ Assert.AreEqual(3, parts.Length);
+ Assert.AreEqual(AUTHID, parts[0]);
+ Assert.AreEqual(USERNAME, parts[1]);
+ Assert.AreEqual(PASSWORD, parts[2]);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ }
+ }
+ }
+
+ } // class PlainSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs b/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e795c267a7
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Sasl.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Sasl.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("84cc3267-8019-4fad-a426-0a40155b3352")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj b/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj
new file mode 100644
index 0000000000..f1a7b07e5a
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj
@@ -0,0 +1,86 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{587B3520-EBB9-41ED-B019-E96116B651CE}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Sasl.Tests</RootNamespace>
+ <AssemblyName>Apache.Qpid.Sasl.Tests</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Client.Tests\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Sasl.Tests/SaslTests.cs b/dotnet/Qpid.Sasl.Tests/SaslTests.cs
new file mode 100644
index 0000000000..e7ae91d6b6
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/SaslTests.cs
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests
+{
+ [TestFixture]
+ public class SaslTests : ISaslCallbackHandler
+ {
+
+ [Test]
+ public void CanCreatePlain()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "PLAIN", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(PlainSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateCramMD5()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "CRAM-MD5", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(CramMD5SaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateAnonymous()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "ANONYMOUS", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(AnonymousSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateDigest()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "DIGEST-MD5", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(DigestSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateExternal()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "EXTERNAL", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(ExternalSaslClient), client);
+ }
+
+ [Test]
+ public void ReturnsNullIfNoFactoryFound()
+ {
+ Hashtable props = new Hashtable();
+ props.Add(SaslProperties.PolicyNoPlainText, true);
+ string[] mechanisms = new string[] { "PLAIN", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNull(client);
+ }
+
+ [Test]
+ public void ParsesConfigurationSection()
+ {
+ // if the TEST mechanism is available, then we know
+ // the configuration section worked!
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "TEST" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(TestSaslClient), client);
+ }
+
+ [Test]
+ public void ChoosesStrongerMechanism()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "PLAIN", "OTHER", "CRAM-MD5" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(CramMD5SaslClient), client);
+ }
+
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class SaslTests
+
+} // namespace Apache.Qpid.Sasl.Tests
diff --git a/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs b/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs
new file mode 100644
index 0000000000..62099237e9
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs
@@ -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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests
+{
+ public class TestClientFactory : ISaslClientFactory
+ {
+ public string[] GetSupportedMechanisms(IDictionary props)
+ {
+ return new string[] { TestSaslClient.Mechanism };
+ }
+
+ public ISaslClient CreateClient(string[] mechanisms, string authorizationId, string protocol, string serverName, IDictionary props, ISaslCallbackHandler handler)
+ {
+ foreach ( string mech in mechanisms )
+ {
+ if ( mech == TestSaslClient.Mechanism )
+ return new TestSaslClient(props, handler);
+ }
+ return null;
+ }
+
+ } // class TestClientFactory
+
+ internal class TestSaslClient : SaslClient
+ {
+ public const string Mechanism = "TEST";
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+ public override bool HasInitialResponse
+ {
+ get { return false; }
+ }
+
+ public TestSaslClient(IDictionary props, ISaslCallbackHandler handler)
+ : base("", "", "", props, handler)
+ {
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ throw new NotImplementedException();
+ }
+ } // class TestSaslClient
+
+} // namespace Apache.Qpid.Sasl.Tests
diff --git a/dotnet/Qpid.Sasl.Tests/default.build b/dotnet/Qpid.Sasl.Tests/default.build
new file mode 100644
index 0000000000..5b51c0a6fa
--- /dev/null
+++ b/dotnet/Qpid.Sasl.Tests/default.build
@@ -0,0 +1,52 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Sasl" default="test">
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="true" debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.Tests.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/${project::get-name()}.dll" />
+ </references>
+
+ </csc>
+ <copy
+ tofile="${build.dir}/${project::get-name()}.Tests.dll.config"
+ file="App.config"
+ />
+ </target>
+ <target name="test" depends="build">
+ <nunit2>
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test assemblyname="${build.dir}/${project::get-name()}.Tests.dll" />
+ </nunit2>
+ </target>
+</project>
+
diff --git a/dotnet/Qpid.Sasl/Callbacks.cs b/dotnet/Qpid.Sasl/Callbacks.cs
new file mode 100644
index 0000000000..f4fcc1c54b
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Callbacks.cs
@@ -0,0 +1,139 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Text;
+using System.Globalization;
+using System.Security.Cryptography;
+
+namespace Apache.Qpid.Sasl
+{
+ /// <summary>
+ /// Marker interface for Sasl Callbacks
+ /// </summary>
+ public interface ISaslCallback
+ {
+ } // interface ISaslCallback
+
+ public abstract class TextSaslCallback : ISaslCallback
+ {
+ private string _prompt;
+ private string _text;
+ private string _defaultText;
+
+ public string Prompt
+ {
+ get { return _prompt; }
+ set { _prompt = value; }
+ }
+
+ public string Text
+ {
+ get {
+ if ( _text == null || _text.Length == 0 )
+ return DefaultText;
+ else
+ return _text;
+ }
+ set { _text = value; }
+ }
+
+ public string DefaultText
+ {
+ get { return _defaultText; }
+ set { _defaultText = value; }
+ }
+
+ protected TextSaslCallback(string prompt, string text, string defaultText)
+ {
+ _prompt = prompt;
+ _text = text;
+ _defaultText = defaultText;
+ }
+
+ } // class TextSaslCallback
+
+ public class NameCallback : TextSaslCallback
+ {
+ public NameCallback()
+ : this(Environment.UserName)
+ {
+ }
+ public NameCallback(string defaultText)
+ : base("username:", "", defaultText)
+ {
+ }
+ } // class NameCallback
+
+ public class PasswordCallback : TextSaslCallback
+ {
+ public PasswordCallback()
+ : base("password:", "", "")
+ {
+ }
+
+ public byte[] HashedText
+ {
+ get
+ {
+ string _text = this.Text;
+ System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
+ byte[] bs = x.ComputeHash(Encoding.UTF8.GetBytes(_text));
+ return bs;
+ }
+
+ }
+ } // class PasswordCallback
+
+ public class HashedPasswordCallback : TextSaslCallback
+ {
+ public HashedPasswordCallback()
+ : base("password:", "", "")
+ {
+ }
+
+ public byte[] HashedText
+ {
+ get {
+ string _text = this.Text;
+ System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
+ _text = _text.PadRight(16, '\0');
+ byte[] bs = x.ComputeHash(Encoding.UTF8.GetBytes(_text));
+ return bs;
+ }
+ }
+ } // class PasswordCallback
+
+ public class RealmCallback : TextSaslCallback
+ {
+ public RealmCallback()
+ : this("localhost")
+ {
+ }
+ public RealmCallback(string defaultText)
+ : base("realm:", "", defaultText)
+ {
+ }
+ } // class RealmCallback
+
+} // namespace Apache.Qpid.Sasl
+
+
diff --git a/dotnet/Qpid.Sasl/Configuration/SaslConfiguration.cs b/dotnet/Qpid.Sasl/Configuration/SaslConfiguration.cs
new file mode 100644
index 0000000000..7a71ec28da
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Configuration/SaslConfiguration.cs
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Configuration;
+using System.Text;
+using System.Xml;
+
+namespace Apache.Qpid.Sasl.Configuration
+{
+ /// <summary>
+ /// Represents an Sasl configuration section
+ /// in the config file
+ /// </summary>
+ internal class SaslConfiguration
+ {
+ private IList _clientFactories;
+
+ /// <summary>
+ /// Set of configured client factores
+ /// </summary>
+ public IList ClientFactories
+ {
+ get { return _clientFactories; }
+ }
+
+ internal SaslConfiguration(IList clientFactoryTypes)
+ {
+ _clientFactories = new ArrayList();
+ foreach ( Type type in clientFactoryTypes )
+ {
+ _clientFactories.Add(Activator.CreateInstance(type));
+ }
+ }
+
+ /// <summary>
+ /// Get the configuration for the library
+ /// </summary>
+ /// <returns>The configuration from app.config or a default configuration</returns>
+ internal static SaslConfiguration GetConfiguration()
+ {
+ // 'obsolete' warning, but needed for .NET 1.1 compatibility
+ SaslConfiguration config = (SaslConfiguration)
+ ConfigurationSettings.GetConfig("qpid.sasl");
+ if ( config == null )
+ {
+ // create default configuration
+ IList clientFactories = GetDefaultClientFactories();
+ config = new SaslConfiguration(clientFactories);
+ }
+ return config;
+ }
+
+ /// <summary>
+ /// Create a list filled with the default client
+ /// factories supported by the library
+ /// </summary>
+ /// <returns>The list of client factory types</returns>
+ internal static IList GetDefaultClientFactories()
+ {
+ IList clientFactories = new ArrayList();
+ clientFactories.Add(typeof(DefaultClientFactory));
+ return clientFactories;
+ }
+
+
+ } // class SaslConfiguration
+
+} // namespace Apache.Qpid.Sasl.Configuration
+
+
diff --git a/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs b/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs
new file mode 100644
index 0000000000..ea8669f8c4
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Configuration;
+using System.Text;
+using System.Xml;
+
+namespace Apache.Qpid.Sasl.Configuration
+{
+ /// <summary>
+ /// Defines the configuration section to configure extra
+ /// Sasl client factories
+ /// </summary>
+ public class SaslConfigurationSectionHandler
+ : IConfigurationSectionHandler
+ {
+ public object Create(object parent, object configContext, XmlNode section)
+ {
+ IList clientFactories = SaslConfiguration.GetDefaultClientFactories();
+
+ foreach ( XmlNode node in section.ChildNodes )
+ {
+ if ( node.LocalName == "clientFactories" )
+ {
+ ProcessFactories(node, clientFactories);
+ }
+ }
+
+ SaslConfiguration config = new SaslConfiguration(clientFactories);
+ return config;
+ }
+
+
+ private void ProcessFactories(XmlNode node, IList factories)
+ {
+ foreach ( XmlNode child in node.ChildNodes )
+ {
+ Type type;
+ switch ( child.LocalName )
+ {
+ case "add":
+ type = Type.GetType(child.Attributes["type"].Value);
+ if ( !factories.Contains(type) )
+ factories.Add(type);
+ break;
+ case "remove":
+ type = Type.GetType(child.Attributes["type"].Value);
+ if ( factories.Contains(type) )
+ factories.Remove(type);
+ break;
+ case "clear":
+ factories.Clear();
+ break;
+ default:
+ // gives obsolete warning but needed for .NET 1.1 support
+ throw new ConfigurationException(string.Format("Unknown element '{0}' in section '{0}'", child.LocalName, node.LocalName));
+ }
+ }
+ }
+ } // class SaslConfigurationSectionHandler
+
+} // namespace Apache.Qpid.Sasl.Configuration
+
+
diff --git a/dotnet/Qpid.Sasl/DefaultClientFactory.cs b/dotnet/Qpid.Sasl/DefaultClientFactory.cs
new file mode 100644
index 0000000000..744d7cae40
--- /dev/null
+++ b/dotnet/Qpid.Sasl/DefaultClientFactory.cs
@@ -0,0 +1,99 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl
+{
+ public class DefaultClientFactory : ISaslClientFactory
+ {
+ private static readonly string[] SUPPORTED = new string[] {
+ DigestSaslClient.Mechanism,
+ CramMD5SaslClient.Mechanism,
+ CramMD5HexSaslClient.Mechanism,
+ PlainSaslClient.Mechanism,
+ AnonymousSaslClient.Mechanism,
+ ExternalSaslClient.Mechanism,
+ };
+
+ public string[] GetSupportedMechanisms(IDictionary props)
+ {
+ if ( props == null )
+ throw new ArgumentNullException("props");
+
+ ArrayList vetoed = new ArrayList();
+
+ if ( props.Contains(SaslProperties.PolicyNoPlainText) ||
+ props.Contains(SaslProperties.PolicyNoDictionary) ||
+ props.Contains(SaslProperties.PolicyNoActive) ||
+ props.Contains(SaslProperties.PolicyForwardSecrecy) ||
+ props.Contains(SaslProperties.PolicyPassCredentials) )
+ {
+ vetoed.Add(CramMD5SaslClient.Mechanism);
+ vetoed.Add(CramMD5HexSaslClient.Mechanism);
+ vetoed.Add(PlainSaslClient.Mechanism);
+ vetoed.Add(AnonymousSaslClient.Mechanism);
+ vetoed.Add(ExternalSaslClient.Mechanism);
+ }
+ if ( props.Contains(SaslProperties.PolicyNoAnonymous) )
+ {
+ vetoed.Add(AnonymousSaslClient.Mechanism);
+ }
+
+ ArrayList available = new ArrayList();
+ foreach ( string mech in SUPPORTED )
+ {
+ if ( !vetoed.Contains(mech) )
+ available.Add(mech);
+ }
+ return (string[])available.ToArray(typeof(string));
+ }
+
+ public ISaslClient CreateClient(
+ string[] mechanisms, string authorizationId,
+ string protocol, string serverName,
+ IDictionary props, ISaslCallbackHandler handler
+ )
+ {
+ IList mechs = mechanisms;
+ if ( mechs.Contains(ExternalSaslClient.Mechanism) )
+ return new ExternalSaslClient(authorizationId, props, handler);
+ if ( mechs.Contains(DigestSaslClient.Mechanism) )
+ return new DigestSaslClient(authorizationId, serverName, protocol, props, handler);
+ if ( mechs.Contains(CramMD5SaslClient.Mechanism) )
+ return new CramMD5SaslClient(authorizationId, props, handler);
+ if ( mechs.Contains(CramMD5HexSaslClient.Mechanism) )
+ return new CramMD5HexSaslClient(authorizationId, props, handler);
+ if ( mechs.Contains(PlainSaslClient.Mechanism) )
+ return new PlainSaslClient(authorizationId, props, handler);
+ if ( mechs.Contains(AnonymousSaslClient.Mechanism) )
+ return new AnonymousSaslClient(authorizationId, props, handler);
+ // unknown mechanism
+ return null;
+ }
+ } // class DefaultClientFactory
+
+} // namespace Apache.Qpid.Sasl
+
+
diff --git a/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs b/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs
new file mode 100644
index 0000000000..c2638f245e
--- /dev/null
+++ b/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ public interface ISaslCallbackHandler
+ {
+ void Handle(ISaslCallback[] callbacks);
+
+ } // interface ISaslCallbackHandler
+
+} // namespace Apache.Qpid.Sasl
+
+
diff --git a/dotnet/Qpid.Sasl/ISaslClient.cs b/dotnet/Qpid.Sasl/ISaslClient.cs
new file mode 100644
index 0000000000..668ca05d26
--- /dev/null
+++ b/dotnet/Qpid.Sasl/ISaslClient.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ public interface ISaslClient
+ {
+ string MechanismName { get; }
+ bool HasInitialResponse { get; }
+ bool IsComplete { get; }
+
+ byte[] EvaluateChallenge(byte[] challenge);
+ object GetNegotiatedProperty(string propName);
+ byte[] Unwrap(byte[] buffer, int offset, int length);
+ byte[] Wrap(byte[] buffer, int offset, int lenght);
+
+ } // interface ISaslClient
+
+} // namespace Apache.Qpid.Sasl
+
+
diff --git a/dotnet/Qpid.Sasl/ISaslClientFactory.cs b/dotnet/Qpid.Sasl/ISaslClientFactory.cs
new file mode 100644
index 0000000000..f052e07ad9
--- /dev/null
+++ b/dotnet/Qpid.Sasl/ISaslClientFactory.cs
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ public interface ISaslClientFactory
+ {
+ string[] GetSupportedMechanisms(IDictionary props);
+ ISaslClient CreateClient(
+ string[] mechanisms, string authorizationId,
+ string protocol, string serverName,
+ IDictionary props, ISaslCallbackHandler handler
+ );
+ } // interface ISaslClientFactory
+
+} // namespace Apache.Qpid.Sasl
+
+
diff --git a/dotnet/Qpid.Sasl/MD5HMAC.cs b/dotnet/Qpid.Sasl/MD5HMAC.cs
new file mode 100644
index 0000000000..7e310c5364
--- /dev/null
+++ b/dotnet/Qpid.Sasl/MD5HMAC.cs
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Security.Cryptography;
+
+namespace Apache.Qpid.Sasl
+{
+ /// <summary>
+ /// Rough HMAC MD5 implementation as presented in
+ /// RFC 2104. Used because the HMACMD5 class in the
+ /// .NET framework is not available in v1.1.
+ /// </summary>
+ public sealed class MD5HMAC : IDisposable
+ {
+ private const int BLOCK_LEN = 64;
+ private MD5 _hash;
+ private byte[] _key;
+ private byte[] _ipad;
+ private byte[] _opad;
+
+ public MD5HMAC(byte[] key)
+ {
+ if ( key == null || key.Length == 0 )
+ throw new ArgumentNullException("key");
+
+ _hash = new MD5CryptoServiceProvider();
+
+ byte[] theKey = key;
+ if ( theKey.Length > BLOCK_LEN )
+ {
+ theKey = _hash.ComputeHash(theKey);
+ }
+ // pad key with 0's up to BLOCK_LEN
+ _key = new byte[BLOCK_LEN];
+ Array.Copy(theKey, _key, theKey.Length);
+
+ CreatePads();
+ }
+
+ public byte[] ComputeHash(byte[] input)
+ {
+ // H(K XOR opad, H(K XOR ipad, text))
+ return H(_opad, H(_ipad, input));
+ }
+
+ public void Dispose()
+ {
+ if ( _hash != null )
+ {
+ ((IDisposable)_hash).Dispose();
+ _hash = null;
+ }
+ }
+
+ #region Private Methods
+ //
+ // Private Methods
+ //
+
+ private void CreatePads()
+ {
+ _ipad = new byte[BLOCK_LEN];
+ _opad = new byte[BLOCK_LEN];
+ for ( int i = 0; i < BLOCK_LEN; i++ )
+ {
+ _ipad[i] = 0x36;
+ _opad[i] = 0x5c;
+ }
+
+ XOR(_ipad, _key);
+ XOR(_opad, _key);
+ }
+
+ private static void XOR(byte[] dest, byte[] other)
+ {
+ // assume both are same size
+ for ( int i = 0; i < dest.Length; i++ )
+ {
+ dest[i] ^= other[i];
+ }
+ }
+
+ private byte[] H(byte[] v1, byte[] v2)
+ {
+ byte[] total = new byte[v1.Length + v2.Length];
+ Array.Copy(v1, total, v1.Length);
+ Array.Copy(v2, 0, total, v1.Length, v2.Length);
+
+ return _hash.ComputeHash(total);
+ }
+
+ #endregion // Private Methods
+
+ } // class MD5HMAC
+
+} // namespace Apache.Qpid.Sasl
diff --git a/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs
new file mode 100644
index 0000000000..e550d10d97
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+ /// <summary>
+ /// Implements the ANONYMOUS authentication mechanism
+ /// as outlined in RFC 2245
+ /// </summary>
+ public class AnonymousSaslClient : SaslClient
+ {
+ public const string Mechanism = "ANONYMOUS";
+
+ public AnonymousSaslClient(
+ string authid, IDictionary properties,
+ ISaslCallbackHandler handler)
+ : base(authid, null, null, properties, handler)
+ {
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return true; }
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ // ignore challenge
+ SetComplete();
+ return Encoding.UTF8.GetBytes(AuthorizationId);
+ }
+
+ #endregion // ISaslClient Implementation
+
+ } // class AnonymousSaslClient
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs
new file mode 100644
index 0000000000..3cce0e3a2d
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+ /// <summary>
+ /// Implements the CRAM-MD5 authentication mechanism as outlined
+ /// in RFC 2195
+ /// </summary>
+ public class CramMD5HexSaslClient : SaslClient
+ {
+ public const string Mechanism = "CRAM-MD5-HEX";
+ private const int MinPwdLen = 16;
+
+ public CramMD5HexSaslClient(
+ string authorizationId,
+ IDictionary properties,
+ ISaslCallbackHandler handler)
+ : base(authorizationId, null, null, properties, handler)
+ {
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return false; }
+ }
+
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ if ( challenge == null || challenge.Length == 0 )
+ throw new ArgumentNullException("challenge");
+
+
+ NameCallback nameCB = new NameCallback(AuthorizationId);
+ PasswordCallback pwdCB = new PasswordCallback();
+ ISaslCallback[] callbacks = { nameCB, pwdCB };
+ Handler.Handle(callbacks);
+
+ string username = nameCB.Text;
+
+ //Encode the Hashed Password as Hex
+ byte[] passwd = Encoding.UTF8.GetBytes(ToHex(pwdCB.HashedText));
+
+ string s = System.Text.UTF8Encoding.UTF8.GetString(challenge);
+
+ using ( HMAC hmac = new HMACMD5(passwd) )
+ {
+ byte[] value = hmac.ComputeHash(challenge);
+ string encoded = ToHex(value);
+ SetComplete();
+ return Encoding.UTF8.GetBytes(username + " " + encoded);
+ }
+ }
+
+ #endregion // ISaslClient Implementation
+
+ } // class CramMD5HashedSaslClient
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs
new file mode 100644
index 0000000000..56b0f6ecd4
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+ /// <summary>
+ /// Implements the CRAM-MD5 authentication mechanism as outlined
+ /// in RFC 2195
+ /// </summary>
+ public class CramMD5SaslClient : SaslClient
+ {
+ public const string Mechanism = "CRAM-MD5";
+ private const int MinPwdLen = 16;
+
+ public CramMD5SaslClient(
+ string authorizationId,
+ IDictionary properties,
+ ISaslCallbackHandler handler)
+ : base(authorizationId, null, null, properties, handler)
+ {
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return false; }
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ if ( challenge == null || challenge.Length == 0 )
+ throw new ArgumentNullException("challenge");
+
+ NameCallback nameCB = new NameCallback(AuthorizationId);
+ PasswordCallback pwdCB = new PasswordCallback();
+ ISaslCallback[] callbacks = { nameCB, pwdCB };
+ Handler.Handle(callbacks);
+
+ string username = nameCB.Text;
+ string passwd = pwdCB.Text.PadRight(MinPwdLen, '\0');
+
+ byte[] secret = Encoding.UTF8.GetBytes(passwd);
+
+ //using ( HMAC hmac = new HMACMD5(secret) )
+ using ( MD5HMAC hmac = new MD5HMAC(secret) )
+ {
+ byte[] value = hmac.ComputeHash(challenge);
+ string encoded = ToHex(value);
+ SetComplete();
+ return Encoding.UTF8.GetBytes(username + " " + encoded);
+ }
+
+ }
+
+ #endregion // ISaslClient Implementation
+
+ } // class CramMD5SaslClient
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs
new file mode 100644
index 0000000000..79843587c7
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs
@@ -0,0 +1,576 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+
+ /// <summary>
+ /// Implements the DIGEST MD5 authentication mechanism
+ /// as outlined in RFC 2831
+ /// </summary>
+ public class DigestSaslClient : SaslClient
+ {
+ public const string Mechanism = "DIGEST-MD5";
+ private static readonly MD5 _md5 = new MD5CryptoServiceProvider();
+ private int _state;
+ private string _cnonce;
+ private Encoding _encoding = Encoding.UTF8;
+
+ public string Cnonce
+ {
+ get { return _cnonce; }
+ set { _cnonce = value; }
+ }
+
+ public DigestSaslClient(
+ string authid, string serverName, string protocol,
+ IDictionary properties, ISaslCallbackHandler handler)
+ : base(authid, serverName, protocol, properties, handler)
+ {
+ _cnonce = Guid.NewGuid().ToString("N");
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return false; }
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ if ( challenge == null || challenge.Length <= 0 )
+ throw new ArgumentNullException("challenge");
+
+ switch ( _state++ )
+ {
+ case 0: return OnInitialChallenge(challenge);
+ case 1: return OnFinalResponse(challenge);
+ }
+ throw new SaslException("Invalid State for authentication");
+ }
+
+ #endregion // ISaslClient Implementation
+
+
+ #region Private Methods
+ //
+ // Private Methods
+ //
+
+ /// <summary>
+ /// Process the first challenge from the server
+ /// and calculate a response
+ /// </summary>
+ /// <param name="challenge">The server issued challenge</param>
+ /// <returns>Client response</returns>
+ private byte[] OnInitialChallenge(byte[] challenge)
+ {
+ DigestChallenge dch =
+ DigestChallenge.Parse(_encoding.GetString(challenge));
+ // validate input challenge
+ if ( dch.Nonce == null || dch.Nonce.Length == 0 )
+ throw new SaslException("Nonce value missing in server challenge");
+ if ( dch.Algorithm != "md5-sess" )
+ throw new SaslException("Invalid or missing algorithm value in server challenge");
+
+
+ NameCallback nameCB = new NameCallback(AuthorizationId);
+ PasswordCallback pwdCB = new PasswordCallback();
+ RealmCallback realmCB = new RealmCallback(dch.Realm);
+ ISaslCallback[] callbacks = { nameCB, pwdCB, realmCB };
+ Handler.Handle(callbacks);
+
+ DigestResponse response = new DigestResponse();
+ response.Username = nameCB.Text;
+ response.Realm = realmCB.Text;
+ response.Nonce = dch.Nonce;
+ response.Cnonce = Cnonce;
+ response.NonceCount = 1;
+ response.Qop = DigestQop.Auth; // only auth supported for now
+ response.DigestUri = Protocol.ToLower() + "/" + ServerName;
+ response.MaxBuffer = dch.MaxBuffer;
+ response.Charset = dch.Charset;
+ response.Cipher = null; // not supported for now
+ response.Authzid = AuthorizationId;
+ response.AuthParam = dch.AuthParam;
+
+ response.Response = CalculateResponse(
+ nameCB.Text, realmCB.Text, pwdCB.Text,
+ dch.Nonce, response.NonceCount, response.Qop, response.DigestUri
+ );
+
+ return _encoding.GetBytes(response.ToString());
+ }
+
+ /// <summary>
+ /// Process the second server challenge
+ /// </summary>
+ /// <param name="challenge">Server issued challenge</param>
+ /// <returns>The client response</returns>
+ private byte[] OnFinalResponse(byte[] challenge)
+ {
+ DigestChallenge dch =
+ DigestChallenge.Parse(_encoding.GetString(challenge));
+
+ if ( dch.Rspauth == null || dch.Rspauth.Length == 0 )
+ throw new SaslException("Expected 'rspauth' in server challenge not found");
+
+ SetComplete();
+ return new byte[0];
+ }
+
+
+
+ /// <summary>
+ /// Calculate the response field of the client response
+ /// </summary>
+ /// <param name="username">The user name</param>
+ /// <param name="realm">The realm</param>
+ /// <param name="passwd">The user's password</param>
+ /// <param name="nonce">Server nonce value</param>
+ /// <param name="nc">Client nonce count (always 1)</param>
+ /// <param name="qop">Quality of Protection</param>
+ /// <param name="digestUri">Digest-URI</param>
+ /// <returns>The value for the response field</returns>
+ private string CalculateResponse(
+ string username, string realm, string passwd,
+ string nonce, int nc, string qop, string digestUri
+ )
+ {
+ string a1 = CalcHexA1(username, realm, passwd, nonce);
+ string a2 = CalcHexA2(digestUri, qop);
+
+ string ncs = nc.ToString("x8", CultureInfo.InvariantCulture);
+ StringBuilder prekd = new StringBuilder();
+ prekd.Append(a1).Append(':').Append(nonce).Append(':')
+ .Append(ncs).Append(':').Append(Cnonce)
+ .Append(':').Append(qop).Append(':').Append(a2);
+
+ return ToHex(CalcH(_encoding.GetBytes(prekd.ToString())));
+ }
+
+ private string CalcHexA1(
+ string username, string realm,
+ string passwd, string nonce
+ )
+ {
+ bool hasAuthId = AuthorizationId != null && AuthorizationId.Length > 0;
+
+ string premd = username + ":" + realm + ":" + passwd;
+ byte[] temp1 = CalcH(_encoding.GetBytes(premd));
+
+
+ int a1len = 16 + 1 + nonce.Length + 1 + Cnonce.Length;
+ if ( hasAuthId )
+ a1len += 1 + AuthorizationId.Length;
+
+ byte[] buffer = new byte[a1len];
+ Array.Copy(temp1, buffer, temp1.Length);
+
+ string p2 = ":" + nonce + ":" + Cnonce;
+ if ( hasAuthId )
+ p2 += ":" + AuthorizationId;
+
+ byte[] temp2 = _encoding.GetBytes(p2);
+ Array.Copy(temp2, 0, buffer, 16, temp2.Length);
+
+ return ToHex(CalcH(buffer));
+ }
+
+ private string CalcHexA2(string digestUri, string qop)
+ {
+ string a2 = "AUTHENTICATE:" + digestUri;
+ if ( qop != DigestQop.Auth )
+ a2 += ":00000000000000000000000000000000";
+ return ToHex(CalcH(_encoding.GetBytes(a2)));
+ }
+
+ private static byte[] CalcH(byte[] value)
+ {
+ return _md5.ComputeHash(value);
+ }
+
+ #endregion // Private Methods
+
+
+ } // class DigestSaslClient
+
+
+ /// <summary>
+ /// Available QOP options in the DIGEST scheme
+ /// </summary>
+ public sealed class DigestQop
+ {
+ public const string Auth = "auth";
+ public const string AuthInt = "auth-int";
+ public const string AuthConf = "auth-conf";
+ } // class DigestQop
+
+
+ /// <summary>
+ /// Represents and parses a digest server challenge
+ /// </summary>
+ public class DigestChallenge
+ {
+ private string _realm = "localhost";
+ private string _nonce;
+ private string[] _qopOptions = { DigestQop.Auth };
+ private bool _stale;
+ private int _maxBuffer = 65536;
+ private string _charset = "ISO 8859-1";
+ private string _algorithm;
+ private string[] _cipherOptions;
+ private string _authParam;
+ private string _rspauth;
+
+ #region Properties
+ //
+ // Properties
+ //
+
+ public string Realm
+ {
+ get { return _realm; }
+ }
+
+ public string Nonce
+ {
+ get { return _nonce; }
+ }
+
+ public string[] QopOptions
+ {
+ get { return _qopOptions; }
+ }
+
+ public bool Stale
+ {
+ get { return _stale; }
+ }
+
+ public int MaxBuffer
+ {
+ get { return _maxBuffer; }
+ set { _maxBuffer = value; }
+ }
+
+ public string Charset
+ {
+ get { return _charset; }
+ }
+
+ public string Algorithm
+ {
+ get { return _algorithm; }
+ }
+
+ public string[] CipherOptions
+ {
+ get { return _cipherOptions; }
+ }
+
+ public string AuthParam
+ {
+ get { return _authParam; }
+ }
+
+ public string Rspauth
+ {
+ get { return _rspauth; }
+ }
+
+ #endregion // Properties
+
+ public static DigestChallenge Parse(string challenge)
+ {
+ DigestChallenge parsed = new DigestChallenge();
+ StringDictionary parts = ParseParameters(challenge);
+ foreach ( string optname in parts.Keys )
+ {
+ switch ( optname )
+ {
+ case "realm":
+ parsed._realm = parts[optname];
+ break;
+ case "nonce":
+ parsed._nonce = parts[optname];
+ break;
+ case "qop-options":
+ parsed._qopOptions = GetOptions(parts[optname]);
+ break;
+ case "cipher-opts":
+ parsed._cipherOptions = GetOptions(parts[optname]);
+ break;
+ case "stale":
+ parsed._stale = Convert.ToBoolean(parts[optname], CultureInfo.InvariantCulture);
+ break;
+ case "maxbuf":
+ parsed._maxBuffer = Convert.ToInt32(parts[optname], CultureInfo.InvariantCulture);
+ break;
+ case "charset":
+ parsed._charset = parts[optname];
+ break;
+ case "algorithm":
+ parsed._algorithm = parts[optname];
+ break;
+ case "auth-param":
+ parsed._authParam = parts[optname];
+ break;
+ case "rspauth":
+ parsed._rspauth = parts[optname];
+ break;
+ }
+ }
+
+ return parsed;
+ }
+
+
+ public static StringDictionary ParseParameters(string source)
+ {
+ if ( source == null )
+ throw new ArgumentNullException("source");
+
+ StringDictionary ret = new StringDictionary();
+
+ string remaining = source.Trim();
+ while ( remaining.Length > 0 )
+ {
+ int equals = remaining.IndexOf('=');
+ if ( equals < 0 )
+ break;
+
+ string optname = remaining.Substring(0, equals).Trim();
+ remaining = remaining.Substring(equals + 1);
+
+ string value = ParseQuoted(ref remaining);
+ ret[optname] = value.Trim();
+ }
+ return ret;
+ }
+
+ private static string ParseQuoted(ref string str)
+ {
+ string ns = str.TrimStart();
+
+ int start = 0;
+ bool quoted = ns[0] == '\"';
+ if ( quoted ) start++;
+ bool inquotes = quoted;
+ bool escaped = false;
+
+ int pos = start;
+ for ( ; pos < ns.Length; pos++ )
+ {
+ if ( !inquotes && ns[pos] == ',' )
+ break;
+
+ // at end of quotes?
+ if ( quoted && !escaped && ns[pos] == '\"' )
+ inquotes = false;
+ // is this char an escape for the next one?
+ escaped = inquotes && ns[pos] == '\\';
+ }
+ // pos has end of string
+ string value = ns.Substring(start, pos-start).Trim();
+ if ( quoted )
+ {
+ // remove trailing quote
+ value = value.Substring(0, value.Length - 1);
+ }
+ str = ns.Substring(pos < ns.Length-1 ? pos+1 : pos);
+ return value;
+ }
+
+ private static string[] GetOptions(string value)
+ {
+ return value.Split(' ');
+ }
+
+ } // class DigestChallenge
+
+
+ /// <summary>
+ /// Represents and knows how to write a
+ /// digest client response
+ /// </summary>
+ public class DigestResponse
+ {
+ private string _username;
+ private string _realm;
+ private string _nonce;
+ private string _cnonce;
+ private int _nonceCount;
+ private string _qop;
+ private string _digestUri;
+ private string _response;
+ private int _maxBuffer;
+ private string _charset;
+ private string _cipher;
+ private string _authzid;
+ private string _authParam;
+
+ #region Properties
+ //
+ // Properties
+ //
+
+ public string Username
+ {
+ get { return _username; }
+ set { _username = value; }
+ }
+
+ public string Realm
+ {
+ get { return _realm; }
+ set { _realm = value; }
+ }
+
+ public string Nonce
+ {
+ get { return _nonce; }
+ set { _nonce = value; }
+ }
+
+ public string Cnonce
+ {
+ get { return _cnonce; }
+ set { _cnonce = value; }
+ }
+
+ public int NonceCount
+ {
+ get { return _nonceCount; }
+ set { _nonceCount = value; }
+ }
+
+ public string Qop
+ {
+ get { return _qop; }
+ set { _qop = value; }
+ }
+
+ public string DigestUri
+ {
+ get { return _digestUri; }
+ set { _digestUri = value; }
+ }
+
+ public string Response
+ {
+ get { return _response; }
+ set { _response = value; }
+ }
+
+ public int MaxBuffer
+ {
+ get { return _maxBuffer; }
+ set { _maxBuffer = value; }
+ }
+
+ public string Charset
+ {
+ get { return _charset; }
+ set { _charset = value; }
+ }
+
+ public string Cipher
+ {
+ get { return _cipher; }
+ set { _cipher = value; }
+ }
+
+ public string Authzid
+ {
+ get { return _authzid; }
+ set { _authzid = value; }
+ }
+
+ public string AuthParam
+ {
+ get { return _authParam; }
+ set { _authParam = value; }
+ }
+
+ #endregion // Properties
+
+
+ public override string ToString()
+ {
+ StringBuilder buffer = new StringBuilder();
+ Pair(buffer, "username", Username, true);
+ Pair(buffer, "realm", Realm, true);
+ Pair(buffer, "nonce", Nonce, true);
+ Pair(buffer, "cnonce", Cnonce, true);
+ string nc = NonceCount.ToString("x8", CultureInfo.InvariantCulture);
+ Pair(buffer, "nc", nc, false);
+ Pair(buffer, "qop", Qop, false);
+ Pair(buffer, "digest-uri", DigestUri, true);
+ Pair(buffer, "response", Response, true);
+ string maxBuffer = MaxBuffer.ToString(CultureInfo.InvariantCulture);
+ Pair(buffer, "maxbuf", maxBuffer, false);
+ Pair(buffer, "charset", Charset, false);
+ Pair(buffer, "cipher", Cipher, false);
+ Pair(buffer, "authzid", Authzid, true);
+ Pair(buffer, "auth-param", AuthParam, true);
+
+ return buffer.ToString().TrimEnd(',');
+ }
+
+ private static void Pair(StringBuilder buffer, string name, string value, bool quoted)
+ {
+ if ( value != null && value.Length > 0 )
+ {
+ buffer.Append(name);
+ buffer.Append('=');
+ if ( quoted )
+ {
+ buffer.Append('\"');
+ buffer.Append(value.Replace("\"", "\\\""));
+ buffer.Append('\"');
+ } else
+ {
+ buffer.Append(value);
+ }
+ buffer.Append(',');
+ }
+ }
+
+ } // class DigestResponse
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Mechanisms/ExternalSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/ExternalSaslClient.cs
new file mode 100644
index 0000000000..fec0d2d3c2
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/ExternalSaslClient.cs
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+ /// <summary>
+ /// Implements the EXTERNAL authentication mechanism
+ /// as outlined in RFC 2222
+ /// </summary>
+ public class ExternalSaslClient : SaslClient
+ {
+ public const string Mechanism = "EXTERNAL";
+
+ public ExternalSaslClient(
+ string authid, IDictionary properties,
+ ISaslCallbackHandler handler)
+ : base(authid, null, null, properties, handler)
+ {
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return true; }
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ // ignore challenge
+ SetComplete();
+ return Encoding.UTF8.GetBytes(AuthorizationId);
+ }
+
+ #endregion // ISaslClient Implementation
+
+ } // class ExternalSaslClient
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs
new file mode 100644
index 0000000000..534be171b7
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Apache.Qpid.Sasl.Mechanisms
+{
+
+ /// <summary>
+ /// Implements the PLAIN authentication mechanism
+ /// as outlined in RFC 4616
+ /// </summary>
+ public class PlainSaslClient : SaslClient
+ {
+ public const string Mechanism = "PLAIN";
+
+ public PlainSaslClient(
+ string authid, IDictionary properties,
+ ISaslCallbackHandler handler)
+ : base(authid, null, null, properties, handler)
+ {
+ }
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+
+ public override bool HasInitialResponse
+ {
+ get { return true; }
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ // ignore challenge
+
+ NameCallback nameCB = new NameCallback();
+ PasswordCallback pwdCB = new PasswordCallback();
+ ISaslCallback[] callbacks = { nameCB, pwdCB };
+ Handler.Handle(callbacks);
+
+ string username = nameCB.Text;
+ string authid = AuthorizationId;
+ string passwd = pwdCB.Text;
+
+ string response =
+ string.Format("{0}\0{1}\0{2}", authid, username, passwd);
+ SetComplete();
+ return Encoding.UTF8.GetBytes(response);
+ }
+
+ #endregion // ISaslClient Implementation
+
+ } // class PlainSaslClient
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs b/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..5245b97d1f
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Sasl")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Sasl")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("27ea23e4-6f84-4a54-8f1f-5725e6d767cc")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: CLSCompliant(true)]
diff --git a/dotnet/Qpid.Sasl/Qpid.Sasl.csproj b/dotnet/Qpid.Sasl/Qpid.Sasl.csproj
new file mode 100644
index 0000000000..8c1d568aa3
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Qpid.Sasl.csproj
@@ -0,0 +1,73 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Sasl</RootNamespace>
+ <AssemblyName>Apache.Qpid.Sasl</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/Qpid.Sasl/Sasl.cs b/dotnet/Qpid.Sasl/Sasl.cs
new file mode 100644
index 0000000000..2f7bacb939
--- /dev/null
+++ b/dotnet/Qpid.Sasl/Sasl.cs
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Configuration;
+using System.Text;
+
+using Apache.Qpid.Sasl.Configuration;
+
+namespace Apache.Qpid.Sasl
+{
+ /// <summary>
+ /// Static class used to access the SASL functionality.
+ /// The core SASL mechanism is described in RFC 2222.
+ /// </summary>
+ /// <remarks>
+ /// Only client side mechanisms are implemented.
+ /// <para>
+ /// New client side factories can be added programatically using the
+ /// RegisterClientFactory method, or through the application
+ /// configuration file, like this:
+ /// </para>
+ /// <example><![CDATA[
+ /// <configuration>
+ /// <configSections>
+ /// <section name="qpid.sasl" type="Apache.Qpid.Sasl.Configuration.SaslConfigurationSectionHandler, Apache.Qpid.Sasl"/>
+ /// </configSections>
+ ///
+ /// <qpid.sasl>
+ /// <clientFactories>
+ /// <add type="Apache.Qpid.Sasl.Tests.TestClientFactory, Apache.Qpid.Sasl.Tests"/>
+ /// </clientFactories>
+ /// </qpid.sasl>
+ /// </configuration>
+ /// ]]></example>
+ /// </remarks>
+ public sealed class Sasl
+ {
+ private static IList _clientFactories;
+
+
+ static Sasl()
+ {
+ SaslConfiguration config = SaslConfiguration.GetConfiguration();
+ _clientFactories = config.ClientFactories;
+ }
+ private Sasl()
+ {
+ }
+
+ public static ISaslClient CreateClient(
+ string[] mechanisms, string authorizationId,
+ string protocol, string serverName,
+ IDictionary props, ISaslCallbackHandler handler
+ )
+ {
+ ISaslClientFactory factory = FindFactory(mechanisms, props);
+ if ( factory == null )
+ return null;
+
+ return factory.CreateClient (
+ mechanisms, authorizationId,
+ protocol, serverName, props, handler
+ );
+ }
+
+ public static void RegisterClientFactory(ISaslClientFactory factory)
+ {
+ lock ( _clientFactories )
+ {
+ _clientFactories.Add(factory);
+ }
+ }
+
+ private static ISaslClientFactory FindFactory(string[] mechanisms, IDictionary props)
+ {
+ lock ( _clientFactories )
+ {
+ foreach ( ISaslClientFactory factory in _clientFactories )
+ {
+ string[] mechs = factory.GetSupportedMechanisms(props);
+ foreach ( string m1 in mechs )
+ {
+ foreach (string m2 in mechanisms )
+ {
+ if ( m1 == m2 )
+ return factory;
+ }
+ }
+ }
+ return null;
+ }
+ }
+ } // class Sasl
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/SaslClient.cs b/dotnet/Qpid.Sasl/SaslClient.cs
new file mode 100644
index 0000000000..a22013181b
--- /dev/null
+++ b/dotnet/Qpid.Sasl/SaslClient.cs
@@ -0,0 +1,145 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ public abstract class SaslClient : ISaslClient
+ {
+ private bool _isComplete;
+ private IDictionary _properties;
+ private string _authorizationId;
+ private string _serverName;
+ private string _protocol;
+ private ISaslCallbackHandler _handler;
+
+ protected string AuthorizationId
+ {
+ get { return _authorizationId; }
+ }
+ protected string ServerName
+ {
+ get { return _serverName; }
+ }
+
+ protected string Protocol
+ {
+ get { return _protocol; }
+ }
+
+ protected ISaslCallbackHandler Handler
+ {
+ get { return _handler; }
+ }
+
+ protected IDictionary Properties
+ {
+ get { return _properties; }
+ }
+
+ protected SaslClient(
+ string authid, string serverName,
+ string protocol, IDictionary properties,
+ ISaslCallbackHandler handler)
+ {
+ if ( properties == null )
+ throw new ArgumentNullException("properties");
+ if ( handler == null )
+ throw new ArgumentNullException("handler");
+
+ _authorizationId = authid==null ? "" : authid;
+ _serverName = serverName;
+ _protocol = protocol;
+ _properties = properties;
+ _handler = handler;
+
+ if ( _serverName == null || _serverName.Length == 0 )
+ {
+ _serverName = System.Net.Dns.GetHostName();
+ }
+ }
+
+
+
+
+ #region ISaslClient Implementation
+ //
+ // ISaslClient Implementation
+ //
+
+ public abstract string MechanismName { get; }
+
+ public abstract bool HasInitialResponse { get; }
+
+ public bool IsComplete
+ {
+ get { return _isComplete; }
+ }
+
+ public abstract byte[] EvaluateChallenge(byte[] challenge);
+
+ public virtual object GetNegotiatedProperty(string propName)
+ {
+ return null;
+ }
+
+ public virtual byte[] Unwrap(byte[] buffer, int offset, int length)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual byte[] Wrap(byte[] buffer, int offset, int lenght)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion // ISaslClient Implementation
+
+
+ #region Helper Methods
+ //
+ // Helper Methods
+ //
+
+ protected void SetComplete()
+ {
+ _isComplete = true;
+ }
+
+ protected static string ToHex(byte[] buffer)
+ {
+ StringBuilder builder = new StringBuilder();
+ foreach ( byte b in buffer )
+ {
+ builder.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+ }
+ return builder.ToString();
+ }
+
+ #endregion // Helper Methods
+
+ } // class SaslClient
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/SaslException.cs b/dotnet/Qpid.Sasl/SaslException.cs
new file mode 100644
index 0000000000..d770ee63fd
--- /dev/null
+++ b/dotnet/Qpid.Sasl/SaslException.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ /// <summary>
+ /// Reports an exception during the processing of an SASL
+ /// Operation. Only used for authentication-relared errors
+ /// </summary>
+ [Serializable]
+ public class SaslException : Exception
+ {
+ public SaslException()
+ {
+ }
+
+ public SaslException(string message)
+ : base(message)
+ {
+ }
+ public SaslException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ protected SaslException(SerializationInfo info, StreamingContext ctxt)
+ : base(info, ctxt)
+ {
+ }
+
+ } // class SaslException
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/SaslProperties.cs b/dotnet/Qpid.Sasl/SaslProperties.cs
new file mode 100644
index 0000000000..f9ad1c68cd
--- /dev/null
+++ b/dotnet/Qpid.Sasl/SaslProperties.cs
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Apache.Qpid.Sasl
+{
+ public sealed class SaslProperties
+ {
+ public const string PolicyNoPlainText = "NOPLAINTEXT";
+ public const string PolicyNoActive = "NOACTIVE";
+ public const string PolicyNoDictionary = "NODICTIONARY";
+ public const string PolicyNoAnonymous = "NOANONYMOUS";
+ public const string PolicyForwardSecrecy = "FORWARD_SECRECY";
+ public const string PolicyPassCredentials = "PASS_CREDENTIALS";
+
+ public const string Qop = "QOP";
+ public const string Strength = "STRENGTH";
+
+ } // class SaslProperties
+
+} // namespace Apache.Qpid.Sasl.Mechanisms
diff --git a/dotnet/Qpid.Sasl/default.build b/dotnet/Qpid.Sasl/default.build
new file mode 100644
index 0000000000..57049ee2ee
--- /dev/null
+++ b/dotnet/Qpid.Sasl/default.build
@@ -0,0 +1,45 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Apache.Qpid.Sasl" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/README.txt b/dotnet/README.txt
new file mode 100644
index 0000000000..0199ad6410
--- /dev/null
+++ b/dotnet/README.txt
@@ -0,0 +1,68 @@
+Info
+====
+
+There are two separate .NET clients: one that implements AMQP 0-8 (and
+can communicate with the Java broker) and another that implements
+0-10 (and can communicate with the C++ broker).
+
+This README contains instructions for building the 0-8 client.
+
+Instructions for building and installing the 0-10 client are located in client-010/README.txt.
+
+Setup
+=====
+
+Essential:
+
+ .NET 2.0 or later
+ Ant 1.6.5 (Java build tool, http://ant.apache.org)
+
+Either:
+ NAnt 0.85 - only required for builds outside Visual Studio
+OR
+ Microsoft Visual Studio 2008 (VS2008)
+
+Ensure that your PATH includes ant, e.g.:
+
+ $ PATH=c:\java\ant\bin:%PATH%
+
+If using nant, set up PATH to include Nant.exe, e.g.:
+
+ $ set PATH=C:\dotnet\nant\bin;%PATH%
+
+If using msbuild, it is recommended to use a "Visual Studio Command Prompt"
+
+Building
+========
+
+Generate framing from /Qpid.Common/amqp.xml specification file by running this script:
+
+ $ build-framing.bat
+
+Alternatively, just switch to /Qpid.Common and run "ant" there.
+
+You can build from Visual Studio 2008 or from the command-line by running msbuild.
+
+The script build-msbuild.bat provides some standard options to do a full build.
+
+If you are using nant, the script build-nant.bat contains standard arguments that do a full build.
+
+To build for Mono on Linux (to bin/mono-2.0) the build-mono shell script is provided.
+
+Releasing
+=========
+
+nant can be used to create a release zip archive. A script is provided:
+
+For .NET 2.0
+
+ $ release net-2.0
+
+Generates ./bin/net-2.0/release/Qpid.NET-net-2.0-yyyyMMdd.zip
+
+For Mono
+
+ $ release mono-2.0
+
+Generates ./bin/mono-2.0/release/Qpid.NET-mono-2.0-yyyyMMdd.zip
+
diff --git a/dotnet/RELEASE_NOTES.txt b/dotnet/RELEASE_NOTES.txt
new file mode 100644
index 0000000000..e824757b42
--- /dev/null
+++ b/dotnet/RELEASE_NOTES.txt
@@ -0,0 +1,11 @@
+Apache Qpid .NET 0.8 Release Notes
+-------------------------------------------
+
+The Qpid 0.8 release contains seperate clients that support the AMQP
+0-10 and AMQP 0-8 protocols.
+
+Known Issues/Outstanding Work
+-----------------------------
+
+You can view the outstanding task list for Qpid by visiting our JIRA:
+http://issues.apache.org/jira/browse/QPID
diff --git a/dotnet/TestClient/Program.cs b/dotnet/TestClient/Program.cs
new file mode 100644
index 0000000000..f4b2db568e
--- /dev/null
+++ b/dotnet/TestClient/Program.cs
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace TopicListener
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Apache.Qpid.Integration.Tests.interop.TestClient.Main(args);
+ }
+ }
+}
diff --git a/dotnet/TestClient/Properties/AssemblyInfo.cs b/dotnet/TestClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e8ffbc5aba
--- /dev/null
+++ b/dotnet/TestClient/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestClient")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("TestClient")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1c2db1cd-239f-495a-b6b4-c815ea534489")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/TestClient/TestClient.csproj b/dotnet/TestClient/TestClient.csproj
new file mode 100644
index 0000000000..cc7ab37657
--- /dev/null
+++ b/dotnet/TestClient/TestClient.csproj
@@ -0,0 +1,115 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6E0374D9-99BE-4D4F-B41D-B227E37E04C6}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TestClient</RootNamespace>
+ <AssemblyName>TestClient</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer.Tests\Qpid.Buffer.Tests.csproj">
+ <Project>{74640962-99D0-4D06-B57A-9CD66517CF52}</Project>
+ <Name>Qpid.Buffer.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client.Tests\Qpid.Client.Tests.csproj">
+ <Project>{BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}</Project>
+ <Name>Qpid.Client.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Codec\Qpid.Codec.csproj">
+ <Project>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</Project>
+ <Name>Qpid.Codec</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common.Tests\Qpid.Common.Tests.csproj">
+ <Project>{F83624B0-762B-4D82-900D-FF4C1B36E36E}</Project>
+ <Name>Qpid.Common.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl.Tests\Qpid.Sasl.Tests.csproj">
+ <Project>{587B3520-EBB9-41ED-B019-E96116B651CE}</Project>
+ <Name>Qpid.Sasl.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/TestClient/default.build b/dotnet/TestClient/default.build
new file mode 100644
index 0000000000..ce1114425e
--- /dev/null
+++ b/dotnet/TestClient/default.build
@@ -0,0 +1,47 @@
+<?xml version="1.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.
+
+-->
+
+<project name="TestClient" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ unsafe="true"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}\Apache.Qpid.Integration.Tests.dll"/>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/TopicListener/Program.cs b/dotnet/TopicListener/Program.cs
new file mode 100644
index 0000000000..14626d6134
--- /dev/null
+++ b/dotnet/TopicListener/Program.cs
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace TopicListener
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Apache.Qpid.Client.Tests.interop.TopicListener.Main(args);
+ }
+ }
+}
diff --git a/dotnet/TopicListener/Properties/AssemblyInfo.cs b/dotnet/TopicListener/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..1fe9bb8249
--- /dev/null
+++ b/dotnet/TopicListener/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TopicListener")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("TopicListener")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1c2db1cd-239f-495a-b6b4-c815ea534489")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/TopicListener/TopicListener.csproj b/dotnet/TopicListener/TopicListener.csproj
new file mode 100644
index 0000000000..46da42ea61
--- /dev/null
+++ b/dotnet/TopicListener/TopicListener.csproj
@@ -0,0 +1,115 @@
+<!--
+
+ 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.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{9A112DF2-146F-4CF4-919B-9D3BE7D088E9}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TopicListener</RootNamespace>
+ <AssemblyName>TopicListener</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer.Tests\Qpid.Buffer.Tests.csproj">
+ <Project>{74640962-99D0-4D06-B57A-9CD66517CF52}</Project>
+ <Name>Qpid.Buffer.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client.Tests\Qpid.Client.Tests.csproj">
+ <Project>{BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}</Project>
+ <Name>Qpid.Client.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Codec\Qpid.Codec.csproj">
+ <Project>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</Project>
+ <Name>Qpid.Codec</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common.Tests\Qpid.Common.Tests.csproj">
+ <Project>{F83624B0-762B-4D82-900D-FF4C1B36E36E}</Project>
+ <Name>Qpid.Common.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl.Tests\Qpid.Sasl.Tests.csproj">
+ <Project>{587B3520-EBB9-41ED-B019-E96116B651CE}</Project>
+ <Name>Qpid.Sasl.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/TopicListener/default.build b/dotnet/TopicListener/default.build
new file mode 100644
index 0000000000..f9b0f97094
--- /dev/null
+++ b/dotnet/TopicListener/default.build
@@ -0,0 +1,47 @@
+<?xml version="1.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.
+
+-->
+
+<project name="TopicListener" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ unsafe="true"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}\Apache.Qpid.Client.Tests.dll"/>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/TopicPublisher/Program.cs b/dotnet/TopicPublisher/Program.cs
new file mode 100644
index 0000000000..b5209b9317
--- /dev/null
+++ b/dotnet/TopicPublisher/Program.cs
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+namespace TopicPublisher
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Apache.Qpid.Client.Tests.interop.TopicPublisher.Main(args);
+ }
+ }
+}
diff --git a/dotnet/TopicPublisher/Properties/AssemblyInfo.cs b/dotnet/TopicPublisher/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..051b34ee37
--- /dev/null
+++ b/dotnet/TopicPublisher/Properties/AssemblyInfo.cs
@@ -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.
+ *
+ */
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TopicPublisher")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("TopicPublisher")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("93fa1c32-c0f8-47e5-b167-dc581e33eb9b")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/TopicPublisher/TopicPublisher.csproj b/dotnet/TopicPublisher/TopicPublisher.csproj
new file mode 100644
index 0000000000..fbbf77fb8e
--- /dev/null
+++ b/dotnet/TopicPublisher/TopicPublisher.csproj
@@ -0,0 +1,111 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A06C9FFD-22FF-4654-856D-897C230978AF}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>TopicPublisher</RootNamespace>
+ <AssemblyName>TopicPublisher</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Buffer\Qpid.Buffer.csproj">
+ <Project>{44384DF2-B0A4-4580-BDBC-EE4BAA87D995}</Project>
+ <Name>Qpid.Buffer</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client.Tests\Qpid.Client.Tests.csproj">
+ <Project>{BA1B0032-4CE6-40DD-A2DC-119F0FFA0A1D}</Project>
+ <Name>Qpid.Client.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Client\Qpid.Client.csproj">
+ <Project>{68987C05-3768-452C-A6FC-6BA1D372852F}</Project>
+ <Name>Qpid.Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Codec\Qpid.Codec.csproj">
+ <Project>{22D0D0C2-77AF-4DE3-B456-7FF3893F9F88}</Project>
+ <Name>Qpid.Codec</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common.Tests\Qpid.Common.Tests.csproj">
+ <Project>{F83624B0-762B-4D82-900D-FF4C1B36E36E}</Project>
+ <Name>Qpid.Common.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Common\Qpid.Common.csproj">
+ <Project>{77064C42-24D2-4CEB-9EA2-0EF481A43205}</Project>
+ <Name>Qpid.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Messaging\Qpid.Messaging.csproj">
+ <Project>{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}</Project>
+ <Name>Qpid.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl.Tests\Qpid.Sasl.Tests.csproj">
+ <Project>{587B3520-EBB9-41ED-B019-E96116B651CE}</Project>
+ <Name>Qpid.Sasl.Tests</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/TopicPublisher/default.build b/dotnet/TopicPublisher/default.build
new file mode 100644
index 0000000000..9b01c2a1bc
--- /dev/null
+++ b/dotnet/TopicPublisher/default.build
@@ -0,0 +1,47 @@
+<?xml version="1.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.
+
+-->
+
+<project name="TopicPublisher" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ unsafe="true"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}\Apache.Qpid.Client.Tests.dll"/>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/build-framing.bat b/dotnet/build-framing.bat
new file mode 100644
index 0000000000..ae9bc749a9
--- /dev/null
+++ b/dotnet/build-framing.bat
@@ -0,0 +1,23 @@
+@REM
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+@REM
+
+cd Qpid.Common
+ant
diff --git a/dotnet/build-mono b/dotnet/build-mono
new file mode 100755
index 0000000000..2bb6147b53
--- /dev/null
+++ b/dotnet/build-mono
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+nant -t:mono-2.0
diff --git a/dotnet/build-msbuild.bat b/dotnet/build-msbuild.bat
new file mode 100644
index 0000000000..1fe4b5d64c
--- /dev/null
+++ b/dotnet/build-msbuild.bat
@@ -0,0 +1,22 @@
+@REM
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+@REM
+
+MSBuild.exe Qpid.NET.sln /p:Configuration=Release /t:rebuild
diff --git a/dotnet/build-nant-release b/dotnet/build-nant-release
new file mode 100755
index 0000000000..611a1efe08
--- /dev/null
+++ b/dotnet/build-nant-release
@@ -0,0 +1,55 @@
+#
+#
+# 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.
+#
+#
+
+#!/bin/bash
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+
+
+Usage()
+{
+ echo "usage: $0 net-2.0|mono-2.0"
+ exit 2
+}
+
+if [[ $# -ne 1 ]]; then
+ Usage
+fi
+
+nant -t:$1 release-pkg -D:build.config=release
diff --git a/dotnet/build-nant.bat b/dotnet/build-nant.bat
new file mode 100644
index 0000000000..785450a9f7
--- /dev/null
+++ b/dotnet/build-nant.bat
@@ -0,0 +1,22 @@
+@REM
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+@REM
+
+nant -t:net-2.0
diff --git a/dotnet/client-010/App.config b/dotnet/client-010/App.config
new file mode 100644
index 0000000000..36b4ffab3e
--- /dev/null
+++ b/dotnet/client-010/App.config
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <appSettings>
+ <add key="Username" value="guest"/>
+ <add key="Password" value="guest123"/>
+ <add key="Host" value="localhost"/>
+ <add key="Port" value="5672"/>
+ <add key="VirtualHost" value="test"/>
+
+ <!-- <add key="ProcessorAssembly" value="C:\Project\qpid\dotnet\client-010\addins\ExcelAddInMessageProcessor\bin\Debug\ExcelAddInMessageProcessor.dll"/>
+ <add key="ProcessorClass" value="ExcelAddInMessageProcessor.Processor"/> -->
+ </appSettings>
+</configuration>
diff --git a/dotnet/client-010/LICENSE.txt b/dotnet/client-010/LICENSE.txt
new file mode 100644
index 0000000000..981d2f83c3
--- /dev/null
+++ b/dotnet/client-010/LICENSE.txt
@@ -0,0 +1,757 @@
+
+ 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.
+
+
+=========================================================================
+== Saxon XSLT License ==
+=========================================================================
+
+Mozilla Public License Version 1.0
+
+1. Definitions.
+
+ 1.1. "Contributor" means each entity that creates or contributes
+ to the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the
+ Original Code, prior Modifications used by a Contributor, and the
+ Modifications made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications
+ or the combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism
+ generally accepted in the software development community for the
+ electronic transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than
+ Source Code.
+
+ 1.6. "Initial Developer" means the individual or entity
+ identified as the Initial Developer in the Source Code notice required by
+ Exhibit A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code
+ or portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.9. "Modifications" means any addition to or deletion from
+ the substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original
+ Code or previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software
+ code which is described in the Source Code notice required by Exhibit
+ A as Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.11. "Source Code" means the preferred form of the Covered
+ Code for making modifications to it, including all modules it contains,
+ plus any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or a list of source code
+ differential comparisons against either the Original Code or another well
+ known, available Covered Code of the Contributor's choice. The Source
+ Code can be in a compressed or archival form, provided the appropriate
+ decompression or de-archiving software is widely available for no charge.
+
+ 1.12. "You" means an individual or a legal entity exercising
+ rights under, and complying with all of the terms of, this License or a
+ future version of this License issued under Section 6.1. For legal
+ entities, "You" includes any entity which controls, is controlled by,
+ or is under common control with You. For purposes of this definition,
+ "control" means (a) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or otherwise,
+ or (b) ownership of fifty percent (50%) or more of the outstanding shares
+ or beneficial ownership of such entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+
+
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+
+ (a) to use, reproduce, modify, display, perform, sublicense
+ and distribute the Original Code (or portions thereof) with or
+ without Modifications, or as part of a Larger Work; and
+
+ (b) under patents now or hereafter owned or controlled by
+ Initial Developer, to make, have made, use and sell ("Utilize") the
+ Original Code (or portions thereof), but solely to the extent that
+ any such patent is reasonably necessary to enable You to Utilize the
+ Original Code (or portions thereof) and not to any greater extent
+ that may be necessary to Utilize further Modifications or
+ combinations.
+
+ 2.2. Contributor Grant.
+
+
+ Each Contributor hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+
+ (a) to use, reproduce, modify, display, perform, sublicense and
+ distribute the Modifications created by such Contributor (or portions
+ thereof) either on an unmodified basis, with other Modifications, as
+ Covered Code or as part of a Larger Work; and
+
+ (b) under patents now or hereafter owned or controlled by
+ Contributor, to Utilize the Contributor Version (or portions thereof),
+ but solely to the extent that any such patent is reasonably necessary to
+ enable You to Utilize the Contributor Version (or portions thereof), and
+ not to any greater extent that may be necessary to Utilize further
+ Modifications or combinations.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+
+
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version of
+ this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this License
+ or the recipients' rights hereunder. However, You may include an
+ additional document offering the additional rights described in Section
+ 3.5.
+
+ 3.2. Availability of Source Code.
+
+
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License either
+ on the same media as an Executable version or via an accepted Electronic
+ Distribution Mechanism to anyone to whom you made an Executable version
+ available; and if made available via Electronic Distribution Mechanism,
+ must remain available for at least twelve (12) months after the date it
+ initially became available, or at least six (6) months after a subsequent
+ version of that particular Modification has been made available to such
+ recipients. You are responsible for ensuring that the Source Code version
+ remains available even if the Electronic Distribution Mechanism is
+ maintained by a third party.
+
+ 3.3. Description of Modifications.
+
+
+ You must cause all Covered Code to which you contribute to contain a
+ file documenting the changes You made to create that Covered Code and the
+ date of any change. You must include a prominent statement that the
+ Modification is derived, directly or indirectly, from Original Code
+ provided by the Initial Developer and including the name of the Initial
+ Developer in (a) the Source Code, and (b) in any notice in an Executable
+ version or related documentation in which You describe the origin or
+ ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+
+ (a) Third Party Claims.
+
+
+ If You have knowledge that a party claims an intellectual
+ property right in particular functionality or code (or its
+ utilization under this License), you must include a text file with
+ the source code distribution titled "LEGAL" which describes the
+ claim and the party making the claim in sufficient detail that a
+ recipient will know whom to contact. If you obtain such knowledge
+ after You make Your Modification available as described in Section
+ 3.2, You shall promptly modify the LEGAL file in all copies
+ You make available thereafter and shall take other steps (such as
+ notifying appropriate mailing lists or newsgroups) reasonably
+ calculated to inform those who received the Covered Code that new
+ knowledge has been obtained.
+
+ (b) Contributor APIs.
+
+
+ If Your Modification is an application programming interface and
+ You own or control patents which are reasonably necessary to
+ implement that API, you must also include this information in the
+ LEGAL file.
+
+ 3.5. Required Notices.
+
+
+ You must duplicate the notice in Exhibit A in each file of the
+ Source Code, and this License in any documentation for the Source Code,
+ where You describe recipients' rights relating to Covered Code. If You
+ created one or more Modification(s), You may add your name as a
+ Contributor to the notice described in Exhibit A. If it is not
+ possible to put such notice in a particular Source Code file due to its
+ structure, then you must include such notice in a location (such as a
+ relevant directory file) where a user would be likely to look for such a
+ notice. You may choose to offer, and to charge a fee for, warranty,
+ support, indemnity or liability obligations to one or more recipients of
+ Covered Code. However, You may do so only on Your own behalf, and not on
+ behalf of the Initial Developer or any Contributor. You must make it
+ absolutely clear than any such warranty, support, indemnity or liability
+ obligation is offered by You alone, and You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty, support,
+ indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+
+
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered
+ Code, and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License, including
+ a description of how and where You have fulfilled the obligations of
+ Section 3.2. The notice must be conspicuously included in any
+ notice in an Executable version, related documentation or collateral in
+ which You describe recipients' rights relating to the Covered Code. You
+ may distribute the Executable version of Covered Code under a license of
+ Your choice, which may contain terms different from this License,
+ provided that You are in compliance with the terms of this License and
+ that the license for the Executable version does not attempt to limit or
+ alter the recipient's rights in the Source Code version from the rights
+ set forth in this License. If You distribute the Executable version under
+ a different license You must make it absolutely clear that any terms
+ which differ from this License are offered by You alone, not by the
+ Initial Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of any such terms You
+ offer.
+
+ 3.7. Larger Works.
+
+
+ You may create a Larger Work by combining Covered Code with other
+ code not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to statute or
+ regulation then You must: (a) comply with the terms of this License to
+ the maximum extent possible; and (b) describe the limitations and the
+ code they affect. Such description must be included in the LEGAL file
+ described in Section 3.4 and must be included with all
+ distributions of the Source Code. Except to the extent prohibited by
+ statute or regulation, such description must be sufficiently detailed for
+ a recipient of ordinary skill
+ to be able to understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has attached
+ the notice in Exhibit A, and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+
+
+ Netscape Communications Corporation ("Netscape") may publish
+ revised and/or new versions of the License from time to time. Each
+ version will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+
+
+ Once Covered Code has been published under a particular version of
+ the License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms of
+ any subsequent version of the License published by Netscape. No one other
+ than Netscape has the right to modify the terms applicable to Covered
+ Code created under this License.
+
+ 6.3. Derivative Works.
+
+
+ If you create or use a modified version of this License (which you
+ may only do in order to apply it to code which is not already Covered
+ Code governed by this License), you must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "NPL"
+ or any confusingly similar phrase do not appear anywhere in your license
+ and (b) otherwise make it clear that your version of the license contains
+ terms which differ from the Mozilla Public License and Netscape Public
+ License. (Filling in the name of the Initial Developer, Original Code or
+ Contributor in the notice described in Exhibit A shall not of
+ themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS,
+ MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE
+ RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH
+ YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+ INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+ NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
+ CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE
+ IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall survive
+ any termination of this License. Provisions which, by their nature, must
+ remain in effect beyond the termination of this License shall survive.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING
+ NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY
+ OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF
+ ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
+ INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER
+ INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK
+ STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED
+ OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL
+ NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH
+ PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH
+ LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION
+ OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION
+ MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in 48
+ C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software"
+ and "commercial computer software documentation," as such terms are
+ used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212
+ and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
+ U.S. Government End Users acquire Covered Code with only those rights set
+ forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject matter
+ hereof. If any provision of this License is held to be unenforceable,
+ such provision shall be reformed only to the extent necessary to make it
+ enforceable. This License shall be governed by California law provisions
+ (except to the extent applicable law, if any, provides otherwise),
+ excluding its conflict-of-law provisions. With respect to disputes in
+ which at least one party is a citizen of, or an entity chartered or
+ registered to do business in, the United States of America: (a) unless
+ otherwise agreed in writing, all disputes relating to this License
+ (excepting any dispute relating to intellectual property rights) shall be
+ subject to final and binding arbitration, with the losing party paying
+ all costs of arbitration; (b) any arbitration relating to this Agreement
+ shall be held in Santa Clara County, California, under the auspices of
+ JAMS/EndDispute; and (c) any litigation relating to this Agreement shall
+ be subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys fees and
+ expenses. The application of the United Nations Convention on Contracts
+ for the International Sale of Goods is expressly excluded. Any law or
+ regulation which provides that the language of a contract shall be
+ construed against the drafter shall not apply to this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ Except in cases where another Contributor has failed to comply with
+ Section 3.4, You are responsible for damages arising, directly or
+ indirectly, out of Your utilization of rights under this License, based
+ on the number of copies of Covered Code you made available, the revenues
+ you received from utilizing such rights, and other relevant factors. You
+ agree to work with affected parties to distribute responsibility on an
+ equitable basis.
+
+EXHIBIT A.
+
+ "The contents of this file are subject to the Mozilla Public License
+ Version 1.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.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations under
+ the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is
+ ________________________. Portions created by ______________________ are
+ Copyright (C) ______ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________."
+
+
+=========================================================================
+== Nunit License ==
+=========================================================================
+Copyright (c) 2002 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
+Copyright (c) 2000-2002 Philip A. Craig
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
+=========================================================================
+== Mentalis Security LibraryLicense ==
+=========================================================================
+
+Source Code License
+
+Copyright © 2002-2007, The Mentalis.org Team
+All rights reserved.
+http://www.mentalis.org/
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+- Neither the name of the Mentalis.org Team, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================
+== AMQP License ==
+=========================================================================
+
+ Copyright Notice
+ ================
+ (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc.,
+ iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc.,
+ TWIST Process Innovations, and 29West Inc. 2006. All rights reserved.
+
+ License
+ =======
+ JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix
+ Corporation, IONA\ufffd Technologies, Red Hat, Inc., TWIST Process Innovations, and
+ 29West Inc. (collectively, the "Authors") each hereby grants to you a worldwide,
+ perpetual, royalty-free, nontransferable, nonexclusive license to
+ (i) copy, display, and implement the Advanced Messaging Queue Protocol
+ ("AMQP") Specification and (ii) the Licensed Claims that are held by
+ the Authors, all for the purpose of implementing the Advanced Messaging
+ Queue Protocol Specification. Your license and any rights under this
+ Agreement will terminate immediately without notice from
+ any Author if you bring any claim, suit, demand, or action related to
+ the Advanced Messaging Queue Protocol Specification against any Author.
+ Upon termination, you shall destroy all copies of the Advanced Messaging
+ Queue Protocol Specification in your possession or control.
+
+ As used hereunder, "Licensed Claims" means those claims of a patent or
+ patent application, throughout the world, excluding design patents and
+ design registrations, owned or controlled, or that can be sublicensed
+ without fee and in compliance with the requirements of this
+ Agreement, by an Author or its affiliates now or at any
+ future time and which would necessarily be infringed by implementation
+ of the Advanced Messaging Queue Protocol Specification. A claim is
+ necessarily infringed hereunder only when it is not possible to avoid
+ infringing it because there is no plausible non-infringing alternative
+ for implementing the required portions of the Advanced Messaging Queue
+ Protocol Specification. Notwithstanding the foregoing, Licensed Claims
+ shall not include any claims other than as set forth above even if
+ contained in the same patent as Licensed Claims; or that read solely
+ on any implementations of any portion of the Advanced Messaging Queue
+ Protocol Specification that are not required by the Advanced Messaging
+ Queue Protocol Specification, or that, if licensed, would require a
+ payment of royalties by the licensor to unaffiliated third parties.
+ Moreover, Licensed Claims shall not include (i) any enabling technologies
+ that may be necessary to make or use any Licensed Product but are not
+ themselves expressly set forth in the Advanced Messaging Queue Protocol
+ Specification (e.g., semiconductor manufacturing technology, compiler
+ technology, object oriented technology, networking technology, operating
+ system technology, and the like); or (ii) the implementation of other
+ published standards developed elsewhere and merely referred to in the
+ body of the Advanced Messaging Queue Protocol Specification, or
+ (iii) any Licensed Product and any combinations thereof the purpose or
+ function of which is not required for compliance with the Advanced
+ Messaging Queue Protocol Specification. For purposes of this definition,
+ the Advanced Messaging Queue Protocol Specification shall be deemed to
+ include both architectural and interconnection requirements essential
+ for interoperability and may also include supporting source code artifacts
+ where such architectural, interconnection requirements and source code
+ artifacts are expressly identified as being required or documentation to
+ achieve compliance with the Advanced Messaging Queue Protocol Specification.
+
+ As used hereunder, "Licensed Products" means only those specific portions
+ of products (hardware, software or combinations thereof) that implement
+ and are compliant with all relevant portions of the Advanced Messaging
+ Queue Protocol Specification.
+
+ The following disclaimers, which you hereby also acknowledge as to any
+ use you may make of the Advanced Messaging Queue Protocol Specification:
+
+ THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS,"
+ AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+ IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE
+ CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE
+ SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED
+ MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
+ USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE
+ PROTOCOL SPECIFICATION.
+
+ The name and trademarks of the Authors may NOT be used in any manner,
+ including advertising or publicity pertaining to the Advanced Messaging
+ Queue Protocol Specification or its contents without specific, written
+ prior permission. Title to copyright in the Advanced Messaging Queue
+ Protocol Specification will at all times remain with the Authors.
+
+ No other rights are granted by implication, estoppel or otherwise.
+
+ Upon termination of your license or rights under this Agreement, you
+ shall destroy all copies of the Advanced Messaging Queue Protocol
+ Specification in your possession or control.
+
+ Trademarks
+ ==========
+ "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the
+ Octagon Symbol are trademarks of JPMorgan Chase & Co.
+
+ IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
+
+ IONA, IONA Technologies, and the IONA logos are trademarks of IONA
+ Technologies PLC and/or its subsidiaries.
+
+ LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered
+ trademarks of Red Hat, Inc. in the US and other countries.
+
+ Java, all Java-based trademarks and OpenOffice.org are trademarks of
+ Sun Microsystems, Inc. in the United States, other countries, or both.
+
+ Other company, product, or service names may be trademarks or service
+ marks of others.
+
+ Links to full AMQP specification:
+ =================================
+ http://www.envoytech.org/spec/amq/
+ http://www.iona.com/opensource/amqp/
+ http://www.redhat.com/solutions/specifications/amqp/
+ http://www.twiststandards.org/tiki-index.php?page=AMQ
+ http://www.imatix.com/amqp
diff --git a/dotnet/client-010/NOTICE.txt b/dotnet/client-010/NOTICE.txt
new file mode 100644
index 0000000000..0b22ed3ab2
--- /dev/null
+++ b/dotnet/client-010/NOTICE.txt
@@ -0,0 +1,32 @@
+=========================================================================
+== NOTICE file corresponding to the section 4 d of ==
+== the Apache License, Version 2.0, ==
+== in this case for the Apache Ant distribution. ==
+=========================================================================
+
+Apache Qpid.NET
+Copyright 2006 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+This product also includes software developed by:
+
+ - The SAXON XSLT Processor from Michael Kay distributed under the Mozilla
+ Public License v1.0, which is available for download at
+ http://saxon.sourceforge.net/
+
+ - The nunit library, Copyright © 2002 James W. Newkirk, Michael C. Two,
+ Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig. Available
+ under terms based on the zlib/libpng licence. Available from
+ http://www.nunit.org/
+
+ - The Mentalis Security Library, Copyright © 2002-2006, , The Mentalis.org Team
+ under tterms based on the BSD license (http://www.mentalis.org/site/license.qpx).
+ Available from http://www.mentalis.org/soft/projects/seclib/
+
+This product includes software, Apache Log4Net
+(http://logging.apache.org/log4net)
+License: Apache 2.0 License (http://www.apache.org/licenses/LICENSE-2.0)
+
+
diff --git a/dotnet/client-010/README.txt b/dotnet/client-010/README.txt
new file mode 100644
index 0000000000..74d54a9786
--- /dev/null
+++ b/dotnet/client-010/README.txt
@@ -0,0 +1,69 @@
+Info
+====
+
+AMQP 0.10 Native .NET client supporting WCF and xcel
+
+In order to build this client from the sources you'll need the following folders :
+- <project home>/java/lib
+- <project home>/python
+- <project home>/specs
+
+
+Setup
+=====
+
+Install:
+ Microsoft Visual Studio 2008 (VS2008). It's also possible to build with vs2005 by creating a new solution and adding Client.csproj
+ NAnt 0.85 - only required for builds outside VS2008 (.net 1.1, .net 2.0, mono 2.0)
+ Ant 1.6.5 (requires Java)
+ Cygwin (or alternatively build via cmd but alter instructions below accordingly)
+
+Set up PATH to include Nant.exe:
+
+ $ PATH=/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:$PATH
+
+Set up PATH to include ant:
+
+ $ PATH=$ANT_HOME/bin:$PATH
+
+
+Building
+========
+
+Generate code from <project home>/dotnet/client-010/gentool:
+
+ $ cd <project home>/dotnet/client-010/gentool
+ $ ant
+
+You can build from Visual Studio 2008 normally. Alternatively, you
+can build debug releases for any supported framework from the
+command line using Nant:
+
+To build .NET 2.0 executables (to bin/net-2.0):
+
+ $ cd <project home>/dotnet/client-010/
+ $ nant
+
+
+To build for Mono on Linux (to bin/mono-2.0):
+
+ $ cd <project home>/dotnet/client-010/
+ $ nant -t:mono-2.0
+
+Releasing
+=========
+
+For .NET 2.0
+
+ $ cd <project home>/dotnet/client-010/
+ $ nant release-pkg
+
+Generates ./bin/net-2.0/release/Qpid.NET-net-2.0-yyyyMMdd.zip
+
+For Mono
+
+ $ cd <project home>/dotnet/client-010/
+ $ nant -t:mono-2.0 release-pkg
+
+Generates ./bin/mono-2.0/release/Qpid.NET-mono-2.0-yyyyMMdd.zip
+
diff --git a/dotnet/client-010/addins/ExcelAddIn/Excel.exe.config b/dotnet/client-010/addins/ExcelAddIn/Excel.exe.config
new file mode 100644
index 0000000000..66bf63532e
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddIn/Excel.exe.config
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <appSettings>
+ <add key="Host" value="localhost" />
+ <add key="Port" value="5672" />
+ <add key="VirtualHost" value="test" />
+ <add key="UserName" value="guest" />
+ <add key="Password" value="guest" />
+ <!-- <add key="ProcessorAssembly" value="C:\Project\qpid\dotnet\client-010\addins\ExcelAddInMessageProcessor\bin\Debug\ExcelAddInMessageProcessor.dll"/>
+ <add key="ProcessorClass" value="ExcelAddInMessageProcessor.Processor"/> -->
+ </appSettings>
+</configuration> \ No newline at end of file
diff --git a/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.cs b/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.cs
new file mode 100644
index 0000000000..66c9b7a8f9
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.cs
@@ -0,0 +1,290 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Office.Interop.Excel;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace ExcelAddIn
+{
+ public delegate string ProcessMessage(IMessage m);
+
+ /// <summary>
+ /// This interface must be implemented so to use a user defined message processor
+ /// </summary>
+ public interface MessageProcessor
+ {
+ string ProcessMessage(IMessage m);
+ }
+
+ [ComVisible(true), ProgId("Qpid")]
+ public class ExcelAddIn : IRtdServer
+ {
+ private IRTDUpdateEvent _onMessage;
+ private readonly Dictionary<int, IMessage> _topicMessages = new Dictionary<int, IMessage>();
+ private readonly Dictionary<string, QpidListener> _queueListener = new Dictionary<string, QpidListener>();
+ private readonly Dictionary<int, string> _topicQueueName = new Dictionary<int, string>();
+ private IClient _client;
+ private IClientSession _session;
+ private ProcessMessage _messageProcessor;
+
+ #region properties
+
+ public IRTDUpdateEvent OnMessage
+ {
+ get { return _onMessage; }
+ }
+
+ public Dictionary<int, IMessage> TopicMessages
+ {
+ get { return _topicMessages; }
+ }
+
+ public IClientSession Session
+ {
+ get { return _session; }
+ }
+
+ #endregion
+
+
+ #region IRtdServer Members
+
+ /// <summary>
+ /// Called when Excel requests the first RTD topic for the server.
+ /// Connect to the broker, returns a on success and 0 otherwise
+ /// </summary>
+ /// <param name="CallbackObject"></param>
+ /// <returns></returns>
+ public int ServerStart(IRTDUpdateEvent CallbackObject)
+ {
+ _onMessage = CallbackObject;
+ string host = "localhost";
+ string port = "5673";
+ string virtualhost = "test";
+ string username = "guest";
+ string password = "guest";
+ _messageProcessor = getMessage;
+
+ if( ConfigurationManager.AppSettings["Host"] != null )
+ {
+ host = ConfigurationManager.AppSettings["Host"];
+ }
+ if (ConfigurationManager.AppSettings["Port"] != null)
+ {
+ port = ConfigurationManager.AppSettings["Port"];
+ }
+ if (ConfigurationManager.AppSettings["VirtualHost"] != null)
+ {
+ virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ }
+ if (ConfigurationManager.AppSettings["Username"] != null)
+ {
+ username = ConfigurationManager.AppSettings["UserName"];
+ }
+ if (ConfigurationManager.AppSettings["Password"] != null)
+ {
+ password = ConfigurationManager.AppSettings["Password"];
+ }
+ if (ConfigurationManager.AppSettings["ProcessorAssembly"] != null)
+ {
+ try
+ {
+ Assembly a = Assembly.LoadFrom(ConfigurationManager.AppSettings["ProcessorAssembly"]);
+ Object o = a.CreateInstance(ConfigurationManager.AppSettings["ProcessorClass"]);
+ MessageProcessor p = (MessageProcessor) o;
+ _messageProcessor = p.ProcessMessage;
+ }
+ catch (Exception e)
+ {
+ System.Windows.Forms.MessageBox.Show("Error: \n" + e.StackTrace);
+ return 0;
+ }
+ }
+
+ System.Windows.Forms.MessageBox.Show("Connection parameters: \n host: " + host + "\n port: "
+ + port + "\n user: " + username);
+ try
+ {
+ _client = new Client();
+ _client.Connect(host, Convert.ToInt16(port), virtualhost, username, password);
+ // create a session
+ _session = _client.CreateSession(0);
+ }
+ catch (Exception e)
+ {
+ System.Windows.Forms.MessageBox.Show("Error: \n" + e.StackTrace);
+ return 0;
+ }
+
+ // always successful
+ return 1;
+ }
+
+ /// <summary>
+ /// Called whenever Excel requests a new RTD topic from the RealTimeData server.
+ /// </summary>
+ /// <param name="TopicID"></param>
+ /// <param name="Strings"></param>
+ /// <param name="GetNewValues"></param>
+ /// <returns></returns>
+ public object ConnectData(int TopicID, ref Array Strings, ref bool GetNewValues)
+ {
+ try
+ {
+ string queuename = "defaultExcelAddInQueue";
+ string destinationName = "ExcelAddIn-" + queuename;
+ if( Strings.Length > 0 )
+ {
+ queuename = (string) Strings.GetValue(0);
+ }
+ // Error message if the queue does not exist
+ QueueQueryResult result = (QueueQueryResult)_session.QueueQuery(queuename).Result;
+ if( result.GetQueue() == null )
+ {
+ System.Windows.Forms.MessageBox.Show("Error: \n queue " + queuename + " does not exist");
+ return "error";
+ }
+
+ QpidListener listener;
+ _topicMessages.Add(TopicID, null);
+ _topicQueueName.Add(TopicID, queuename);
+ if (_queueListener.ContainsKey(queuename))
+ {
+ listener = _queueListener[queuename];
+ listener.addTopic(TopicID);
+ }
+ else
+ {
+ listener = new QpidListener(this);
+ listener.addTopic(TopicID);
+ _queueListener.Add(queuename, listener);
+ _session.AttachMessageListener(listener, destinationName);
+ _session.MessageSubscribe(queuename, destinationName, MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED, null, 0, null);
+ // issue credits
+ _session.MessageSetFlowMode(destinationName, MessageFlowMode.WINDOW);
+ _session.MessageFlow(destinationName, MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ _session.MessageFlow(destinationName, MessageCreditUnit.MESSAGE, 1000);
+ _session.Sync();
+ }
+ }
+ catch (Exception e)
+ {
+ System.Windows.Forms.MessageBox.Show("Error: \n" + e.StackTrace);
+ return "error";
+ }
+ return "waiting";
+ }
+
+ /// <summary>
+ /// Called whenever Excel no longer requires a specific topic.
+ /// </summary>
+ /// <param name="TopicID"></param>
+ public void DisconnectData(int TopicID)
+ {
+ _topicMessages.Remove(TopicID);
+ string queueName = _topicQueueName[TopicID];
+ if (_topicQueueName.Remove(TopicID) && !_topicQueueName.ContainsValue(queueName))
+ {
+ _session.MessageStop("ExcelAddIn-" + queueName);
+ _session.MessageListeners.Remove("ExcelAddIn-" + queueName);
+ }
+ }
+
+ public int Heartbeat()
+ {
+ return 1;
+ }
+
+ public Array RefreshData(ref int TopicCount)
+ {
+ Array result = new object[2, _topicMessages.Count];
+ foreach (KeyValuePair<int, IMessage> pair in _topicMessages)
+ {
+ result.SetValue(pair.Key, 0, pair.Key);
+ string value = _messageProcessor(pair.Value);
+ result.SetValue(value, 1, pair.Key);
+ }
+ TopicCount = _topicMessages.Count;
+ return result;
+ }
+
+ public void ServerTerminate()
+ {
+
+ }
+
+ #endregion
+ //END IRTDServer METHODS
+
+ private string getMessage(IMessage m)
+ {
+ string res;
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ res = enc.GetString(body);
+ return res;
+ }
+
+ }
+
+ class QpidListener : IMessageListener
+ {
+ private readonly ExcelAddIn _excel;
+ private readonly List<int> _topics = new List<int>();
+
+ public QpidListener(ExcelAddIn excel)
+ {
+ _excel = excel;
+ }
+
+ public void addTopic(int topic)
+ {
+ _topics.Add(topic);
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ foreach (int i in _topics)
+ {
+ if (_excel.TopicMessages.ContainsKey(i))
+ {
+ _excel.TopicMessages[i] = m;
+ }
+ }
+ // ack this message
+ RangeSet rs = new RangeSet();
+ rs.Add(m.Id);
+ _excel.Session.MessageAccept(rs);
+ _excel.OnMessage.UpdateNotify();
+ }
+ }
+}
diff --git a/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.csproj b/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.csproj
new file mode 100644
index 0000000000..b44bf9cc69
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddIn/ExcelAddIn.csproj
@@ -0,0 +1,89 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85EFD719-39F6-4471-90FF-9E621430344B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ExcelAddIn</RootNamespace>
+ <AssemblyName>Qpid Excel AddIn</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <RegisterForComInterop>true</RegisterForComInterop>
+ <DocumentationFile>bin\Debug\Qpid Excel AddIn.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Office.Interop.Excel, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/addins/ExcelAddIn/Properties/AssemblyInfo.cs b/dotnet/client-010/addins/ExcelAddIn/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..67e95f69a3
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddIn/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid Excel AddIn")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid Excel AddIn")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3bbd4414-60df-407f-9c64-c14b221167af")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/addins/ExcelAddInMessageProcessor/ExcelAddInMessageProcessor.csproj b/dotnet/client-010/addins/ExcelAddInMessageProcessor/ExcelAddInMessageProcessor.csproj
new file mode 100644
index 0000000000..447ded4b55
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInMessageProcessor/ExcelAddInMessageProcessor.csproj
@@ -0,0 +1,86 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C2AE83A3-D5D1-469D-8611-A4738B9997CF}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ExcelAddInMessageProcessor</RootNamespace>
+ <AssemblyName>ExcelAddInMessageProcessor</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\ExcelAddIn\ExcelAddIn.csproj">
+ <Project>{85EFD719-39F6-4471-90FF-9E621430344B}</Project>
+ <Name>ExcelAddIn</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/addins/ExcelAddInMessageProcessor/Processor.cs b/dotnet/client-010/addins/ExcelAddInMessageProcessor/Processor.cs
new file mode 100644
index 0000000000..e414da131f
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInMessageProcessor/Processor.cs
@@ -0,0 +1,44 @@
+/*
+*
+* 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.
+*
+*/
+
+using System.IO;
+using System.Text;
+using org.apache.qpid.client;
+
+namespace ExcelAddInMessageProcessor
+{
+ class Processor : ExcelAddIn.MessageProcessor
+ {
+ public string ProcessMessage(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string res = enc.GetString(body);
+ if (m.ApplicationHeaders.ContainsKey("price"))
+ {
+ res = res + ": price: " + m.ApplicationHeaders["price"];
+ }
+ return res;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/addins/ExcelAddInMessageProcessor/Properties/AssemblyInfo.cs b/dotnet/client-010/addins/ExcelAddInMessageProcessor/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..302007674f
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInMessageProcessor/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ExcelAddInMessageProcessor")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("ExcelAddInMessageProcessor")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d20b2d75-7b8b-4f7d-8a81-40a4cce94195")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/addins/ExcelAddInProducer/ExcelAddInProducer.csproj b/dotnet/client-010/addins/ExcelAddInProducer/ExcelAddInProducer.csproj
new file mode 100644
index 0000000000..d9b1b63737
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInProducer/ExcelAddInProducer.csproj
@@ -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.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{80F00C3B-EB38-4B3B-9F77-68977A30B155}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ExcelAddInProducer</RootNamespace>
+ <AssemblyName>Qpid Excel AddIn Producer</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/addins/ExcelAddInProducer/Program.cs b/dotnet/client-010/addins/ExcelAddInProducer/Program.cs
new file mode 100644
index 0000000000..a8bbdf2fbd
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInProducer/Program.cs
@@ -0,0 +1,62 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Configuration;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+
+namespace ExcelAddInProducer
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client client = new Client();
+ Console.WriteLine("Client created");
+ client.Connect(host, port, virtualhost, username, password);
+ Console.WriteLine("Connection established");
+
+ IClientSession ssn = client.CreateSession(50000);
+ Console.WriteLine("Session created");
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+ IMessage message = new Message();
+ message.ApplicationHeaders.Add("price", 0);
+ for (int i = 0; i < 100; i++)
+ {
+ message.ClearData();
+ message.AppendData( Encoding.UTF8.GetBytes("test: " + i));
+ message.ApplicationHeaders["price"] = i;
+ ssn.MessageTransfer("amq.direct", "queue1", message);
+ Thread.Sleep(1000);
+ }
+
+ client.Close();
+ }
+ }
+}
diff --git a/dotnet/client-010/addins/ExcelAddInProducer/Properties/AssemblyInfo.cs b/dotnet/client-010/addins/ExcelAddInProducer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..28fe3427cb
--- /dev/null
+++ b/dotnet/client-010/addins/ExcelAddInProducer/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid Excel AddIn Producer")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid Excel AddIn Producer")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3416a5c2-eb70-4d77-b401-dfa659bd419e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/addins/README.txt b/dotnet/client-010/addins/README.txt
new file mode 100644
index 0000000000..5f8df77189
--- /dev/null
+++ b/dotnet/client-010/addins/README.txt
@@ -0,0 +1,29 @@
+This project contains three sub-projects:
+- The RTD excell Addin
+- A sample client sending messages to queue1
+- A ample message processor
+
+RDT AddIn
+Excel provides a function called RTD (real-time data) that lets you specify a COM server via its ProgId here "Qpid" so that you can push qpid messages into Excel.
+For using the Qpid RTD follows those steps:
+
+1) Copy the configuration Excel.exe.config into C:\Program Files\Microsoft Office\Office12
+2) Edit Excel.exe.xml and set the targeted Qpid broker host, port number
+3) Select the cell or cell range to contain the information
+4) enter the following formula =rtd("Qpid",,"myQueue") Where MyQueue is the queue from which you wish to receive messages from
+
+Note: The Qpid RTD is a COM-AddIn that must be registered with Excel. This is done automatically when compiling the Addin with visual studio.
+
+The default behavior of the RDT AddIn is to display the message payload. This could be altered by specifying your own message processor.
+A Message processor is a class that implements the API ExcelAddIn.MessageProcessor. For example, the provided processor in client-010\addins\ExcelAddInMessageProcessor displays the message body and the the header price when specified.
+
+To use you own message processor follows those steps:
+1) Write your own message processor that extends ExcelAddIn.MessageProcessor
+2) Edit Excel.exe.config and uncomment the entries:
+ <add key="ProcessorAssembly" value="<path>\qpid\dotnet\client-010\addins\ExcelAddInMessageProcessor\bin\Debug\ExcelAddInMessageProcessor.dll"/>
+ <add key="ProcessorClass" value="ExcelAddInMessageProcessor.Processor"/>
+- ProcessorAssembly is the path on the Assembly that contains your processor class
+- ProcessorClass is your processor class name
+3) run excel and define a rtd function
+
+Note: the provided ExcelAddInProducer can be used for testing the provided message processor. As messages are sent to queue1 the following rtd fucntion should be used =rtd("Qpiud",,"queue1") \ No newline at end of file
diff --git a/dotnet/client-010/client/Client.csproj b/dotnet/client-010/client/Client.csproj
new file mode 100644
index 0000000000..000407da59
--- /dev/null
+++ b/dotnet/client-010/client/Client.csproj
@@ -0,0 +1,242 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B911FFD7-754F-4735-A188-218D5065BE79}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>client</RootNamespace>
+ <AssemblyName>Qpid Client</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="client\Client.cs" />
+ <Compile Include="client\ClientConnectionDelegate.cs" />
+ <Compile Include="client\ClientSession.cs" />
+ <Compile Include="client\ClientSessionDelegate.cs" />
+ <Compile Include="client\ErrorCode.cs" />
+ <Compile Include="client\IClient.cs" />
+ <Compile Include="client\IClientSession.cs" />
+ <Compile Include="client\IClosedListener.cs" />
+ <Compile Include="client\IMessage.cs" />
+ <Compile Include="client\Message.cs" />
+ <Compile Include="client\IMessageListener.cs" />
+ <Compile Include="generated\Acquired.cs" />
+ <Compile Include="generated\ConnectionClose.cs" />
+ <Compile Include="generated\ConnectionCloseCode.cs" />
+ <Compile Include="generated\ConnectionCloseOk.cs" />
+ <Compile Include="generated\ConnectionHeartbeat.cs" />
+ <Compile Include="generated\ConnectionOpen.cs" />
+ <Compile Include="generated\ConnectionOpenOk.cs" />
+ <Compile Include="generated\ConnectionRedirect.cs" />
+ <Compile Include="generated\ConnectionSecure.cs" />
+ <Compile Include="generated\ConnectionSecureOk.cs" />
+ <Compile Include="generated\ConnectionStart.cs" />
+ <Compile Include="generated\ConnectionStartOk.cs" />
+ <Compile Include="generated\ConnectionTune.cs" />
+ <Compile Include="generated\ConnectionTuneOk.cs" />
+ <Compile Include="generated\Constant.cs" />
+ <Compile Include="generated\DeliveryProperties.cs" />
+ <Compile Include="generated\DtxCommit.cs" />
+ <Compile Include="generated\DtxEnd.cs" />
+ <Compile Include="generated\DtxForget.cs" />
+ <Compile Include="generated\DtxGetTimeout.cs" />
+ <Compile Include="generated\DtxPrepare.cs" />
+ <Compile Include="generated\DtxRecover.cs" />
+ <Compile Include="generated\DtxRollback.cs" />
+ <Compile Include="generated\DtxSelect.cs" />
+ <Compile Include="generated\DtxSetTimeout.cs" />
+ <Compile Include="generated\DtxStart.cs" />
+ <Compile Include="generated\DtxXaStatus.cs" />
+ <Compile Include="generated\ExchangeBind.cs" />
+ <Compile Include="generated\ExchangeBound.cs" />
+ <Compile Include="generated\ExchangeBoundResult.cs" />
+ <Compile Include="generated\ExchangeDeclare.cs" />
+ <Compile Include="generated\ExchangeDelete.cs" />
+ <Compile Include="generated\ExchangeQuery.cs" />
+ <Compile Include="generated\ExchangeQueryResult.cs" />
+ <Compile Include="generated\ExchangeUnbind.cs" />
+ <Compile Include="generated\ExecutionErrorCode.cs" />
+ <Compile Include="generated\ExecutionException.cs" />
+ <Compile Include="generated\ExecutionResult.cs" />
+ <Compile Include="generated\ExecutionSync.cs" />
+ <Compile Include="generated\FileReturnCode.cs" />
+ <Compile Include="generated\FragmentProperties.cs" />
+ <Compile Include="generated\GetTimeoutResult.cs" />
+ <Compile Include="generated\IInvoker.cs" />
+ <Compile Include="generated\Invoker.cs" />
+ <Compile Include="generated\MessageAccept.cs" />
+ <Compile Include="generated\MessageAcceptMode.cs" />
+ <Compile Include="generated\MessageAcquire.cs" />
+ <Compile Include="generated\MessageAcquireMode.cs" />
+ <Compile Include="generated\MessageCancel.cs" />
+ <Compile Include="generated\MessageCreditUnit.cs" />
+ <Compile Include="generated\MessageDeliveryMode.cs" />
+ <Compile Include="generated\MessageDeliveryPriority.cs" />
+ <Compile Include="generated\MessageFlow.cs" />
+ <Compile Include="generated\MessageFlowMode.cs" />
+ <Compile Include="generated\MessageFlush.cs" />
+ <Compile Include="generated\MessageProperties.cs" />
+ <Compile Include="generated\MessageReject.cs" />
+ <Compile Include="generated\MessageRejectCode.cs" />
+ <Compile Include="generated\MessageRelease.cs" />
+ <Compile Include="generated\MessageResume.cs" />
+ <Compile Include="generated\MessageResumeResult.cs" />
+ <Compile Include="generated\MessageSetFlowMode.cs" />
+ <Compile Include="generated\MessageStop.cs" />
+ <Compile Include="generated\MessageSubscribe.cs" />
+ <Compile Include="generated\MessageTransfer.cs" />
+ <Compile Include="generated\MethodDelegate.cs" />
+ <Compile Include="generated\Option.cs" />
+ <Compile Include="generated\QueueDeclare.cs" />
+ <Compile Include="generated\QueueDelete.cs" />
+ <Compile Include="generated\QueuePurge.cs" />
+ <Compile Include="generated\QueueQuery.cs" />
+ <Compile Include="generated\QueueQueryResult.cs" />
+ <Compile Include="generated\RecoverResult.cs" />
+ <Compile Include="generated\ReplyTo.cs" />
+ <Compile Include="generated\SegmentType.cs" />
+ <Compile Include="generated\SessionAttach.cs" />
+ <Compile Include="generated\SessionAttached.cs" />
+ <Compile Include="generated\SessionCommandFragment.cs" />
+ <Compile Include="generated\SessionCommandPoint.cs" />
+ <Compile Include="generated\SessionCompleted.cs" />
+ <Compile Include="generated\SessionConfirmed.cs" />
+ <Compile Include="generated\SessionDetach.cs" />
+ <Compile Include="generated\SessionDetachCode.cs" />
+ <Compile Include="generated\SessionDetached.cs" />
+ <Compile Include="generated\SessionExpected.cs" />
+ <Compile Include="generated\SessionFlush.cs" />
+ <Compile Include="generated\SessionGap.cs" />
+ <Compile Include="generated\SessionHeader.cs" />
+ <Compile Include="generated\SessionKnownCompleted.cs" />
+ <Compile Include="generated\SessionRequestTimeout.cs" />
+ <Compile Include="generated\SessionTimeout.cs" />
+ <Compile Include="generated\StreamReturnCode.cs" />
+ <Compile Include="generated\StructFactory.cs" />
+ <Compile Include="generated\Track.cs" />
+ <Compile Include="generated\TxCommit.cs" />
+ <Compile Include="generated\TxRollback.cs" />
+ <Compile Include="generated\TxSelect.cs" />
+ <Compile Include="generated\Type.cs" />
+ <Compile Include="generated\XaResult.cs" />
+ <Compile Include="generated\Xid.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="transport\Binary.cs" />
+ <Compile Include="transport\IBinding.cs" />
+ <Compile Include="transport\Channel.cs" />
+ <Compile Include="transport\ChannelDelegate.cs" />
+ <Compile Include="transport\ClientDelegate.cs" />
+ <Compile Include="transport\codec\AbstractDecoder.cs" />
+ <Compile Include="transport\codec\AbstractEncoder.cs" />
+ <Compile Include="transport\codec\IDecoder.cs" />
+ <Compile Include="transport\codec\IEncodable.cs" />
+ <Compile Include="transport\codec\IEncoder.cs" />
+ <Compile Include="transport\codec\MSDecoder.cs" />
+ <Compile Include="transport\codec\MSEncoder.cs" />
+ <Compile Include="transport\Connection.cs" />
+ <Compile Include="transport\ConnectionDelegate.cs" />
+ <Compile Include="transport\exception\ConnectionException.cs" />
+ <Compile Include="transport\exception\ExceptionArgs.cs" />
+ <Compile Include="transport\exception\ProtocolVersionException.cs" />
+ <Compile Include="transport\exception\SessionClosedException.cs" />
+ <Compile Include="transport\exception\SessionException.cs" />
+ <Compile Include="transport\exception\TransportException.cs" />
+ <Compile Include="transport\Field.cs" />
+ <Compile Include="transport\IFuture.cs" />
+ <Compile Include="transport\Header.cs" />
+ <Compile Include="transport\ISession.cs" />
+ <Compile Include="transport\Method.cs" />
+ <Compile Include="transport\network\Assembler.cs" />
+ <Compile Include="transport\network\Disassembler.cs" />
+ <Compile Include="transport\network\Frame.cs" />
+ <Compile Include="transport\network\io\IIoSender.cs" />
+ <Compile Include="transport\network\InputHandler.cs" />
+ <Compile Include="transport\network\io\IIoTransport.cs" />
+ <Compile Include="transport\network\io\IoReceiver.cs" />
+ <Compile Include="transport\network\io\IoSender.cs" />
+ <Compile Include="transport\network\io\IoSSLTransport.cs" />
+ <Compile Include="transport\network\io\IoTransport.cs" />
+ <Compile Include="transport\network\INetworkDelegate.cs" />
+ <Compile Include="transport\network\INetworkEvent.cs" />
+ <Compile Include="transport\IProtocolDelegate.cs" />
+ <Compile Include="transport\ProtocolError.cs" />
+ <Compile Include="transport\IProtocolEvent.cs" />
+ <Compile Include="transport\ProtocolHeader.cs" />
+ <Compile Include="transport\Range.cs" />
+ <Compile Include="transport\RangeSet.cs" />
+ <Compile Include="transport\ReceivedPayload.cs" />
+ <Compile Include="transport\IReceiver.cs" />
+ <Compile Include="transport\ISender.cs" />
+ <Compile Include="transport\Session.cs" />
+ <Compile Include="transport\SessionDelegate.cs" />
+ <Compile Include="transport\Struct.cs" />
+ <Compile Include="transport\util\ByteEncoder.cs" />
+ <Compile Include="transport\util\CircularBuffer.cs" />
+ <Compile Include="transport\util\Functions.cs" />
+ <Compile Include="transport\util\Logger.cs" />
+ <Compile Include="transport\util\ResultFuture.cs" />
+ <Compile Include="transport\util\Serial.cs" />
+ <Compile Include="transport\util\UUID.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/client/Properties/AssemblyInfo.cs b/dotnet/client-010/client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..2b6c525b86
--- /dev/null
+++ b/dotnet/client-010/client/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid Client")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid Client")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("dac7ef42-e9c8-45a5-8050-1301b6f8160e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/client/client.sln b/dotnet/client-010/client/client.sln
new file mode 100644
index 0000000000..37455fd177
--- /dev/null
+++ b/dotnet/client-010/client/client.sln
@@ -0,0 +1,129 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+
+#
+# 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
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client.csproj", "{B911FFD7-754F-4735-A188-218D5065BE79}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "..\demo\Demo.csproj", "{E4C46FBC-7560-406D-BFEF-CA010E584DF4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelAddIn", "..\addins\ExcelAddIn\ExcelAddIn.csproj", "{85EFD719-39F6-4471-90FF-9E621430344B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelAddInProducer", "..\addins\ExcelAddInProducer\ExcelAddInProducer.csproj", "{80F00C3B-EB38-4B3B-9F77-68977A30B155}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-direct-producer", "..\examples\direct\example-direct-producer\example-direct-producer.csproj", "{96FCB250-8142-40EE-9BDD-CA839EE21021}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-direct-Listener", "..\examples\direct\example-direct-Listener\example-direct-Listener.csproj", "{AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-pub-sub-Listener", "..\examples\pub-sub\example-pub-sub-Listener\example-pub-sub-Listener.csproj", "{2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-pub-sub-Publisher", "..\examples\pub-sub\example-pub-sub-Publisher\example-pub-sub-Publisher.csproj", "{F8857634-A134-44E7-A953-F2B22688C599}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "..\test\Test.csproj", "{95CB4C90-7C53-44A9-B11C-96235F158ACA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-request-response-Client", "..\examples\request-response\example-request-response-Client\example-request-response-Client.csproj", "{1BC63815-4029-4039-9207-35E7E06ECC99}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-request-response-Server", "..\examples\request-response\example-request-response-Server\example-request-response-Server.csproj", "{922FBA9C-E483-4AEF-ABE8-AC87421E829B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-fanout-Producer", "..\examples\fanout\example-fanout-Producer\example-fanout-Producer.csproj", "{4513BF94-D54A-42FE-8506-FE2CD57B2C51}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-fanout-Listener", "..\examples\fanout\example-fanout-Listener\example-fanout-Listener.csproj", "{18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "perftest", "..\perftest\perftest.csproj", "{7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelAddInMessageProcessor", "..\addins\ExcelAddInMessageProcessor\ExcelAddInMessageProcessor.csproj", "{C2AE83A3-D5D1-469D-8611-A4738B9997CF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3CE4FA2A-393F-4DED-ABDF-1BC2F253ACA8}"
+ ProjectSection(SolutionItems) = preProject
+ ..\App.config = ..\App.config
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E4C46FBC-7560-406D-BFEF-CA010E584DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E4C46FBC-7560-406D-BFEF-CA010E584DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E4C46FBC-7560-406D-BFEF-CA010E584DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E4C46FBC-7560-406D-BFEF-CA010E584DF4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {85EFD719-39F6-4471-90FF-9E621430344B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {85EFD719-39F6-4471-90FF-9E621430344B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {85EFD719-39F6-4471-90FF-9E621430344B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {85EFD719-39F6-4471-90FF-9E621430344B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {80F00C3B-EB38-4B3B-9F77-68977A30B155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {80F00C3B-EB38-4B3B-9F77-68977A30B155}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {80F00C3B-EB38-4B3B-9F77-68977A30B155}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {80F00C3B-EB38-4B3B-9F77-68977A30B155}.Release|Any CPU.Build.0 = Release|Any CPU
+ {96FCB250-8142-40EE-9BDD-CA839EE21021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {96FCB250-8142-40EE-9BDD-CA839EE21021}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {96FCB250-8142-40EE-9BDD-CA839EE21021}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {96FCB250-8142-40EE-9BDD-CA839EE21021}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F8857634-A134-44E7-A953-F2B22688C599}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F8857634-A134-44E7-A953-F2B22688C599}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F8857634-A134-44E7-A953-F2B22688C599}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F8857634-A134-44E7-A953-F2B22688C599}.Release|Any CPU.Build.0 = Release|Any CPU
+ {95CB4C90-7C53-44A9-B11C-96235F158ACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {95CB4C90-7C53-44A9-B11C-96235F158ACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {95CB4C90-7C53-44A9-B11C-96235F158ACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {95CB4C90-7C53-44A9-B11C-96235F158ACA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1BC63815-4029-4039-9207-35E7E06ECC99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1BC63815-4029-4039-9207-35E7E06ECC99}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1BC63815-4029-4039-9207-35E7E06ECC99}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1BC63815-4029-4039-9207-35E7E06ECC99}.Release|Any CPU.Build.0 = Release|Any CPU
+ {922FBA9C-E483-4AEF-ABE8-AC87421E829B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {922FBA9C-E483-4AEF-ABE8-AC87421E829B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {922FBA9C-E483-4AEF-ABE8-AC87421E829B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {922FBA9C-E483-4AEF-ABE8-AC87421E829B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4513BF94-D54A-42FE-8506-FE2CD57B2C51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4513BF94-D54A-42FE-8506-FE2CD57B2C51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4513BF94-D54A-42FE-8506-FE2CD57B2C51}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4513BF94-D54A-42FE-8506-FE2CD57B2C51}.Release|Any CPU.Build.0 = Release|Any CPU
+ {18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2AE83A3-D5D1-469D-8611-A4738B9997CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2AE83A3-D5D1-469D-8611-A4738B9997CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2AE83A3-D5D1-469D-8611-A4738B9997CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2AE83A3-D5D1-469D-8611-A4738B9997CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/client-010/client/client.suo b/dotnet/client-010/client/client.suo
new file mode 100644
index 0000000000..0640275f99
--- /dev/null
+++ b/dotnet/client-010/client/client.suo
Binary files differ
diff --git a/dotnet/client-010/client/client/Client.cs b/dotnet/client-010/client/client/Client.cs
new file mode 100644
index 0000000000..fc9ff22191
--- /dev/null
+++ b/dotnet/client-010/client/client/Client.cs
@@ -0,0 +1,195 @@
+/*
+* 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.
+*/
+using System;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.network.io;
+using org.apache.qpid.transport.util;
+using System.Security.Cryptography.X509Certificates;
+
+namespace org.apache.qpid.client
+{
+ public class Client : IClient
+ {
+ private Connection _conn;
+ private static readonly Logger _log = Logger.Get(typeof (Client));
+ private const long timeout = 60000;
+ private bool _isClosed;
+ private readonly Object _closeOK;
+ private IClosedListener _closedListner;
+
+ public event EventHandler<ExceptionArgs> ExceptionRaised;
+ public event EventHandler ConnectionOpenOK;
+ public event EventHandler ConnectionLost;
+
+ public bool IsClosed
+ {
+ get { return _isClosed; }
+ set
+ {
+ _isClosed = value;
+ if(_isClosed && ConnectionLost != null)
+ ConnectionLost(this, EventArgs.Empty);
+ }
+ }
+
+ public Object CloseOk
+ {
+ get { return _closeOK; }
+ }
+
+ public Client()
+ {
+ _isClosed = false;
+ _closeOK = new object();
+ }
+
+ #region Interface IClient
+
+ public void Connect(String host, int port, String virtualHost, String username, String password)
+ {
+ Connect(host, port, virtualHost, username, password, "PLAIN");
+ }
+
+ /// <summary>
+ /// Establishes a connection with a broker using the provided user auths
+ ///
+ /// </summary>
+ /// <param name="host">Host name on which a broker is deployed</param>
+ /// <param name="port">Broker port </param>
+ /// <param name="virtualHost">virtual host name</param>
+ /// <param name="username">User Name</param>
+ /// <param name="password">Password</param>
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
+ public void Connect(String host, int port, String virtualHost, String username, String password, String mechanism)
+ {
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}; mechanism {4}",
+ host, port, virtualHost, username, mechanism));
+ ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(this, username, password, mechanism);
+ ManualResetEvent negotiationComplete = new ManualResetEvent(false);
+ connectionDelegate.SetCondition(negotiationComplete);
+ connectionDelegate.VirtualHost = virtualHost;
+ _conn = IoTransport.Connect(host, port, connectionDelegate);
+
+ _conn.Send(new ProtocolHeader(1, 0, 10));
+ negotiationComplete.WaitOne();
+
+ if (connectionDelegate.Exception != null)
+ throw connectionDelegate.Exception;
+
+ connectionDelegate.SetCondition(null);
+
+ }
+
+ /// <summary>
+ /// Establishes a connection with a broker using SSL
+ ///
+ /// </summary>
+ /// <param name="host">Host name on which a broker is deployed</param>
+ /// <param name="port">Broker port </param>
+ /// <param name="virtualHost">virtual host name</param>
+ /// <param name="username">User Name</param>
+ /// <param name="password">Password</param>
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
+ /// <param name="serverName">Name of the SSL server</param>
+ /// <param name="certPath">Path to the X509 certificate to be used for client authentication</param>
+ /// <param name="certPass">Password to certificate file, pass null if no password is required</param>
+ /// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
+ public void ConnectSSL(String host, int port, String virtualHost, String username, String password, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted)
+ {
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; virtualHost {2}; username {3}; mechanism {4}",
+ host, port, virtualHost, username, mechanism));
+ _log.Debug(String.Format("SSL parameters: serverName: {0}; certPath: {1}; rejectUntrusted: {2}", serverName, certPath, rejectUntrusted));
+ _conn = IoSSLTransport.Connect(host, port, virtualHost, mechanism, serverName, certPath, certPass, rejectUntrusted, this);
+ }
+
+ /// <summary>
+ /// Establishes a connection with a broker using SSL
+ ///
+ /// </summary>
+ /// <param name="host">Host name on which a broker is deployed</param>
+ /// <param name="port">Broker port </param>
+ /// <param name="mechanism">SASL authentication mechanism, possible values: PLAIN, EXTERNAL, DIGEST-MD5, ANONYMOUS</param>
+ /// <param name="certificate">X509 certificate to be used for client authentication</param>
+ /// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
+ public void ConnectSSL(String host, int port, String mechanism, X509Certificate certificate, bool rejectUntrusted)
+ {
+ _log.Debug(String.Format("Client Connecting to host {0}; port {1}; mechanism {2}",
+ host, port, mechanism));
+ _log.Debug(String.Format("SSL parameters: certSubject: {0}; rejectUntrusted: {1}",
+ certificate.Subject, rejectUntrusted));
+
+ _conn = IoSSLTransport.Connect(host, port, mechanism, certificate, rejectUntrusted, this);
+ }
+
+ public void Close()
+ {
+ Channel ch = _conn.GetChannel(0);
+ ch.ConnectionClose(ConnectionCloseCode.NORMAL, "client is closing");
+ lock (CloseOk)
+ {
+ DateTime start = DateTime.Now;
+ long elapsed = 0;
+ while (!IsClosed && elapsed < timeout)
+ {
+ Monitor.Wait(CloseOk, (int) (timeout - elapsed));
+ elapsed = DateTime.Now.Subtract(start).Milliseconds;
+ }
+ if (!IsClosed)
+ {
+ throw new Exception("Timed out when closing connection");
+ }
+ _conn.Close();
+ }
+ }
+
+ public IClientSession CreateSession(long expiryInSeconds)
+ {
+ Channel ch = _conn.GetChannel();
+ ClientSession ssn = new ClientSession(Encoding.UTF8.GetBytes(UUID.RandomUuid().ToString()));
+ ssn.Attach(ch);
+ ssn.SessionAttach(ssn.GetName());
+ ssn.SessionRequestTimeout(expiryInSeconds);
+ return ssn;
+ }
+
+ public IClosedListener ClosedListener
+ {
+ set { _closedListner = value; }
+ get { return _closedListner; }
+ }
+
+ #endregion
+
+ public void RaiseException(Exception exception)
+ {
+ if (ExceptionRaised != null)
+ ExceptionRaised(this, new ExceptionArgs(exception));
+ }
+
+ internal void ConnectionOpenOk(Channel context, ConnectionOpenOk mstruct)
+ {
+ if (ConnectionOpenOK != null)
+ {
+ ConnectionOpenOK(this, new EventArgs());
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/client/ClientConnectionDelegate.cs b/dotnet/client-010/client/client/ClientConnectionDelegate.cs
new file mode 100644
index 0000000000..83aac80e83
--- /dev/null
+++ b/dotnet/client-010/client/client/ClientConnectionDelegate.cs
@@ -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.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.client
+{
+ internal class ClientConnectionDelegate : ClientDelegate
+ {
+ private static readonly Logger log = Logger.Get(typeof (ClientConnectionDelegate));
+ private readonly Client _client;
+ private string _username;
+ private string _password;
+
+ // PLAIN SASL mechanism by default
+ private string _mechanism = "PLAIN";
+ private Exception _exception;
+
+ public ClientConnectionDelegate(Client client, string username, string pasword)
+ {
+ _client = client;
+ _username = username;
+ _password = pasword;
+ }
+
+ public ClientConnectionDelegate(Client client, string username, string pasword, string mechanism)
+ : this(client, username, pasword)
+ {
+ _mechanism = mechanism;
+ }
+
+ public Exception Exception
+ {
+ get { return _exception; }
+ }
+
+ public override SessionDelegate GetSessionDelegate()
+ {
+ return new ClientSessionDelegate();
+ }
+
+ public override void RaiseException(Exception exception)
+ {
+ _exception = exception;
+
+ if (_negotiationComplete != null)
+ _negotiationComplete.Set();
+ else
+ _client.RaiseException(exception);
+ }
+
+ public override void ConnectionStart(Channel context, ConnectionStart mystruct)
+ {
+ MemoryStream stResponse = new MemoryStream();
+
+ // do not send username and password for EXTERNAL mechanism,
+ // because they are inside a certificate file
+ if (_mechanism != "EXTERNAL")
+ {
+ byte[] part = Encoding.UTF8.GetBytes(_username);
+ stResponse.WriteByte(0);
+ stResponse.Write(part, 0, part.Length);
+ stResponse.WriteByte(0);
+ part = Encoding.UTF8.GetBytes(_password);
+ stResponse.Write(part, 0, part.Length);
+ }
+ Dictionary<String, Object> props = new Dictionary<String, Object>();
+ context.ConnectionStartOk(props, _mechanism, stResponse.ToArray(), "utf8");
+ }
+
+ public override void ConnectionOpenOk(Channel context, ConnectionOpenOk mstruct)
+ {
+ base.ConnectionOpenOk(context, mstruct);
+ _client.ConnectionOpenOk(context, mstruct);
+ }
+
+ public override void Closed()
+ {
+ log.Debug("Delegate Closed");
+ lock (_client.CloseOk)
+ {
+ try
+ {
+ _client.IsClosed = true;
+ Monitor.PulseAll(_client.CloseOk);
+ }
+ catch (Exception e)
+ {
+ throw new SystemException("Error when closing client", e);
+ }
+ }
+ }
+
+ public override void ConnectionClose(Channel context, ConnectionClose connectionClose)
+ {
+ base.ConnectionClose(context, connectionClose);
+ ErrorCode errorCode = ErrorCode.GetErrorCode((int) connectionClose.GetReplyCode());
+
+ if(_client.ClosedListener != null)
+ _client.ClosedListener.OnClosed(errorCode, connectionClose.GetReplyText(), null);
+
+ if (errorCode.Code != (int)QpidErrorCode.NO_ERROR)
+ throw new Exception ("Server Closed the connection: Reason " + connectionClose.GetReplyText());
+ }
+ }
+}
diff --git a/dotnet/client-010/client/client/ClientInterface.cs b/dotnet/client-010/client/client/ClientInterface.cs
new file mode 100644
index 0000000000..fcf7ae9f31
--- /dev/null
+++ b/dotnet/client-010/client/client/ClientInterface.cs
@@ -0,0 +1,59 @@
+/*
+* 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.
+*/
+
+using System;
+
+namespace org.apache.qpid.client
+{
+ public interface ClientInterface
+ {
+ /// <summary>
+ /// Establish a connection with the broker using the given parameters
+ ///
+ /// </summary>
+ /// <param name="host">host name</param>
+ /// <param name="port">port number</param>
+ /// <param name="virtualHost">virtualHost the virtual host name</param>
+ /// <param name="username"> username user name</param>
+ /// <param name="passwor">password password</param>
+ void connect(String host, int port, String virtualHost, String username, String passwor);
+
+ /// <summary>
+ /// Close this client
+ /// </summary>
+ void close();
+
+ /// <summary>
+ /// Create a session for this connection.
+ /// The returned session is suspended
+ /// (i.e. this session is not attached to an underlying channel)
+ /// </summary>
+ /// <param name="expiryInSeconds">Expiry time expressed in seconds, if the value is less than
+ /// or equal to 0 then the session does not expire.</param>
+ /// <returns>A newly created (suspended) session.</returns>
+ ClientSession createSession(long expiryInSeconds);
+
+ /// <summary>
+ /// If the communication layer detects a serious problem with a connection, it
+ // informs the client's ClosedListener
+ /// </summary>
+ ///
+ ClosedListener ClosedListener { set; }
+ }
+}
diff --git a/dotnet/client-010/client/client/ClientSession.cs b/dotnet/client-010/client/client/ClientSession.cs
new file mode 100644
index 0000000000..190fd7c940
--- /dev/null
+++ b/dotnet/client-010/client/client/ClientSession.cs
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.client
+{
+ /// <summary> Implements a Qpid Sesion.</summary>
+ public class ClientSession : Session, IClientSession
+ {
+ public static short TRANSFER_ACQUIRE_MODE_NO_ACQUIRE = 1;
+ public static short TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE = 0;
+ public static short TRANSFER_CONFIRM_MODE_REQUIRED = 0;
+ public static short TRANSFER_CONFIRM_MODE_NOT_REQUIRED = 1;
+ public static short MESSAGE_FLOW_MODE_CREDIT = 0;
+ public static short MESSAGE_FLOW_MODE_WINDOW = 1;
+ public static short MESSAGE_FLOW_UNIT_MESSAGE = 0;
+ public static short MESSAGE_FLOW_UNIT_BYTE = 1;
+ public static long MESSAGE_FLOW_MAX_BYTES = 0xFFFFFFFF;
+ public static short MESSAGE_REJECT_CODE_GENERIC = 0;
+ public static short MESSAGE_REJECT_CODE_IMMEDIATE_DELIVERY_FAILED = 1;
+ public static short MESSAGE_ACQUIRE_ANY_AVAILABLE_MESSAGE = 0;
+ public static short MESSAGE_ACQUIRE_MESSAGES_IF_ALL_ARE_AVAILABLE = 1;
+
+ private readonly Dictionary<String, IMessageListener> _listeners = new Dictionary<String, IMessageListener>();
+
+ public ClientSession(byte[] name) : base(name)
+ {
+ }
+
+ public void AttachMessageListener(IMessageListener listener, string Destination)
+ {
+ _listeners.Add(Destination, listener);
+ }
+
+ public Dictionary<String, IMessageListener> MessageListeners
+ {
+ get { return _listeners; }
+ }
+
+ public void MessageTransfer(String destination, string routingkey, IMessage message)
+ {
+ message.DeliveryProperties.SetRoutingKey(routingkey);
+ MessageTransfer(destination, message);
+ }
+
+ public void MessageTransfer(String destination, IMessage message)
+ {
+ byte[] body = new byte[message.Body.Position];
+ message.Body.Seek(0, SeekOrigin.Begin);
+ message.Body.Read(body, 0, body.Length);
+ message.MessageProperties.SetMessageId(UUID.RandomUuid());
+ MessageTransfer(destination,
+ MessageAcceptMode.NONE,
+ MessageAcquireMode.PRE_ACQUIRED,
+ message.Header,
+ body);
+ }
+
+ public void QueueDeclare(String queue)
+ {
+ QueueDeclare(queue, null, null);
+ }
+
+ public void QueueDeclare(String queue, params Option[] options)
+ {
+ QueueDeclare(queue, null, null, options);
+ }
+
+ public void ExchangeBind(String queue, String exchange, String bindingKey)
+ {
+ ExchangeBind(queue, exchange, bindingKey, null);
+ }
+
+ public void MessageSubscribe(String queue)
+ {
+ MessageSubscribe(queue, queue, MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED, null, 0, null);
+ // issue credits
+ MessageSetFlowMode(queue, MessageFlowMode.WINDOW);
+ MessageFlow(queue, MessageCreditUnit.BYTE, MESSAGE_FLOW_MAX_BYTES);
+ MessageFlow(queue, MessageCreditUnit.MESSAGE, 10000);
+ }
+
+ }
+}
diff --git a/dotnet/client-010/client/client/ClientSessionDelegate.cs b/dotnet/client-010/client/client/ClientSessionDelegate.cs
new file mode 100644
index 0000000000..7cc4042557
--- /dev/null
+++ b/dotnet/client-010/client/client/ClientSessionDelegate.cs
@@ -0,0 +1,55 @@
+/*
+* 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.
+*/
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.client
+{
+ public class ClientSessionDelegate : SessionDelegate
+ {
+ private static readonly Logger _log = Logger.Get(typeof (ClientSessionDelegate));
+
+ // --------------------------------------------
+ // Message methods
+ // --------------------------------------------
+ public override void MessageTransfer(Session session, MessageTransfer xfr)
+ {
+ if (((ClientSession) session).MessageListeners.ContainsKey(xfr.GetDestination()))
+ {
+ IMessageListener listener = ((ClientSession)session).MessageListeners[xfr.GetDestination()];
+ listener.MessageTransfer( new Message(xfr));
+ }
+ else
+ {
+ _log.Warn("No listener set for: {0}", xfr);
+ }
+ }
+
+ public override void MessageReject(Session session, MessageReject mstruct)
+ {
+ foreach (Range range in mstruct.GetTransfers())
+ {
+ for (long l = range.Lower; l <= range.Upper; l++)
+ {
+ _log.Warn("message rejected: " + session.GetCommand((int) l));
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/client/ClosedListenerInterface.cs b/dotnet/client-010/client/client/ClosedListenerInterface.cs
new file mode 100644
index 0000000000..133b00abdd
--- /dev/null
+++ b/dotnet/client-010/client/client/ClosedListenerInterface.cs
@@ -0,0 +1,29 @@
+/*
+* 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.
+*/
+
+using System;
+
+namespace org.apache.qpid.client
+{
+ public interface ClosedListener
+ {
+
+ void onClosed(ErrorCode errorCode, String reason, Exception t);
+ }
+}
diff --git a/dotnet/client-010/client/client/ErrorCode.cs b/dotnet/client-010/client/client/ErrorCode.cs
new file mode 100644
index 0000000000..74c3daba4b
--- /dev/null
+++ b/dotnet/client-010/client/client/ErrorCode.cs
@@ -0,0 +1,140 @@
+/*
+* 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.
+*/
+
+using System;
+
+namespace org.apache.qpid.client
+{
+ public enum QpidErrorCode
+ {
+ NO_ERROR = 200,
+ CONTENT_TOO_LARGE = 311,
+ NO_ROUTE = 312,
+ NO_CONSUMERS = 313,
+ CONNECTION_FORCED = 320,
+ INVALID_PATH = 402,
+ ACCESS_REFUSED = 403,
+ NOT_FOUND = 404,
+ RESOURCE_LOCKED = 405,
+ PRE_CONDITION_FAILED = 406,
+ FRAME_ERROR = 501,
+ SYNTAX_ERROR = 502,
+ COMMAND_INVALID = 503,
+ SESSION_ERROR = 504,
+ NOT_ALLOWED = 530,
+ NOT_IMPLEMENTED = 540,
+ INTERNAL_ERROR = 541,
+ INVALID_ARGUMENT = 542,
+ UNDEFINED = 1
+ }
+
+ public struct ErrorCode
+ {
+ private int _code;
+ private String _desc;
+ private readonly bool _hardError;
+
+ public ErrorCode(int code, String desc, bool hardError)
+ {
+ _code = code;
+ _desc = desc;
+ _hardError = hardError;
+ }
+
+ public int Code
+ {
+ get { return _code; }
+ set { _code = value; }
+ }
+
+ public String Description
+ {
+ get { return _desc; }
+ set { _desc = value; }
+ }
+
+ public bool ISHardError
+ {
+ get { return _hardError; }
+ }
+
+ public static ErrorCode GetErrorCode(int code)
+ {
+ switch (code)
+ {
+ case 200:
+ return
+ new ErrorCode(200, "reply-success", true);
+ case 311:
+ return
+ new ErrorCode(311, "content-too-large", false);
+ case 312:
+ return
+ new ErrorCode(312, "no-route", false);
+ case 313:
+ return
+ new ErrorCode(313, "content-consumers", false);
+ case 320:
+ return
+ new ErrorCode(320, "connection-forced", true);
+ case 402:
+ return
+ new ErrorCode(402, "invalid-path", true);
+ case 403:
+ return
+ new ErrorCode(403, "access-refused", false);
+ case 404:
+ return
+ new ErrorCode(404, "not-found", false);
+ case 405:
+ return
+ new ErrorCode(405, "resource-locked", false);
+ case 406:
+ return
+ new ErrorCode(406, "precondition-failed", false);
+ case 501:
+ return
+ new ErrorCode(501, "frame_error", true);
+ case 502:
+ return
+ new ErrorCode(502, "syntax_error", true);
+ case 503:
+ return
+ new ErrorCode(503, "command_invalid", true);
+ case 504:
+ return
+ new ErrorCode(504, "sesion_error", true);
+ case 530:
+ return
+ new ErrorCode(530, "not_allowed", true);
+ case 540:
+ return
+ new ErrorCode(540, "not_implemented", true);
+ case 541:
+ return
+ new ErrorCode(541, "internal_error", true);
+ case 542:
+ return
+ new ErrorCode(542, "invalid_argument", true);
+ default:
+ return new ErrorCode(1, "undefined", true);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/client/IClient.cs b/dotnet/client-010/client/client/IClient.cs
new file mode 100644
index 0000000000..b7b6c26957
--- /dev/null
+++ b/dotnet/client-010/client/client/IClient.cs
@@ -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.
+*/
+
+using System;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.client
+{
+ public interface IClient
+ {
+ /// <summary>
+ /// Establish a connection with the broker using the given parameters
+ ///
+ /// </summary>
+ /// <param name="host">host name</param>
+ /// <param name="port">port number</param>
+ /// <param name="virtualHost">virtualHost the virtual host name</param>
+ /// <param name="username"> username user name</param>
+ /// <param name="passwor">password password</param>
+ void Connect(String host, int port, String virtualHost, String username, String password, String mechanism);
+ void Connect(String host, int port, String virtualHost, String username, String password);
+
+ /// <summary>
+ /// Close this client
+ /// </summary>
+ void Close();
+
+ /// <summary>
+ /// Create a session for this connection.
+ /// The returned session is suspended
+ /// (i.e. this session is not attached to an underlying channel)
+ /// </summary>
+ /// <param name="expiryInSeconds">Expiry time expressed in seconds, if the value is less than
+ /// or equal to 0 then the session does not expire.</param>
+ /// <returns>A newly created (suspended) session.</returns>
+ IClientSession CreateSession(long expiryInSeconds);
+
+
+ event EventHandler<ExceptionArgs> ExceptionRaised;
+ event EventHandler ConnectionLost;
+
+ /// <summary>
+ /// If the broker sends a disconnect message, it will notify the ClosedListener
+ /// </summary>
+ ///
+ IClosedListener ClosedListener { set; }
+
+
+
+ bool IsClosed { get; set; }
+
+ /// <summary>
+ /// Establishes a connection with a broker using SSL
+ ///
+ /// </summary>
+ /// <param name="host">Host name on which a broker is deployed</param>
+ /// <param name="port">Broker port </param>
+ /// <param name="virtualHost">virtual host name</param>
+ /// <param name="username">User Name</param>
+ /// <param name="password">Password</param>
+ /// <param name="serverName">Name of the SSL server</param>
+ /// <param name="certPath">Path to the X509 certificate to be used for client authentication</param>
+ /// <param name="rejectUntrusted">If true connection will not be established if the broker is not trusted</param>
+ void ConnectSSL(String host, int port, String virtualHost, String username, String password, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted);
+ }
+}
diff --git a/dotnet/client-010/client/client/IClientSession.cs b/dotnet/client-010/client/client/IClientSession.cs
new file mode 100644
index 0000000000..8667db1fb4
--- /dev/null
+++ b/dotnet/client-010/client/client/IClientSession.cs
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.client
+{
+ public interface IClientSession : ISession
+ {
+ void AttachMessageListener(IMessageListener listener, string Destination);
+ Dictionary<String, IMessageListener> MessageListeners { get; }
+ void MessageTransfer(String destination, string routingkey, IMessage message);
+ void MessageTransfer(String destination, IMessage message);
+ void QueueDeclare(String queue);
+ void QueueDeclare(String queue, params Option[] options);
+ void ExchangeBind(String queue, String exchange, String bindingKey);
+ void MessageSubscribe(String queue);
+ }
+}
diff --git a/dotnet/client-010/client/client/IClosedListener.cs b/dotnet/client-010/client/client/IClosedListener.cs
new file mode 100644
index 0000000000..0e2472bba6
--- /dev/null
+++ b/dotnet/client-010/client/client/IClosedListener.cs
@@ -0,0 +1,29 @@
+/*
+* 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.
+*/
+
+using System;
+
+namespace org.apache.qpid.client
+{
+ public interface IClosedListener
+ {
+
+ void OnClosed(ErrorCode errorCode, String reason, Exception t);
+ }
+}
diff --git a/dotnet/client-010/client/client/IMessage.cs b/dotnet/client-010/client/client/IMessage.cs
new file mode 100644
index 0000000000..6eae826a4c
--- /dev/null
+++ b/dotnet/client-010/client/client/IMessage.cs
@@ -0,0 +1,48 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.client
+{
+ public interface IMessage
+ {
+ int Id { get; }
+
+ Header Header { get; set; }
+
+ MessageProperties MessageProperties { get; set; }
+
+ DeliveryProperties DeliveryProperties { get; set; }
+
+ Dictionary<String, Object> ApplicationHeaders { get; set; }
+
+ void AppendData(byte[] bytes);
+
+ MemoryStream Body { get; }
+
+ string Destination { get; }
+
+ void ClearData();
+ }
+}
diff --git a/dotnet/client-010/client/client/IMessageListener.cs b/dotnet/client-010/client/client/IMessageListener.cs
new file mode 100644
index 0000000000..44ceb3721e
--- /dev/null
+++ b/dotnet/client-010/client/client/IMessageListener.cs
@@ -0,0 +1,31 @@
+/*
+* 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.
+*/
+
+
+namespace org.apache.qpid.client
+{
+ public interface IMessageListener
+ {
+ /// <summary>
+ /// Inform the listener of the message transfer
+ /// </summary>
+ /// <param name="xfr">The message transfer object</param>
+ void MessageTransfer(IMessage xfr);
+ }
+}
diff --git a/dotnet/client-010/client/client/Message.cs b/dotnet/client-010/client/client/Message.cs
new file mode 100644
index 0000000000..6ab62070d2
--- /dev/null
+++ b/dotnet/client-010/client/client/Message.cs
@@ -0,0 +1,131 @@
+/*
+*
+* 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.
+*
+*/
+using System.Collections.Generic;
+using System.IO;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.client
+{
+ public class Message : IMessage
+ {
+ private readonly MessageTransfer _message;
+
+ public Message(MessageTransfer m)
+ {
+ _message = m;
+ }
+
+ public Message()
+ {
+ _message = new MessageTransfer();
+ _message.Header = new Header( new MessageProperties(), new DeliveryProperties());
+ ((MessageProperties) _message.Header.Structs[0]).SetApplicationHeaders(new Dictionary<string, object>());
+ }
+
+ public MessageProperties MessageProperties
+ {
+ get
+ {
+ if (_message.Header != null && Header.Structs.Length > 1)
+ return (MessageProperties) Header.Structs[0];
+ return null;
+ }
+ set
+ {
+ if (_message.Header != null)
+ {
+ Header.Structs[0] = value;
+ }
+ }
+ }
+
+ public DeliveryProperties DeliveryProperties
+ {
+ get
+ {
+ if (Header != null)
+ {
+ if( Header.Structs.Length > 1 )
+ return (DeliveryProperties)Header.Structs[1];
+ return (DeliveryProperties)Header.Structs[0];
+ }
+
+ return null;
+ }
+ set
+ {
+ if (Header != null)
+ {
+ Header.Structs[1] = value;
+ }
+ }
+ }
+
+ public Dictionary<string, object> ApplicationHeaders
+ {
+ get
+ {
+ if (Header != null)
+ return ((MessageProperties) Header.Structs[0]).GetApplicationHeaders();
+ return null;
+ }
+ set
+ {
+ if (Header != null)
+ {
+ ((MessageProperties) Header.Structs[0]).SetApplicationHeaders(value);
+ }
+ }
+ }
+
+ public void AppendData(byte[] bytes)
+ {
+ Body.Write(bytes, 0, bytes.Length);
+ }
+
+ public void ClearData()
+ {
+ Body.Seek(0, SeekOrigin.Begin);
+ }
+
+ public Header Header
+ {
+ get{ return _message.Header;}
+ set{ _message.Header = value;}
+ }
+
+ public MemoryStream Body
+ {
+ get { return _message.Body; }
+ set { _message.Body = value; }
+ }
+
+ public int Id
+ {
+ get { return _message.Id; }
+ }
+
+ public string Destination
+ {
+ get{ return _message.GetDestination();}
+ }
+ }
+}
diff --git a/dotnet/client-010/client/default.build b/dotnet/client-010/client/default.build
new file mode 100644
index 0000000000..139796a58d
--- /dev/null
+++ b/dotnet/client-010/client/default.build
@@ -0,0 +1,46 @@
+<?xml version="1.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.
+
+-->
+
+<project name="qpid.client" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/client/transport/Binary.cs b/dotnet/client-010/client/transport/Binary.cs
new file mode 100644
index 0000000000..f9bd3612dc
--- /dev/null
+++ b/dotnet/client-010/client/transport/Binary.cs
@@ -0,0 +1,129 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+
+
+ /// <summary>
+ /// Binary
+ /// </summary>
+
+ public sealed class Binary
+ {
+
+ private readonly byte[] bytes;
+ private readonly int offset_Renamed_Field;
+ private readonly int size_Renamed_Field;
+ private int hash = 0;
+
+ public Binary(byte[] bytes, int offset, int size)
+ {
+ if (offset + size > bytes.Length)
+ {
+ throw new System.IndexOutOfRangeException();
+ }
+
+ this.bytes = bytes;
+ offset_Renamed_Field = offset;
+ size_Renamed_Field = size;
+ }
+
+ public Binary(byte[] bytes):this(bytes, 0, bytes.Length)
+ {
+ }
+
+ public byte[] Array()
+ {
+ return bytes;
+ }
+
+ public int Offset()
+ {
+ return offset_Renamed_Field;
+ }
+
+ public int Size()
+ {
+ return size_Renamed_Field;
+ }
+
+ public Binary Slice(int low, int high)
+ {
+ int sz;
+
+ if (high < 0)
+ {
+ sz = size_Renamed_Field + high;
+ }
+ else
+ {
+ sz = high - low;
+ }
+
+ if (sz < 0)
+ {
+ sz = 0;
+ }
+
+ return new Binary(bytes, offset_Renamed_Field + low, sz);
+ }
+
+ public override int GetHashCode()
+ {
+ if (hash == 0)
+ {
+ int hc = 0;
+ for (int i = 0; i < size_Renamed_Field; i++)
+ {
+ hc = 31 * hc + (0xFF & bytes[offset_Renamed_Field + i]);
+ }
+ hash = hc;
+ }
+
+ return hash;
+ }
+
+ public override bool Equals(System.Object o)
+ {
+ if (!(o is Binary))
+ {
+ return false;
+ }
+
+ Binary buf = (Binary) o;
+ if (size_Renamed_Field != buf.size_Renamed_Field)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < size_Renamed_Field; i++)
+ {
+ if (bytes[offset_Renamed_Field + i] != buf.bytes[buf.offset_Renamed_Field + i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/Binding.cs b/dotnet/client-010/client/transport/Binding.cs
new file mode 100644
index 0000000000..a0899c1066
--- /dev/null
+++ b/dotnet/client-010/client/transport/Binding.cs
@@ -0,0 +1,34 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Binding
+ /// </summary>
+ internal interface Binding<E, T>
+ {
+ E endpoint(Sender<T> sender);
+
+ Receiver<R> receiver<R>(E endpoint) where R : EventArgs;
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/Channel.cs b/dotnet/client-010/client/transport/Channel.cs
new file mode 100644
index 0000000000..48ba707182
--- /dev/null
+++ b/dotnet/client-010/client/transport/Channel.cs
@@ -0,0 +1,174 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using org.apache.qpid.transport.network;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Channel
+ /// </summary>
+ public class Channel : Invoker, IProtocolDelegate<Object>
+ {
+ private static readonly Logger log = Logger.Get(typeof (Channel));
+
+ private readonly Connection _connection;
+ private readonly int _channel;
+ private readonly MethodDelegate<Channel> _methoddelegate;
+ private readonly SessionDelegate _sessionDelegate;
+ // session may be null
+ private Session _session;
+
+ public Channel(Connection connection, int channel, SessionDelegate sessionDelegate)
+ {
+ _connection = connection;
+ _channel = channel;
+ _methoddelegate = new ChannelDelegate();
+ _sessionDelegate = sessionDelegate;
+ }
+
+ public Connection Connection
+ {
+ get { return _connection; }
+ }
+
+ // Invoked when a network event is received
+ public void On_ReceivedEvent(object sender, ReceivedPayload<IProtocolEvent> payload)
+ {
+ if (payload.Payload.Channel == _channel)
+ {
+ payload.Payload.ProcessProtocolEvent(null, this);
+ }
+ }
+
+ #region ProtocolDelegate<T>
+
+ public void Init(Object v, ProtocolHeader hdr)
+ {
+ _connection.ConnectionDelegate.Init(this, hdr);
+ }
+
+ public void Control(Object v, Method method)
+ {
+ switch (method.EncodedTrack)
+ {
+ case Frame.L1:
+ method.Dispatch(this, _connection.ConnectionDelegate);
+ break;
+ case Frame.L2:
+ method.Dispatch(this, _methoddelegate);
+ break;
+ case Frame.L3:
+ method.ProcessProtocolEvent(_session, _sessionDelegate);
+ break;
+ default:
+ throw new Exception("unknown track: " + method.EncodedTrack);
+ }
+ }
+
+ public void Command(Object v, Method method)
+ {
+ method.ProcessProtocolEvent(_session, _sessionDelegate);
+ }
+
+ public void Error(Object v, ProtocolError error)
+ {
+ throw new Exception(error.Message);
+ }
+
+ #endregion
+
+ public void Exception(Exception t)
+ {
+ _session.Exception(t);
+ }
+
+ public void ClosedFromConnection()
+ {
+ log.Debug("channel Closed: ", this);
+ if (_session != null)
+ {
+ _session.Closed();
+ }
+ }
+
+ public void Closed()
+ {
+ log.Debug("channel Closed: ", this);
+ if (_session != null)
+ {
+ _session.Closed();
+ }
+ _connection.RemoveChannel(_channel);
+ }
+
+ public int EncodedChannel
+ {
+ get { return _channel; }
+ }
+
+ public Session Session
+ {
+ get { return _session; }
+ set { _session = value; }
+ }
+
+ public void CloseCode(ConnectionClose close)
+ {
+ if (_session != null)
+ {
+ _session.CloseCode(close);
+ }
+ }
+
+ private void Emit(IProtocolEvent pevent)
+ {
+ pevent.Channel = _channel;
+ _connection.Send(pevent);
+ }
+
+ public void Method(Method m)
+ {
+ Emit(m);
+
+ if (!m.Batch)
+ {
+ _connection.Flush();
+ }
+ }
+
+ protected override void Invoke(Method m)
+ {
+ Method(m);
+ }
+
+ public override IFuture Invoke(Method m, IFuture future)
+ {
+ throw new Exception("UnsupportedOperation");
+ }
+
+ public override String ToString()
+ {
+ return String.Format("{0}:{1}", _connection, _channel);
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/ChannelDelegate.cs b/dotnet/client-010/client/transport/ChannelDelegate.cs
new file mode 100644
index 0000000000..3a43d6d231
--- /dev/null
+++ b/dotnet/client-010/client/transport/ChannelDelegate.cs
@@ -0,0 +1,41 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ChannelDelegate
+ ///
+ /// </summary>
+ internal class ChannelDelegate : MethodDelegate<Channel>
+ {
+ public override void SessionDetached(Channel channel, SessionDetached closed)
+ {
+ channel.Closed();
+ }
+
+ public override void SessionDetach(Channel channel, SessionDetach dtc)
+ {
+ channel.Session.Closed();
+ channel.SessionDetached(dtc.GetName(), SessionDetachCode.NORMAL);
+ channel.Closed();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/ClientDelegate.cs b/dotnet/client-010/client/transport/ClientDelegate.cs
new file mode 100644
index 0000000000..957324ad41
--- /dev/null
+++ b/dotnet/client-010/client/transport/ClientDelegate.cs
@@ -0,0 +1,35 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.transport
+{
+ abstract class ClientDelegate : ConnectionDelegate
+ {
+ public override void Init(Channel ch, ProtocolHeader hdr)
+ {
+ if (hdr.Major != 0 && hdr.Minor != 10)
+ {
+ throw new ProtocolVersionException((sbyte) hdr.Major, (sbyte) hdr.Minor);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/Connection.cs b/dotnet/client-010/client/transport/Connection.cs
new file mode 100644
index 0000000000..b97357a96b
--- /dev/null
+++ b/dotnet/client-010/client/transport/Connection.cs
@@ -0,0 +1,168 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using Logger = org.apache.qpid.transport.util.Logger;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Connection
+ /// </summary>
+ public class Connection
+ {
+ private static readonly Logger log = Logger.Get(typeof (Connection));
+
+ private readonly ISender<IProtocolEvent> _sender;
+ private readonly ConnectionDelegate _connDdelegate;
+ private int _channelMax = 1;
+ private int _connectionId;
+ private readonly IReceiver<ReceivedPayload<IProtocolEvent>> _receiver;
+
+ private readonly Dictionary<int, Channel> _channels = new Dictionary<int, Channel>();
+
+ public Connection(IReceiver<ReceivedPayload<IProtocolEvent>> receiver, ISender<IProtocolEvent> sender, ConnectionDelegate connDdelegate)
+ {
+ _receiver = receiver;
+ _sender = sender;
+ _connDdelegate = connDdelegate;
+ }
+
+ public int ConnectionId
+ {
+ get { return _connectionId; }
+ set { _connectionId = value; }
+ }
+
+ public ConnectionDelegate ConnectionDelegate
+ {
+ get { return _connDdelegate; }
+ }
+
+ public int ChannelMax
+ {
+ get { return _channelMax; }
+ set { _channelMax = value; }
+ }
+
+ public void Send(IProtocolEvent pevent)
+ {
+ log.Debug("SEND: [{0}] {1}", this, pevent);
+ _sender.Send(pevent);
+ }
+
+ public void Flush()
+ {
+ log.Debug("FLUSH: [{0}]", this);
+ _sender.Flush();
+ }
+
+
+ public Channel GetChannel()
+ {
+ lock (_channels)
+ {
+ for (int i = 0; i < ChannelMax; i++)
+ {
+ if (!_channels.ContainsKey(i))
+ {
+ return GetChannel(i);
+ }
+ }
+ throw new Exception("no more _channels available");
+ }
+ }
+
+ public Channel GetChannel(int number)
+ {
+ lock (_channels)
+ {
+ Channel channel = null;
+ if (_channels.Count > 0)
+ {
+ if( _channels.ContainsKey(number))
+ channel = _channels[number];
+ }
+ if (channel == null)
+ {
+ channel = new Channel(this, number, _connDdelegate.GetSessionDelegate());
+ _receiver.Received += channel.On_ReceivedEvent;
+ _channels.Add(number, channel);
+ }
+ return channel;
+ }
+ }
+
+ public void RemoveChannel(int number)
+ {
+ lock (_channels)
+ {
+ _receiver.Received -= _channels[number].On_ReceivedEvent;
+ _channels.Remove(number);
+ }
+ }
+
+ public void On_ReceivedEvent(object sender, ReceivedPayload<IProtocolEvent> payload)
+ {
+ log.Debug("RECV: [{0}] {1}", this, payload.Payload);
+ if (_channels.ContainsKey(payload.Payload.Channel)) return;
+ Channel channel = GetChannel(payload.Payload.Channel);
+ channel.On_ReceivedEvent(sender, payload);
+ }
+
+ public void On_ReceivedException(Object sender, ExceptionArgs arg)
+ {
+ _connDdelegate.RaiseException(arg.Exception);
+ }
+
+ public void On_ReceivedClosed(Object sender, EventArgs arg)
+ {
+ log.Debug("Connection Closed: {0}", this);
+ lock (_channels)
+ {
+ foreach (Channel ch in _channels.Values)
+ {
+ ch.ClosedFromConnection();
+ }
+ }
+ _channels.Clear();
+ _connDdelegate.Closed();
+ }
+
+
+ public void CloseCode(ConnectionClose close)
+ {
+ lock (_channels)
+ {
+ foreach (Channel ch in _channels.Values)
+ {
+ ch.CloseCode(close);
+ }
+ }
+ }
+
+ public void Close()
+ {
+ _sender.Close();
+ }
+ }
+
+}
diff --git a/dotnet/client-010/client/transport/ConnectionDelegate.cs b/dotnet/client-010/client/transport/ConnectionDelegate.cs
new file mode 100644
index 0000000000..5d491bc06f
--- /dev/null
+++ b/dotnet/client-010/client/transport/ConnectionDelegate.cs
@@ -0,0 +1,108 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Logger = org.apache.qpid.transport.util.Logger;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ConnectionDelegate
+ ///
+ /// Currently only implemented client specific methods
+ /// </summary>
+ public abstract class ConnectionDelegate : MethodDelegate<Channel>
+ {
+ private static readonly Logger log = Logger.Get(typeof(ConnectionDelegate));
+ private String _virtualHost;
+
+ protected ManualResetEvent _negotiationComplete;
+
+ public abstract SessionDelegate GetSessionDelegate();
+
+ public abstract void RaiseException(Exception t);
+
+ public abstract void Closed();
+
+ public void SetCondition(ManualResetEvent negotiationComplete)
+ {
+ _negotiationComplete = negotiationComplete;
+ }
+
+ public virtual void Init(Channel ch, ProtocolHeader hdr)
+ {
+ ch.Connection.Send(new ProtocolHeader((byte)1, hdr.Major, hdr.Minor));
+ List<Object> plain = new List<Object>();
+ plain.Add("PLAIN");
+ List<Object> utf8 = new List<Object>();
+ utf8.Add("utf8");
+ ch.ConnectionStart(null, plain, utf8);
+ }
+
+ public String VirtualHost
+ {
+ get { return _virtualHost; }
+ set { _virtualHost = value; }
+ }
+
+ // ----------------------------------------------
+ // Client side
+ //-----------------------------------------------
+ public override void ConnectionStart(Channel context, ConnectionStart mstruct)
+ {
+ Dictionary<String, Object> props = new Dictionary<String, Object>();
+ context.ConnectionStartOk(props, null, null, "utf8");
+ }
+
+ public override void ConnectionSecure(Channel context, ConnectionSecure mstruct)
+ { // todo SASL
+ context.ConnectionSecureOk(new byte[0]);
+ }
+
+ public override void ConnectionTune(Channel context, ConnectionTune mstruct)
+ {
+ context.Connection.ChannelMax = mstruct.GetChannelMax();
+ context.ConnectionTuneOk(mstruct.GetChannelMax(), mstruct.GetMaxFrameSize(), mstruct.GetHeartbeatMax());
+ context.ConnectionOpen(_virtualHost, null, Option.INSIST);
+ }
+
+ public override void ConnectionOpenOk(Channel context, ConnectionOpenOk mstruct)
+ {
+ List<Object> knownHosts = mstruct.GetKnownHosts();
+ if (_negotiationComplete != null)
+ {
+ _negotiationComplete.Set();
+ }
+ }
+
+ public override void ConnectionRedirect(Channel context, ConnectionRedirect mstruct)
+ {
+ // not going to bother at the moment
+ }
+
+ public override void ConnectionClose(Channel ch, ConnectionClose close)
+ {
+ ch.Connection.CloseCode(close);
+ ch.ConnectionCloseOk();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/Field.cs b/dotnet/client-010/client/transport/Field.cs
new file mode 100644
index 0000000000..9af8c4a476
--- /dev/null
+++ b/dotnet/client-010/client/transport/Field.cs
@@ -0,0 +1,74 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using org.apache.qpid.transport.codec;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Field
+ /// </summary>
+ public abstract class Field<C, T>
+ {
+ private C container;
+ private T type;
+ private String name;
+ private int index;
+
+ protected Field(C container, T type, String name, int index)
+ {
+ this.container = container;
+ this.type = type;
+ this.name = name;
+ this.index = index;
+ }
+
+ public C Container
+ {
+ get { return container; }
+ }
+
+ public T Type
+ {
+ get { return type; }
+ }
+
+ public String Name
+ {
+ get { return name; }
+ }
+
+ public int Index
+ {
+ get { return index; }
+ }
+
+ public abstract bool Has(Object mystruct);
+
+ public abstract void Has(Object mystruct, bool value);
+
+ public abstract T Get(Object mystruct);
+
+ public abstract void Read(IDecoder dec, Object mystruct);
+
+ public abstract void Write(IEncoder enc, Object mystruct);
+ }
+}
diff --git a/dotnet/client-010/client/transport/Future.cs b/dotnet/client-010/client/transport/Future.cs
new file mode 100644
index 0000000000..c0eadfb7ae
--- /dev/null
+++ b/dotnet/client-010/client/transport/Future.cs
@@ -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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Future
+ /// </summary>
+ public interface Future
+ {
+ Struct Result
+ {
+ get; set;
+ }
+
+ Session Session
+ { set;
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/Header.cs b/dotnet/client-010/client/transport/Header.cs
new file mode 100644
index 0000000000..742531cfd8
--- /dev/null
+++ b/dotnet/client-010/client/transport/Header.cs
@@ -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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Header
+ /// </summary>
+ public class Header
+ {
+ private readonly Struct[] _mystructs;
+
+ public Header(List<Struct> structs)
+ : this(structs.ToArray())
+ {
+ }
+
+ public Header(params Struct[] structs)
+ {
+ _mystructs = structs;
+ }
+
+ public Struct[] Structs
+ {
+ get { return _mystructs; }
+ }
+
+
+ public Struct Get(Struct klass)
+ {
+ foreach (Struct st in _mystructs)
+ {
+ if (Equals(st.GetType(), klass.GetType()))
+ {
+ return st;
+ }
+ }
+ return null;
+ }
+
+ public override String ToString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.Append(" Header(");
+ bool first = true;
+ foreach (Struct s in _mystructs)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ str.Append(", ");
+ }
+ str.Append(s);
+ }
+ str.Append(")");
+ return str.ToString();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/IBinding.cs b/dotnet/client-010/client/transport/IBinding.cs
new file mode 100644
index 0000000000..607212f1fe
--- /dev/null
+++ b/dotnet/client-010/client/transport/IBinding.cs
@@ -0,0 +1,34 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Binding
+ /// </summary>
+ internal interface IBinding<E, T>
+ {
+ E Endpoint(ISender<T> sender);
+
+ IReceiver<R> Receiver<R>(E endpoint) where R : EventArgs;
+ }
+}
diff --git a/dotnet/client-010/client/transport/IFuture.cs b/dotnet/client-010/client/transport/IFuture.cs
new file mode 100644
index 0000000000..054b828d13
--- /dev/null
+++ b/dotnet/client-010/client/transport/IFuture.cs
@@ -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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Future
+ /// </summary>
+ public interface IFuture
+ {
+ Struct Result
+ {
+ get; set;
+ }
+
+ Session Session
+ { set;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/IProtocolDelegate.cs b/dotnet/client-010/client/transport/IProtocolDelegate.cs
new file mode 100644
index 0000000000..a9875fd290
--- /dev/null
+++ b/dotnet/client-010/client/transport/IProtocolDelegate.cs
@@ -0,0 +1,37 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ProtocolDelegate
+ /// </summary>
+ public interface IProtocolDelegate<T>
+ {
+ void Init(T context, ProtocolHeader header);
+
+ void Control(T context, Method control);
+
+ void Command(T context, Method command);
+
+ void Error(T context, ProtocolError error);
+ }
+}
diff --git a/dotnet/client-010/client/transport/IProtocolEvent.cs b/dotnet/client-010/client/transport/IProtocolEvent.cs
new file mode 100644
index 0000000000..8f915b204a
--- /dev/null
+++ b/dotnet/client-010/client/transport/IProtocolEvent.cs
@@ -0,0 +1,42 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// IProtocolEvent
+ /// </summary>
+ public interface IProtocolEvent
+ {
+ int Channel
+ {
+ get;
+ set;
+ }
+
+ byte EncodedTrack
+ {
+ set;
+ get;
+ }
+
+ void ProcessProtocolEvent<C>(C context, IProtocolDelegate<C> protocoldelegate);
+ }
+}
diff --git a/dotnet/client-010/client/transport/IReceiver.cs b/dotnet/client-010/client/transport/IReceiver.cs
new file mode 100644
index 0000000000..4c4c9572b9
--- /dev/null
+++ b/dotnet/client-010/client/transport/IReceiver.cs
@@ -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.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// a receiver will raise an event when:
+ /// - data is received
+ /// - an exception is thrown
+ /// - it is Closed
+ /// </summary>
+ public interface IReceiver <T> where T : EventArgs
+ {
+ event EventHandler<T> Received;
+ event EventHandler<ExceptionArgs> Exception;
+ event EventHandler Closed;
+ }
+}
diff --git a/dotnet/client-010/client/transport/ISender.cs b/dotnet/client-010/client/transport/ISender.cs
new file mode 100644
index 0000000000..d7d1781aec
--- /dev/null
+++ b/dotnet/client-010/client/transport/ISender.cs
@@ -0,0 +1,32 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Sender
+ /// </summary>
+ public interface ISender<T>
+ {
+ void Send(T msg);
+ void Flush();
+ void Close();
+ }
+}
diff --git a/dotnet/client-010/client/transport/ISession.cs b/dotnet/client-010/client/transport/ISession.cs
new file mode 100644
index 0000000000..e843095df6
--- /dev/null
+++ b/dotnet/client-010/client/transport/ISession.cs
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace org.apache.qpid.transport
+{
+ public interface ISession : IInvoker
+ {
+ bool IsClosed { get; set; }
+ string Name { get; }
+ int CommandsIn { get; set; }
+ byte[] GetName();
+ void SetAutoSync(bool value);
+ Dictionary<int, Method> GetOutstandingCommands();
+ int GetCommandsOut();
+ int NextCommandId();
+ void Identify(Method cmd);
+ void Processed(Method command);
+ void Processed(int command);
+ void Processed(int lower, int upper);
+ void Processed(Range range);
+ void FlushProcessed(params Option[] options);
+ void KnownComplete(RangeSet kc);
+ void SyncPoint();
+ void Attach(Channel channel);
+ Method GetCommand(int id);
+ bool Complete(int lower, int upper);
+ void Sync();
+ void Sync(long timeout);
+ void Result(int command, Struct result);
+ void AddException(ExecutionException exc);
+ void CloseCode(ConnectionClose close);
+ List<ExecutionException> GetExceptions();
+
+ void MessageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ byte[] body,
+ params Option[] options);
+
+ void MessageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ String body,
+ params Option[] options);
+
+ void Close();
+ void Exception(Exception t);
+ void Closed();
+ }
+}
diff --git a/dotnet/client-010/client/transport/Method.cs b/dotnet/client-010/client/transport/Method.cs
new file mode 100644
index 0000000000..8540698822
--- /dev/null
+++ b/dotnet/client-010/client/transport/Method.cs
@@ -0,0 +1,150 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+using System.Text;
+using Frame = org.apache.qpid.transport.network.Frame;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Method
+ /// </summary>
+ public abstract class Method : Struct, IProtocolEvent
+ {
+ public new static Method Create(int type)
+ {
+ return (Method) StructFactory.createInstruction(type);
+ }
+
+ // XXX: command subclass?
+ private int id;
+ private int channel;
+ private bool idSet;
+ private bool sync;
+ private bool batch;
+
+ public int Id
+ {
+ get { return id; }
+ set
+ {
+ id = value;
+ idSet = true;
+ }
+ }
+
+
+ public bool Sync
+ {
+ get { return sync; }
+ set { sync = value; }
+ }
+
+ public bool Batch
+ {
+ get { return batch; }
+ set { batch = value; }
+ }
+
+ public abstract bool HasPayload();
+
+ public virtual Header Header
+ {
+ get { return null; }
+ set { throw new Exception(); }
+ }
+
+ public virtual MemoryStream Body
+ {
+ get { return null; }
+ set { throw new Exception(); }
+ }
+
+
+ public abstract void Dispatch<C>(C context, MethodDelegate<C> mdelegate );
+
+ #region IProtocolEvent
+
+ public int Channel
+ {
+ get { return channel; }
+ set { channel = value; }
+ }
+
+ public abstract byte EncodedTrack { get; set; }
+
+ public void ProcessProtocolEvent<C>(C context, IProtocolDelegate<C> protocoldelegate)
+ {
+ if (EncodedTrack == Frame.L4)
+ {
+ protocoldelegate.Command(context, this);
+ }
+ else
+ {
+ protocoldelegate.Control(context, this);
+ }
+ }
+
+ #endregion
+
+ public override String ToString()
+ {
+ StringBuilder str = new StringBuilder();
+
+ str.Append("ch=");
+ str.Append(channel);
+
+ if (EncodedTrack == Frame.L4 && idSet)
+ {
+ str.Append(" id=");
+ str.Append(id);
+ }
+
+ if (sync || batch)
+ {
+ str.Append(" ");
+ str.Append("[");
+ if (Sync)
+ {
+ str.Append("S");
+ }
+ if (Batch)
+ {
+ str.Append("B");
+ }
+ str.Append("]");
+ }
+ str.Append(" ");
+ str.Append(base.ToString());
+ if (Header != null)
+ {
+ str.Append(Header.ToString());
+ }
+ if (Body != null)
+ {
+ str.Append("\n body=");
+ str.Append(Body.ToString());
+ }
+ return str.ToString();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/ProtocolDelegate.cs b/dotnet/client-010/client/transport/ProtocolDelegate.cs
new file mode 100644
index 0000000000..32dbd116ff
--- /dev/null
+++ b/dotnet/client-010/client/transport/ProtocolDelegate.cs
@@ -0,0 +1,37 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ProtocolDelegate
+ /// </summary>
+ public interface ProtocolDelegate<T>
+ {
+ void Init(T context, ProtocolHeader header);
+
+ void Control(T context, Method control);
+
+ void Command(T context, Method command);
+
+ void Error(T context, ProtocolError error);
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/ProtocolError.cs b/dotnet/client-010/client/transport/ProtocolError.cs
new file mode 100644
index 0000000000..2a5bf39565
--- /dev/null
+++ b/dotnet/client-010/client/transport/ProtocolError.cs
@@ -0,0 +1,85 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+using org.apache.qpid.transport.network;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ProtocolError
+ /// </summary>
+ public sealed class ProtocolError : INetworkEvent, IProtocolEvent
+ {
+ private int channel;
+ private byte track;
+ private String format;
+ private Object[] args;
+
+ public ProtocolError(byte track, String format, params Object[] args)
+ {
+ this.track = track;
+ this.format = format;
+ this.args = args;
+ }
+
+ #region INetworkEvent Methods
+
+ public void ProcessNetworkEvent(INetworkDelegate ndelegate)
+ {
+ ndelegate.Error(this);
+ }
+
+ #endregion
+
+ #region IProtocolEvent Methods
+
+ public int Channel
+ {
+ get { return channel; }
+ set { channel = value; }
+ }
+
+ public byte EncodedTrack
+ {
+ get { return track; }
+ set { throw new NotImplementedException(); }
+ }
+
+ public void ProcessProtocolEvent<C>(C context, IProtocolDelegate<C> protocoldelegate)
+ {
+ protocoldelegate.Error(context, this);
+ }
+
+ #endregion
+
+ public String Message
+ {
+ get { return String.Format(format, args); }
+ }
+
+
+ public override String ToString()
+ {
+ return String.Format("protocol error: {0}", Message);
+ }
+
+ }
+}
diff --git a/dotnet/client-010/client/transport/ProtocolEvent.cs b/dotnet/client-010/client/transport/ProtocolEvent.cs
new file mode 100644
index 0000000000..990d5ecc3a
--- /dev/null
+++ b/dotnet/client-010/client/transport/ProtocolEvent.cs
@@ -0,0 +1,42 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// ProtocolEvent
+ /// </summary>
+ public interface ProtocolEvent
+ {
+ int Channel
+ {
+ get;
+ set;
+ }
+
+ byte EncodedTrack
+ {
+ set;
+ get;
+ }
+
+ void ProcessProtocolEvent<C>(C context, ProtocolDelegate<C> protocoldelegate);
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/ProtocolHeader.cs b/dotnet/client-010/client/transport/ProtocolHeader.cs
new file mode 100644
index 0000000000..4adfee25df
--- /dev/null
+++ b/dotnet/client-010/client/transport/ProtocolHeader.cs
@@ -0,0 +1,124 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+using System.Text;
+using org.apache.qpid.transport.network;
+using Frame = org.apache.qpid.transport.network.Frame;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary> ProtocolHeader
+ ///
+ /// </summary>
+ public sealed class ProtocolHeader : INetworkEvent, IProtocolEvent
+ {
+ private readonly char[] AMQP = new char[] {'A', 'M', 'Q', 'P'};
+ private const byte CLASS = 1;
+
+ private readonly byte instance;
+ private readonly byte major;
+ private readonly byte minor;
+ private int channel;
+
+ public ProtocolHeader(byte instance, byte major, byte minor)
+ {
+ this.instance = instance;
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public ProtocolHeader(int instance, int major, int minor) : this((byte)instance, (byte)major, (byte)minor)
+ {
+ }
+
+ #region INetworkEvent Methods
+
+ public void ProcessNetworkEvent(INetworkDelegate ndelegate)
+ {
+ ndelegate.Init(this);
+ }
+
+ #endregion
+
+ #region IProtocolEvent Methods
+
+ public int Channel
+ {
+ get
+ {
+ return channel;
+ }
+ set
+ {
+ channel = value;
+ }
+ }
+
+ public byte EncodedTrack
+ {
+ get
+ {
+ return Frame.L1;
+ }
+ set { throw new NotImplementedException(); }
+ }
+
+ public void ProcessProtocolEvent<C>(C context, IProtocolDelegate<C> protocoldelegate)
+ {
+ protocoldelegate.Init(context, this);
+ }
+
+ #endregion
+
+ public byte Instance
+ {
+ get { return instance; }
+ }
+
+ public byte Major
+ {
+ get { return major; }
+ }
+
+ public byte Minor
+ {
+ get { return minor; }
+ }
+
+ public MemoryStream ToMemoryStream()
+ {
+ MemoryStream buf = new MemoryStream(8);
+ BinaryWriter writer = new BinaryWriter(buf);
+ writer.Write(AMQP);
+ writer.Write(CLASS);
+ writer.Write(instance);
+ writer.Write((sbyte) major);
+ writer.Write((sbyte) minor);
+ return buf;
+ }
+
+ public override String ToString()
+ {
+ return String.Format("AMQP.{0:d} {1:d}-{2:d}", instance, major, minor);
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/Range.cs b/dotnet/client-010/client/transport/Range.cs
new file mode 100644
index 0000000000..904b1c1229
--- /dev/null
+++ b/dotnet/client-010/client/transport/Range.cs
@@ -0,0 +1,117 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport
+{
+
+ /// <summary>
+ /// Range
+ /// </summary>
+
+
+ public sealed class Range
+ {
+ private int _lower;
+ private int _upper;
+
+ public Range(int lower, int upper)
+ {
+ _lower = lower;
+ _upper = upper;
+ }
+
+ public int Lower
+ {
+ get { return _lower; }
+ set { _lower = value; }
+ }
+ public int Upper
+ {
+ get { return _upper; }
+ set { _upper = value; }
+ }
+
+ public bool Includes(int value)
+ {
+ return Serial.Le(_lower, value) && Serial.Le(value, _upper);
+ }
+
+ public bool Includes(Range range)
+ {
+ return Includes(range._lower) && Includes(range._upper);
+ }
+
+ public bool Intersects(Range range)
+ {
+ return (Includes(range._lower) || Includes(range._upper) ||
+ range.Includes(_lower) || range.Includes(_upper));
+ }
+
+ public bool Touches(Range range)
+ {
+ return (Intersects(range) ||
+ Includes(range._upper + 1) || Includes(range._lower - 1) ||
+ range.Includes(_upper + 1) || range.Includes(_lower - 1));
+ }
+
+ public Range Span(Range range)
+ {
+ return new Range(Serial.Min(_lower, range._lower), Serial.Max(_upper, range._upper));
+ }
+
+ public List<Range> Subtract(Range range)
+ {
+ List<Range> result = new List<Range>();
+
+ if (Includes(range._lower) && Serial.Le(_lower, range._lower - 1))
+ {
+ result.Add(new Range(_lower, range._lower - 1));
+ }
+
+ if (Includes(range._upper) && Serial.Le(range._upper + 1, _upper))
+ {
+ result.Add(new Range(range._upper + 1, _upper));
+ }
+
+ if (result.Count == 0 && !range.Includes(this))
+ {
+ result.Add(this);
+ }
+
+ return result;
+ }
+
+ public Range Intersect(Range range)
+ {
+ int l = Serial.Max(_lower, range._lower);
+ int r = Serial.Min(_upper, range._upper);
+ return Serial.Gt(l, r) ? null : new Range(l, r);
+ }
+
+ public override String ToString()
+ {
+ return "[" + _lower + ", " + _upper + "]";
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/RangeSet.cs b/dotnet/client-010/client/transport/RangeSet.cs
new file mode 100644
index 0000000000..0a856ee979
--- /dev/null
+++ b/dotnet/client-010/client/transport/RangeSet.cs
@@ -0,0 +1,150 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// RangeSet
+ /// </summary>
+ public sealed class RangeSet : IEnumerable<Range>
+ {
+ private readonly List<Range> _ranges = new List<Range>();
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IEnumerator<Range> GetEnumerator()
+ {
+ return _ranges.GetEnumerator();
+ }
+
+
+ public int Size()
+ {
+ return _ranges.Count;
+ }
+
+
+ public Range GetFirst()
+ {
+ return _ranges[0];
+ }
+
+ public bool Includes(Range range)
+ {
+ foreach (Range r in this)
+ {
+ if (r.Includes(range))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public bool Includes(int n)
+ {
+ foreach (Range r in this)
+ {
+ if (r.Includes(n))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void Add(Range range)
+ {
+ for (int i = 0; i < _ranges.Count; i++)
+ {
+ Range r = _ranges[i];
+ if (range.Touches(r))
+ {
+ _ranges.Remove(r);
+ range = range.Span(r);
+ }
+ else if (Serial.Lt(range.Upper, r.Lower))
+ {
+ _ranges.Insert(i - 1 , range);
+ return;
+ }
+ }
+ _ranges.Add(range);
+ }
+
+ public void Add(int lower, int upper)
+ {
+ Add(new Range(lower, upper));
+ }
+
+ public void Add(int value)
+ {
+ Add(value, value);
+ }
+
+ public void Clear()
+ {
+ _ranges.Clear();
+ }
+
+ public RangeSet Copy()
+ {
+ RangeSet copy = new RangeSet();
+ foreach (Range r in _ranges)
+ {
+ copy._ranges.Add(r);
+ }
+ return copy;
+ }
+
+ public override String ToString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.Append("{");
+ bool first = true;
+ foreach (Range range in _ranges)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ str.Append(", ");
+ }
+ str.Append(range);
+ }
+ str.Append("}");
+ return str.ToString();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/ReceivedPayload.cs b/dotnet/client-010/client/transport/ReceivedPayload.cs
new file mode 100644
index 0000000000..e072ba7493
--- /dev/null
+++ b/dotnet/client-010/client/transport/ReceivedPayload.cs
@@ -0,0 +1,43 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+
+namespace org.apache.qpid.transport
+{
+ public class ReceivedPayload<T> : EventArgs
+ {
+ public ReceivedPayload()
+ {
+ }
+
+ public ReceivedPayload(T payload)
+ {
+ m_payload = payload;
+ }
+ private T m_payload;
+
+ public T Payload
+ {
+ get { return m_payload; }
+ set { m_payload = value; }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/Receiver.cs b/dotnet/client-010/client/transport/Receiver.cs
new file mode 100644
index 0000000000..f8d91c3f10
--- /dev/null
+++ b/dotnet/client-010/client/transport/Receiver.cs
@@ -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.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// a receiver will raise an event when:
+ /// - data is received
+ /// - an exception is thrown
+ /// - it is closed
+ /// </summary>
+ public interface Receiver <T> where T : EventArgs
+ {
+ event EventHandler<T> Received;
+ event EventHandler<ExceptionArgs> Exception;
+ event EventHandler Closed;
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/Sender.cs b/dotnet/client-010/client/transport/Sender.cs
new file mode 100644
index 0000000000..f8b5bdef06
--- /dev/null
+++ b/dotnet/client-010/client/transport/Sender.cs
@@ -0,0 +1,32 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Sender
+ /// </summary>
+ public interface Sender<T>
+ {
+ void send(T msg);
+ void flush();
+ void close();
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/Session.cs b/dotnet/client-010/client/transport/Session.cs
new file mode 100644
index 0000000000..7b4aff9811
--- /dev/null
+++ b/dotnet/client-010/client/transport/Session.cs
@@ -0,0 +1,522 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.transport.util;
+using Frame = org.apache.qpid.transport.network.Frame;
+using Logger = org.apache.qpid.transport.util.Logger;
+
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Session
+ ///
+ /// </summary>
+ public class Session : Invoker, ISession
+ {
+ private static readonly Logger log = Logger.Get(typeof (Session));
+ private static readonly bool ENABLE_REPLAY;
+
+ static Session()
+ {
+ const string enableReplay = "enable_command_replay";
+ try
+ {
+ String var = Environment.GetEnvironmentVariable(enableReplay);
+ if (var != null)
+ {
+ ENABLE_REPLAY = bool.Parse(var);
+ }
+ }
+ catch (Exception)
+ {
+ ENABLE_REPLAY = false;
+ }
+ }
+
+ private readonly byte[] _name;
+ private const long _timeout = 600000;
+ private bool _autoSync = false;
+
+ // channel may be null
+ private Channel _channel;
+
+ // incoming command count
+ private int _commandsIn = 0;
+ // completed incoming commands
+ private readonly Object _processedLock = new Object();
+ private RangeSet _processed = new RangeSet();
+ private int _maxProcessed = - 1;
+ private int _syncPoint = -1;
+
+ // outgoing command count
+ private int _commandsOut = 0;
+ private readonly Dictionary<int, Method> _commands = new Dictionary<int, Method>();
+ private int _maxComplete = - 1;
+ private bool _needSync = false;
+ private bool _closed;
+ private readonly Dictionary<int, IFuture> _results = new Dictionary<int, IFuture>();
+ private readonly List<ExecutionException> _exceptions = new List<ExecutionException>();
+
+
+ public bool IsClosed
+ {
+ get
+ {
+ lock (this)
+ {
+ return _closed;
+ }
+ }
+ set
+ {
+ lock (this)
+ {
+ _closed = value;
+ }
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ ASCIIEncoding enc = new ASCIIEncoding();
+ return enc.GetString(_name);
+ }
+ }
+
+ public Session(byte[] name)
+ {
+ _name = name;
+ }
+
+ public byte[] GetName()
+ {
+ return _name;
+ }
+
+ public void SetAutoSync(bool value)
+ {
+ lock (_commands)
+ {
+ _autoSync = value;
+ }
+ }
+
+ public Dictionary<int, Method> GetOutstandingCommands()
+ {
+ return _commands;
+ }
+
+ public int GetCommandsOut()
+ {
+ return _commandsOut;
+ }
+
+ public int CommandsIn
+ {
+ get { return _commandsIn; }
+ set { _commandsIn = value; }
+ }
+
+ public int NextCommandId()
+ {
+ return _commandsIn++;
+ }
+
+ public void Identify(Method cmd)
+ {
+ int id = NextCommandId();
+ cmd.Id = id;
+
+ if (log.IsDebugEnabled())
+ {
+ log.Debug("ID: [{0}] %{1}", _channel, id);
+ }
+
+ //if ((id % 65536) == 0)
+ if ((id & 0xff) == 0)
+ {
+ FlushProcessed(Option.TIMELY_REPLY);
+ }
+ }
+
+ public void Processed(Method command)
+ {
+ Processed(command.Id);
+ }
+
+ public void Processed(int command)
+ {
+ Processed(new Range(command, command));
+ }
+
+ public void Processed(int lower, int upper)
+ {
+ Processed(new Range(lower, upper));
+ }
+
+ public void Processed(Range range)
+ {
+ log.Debug("{0} processed({1})", this, range);
+
+ bool flush;
+ lock (_processedLock)
+ {
+ _processed.Add(range);
+ Range first = _processed.GetFirst();
+ int lower = first.Lower;
+ int upper = first.Upper;
+ int old = _maxProcessed;
+ if (Serial.Le(lower, _maxProcessed + 1))
+ {
+ _maxProcessed = Serial.Max(_maxProcessed, upper);
+ }
+ flush = Serial.Lt(old, _syncPoint) && Serial.Ge(_maxProcessed, _syncPoint);
+ _syncPoint = _maxProcessed;
+ }
+ if (flush)
+ {
+ FlushProcessed();
+ }
+ }
+
+ public void FlushProcessed(params Option[] options)
+ {
+ RangeSet copy;
+ lock (_processedLock)
+ {
+ copy = _processed.Copy();
+ }
+ SessionCompleted(copy, options);
+ }
+
+ public void KnownComplete(RangeSet kc)
+ {
+ lock (_processedLock)
+ {
+ RangeSet newProcessed = new RangeSet();
+ foreach (Range pr in _processed)
+ {
+ foreach (Range kr in kc)
+ {
+ foreach (Range r in pr.Subtract(kr))
+ {
+ newProcessed.Add(r);
+ }
+ }
+ }
+ _processed = newProcessed;
+ }
+ }
+
+ public void SyncPoint()
+ {
+ int id = CommandsIn - 1;
+ log.Debug("{0} synced to {1}", this, id);
+ bool flush;
+ lock (_processedLock)
+ {
+ _syncPoint = id;
+ flush = Serial.Ge(_maxProcessed, _syncPoint);
+ }
+ if (flush)
+ {
+ FlushProcessed();
+ }
+ }
+
+ public void Attach(Channel channel)
+ {
+ _channel = channel;
+ _channel.Session = this;
+ }
+
+ public Method GetCommand(int id)
+ {
+ lock (_commands)
+ {
+ return _commands[id];
+ }
+ }
+
+ public bool Complete(int lower, int upper)
+ {
+ //avoid autoboxing
+ if (log.IsDebugEnabled())
+ {
+ log.Debug("{0} complete({1}, {2})", this, lower, upper);
+ }
+ lock (_commands)
+ {
+ int old = _maxComplete;
+ for (int id = Serial.Max(_maxComplete, lower); Serial.Le(id, upper); id++)
+ {
+ _commands.Remove(id);
+ }
+ if (Serial.Le(lower, _maxComplete + 1))
+ {
+ _maxComplete = Serial.Max(_maxComplete, upper);
+ }
+ log.Debug("{0} commands remaining: {1}", this, _commands);
+ Monitor.PulseAll(_commands);
+ return Serial.Gt(_maxComplete, old);
+ }
+ }
+
+ protected override void Invoke(Method m)
+ {
+ if (IsClosed)
+ {
+ List<ExecutionException> exc = GetExceptions();
+ if (exc.Count > 0)
+ {
+ throw new SessionException(exc);
+ }
+ else if (_close != null)
+ {
+ throw new ConnectionException(_close);
+ }
+ else
+ {
+ throw new SessionClosedException();
+ }
+ }
+
+ if (m.EncodedTrack == Frame.L4)
+ {
+ lock (_commands)
+ {
+ int next = _commandsOut++;
+ m.Id = next;
+ if (next == 0)
+ {
+ SessionCommandPoint(0, 0);
+ }
+ if (ENABLE_REPLAY)
+ {
+ _commands.Add(next, m);
+ }
+ if (_autoSync)
+ {
+ m.Sync = true;
+ }
+ _needSync = ! m.Sync;
+ _channel.Method(m);
+ if (_autoSync)
+ {
+ Sync();
+ }
+
+ // flush every 64K commands to avoid ambiguity on
+ // wraparound
+ if ((next%65536) == 0)
+ {
+ SessionFlush(Option.COMPLETED);
+ }
+ }
+ }
+ else
+ {
+ _channel.Method(m);
+ }
+ }
+
+ public void Sync()
+ {
+ Sync(_timeout);
+ }
+
+ public void Sync(long timeout)
+ {
+ log.Debug("{0} sync()", this);
+ lock (_commands)
+ {
+ int point = _commandsOut - 1;
+
+ if (_needSync && Serial.Lt(_maxComplete, point))
+ {
+ ExecutionSync(Option.SYNC);
+ }
+
+ DateTime start = DateTime.Now;
+ long elapsed = 0;
+
+ while (!IsClosed && elapsed < timeout && Serial.Lt(_maxComplete, point))
+ {
+ log.Debug("{0} waiting for[{1}]: {2}, {3}", this, point,
+ _maxComplete, _commands);
+ Monitor.Wait(_commands, (int) (timeout - elapsed));
+ elapsed = DateTime.Now.Subtract(start).Milliseconds;
+ }
+
+ if (Serial.Lt(_maxComplete, point))
+ {
+ if (IsClosed)
+ {
+ throw new SessionException(GetExceptions());
+ }
+ else
+ {
+ throw new Exception
+ (String.Format
+ ("timed out waiting for sync: complete = {0}, point = {1}", _maxComplete, point));
+ }
+ }
+ }
+ }
+
+
+ public void Result(int command, Struct result)
+ {
+ IFuture future;
+ lock (_results)
+ {
+ if (_results.ContainsKey(command))
+ {
+ future = _results[command];
+ _results.Remove(command);
+ }
+ else
+ {
+ throw new Exception(String.Format("Cannot ger result {0} for {1}", command, result));
+ }
+ }
+ future.Result = result;
+ }
+
+ public void AddException(ExecutionException exc)
+ {
+ lock (_exceptions)
+ {
+ _exceptions.Add(exc);
+ }
+ }
+
+ private ConnectionClose _close = null;
+
+ public void CloseCode(ConnectionClose close)
+ {
+ _close = close;
+ }
+
+ public List<ExecutionException> GetExceptions()
+ {
+ lock (_exceptions)
+ {
+ return new List<ExecutionException>(_exceptions);
+ }
+ }
+
+ public override IFuture Invoke(Method m, IFuture future)
+ {
+ lock (_commands)
+ {
+ future.Session = this;
+ int command = _commandsOut;
+ lock (_results)
+ {
+ _results.Add(command, future);
+ }
+ Invoke(m);
+ }
+ return future;
+ }
+
+
+ public void MessageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ byte[] body,
+ params Option[] options)
+ {
+ MemoryStream mbody = new MemoryStream();
+ mbody.Write(body,0, body.Length);
+ MessageTransfer(destination, acceptMode, acquireMode, header,
+ mbody, options);
+ }
+
+ public void MessageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ String body,
+ params Option[] options)
+ {
+ MessageTransfer(destination, acceptMode, acquireMode, header,
+ new MemoryStream(Convert.ToByte(body)), options);
+ }
+
+ public void Close()
+ {
+ SessionRequestTimeout(0);
+ SessionDetach(_name);
+ lock (_commands)
+ {
+ DateTime start = DateTime.Now;
+ long elapsed = 0;
+
+ while (!IsClosed && elapsed < _timeout)
+ {
+ Monitor.Wait(_commands, (int) (_timeout - elapsed));
+ elapsed = DateTime.Now.Subtract(start).Milliseconds;
+ }
+ }
+ }
+
+ public void Exception(Exception t)
+ {
+ log.Error(t, "Caught exception");
+ }
+
+ public void Closed()
+ {
+ IsClosed = true;
+ lock (_commands)
+ {
+ Monitor.PulseAll(_commands);
+ }
+ lock (_results)
+ {
+ foreach (IFuture result in _results.Values)
+ {
+ lock (result)
+ {
+ Monitor.PulseAll(result);
+ }
+ }
+ }
+ _channel.Session = null;
+ _channel = null;
+ }
+
+ public override String ToString()
+ {
+ return String.Format("session:{0}", _name);
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/SessionDelegate.cs b/dotnet/client-010/client/transport/SessionDelegate.cs
new file mode 100644
index 0000000000..973e22df16
--- /dev/null
+++ b/dotnet/client-010/client/transport/SessionDelegate.cs
@@ -0,0 +1,126 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// SessionDelegate
+ ///
+ /// </summary>
+ public abstract class SessionDelegate : MethodDelegate<Session>, IProtocolDelegate<Session>
+ {
+ public void Init(Session ssn, ProtocolHeader hdr)
+ {
+ }
+
+ public void Control(Session ssn, Method method)
+ {
+ method.Dispatch(ssn, this);
+ }
+
+ public void Command(Session ssn, Method method)
+ {
+ ssn.Identify(method);
+ method.Dispatch(ssn, this);
+ if (!method.HasPayload())
+ {
+ ssn.Processed(method);
+ }
+ }
+
+ public void Error(Session ssn, ProtocolError error)
+ {
+ }
+
+ public override void ExecutionResult(Session ssn, ExecutionResult result)
+ {
+ ssn.Result(result.GetCommandId(), result.GetValue());
+ }
+
+ public override void ExecutionException(Session ssn, ExecutionException exc)
+ {
+ ssn.AddException(exc);
+ }
+
+ public override void SessionCompleted(Session ssn, SessionCompleted cmp)
+ {
+ RangeSet ranges = cmp.GetCommands();
+ RangeSet known = null;
+ if (cmp.GetTimelyReply())
+ {
+ known = new RangeSet();
+ }
+
+ if (ranges != null)
+ {
+ foreach (Range range in ranges)
+ {
+ bool advanced = ssn.Complete(range.Lower, range.Upper);
+ if (advanced && known != null)
+ {
+ known.Add(range);
+ }
+ }
+ }
+
+ if (known != null)
+ {
+ ssn.SessionKnownCompleted(known);
+ }
+ }
+
+ public override void SessionKnownCompleted(Session ssn, SessionKnownCompleted kcmp)
+ {
+ RangeSet kc = kcmp.GetCommands();
+ if (kc != null)
+ {
+ ssn.KnownComplete(kc);
+ }
+ }
+
+ public override void SessionFlush(Session ssn, SessionFlush flush)
+ {
+ if (flush.GetCompleted())
+ {
+ ssn.FlushProcessed();
+ }
+ if (flush.GetConfirmed())
+ {
+ ssn.FlushProcessed();
+ }
+ if (flush.GetExpected())
+ {
+ // to be done
+ //throw new Exception("not implemented");
+ }
+ }
+
+ public override void SessionCommandPoint(Session ssn, SessionCommandPoint scp)
+ {
+ ssn.CommandsIn = scp.GetCommandId();
+ }
+
+ public override void ExecutionSync(Session ssn, ExecutionSync sync)
+ {
+ ssn.SyncPoint();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/Struct.cs b/dotnet/client-010/client/transport/Struct.cs
new file mode 100644
index 0000000000..ff8d80fcb1
--- /dev/null
+++ b/dotnet/client-010/client/transport/Struct.cs
@@ -0,0 +1,121 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using org.apache.qpid.transport.codec;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// Struct
+ /// </summary>
+
+ public abstract class Struct : IEncodable
+ {
+ public static Struct Create(int type)
+ {
+ return StructFactory.create(type);
+ }
+
+ bool dirty = true;
+
+ public bool Dirty
+ {
+ get { return dirty; }
+ set { dirty = value; }
+ }
+
+ public abstract int GetStructType();
+
+ public abstract int GetSizeWidth();
+
+ public abstract int GetPackWidth();
+
+ public int GetEncodedType()
+ {
+ int type = GetStructType();
+ if (type < 0)
+ {
+ throw new Exception();
+ }
+ return type;
+ }
+
+ private bool IsBit<C, T>(Field<C, T> f)
+ {
+ return Equals(f.Type, typeof(Boolean));
+ }
+
+ private bool Packed()
+ {
+ return GetPackWidth() > 0;
+ }
+
+ private bool Encoded<C, T>(Field<C, T> f)
+ {
+ return !Packed() || !IsBit(f) && f.Has(this);
+ }
+
+ private int GetFlagWidth()
+ {
+ return (Fields.Count + 7) / 8;
+ }
+
+ private int GetFlagCount()
+ {
+ return 8 * GetPackWidth();
+ }
+
+ public abstract void Read(IDecoder dec);
+
+ public abstract void Write(IEncoder enc);
+
+ public abstract Dictionary<String, Object> Fields
+ {
+ get;
+ }
+
+ public override String ToString()
+ {
+ StringBuilder str = new StringBuilder();
+ str.Append(GetType());
+ str.Append("(");
+ bool first = true;
+ foreach (KeyValuePair<String, Object> me in Fields)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ str.Append(", ");
+ }
+ str.Append(me.Key);
+ str.Append("=");
+ str.Append(me.Value);
+ }
+ str.Append(")");
+ return str.ToString();
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/AbstractDecoder.cs b/dotnet/client-010/client/transport/codec/AbstractDecoder.cs
new file mode 100644
index 0000000000..2e9e587407
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/AbstractDecoder.cs
@@ -0,0 +1,399 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// AbstractDecoder
+ /// </summary>
+ public abstract class AbstractDecoder : IDecoder
+ {
+ private readonly Dictionary<Binary, String> str8cache = new Dictionary<Binary, String>();
+
+ protected abstract byte DoGet();
+
+ protected abstract void DoGet(byte[] bytes);
+ public abstract bool HasRemaining();
+
+ protected byte Get()
+ {
+ return DoGet();
+ }
+
+ protected void Get(byte[] bytes)
+ {
+ DoGet(bytes);
+ }
+
+ protected Binary Get(int size)
+ {
+ byte[] bytes = new byte[size];
+ Get(bytes);
+ return new Binary(bytes);
+ }
+
+ protected short Uget()
+ {
+ return (short) (0xFF & Get());
+ }
+
+ public virtual short ReadUint8()
+ {
+ return Uget();
+ }
+
+ public abstract int ReadUint16();
+
+
+ public abstract long ReadUint32();
+
+
+ public int ReadSequenceNo()
+ {
+ return (int) ReadUint32();
+ }
+
+ public virtual long ReadUint64()
+ {
+ long l = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ l |= ((long) (0xFF & Get())) << (56 - i*8);
+ }
+ return l;
+ }
+
+ public abstract short ReadInt8();
+ public abstract int ReadInt16();
+ public abstract long ReadInt32() ;
+ public abstract long ReadInt64();
+ public abstract float ReadFloat() ;
+ public abstract double ReadDouble() ;
+
+ public long ReadDatetime()
+ {
+ return ReadUint64();
+ }
+
+ private static String Decode(byte[] bytes, int offset, int length, Encoding encoding)
+ {
+ return encoding.GetString(bytes, offset, length);
+ }
+
+ private static String Decode(byte[] bytes, Encoding encoding)
+ {
+ return Decode(bytes, 0, bytes.Length, encoding);
+ }
+
+ public String ReadStr8()
+ {
+ short size = ReadUint8();
+ Binary bin = Get(size);
+ String str;
+ if (! str8cache.TryGetValue(bin, out str))
+ {
+ str = Decode(bin.Array(), bin.Offset(), bin.Size(), Encoding.UTF8);
+ str8cache.Add(bin, str);
+ }
+ return str;
+ }
+
+ public String ReadStr16()
+ {
+ int size = ReadUint16();
+ byte[] bytes = new byte[size];
+ Get(bytes);
+ return Decode(bytes, Encoding.UTF8);
+ }
+
+ public byte[] ReadVbin8()
+ {
+ int size = ReadUint8();
+ byte[] bytes = new byte[size];
+ Get(bytes);
+ return bytes;
+ }
+
+ public byte[] ReadVbin16()
+ {
+ int size = ReadUint16();
+ byte[] bytes = new byte[size];
+ Get(bytes);
+ return bytes;
+ }
+
+ public byte[] ReadVbin32()
+ {
+ int size = (int) ReadUint32();
+ byte[] bytes = new byte[size];
+ Get(bytes);
+ return bytes;
+ }
+
+ public RangeSet ReadSequenceSet()
+ {
+ int count = ReadUint16()/8;
+ if (count == 0)
+ {
+ return null;
+ }
+ RangeSet ranges = new RangeSet();
+ for (int i = 0; i < count; i++)
+ {
+ ranges.Add(ReadSequenceNo(), ReadSequenceNo());
+ }
+ return ranges;
+ }
+
+ public RangeSet ReadByteRanges()
+ {
+ throw new Exception("not implemented");
+ }
+
+ public UUID ReadUuid()
+ {
+ long msb = ReadUint64();
+ long lsb = ReadUint64();
+ return new UUID(msb, lsb);
+ }
+
+ public String ReadContent()
+ {
+ throw new Exception("Deprecated");
+ }
+
+ public Struct ReadStruct(int type)
+ {
+ Struct st = Struct.Create(type);
+ int width = st.GetSizeWidth();
+ if (width > 0)
+ {
+ long size = ReadSize(width);
+ if (size == 0)
+ {
+ return null;
+ }
+ }
+ if (type > 0)
+ {
+ int code = ReadUint16();
+ Debug.Assert(code == type);
+ }
+ st.Read(this);
+ return st;
+ }
+
+ public Struct ReadStruct32()
+ {
+ long size = ReadUint32();
+ if (size == 0)
+ {
+ return null;
+ }
+ int type = ReadUint16();
+ Struct result = Struct.Create(type);
+ result.Read(this);
+ return result;
+ }
+
+ public Dictionary<String, Object> ReadMap()
+ {
+ long size = ReadUint32();
+
+ if (size == 0)
+ {
+ return null;
+ }
+
+ long count = ReadUint32();
+
+ Dictionary<String, Object> result = new Dictionary<String, Object>();
+ for (int i = 0; i < count; i++)
+ {
+ String key = ReadStr8();
+ byte code = Get();
+ QpidType t = GetType(code);
+ Object value = Read(t);
+ result.Add(key, value);
+ }
+
+ return result;
+ }
+
+ public List<Object> ReadList()
+ {
+ long size = ReadUint32();
+
+ if (size == 0)
+ {
+ return null;
+ }
+
+ long count = ReadUint32();
+
+ List<Object> result = new List<Object>();
+ for (int i = 0; i < count; i++)
+ {
+ byte code = Get();
+ QpidType t = GetType(code);
+ Object value = Read(t);
+ result.Add(value);
+ }
+ return result;
+ }
+
+ public List<Object> ReadArray()
+ {
+ long size = ReadUint32();
+
+ if (size == 0)
+ {
+ return null;
+ }
+
+ byte code = Get();
+ QpidType t = GetType(code);
+ long count = ReadUint32();
+
+ List<Object> result = new List<Object>();
+ for (int i = 0; i < count; i++)
+ {
+ Object value = Read(t);
+ result.Add(value);
+ }
+ return result;
+ }
+
+ private QpidType GetType(byte code)
+ {
+ return QpidType.get(code);
+ }
+
+ private long ReadSize(QpidType t)
+ {
+ return t.Fixed ? t.Width : ReadSize(t.Width);
+ }
+
+ private long ReadSize(int width)
+ {
+ switch (width)
+ {
+ case 1:
+ return ReadUint8();
+ case 2:
+ return ReadUint16();
+ case 4:
+ return ReadUint32();
+ default:
+ throw new Exception("illegal width: " + width);
+ }
+ }
+
+ private byte[] ReadBytes(QpidType t)
+ {
+ long size = ReadSize(t);
+ byte[] result = new byte[(int) size];
+ Get(result);
+ return result;
+ }
+
+ private Object Read(QpidType t)
+ {
+ switch (t.Code)
+ {
+ case Code.BIN8:
+ case Code.UINT8:
+ return ReadUint8();
+ case Code.INT8:
+ return Get();
+ case Code.CHAR:
+ return (char) Get();
+ case Code.BOOLEAN:
+ return Get() > 0;
+
+ case Code.BIN16:
+ case Code.UINT16:
+ return ReadUint16();
+ case Code.INT16:
+ return (short) ReadUint16();
+
+ case Code.BIN32:
+ case Code.UINT32:
+ return ReadUint32();
+
+ case Code.CHAR_UTF32:
+ case Code.INT32:
+ return (int) ReadUint32();
+
+ case Code.FLOAT:
+ return (float)BitConverter.Int64BitsToDouble(ReadUint32() << 32);
+
+ case Code.BIN64:
+ case Code.UINT64:
+ case Code.INT64:
+ case Code.DATETIME:
+ return ReadUint64();
+
+ case Code.DOUBLE:
+ return BitConverter.Int64BitsToDouble(ReadUint64());
+ case Code.UUID:
+ return ReadUuid();
+ case Code.STR8:
+ return ReadStr8();
+ case Code.STR16:
+ return ReadStr16();
+ case Code.STR8_LATIN:
+ case Code.STR8_UTF16:
+ case Code.STR16_LATIN:
+ case Code.STR16_UTF16:
+ // XXX: need to do character conversion
+ return Encoding.UTF8.GetString(ReadBytes(t));
+
+ case Code.MAP:
+ return ReadMap();
+ case Code.LIST:
+ return ReadList();
+ case Code.ARRAY:
+ return ReadArray();
+ case Code.STRUCT32:
+ return ReadStruct32();
+
+ case Code.BIN40:
+ case Code.DEC32:
+ case Code.BIN72:
+ case Code.DEC64:
+ // XXX: what types are we supposed to use here?
+ return ReadBytes(t);
+
+ case Code.VOID:
+ return null;
+
+ default:
+ return ReadBytes(t);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/AbstractEncoder.cs b/dotnet/client-010/client/transport/codec/AbstractEncoder.cs
new file mode 100644
index 0000000000..eb8bdae80a
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/AbstractEncoder.cs
@@ -0,0 +1,590 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// AbstractEncoder
+ /// </summary>
+ public abstract class AbstractEncoder : IEncoder
+ {
+ private static readonly Dictionary<Type, Code> ENCODINGS = new Dictionary<Type, Code>();
+ private readonly Dictionary<String, byte[]> str8cache = new Dictionary<String, byte[]>();
+
+ static AbstractEncoder()
+ {
+ ENCODINGS.Add(typeof (Boolean), Code.BOOLEAN);
+ ENCODINGS.Add(typeof (String), Code.STR16);
+ ENCODINGS.Add(typeof (long), Code.INT64);
+ ENCODINGS.Add(typeof (int), Code.INT32);
+ ENCODINGS.Add(typeof (short), Code.INT16);
+ ENCODINGS.Add(typeof (Byte), Code.INT8);
+ ENCODINGS.Add(typeof (Dictionary<String, Object>), Code.MAP);
+ ENCODINGS.Add(typeof (List<Object>), Code.LIST);
+ ENCODINGS.Add(typeof (float), Code.FLOAT);
+ ENCODINGS.Add(typeof (Double), Code.DOUBLE);
+ ENCODINGS.Add(typeof (char), Code.CHAR);
+ ENCODINGS.Add(typeof (byte[]), Code.VBIN32);
+ ENCODINGS.Add(typeof (UUID), Code.UUID);
+ }
+
+ protected abstract void DoPut(byte b);
+
+ protected abstract void DoPut(MemoryStream src);
+
+
+ protected void Put(byte b)
+ {
+ DoPut(b);
+ }
+
+ protected void Put(MemoryStream src)
+ {
+ DoPut(src);
+ }
+
+ protected virtual void Put(byte[] bytes)
+ {
+ Put(new MemoryStream(bytes));
+ }
+
+ protected abstract int BeginSize8();
+ protected abstract void EndSize8(int pos);
+
+ protected abstract int BeginSize16();
+ protected abstract void EndSize16(int pos);
+
+ protected abstract int BeginSize32();
+ protected abstract void EndSize32(int pos);
+
+ public virtual void WriteUint8(short b)
+ {
+ Debug.Assert(b < 0x100);
+ Put((byte) b);
+ }
+
+ public virtual void WriteUint16(int s)
+ {
+ Debug.Assert(s < 0x10000);
+ Put((byte) Functions.Lsb(s >> 8));
+ Put((byte) Functions.Lsb(s));
+ }
+
+ public virtual void WriteUint32(long i)
+ {
+ Debug.Assert(i < 0x100000000L);
+ Put((byte) Functions.Lsb(i >> 24));
+ Put((byte) Functions.Lsb(i >> 16));
+ Put((byte) Functions.Lsb(i >> 8));
+ Put((byte) Functions.Lsb(i));
+ }
+
+ public void WriteSequenceNo(int i)
+ {
+ WriteUint32(i);
+ }
+
+ public virtual void WriteUint64(long l)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ Put((byte) Functions.Lsb(l >> (56 - i*8)));
+ }
+ }
+
+ public abstract void WriteInt8(short b) ;
+ public abstract void WriteInt16(int s) ;
+ public abstract void WriteInt32(long i) ;
+ public abstract void WriteInt64(long l) ;
+ public abstract void WriteFloat(float f) ;
+ public abstract void WriteDouble(double d) ;
+
+ public void WriteDatetime(long l)
+ {
+ WriteUint64(l);
+ }
+
+ private static byte[] Encode(String s, Encoding encoding)
+ {
+ return encoding.GetBytes(s);
+ }
+
+ public void WriteStr8(String s)
+ {
+ if (s == null)
+ {
+ s = "";
+ }
+
+ byte[] bytes;
+ if (! str8cache.ContainsKey(s))
+ {
+ bytes = Encode(s, System.Text.Encoding.UTF8);
+ str8cache.Add(s, bytes);
+ }
+ else
+ {
+ bytes = str8cache[s];
+ }
+ WriteUint8((short) bytes.Length);
+ Put(bytes);
+ }
+
+ public void WriteStr16(String s)
+ {
+ if (s == null)
+ {
+ s = "";
+ }
+
+ byte[] bytes = Encode(s, System.Text.Encoding.UTF8);
+ WriteUint16(bytes.Length);
+ Put(bytes);
+ }
+
+ public void WriteVbin8(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ bytes = new byte[0];
+ }
+ if (bytes.Length > 255)
+ {
+ throw new Exception("array too long: " + bytes.Length);
+ }
+ WriteUint8((short) bytes.Length);
+ Put(bytes);
+ }
+
+ public void WriteVbin16(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ bytes = new byte[0];
+ }
+ WriteUint16(bytes.Length);
+ Put(bytes);
+ }
+
+ public void WriteVbin32(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ bytes = new byte[0];
+ }
+ WriteUint32(bytes.Length);
+ Put(bytes);
+ }
+
+ public void WriteSequenceSet(RangeSet ranges)
+ {
+ if (ranges == null)
+ {
+ WriteUint16(0);
+ }
+ else
+ {
+ WriteUint16(ranges.Size()*8);
+ foreach (Range range in ranges)
+ {
+ WriteSequenceNo(range.Lower);
+ WriteSequenceNo(range.Upper);
+ }
+ }
+ }
+
+ public void WriteByteRanges(RangeSet ranges)
+ {
+ throw new Exception("not implemented");
+ }
+
+ public void WriteUuid(UUID uuid)
+ {
+ long msb = 0;
+ long lsb = 0;
+ if (uuid != null)
+ {
+ msb = uuid.MostSignificantBits;
+ lsb = uuid.LeastSignificantBits;
+ }
+ WriteUint64(msb);
+ WriteUint64(lsb);
+ }
+
+ public void WriteStruct(int type, Struct s)
+ {
+ if (s == null)
+ {
+ s = Struct.Create(type);
+ }
+
+ int width = s.GetSizeWidth();
+ int pos = -1;
+ if (width > 0)
+ {
+ pos = BeginSize(width);
+ }
+
+ if (type > 0)
+ {
+ WriteUint16(type);
+ }
+
+ s.Write(this);
+
+ if (width > 0)
+ {
+ EndSize(width, pos);
+ }
+ }
+
+ public void WriteStruct32(Struct s)
+ {
+ if (s == null)
+ {
+ WriteUint32(0);
+ }
+ else
+ {
+ int pos = BeginSize32();
+ WriteUint16(s.GetEncodedType());
+ s.Write(this);
+ EndSize32(pos);
+ }
+ }
+
+ private Code Encoding(Object value)
+ {
+ if (value == null)
+ {
+ return Code.VOID;
+ }
+
+ Type klass = value.GetType();
+ Code type = Resolve(klass);
+
+ if (type == Code.VOID)
+ {
+ throw new Exception
+ ("unable to resolve type: " + klass + ", " + value);
+ }
+ else
+ {
+ return type;
+ }
+ }
+
+ private static Code Resolve(Type klass)
+ {
+ Code type;
+ if(ENCODINGS.ContainsKey(klass))
+ {
+ return ENCODINGS[klass];
+ }
+
+ Type sup = klass.BaseType;
+ if (sup != null)
+ {
+ type = Resolve(sup);
+
+ if (type != Code.VOID)
+ {
+ return type;
+ }
+ }
+ foreach (Type iface in klass.GetInterfaces())
+ {
+ type = Resolve(iface);
+ if (type != Code.VOID)
+ {
+ return type;
+ }
+ }
+ return Code.VOID;
+ }
+
+ public void WriteMap(Dictionary<String, Object> map)
+ {
+ int pos = BeginSize32();
+ if (map != null)
+ {
+ WriteUint32(map.Count);
+ WriteMapEntries(map);
+ }
+ EndSize32(pos);
+ }
+
+ protected void WriteMapEntries(Dictionary<String, Object> map)
+ {
+ foreach (KeyValuePair<String, Object> entry in map)
+ {
+ String key = entry.Key;
+ Object value = entry.Value;
+ Code type = Encoding(value);
+ WriteStr8(key);
+ Put((byte) type);
+ Write(type, value);
+ }
+ }
+
+ public void WriteList(List<Object> list)
+ {
+ int pos = BeginSize32();
+ if (list != null)
+ {
+ WriteUint32(list.Count);
+ WriteListEntries(list);
+ }
+ EndSize32(pos);
+ }
+
+ protected void WriteListEntries(List<Object> list)
+ {
+ foreach (Object value in list)
+ {
+ Code type = Encoding(value);
+ Put((byte) type);
+ Write(type, value);
+ }
+ }
+
+ public void WriteArray(List<Object> array)
+ {
+ int pos = BeginSize32();
+ if (array != null)
+ {
+ WriteArrayEntries(array);
+ }
+ EndSize32(pos);
+ }
+
+ protected void WriteArrayEntries(List<Object> array)
+ {
+ Code type;
+
+ if (array.Count == 0)
+ {
+ return;
+ }
+ else
+ {
+ type = Encoding(array[0]);
+ }
+ Put((byte) type);
+ WriteUint32(array.Count);
+
+ foreach (Object value in array)
+ {
+ Write(type, value);
+ }
+ }
+
+ private void WriteSize(QpidType t, int size)
+ {
+ if (t.Fixed)
+ {
+ if (size != t.width)
+ {
+ throw new Exception("size does not match fixed width " + t.width + ": " + size);
+ }
+ }
+ else
+ {
+ WriteSize(t.width, size);
+ }
+ }
+
+ private void WriteSize(int width, int size)
+ {
+ // XXX: should check lengths
+ switch (width)
+ {
+ case 1:
+ WriteUint8((short) size);
+ break;
+ case 2:
+ WriteUint16(size);
+ break;
+ case 4:
+ WriteUint32(size);
+ break;
+ default:
+ throw new Exception("illegal width: " + width);
+ }
+ }
+
+ private int BeginSize(int width)
+ {
+ switch (width)
+ {
+ case 1:
+ return BeginSize8();
+ case 2:
+ return BeginSize16();
+ case 4:
+ return BeginSize32();
+ default:
+ throw new Exception("illegal width: " + width);
+ }
+ }
+
+ private void EndSize(int width, int pos)
+ {
+ switch (width)
+ {
+ case 1:
+ EndSize8(pos);
+ break;
+ case 2:
+ EndSize16(pos);
+ break;
+ case 4:
+ EndSize32(pos);
+ break;
+ default:
+ throw new Exception("illegal width: " + width);
+ }
+ }
+
+ private void WriteBytes(QpidType t, byte[] bytes)
+ {
+ WriteSize(t, bytes.Length);
+ Put(bytes);
+ }
+
+ private void Write(Code t, Object value)
+ {
+ switch (t)
+ {
+ case Code.BIN8:
+ case Code.UINT8:
+ WriteUint8((short) value);
+ break;
+ case Code.INT8:
+ Put((Byte) value);
+ break;
+ case Code.CHAR:
+ byte[] b = BitConverter.GetBytes((char) value);
+ Put(b[0]);
+ break;
+ case Code.BOOLEAN:
+ if ((bool) value)
+ {
+ Put(1);
+ }
+ else
+ {
+ Put(0);
+ }
+
+ break;
+
+ case Code.BIN16:
+ case Code.UINT16:
+ WriteUint16((int) value);
+ break;
+
+ case Code.INT16:
+ WriteUint16((short) value);
+ break;
+
+ case Code.BIN32:
+ case Code.UINT32:
+ WriteUint32((long) value);
+ break;
+
+ case Code.CHAR_UTF32:
+ case Code.INT32:
+ WriteUint32((int) value);
+ break;
+
+ case Code.FLOAT:
+ WriteUint32(BitConverter.DoubleToInt64Bits((float) value) >> 32);
+ break;
+
+ case Code.BIN64:
+ case Code.UINT64:
+ case Code.INT64:
+ case Code.DATETIME:
+ WriteUint64((long) value);
+ break;
+
+ case Code.DOUBLE:
+ WriteUint64( BitConverter.DoubleToInt64Bits((double) value));
+ break;
+
+ case Code.UUID:
+ WriteUuid((UUID) value);
+ break;
+
+ case Code.STR8:
+ WriteStr8((string) value);
+ break;
+
+ case Code.STR16:
+ WriteStr16((string) value);
+ break;
+
+ case Code.STR8_LATIN:
+ case Code.STR8_UTF16:
+ case Code.STR16_LATIN:
+ case Code.STR16_UTF16:
+ // XXX: need to do character conversion
+ WriteBytes(QpidType.get((byte) t), Encode((string) value, System.Text.Encoding.Unicode));
+ break;
+
+ case Code.MAP:
+ WriteMap((Dictionary<String, Object>) value);
+ break;
+ case Code.LIST:
+ WriteList((List<Object>) value);
+ break;
+ case Code.ARRAY:
+ WriteList((List<Object>) value);
+ break;
+ case Code.STRUCT32:
+ WriteStruct32((Struct) value);
+ break;
+
+ case Code.BIN40:
+ case Code.DEC32:
+ case Code.BIN72:
+ case Code.DEC64:
+ // XXX: what types are we supposed to use here?
+ WriteBytes(QpidType.get((byte) t), (byte[]) value);
+ break;
+
+ case Code.VOID:
+ break;
+
+ default:
+ WriteBytes(QpidType.get((byte) t), (byte[]) value);
+ break;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/Decoder.cs b/dotnet/client-010/client/transport/codec/Decoder.cs
new file mode 100644
index 0000000000..9afc23fd4e
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/Decoder.cs
@@ -0,0 +1,72 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// Decoder
+ /// </summary>
+
+ public interface Decoder
+ {
+
+ bool hasRemaining();
+
+ short readUint8();
+ int readUint16();
+ long readUint32();
+ long readUint64();
+
+ short readInt8();
+ int readInt16();
+ long readInt32();
+ long readInt64();
+
+ double readDouble() ;
+ float readFloat() ;
+ long readDatetime();
+
+ UUID readUuid();
+
+ int readSequenceNo();
+ RangeSet readSequenceSet(); // XXX
+ RangeSet readByteRanges(); // XXX
+
+ String readStr8();
+ String readStr16();
+
+ byte[] readVbin8();
+ byte[] readVbin16();
+ byte[] readVbin32();
+
+ Struct readStruct32();
+ Dictionary<String, Object> readMap();
+ List<Object> readList();
+ List<Object> readArray();
+
+ Struct readStruct(int type);
+ }
+
+}
diff --git a/dotnet/client-010/client/transport/codec/Encodable.cs b/dotnet/client-010/client/transport/codec/Encodable.cs
new file mode 100644
index 0000000000..71f4f62458
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/Encodable.cs
@@ -0,0 +1,37 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport.codec
+{
+
+
+ /// <summary>
+ /// Encodable
+ /// </summary>
+
+ public interface Encodable
+ {
+
+ void write(Encoder enc);
+
+ void read(Decoder dec);
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/codec/Encoder.cs b/dotnet/client-010/client/transport/codec/Encoder.cs
new file mode 100644
index 0000000000..282e3ff5b5
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/Encoder.cs
@@ -0,0 +1,70 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+using RangeSet = org.apache.qpid.transport.RangeSet;
+using Struct = org.apache.qpid.transport.Struct;
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// Encoder
+ /// </summary>
+
+ public interface Encoder
+ {
+
+ void writeUint8(short b);
+ void writeUint16(int s);
+ void writeUint32(long i);
+ void writeUint64(long l);
+
+ void writeInt8(short b);
+ void writeInt16(int s);
+ void writeInt32(long i);
+ void writeInt64(long l);
+
+ void writeFloat(float f) ;
+ void writeDouble(double d) ;
+
+ void writeDatetime(long l);
+ void writeUuid(UUID uuid);
+
+ void writeSequenceNo(int s);
+ void writeSequenceSet(RangeSet ranges); // XXX
+ void writeByteRanges(RangeSet ranges); // XXX
+
+ void writeStr8(string s);
+ void writeStr16(string s);
+
+ void writeVbin8(byte[] bytes);
+ void writeVbin16(byte[] bytes);
+ void writeVbin32(byte[] bytes);
+
+ void writeStruct32(Struct s);
+ void writeMap(Dictionary<String, Object> map);
+ void writeList(List<Object> list);
+ void writeArray(List<Object> array);
+
+ void writeStruct(int type, Struct s);
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/IDecoder.cs b/dotnet/client-010/client/transport/codec/IDecoder.cs
new file mode 100644
index 0000000000..7de2e93fe7
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/IDecoder.cs
@@ -0,0 +1,72 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// Decoder
+ /// </summary>
+
+ public interface IDecoder
+ {
+
+ bool HasRemaining();
+
+ short ReadUint8();
+ int ReadUint16();
+ long ReadUint32();
+ long ReadUint64();
+
+ short ReadInt8();
+ int ReadInt16();
+ long ReadInt32();
+ long ReadInt64();
+
+ double ReadDouble() ;
+ float ReadFloat() ;
+ long ReadDatetime();
+
+ UUID ReadUuid();
+
+ int ReadSequenceNo();
+ RangeSet ReadSequenceSet(); // XXX
+ RangeSet ReadByteRanges(); // XXX
+
+ String ReadStr8();
+ String ReadStr16();
+
+ byte[] ReadVbin8();
+ byte[] ReadVbin16();
+ byte[] ReadVbin32();
+
+ Struct ReadStruct32();
+ Dictionary<String, Object> ReadMap();
+ List<Object> ReadList();
+ List<Object> ReadArray();
+
+ Struct ReadStruct(int type);
+ }
+
+}
diff --git a/dotnet/client-010/client/transport/codec/IEncodable.cs b/dotnet/client-010/client/transport/codec/IEncodable.cs
new file mode 100644
index 0000000000..5c63e17fdd
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/IEncodable.cs
@@ -0,0 +1,37 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport.codec
+{
+
+
+ /// <summary>
+ /// Encodable
+ /// </summary>
+
+ public interface IEncodable
+ {
+
+ void Write(IEncoder enc);
+
+ void Read(IDecoder dec);
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/IEncoder.cs b/dotnet/client-010/client/transport/codec/IEncoder.cs
new file mode 100644
index 0000000000..4ffc852052
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/IEncoder.cs
@@ -0,0 +1,70 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+using RangeSet = org.apache.qpid.transport.RangeSet;
+using Struct = org.apache.qpid.transport.Struct;
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// Encoder
+ /// </summary>
+
+ public interface IEncoder
+ {
+
+ void WriteUint8(short b);
+ void WriteUint16(int s);
+ void WriteUint32(long i);
+ void WriteUint64(long l);
+
+ void WriteInt8(short b);
+ void WriteInt16(int s);
+ void WriteInt32(long i);
+ void WriteInt64(long l);
+
+ void WriteFloat(float f) ;
+ void WriteDouble(double d) ;
+
+ void WriteDatetime(long l);
+ void WriteUuid(UUID uuid);
+
+ void WriteSequenceNo(int s);
+ void WriteSequenceSet(RangeSet ranges); // XXX
+ void WriteByteRanges(RangeSet ranges); // XXX
+
+ void WriteStr8(string s);
+ void WriteStr16(string s);
+
+ void WriteVbin8(byte[] bytes);
+ void WriteVbin16(byte[] bytes);
+ void WriteVbin32(byte[] bytes);
+
+ void WriteStruct32(Struct s);
+ void WriteMap(Dictionary<String, Object> map);
+ void WriteList(List<Object> list);
+ void WriteArray(List<Object> array);
+
+ void WriteStruct(int type, Struct s);
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/MSDecoder.cs b/dotnet/client-010/client/transport/codec/MSDecoder.cs
new file mode 100644
index 0000000000..59731b739a
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/MSDecoder.cs
@@ -0,0 +1,110 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.IO;
+using System.Text;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+
+
+ /// <summary>
+ /// MSDecoder
+ ///
+ /// </summary>
+
+
+ public sealed class MSDecoder : AbstractDecoder
+ {
+
+ private BinaryReader _reader;
+
+ public void Init(MemoryStream st)
+ {
+ _reader = new BinaryReader(st, Encoding.BigEndianUnicode);
+ }
+
+ protected override byte DoGet()
+ {
+ return _reader.ReadByte();
+ }
+
+ protected override void DoGet(byte[] bytes)
+ {
+ _reader.Read(bytes, 0, bytes.Length);
+ }
+
+ public override bool HasRemaining()
+ {
+ return (_reader.BaseStream.Position < _reader.BaseStream.Length);
+ }
+
+ public override short ReadUint8()
+ {
+ return (short) (0xFF & _reader.ReadByte());
+ }
+
+ public override int ReadUint16()
+ {
+ return ByteEncoder.GetBigEndian((UInt16) _reader.ReadInt16());
+ }
+
+ public override long ReadUint32()
+ {
+ return ByteEncoder.GetBigEndian((UInt32) _reader.ReadInt32());
+ }
+
+ public override long ReadUint64()
+ {
+ return (long) ByteEncoder.GetBigEndian(_reader.ReadInt64());
+ }
+
+ public override short ReadInt8()
+ {
+ return (short) (0xFF & _reader.ReadByte());
+ }
+
+ public override int ReadInt16()
+ {
+ return ByteEncoder.GetBigEndian((Int16) _reader.ReadInt16());
+ }
+
+ public override long ReadInt32()
+ {
+ return ByteEncoder.GetBigEndian((Int32) _reader.ReadInt32());
+ }
+
+ public override long ReadInt64()
+ {
+ return (long) ByteEncoder.GetBigEndian(_reader.ReadInt64());
+ }
+
+ public override double ReadDouble() {
+ return (double) ByteEncoder.GetBigEndian(_reader.ReadDouble()) ;
+ }
+
+ public override float ReadFloat() {
+ return (float) _reader.ReadSingle() ;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/codec/MSEncoder.cs b/dotnet/client-010/client/transport/codec/MSEncoder.cs
new file mode 100644
index 0000000000..d863c57dee
--- /dev/null
+++ b/dotnet/client-010/client/transport/codec/MSEncoder.cs
@@ -0,0 +1,172 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.codec
+{
+ /// <summary>
+ /// MSEncoder
+ /// </summary>
+ public sealed class MSEncoder : AbstractEncoder
+ {
+ private readonly MemoryStream _out;
+ private readonly BinaryWriter _writer;
+
+ public MSEncoder(int capacity)
+ {
+ _out = new MemoryStream(capacity);
+ _writer = new BinaryWriter(_out);
+ }
+
+ public void Init()
+ {
+ _out.Seek(0, SeekOrigin.Begin);
+ }
+
+ public MemoryStream Segment()
+ {
+ int length = (int) _out.Position;
+ MemoryStream result = new MemoryStream(_out.ToArray(), 0, length);
+ result.Seek(length, SeekOrigin.Begin);
+ _out.Seek(0, SeekOrigin.Begin);
+ return result;
+ }
+
+
+ protected override void DoPut(byte b)
+ {
+ _writer.Write(b);
+ }
+
+ protected override void DoPut(MemoryStream src)
+ {
+ _writer.Write(src.ToArray());
+ }
+
+ protected override void Put(byte[] bytes)
+ {
+ _writer.Write(bytes);
+ }
+
+ public override void WriteUint8(short b)
+ {
+ Debug.Assert(b < 0x100);
+ _writer.Write((byte) b);
+ }
+
+ public override void WriteUint16(int s)
+ {
+ Debug.Assert(s < 0x10000);
+ _writer.Write(ByteEncoder.GetBigEndian((UInt16) s));
+ }
+
+ public override void WriteUint32(long i)
+ {
+ Debug.Assert(i < 0x100000000L);
+ _writer.Write(ByteEncoder.GetBigEndian((UInt32) i));
+ }
+
+ public override void WriteUint64(long l)
+ {
+ _writer.Write(ByteEncoder.GetBigEndian(l));
+ }
+
+ public override void WriteInt8(short b)
+ {
+ Debug.Assert(b < 0x100);
+ _writer.Write((byte) b);
+ }
+
+ public override void WriteInt16(int s)
+ {
+ Debug.Assert(s < 0x10000);
+ _writer.Write(ByteEncoder.GetBigEndian((Int16) s));
+ }
+
+ public override void WriteInt32(long i)
+ {
+ Debug.Assert(i < 0x100000000L);
+ _writer.Write(ByteEncoder.GetBigEndian((Int32) i));
+ }
+
+ public override void WriteInt64(long l)
+ {
+ _writer.Write(ByteEncoder.GetBigEndian(l));
+ }
+
+ public override void WriteFloat(float f) {
+ _writer.Write(f) ;
+ }
+
+ public override void WriteDouble(double d) {
+ _writer.Write(ByteEncoder.GetBigEndian(d)) ;
+ }
+
+ protected override int BeginSize8()
+ {
+ int pos = (int) _out.Position;
+ _writer.Write((byte) 0);
+ return pos;
+ }
+
+ protected override void EndSize8(int pos)
+ {
+ int cur = (int) _out.Position;
+ _out.Seek(pos, SeekOrigin.Begin);
+ _writer.Write((byte) (cur - pos - 1));
+ _out.Seek(cur, SeekOrigin.Begin);
+ }
+
+ protected override int BeginSize16()
+ {
+ int pos = (int) _out.Position;
+ _writer.Write((short) 0);
+ return pos;
+ }
+
+ protected override void EndSize16(int pos)
+ {
+ int cur = (int) _out.Position;
+ _out.Seek(pos, SeekOrigin.Begin);
+ _writer.Write((short) (cur - pos - 2));
+ _out.Seek(cur, SeekOrigin.Begin);
+ }
+
+ protected override int BeginSize32()
+ {
+ int pos = (int) _out.Position;
+ _writer.Write(0);
+ return pos;
+ }
+
+ protected override void EndSize32(int pos)
+ {
+ int cur = (int) _out.Position;
+ _out.Seek(pos, SeekOrigin.Begin);
+ _writer.Write(ByteEncoder.GetBigEndian((Int32) cur - pos - 4));
+ _out.Seek(cur, SeekOrigin.Begin);
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/exception/ConnectionException.cs b/dotnet/client-010/client/transport/exception/ConnectionException.cs
new file mode 100644
index 0000000000..cbf5e39e52
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/ConnectionException.cs
@@ -0,0 +1,49 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+namespace org.apache.qpid.transport
+{
+
+
+ /// <summary>
+ /// ConnectionException
+ /// </summary>
+
+ [Serializable]
+ public class ConnectionException : Exception
+ {
+ virtual public ConnectionClose Close
+ {
+ get
+ {
+ return _close;
+ }
+
+ }
+
+ private ConnectionClose _close;
+
+ public ConnectionException(ConnectionClose close):base(close.GetReplyText())
+ {
+ _close = close;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/exception/ExceptionArgs.cs b/dotnet/client-010/client/transport/exception/ExceptionArgs.cs
new file mode 100644
index 0000000000..01793a6ad0
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/ExceptionArgs.cs
@@ -0,0 +1,41 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.transport
+{
+ public class ExceptionArgs : EventArgs
+ {
+ public ExceptionArgs(Exception e)
+ {
+ _exception = e;
+ }
+ private Exception _exception;
+
+ public Exception Exception
+ {
+ get { return _exception; }
+ set { _exception = value; }
+ }
+
+ }
+}
diff --git a/dotnet/client-010/client/transport/exception/ProtocolVersionException.cs b/dotnet/client-010/client/transport/exception/ProtocolVersionException.cs
new file mode 100644
index 0000000000..f18fc1173f
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/ProtocolVersionException.cs
@@ -0,0 +1,59 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+namespace org.apache.qpid.transport
+{
+
+
+ /// <summary> ProtocolVersionException
+ ///
+ /// </summary>
+
+ [Serializable]
+ public sealed class ProtocolVersionException:TransportException
+ {
+ public sbyte Major
+ {
+ get
+ {
+ return _major;
+ }
+
+ }
+ public sbyte Minor
+ {
+ get
+ {
+ return _minor;
+ }
+
+ }
+
+ private sbyte _major;
+ private sbyte _minor;
+
+ public ProtocolVersionException(sbyte major, sbyte minor):base(String.Format("version missmatch: %{0}-{1}", major, minor))
+ {
+ this._major = major;
+ this._minor = minor;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/exception/SessionClosedException.cs b/dotnet/client-010/client/transport/exception/SessionClosedException.cs
new file mode 100644
index 0000000000..89453433ee
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/SessionClosedException.cs
@@ -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.
+*
+*/
+using System.Collections.Generic;
+
+namespace org.apache.qpid.transport
+{
+
+
+ /// <summary>
+ /// SessionClosedException
+ /// </summary>
+
+ public class SessionClosedException : SessionException
+ {
+
+ public SessionClosedException(): base(new List<ExecutionException>())
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/exception/SessionException.cs b/dotnet/client-010/client/transport/exception/SessionException.cs
new file mode 100644
index 0000000000..f02ffa5c2f
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/SessionException.cs
@@ -0,0 +1,45 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+using System.Collections.Generic;
+
+namespace org.apache.qpid.transport
+{
+ /// <summary>
+ /// SessionException
+ /// </summary>
+ public class SessionException : Exception
+ {
+ private readonly List<ExecutionException> _exceptions;
+
+ public SessionException(List<ExecutionException> exceptions)
+ : base(exceptions.Count == 0 ? "" : exceptions.ToString())
+
+ {
+ _exceptions = exceptions;
+ }
+
+ public List<ExecutionException> Exceptions
+ {
+ get { return _exceptions; }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/exception/TransportException.cs b/dotnet/client-010/client/transport/exception/TransportException.cs
new file mode 100644
index 0000000000..d016f90a83
--- /dev/null
+++ b/dotnet/client-010/client/transport/exception/TransportException.cs
@@ -0,0 +1,46 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+namespace org.apache.qpid.transport
+{
+
+
+ /// <summary>
+ /// TransportException
+ /// </summary>
+
+
+ public class TransportException : Exception
+ {
+ public TransportException(String msg) : base(msg)
+ {
+ }
+
+ public TransportException(String msg, Exception cause) : base(msg, cause)
+ {
+ }
+
+ public TransportException(Exception cause): base("Transport Exception", cause)
+ {
+ }
+
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/Assembler.cs b/dotnet/client-010/client/transport/network/Assembler.cs
new file mode 100644
index 0000000000..ff85f11c2f
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/Assembler.cs
@@ -0,0 +1,254 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using org.apache.qpid.transport.codec;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.network
+{
+ /// <summary>
+ /// Assembler
+ /// </summary>
+ public delegate void Processor(INetworkDelegate ndelegate);
+
+ public class Assembler : INetworkDelegate, IReceiver<ReceivedPayload<IProtocolEvent>>
+ {
+ private static readonly Logger log = Logger.Get(typeof (Assembler));
+ private readonly Dictionary<int, List<byte[]>> segments;
+ private readonly Method[] incomplete;
+ [ThreadStatic] static MSDecoder _decoder;
+ private readonly Object m_objectLock = new object();
+
+ // the event raised when a buffer is read from the wire
+ public event EventHandler<ReceivedPayload<IProtocolEvent>> ReceivedEvent;
+ public event EventHandler Closed;
+
+
+ // Not in use :
+ public event EventHandler<ExceptionArgs> Exception;
+
+ event EventHandler<ReceivedPayload<IProtocolEvent>> IReceiver<ReceivedPayload<IProtocolEvent>>.Received
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ReceivedEvent += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ReceivedEvent -= value;
+ }
+ }
+ }
+
+ public Assembler()
+ {
+ segments = new Dictionary<int, List<byte[]>>();
+ incomplete = new Method[64*1024];
+ }
+
+ // Invoked when a network event is received
+ public void On_ReceivedEvent(object sender, ReceivedPayload<INetworkEvent> payload)
+ {
+ payload.Payload.ProcessNetworkEvent(this);
+ }
+
+ #region Interface INetworkDelegate
+
+ public void Init(ProtocolHeader header)
+ {
+ Emit(0, header);
+ }
+
+ public void Error(ProtocolError error)
+ {
+ Emit(0, error);
+ }
+
+ public void Frame(Frame frame)
+ {
+ MemoryStream segment;
+ if (frame.IsFirstFrame() && frame.IsLastFrame())
+ {
+ byte[] tmp = new byte[frame.BodySize];
+ frame.Body.Read(tmp, 0, tmp.Length);
+ segment = new MemoryStream();
+ BinaryWriter w = new BinaryWriter(segment);
+ w.Write(tmp);
+ Assemble(frame, new MemoryStream(tmp));
+ }
+ else
+ {
+ List<byte[]> frames;
+ if (frame.IsFirstFrame())
+ {
+ frames = new List<byte[]>();
+ SetSegment(frame, frames);
+ }
+ else
+ {
+ frames = GetSegment(frame);
+ }
+ byte[] tmp = new byte[frame.BodySize];
+ frame.Body.Read(tmp, 0, tmp.Length);
+ frames.Add(tmp);
+
+ if (frame.IsLastFrame())
+ {
+ ClearSegment(frame);
+ segment = new MemoryStream();
+ BinaryWriter w = new BinaryWriter(segment);
+ foreach (byte[] f in frames)
+ {
+ w.Write(f);
+ }
+ Assemble(frame, segment);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private Support Functions
+
+
+ private MSDecoder GetDecoder()
+ {
+ if( _decoder == null )
+ {
+ _decoder = new MSDecoder();
+ }
+ return _decoder;
+ }
+
+ private void Assemble(Frame frame, MemoryStream segment)
+ {
+ MSDecoder decoder = GetDecoder();
+ decoder.Init(segment);
+ int channel = frame.Channel;
+ Method command;
+ switch (frame.Type)
+ {
+ case SegmentType.CONTROL:
+ int controlType = decoder.ReadUint16();
+ Method control = Method.Create(controlType);
+ control.Read(decoder);
+ Emit(channel, control);
+ break;
+ case SegmentType.COMMAND:
+ int commandType = decoder.ReadUint16();
+ // read in the session header, right now we don't use it
+ decoder.ReadUint16();
+ command = Method.Create(commandType);
+ command.Read(decoder);
+ if (command.HasPayload())
+ {
+ incomplete[channel] = command;
+ }
+ else
+ {
+ Emit(channel, command);
+ }
+ break;
+ case SegmentType.HEADER:
+ command = incomplete[channel];
+ List<Struct> structs = new List<Struct>();
+ while (decoder.HasRemaining())
+ {
+ structs.Add(decoder.ReadStruct32());
+ }
+ command.Header = new Header(structs);
+ if (frame.IsLastSegment())
+ {
+ incomplete[channel] = null;
+ Emit(channel, command);
+ }
+ break;
+ case SegmentType.BODY:
+ command = incomplete[channel];
+ segment.Seek(0, SeekOrigin.Begin);
+ command.Body = segment;
+ incomplete[channel] = null;
+ Emit(channel, command);
+ break;
+ default:
+ throw new Exception("unknown frame type: " + frame.Type);
+ }
+ }
+
+ private int SegmentKey(Frame frame)
+ {
+ return (frame.Track + 1)*frame.Channel;
+ }
+
+ private List<byte[]> GetSegment(Frame frame)
+ {
+ return segments[SegmentKey(frame)];
+ }
+
+ private void SetSegment(Frame frame, List<byte[]> segment)
+ {
+ int key = SegmentKey(frame);
+ if (segments.ContainsKey(key))
+ {
+ Error(new ProtocolError(network.Frame.L2, "segment in progress: %s",
+ frame));
+ }
+ segments.Add(SegmentKey(frame), segment);
+ }
+
+ private void ClearSegment(Frame frame)
+ {
+ segments.Remove(SegmentKey(frame));
+ }
+
+ // Emit a protocol event
+ private void Emit(int channel, IProtocolEvent protevent)
+ {
+ protevent.Channel = channel;
+ log.Debug("Assembler: protocol event:", protevent);
+ ReceivedPayload<IProtocolEvent> payload = new ReceivedPayload<IProtocolEvent>();
+ payload.Payload = protevent;
+
+ if (protevent is ConnectionCloseOk)
+ {
+ if (Closed != null)
+ Closed(this, EventArgs.Empty);
+ }
+ else
+ {
+ if (ReceivedEvent != null)
+ ReceivedEvent(this, payload);
+ else
+ log.Debug("No listener for event: {0}", protevent);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/Disassembler.cs b/dotnet/client-010/client/transport/network/Disassembler.cs
new file mode 100644
index 0000000000..3f0a6a8974
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/Disassembler.cs
@@ -0,0 +1,222 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+using org.apache.qpid.transport.codec;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.network
+{
+ /// <summary>
+ /// Disassembler
+ /// </summary>
+ public sealed class Disassembler : ISender<IProtocolEvent>, IProtocolDelegate<Object>
+ {
+ private readonly IIoSender<MemoryStream> _sender;
+ private readonly int _maxPayload;
+ private readonly MemoryStream _header;
+ private readonly BinaryWriter _writer;
+ private readonly Object _sendlock = new Object();
+ [ThreadStatic] static MSEncoder _encoder;
+
+
+ public Disassembler(IIoSender<MemoryStream> sender, int maxFrame)
+ {
+ if (maxFrame <= network.Frame.HEADER_SIZE || maxFrame >= 64*1024)
+ {
+ throw new Exception(String.Format("maxFrame must be > {0} and < 64K: ", network.Frame.HEADER_SIZE) + maxFrame);
+ }
+ _sender = sender;
+ _maxPayload = maxFrame - network.Frame.HEADER_SIZE;
+ _header = new MemoryStream(network.Frame.HEADER_SIZE);
+ _writer = new BinaryWriter(_header);
+ }
+
+ #region Sender Interface
+
+ public void Send(IProtocolEvent pevent)
+ {
+ pevent.ProcessProtocolEvent(null, this);
+ }
+
+ public void Flush()
+ {
+ lock (_sendlock)
+ {
+ _sender.Flush();
+ }
+ }
+
+ public void Close()
+ {
+ lock (_sendlock)
+ {
+ _sender.Close();
+ }
+ }
+
+ #endregion
+
+ #region ProtocolDelegate<Object> Interface
+
+ public void Init(Object v, ProtocolHeader header)
+ {
+ lock (_sendlock)
+ {
+ _sender.Send(header.ToMemoryStream());
+ _sender.Flush();
+ }
+ }
+
+ public void Control(Object v, Method method)
+ {
+ InvokeMethod(method, SegmentType.CONTROL);
+ }
+
+ public void Command(Object v, Method method)
+ {
+ InvokeMethod(method, SegmentType.COMMAND);
+ }
+
+ public void Error(Object v, ProtocolError error)
+ {
+ throw new Exception("Error: " + error);
+ }
+
+ #endregion
+
+ #region private
+
+ private void Frame(byte flags, byte type, byte track, int channel, int size, MemoryStream buf)
+ {
+ lock (_sendlock)
+ {
+ _writer.Write(flags);
+ _writer.Write(type);
+ _writer.Write(ByteEncoder.GetBigEndian((UInt16)(size + network.Frame.HEADER_SIZE)));
+ _writer.Write((byte)0);
+ _writer.Write(track);
+ _writer.Write(ByteEncoder.GetBigEndian((UInt16)( channel)));
+ _writer.Write((byte)0);
+ _writer.Write((byte)0);
+ _writer.Write((byte)0);
+ _writer.Write((byte)0);
+ _sender.Send(_header);
+ _header.Seek(0, SeekOrigin.Begin);
+ _sender.Send(buf, size);
+ }
+ }
+
+ private void Fragment(byte flags, SegmentType type, IProtocolEvent mevent, MemoryStream buf)
+ {
+ byte typeb = (byte) type;
+ byte track = mevent.EncodedTrack == network.Frame.L4 ? (byte) 1 : (byte) 0;
+ int remaining = (int) buf.Length;
+ buf.Seek(0, SeekOrigin.Begin);
+ bool first = true;
+ while (true)
+ {
+ int size = Math.Min(_maxPayload, remaining);
+ remaining -= size;
+
+ byte newflags = flags;
+ if (first)
+ {
+ newflags |= network.Frame.FIRST_FRAME;
+ first = false;
+ }
+ if (remaining == 0)
+ {
+ newflags |= network.Frame.LAST_FRAME;
+ }
+
+ Frame(newflags, typeb, track, mevent.Channel, size, buf);
+
+ if (remaining == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ private MSEncoder GetEncoder()
+ {
+ if( _encoder == null)
+ {
+ _encoder = new MSEncoder(4 * 1024);
+ }
+ return _encoder;
+ }
+
+ private void InvokeMethod(Method method, SegmentType type)
+ {
+ MSEncoder encoder = GetEncoder();
+ encoder.Init();
+ encoder.WriteUint16(method.GetEncodedType());
+ if (type == SegmentType.COMMAND)
+ {
+ if (method.Sync)
+ {
+ encoder.WriteUint16(0x0101);
+ }
+ else
+ {
+ encoder.WriteUint16(0x0100);
+ }
+ }
+ method.Write(_encoder);
+ MemoryStream methodSeg = encoder.Segment();
+
+ byte flags = network.Frame.FIRST_SEG;
+
+ bool payload = method.HasPayload();
+ if (!payload)
+ {
+ flags |= network.Frame.LAST_SEG;
+ }
+
+ MemoryStream headerSeg = null;
+ if (payload)
+ {
+ Header hdr = method.Header;
+ Struct[] structs = hdr.Structs;
+
+ foreach (Struct st in structs)
+ {
+ encoder.WriteStruct32(st);
+ }
+ headerSeg = encoder.Segment();
+ }
+
+ lock (_sendlock)
+ {
+ Fragment(flags, type, method, methodSeg);
+ if (payload)
+ {
+ Fragment( 0x0, SegmentType.HEADER, method, headerSeg);
+ Fragment(network.Frame.LAST_SEG, SegmentType.BODY, method, method.Body);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/Frame.cs b/dotnet/client-010/client/transport/network/Frame.cs
new file mode 100644
index 0000000000..b8ec36d8b6
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/Frame.cs
@@ -0,0 +1,143 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+
+namespace org.apache.qpid.transport.network
+{
+ public sealed class Frame : INetworkEvent
+ {
+ internal static int HEADER_SIZE = 12;
+
+ // XXX: enums?
+ public const byte L1 = 0;
+ public const byte L2 = 1;
+ public const byte L3 = 2;
+ public const byte L4 = 3;
+
+ public static byte RESERVED = 0x0;
+
+ public static byte VERSION = 0x0;
+
+ public static byte FIRST_SEG = 0x8;
+ public static byte LAST_SEG = 0x4;
+ public static byte FIRST_FRAME = 0x2;
+ public static byte LAST_FRAME = 0x1;
+
+ private readonly byte flags;
+ private readonly SegmentType type;
+ private readonly byte track;
+ private readonly int channel;
+ private readonly MemoryStream body;
+ private int _bodySize;
+
+
+ public Frame(byte flags, SegmentType type, byte track, int channel, int bodySize,
+ MemoryStream body)
+ {
+ this.flags = flags;
+ this.type = type;
+ this.track = track;
+ this.channel = channel;
+ this.body = body;
+ _bodySize = bodySize;
+ }
+
+ public int BodySize
+ {
+ get { return _bodySize; }
+ }
+
+ public MemoryStream Body
+ {
+ get { return body; }
+ }
+
+ public byte Flags
+ {
+ get { return flags; }
+ }
+
+ public int Channel
+ {
+ get { return channel; }
+ }
+
+ public int Size
+ {
+ get { return (int) body.Length;}
+ }
+
+ public SegmentType Type
+ {
+ get { return type; }
+ }
+
+ public byte Track
+ {
+ get { return track; }
+ }
+
+ private bool Flag(byte mask)
+ {
+ return (flags & mask) != 0;
+ }
+
+ public bool IsFirstSegment()
+ {
+ return Flag(FIRST_SEG);
+ }
+
+ public bool IsLastSegment()
+ {
+ return Flag(LAST_SEG);
+ }
+
+ public bool IsFirstFrame()
+ {
+ return Flag(FIRST_FRAME);
+ }
+
+ public bool IsLastFrame()
+ {
+ return Flag(LAST_FRAME);
+ }
+
+ #region INetworkEvent Methods
+
+ public void ProcessNetworkEvent(INetworkDelegate ndelegate)
+ {
+ ndelegate.Frame(this);
+ }
+
+ #endregion
+
+ public override String ToString()
+ {
+ return String.Format
+ ("[{0:d} {1:d} {2:d} {3} {4}{5}{6}{7}] ", Channel, Size, Track, Type,
+ IsFirstSegment() ? 1 : 0, IsLastSegment() ? 1 : 0,
+ IsFirstFrame() ? 1 : 0, IsLastFrame() ? 1 : 0);
+ }
+
+
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/IIoSender.cs b/dotnet/client-010/client/transport/network/IIoSender.cs
new file mode 100644
index 0000000000..747b5b9f98
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/IIoSender.cs
@@ -0,0 +1,28 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport.network
+{
+ public interface IIOSender<T>:Sender<T>
+ {
+ void send(T body, int siz);
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/INetworkDelegate.cs b/dotnet/client-010/client/transport/network/INetworkDelegate.cs
new file mode 100644
index 0000000000..9226adc2b7
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/INetworkDelegate.cs
@@ -0,0 +1,40 @@
+/*
+*
+* 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.
+*
+*/
+using ProtocolError = org.apache.qpid.transport.ProtocolError;
+using ProtocolHeader = org.apache.qpid.transport.ProtocolHeader;
+namespace org.apache.qpid.transport.network
+{
+
+
+ /// <summary>
+ /// NetworkDelegate
+ /// </summary>
+
+ public interface INetworkDelegate
+ {
+
+ void Init(ProtocolHeader header);
+
+ void Frame(Frame frame);
+
+ void Error(ProtocolError error);
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/INetworkEvent.cs b/dotnet/client-010/client/transport/network/INetworkEvent.cs
new file mode 100644
index 0000000000..e6f0d6fc8a
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/INetworkEvent.cs
@@ -0,0 +1,32 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport.network
+{
+
+ /// <summary>
+ /// INetworkEvent
+ /// </summary>
+
+ public interface INetworkEvent
+ {
+ void ProcessNetworkEvent(INetworkDelegate networkDelegate);
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/InputHandler.cs b/dotnet/client-010/client/transport/network/InputHandler.cs
new file mode 100644
index 0000000000..c5d5f13727
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/InputHandler.cs
@@ -0,0 +1,266 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+using System.Text;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.network
+{
+ /// <summary>
+ /// InputHandler
+ /// </summary>
+ public sealed class InputHandler : IReceiver<ReceivedPayload<INetworkEvent>>
+ {
+ public enum State
+ {
+ PROTO_HDR,
+ FRAME_HDR,
+ FRAME_BODY,
+ ERROR
+ }
+
+ private static readonly Logger log = Logger.Get(typeof(InputHandler));
+ private readonly Object m_objectLock = new object();
+
+ // the event raised when a buffer is read from the wire
+ public event EventHandler<ReceivedPayload<INetworkEvent>> ReceivedEvent;
+ public event EventHandler<ExceptionArgs> ExceptionProcessing;
+
+ // Not in used... This even is never raised in the code => the application will block on Close() until the timeout is reached
+ public event EventHandler Closed;
+
+ event EventHandler<ReceivedPayload<INetworkEvent>> IReceiver<ReceivedPayload<INetworkEvent>>.Received
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ReceivedEvent += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ReceivedEvent -= value;
+ }
+ }
+ }
+
+ event EventHandler<ExceptionArgs> IReceiver<ReceivedPayload<INetworkEvent>>.Exception
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ExceptionProcessing += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ExceptionProcessing -= value;
+ }
+ }
+ }
+
+ private State state;
+ private MemoryStream input;
+ private int needed;
+
+ private byte flags;
+ private SegmentType type;
+ private byte track;
+ private int channel;
+
+ public InputHandler(State state)
+ {
+ this.state = state;
+ switch (state)
+ {
+ case State.PROTO_HDR:
+ needed = 8;
+ break;
+ case State.FRAME_HDR:
+ needed = Frame.HEADER_SIZE;
+ break;
+ }
+ }
+
+ // The command listening for a buffer read.
+ public void On_ReceivedBuffer(object sender, ReceivedPayload<MemoryStream> payload)
+ {
+ MemoryStream buf = payload.Payload;
+ int remaining = (int) buf.Length;
+ if( input != null )
+ {
+ remaining += (int) input.Length;
+ }
+ try
+ {
+ while (remaining > 0)
+ {
+ if (remaining >= needed)
+ {
+ if (input != null)
+ {
+ byte[] tmp = new byte[buf.Length];
+ buf.Read(tmp, 0, tmp.Length);
+ input.Write(tmp, 0, tmp.Length);
+ input.Seek(0, SeekOrigin.Begin);
+ buf = input;
+ }
+ int startPos = (int)buf.Position;
+ int consumed = needed;
+ state = Next(buf);
+ if ((buf.Position - startPos) < consumed)
+ {
+ buf.Seek(consumed - (buf.Position - startPos), SeekOrigin.Current);
+ }
+ remaining -= consumed;
+ input = null;
+ }
+ else
+ {
+ byte[] tmp;
+ if (input == null)
+ {
+ input = new MemoryStream();
+ tmp = new byte[remaining];
+ }
+ else
+ {
+ // this is a full buffer
+ tmp = new byte[buf.Length];
+ }
+ buf.Read(tmp, 0, tmp.Length);
+ input.Write(tmp, 0, tmp.Length);
+ remaining = 0;
+ }
+ }
+ }
+ catch (Exception t)
+ {
+ Console.Write(t);
+ if (ExceptionProcessing != null)
+ {
+ ExceptionProcessing(this, new ExceptionArgs(t));
+ }
+ }
+ }
+
+ #region Private Support Functions
+
+ private State Next(MemoryStream buf)
+ {
+ BinaryReader reader = new BinaryReader(buf);
+
+ switch (state)
+ {
+ case State.PROTO_HDR:
+ char a = reader.ReadChar();
+ char m = reader.ReadChar();
+ char q = reader.ReadChar();
+ char p = reader.ReadChar();
+ if (a != 'A' &&
+ m != 'M' &&
+ q != 'Q' &&
+ p != 'P')
+ {
+ Error("bad protocol header: {0}", buf.ToString());
+ return State.ERROR;
+ }
+ reader.ReadByte();
+ byte instance = reader.ReadByte();
+ byte major = reader.ReadByte();
+ byte minor = reader.ReadByte();
+ Fire_NetworkEvent(new ProtocolHeader(instance, major, minor));
+ needed = Frame.HEADER_SIZE;
+ return State.FRAME_HDR;
+ case State.FRAME_HDR:
+ reader = new BinaryReader(buf, Encoding.BigEndianUnicode);
+ flags = reader.ReadByte();
+ type = SegmentTypeGetter.Get(reader.ReadByte()); // generated code
+ int size = reader.ReadUInt16();
+ size = ByteEncoder.GetBigEndian((UInt16)size);
+ size -= Frame.HEADER_SIZE;
+ if (size < 0 || size > (64 * 1024 - 12))
+ {
+ Error("bad frame size: {0:d}", size);
+ return State.ERROR;
+ }
+ reader.ReadByte();
+ byte b = reader.ReadByte();
+ if ((b & 0xF0) != 0)
+ {
+ Error("non-zero reserved bits in upper nibble of " +
+ "frame header byte 5: {0}", b);
+ return State.ERROR;
+ }
+ track = (byte)(b & 0xF);
+ channel = reader.ReadUInt16();
+ channel = ByteEncoder.GetBigEndian((UInt16)channel);
+ if (size == 0)
+ {
+ Fire_NetworkEvent(new Frame(flags, type, track, channel, 0, new MemoryStream()));
+ needed = Frame.HEADER_SIZE;
+ return State.FRAME_HDR;
+ }
+ needed = size;
+ return State.FRAME_BODY;
+ case State.FRAME_BODY:
+ Fire_NetworkEvent(new Frame(flags, type, track, channel, needed, buf));
+ needed = Frame.HEADER_SIZE;
+ return State.FRAME_HDR;
+ default:
+ if (ExceptionProcessing != null)
+ {
+ ExceptionProcessing(this, new ExceptionArgs(new Exception("Error creating frame")));
+ }
+ throw new Exception("Error creating frame");
+ }
+ }
+
+ private void Error(String fmt, params Object[] args)
+ {
+ Fire_NetworkEvent(new ProtocolError(Frame.L1, fmt, args));
+ }
+
+ private void Fire_NetworkEvent(INetworkEvent netevent)
+ {
+ log.Debug("InputHandler: network event:", netevent);
+ ReceivedPayload<INetworkEvent> payload = new ReceivedPayload<INetworkEvent>();
+ payload.Payload = netevent;
+ if (ReceivedEvent != null)
+ {
+ ReceivedEvent(this, payload);
+ }
+ else
+ {
+ log.Debug("Nobody listening for event: {0}");
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/NetworkDelegate.cs b/dotnet/client-010/client/transport/network/NetworkDelegate.cs
new file mode 100644
index 0000000000..69598a43e8
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/NetworkDelegate.cs
@@ -0,0 +1,40 @@
+/*
+*
+* 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.
+*
+*/
+using ProtocolError = org.apache.qpid.transport.ProtocolError;
+using ProtocolHeader = org.apache.qpid.transport.ProtocolHeader;
+namespace org.apache.qpid.transport.network
+{
+
+
+ /// <summary>
+ /// NetworkDelegate
+ /// </summary>
+
+ public interface NetworkDelegate
+ {
+
+ void Init(ProtocolHeader header);
+
+ void Frame(Frame frame);
+
+ void Error(ProtocolError error);
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/NetworkEvent.cs b/dotnet/client-010/client/transport/network/NetworkEvent.cs
new file mode 100644
index 0000000000..e5ac6de93a
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/NetworkEvent.cs
@@ -0,0 +1,32 @@
+/*
+*
+* 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.
+*
+*/
+namespace org.apache.qpid.transport.network
+{
+
+ /// <summary>
+ /// NetworkEvent
+ /// </summary>
+
+ public interface NetworkEvent
+ {
+ void ProcessNetworkEvent(NetworkDelegate networkDelegate);
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/io/IIoSender.cs b/dotnet/client-010/client/transport/network/io/IIoSender.cs
new file mode 100644
index 0000000000..acc7724a06
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IIoSender.cs
@@ -0,0 +1,28 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport.network
+{
+ public interface IIoSender<T>:ISender<T>
+ {
+ void Send(T body, int siz);
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/io/IIoTransport.cs b/dotnet/client-010/client/transport/network/io/IIoTransport.cs
new file mode 100644
index 0000000000..41a09e7079
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IIoTransport.cs
@@ -0,0 +1,57 @@
+/*
+* 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.
+*/
+using System.IO;
+using System.Net.Sockets;
+
+namespace org.apache.qpid.transport.network.io
+{
+ public interface IIoTransport
+ {
+ Connection Connection
+ {
+ get;
+ set;
+ }
+
+ IReceiver<ReceivedPayload<MemoryStream>> Receiver
+ {
+ get;
+ set;
+ }
+
+ IoSender Sender
+ {
+ get;
+ set;
+ }
+
+
+ Stream Stream
+ {
+ get;
+ set;
+ }
+
+ TcpClient Socket
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/io/IoReceiver.cs b/dotnet/client-010/client/transport/network/io/IoReceiver.cs
new file mode 100644
index 0000000000..b60444fa29
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IoReceiver.cs
@@ -0,0 +1,185 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.IO;
+using System.Threading;
+using Logger = org.apache.qpid.transport.util.Logger;
+
+
+namespace org.apache.qpid.transport.network.io
+{
+ /// <summary>
+ /// IoReceiver
+ /// </summary>
+ public sealed class IoReceiver : IReceiver<ReceivedPayload<MemoryStream>>
+ {
+ private static readonly Logger log = Logger.Get(typeof(IoReceiver));
+ private readonly int m_bufferSize;
+ private readonly Stream m_bufStream;
+ private readonly int m_timeout;
+ private readonly Thread m_thread;
+ private bool m_closed;
+ private readonly Object m_objectLock = new object();
+
+ // the event raised when a buffer is read from the wire
+ event EventHandler<ReceivedPayload<MemoryStream>> ReceivedBuffer;
+ event EventHandler<ExceptionArgs> ExceptionReading;
+ event EventHandler ReceiverClosed;
+
+ event EventHandler<ReceivedPayload<MemoryStream>> IReceiver<ReceivedPayload<MemoryStream>>.Received
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ReceivedBuffer += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ReceivedBuffer -= value;
+ }
+ }
+ }
+
+ event EventHandler<ExceptionArgs> IReceiver<ReceivedPayload<MemoryStream>>.Exception
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ExceptionReading += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ExceptionReading -= value;
+ }
+ }
+ }
+
+ event EventHandler IReceiver<ReceivedPayload<MemoryStream>>.Closed
+ {
+ add
+ {
+ lock (m_objectLock)
+ {
+ ReceiverClosed += value;
+ }
+ }
+ remove
+ {
+ lock (m_objectLock)
+ {
+ ReceiverClosed -= value;
+ }
+ }
+ }
+
+ public IoReceiver(Stream stream, int bufferSize, int timeout)
+ {
+ m_bufferSize = bufferSize;
+ m_bufStream = stream;
+ m_timeout = timeout;
+ m_thread = new Thread(Go);
+ m_thread.Name = String.Format("IoReceiver - {0}", stream);
+ m_thread.IsBackground = true;
+ m_thread.Start();
+ }
+
+ public void Close()
+ {
+ Mutex mut = new Mutex();
+ mut.WaitOne();
+ if (!m_closed)
+ {
+ m_closed = true;
+ try
+ {
+ log.Debug("Receiver closing");
+ m_bufStream.Close();
+ m_thread.Join(m_timeout);
+ if (m_thread.IsAlive)
+ {
+ throw new TransportException("join timed out");
+ }
+ }
+ catch (ThreadInterruptedException e)
+ {
+ throw new TransportException(e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+ }
+ mut.ReleaseMutex();
+ }
+
+ void Go()
+ {
+ // create a BufferedStream on top of the NetworkStream.
+ int threshold = m_bufferSize/2;
+ byte[] buffer = new byte[m_bufferSize];
+ try
+ {
+ int read;
+ int offset = 0;
+ ReceivedPayload<MemoryStream> payload = new ReceivedPayload<MemoryStream>();
+ while ((read = m_bufStream.Read(buffer, offset, m_bufferSize - offset)) > 0)
+ {
+ MemoryStream memStream = new MemoryStream(buffer, offset, read);
+ if (ReceivedBuffer != null)
+ {
+ // call the event
+ payload.Payload = memStream;
+ ReceivedBuffer(this, payload);
+ }
+ offset += read;
+ if (offset > threshold)
+ {
+ offset = 0;
+ buffer = new byte[m_bufferSize];
+ }
+ }
+ log.Debug("Receiver thread terminating");
+ }
+ catch (Exception t)
+ {
+ if (ExceptionReading != null)
+ {
+ ExceptionReading(this, new ExceptionArgs(t));
+ }
+ }
+ finally
+ {
+ if (ReceiverClosed != null)
+ {
+ ReceiverClosed(this, new EventArgs());
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs b/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs
new file mode 100644
index 0000000000..b6c7940a1d
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IoSSLTransport.cs
@@ -0,0 +1,227 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+using System;
+using System.IO;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+
+using org.apache.qpid.transport.util;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.transport.network.io
+{
+ public sealed class IoSSLTransport : IIoTransport
+ {
+ // constants
+ private const int DEFAULT_READ_WRITE_BUFFER_SIZE = 64*1024;
+ private const int TIMEOUT = 60000;
+ private const int QUEUE_SIZE = 1000;
+ // props
+ private static readonly Logger log = Logger.Get(typeof (IoSSLTransport));
+ private Stream m_stream;
+ private IoSender m_sender;
+ private IReceiver<ReceivedPayload<MemoryStream>> m_receiver;
+ private TcpClient m_socket;
+ private Connection m_con;
+ private readonly bool _rejectUntrusted;
+
+ public static Connection Connect(String host, int port, String mechanism, X509Certificate certificate, bool rejectUntrusted, Client client)
+ {
+ ClientConnectionDelegate connectionDelegate = new ClientConnectionDelegate(client, string.Empty, string.Empty, mechanism);
+ ManualResetEvent negotiationComplete = new ManualResetEvent(true);
+ connectionDelegate.SetCondition(negotiationComplete);
+ connectionDelegate.VirtualHost = string.Empty;
+
+ IIoTransport transport = new IoSSLTransport(host, port, certificate, rejectUntrusted, connectionDelegate);
+
+ Connection _conn = transport.Connection;
+ _conn.Send(new ProtocolHeader(1, 0, 10));
+ negotiationComplete.WaitOne();
+
+ if (connectionDelegate.Exception != null)
+ throw connectionDelegate.Exception;
+
+ connectionDelegate.SetCondition(null);
+
+ return _conn;
+ }
+
+ public static Connection Connect(String host, int port, String virtualHost, String mechanism, string serverName, string certPath, String certPass, bool rejectUntrusted, Client client)
+ {
+ // create certificate object based on whether or not password is null
+ X509Certificate cert;
+ if (certPass != null)
+ {
+ cert = new X509Certificate2(certPath, certPass);
+ }
+ else
+ {
+ cert = X509Certificate.CreateFromCertFile(certPath);
+ }
+
+ return Connect(host, port, mechanism, cert, rejectUntrusted, client);
+ }
+
+ public IoSSLTransport(String host, int port, X509Certificate certificate, bool rejectUntrusted, ConnectionDelegate conndel)
+ {
+ _rejectUntrusted = rejectUntrusted;
+ CreateSocket(host, port);
+ CreateSSLStream(host, Socket, certificate);
+ Sender = new IoSender(this, QUEUE_SIZE, TIMEOUT);
+ Receiver = new IoReceiver(Stream, Socket.ReceiveBufferSize*2, TIMEOUT);
+ Assembler assembler = new Assembler();
+ InputHandler inputHandler = new InputHandler(InputHandler.State.PROTO_HDR);
+ Connection = new Connection(assembler, new Disassembler(Sender, 64*1024 - 1), conndel);
+ // Input handler listen to Receiver events
+ Receiver.Received += inputHandler.On_ReceivedBuffer;
+ // Assembler listen to inputhandler events
+ inputHandler.ReceivedEvent += assembler.On_ReceivedEvent;
+ // Connection listen to asembler protocol event
+ Receiver.Closed += Connection.On_ReceivedClosed;
+ assembler.Closed += Connection.On_ReceivedClosed;
+ Receiver.Exception += Connection.On_ReceivedException;
+ inputHandler.ExceptionProcessing += Connection.On_ReceivedException;
+ assembler.ReceivedEvent += Connection.On_ReceivedEvent;
+ }
+
+ public Connection Connection
+ {
+ get { return m_con; }
+ set { m_con = value; }
+ }
+
+ public IReceiver<ReceivedPayload<MemoryStream>> Receiver
+ {
+ get { return m_receiver; }
+ set { m_receiver = value; }
+ }
+
+ public IoSender Sender
+ {
+ get { return m_sender; }
+ set { m_sender = value; }
+ }
+
+
+ public Stream Stream
+ {
+ get { return m_stream; }
+ set { m_stream = value; }
+ }
+
+ public TcpClient Socket
+ {
+ get { return m_socket; }
+ set { m_socket = value; }
+ }
+
+ #region Private Support Functions
+
+ private void CreateSocket(String host, int port)
+ {
+ TcpClient socket;
+ try
+ {
+ socket = new TcpClient();
+ String noDelay = Environment.GetEnvironmentVariable("qpid.tcpNoDelay");
+ String writeBufferSize = Environment.GetEnvironmentVariable("qpid.writeBufferSize");
+ String readBufferSize = Environment.GetEnvironmentVariable("qpid.readBufferSize");
+ socket.NoDelay = noDelay != null && bool.Parse(noDelay);
+ socket.ReceiveBufferSize = readBufferSize == null
+ ? DEFAULT_READ_WRITE_BUFFER_SIZE
+ : int.Parse(readBufferSize);
+ socket.SendBufferSize = writeBufferSize == null
+ ? DEFAULT_READ_WRITE_BUFFER_SIZE
+ : int.Parse(writeBufferSize);
+
+ log.Debug("NoDelay : {0}", socket.NoDelay);
+ log.Debug("ReceiveBufferSize : {0}", socket.ReceiveBufferSize);
+ log.Debug("SendBufferSize : {0}", socket.SendBufferSize);
+ log.Debug("Openning connection with host : {0}; port: {1}", host, port);
+
+ socket.Connect(host, port);
+ Socket = socket;
+ }
+ catch (Exception e)
+ {
+ throw new TransportException(string.Format("Error connecting to broker: {0}", e.Message));
+ }
+ }
+
+ private void CreateSSLStream(String host, TcpClient socket, X509Certificate certificate)
+ {
+ try
+ {
+ //Initializes a new instance of the SslStream class using the specified Stream, stream closure behavior, certificate validation delegate and certificate selection delegate
+ SslStream sslStream = new SslStream(socket.GetStream(), false, ValidateServerCertificate, LocalCertificateSelection);
+
+ X509CertificateCollection certCol = new X509CertificateCollection();
+ certCol.Add(certificate);
+
+ sslStream.AuthenticateAsClient(host, certCol, SslProtocols.Default, true);
+ Stream = sslStream;
+ }
+ catch (AuthenticationException e)
+ {
+ log.Warn("Exception: {0}", e.Message);
+ if (e.InnerException != null)
+ {
+ log.Warn("Inner exception: {0}", e.InnerException.Message);
+ e = new AuthenticationException(e.InnerException.Message, e.InnerException);
+ }
+ socket.Close();
+ throw new TransportException(string.Format("Authentication failed, closing connection to broker: {0}", e.Message));
+ }
+ }
+
+ // The following method is invoked by the RemoteCertificateValidationDelegate.
+ public bool ValidateServerCertificate(
+ object sender,
+ X509Certificate certificate,
+ X509Chain chain,
+ SslPolicyErrors sslPolicyErrors)
+ {
+ bool result = true;
+ if (sslPolicyErrors != SslPolicyErrors.None && _rejectUntrusted )
+ {
+ log.Warn("Certificate error: {0}", sslPolicyErrors);
+ // Do not allow this client to communicate with unauthenticated servers.
+ result = false;
+ }
+ return result;
+ }
+
+ public X509Certificate LocalCertificateSelection(
+ Object sender,
+ string targetHost,
+ X509CertificateCollection localCertificates,
+ X509Certificate remoteCertificate,
+ string[] acceptableIssuers
+ )
+ {
+ // used to be return null; in the original version
+ return localCertificates[0];
+ }
+
+ #endregion
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/io/IoSender.cs b/dotnet/client-010/client/transport/network/io/IoSender.cs
new file mode 100644
index 0000000000..025b782a12
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IoSender.cs
@@ -0,0 +1,137 @@
+/*
+* 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.
+*/
+using System;
+using System.IO;
+using System.Threading;
+using common.org.apache.qpid.transport.util;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.network.io
+{
+ public sealed class IoSender : IIoSender<MemoryStream>
+ {
+ private static readonly Logger log = Logger.Get(typeof (IoReceiver));
+ private readonly IIoTransport ioTransport;
+ private readonly Stream bufStream;
+ private bool closed;
+ private readonly Mutex mutClosed = new Mutex();
+ private readonly CircularBuffer<byte[]> queue;
+ private readonly Thread thread;
+ private readonly int timeout;
+ private readonly MemoryStream _tobeSent = new MemoryStream();
+ public IoSender(IIoTransport transport, int queueSize, int timeout)
+ {
+ this.timeout = timeout;
+ ioTransport = transport;
+ bufStream = transport.Stream;
+ queue = new CircularBuffer<byte[]>(queueSize);
+ thread = new Thread(Go);
+ log.Debug("Creating IoSender thread");
+ thread.Name = String.Format("IoSender - {0}", transport.Socket) ;
+ thread.IsBackground = true;
+ thread.Start();
+ }
+
+ public void Send(MemoryStream str)
+ {
+ int pos = (int) str.Position;
+ str.Seek(0, SeekOrigin.Begin);
+ Send(str, pos);
+ }
+
+ public void Send(MemoryStream str, int size)
+ {
+ mutClosed.WaitOne();
+ if (closed)
+ {
+ throw new TransportException("sender is Closed");
+ }
+ mutClosed.ReleaseMutex();
+ byte[] buf = new byte[size];
+ str.Read(buf, 0, size);
+ _tobeSent.Write(buf, 0, size);
+ }
+
+ public void Flush()
+ {
+ int length = (int)_tobeSent.Position;
+ byte[] buf = new byte[length];
+ _tobeSent.Seek(0, SeekOrigin.Begin);
+ _tobeSent.Read(buf, 0, length);
+ queue.Enqueue(buf);
+ // bufStream.Write(buf, 0, length);
+ // _tobeSent = new MemoryStream();
+ // _writer.Write(buf, 0, length);
+ // _writer.Flush();
+ _tobeSent.Seek(0, SeekOrigin.Begin);
+ }
+
+ public void Close()
+ {
+ log.Debug("Closing Sender");
+ mutClosed.WaitOne();
+ if (!closed)
+ {
+ try
+ {
+ closed = true;
+ queue.Close();
+ thread.Join(timeout);
+ if (thread.IsAlive)
+ {
+ throw new TransportException("join timed out");
+ }
+ }
+ catch (ThreadInterruptedException e)
+ {
+ throw new TransportException(e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+ }
+ mutClosed.ReleaseMutex();
+ }
+
+ private void Go()
+ {
+ while (! closed)
+ {
+ //MemoryStream st = queue.Dequeue();
+ byte[] st = queue.Dequeue();
+ if (st != null)
+ {
+ try
+ {
+ // int length = (int) st.Length;
+ // byte[] buf = new byte[length];
+ // st.Read(buf, 0, length);
+ bufStream.Write(st, 0, st.Length);
+ }
+ catch (Exception e)
+ {
+ closed = true;
+ ioTransport.Connection.On_ReceivedException(this, new ExceptionArgs(e));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/network/io/IoTransport.cs b/dotnet/client-010/client/transport/network/io/IoTransport.cs
new file mode 100644
index 0000000000..483e5428b8
--- /dev/null
+++ b/dotnet/client-010/client/transport/network/io/IoTransport.cs
@@ -0,0 +1,141 @@
+/*
+* 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.
+*/
+using System;
+using System.IO;
+using System.Net.Sockets;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport.network.io
+{
+ /// <summary>
+ /// This class provides a socket based transport using sync io classes.
+ ///
+ /// The following params are configurable via JVM arguments
+ /// TCP_NO_DELAY - qpid.tcpNoDelay
+ /// SO_RCVBUF - qpid.readBufferSize
+ /// SO_SNDBUF - qpid.writeBufferSize
+ /// </summary>
+ public sealed class IoTransport : IIoTransport
+ {
+ // constants
+ private const int DEFAULT_READ_WRITE_BUFFER_SIZE = 64*1024;
+ private const int TIMEOUT = 60000;
+ private const int QUEUE_SIZE = 1000;
+ // props
+ private static readonly Logger log = Logger.Get(typeof (IoTransport));
+ private Stream m_stream;
+ private IoSender m_sender;
+ private IReceiver<ReceivedPayload<MemoryStream>> m_receiver;
+ private TcpClient m_socket;
+ private Connection m_con;
+
+ public static Connection Connect(String host, int port, ConnectionDelegate conndel)
+ {
+ IoTransport transport = new IoTransport(host, port, conndel);
+ return transport.Connection;
+ }
+
+ public IoTransport(String host, int port, ConnectionDelegate conndel)
+ {
+ CreateSocket(host, port);
+ Sender = new IoSender(this, QUEUE_SIZE, TIMEOUT);
+ Receiver = new IoReceiver(Stream, Socket.ReceiveBufferSize * 2, TIMEOUT);
+ Assembler assembler = new Assembler();
+ InputHandler inputHandler = new InputHandler(InputHandler.State.PROTO_HDR);
+ Connection = new Connection(assembler, new Disassembler(Sender, 64 * 1024 - 1), conndel);
+ // Input handler listen to Receiver events
+ Receiver.Received += inputHandler.On_ReceivedBuffer;
+ // Assembler listen to inputhandler events
+ inputHandler.ReceivedEvent += assembler.On_ReceivedEvent;
+ // Connection listen to asembler protocol event
+ Receiver.Closed += Connection.On_ReceivedClosed;
+ assembler.Closed += Connection.On_ReceivedClosed;
+ Receiver.Exception += Connection.On_ReceivedException;
+ inputHandler.ExceptionProcessing += Connection.On_ReceivedException;
+ assembler.ReceivedEvent += Connection.On_ReceivedEvent;
+ }
+
+ public Connection Connection
+ {
+ get { return m_con; }
+ set { m_con = value; }
+ }
+
+ public IReceiver<ReceivedPayload<MemoryStream>> Receiver
+ {
+ get { return m_receiver; }
+ set { m_receiver = value; }
+ }
+
+ public IoSender Sender
+ {
+ get { return m_sender; }
+ set { m_sender = value; }
+ }
+
+
+ public Stream Stream
+ {
+ get { return m_stream; }
+ set { m_stream = value; }
+ }
+
+ public TcpClient Socket
+ {
+ get { return m_socket; }
+ set { m_socket = value; }
+ }
+
+ #region Private Support Functions
+
+ private void CreateSocket(String host, int port)
+ {
+ try
+ {
+ TcpClient socket = new TcpClient();
+ String noDelay = Environment.GetEnvironmentVariable("qpid.tcpNoDelay");
+ String writeBufferSize = Environment.GetEnvironmentVariable("qpid.writeBufferSize");
+ String readBufferSize = Environment.GetEnvironmentVariable("qpid.readBufferSize");
+ socket.NoDelay = noDelay != null && bool.Parse(noDelay);
+ socket.ReceiveBufferSize = readBufferSize == null ? DEFAULT_READ_WRITE_BUFFER_SIZE : int.Parse(readBufferSize);
+ socket.SendBufferSize = writeBufferSize == null ? DEFAULT_READ_WRITE_BUFFER_SIZE : int.Parse(writeBufferSize);
+
+ log.Debug("NoDelay : {0}", socket.NoDelay);
+ log.Debug("ReceiveBufferSize : {0}", socket.ReceiveBufferSize);
+ log.Debug("SendBufferSize : {0}", socket.SendBufferSize);
+ log.Debug("Openning connection with host : {0}; port: {1}", host, port);
+
+ socket.Connect(host, port);
+ Socket = socket;
+ Stream = socket.GetStream();
+ }
+ catch (SocketException e)
+ {
+ Console.WriteLine(e.StackTrace);
+ throw new TransportException("Error connecting to broker", e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException("Error connecting to broker", e);
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/client/transport/util/ByteEncoder.cs b/dotnet/client-010/client/transport/util/ByteEncoder.cs
new file mode 100644
index 0000000000..873ca75688
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/ByteEncoder.cs
@@ -0,0 +1,218 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+
+namespace org.apache.qpid.transport.util
+{
+ public static class ByteEncoder
+ {
+ #region Endian conversion helper routines
+ /// <summary>
+ /// Returns the value encoded in Big Endian (PPC, XDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Big-endian encoded value.</returns>
+ public static Int32 GetBigEndian(Int32 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return SwapByteOrder(value);
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Big Endian (PPC, XDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Big-endian encoded value.</returns>
+ public static UInt16 GetBigEndian(UInt16 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return SwapByteOrder(value);
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Big Endian (PPC, XDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Big-endian encoded value.</returns>
+ public static UInt32 GetBigEndian(UInt32 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return SwapByteOrder(value);
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Big Endian (PPC, XDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Big-endian encoded value.</returns>
+ public static long GetBigEndian(long value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return SwapByteOrder(value);
+ }
+ return value;
+ }
+
+ public static double GetBigEndian(double value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return SwapByteOrder(value);
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Little Endian (x86, NDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Little-endian encoded value.</returns>
+ public static Int32 GetLittleEndian(Int32 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return value;
+ }
+ return SwapByteOrder(value);
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Little Endian (x86, NDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Little-endian encoded value.</returns>
+ public static UInt32 GetLittleEndian(UInt32 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return value;
+ }
+ return SwapByteOrder(value);
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Little Endian (x86, NDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Little-endian encoded value.</returns>
+ public static UInt16 GetLittleEndian(UInt16 value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return value;
+ }
+ return SwapByteOrder(value);
+ }
+
+ /// <summary>
+ /// Returns the value encoded in Little Endian (x86, NDR) format.
+ /// </summary>
+ /// <param name="value">Value to encode.</param>
+ /// <returns>Little-endian encoded value.</returns>
+ public static long GetLittleEndian(long value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return value;
+ }
+ return SwapByteOrder(value);
+ }
+
+ public static double GetLittleEndian(double value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ return value;
+ }
+ return SwapByteOrder(value);
+ }
+
+ /// <summary>
+ /// Swaps the Byte order of an <see cref="Int32"/>.
+ /// </summary>
+ /// <param name="value"><see cref="Int32"/> to swap the bytes of.</param>
+ /// <returns>Byte order swapped <see cref="Int32"/>.</returns>
+ private static Int32 SwapByteOrder(Int32 value)
+ {
+ Int32 swapped = (Int32)((0x000000FF) & (value >> 24)
+ | (0x0000FF00) & (value >> 8)
+ | (0x00FF0000) & (value << 8)
+ | (0xFF000000) & (value << 24));
+ return swapped;
+ }
+
+ /// <summary>
+ /// Swaps the byte order of a <see cref="UInt16"/>.
+ /// </summary>
+ /// <param name="value"><see cref="UInt16"/> to swap the bytes of.</param>
+ /// <returns>Byte order swapped <see cref="UInt16"/>.</returns>
+ private static UInt16 SwapByteOrder(UInt16 value)
+ {
+ return (UInt16)((0x00FF & (value >> 8))
+ | (0xFF00 & (value << 8)));
+ }
+
+ /// <summary>
+ /// Swaps the byte order of a <see cref="UInt32"/>.
+ /// </summary>
+ /// <param name="value"><see cref="UInt32"/> to swap the bytes of.</param>
+ /// <returns>Byte order swapped <see cref="UInt32"/>.</returns>
+ private static UInt32 SwapByteOrder(UInt32 value)
+ {
+ UInt32 swapped = ((0x000000FF) & (value >> 24)
+ | (0x0000FF00) & (value >> 8)
+ | (0x00FF0000) & (value << 8)
+ | (0xFF000000) & (value << 24));
+ return swapped;
+ }
+
+ /// <summary>
+ /// Swaps the byte order of a <see cref="Double"/> (double precision IEEE 754)
+ /// </summary>
+ /// <param name="value"><see cref="Double"/> to swap.</param>
+ /// <returns>Byte order swapped <see cref="Double"/> value.</returns>
+ private static long SwapByteOrder(long value)
+ {
+ Byte[] buffer = BitConverter.GetBytes(value);
+ Array.Reverse(buffer, 0, buffer.Length);
+ return BitConverter.ToInt64(buffer, 0);
+ }
+
+ private static double SwapByteOrder(double value)
+ {
+ Byte[] buffer = BitConverter.GetBytes(value);
+ Array.Reverse(buffer, 0, buffer.Length);
+ return BitConverter.ToDouble(buffer,0) ;
+ }
+ #endregion
+ }
+
+}
diff --git a/dotnet/client-010/client/transport/util/CircularBuffer.cs b/dotnet/client-010/client/transport/util/CircularBuffer.cs
new file mode 100644
index 0000000000..00d7b20d4c
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/CircularBuffer.cs
@@ -0,0 +1,132 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Threading;
+
+namespace common.org.apache.qpid.transport.util
+{
+ public class CircularBuffer<T>
+ {
+ private readonly T[] buffer;
+ private Int32 nrp, nwp;
+ private readonly Int32 len;
+ private Int32 countValue;
+ private readonly Int32 add;
+
+
+ /// <summary>
+ /// Constructor creates N=len element
+ /// Circular Buffer that olds MemoryStream
+ /// </summary>
+ public CircularBuffer(Int32 len)
+ {
+ buffer = new T[len];
+ this.len = len;
+ add = 1 - len;
+ nrp = 0;
+ nwp = 0;
+ countValue = 0;
+ }
+
+
+ public void Enqueue(T t)
+ {
+ lock (this)
+ {
+ if (countValue >= (len - 1))
+ {
+ // wait for room to be available
+ Monitor.Wait(this);
+ }
+ bool notifyDequeue = countValue <= 0;
+ Load(t);
+ if (notifyDequeue) //notifyDequeue)
+ {
+ Monitor.PulseAll(this);
+ }
+ }
+ }
+
+
+ public T Dequeue()
+ {
+ lock (this)
+ {
+ if (countValue <= 0)
+ {
+ Monitor.Wait(this);
+ }
+ bool notifyEnqueue = countValue >= (len - 1);
+ T temp = Get();
+ if (notifyEnqueue) //notifyEnqueue)
+ {
+ Monitor.PulseAll(this);
+ }
+ return temp;
+ }
+ }
+
+ public void Close()
+ {
+ nrp = 0;
+ nwp = 0;
+ countValue = 0;
+ Array.Clear(buffer, 0, len);
+ lock (this)
+ {
+ Monitor.PulseAll(this);
+ }
+ }
+
+ #region Private Support Functions
+
+ private void Load(T t)
+ {
+ Int32 i = nwp;
+ buffer[i] = t;
+ i += add;
+ if (i < 0) i += len;
+ nwp = i;
+ UpdateCount();
+ }
+
+ private void UpdateCount()
+ {
+ countValue = nwp - nrp;
+ if (countValue <= 0 )
+ countValue += len; // modulo buffer size
+ }
+
+ private T Get()
+ {
+ Int32 i = nrp;
+ T temp = buffer[i];
+ i += add;
+ if (i < 0) i += len;
+ nrp = i;
+ countValue--;
+ return (temp);
+ }
+
+ #endregion
+ }
+}
diff --git a/dotnet/client-010/client/transport/util/Functions.cs b/dotnet/client-010/client/transport/util/Functions.cs
new file mode 100644
index 0000000000..eee3848386
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/Functions.cs
@@ -0,0 +1,41 @@
+/*
+*
+* 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.
+*
+*/
+
+namespace org.apache.qpid.transport.util
+{
+
+ /// <summary>
+ /// Functions
+ /// </summary>
+
+ public class Functions
+ {
+ public static sbyte Lsb(int i)
+ {
+ return (sbyte) (0xFF & i);
+ }
+
+ public static sbyte Lsb(long l)
+ {
+ return (sbyte) (0xFF & l);
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/util/Logger.cs b/dotnet/client-010/client/transport/util/Logger.cs
new file mode 100644
index 0000000000..f889fe2aab
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/Logger.cs
@@ -0,0 +1,114 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using log4net;
+
+namespace org.apache.qpid.transport.util
+{
+
+ /// <summary> Logger
+ ///
+ /// </summary>
+
+ public sealed class Logger
+ {
+ private readonly ILog log;
+
+ public static Logger Get(Type type)
+ {
+ return new Logger(LogManager.GetLogger(type));
+ }
+
+ private Logger(ILog log)
+ {
+ this.log = log;
+ }
+
+ public bool IsDebugEnabled()
+ {
+ return log.IsDebugEnabled;
+ }
+
+ public void Debug(String message, params Object[] args)
+ {
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(String.Format(message, args));
+ }
+ }
+
+ public void Debug(Exception t, String message, params Object[] args)
+ {
+ if (log.IsDebugEnabled)
+ {
+ log.Debug(String.Format(message, args), t);
+ }
+ }
+
+ public void Error(String message, params Object[] args)
+ {
+ if (log.IsErrorEnabled)
+ {
+ log.Error(String.Format(message, args));
+ }
+ }
+
+ public void Error(Exception t, String message, params Object[] args)
+ {
+ if (log.IsErrorEnabled)
+ {
+ log.Error(String.Format(message, args), t);
+ }
+ }
+
+ public void Warn(String message, params Object[] args)
+ {
+ if (log.IsWarnEnabled)
+ {
+ log.Warn(String.Format(message, args));
+ }
+ }
+
+ public void Warn(Exception t, String message, params Object[] args)
+ {
+ if (log.IsWarnEnabled)
+ {
+ log.Warn(String.Format(message, args), t);
+ }
+ }
+
+ public void Info(String message, params Object[] args)
+ {
+ if (log.IsInfoEnabled)
+ {
+ log.Info(String.Format(message, args));
+ }
+ }
+
+ public void Info(Exception t, String message, params Object[] args)
+ {
+ if (log.IsInfoEnabled)
+ {
+ log.Info(String.Format(message, args), t);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/util/ResultFuture.cs b/dotnet/client-010/client/transport/util/ResultFuture.cs
new file mode 100644
index 0000000000..0de2b27656
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/ResultFuture.cs
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Threading;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace common.org.apache.qpid.transport.util
+{
+ public class ResultFuture : IFuture
+ {
+ const long _timeout = 60000;
+ private Struct _result;
+ private Session _session;
+ private static readonly Logger log = Logger.Get(typeof(ResultFuture));
+
+ public Struct Get(long timeout)
+ {
+ lock (this)
+ {
+ DateTime start = DateTime.Now;
+ long elapsed = 0;
+ while (! _session.IsClosed && timeout - elapsed > 0 && _result == null)
+ {
+ log.Debug("{0} waiting for result: {1}", _session, this );
+ Monitor.Wait(this, (int) (timeout - elapsed));
+ elapsed = (long) (DateTime.Now.Subtract(start)).TotalMilliseconds;
+ }
+ }
+ if( _session.IsClosed )
+ {
+ throw new SessionException(_session.GetExceptions());
+ }
+ return _result;
+ }
+
+ public Struct Result
+ {
+ get { return Get(_timeout); }
+ set
+ {
+ lock (this)
+ {
+ _result = value;
+ Monitor.PulseAll(this);
+ }
+ }
+ }
+
+ public Session Session
+ {
+ set { _session = value; }
+ }
+
+ public override String ToString()
+ {
+ return String.Format("Future({0})", _result);
+ }
+
+ }
+}
diff --git a/dotnet/client-010/client/transport/util/Serial.cs b/dotnet/client-010/client/transport/util/Serial.cs
new file mode 100644
index 0000000000..874097084a
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/Serial.cs
@@ -0,0 +1,94 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+namespace org.apache.qpid.transport.util
+{
+ /// <summary>
+ /// This class provides basic serial number comparisons as defined in
+ /// RFC 1982.
+ /// </summary>
+ public class Serial
+ {
+ ///
+ ///
+ ///Compares two numbers using serial arithmetic.
+ ///
+ /// param s1 the first serial number
+ /// param s2 the second serial number
+ ///
+ /// return a negative integer, zero, or a positive integer as the
+ /// first argument is less than, equal to, or greater than the
+ /// second
+ ///
+ public static int Compare(int s1, int s2)
+ {
+ return s1 - s2;
+ }
+
+ public static bool Lt(int s1, int s2)
+ {
+ return Compare(s1, s2) < 0;
+ }
+
+ public static bool Le(int s1, int s2)
+ {
+ return Compare(s1, s2) <= 0;
+ }
+
+ public static bool Gt(int s1, int s2)
+ {
+ return Compare(s1, s2) > 0;
+ }
+
+ public static bool Ge(int s1, int s2)
+ {
+ return Compare(s1, s2) >= 0;
+ }
+
+ public static bool Eq(int s1, int s2)
+ {
+ return s1 == s2;
+ }
+
+ public static int Min(int s1, int s2)
+ {
+ if (Lt(s1, s2))
+ {
+ return s1;
+ }
+ else
+ {
+ return s2;
+ }
+ }
+
+ public static int Max(int s1, int s2)
+ {
+ if (Gt(s1, s2))
+ {
+ return s1;
+ }
+ else
+ {
+ return s2;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/client/transport/util/UUID.cs b/dotnet/client-010/client/transport/util/UUID.cs
new file mode 100644
index 0000000000..07a3d267a5
--- /dev/null
+++ b/dotnet/client-010/client/transport/util/UUID.cs
@@ -0,0 +1,129 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.transport.util
+{
+ public class UUID
+ {
+ private long _mostSigBits;
+ private long _leastSigBits;
+ private static readonly Random _random = new Random();
+ private static readonly object _randomLock = new object();
+
+
+ public UUID(long mostSigBits, long leastSigBits)
+ {
+ _mostSigBits = mostSigBits;
+ _leastSigBits = leastSigBits;
+ }
+
+ public long MostSignificantBits
+ {
+ get { return _mostSigBits; }
+ set { _mostSigBits = value; }
+ }
+
+ public long LeastSignificantBits
+ {
+ get { return _leastSigBits; }
+ set { _leastSigBits = value; }
+ }
+
+ internal UUID(byte[] r)
+ {
+ MostSignificantBits = 0;
+ LeastSignificantBits = 0;
+ for (int i = 0; i < 8; i++)
+ MostSignificantBits = (MostSignificantBits << 8) | (r[i] & 0xff);
+ for (int i = 8; i < 16; i++)
+ LeastSignificantBits = (LeastSignificantBits << 8) | (r[i] & 0xff);
+ }
+
+ public static UUID RandomUuid()
+ {
+ byte[] randomBytes = new byte[16];
+ lock (_randomLock)
+ {
+ _random.NextBytes(randomBytes);
+ }
+
+ randomBytes[6] &= 0x0f;
+ randomBytes[6] |= 0x40;
+ randomBytes[8] &= 0x3f;
+ randomBytes[8] |= 0x80;
+
+ return new UUID(randomBytes);
+ }
+
+
+ public override String ToString()
+ {
+ return (Digits(_mostSigBits >> 32, 8) + "-" +
+ Digits(_mostSigBits >> 16, 4) + "-" +
+ Digits(_mostSigBits, 4) + "-" +
+ Digits(_leastSigBits >> 48, 4) + "-" +
+ Digits(_leastSigBits, 12));
+ }
+
+ private static String Digits(long val, int digits)
+ {
+ long hi = 1L << (digits * 4);
+ return Convert.ToString((hi | (val & (hi - 1))), 16);
+ }
+
+ #region equality
+ public bool Equals(UUID other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return other._mostSigBits == _mostSigBits && other._leastSigBits == _leastSigBits;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != typeof (UUID)) return false;
+ return Equals((UUID) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (_mostSigBits.GetHashCode()*397) ^ _leastSigBits.GetHashCode();
+ }
+ }
+
+ public static bool operator ==(UUID left, UUID right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(UUID left, UUID right)
+ {
+ return !Equals(left, right);
+ }
+ #endregion
+ }
+}
diff --git a/dotnet/client-010/default.build b/dotnet/client-010/default.build
new file mode 100644
index 0000000000..eb6ee371f7
--- /dev/null
+++ b/dotnet/client-010/default.build
@@ -0,0 +1,275 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Qpid.NET" default="build">
+
+ <!-- Determines the formatter to use to format output of test results. -->
+ <property name="nant.formatter" value="Plain" />
+
+ <!-- Determines whether a 'debug' or 'release' build is to be done. Defaults to 'debug' -->
+ <property name="build.config" value="debug" />
+
+ <!-- Sets build properties consistently accross all assemblies in the project. -->
+ <property name="build.version.major" value="0"/>
+ <property name="build.version.minor" value="5"/>
+ <property name="build.version.build" value="0"/>
+ <property name="build.version.revision" value="0"/>
+ <property name="build.company" value="Apache Software Foundation"/>
+ <property name="build.copyright" value="Apache Software Foundation"/>
+ <property name="build.description" value="Built from svn revision number: "/>
+
+ <!-- Fileset with build files for each 'core' assembly. -->
+ <fileset id="src.builds">
+ <include name="client/default.build" />
+ <include name="management/console/default.build" />
+ <include name="demo/default.build" />
+ </fileset>
+
+ <!-- Fileset with build files for each 'core' assembly. -->
+ <fileset id="examples.builds">
+ <include name="examples/request-response/example-request-response-Client/default.build" />
+ <include name="examples/request-response/example-request-response-Server/default.build" />
+ <include name="examples/direct/example-direct-Listener/default.build" />
+ <include name="examples/direct/example-direct-producer/default.build" />
+ <include name="examples/fanout/example-fanout-Listener/default.build" />
+ <include name="examples/fanout/example-fanout-Producer/default.build" />
+ <include name="examples/pub-sub/example-pub-sub-Listener/default.build" />
+ <include name="examples/pub-sub/example-pub-sub-Publisher/default.build" />
+ </fileset>
+
+ <!-- Fileset with build files for 'integration' test assemblies. -->
+ <fileset id="tests.builds">
+ <include name="test/default.build" />
+ </fileset>
+
+ <!-- Fileset with build files for 'performence' test assemblies. -->
+ <fileset id="perftest.builds">
+ <include name="perftest/default.build" />
+ </fileset>
+
+ <!-- Prepare environment for a debug build. -->
+ <target name="debug">
+ <property name="build.debug" value="true" />
+ <property name="build.defines" value="DEBUG;TRACE"/>
+ </target>
+
+ <!-- Prepare environment for a release build. -->
+ <target name="release">
+ <property name="build.debug" value="false" />
+ <property name="build.defines" value=""/>
+ </target>
+
+ <!-- Prepare environment for build. -->
+ <target name="init">
+ <property name="base.dir" value="${project::get-base-directory()}" />
+ <property name="build.dir" value="${base.dir}/bin/${framework::get-target-framework()}/${build.config}" />
+ <call target="${build.config}" />
+ </target>
+
+ <!-- Cleans up the build output directory. -->
+ <target name="clean" depends="init">
+ <delete dir="${build.dir}" failonerror="false" />
+ </target>
+
+ <!-- Runs 'svnversion' to get the repository revision into the build property 'build.svnversion'. -->
+ <target name="svnversion" description="Runs svnversion to get the current repository version into a build script property.">
+ <exec program="svnversion" output="svnversion_tmp.txt">
+ <arg value="-n"/>
+ </exec>
+
+ <loadfile file="svnversion_tmp.txt" property="build.svnversion"/>
+ <delete file="svnversion_tmp.txt"/>
+
+ <!-- For some competely retarted reason the '-n' parameter to svnversion doesn't really work under windows...
+ Here is some code to strip the unwanted newlines. -->
+ <script language="C#">
+ <code><![CDATA[
+ public static void ScriptMain(Project project)
+ {
+ project.Properties["build.svnversion"] = project.Properties["build.svnversion"].Trim("\n\r".ToCharArray());
+ }
+ ]]>
+ </code>
+ </script>
+
+ </target>
+
+ <!-- Performs a regex find-and-replace on assembly info files, substituting fields defined as build properties. -->
+ <target name="setversion" description="Stamp the version info onto assemblyinfo.cs files" depends="svnversion">
+
+ <echo>build.svnversion = ${build.svnversion}</echo>
+
+ <foreach item="File" property="filename">
+ <in>
+ <items basedir=".">
+ <include name="**\AssemblyInfo.cs"></include>
+ </items>
+ </in>
+ <do>
+ <script language="C#">
+ <code><![CDATA[
+ public static void ScriptMain(Project project)
+ {
+ // Read in the entire file to perform the substitution in.
+ StreamReader reader = new StreamReader(project.Properties["filename"]);
+ string contents = reader.ReadToEnd();
+ reader.Close();
+
+ // Substitute the version numbers.
+ string replacement = string.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]",
+ project.Properties["build.version.major"],
+ project.Properties["build.version.minor"],
+ project.Properties["build.version.build"],
+ project.Properties["build.version.revision"]);
+ contents = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
+
+ // Substitute the company name and copyright.
+ replacement = string.Format("[assembly: AssemblyCompany(\"{0}\")]",
+ project.Properties["build.company"]);
+ contents = Regex.Replace(contents, @"\[assembly: AssemblyCompany\("".*""\)\]", replacement);
+
+ replacement = string.Format("[assembly: AssemblyCopyright(\"{0}\")]",
+ project.Properties["build.copyright"]);
+ contents = Regex.Replace(contents, @"\[assembly: AssemblyCopyright\("".*""\)\]", replacement);
+
+ // Update the description.
+ //replacement = string.Format("[assembly: AssemblyDescription(\"{0} {1}\")]",
+ // project.Properties["build.description"],
+ // project.Properties["build.svnversion"]);
+ replacement = string.Format("[assembly: AssemblyDescription(\"{0}\")]",
+ project.Properties["build.description"]);
+ contents = Regex.Replace(contents, @"\[assembly: AssemblyDescription\("".*""\)\]", replacement);
+
+ // Write out the file with the substituted version.
+ StreamWriter writer = new StreamWriter(project.Properties["filename"], false);
+ writer.Write(contents);
+ writer.Close();
+ }
+ ]]>
+ </code>
+ </script>
+ </do>
+ </foreach>
+ </target>
+
+ <!-- Do the build. -->
+ <target name="build" depends="init, setversion">
+ <echo message="Building all modules including tests."/>
+
+ <!-- Make sure output folder exists. -->
+ <mkdir dir="${build.dir}" />
+
+ <echo message="Output folder: ${build.dir}"/>
+
+ <!-- copy reference assemblies over to the output dir -->
+ <copy todir="${build.dir}" file="lib/log4net/log4net.dll"/>
+ <copy todir="${build.dir}" file="lib/nunit/nunit.framework.dll"/>
+ <copy todir="${build.dir}" file="lib/plossum/C5.dll"/>
+ <copy todir="${build.dir}" file="lib/plossum/Plossum CommandLine.dll"/>
+
+ <!-- Compile assemblies. -->
+ <nant target="build">
+ <buildfiles refid="src.builds" />
+ </nant>
+
+ <!-- Compile test assemblies. -->
+ <nant target="build">
+ <buildfiles refid="examples.builds" />
+ </nant>
+
+ <!-- Compile test assemblies. -->
+ <nant target="build">
+ <buildfiles refid="tests.builds" />
+ </nant>
+
+ <!-- Compile test assemblies. -->
+ <nant target="build">
+ <buildfiles refid="perftest.builds" />
+ </nant>
+
+ <!-- copy config files over to the output dir -->
+ <copy todir="${build.dir}" file="test/Qpid Test.dll.config"/>
+ <copy todir="${build.dir}" file="log.xml"/>
+
+
+ </target>
+
+ <!-- Runs all 'pure unit' tests. -->
+ <target name="test" depends="build">
+ <echo message="Running all pure unit tests."/>
+ <nant target="test">
+ <buildfiles refid="tests.builds" />
+ </nant>
+ </target>
+
+ <!-- Creates a release package. -->
+ <target name="release-pkg">
+ <echo message="Building and packaging a release."/>
+
+ <call target="clean"/>
+ <call target="build"/>
+
+ <property name="build.date" value="${datetime::now()}"/>
+
+ <zip zipfile="${build.dir}/Qpid.NET-${framework::get-target-framework()}-${datetime::get-year(build.date)}${datetime::get-month(build.date)}${datetime::get-day(build.date)}.zip">
+ <fileset basedir="${build.dir}" prefix="qpid/lib">
+ <include name="**/*.*"/>
+ <exclude name="**/*.tests.*"/>
+ <exclude name="**/example*.*"/>
+ <exclude name="**/nunit.framework.dll"/>
+ <exclude name="**/*.exe"/>
+ <exclude name="**/*.pdb"/>
+ </fileset>
+
+ <fileset basedir="${build.dir}" prefix="qpid/examples/direct">
+ <include name="**/example*direct*.exe"/>
+ </fileset>
+
+ <fileset basedir="${build.dir}" prefix="qpid/examples/fanout">
+ <include name="**/example*fanout*.exe"/>
+ </fileset>
+
+ <fileset basedir="${build.dir}" prefix="qpid/examples/pub-sub">
+ <include name="**/example*pub-sub*.exe"/>
+ </fileset>
+
+ <fileset basedir="${build.dir}" prefix="qpid/examples/request-response">
+ <include name="**/example*request-response*.exe"/>
+ </fileset>
+
+ <fileset basedir="${base.dir}/.." prefix="qpid">
+ <include name="LICENSE.txt"/>
+ <include name="NOTICE.txt"/>
+ <include name="RELEASE_NOTES.txt"/>
+ <include name="DISCLAIMER"/>
+ </fileset>
+
+
+ <fileset basedir="${base.dir}" prefix="qpid">
+ <include name="README.txt"/>
+ </fileset>
+ </zip>
+ </target>
+
+</project>
+
+
diff --git a/dotnet/client-010/demo/Demo.csproj b/dotnet/client-010/demo/Demo.csproj
new file mode 100644
index 0000000000..1668314425
--- /dev/null
+++ b/dotnet/client-010/demo/Demo.csproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E4C46FBC-7560-406D-BFEF-CA010E584DF4}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>demo</RootNamespace>
+ <AssemblyName>Qpid Demo</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <StartupObject>
+ </StartupObject>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="*.cs" />
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ <DesignTime>True</DesignTime>
+ </Compile>
+ <None Include="..\App.config">
+ <Link>App.config</Link>
+ </None>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/demo/Program.cs b/dotnet/client-010/demo/Program.cs
new file mode 100644
index 0000000000..aa748544a0
--- /dev/null
+++ b/dotnet/client-010/demo/Program.cs
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using log4net.Config;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace WindowsClient
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ XmlConfigurator.Configure(new FileInfo("..\\..\\log.xml"));
+ // DOMConfigurator.Configure()
+
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client client = new Client();
+ Console.WriteLine("Client created");
+ client.Connect(host, port, virtualhost, username, password);
+ Console.WriteLine("Connection established");
+
+ IClientSession ssn = client.CreateSession(50000);
+ Console.WriteLine("Session created");
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+
+
+ Object wl = new Object();
+ ssn.AttachMessageListener(new MyListener(ssn, wl), "myDest");
+
+ ssn.MessageSubscribe("queue1", "myDest", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED, null,
+ 0, null);
+ DateTime start = DateTime.Now;
+
+ // issue credits
+ ssn.MessageSetFlowMode("myDest", MessageFlowMode.WINDOW);
+ ssn.MessageFlow("myDest", MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ ssn.MessageFlow("myDest", MessageCreditUnit.MESSAGE, 10000);
+ ssn.Sync();
+
+
+ for (int i = 0; i < 10000; i ++)
+ {
+ ssn.MessageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().SetRoutingKey("queue1"),
+ new MessageProperties().SetMessageId(UUID.RandomUuid())),
+ Encoding.UTF8.GetBytes("test: " + i));
+ }
+
+ lock(wl)
+ {
+ Monitor.Wait(wl);
+ }
+ DateTime now = DateTime.Now;
+ Console.WriteLine("Start time " + start + " now: " + now);
+
+ Console.WriteLine("Done time: " + (now - start));
+ lock (wl)
+ {
+ Monitor.Wait(wl, 30000);
+ }
+ client.Close();
+ }
+ }
+
+ class MyListener : IMessageListener
+ {
+ private readonly Object _wl;
+ private IClientSession _session;
+ private int _count;
+
+ public MyListener(IClientSession session, object wl)
+ {
+ _wl = wl;
+ _session = session;
+ _count = 0;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ // Console.WriteLine("Got a message: " + enc.GetString(body) + " count = " + _count);
+ _count++;
+ if (_count == 10000)
+ {
+ lock (_wl)
+ {
+ Monitor.PulseAll(_wl);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/demo/Properties/AssemblyInfo.cs b/dotnet/client-010/demo/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..58c7baf4b4
--- /dev/null
+++ b/dotnet/client-010/demo/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid Demo")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid Demo")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("434bc34e-b59b-4800-87cf-c2d301cb5082")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/demo/Properties/Resources.Designer.cs b/dotnet/client-010/demo/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000..912f9e5b81
--- /dev/null
+++ b/dotnet/client-010/demo/Properties/Resources.Designer.cs
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3053
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace demo.Properties {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("demo.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/demo/Properties/Resources.resx b/dotnet/client-010/demo/Properties/Resources.resx
new file mode 100644
index 0000000000..af03750170
--- /dev/null
+++ b/dotnet/client-010/demo/Properties/Resources.resx
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/dotnet/client-010/demo/Properties/Settings.Designer.cs b/dotnet/client-010/demo/Properties/Settings.Designer.cs
new file mode 100644
index 0000000000..fc41e577fe
--- /dev/null
+++ b/dotnet/client-010/demo/Properties/Settings.Designer.cs
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.3053
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace demo.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/demo/Properties/Settings.settings b/dotnet/client-010/demo/Properties/Settings.settings
new file mode 100644
index 0000000000..64cfd9241c
--- /dev/null
+++ b/dotnet/client-010/demo/Properties/Settings.settings
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
diff --git a/dotnet/client-010/demo/default.build b/dotnet/client-010/demo/default.build
new file mode 100644
index 0000000000..f582e392f8
--- /dev/null
+++ b/dotnet/client-010/demo/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="qpid.client.demo" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll"/>
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/direct/example-direct-Listener/Listener.cs b/dotnet/client-010/examples/direct/example-direct-Listener/Listener.cs
new file mode 100644
index 0000000000..f20090526d
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-Listener/Listener.cs
@@ -0,0 +1,117 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.example.direct
+{
+ /// <summary>
+ /// This program is one of three programs designed to be used
+ /// together. These programs use the "amq.direct" exchange.
+ ///
+ /// Producer:
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener (this program):
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ public class Listener
+ {
+ private static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+ // Create a queue named "message_queue", and route all messages whose
+ // routing key is "routing_key" to this newly created queue.
+
+ session.QueueDeclare("message_queue");
+ session.ExchangeBind("message_queue", "amq.direct", "routing_key");
+
+ lock (session)
+ {
+ // Create a listener and subscribe it to the queue named "message_queue"
+ IMessageListener listener = new MessageListener(session);
+ session.AttachMessageListener(listener, "message_queue");
+ session.MessageSubscribe("message_queue");
+ // Receive messages until all messages are received
+ Monitor.Wait(session);
+ }
+
+ //---------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+
+ public class MessageListener : IMessageListener
+ {
+ private readonly IClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+ public MessageListener(IClientSession session)
+ {
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Message: " + message);
+ // Add this message to the list of message to be acknowledged
+ _range.Add(m.Id);
+ if( message.Equals("That's all, folks!") )
+ {
+ // Acknowledge all the received messages
+ _session.MessageAccept(_range);
+ lock(_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/direct/example-direct-Listener/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/direct/example-direct-Listener/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..2fab6a538a
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-Listener/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-direct-Listener")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-direct-Listener")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6a24bfe4-4714-4d2a-acf4-96cf9a678a06")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/direct/example-direct-Listener/default.build b/dotnet/client-010/examples/direct/example-direct-Listener/default.build
new file mode 100644
index 0000000000..f5db519af7
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-Listener/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-direct-Listener" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/direct/example-direct-Listener/example-direct-Listener.csproj b/dotnet/client-010/examples/direct/example-direct-Listener/example-direct-Listener.csproj
new file mode 100644
index 0000000000..ac026b397d
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-Listener/example-direct-Listener.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{AE65B1B9-8779-4CB1-91AF-E7F6C7A736D7}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_direct_Listener</RootNamespace>
+ <AssemblyName>example-direct-Listener</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Listener.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/direct/example-direct-producer/Producer.cs b/dotnet/client-010/examples/direct/example-direct-producer/Producer.cs
new file mode 100644
index 0000000000..f62667bf98
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-producer/Producer.cs
@@ -0,0 +1,92 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.Text;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.example.direct
+{
+ /// <summary>
+ /// This program is one of three programs designed to be used
+ /// together. These programs use the "amq.direct" exchange.
+ ///
+ /// Producer (this program):
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener:
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ class Producer
+ {
+ static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+
+ IMessage message = new Message();
+
+ // The routing key is a message property. We will use the same
+ // routing key for each message, so we'll set this property
+ // just once. (In most simple cases, there is no need to set
+ // other message properties.)
+
+ message.DeliveryProperties.SetRoutingKey("routing_key");
+
+ // Asynchronous transfer sends messages as quickly as
+ // possible without waiting for confirmation.
+ for (int i = 0; i < 10; i++)
+ {
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.MessageTransfer("amq.direct", message);
+ }
+
+ // And send a syncrhonous final message to indicate termination.
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+ session.MessageTransfer("amq.direct", "routing_key", message);
+ session.Sync();
+
+ //-----------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/direct/example-direct-producer/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/direct/example-direct-producer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..84590e67c1
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-producer/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-direct-producer")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-direct-producer")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("006144c2-5e45-4543-8e16-c09cd4309ed7")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/direct/example-direct-producer/default.build b/dotnet/client-010/examples/direct/example-direct-producer/default.build
new file mode 100644
index 0000000000..c4e78444c7
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-producer/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-direct-Producer" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/direct/example-direct-producer/example-direct-producer.csproj b/dotnet/client-010/examples/direct/example-direct-producer/example-direct-producer.csproj
new file mode 100644
index 0000000000..10d9d96aea
--- /dev/null
+++ b/dotnet/client-010/examples/direct/example-direct-producer/example-direct-producer.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{96FCB250-8142-40EE-9BDD-CA839EE21021}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_direct_producer</RootNamespace>
+ <AssemblyName>example-direct-producer</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Producer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/direct/verify b/dotnet/client-010/examples/direct/verify
new file mode 100644
index 0000000000..7da08480a2
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify
@@ -0,0 +1,37 @@
+#
+##
+## 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.
+##
+##
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/direct
+
+direct_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-direct-Listener.exe localhost 5672
+}
+
+direct_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-direct-Producer.exe localhost 5672
+}
+
+clients $cpp/declare_queues direct_producer_dotnet direct_listener_dotnet
+outputs $cpp/declare_queues.out ./direct_producer_dotnet.out ./direct_listener_dotnet.out
diff --git a/dotnet/client-010/examples/direct/verify.in b/dotnet/client-010/examples/direct/verify.in
new file mode 100644
index 0000000000..f57d931663
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify.in
@@ -0,0 +1,14 @@
+==== declare_queues.out
+==== direct_producer_dotnet.out
+==== direct_listener_dotnet.out
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
diff --git a/dotnet/client-010/examples/direct/verify_cpp_dotnet b/dotnet/client-010/examples/direct/verify_cpp_dotnet
new file mode 100644
index 0000000000..648c8b6bc1
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify_cpp_dotnet
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/direct
+
+direct_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-direct-Listener.exe localhost 5672
+}
+
+clients $cpp/declare_queues $cpp/direct_producer direct_listener_dotnet
+outputs $cpp/declare_queues.out $cpp/direct_producer.out ./direct_listener_dotnet.out
diff --git a/dotnet/client-010/examples/direct/verify_cpp_dotnet.in b/dotnet/client-010/examples/direct/verify_cpp_dotnet.in
new file mode 100644
index 0000000000..b3543cefe5
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify_cpp_dotnet.in
@@ -0,0 +1,14 @@
+==== declare_queues.out
+==== direct_producer.out
+==== direct_listener_dotnet.out
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
diff --git a/dotnet/client-010/examples/direct/verify_dotnet_cpp b/dotnet/client-010/examples/direct/verify_dotnet_cpp
new file mode 100644
index 0000000000..5093da6088
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify_dotnet_cpp
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/direct
+
+direct_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-direct-Producer.exe localhost 5672
+}
+
+clients $cpp/declare_queues direct_producer_dotnet $cpp/listener
+outputs $cpp/declare_queues.out ./direct_producer_dotnet.out $cpp/listener.out
diff --git a/dotnet/client-010/examples/direct/verify_dotnet_cpp.in b/dotnet/client-010/examples/direct/verify_dotnet_cpp.in
new file mode 100644
index 0000000000..fcb6cd66de
--- /dev/null
+++ b/dotnet/client-010/examples/direct/verify_dotnet_cpp.in
@@ -0,0 +1,15 @@
+==== declare_queues.out
+==== direct_producer_dotnet.out
+==== listener.out
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
+Shutting down listener for message_queue
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Listener/Listener.cs b/dotnet/client-010/examples/fanout/example-fanout-Listener/Listener.cs
new file mode 100644
index 0000000000..b1967b59be
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Listener/Listener.cs
@@ -0,0 +1,126 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.example.fanout
+{
+ /// <summary>
+ /// This program is one of two programs designed to be used
+ /// together.
+ ///
+ /// Producer (this program):
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener:
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ public class Listener
+ {
+ private static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+ // Each client creates its own private queue, using the
+ // session id to guarantee a unique name. It then routes
+ // all messages from the fanout exchange to its own queue
+ // by binding to the queue.
+ //
+ // The binding specifies a binding key, but for a fanout
+ // exchange, the binding key is optional and is not used
+ // for routing decisions. It can be useful for tracking
+ // messages and routing in logs.
+
+ string myQueue = session.Name;
+ session.QueueDeclare(myQueue, Option.EXCLUSIVE, Option.AUTO_DELETE);
+ session.ExchangeBind(myQueue, "amq.fanout", "my-key");
+
+ lock (session)
+ {
+ Console.WriteLine("Listening");
+ // Create a listener and subscribe it to my queue.
+ IMessageListener listener = new MessageListener(session);
+ session.AttachMessageListener(listener, myQueue);
+ session.MessageSubscribe(myQueue);
+ // Receive messages until all messages are received
+ Monitor.Wait(session);
+ }
+
+ //---------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+
+ public class MessageListener : IMessageListener
+ {
+ private readonly IClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+ public MessageListener(IClientSession session)
+ {
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Message: " + message);
+ // Add this message to the list of message to be acknowledged
+ _range.Add(m.Id);
+ if (message.Equals("That's all, folks!"))
+ {
+ // Acknowledge all the received messages
+ _session.MessageAccept(_range);
+ lock (_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Listener/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/fanout/example-fanout-Listener/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..45ff62073e
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Listener/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-fanout-Listener")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-fanout-Listener")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("68686ef9-aa0a-4334-9c52-d7e6fc507bec")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Listener/default.build b/dotnet/client-010/examples/fanout/example-fanout-Listener/default.build
new file mode 100644
index 0000000000..dde36daf17
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Listener/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-fanout-Listener" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Listener/example-fanout-Listener.csproj b/dotnet/client-010/examples/fanout/example-fanout-Listener/example-fanout-Listener.csproj
new file mode 100644
index 0000000000..3bd0b3d0d0
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Listener/example-fanout-Listener.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{18A0792B-DC3A-4EC5-93D6-DB8A111D8F15}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_fanout_Listener</RootNamespace>
+ <AssemblyName>example-fanout-Listener</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Listener.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Producer/Producer.cs b/dotnet/client-010/examples/fanout/example-fanout-Producer/Producer.cs
new file mode 100644
index 0000000000..a781358a7e
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Producer/Producer.cs
@@ -0,0 +1,89 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.Text;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.example.fanout
+{
+ /// <summary>
+ /// This program is one of two programs designed to be used
+ /// together. These programs do not specify the exchange type - the
+ /// default exchange type is the direct exchange.
+ ///
+ ///
+ /// Producer (this program):
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener:
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ class Producer
+ {
+ static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+
+ // Unlike topic exchanges and direct exchanges, a fanout
+ // exchange need not set a routing key.
+ IMessage message = new Message();
+
+ // Asynchronous transfer sends messages as quickly as
+ // possible without waiting for confirmation.
+ for (int i = 0; i < 10; i++)
+ {
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.MessageTransfer("amq.fanout", message);
+ }
+
+ // And send a syncrhonous final message to indicate termination.
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+ session.MessageTransfer("amq.fanout", message);
+ session.Sync();
+
+ //-----------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Producer/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/fanout/example-fanout-Producer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..c19bb5b949
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Producer/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-fanout-Producer")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-fanout-Producer")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("01c0ba10-2f23-409b-9adc-bc514a13131a")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Producer/default.build b/dotnet/client-010/examples/fanout/example-fanout-Producer/default.build
new file mode 100644
index 0000000000..c4d39e41da
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Producer/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-fanout-Producer" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/fanout/example-fanout-Producer/example-fanout-Producer.csproj b/dotnet/client-010/examples/fanout/example-fanout-Producer/example-fanout-Producer.csproj
new file mode 100644
index 0000000000..8b04dd8199
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/example-fanout-Producer/example-fanout-Producer.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4513BF94-D54A-42FE-8506-FE2CD57B2C51}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_fanout_Producer</RootNamespace>
+ <AssemblyName>example-fanout-Producer</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Producer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/fanout/verify b/dotnet/client-010/examples/fanout/verify
new file mode 100644
index 0000000000..51b7327243
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify
@@ -0,0 +1,36 @@
+#
+#
+# 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.
+#
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+
+fanout_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-fanout-Listener.exe localhost 5672
+}
+
+fanout_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-fanout-Producer.exe localhost 5672
+}
+
+background "Listening" fanout_listener_dotnet
+clients fanout_producer_dotnet
+outputs ./fanout_listener_dotnet.out ./fanout_producer_dotnet.out
diff --git a/dotnet/client-010/examples/fanout/verify.in b/dotnet/client-010/examples/fanout/verify.in
new file mode 100644
index 0000000000..37a4a4aaa8
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify.in
@@ -0,0 +1,14 @@
+==== fanout_listener_dotnet.out
+Listening
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
+==== fanout_producer_dotnet.out
diff --git a/dotnet/client-010/examples/fanout/verify_cpp_dotnet b/dotnet/client-010/examples/fanout/verify_cpp_dotnet
new file mode 100644
index 0000000000..5716d3119b
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify_cpp_dotnet
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/fanout
+
+fanout_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-fanout-Listener.exe localhost 5672
+}
+
+background "Listening" fanout_listener_dotnet
+clients $cpp/fanout_producer
+outputs $cpp/fanout_producer.out "./fanout_listener_dotnet.out | remove_uuid"
diff --git a/dotnet/client-010/examples/fanout/verify_cpp_dotnet.in b/dotnet/client-010/examples/fanout/verify_cpp_dotnet.in
new file mode 100644
index 0000000000..0a72d8fd3c
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify_cpp_dotnet.in
@@ -0,0 +1,14 @@
+==== fanout_producer.out
+==== fanout_listener_dotnet.out | remove_uuid
+Listening
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
diff --git a/dotnet/client-010/examples/fanout/verify_dotnet_cpp b/dotnet/client-010/examples/fanout/verify_dotnet_cpp
new file mode 100644
index 0000000000..c755d1da41
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify_dotnet_cpp
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/fanout
+
+fanout_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-fanout-Producer.exe localhost 5672
+}
+
+
+background "Listening" $cpp/listener
+clients fanout_producer_dotnet
+outputs ./fanout_producer_dotnet.out "$cpp/listener.out | remove_uuid"
diff --git a/dotnet/client-010/examples/fanout/verify_dotnet_cpp.in b/dotnet/client-010/examples/fanout/verify_dotnet_cpp.in
new file mode 100644
index 0000000000..588559938f
--- /dev/null
+++ b/dotnet/client-010/examples/fanout/verify_dotnet_cpp.in
@@ -0,0 +1,15 @@
+==== fanout_producer_dotnet.out
+==== listener.out | remove_uuid
+Listening
+Message: Message 0
+Message: Message 1
+Message: Message 2
+Message: Message 3
+Message: Message 4
+Message: Message 5
+Message: Message 6
+Message: Message 7
+Message: Message 8
+Message: Message 9
+Message: That's all, folks!
+Shutting down listener for
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Listener.cs b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Listener.cs
new file mode 100644
index 0000000000..aeaf3f043b
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Listener.cs
@@ -0,0 +1,143 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.example.pubsub
+{
+ /// <summary>
+ /// This program is one of two programs designed to be used
+ /// together. These programs use the topic exchange.
+ ///
+ /// Publisher:
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener (this program):
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ internal class Listener
+ {
+ public static int _count = 4;
+
+ private static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+
+ lock (session)
+ {
+ Console.WriteLine("Listening for messages ...");
+ // Create a listener
+ prepareQueue("usa", "usa.#", session);
+ prepareQueue("europe", "europe.#", session);
+ prepareQueue("news", "#.news", session);
+ prepareQueue("weather", "#.weather", session);
+ while (_count > 0)
+ {
+ Monitor.Wait(session);
+ }
+ }
+
+ //---------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+
+ private static void prepareQueue(string queue, string routing_key, IClientSession session)
+ {
+ // Create a unique queue name for this consumer by concatenating
+ // the queue name parameter with the Session ID.
+ Console.WriteLine("Declaring queue: " + queue);
+ session.QueueDeclare(queue, Option.EXCLUSIVE, Option.AUTO_DELETE);
+
+ // Route messages to the new queue if they match the routing key.
+ // Also route any messages to with the "control" routing key to
+ // this queue so we know when it's time to stop. A publisher sends
+ // a message with the content "That's all, Folks!", using the
+ // "control" routing key, when it is finished.
+
+ session.ExchangeBind(queue, "amq.topic", routing_key);
+ session.ExchangeBind(queue, "amq.topic", "control");
+
+ // subscribe the listener to the queue
+ IMessageListener listener = new MessageListener(session);
+ session.AttachMessageListener(listener, queue);
+ session.MessageSubscribe(queue);
+ }
+ }
+
+ public class MessageListener : IMessageListener
+ {
+ private readonly IClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+
+ public MessageListener(IClientSession session)
+ {
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Message: " + message + " from " + m.Destination);
+ // Add this message to the list of message to be acknowledged
+ _range.Add(m.Id);
+ if (message.Equals("That's all, folks!"))
+ {
+ Console.WriteLine("Shutting down listener for " + m.DeliveryProperties.GetRoutingKey());
+ Listener._count--;
+ // Acknowledge all the received messages
+ _session.MessageAccept(_range);
+ lock (_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..ef791c6738
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-pub-sub-Listener")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-pub-sub-Listener")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("74ab02ae-95d1-4bad-a7cf-9964005b9b05")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/default.build b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/default.build
new file mode 100644
index 0000000000..fe2d9bf4ba
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-pub-sub-Listener" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/example-pub-sub-Listener.csproj b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/example-pub-sub-Listener.csproj
new file mode 100644
index 0000000000..851faa7f21
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Listener/example-pub-sub-Listener.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2BCDC2CC-5BDA-4CC7-944D-2899AD8A53C7}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_pub_sub_Listener</RootNamespace>
+ <AssemblyName>example-pub-sub-Listener</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Listener.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..b6d7f3c818
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-pub-sub-Publisher")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-pub-sub-Publisher")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f6d282a0-9dc5-46cf-a4cd-44ae402d667f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Publisher.cs b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Publisher.cs
new file mode 100644
index 0000000000..c87985d288
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/Publisher.cs
@@ -0,0 +1,98 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.Text;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.example.pubsub
+{
+ /// <summary>
+ /// This program is one of two programs designed to be used
+ /// together. These programs use the topic exchange.
+ ///
+ /// Publisher (this program):
+ ///
+ /// Publishes to a broker, specifying a routing key.
+ ///
+ /// Listener:
+ ///
+ /// Reads from a queue on the broker using a message listener.
+ ///
+ /// </summary>
+ internal class Publisher
+ {
+ private static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+
+ publishMessages(session, "usa.news");
+ publishMessages(session, "usa.weather");
+ publishMessages(session, "europe.news");
+ publishMessages(session, "europe.weather");
+
+ noMoreMessages(session);
+
+ //-----------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+
+ private static void publishMessages(IClientSession session, string routing_key)
+ {
+ IMessage message = new Message();
+ // Asynchronous transfer sends messages as quickly as
+ // possible without waiting for confirmation.
+ for (int i = 0; i < 10; i++)
+ {
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("Message " + i));
+ session.MessageTransfer("amq.topic", routing_key, message);
+ }
+ }
+
+ private static void noMoreMessages(IClientSession session)
+ {
+ IMessage message = new Message();
+ // And send a syncrhonous final message to indicate termination.
+ message.ClearData();
+ message.AppendData(Encoding.UTF8.GetBytes("That's all, folks!"));
+ session.MessageTransfer("amq.topic", "control", message);
+ session.Sync();
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/default.build b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/default.build
new file mode 100644
index 0000000000..3f270afe9e
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-pub-sub-Publisher" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/example-pub-sub-Publisher.csproj b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/example-pub-sub-Publisher.csproj
new file mode 100644
index 0000000000..a9dee76a36
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/example-pub-sub-Publisher/example-pub-sub-Publisher.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F8857634-A134-44E7-A953-F2B22688C599}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_pub_sub_Publisher</RootNamespace>
+ <AssemblyName>example-pub-sub-Publisher</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Publisher.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/pub-sub/verify b/dotnet/client-010/examples/pub-sub/verify
new file mode 100644
index 0000000000..45d80c4866
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify
@@ -0,0 +1,36 @@
+#
+#
+# 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.
+#
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+
+pubsub_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-pub-sub-Listener.exe localhost 5672
+}
+
+pubsub_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-pub-sub-Publisher.exe localhost 5672
+}
+
+background "Listening for messages ..." pubsub_listener_dotnet
+clients pubsub_producer_dotnet
+outputs pubsub_producer_dotnet.out "pubsub_listener_dotnet.out | remove_uuid | sort"
diff --git a/dotnet/client-010/examples/pub-sub/verify.in b/dotnet/client-010/examples/pub-sub/verify.in
new file mode 100644
index 0000000000..6a5adc4d89
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify.in
@@ -0,0 +1,95 @@
+==== pubsub_producer_dotnet.out
+==== pubsub_listener_dotnet.out | remove_uuid | sort
+Declaring queue: europe
+Declaring queue: news
+Declaring queue: usa
+Declaring queue: weather
+Listening for messages ...
+Message: Message 0 from europe
+Message: Message 0 from europe
+Message: Message 0 from news
+Message: Message 0 from news
+Message: Message 0 from usa
+Message: Message 0 from usa
+Message: Message 0 from weather
+Message: Message 0 from weather
+Message: Message 1 from europe
+Message: Message 1 from europe
+Message: Message 1 from news
+Message: Message 1 from news
+Message: Message 1 from usa
+Message: Message 1 from usa
+Message: Message 1 from weather
+Message: Message 1 from weather
+Message: Message 2 from europe
+Message: Message 2 from europe
+Message: Message 2 from news
+Message: Message 2 from news
+Message: Message 2 from usa
+Message: Message 2 from usa
+Message: Message 2 from weather
+Message: Message 2 from weather
+Message: Message 3 from europe
+Message: Message 3 from europe
+Message: Message 3 from news
+Message: Message 3 from news
+Message: Message 3 from usa
+Message: Message 3 from usa
+Message: Message 3 from weather
+Message: Message 3 from weather
+Message: Message 4 from europe
+Message: Message 4 from europe
+Message: Message 4 from news
+Message: Message 4 from news
+Message: Message 4 from usa
+Message: Message 4 from usa
+Message: Message 4 from weather
+Message: Message 4 from weather
+Message: Message 5 from europe
+Message: Message 5 from europe
+Message: Message 5 from news
+Message: Message 5 from news
+Message: Message 5 from usa
+Message: Message 5 from usa
+Message: Message 5 from weather
+Message: Message 5 from weather
+Message: Message 6 from europe
+Message: Message 6 from europe
+Message: Message 6 from news
+Message: Message 6 from news
+Message: Message 6 from usa
+Message: Message 6 from usa
+Message: Message 6 from weather
+Message: Message 6 from weather
+Message: Message 7 from europe
+Message: Message 7 from europe
+Message: Message 7 from news
+Message: Message 7 from news
+Message: Message 7 from usa
+Message: Message 7 from usa
+Message: Message 7 from weather
+Message: Message 7 from weather
+Message: Message 8 from europe
+Message: Message 8 from europe
+Message: Message 8 from news
+Message: Message 8 from news
+Message: Message 8 from usa
+Message: Message 8 from usa
+Message: Message 8 from weather
+Message: Message 8 from weather
+Message: Message 9 from europe
+Message: Message 9 from europe
+Message: Message 9 from news
+Message: Message 9 from news
+Message: Message 9 from usa
+Message: Message 9 from usa
+Message: Message 9 from weather
+Message: Message 9 from weather
+Message: That's all, folks! from europe
+Message: That's all, folks! from news
+Message: That's all, folks! from usa
+Message: That's all, folks! from weather
+Shutting down listener for control
+Shutting down listener for control
+Shutting down listener for control
+Shutting down listener for control
diff --git a/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet b/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet
new file mode 100644
index 0000000000..39d92cbb8b
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/pub-sub
+
+pubsub_listener_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-pub-sub-Listener.exe localhost 5672
+}
+
+
+background "Listening for messages ..." pubsub_listener_dotnet
+clients $cpp/topic_publisher
+outputs $cpp/topic_publisher.out "pubsub_listener_dotnet.out | remove_uuid | sort"
diff --git a/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet.in b/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet.in
new file mode 100644
index 0000000000..4e058f7645
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify_cpp_dotnet.in
@@ -0,0 +1,55 @@
+==== topic_publisher.out
+==== pubsub_listener_dotnet.out | remove_uuid | sort
+Declaring queue: europe
+Declaring queue: news
+Declaring queue: usa
+Declaring queue: weather
+Listening for messages ...
+Message: Message 0 from europe
+Message: Message 0 from europe
+Message: Message 0 from news
+Message: Message 0 from news
+Message: Message 0 from usa
+Message: Message 0 from usa
+Message: Message 0 from weather
+Message: Message 0 from weather
+Message: Message 1 from europe
+Message: Message 1 from europe
+Message: Message 1 from news
+Message: Message 1 from news
+Message: Message 1 from usa
+Message: Message 1 from usa
+Message: Message 1 from weather
+Message: Message 1 from weather
+Message: Message 2 from europe
+Message: Message 2 from europe
+Message: Message 2 from news
+Message: Message 2 from news
+Message: Message 2 from usa
+Message: Message 2 from usa
+Message: Message 2 from weather
+Message: Message 2 from weather
+Message: Message 3 from europe
+Message: Message 3 from europe
+Message: Message 3 from news
+Message: Message 3 from news
+Message: Message 3 from usa
+Message: Message 3 from usa
+Message: Message 3 from weather
+Message: Message 3 from weather
+Message: Message 4 from europe
+Message: Message 4 from europe
+Message: Message 4 from news
+Message: Message 4 from news
+Message: Message 4 from usa
+Message: Message 4 from usa
+Message: Message 4 from weather
+Message: Message 4 from weather
+Message: That's all, folks! from europe
+Message: That's all, folks! from news
+Message: That's all, folks! from usa
+Message: That's all, folks! from weather
+Shutting down listener for control
+Shutting down listener for control
+Shutting down listener for control
+Shutting down listener for control
diff --git a/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp b/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp
new file mode 100644
index 0000000000..bf99e422a1
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/pub-sub
+
+pubsub_producer_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-pub-sub-Publisher.exe localhost 5672
+}
+
+background "Listening" $cpp/topic_listener
+clients pubsub_producer_dotnet
+outputs pubsub_producer_dotnet.out "$cpp/topic_listener.out | remove_uuid | sort"
diff --git a/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp.in b/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp.in
new file mode 100644
index 0000000000..64ac27846d
--- /dev/null
+++ b/dotnet/client-010/examples/pub-sub/verify_dotnet_cpp.in
@@ -0,0 +1,99 @@
+==== pubsub_producer_dotnet.out
+==== topic_listener.out | remove_uuid | sort
+Declaring queue: europe
+Declaring queue: news
+Declaring queue: usa
+Declaring queue: weather
+Listening for messages ...
+Message: Message 0 from europe
+Message: Message 0 from europe
+Message: Message 0 from news
+Message: Message 0 from news
+Message: Message 0 from usa
+Message: Message 0 from usa
+Message: Message 0 from weather
+Message: Message 0 from weather
+Message: Message 1 from europe
+Message: Message 1 from europe
+Message: Message 1 from news
+Message: Message 1 from news
+Message: Message 1 from usa
+Message: Message 1 from usa
+Message: Message 1 from weather
+Message: Message 1 from weather
+Message: Message 2 from europe
+Message: Message 2 from europe
+Message: Message 2 from news
+Message: Message 2 from news
+Message: Message 2 from usa
+Message: Message 2 from usa
+Message: Message 2 from weather
+Message: Message 2 from weather
+Message: Message 3 from europe
+Message: Message 3 from europe
+Message: Message 3 from news
+Message: Message 3 from news
+Message: Message 3 from usa
+Message: Message 3 from usa
+Message: Message 3 from weather
+Message: Message 3 from weather
+Message: Message 4 from europe
+Message: Message 4 from europe
+Message: Message 4 from news
+Message: Message 4 from news
+Message: Message 4 from usa
+Message: Message 4 from usa
+Message: Message 4 from weather
+Message: Message 4 from weather
+Message: Message 5 from europe
+Message: Message 5 from europe
+Message: Message 5 from news
+Message: Message 5 from news
+Message: Message 5 from usa
+Message: Message 5 from usa
+Message: Message 5 from weather
+Message: Message 5 from weather
+Message: Message 6 from europe
+Message: Message 6 from europe
+Message: Message 6 from news
+Message: Message 6 from news
+Message: Message 6 from usa
+Message: Message 6 from usa
+Message: Message 6 from weather
+Message: Message 6 from weather
+Message: Message 7 from europe
+Message: Message 7 from europe
+Message: Message 7 from news
+Message: Message 7 from news
+Message: Message 7 from usa
+Message: Message 7 from usa
+Message: Message 7 from weather
+Message: Message 7 from weather
+Message: Message 8 from europe
+Message: Message 8 from europe
+Message: Message 8 from news
+Message: Message 8 from news
+Message: Message 8 from usa
+Message: Message 8 from usa
+Message: Message 8 from weather
+Message: Message 8 from weather
+Message: Message 9 from europe
+Message: Message 9 from europe
+Message: Message 9 from news
+Message: Message 9 from news
+Message: Message 9 from usa
+Message: Message 9 from usa
+Message: Message 9 from weather
+Message: Message 9 from weather
+Message: That's all, folks! from europe
+Message: That's all, folks! from news
+Message: That's all, folks! from usa
+Message: That's all, folks! from weather
+Shutting down listener for europe
+Shutting down listener for news
+Shutting down listener for usa
+Shutting down listener for weather
+Subscribing to queue europe
+Subscribing to queue news
+Subscribing to queue usa
+Subscribing to queue weather
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Client/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/request-response/example-request-response-Client/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..a438acaa1f
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Client/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-request-response-Client")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-request-response-Client")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("08bf6aed-bf79-4d16-9a28-6363d5322cdd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Client/RequestResponseClient.cs b/dotnet/client-010/examples/request-response/example-request-response-Client/RequestResponseClient.cs
new file mode 100644
index 0000000000..170008c840
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Client/RequestResponseClient.cs
@@ -0,0 +1,142 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.example.requestresponse
+{
+ /// <summary>
+ /// This program is one of two programs that illustrate the
+ /// request/response pattern.
+ ///
+ /// Client (this program):
+ /// Make requests of a service, print the response.
+ ///
+ /// Server:
+ /// Accept requests, set the letters to uppercase in each message, and
+ /// return it as a response.
+ ///
+ /// </summary>
+ internal class RequestResponseClient
+ {
+ private static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+ IMessage request = new Message();
+
+ //--------- Main body of program --------------------------------------------
+ // Create a response queue so the server can send us responses
+ // to our requests. Use the client's session ID as the name
+ // of the response queue.
+ string response_queue = "client" + session.GetName();
+ // Use the name of the response queue as the routing key
+ session.QueueDeclare(response_queue);
+ session.ExchangeBind(response_queue, "amq.direct", response_queue);
+
+ // Each client sends the name of their own response queue so
+ // the service knows where to route messages.
+ request.DeliveryProperties.SetRoutingKey("request");
+ request.MessageProperties.SetReplyTo(new ReplyTo("amq.direct", response_queue));
+
+ lock (session)
+ {
+ // Create a listener for the response queue and listen for response messages.
+ Console.WriteLine("Activating response queue listener for: " + response_queue);
+ IMessageListener listener = new ClientMessageListener(session);
+ session.AttachMessageListener(listener, response_queue);
+ session.MessageSubscribe(response_queue);
+
+ // Now send some requests ...
+ string[] strs = {
+ "Twas brillig, and the slithy toves",
+ "Did gire and gymble in the wabe.",
+ "All mimsy were the borogroves,",
+ "And the mome raths outgrabe.",
+ "That's all, folks!"
+ };
+ foreach (string s in strs)
+ {
+ request.ClearData();
+ request.AppendData(Encoding.UTF8.GetBytes(s));
+ session.MessageTransfer("amq.direct", request);
+ }
+ Console.WriteLine("Waiting for all responses to arrive ...");
+ Monitor.Wait(session);
+ }
+ //---------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+
+ public class ClientMessageListener : IMessageListener
+ {
+ private readonly IClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+ private int _counter;
+ public ClientMessageListener(IClientSession session)
+ {
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ _counter++;
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Response: " + message);
+ // Add this message to the list of message to be acknowledged
+ _range.Add(m.Id);
+ if (_counter == 4)
+ {
+ Console.WriteLine("Shutting down listener for " + m.DeliveryProperties.GetRoutingKey());
+ // Acknowledge all the received messages
+ _session.MessageAccept(_range);
+ lock (_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Client/default.build b/dotnet/client-010/examples/request-response/example-request-response-Client/default.build
new file mode 100644
index 0000000000..c3d9af9baf
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Client/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-request-response-Client" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Client/example-request-response-Client.csproj b/dotnet/client-010/examples/request-response/example-request-response-Client/example-request-response-Client.csproj
new file mode 100644
index 0000000000..21dc6ceed4
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Client/example-request-response-Client.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1BC63815-4029-4039-9207-35E7E06ECC99}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_request_response_Client</RootNamespace>
+ <AssemblyName>example-request-response-Client</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="RequestResponseClient.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Server/Properties/AssemblyInfo.cs b/dotnet/client-010/examples/request-response/example-request-response-Server/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..ba702a28cc
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Server/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("example-request-response-Server")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("example-request-response-Server")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ef3456e2-7c19-47aa-8dd6-aeaa88c5c4ad")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Server/Server.cs b/dotnet/client-010/examples/request-response/example-request-response-Server/Server.cs
new file mode 100644
index 0000000000..ea87627dbf
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Server/Server.cs
@@ -0,0 +1,141 @@
+/*
+* 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.
+*/
+
+using System;
+using System.Configuration;
+using System.IO;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+
+namespace org.apache.qpid.example.requestresponse
+{
+ /// <summary>
+ /// This program is one of two programs that illustrate the
+ /// request/response pattern.
+ ///
+ /// Client:
+ /// Make requests of a service, print the response.
+ ///
+ /// Server (this program):
+ /// Accept requests, set the letters to uppercase in each message, and
+ /// return it as a response.
+ ///
+ /// </summary>
+ class Server
+ {
+ static void Main(string[] args)
+ {
+ string host = ConfigurationManager.AppSettings["Host"];
+ int port = int.Parse(ConfigurationManager.AppSettings["Port"]);
+ string virtualhost = ConfigurationManager.AppSettings["VirtualHost"];
+ string username = ConfigurationManager.AppSettings["Username"];
+ string password = ConfigurationManager.AppSettings["Password"];
+
+ Client connection = new Client();
+ try
+ {
+ connection.Connect(host, port, virtualhost, username, password);
+ IClientSession session = connection.CreateSession(50000);
+
+ //--------- Main body of program --------------------------------------------
+ // Create a request queue for clients to use when making
+ // requests.
+ const string request_queue = "request";
+ // Use the name of the request queue as the routing key
+ session.QueueDeclare(request_queue);
+ session.ExchangeBind(request_queue, "amq.direct", request_queue);
+
+ lock (session)
+ {
+ // Create a listener and subscribe it to the request_queue
+ IMessageListener listener = new MessageListener(session);
+ session.AttachMessageListener(listener, request_queue);
+ session.MessageSubscribe(request_queue);
+ // Receive messages until all messages are received
+ Console.WriteLine("Waiting for requests");
+ Monitor.Wait(session);
+ }
+
+ //---------------------------------------------------------------------------
+
+ connection.Close();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error: \n" + e.StackTrace);
+ }
+ }
+ }
+
+ public class MessageListener : IMessageListener
+ {
+ private readonly IClientSession _session;
+ private readonly RangeSet _range = new RangeSet();
+ public MessageListener(IClientSession session)
+ {
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage request)
+ {
+ IMessage response = new Message();
+
+ // Get routing key for response from the request's replyTo property
+ string routingKey;
+ if( request.MessageProperties.HasReplyTo() )
+ {
+ routingKey = request.MessageProperties.GetReplyTo().GetRoutingKey();
+ }
+ else
+ {
+ Console.WriteLine("Error: \n No routing key for request " + request);
+ return;
+ }
+
+ BinaryReader reader = new BinaryReader(request.Body, Encoding.UTF8);
+ byte[] body = new byte[request.Body.Length - request.Body.Position];
+ reader.Read(body, 0, body.Length);
+ ASCIIEncoding enc = new ASCIIEncoding();
+ string message = enc.GetString(body);
+ Console.WriteLine("Request: " + message);
+
+ // Transform message content to upper case
+ string responseBody = message.ToUpper();
+
+ // Send it back to the user
+ response.ClearData();
+ response.AppendData(Encoding.UTF8.GetBytes(responseBody));
+ _session.MessageTransfer("amq.direct", routingKey, response);
+
+ // Add this message to the list of message to be acknowledged
+ _range.Add(request.Id);
+ if (message.Equals("That's all, folks!"))
+ {
+ // Acknowledge all the received messages
+ _session.MessageAccept(_range);
+ lock (_session)
+ {
+ Monitor.Pulse(_session);
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Server/default.build b/dotnet/client-010/examples/request-response/example-request-response-Server/default.build
new file mode 100644
index 0000000000..a3e4691d10
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Server/default.build
@@ -0,0 +1,48 @@
+<?xml version="1.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.
+
+-->
+
+<project name="example-request-response-Server" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="System.Configuration.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/examples/request-response/example-request-response-Server/example-request-response-Server.csproj b/dotnet/client-010/examples/request-response/example-request-response-Server/example-request-response-Server.csproj
new file mode 100644
index 0000000000..3eb2a3c035
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/example-request-response-Server/example-request-response-Server.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{922FBA9C-E483-4AEF-ABE8-AC87421E829B}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>example_request_response_Server</RootNamespace>
+ <AssemblyName>example-request-response-Server</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Server.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/examples/request-response/verify b/dotnet/client-010/examples/request-response/verify
new file mode 100644
index 0000000000..fa69461f68
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify
@@ -0,0 +1,36 @@
+#
+#
+# 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.
+#
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+
+server_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-request-response-Server.exe localhost 5672
+}
+
+client_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-request-response-Client.exe localhost 5672
+}
+
+background "Waiting for requests" server_dotnet
+clients client_dotnet
+outputs ./server_dotnet.out ./client_dotnet.out
diff --git a/dotnet/client-010/examples/request-response/verify.in b/dotnet/client-010/examples/request-response/verify.in
new file mode 100644
index 0000000000..5357591289
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify.in
@@ -0,0 +1,16 @@
+==== server_dotnet.out
+Waiting for requests
+Request: Twas brillig, and the slithy toves
+Request: Did gire and gymble in the wabe.
+Request: All mimsy were the borogroves,
+Request: And the mome raths outgrabe.
+Request: That's all, folks!
+==== client_dotnet.out
+Activating response queue listener for: clientSystem.Byte[]
+Waiting for all responses to arrive ...
+Response: TWAS BRILLIG, AND THE SLITHY TOVES
+Response: DID GIRE AND GYMBLE IN THE WABE.
+Response: ALL MIMSY WERE THE BOROGROVES,
+Response: AND THE MOME RATHS OUTGRABE.
+Shutting down listener for clientSystem.Byte[]
+Response: THAT'S ALL, FOLKS!
diff --git a/dotnet/client-010/examples/request-response/verify_cpp_dotnet b/dotnet/client-010/examples/request-response/verify_cpp_dotnet
new file mode 100644
index 0000000000..791f48fe60
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify_cpp_dotnet
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/request-response
+
+client_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-request-response-Client.exe localhost 5672
+}
+
+background "Waiting" $cpp/server
+clients client_dotnet
+kill %%
+outputs ./client_dotnet.out "$cpp/server.out | remove_uuid"
diff --git a/dotnet/client-010/examples/request-response/verify_cpp_dotnet.in b/dotnet/client-010/examples/request-response/verify_cpp_dotnet.in
new file mode 100644
index 0000000000..0f4b5341b2
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify_cpp_dotnet.in
@@ -0,0 +1,17 @@
+==== client_dotnet.out
+Activating response queue listener for: clientSystem.Byte[]
+Waiting for all responses to arrive ...
+Response: TWAS BRILLIG, AND THE SLITHY TOVES
+Response: DID GIRE AND GYMBLE IN THE WABE.
+Response: ALL MIMSY WERE THE BOROGROVES,
+Response: AND THE MOME RATHS OUTGRABE.
+Shutting down listener for clientSystem.Byte[]
+Response: THAT'S ALL, FOLKS!
+==== server.out | remove_uuid
+Activating request queue listener for: request
+Waiting for requests
+Request: Twas brillig, and the slithy toves (clientSystem.Byte[])
+Request: Did gire and gymble in the wabe. (clientSystem.Byte[])
+Request: All mimsy were the borogroves, (clientSystem.Byte[])
+Request: And the mome raths outgrabe. (clientSystem.Byte[])
+Request: That's all, folks! (clientSystem.Byte[])
diff --git a/dotnet/client-010/examples/request-response/verify_dotnet_cpp b/dotnet/client-010/examples/request-response/verify_dotnet_cpp
new file mode 100644
index 0000000000..95905c43c9
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify_dotnet_cpp
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+
+# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
+cpp=$CPP/request-response
+
+server_dotnet()
+{
+mono $DOTNET_EXAMPLES/example-request-response-Server.exe localhost 5672
+}
+
+background "Waiting for requests" server_dotnet
+clients $cpp/client
+kill %%
+outputs "$cpp/client.out | remove_uuid" ./server_dotnet.out
diff --git a/dotnet/client-010/examples/request-response/verify_dotnet_cpp.in b/dotnet/client-010/examples/request-response/verify_dotnet_cpp.in
new file mode 100644
index 0000000000..849fad39c6
--- /dev/null
+++ b/dotnet/client-010/examples/request-response/verify_dotnet_cpp.in
@@ -0,0 +1,18 @@
+==== client.out | remove_uuid
+Activating response queue listener for: client
+Request: Twas brillig, and the slithy toves
+Request: Did gire and gymble in the wabe.
+Request: All mimsy were the borogroves,
+Request: And the mome raths outgrabe.
+Waiting for all responses to arrive ...
+Response: TWAS BRILLIG, AND THE SLITHY TOVES
+Response: DID GIRE AND GYMBLE IN THE WABE.
+Response: ALL MIMSY WERE THE BOROGROVES,
+Response: AND THE MOME RATHS OUTGRABE.
+Shutting down listener for client
+==== server_dotnet.out
+Waiting for requests
+Request: Twas brillig, and the slithy toves
+Request: Did gire and gymble in the wabe.
+Request: All mimsy were the borogroves,
+Request: And the mome raths outgrabe.
diff --git a/dotnet/client-010/gentool/Composite.tpl b/dotnet/client-010/gentool/Composite.tpl
new file mode 100644
index 0000000000..c5a1099ef3
--- /dev/null
+++ b/dotnet/client-010/gentool/Composite.tpl
@@ -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.
+ *
+ */
+
+using System;
+using org.apache.qpid.transport.codec;
+using System.Collections.Generic;
+using org.apache.qpid.transport.util;
+using org.apache.qpid.transport.network;
+using System.IO;
+
+namespace org.apache.qpid.transport
+{
+
+${
+from genutil import *
+
+cls = klass(type)["@name"]
+
+segments = type["segments"]
+
+if type.name in ("control", "command"):
+ override = "override"
+ base = "Method"
+ size = 0
+ pack = 2
+ if segments:
+ payload = "true"
+ else:
+ payload = "false"
+ if type.name == "control" and cls == "connection":
+ track = "Frame.L1"
+ elif cls == "session" and type["@name"] in ("attach", "attached", "detach", "detached"):
+ track = "Frame.L2"
+ elif type.name == "command":
+ track = "Frame.L4"
+ else:
+ track = "Frame.L3"
+else:
+ override = ""
+ base = "Struct"
+ size = type["@size"]
+ pack = num(type["@pack"])
+ payload = "false"
+ track = "4"
+
+PACK_TYPES = {
+ 1: "byte",
+ 2: "int",
+ 4: "int"
+}
+
+typecode = code(type)
+}
+
+public sealed class $name : $base {
+
+ public const int TYPE = $typecode;
+
+ public override int GetStructType() {
+ return TYPE;
+ }
+
+ public override int GetSizeWidth() {
+ return $size;
+ }
+
+ public override int GetPackWidth() {
+ return $pack;
+ }
+
+ public $override bool HasPayload() {
+ return $payload;
+ }
+
+ public $override byte EncodedTrack
+ {
+ get{ return $track; }
+ set { throw new NotImplementedException(); }
+ }
+
+${
+from dotnetgenutil import *
+if pack > 0:
+ out(" private $(PACK_TYPES[pack]) packing_flags = 0;\n");
+
+fields = get_fields(type)
+params = get_dotnetparameters(type, fields)
+options = get_options(fields)
+
+for f in fields:
+ if not f.empty:
+ out(" private $(f.type) _$(f.name);\n")
+
+if segments:
+ out(" private Header _header;\n")
+ out(" private MemoryStream _body = new MemoryStream();\n")
+}
+
+${
+if fields:
+ out(" public $name() {}\n")
+}
+
+ public $name($(", ".join(params))) {
+${
+for f in fields:
+ if f.option: continue
+ out(" $(f.set)($(f.name));\n")
+
+if segments:
+ out(" Header = header;\n")
+ out(" Body = body;\n")
+
+if options or base == "Method":
+ out("""
+ for (int i=0; i < options.Length; i++) {
+ switch (options[i]) {
+""")
+
+ for f in options:
+ out(" case Option.$(f.option): packing_flags |= $(f.flag_mask(pack)); break;\n")
+
+ if base == "Method":
+ out(""" case Option.SYNC: Sync = true; break;
+ case Option.BATCH: Batch = true; break;
+""")
+ out(""" case Option.NONE: break;
+ default: throw new Exception("invalid option: " + options[i]);
+ }
+ }
+""")
+}
+ }
+
+ public $override void Dispatch<C>(C context, MethodDelegate<C> mdelegate) {
+ mdelegate.$(name)(context, this);
+ }
+
+${
+for f in fields:
+ if pack > 0:
+ out("""
+ public bool $(f.has)() {
+ return (packing_flags & $(f.flag_mask(pack))) != 0;
+ }
+
+ public $name $(f.clear)() {
+ packing_flags = (byte) (packing_flags & ~$(f.flag_mask(pack)));
+${
+if (not f.empty and not (f.default == "null")):
+ out(" _$(f.name) = $(f.default);")
+}
+ Dirty = true;
+ return this;
+ }
+""")
+
+ out("""
+ public $(f.type) $(f.get)() {
+${
+if f.empty:
+ out(" return $(f.has)();")
+else:
+ out(" return _$(f.name);")
+}
+ }
+
+ public $name $(f.set)($(f.type) value) {
+${
+if not f.empty:
+ out(" _$(f.name) = value;")
+}
+${
+if pack > 0:
+ out(" packing_flags |= $(f.flag_mask(pack));")
+}
+ Dirty = true;
+ return this;
+ }
+
+""")
+}
+
+${
+if segments:
+ out(""" public override Header Header {
+ get { return _header;}
+ set { _header = value;}
+ }
+
+ public $name SetHeader(Header header) {
+ Header = header;
+ return this;
+ }
+
+ public override MemoryStream Body
+ {
+ get{ return _body;}
+ set{ _body = value;}
+ }
+
+ public $name SetBody(MemoryStream body)
+ {
+ Body = body;
+ return this;
+ }
+""")
+}
+
+ public override void Write(IEncoder enc)
+ {
+${
+if pack > 0:
+ out(" enc.WriteUint%s(packing_flags);\n" % (pack*8));
+
+for f in fields:
+ if f.empty:
+ continue
+ if pack > 0:
+ out(" if ((packing_flags & $(f.flag_mask(pack))) != 0)\n ")
+ pre = ""
+ post = ""
+ if f.type_node.name == "struct":
+ pre = "%s.TYPE, " % cname(f.type_node)
+ elif f.type_node.name == "domain":
+ post = ""
+ pre = "(short)"
+ out(" enc.Write$(f.coder)($(pre)_$(f.name)$(post));\n")
+}
+ }
+
+ public override void Read(IDecoder dec)
+ {
+${
+if pack > 0:
+ out(" packing_flags = ($(PACK_TYPES[pack])) dec.ReadUint%s();\n" % (pack*8));
+
+for f in fields:
+ if f.empty:
+ continue
+ if pack > 0:
+ out(" if ((packing_flags & $(f.flag_mask(pack))) != 0)\n ")
+ pre = ""
+ post = ""
+ arg = ""
+ if f.type_node.name == "struct":
+ pre = "(%s)" % cname(f.type_node)
+ arg = "%s.TYPE" % cname(f.type_node)
+ elif f.type_node.name == "domain":
+ pre = "%sGetter.Get(" % cname(f.type_node)
+ post = ")"
+ out(" _$(f.name) = $(pre)dec.Read$(f.coder)($(arg))$(post);\n")
+}
+ }
+
+ public override Dictionary<String,Object> Fields
+ {
+ get
+ {
+ Dictionary<String,Object> result = new Dictionary<String,Object>();
+
+${
+for f in fields:
+ if pack > 0:
+ out(" if ((packing_flags & $(f.flag_mask(pack))) != 0)\n ")
+ out(' result.Add("_$(f.name)", $(f.get)());\n')
+}
+ return result;
+ }
+ }
+
+}
+}
diff --git a/dotnet/client-010/gentool/Constant.tpl b/dotnet/client-010/gentool/Constant.tpl
new file mode 100644
index 0000000000..191a1dbd6e
--- /dev/null
+++ b/dotnet/client-010/gentool/Constant.tpl
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+namespace org.apache.qpid.transport
+{
+
+${from genutil import *}
+
+public class Constant
+{
+${
+constants = spec.query["amqp/constant"]
+
+for c in constants:
+ name = scream(c["@name"])
+ value = c["@value"]
+ out(" public const int $name = $value;\n")
+}}
+}
diff --git a/dotnet/client-010/gentool/Enum.tpl b/dotnet/client-010/gentool/Enum.tpl
new file mode 100644
index 0000000000..5d958c7bf6
--- /dev/null
+++ b/dotnet/client-010/gentool/Enum.tpl
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+namespace org.apache.qpid.transport
+{
+${
+from genutil import *
+
+vtype = jtype(resolve_type(type))
+
+out(" public enum $name : $vtype")
+
+choices = [(scream(ch["@name"]), "= %s" % (ch["@value"]))
+ for ch in type.query["enum/choice"]]
+}
+ {
+ $(",\n ".join(["%s%s" % ch for ch in choices]))
+ }
+
+${
+
+out(" public struct $name")
+out("Getter")
+}
+ {
+ public static $name Get($vtype value)
+ {
+ switch (value)
+ {
+${
+choices = [(scream(ch["@name"]), "%s" % (ch["@value"]))
+ for ch in type.query["enum/choice"]]
+
+for ch, value in choices:
+ out(' case $value: return $name.$ch;\n')
+} default: throw new Exception("no such value: " + value);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/gentool/IInvoker.tpl b/dotnet/client-010/gentool/IInvoker.tpl
new file mode 100644
index 0000000000..713d10c610
--- /dev/null
+++ b/dotnet/client-010/gentool/IInvoker.tpl
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace org.apache.qpid.transport
+{
+
+public interface IInvoker {
+
+ IFuture Invoke(Method method, IFuture resultClass);
+
+${
+from dotnetgenutil import *
+
+for c in composites:
+ name = cname(c)
+ fields = get_fields(c)
+ params = get_dotnetparameters(c, fields)
+ args = get_arguments(c, fields)
+ result = c["result"]
+ if result:
+ if not result["@type"]:
+ rname = cname(result["struct"])
+ else:
+ rname = cname(result, "@type")
+ jresult = "IFuture"
+ else:
+ jresult = "void"
+
+ out("""
+ $jresult $(name)($(", ".join(params)));
+""")
+}
+
+}
+}
diff --git a/dotnet/client-010/gentool/Invoker.tpl b/dotnet/client-010/gentool/Invoker.tpl
new file mode 100644
index 0000000000..2f69aee66d
--- /dev/null
+++ b/dotnet/client-010/gentool/Invoker.tpl
@@ -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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using common.org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.transport
+{
+
+public abstract class Invoker : IInvoker {
+
+ protected abstract void Invoke(Method method);
+ public abstract IFuture Invoke(Method method, IFuture resultClass);
+
+${
+from dotnetgenutil import *
+
+for c in composites:
+ name = cname(c)
+ fields = get_fields(c)
+ params = get_dotnetparameters(c, fields)
+ args = get_arguments(c, fields)
+ result = c["result"]
+ if result:
+ if not result["@type"]:
+ rname = cname(result["struct"])
+ else:
+ rname = cname(result, "@type")
+ jresult = "IFuture"
+ jreturn = "return "
+ jclass = ", new ResultFuture()"
+ jinvoke = "Invoke"
+ else:
+ jinvoke = "Invoke"
+ jresult = "void"
+ jreturn = ""
+ jclass = ""
+
+ out("""
+ public $jresult $(name)($(", ".join(params))) {
+ $(jreturn)$jinvoke(new $name($(", ".join(args)))$jclass);
+ }
+""")
+}
+
+}
+}
diff --git a/dotnet/client-010/gentool/MethodDelegate.tpl b/dotnet/client-010/gentool/MethodDelegate.tpl
new file mode 100644
index 0000000000..788d2e29e6
--- /dev/null
+++ b/dotnet/client-010/gentool/MethodDelegate.tpl
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+namespace org.apache.qpid.transport
+{
+
+public abstract class MethodDelegate<C> {
+
+${
+from genutil import *
+
+for c in composites:
+ name = cname(c)
+ out(" public virtual void $(name)(C context, $name mystruct) {}\n")
+}
+}
+}
diff --git a/dotnet/client-010/gentool/Option.tpl b/dotnet/client-010/gentool/Option.tpl
new file mode 100644
index 0000000000..d6e1a44870
--- /dev/null
+++ b/dotnet/client-010/gentool/Option.tpl
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+namespace org.apache.qpid.transport
+{
+public enum Option {
+
+${
+from genutil import *
+
+options = {}
+
+for c in composites:
+ for f in c.query["field"]:
+ t = resolve_type(f)
+ if t["@name"] == "bit":
+ option = scream(f["@name"])
+ if not options.has_key(option):
+ options[option] = None
+ out(" $option,\n")}
+ BATCH,
+ NONE
+}
+}
diff --git a/dotnet/client-010/gentool/StructFactory.tpl b/dotnet/client-010/gentool/StructFactory.tpl
new file mode 100644
index 0000000000..2a11e2530c
--- /dev/null
+++ b/dotnet/client-010/gentool/StructFactory.tpl
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+
+namespace org.apache.qpid.transport
+{
+
+class StructFactory {
+
+ public static Struct create(int type)
+ {
+ switch (type)
+ {
+${
+from genutil import *
+
+fragment = """ case $name.TYPE:
+ return new $name();
+"""
+
+for c in composites:
+ name = cname(c)
+ if c.name == "struct":
+ out(fragment)
+} default:
+ throw new Exception("type: " + type);
+ }
+ }
+
+ public static Struct createInstruction(int type)
+ {
+ switch (type)
+ {
+${
+for c in composites:
+ name = cname(c)
+ if c.name in ("command", "control"):
+ out(fragment)
+} default:
+ throw new Exception("type: " + type);
+ }
+ }
+
+}
+}
diff --git a/dotnet/client-010/gentool/Type.tpl b/dotnet/client-010/gentool/Type.tpl
new file mode 100644
index 0000000000..c8ec7ac153
--- /dev/null
+++ b/dotnet/client-010/gentool/Type.tpl
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+namespace org.apache.qpid.transport
+{
+
+${from genutil import *}
+
+public struct QpidType
+{
+ public Code code;
+ public int width;
+ public bool isfixed;
+
+ public Code Code
+ {
+ get { return code; }
+ set { code = value; }
+ }
+
+ public int Width
+ {
+ get { return width; }
+ set { width = value; }
+ }
+
+ public bool Fixed
+ {
+ get { return isfixed; }
+ set { isfixed = value; }
+ }
+
+ QpidType(Code code, int width, bool isfixed)
+ {
+ this.code = code;
+ this.width = width;
+ this.isfixed = isfixed;
+ }
+
+ public static QpidType get(byte code)
+ {
+ switch (code)
+ {
+${
+types = spec.query["amqp/type"] + spec.query["amqp/class/type"]
+codes = {}
+first = True
+for t in types:
+ code = t["@code"]
+ fix_width = t["@fixed-width"]
+ var_width = t["@variable-width"]
+
+ if code is None:
+ continue
+
+ if fix_width is None:
+ width = var_width
+ fixed = "false"
+ else:
+ width = fix_width
+ fixed = "true"
+
+ name = scream(t["@name"])
+ codes[code] = name
+
+ out(" case $code : return new QpidType(Code.$name, $width, $fixed);\n")
+}
+ default: throw new Exception("unknown code: " + code);
+ }
+ }
+}
+
+public enum Code : byte
+ {
+${
+keys = list(codes.keys())
+keys.sort()
+
+for code in keys:
+ out(" $(codes[code]) = $code,\n")
+}
+ }
+}
diff --git a/dotnet/client-010/gentool/build.xml b/dotnet/client-010/gentool/build.xml
new file mode 100644
index 0000000000..76ddb1571d
--- /dev/null
+++ b/dotnet/client-010/gentool/build.xml
@@ -0,0 +1,52 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<project name="GenTool" default="build">
+
+ <property name="generated.dir" location="../client/" />
+ <property name="gentools.timestamp" location="${generated.dir}/gentools.timestamp" />
+ <property name="jython.timestamp" location="${generated.dir}/jython.timestamp" />
+ <property name="java.basedir" location="../../../java/common" />
+ <property name="mllib.dir" location="../../../python" />
+ <property name="xml.spec.dir" location="../../../specs" />
+
+
+ <target name="check_jython_deps">
+ <uptodate property="jython.notRequired" targetfile="${jython.timestamp}">
+ <srcfiles dir="${xml.spec.dir}" includes="amqp.0-10-qpid-errata.xml" />
+ </uptodate>
+ </target>
+
+ <target name="build" depends="check_jython_deps" unless="jython.notRequired">
+ <java classname="org.python.util.jython" fork="true" failonerror="true">
+ <arg value="-Dpython.cachedir.skip=true"/>
+ <arg value="-Dpython.path=${java.basedir}/../lib/jython-lib.jar/Lib${path.separator}${mllib.dir}${path.separator}${java.basedir}${path.separator}${basedir}"/>
+ <arg value="${basedir}/codegen"/>
+ <arg value="${generated.dir}"/>
+ <arg value="${xml.spec.dir}/amqp.0-10-qpid-errata.xml"/>
+ <arg value="${basedir}"/>
+ <classpath>
+ <pathelement location="../../../java/lib/jython-2.5.0.jar"/>
+ </classpath>
+ </java>
+ <touch file="${jython.timestamp}" />
+ </target>
+
+</project>
diff --git a/dotnet/client-010/gentool/codegen b/dotnet/client-010/gentool/codegen
new file mode 100644
index 0000000000..baebf378fd
--- /dev/null
+++ b/dotnet/client-010/gentool/codegen
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+#
+# 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.
+#
+#
+
+
+import os, sys, mllib
+from templating import Parser
+from dotnetgenutil import *
+
+out_dir = sys.argv[1]
+spec_file = sys.argv[2]
+tpl_dir = sys.argv[3]
+pkg_dir = os.path.join(out_dir, "generated")
+
+if not os.path.exists(pkg_dir):
+ os.makedirs(pkg_dir)
+
+spec = mllib.xml_parse(spec_file)
+
+def excludes(nd):
+ if (nd.parent is not None and
+ nd.parent.name == "class" and
+ nd.parent["@name"] in ("file", "stream")):
+ return False
+ else:
+ return True
+
+def execute(output, template, **kwargs):
+ f = open(os.path.join(tpl_dir, template))
+ input = f.read()
+ f.close()
+ p = Parser(**kwargs)
+ p.parse(input)
+ fname = os.path.join(pkg_dir, output)
+ f = open(fname, "w")
+ f.write(p.output)
+ f.close()
+
+execute("Type.cs", "Type.tpl", spec = spec)
+execute("Constant.cs", "Constant.tpl", spec = spec)
+
+structs = spec.query["amqp/struct"] + \
+ spec.query["amqp/class/struct", excludes] + \
+ spec.query["amqp/class/command/result/struct", excludes]
+controls = spec.query["amqp/class/control", excludes]
+commands = spec.query["amqp/class/command", excludes]
+
+composites = structs + controls + commands
+
+for c in composites:
+ name = cname(c)
+ execute("%s.cs" % name, "Composite.tpl", type = c, name = name)
+
+execute("MethodDelegate.cs", "MethodDelegate.tpl", composites = composites)
+execute("Option.cs", "Option.tpl", composites = composites)
+execute("Invoker.cs", "Invoker.tpl", composites = controls + commands)
+execute("IInvoker.cs", "IInvoker.tpl", composites = controls + commands)
+execute("StructFactory.cs", "StructFactory.tpl", composites = composites)
+
+def is_enum(nd):
+ return nd["enum"] is not None
+
+enums = spec.query["amqp/domain", is_enum] + \
+ spec.query["amqp/class/domain", is_enum]
+
+for e in enums:
+ name = cname(e)
+ execute("%s.cs" % name, "Enum.tpl", name = name, type = e)
diff --git a/dotnet/client-010/gentool/dotnetgenutil.py b/dotnet/client-010/gentool/dotnetgenutil.py
new file mode 100644
index 0000000000..4d9c8a69d7
--- /dev/null
+++ b/dotnet/client-010/gentool/dotnetgenutil.py
@@ -0,0 +1,271 @@
+#
+#
+# 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.
+#
+#
+
+
+def pascal(offset, *args):
+ parts = []
+ for a in args:
+ parts.extend(a.split("-"))
+ return "".join([p[0].upper() + p[1:] for p in parts[:offset]] + [p[0].upper() + p[1:] for p in parts[offset:]])
+
+
+def scream(*args):
+ return "_".join([a.replace("-", "_").upper() for a in args])
+
+def num(x, default=None):
+ if x is not None and x != "":
+ return int(x, 0)
+ else:
+ return default
+
+def klass(nd):
+ parent = nd.parent
+ while parent is not None:
+ if hasattr(parent, "name") and parent.name == "class":
+ return parent
+ parent = parent.parent
+
+untyped = -1
+
+def code(nd):
+ global untyped
+ cd = num(nd["@code"])
+ if cd is None:
+ cd = untyped
+ untyped -= 1
+ return cd
+
+ cls = klass(nd)
+ if cls:
+ cd |= (num(cls["@code"]) << 8)
+ return cd
+
+def root(nd):
+ if nd.parent is None:
+ return nd
+ else:
+ return root(nd.parent)
+
+def qname(nd):
+ name = nd["@name"]
+ cls = klass(nd)
+ if cls != None:
+ return "%s.%s" % (cls["@name"], name)
+ else:
+ return name
+
+RESOLVED = {}
+
+def resolve(node, name):
+ key = (node, name)
+ if RESOLVED.has_key(key):
+ return RESOLVED[key]
+ else:
+ spec = root(node)
+ cls = klass(node)
+ if cls:
+ for nd in cls.query["#tag"]:
+ if nd["@name"] == name:
+ RESOLVED[key] = nd
+ return nd
+ for nd in spec.query["amqp/#tag"] + spec.query["amqp/class/#tag"]:
+ if name == qname(nd):
+ RESOLVED[key] = nd
+ return nd
+ raise Exception("unresolved name: %s" % name)
+
+def resolve_type(nd):
+ if hasattr(nd, "_resolved_type"):
+ return nd._resolved_type
+ else:
+ name = nd["@type"]
+ type = resolve(nd, name)
+ if type.name == "domain" and not type["enum"]:
+ type = resolve_type(type)
+ nd._resolved_type = type
+ return type
+
+TYPES = {
+ "bit": "bool",
+ "uint8": "short",
+ "uint16": "int",
+ "uint32": "long",
+ "uint64": "long",
+ "datetime": "long",
+ "uuid": "UUID",
+ "sequence-no": "int",
+ "sequence-set": "RangeSet", # XXX
+ "byte-ranges": "RangeSet", # XXX
+ "str8": "String",
+ "str16": "String",
+ "vbin8": "byte[]",
+ "vbin16": "byte[]",
+ "vbin32": "byte[]",
+ "struct32": "Struct",
+ "map": "Dictionary<String,Object>",
+ "array": "List<Object>"
+ }
+
+def cname(nd, field="@name"):
+ cls = klass(nd)
+ if cls:
+ if (nd.name in ("struct", "result") and
+ cls["@name"] != "session" and
+ nd[field] != "header"):
+ return pascal(0, nd[field])
+ else:
+ return pascal(0, cls["@name"], nd[field])
+ else:
+ return pascal(0, nd[field])
+
+def jtype(nd):
+ if nd.name == "struct" or nd["enum"]:
+ return cname(nd)
+ else:
+ return TYPES[nd["@name"]]
+
+REFS = {
+ "bool": "Boolean",
+ "byte": "Byte",
+ "short": "Short",
+ "int": "Integer",
+ "long": "Long",
+ "float": "Float",
+ "double": "Double",
+ "char": "Character"
+}
+
+def jref(jt):
+ return REFS.get(jt, jt)
+
+def jclass(jt):
+ idx = jt.find('<')
+ if idx > 0:
+ return jt[:idx]
+ else:
+ return jt
+
+DEFAULTS = {
+ "long": 0,
+ "int": 0,
+ "short": 0,
+ "byte": 0,
+ "char": 0,
+ "bool": "false"
+ }
+
+class Field:
+
+ def __init__(self, index, nd):
+ self.index = index
+ self.name = pascal(1, nd["@name"])
+ self.type_node = resolve_type(nd)
+ if self.type_node.name == "domain":
+ self.prim_type = resolve_type(self.type_node)
+ else:
+ self.prim_type = self.type_node
+ self.variable_width = num(self.prim_type["@variable-width"], 0)
+ self.fixed_width = num(self.prim_type["@fixed-width"], 0)
+ self.empty = self.variable_width == 0 and self.fixed_width == 0 and self.prim_type.name != "struct"
+ tname = cname(self.type_node)
+ if self.type_node.name == "struct":
+ self.read = "(%s) dec.ReadStruct(%s.TYPE)" % (tname, tname)
+ self.write = "enc.WriteStruct(%s.TYPE, check(struct).%s)" % (tname, self.name)
+ self.coder = "Struct"
+ elif self.type_node.name == "domain":
+ self.coder = pascal(0, self.prim_type["@name"])
+ self.read = "%s.Get(dec.Read%s())" % (tname, self.coder)
+ self.write = "enc.Write%s(check(struct).%s.GetValue())" % (self.coder, self.name)
+ else:
+ self.coder = pascal(0, self.type_node["@name"])
+ self.read = "dec.Read%s()" % self.coder
+ self.write = "enc.Write%s(check(struct).%s)" % (self.coder, self.name)
+ self.type = jtype(self.type_node)
+ self.default = DEFAULTS.get(self.type, "null")
+ self.has = pascal(1, "Has", self.name)
+ self.get = pascal(1, "Get", self.name)
+ self.set = pascal(1, "Set", self.name)
+ self.clear = pascal(1, "clear", self.name)
+ if self.type == "bool":
+ self.option = scream(nd["@name"])
+ else:
+ self.option = None
+
+ def flag_mask(self, pack):
+ flag = pack * 8 - 8 - (self.index/8)*8 + (self.index % 8)
+ return 1 << flag
+
+
+def get_fields(nd):
+ fields = []
+ index = 0
+ for f in nd.query["field"]:
+ fields.append(Field(index, f))
+ index += 1
+ return fields
+
+def get_parameters(type, fields):
+ params = []
+ options = False
+ for f in fields:
+ if f.option:
+ options = True
+ else:
+ params.append("%s %s" % (f.type, f.name))
+ if type["segments"]:
+ params.append("Header header")
+ params.append("MemoryStream body")
+ if options or type.name in ("control", "command"):
+ params.append("Option ... options")
+ return params
+
+def get_arguments(type, fields):
+ args = []
+ options = False
+ for f in fields:
+ if f.option:
+ options = True
+ else:
+ args.append(f.name)
+ if type["segments"]:
+ args.append("header")
+ args.append("body")
+ if options or type.name in ("control", "command"):
+ args.append("options")
+ return args
+
+def get_options(fields):
+ return [f for f in fields if f.option]
+
+def get_dotnetparameters(type, fields):
+ params = []
+ options = False
+ for f in fields:
+ if f.option:
+ options = True
+ else:
+ params.append("%s %s" % (f.type, f.name))
+ if type["segments"]:
+ params.append("Header header")
+ params.append("MemoryStream body")
+ if options or type.name in ("control", "command"):
+ params.append("params Option[] options")
+ return params
diff --git a/dotnet/client-010/lib/log4net/log4net-licence.txt b/dotnet/client-010/lib/log4net/log4net-licence.txt
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/dotnet/client-010/lib/log4net/log4net-licence.txt
@@ -0,0 +1,201 @@
+ 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/dotnet/client-010/lib/log4net/log4net.dll b/dotnet/client-010/lib/log4net/log4net.dll
new file mode 100644
index 0000000000..995816f27b
--- /dev/null
+++ b/dotnet/client-010/lib/log4net/log4net.dll
Binary files differ
diff --git a/dotnet/client-010/lib/log4net/log4net.xml b/dotnet/client-010/lib/log4net/log4net.xml
new file mode 100644
index 0000000000..5beb669ab0
--- /dev/null
+++ b/dotnet/client-010/lib/log4net/log4net.xml
@@ -0,0 +1,28676 @@
+<?xml version="1.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.
+
+-->
+
+<doc>
+ <assembly>
+ <name>log4net</name>
+ </assembly>
+ <members>
+ <member name="T:log4net.Appender.AdoNetAppender">
+ <summary>
+ Appender that logs to a database.
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Appender.AdoNetAppender"/> appends logging events to a table within a
+ database. The appender can be configured to specify the connection
+ string by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionString"/> property.
+ The connection type (provider) can be specified by setting the <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/>
+ property. For more information on database connection strings for
+ your specific database see <a href="http://www.connectionstrings.com/">http://www.connectionstrings.com/</a>.
+ </para>
+ <para>
+ Records are written into the database either using a prepared
+ statement or a stored procedure. The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property
+ is set to <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify a prepared statement
+ or to <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify a stored
+ procedure.
+ </para>
+ <para>
+ The prepared statement text or the name of the stored procedure
+ must be set in the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property.
+ </para>
+ <para>
+ The prepared statement or stored procedure can take a number
+ of parameters. Parameters are added using the <see cref="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)"/>
+ method. This adds a single <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> to the
+ ordered list of parameters. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/>
+ type may be subclassed if required to provide database specific
+ functionality. The <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> specifies
+ the parameter name, database type, size, and how the value should
+ be generated using a <see cref="T:log4net.Layout.ILayout"/>.
+ </para>
+ </remarks>
+ <example>
+ An example of a SQL Server table that could be logged to:
+ <code lang="SQL">
+ CREATE TABLE [dbo].[Log] (
+ [ID] [int] IDENTITY (1, 1) NOT NULL ,
+ [Date] [datetime] NOT NULL ,
+ [Thread] [varchar] (255) NOT NULL ,
+ [Level] [varchar] (20) NOT NULL ,
+ [Logger] [varchar] (255) NOT NULL ,
+ [Message] [varchar] (4000) NOT NULL
+ ) ON [PRIMARY]
+ </code>
+ </example>
+ <example>
+ An example configuration to log to the above table:
+ <code lang="XML" escaped="true">
+ <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
+ <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
+ <connectionString value="data source=SQLSVR;initial catalog=test_log4net;integrated security=false;persist security info=True;User ID=sa;Password=sa"/>
+ <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message]) VALUES (@log_date, @thread, @log_level, @logger, @message)"/>
+ <parameter>
+ <parameterName value="@log_date"/>
+ <dbType value="DateTime"/>
+ <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss'.'fff}"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@thread"/>
+ <dbType value="String"/>
+ <size value="255"/>
+ <layout type="log4net.Layout.PatternLayout" value="%thread"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@log_level"/>
+ <dbType value="String"/>
+ <size value="50"/>
+ <layout type="log4net.Layout.PatternLayout" value="%level"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@logger"/>
+ <dbType value="String"/>
+ <size value="255"/>
+ <layout type="log4net.Layout.PatternLayout" value="%logger"/>
+ </parameter>
+ <parameter>
+ <parameterName value="@message"/>
+ <dbType value="String"/>
+ <size value="4000"/>
+ <layout type="log4net.Layout.PatternLayout" value="%message"/>
+ </parameter>
+ </appender>
+ </code>
+ </example>
+ <author>Julian Biddle</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Lance Nehring</author>
+ </member>
+ <member name="T:log4net.Appender.BufferingAppenderSkeleton">
+ <summary>
+ Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/> that
+ buffers events in a fixed size buffer.
+ </summary>
+ <remarks>
+ <para>
+ This base class should be used by appenders that need to buffer a
+ number of events before logging them. For example the <see cref="T:log4net.Appender.AdoNetAppender"/>
+ buffers events and then submits the entire contents of the buffer to
+ the underlying database in one go.
+ </para>
+ <para>
+ Subclasses should override the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>
+ method to deliver the buffered events.
+ </para>
+ <para>The BufferingAppenderSkeleton maintains a fixed size cyclic
+ buffer of events. The size of the buffer is set using
+ the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> property.
+ </para>
+ <para>A <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> is used to inspect
+ each event as it arrives in the appender. If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/>
+ triggers, then the current buffer is sent immediately
+ (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>). Otherwise the event
+ is stored in the buffer. For example, an evaluator can be used to
+ deliver the events immediately when an ERROR event arrives.
+ </para>
+ <para>
+ The buffering appender can be configured in a <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode.
+ By default the appender is NOT lossy. When the buffer is full all
+ the buffered events are sent with <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+ If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property is set to <c>true</c> then the
+ buffer will not be sent when it is full, and new events arriving
+ in the appender will overwrite the oldest event in the buffer.
+ In lossy mode the buffer will only be sent when the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/>
+ triggers. This can be useful behavior when you need to know about
+ ERROR events but not about events with a lower level, configure an
+ evaluator that will trigger when an ERROR event arrives, the whole
+ buffer will be sent which gives a history of events leading up to
+ the ERROR event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Appender.AppenderSkeleton">
+ <summary>
+ Abstract base class implementation of <see cref="T:log4net.Appender.IAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ This class provides the code for common functionality, such
+ as support for threshold filtering and support for general filters.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Appender.IAppender">
+ <summary>
+ Implement this interface for your own strategies for printing log statements.
+ </summary>
+ <remarks>
+ <para>
+ Implementors should consider extending the <see cref="T:log4net.Appender.AppenderSkeleton"/>
+ class which provides a default implementation of this interface.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.IAppender.Close">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logging event in Appender specific way.
+ </summary>
+ <param name="loggingEvent">The event to log</param>
+ <remarks>
+ <para>
+ This method is called to log a message into this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.IAppender.Name">
+ <summary>
+ Gets or sets the name of this appender.
+ </summary>
+ <value>The name of the appender.</value>
+ <remarks>
+ <para>The name uniquely identifies the appender.</para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.IBulkAppender">
+ <summary>
+ Interface for appenders that support bulk logging.
+ </summary>
+ <remarks>
+ <para>
+ This interface extends the <see cref="T:log4net.Appender.IAppender"/> interface to
+ support bulk logging of <see cref="T:log4net.Core.LoggingEvent"/> objects. Appenders
+ should only implement this interface if they can bulk log efficiently.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.IBulkAppender.DoAppend(log4net.Core.LoggingEvent[])">
+ <summary>
+ Log the array of logging events in Appender specific way.
+ </summary>
+ <param name="loggingEvents">The events to log</param>
+ <remarks>
+ <para>
+ This method is called to log an array of events into this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.IOptionHandler">
+ <summary>
+ Interface used to delay activate a configured object.
+ </summary>
+ <remarks>
+ <para>
+ This allows an object to defer activation of its options until all
+ options have been set. This is required for components which have
+ related options that remain ambiguous until all are set.
+ </para>
+ <para>
+ If a component implements this interface then the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ must be called by the container after its all the configured properties have been set
+ and before the component can be used.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.IOptionHandler.ActivateOptions">
+ <summary>
+ Activate the options that were previously set with calls to properties.
+ </summary>
+ <remarks>
+ <para>
+ This allows an object to defer activation of its options until all
+ options have been set. This is required for components which have
+ related options that remain ambiguous until all are set.
+ </para>
+ <para>
+ If a component implements this interface then this method must be called
+ after its properties have been set before the component can be used.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferSize">
+ <summary>
+ Initial buffer size
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.c_renderBufferMaxCapacity">
+ <summary>
+ Maximum buffer size before it is recycled
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>Empty default constructor</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Finalize">
+ <summary>
+ Finalizes this appender by calling the implementation's
+ <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> method.
+ </summary>
+ <remarks>
+ <para>
+ If this appender has not been closed then the <c>Finalize</c> method
+ will call <see cref="M:log4net.Appender.AppenderSkeleton.Close"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Close">
+ <summary>
+ Closes the appender and release resources.
+ </summary>
+ <remarks>
+ <para>
+ Release any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ <para>
+ This method cannot be overridden by subclasses. This method
+ delegates the closing of the appender to the <see cref="M:log4net.Appender.AppenderSkeleton.OnClose"/>
+ method which must be overridden in the subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)">
+ <summary>
+ Performs threshold checks and invokes filters before
+ delegating actual logging to the subclasses specific
+ <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ This method cannot be overridden by derived classes. A
+ derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method
+ which is called by this method.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ <item>
+ <description>
+ Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that
+ it returns <c>true</c>.</description>
+ </item>
+ </list>
+ </para>
+ <para>
+ If all of the above steps succeed then the <paramref name="loggingEvent"/>
+ will be passed to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])">
+ <summary>
+ Performs threshold checks and invokes filters before
+ delegating actual logging to the subclasses specific
+ <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ This method cannot be overridden by derived classes. A
+ derived class should override the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method
+ which is called by this method.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ <item>
+ <description>
+ Calls <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> and checks that
+ it returns <c>true</c>.</description>
+ </item>
+ </list>
+ </para>
+ <para>
+ If all of the above steps succeed then the <paramref name="loggingEvents"/>
+ will be passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.FilterEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Test if the logging event should we output by this appender
+ </summary>
+ <param name="loggingEvent">the event to test</param>
+ <returns><c>true</c> if the event should be output, <c>false</c> if the event should be ignored</returns>
+ <remarks>
+ <para>
+ This method checks the logging event against the threshold level set
+ on this appender and also against the filters specified on this
+ appender.
+ </para>
+ <para>
+ The implementation of this method is as follows:
+ </para>
+ <para>
+ <list type="bullet">
+ <item>
+ <description>
+ Checks that the severity of the <paramref name="loggingEvent"/>
+ is greater than or equal to the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> of this
+ appender.</description>
+ </item>
+ <item>
+ <description>
+ Checks that the <see cref="T:log4net.Filter.IFilter"/> chain accepts the
+ <paramref name="loggingEvent"/>.
+ </description>
+ </item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.AddFilter(log4net.Filter.IFilter)">
+ <summary>
+ Adds a filter to the end of the filter chain.
+ </summary>
+ <param name="filter">the filter to add to this appender</param>
+ <remarks>
+ <para>
+ The Filters are organized in a linked list.
+ </para>
+ <para>
+ Setting this property causes the new filter to be pushed onto the
+ back of the filter chain.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.ClearFilters">
+ <summary>
+ Clears the filter list for this appender.
+ </summary>
+ <remarks>
+ <para>
+ Clears the filter list for this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.IsAsSevereAsThreshold(log4net.Core.Level)">
+ <summary>
+ Checks if the message level is below this appender's threshold.
+ </summary>
+ <param name="level"><see cref="T:log4net.Core.Level"/> to test against.</param>
+ <remarks>
+ <para>
+ If there is no threshold set, then the return value is always <c>true</c>.
+ </para>
+ </remarks>
+ <returns>
+ <c>true</c> if the <paramref name="level"/> meets the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/>
+ requirements of this appender.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.OnClose">
+ <summary>
+ Is called when the appender is closed. Derived classes should override
+ this method if resources need to be released.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Subclasses of <see cref="T:log4net.Appender.AppenderSkeleton"/> should implement this method
+ to perform actual logging.
+ </summary>
+ <param name="loggingEvent">The event to append.</param>
+ <remarks>
+ <para>
+ A subclass must implement this method to perform
+ logging of the <paramref name="loggingEvent"/>.
+ </para>
+ <para>This method will be called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ if all the conditions listed for that method are met.
+ </para>
+ <para>
+ To restrict the logging of events in the appender
+ override the <see cref="M:log4net.Appender.AppenderSkeleton.PreAppendCheck"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Append a bulk array of logging events.
+ </summary>
+ <param name="loggingEvents">the array of logging events</param>
+ <remarks>
+ <para>
+ This base class implementation calls the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>
+ method for each element in the bulk array.
+ </para>
+ <para>
+ A sub class that can better process a bulk array of events should
+ override this method in addition to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.PreAppendCheck">
+ <summary>
+ Called before <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> as a precondition.
+ </summary>
+ <remarks>
+ <para>
+ This method is called by <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ before the call to the abstract <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ This method can be overridden in a subclass to extend the checks
+ made before the event is passed to the <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ A subclass should ensure that they delegate this call to
+ this base class if it is overridden.
+ </para>
+ </remarks>
+ <returns><c>true</c> if the call to <see cref="M:log4net.Appender.AppenderSkeleton.Append(log4net.Core.LoggingEvent)"/> should proceed.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+ </summary>
+ <param name="loggingEvent">The event to render.</param>
+ <returns>The event rendered as a string.</returns>
+ <remarks>
+ <para>
+ Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to
+ a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+ set to render the <paramref name="loggingEvent"/> to
+ a string.
+ </para>
+ <para>If there is exception data in the logging event and
+ the layout does not process the exception, this method
+ will append the exception text to the rendered string.
+ </para>
+ <para>
+ Where possible use the alternative version of this method
+ <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)"/>.
+ That method streams the rendering onto an existing Writer
+ which can give better performance if the caller already has
+ a <see cref="T:System.IO.TextWriter"/> open and ready for writing.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the <see cref="T:log4net.Core.LoggingEvent"/> to a string.
+ </summary>
+ <param name="loggingEvent">The event to render.</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Helper method to render a <see cref="T:log4net.Core.LoggingEvent"/> to
+ a string. This appender must have a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/>
+ set to render the <paramref name="loggingEvent"/> to
+ a string.
+ </para>
+ <para>If there is exception data in the logging event and
+ the layout does not process the exception, this method
+ will append the exception text to the rendered string.
+ </para>
+ <para>
+ Use this method in preference to <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/>
+ where possible. If, however, the caller needs to render the event
+ to a string then <see cref="M:log4net.Appender.AppenderSkeleton.RenderLoggingEvent(log4net.Core.LoggingEvent)"/> does
+ provide an efficient mechanism for doing so.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_layout">
+ <summary>
+ The layout of this appender.
+ </summary>
+ <remarks>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_name">
+ <summary>
+ The name of this appender.
+ </summary>
+ <remarks>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Name"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_threshold">
+ <summary>
+ The level threshold of this appender.
+ </summary>
+ <remarks>
+ <para>
+ There is no level threshold filtering by default.
+ </para>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_errorHandler">
+ <summary>
+ It is assumed and enforced that errorHandler is never null.
+ </summary>
+ <remarks>
+ <para>
+ It is assumed and enforced that errorHandler is never null.
+ </para>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_headFilter">
+ <summary>
+ The first filter in the filter chain.
+ </summary>
+ <remarks>
+ <para>
+ Set to <c>null</c> initially.
+ </para>
+ <para>
+ See <see cref="T:log4net.Filter.IFilter"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_tailFilter">
+ <summary>
+ The last filter in the filter chain.
+ </summary>
+ <remarks>
+ See <see cref="T:log4net.Filter.IFilter"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_closed">
+ <summary>
+ Flag indicating if this appender is closed.
+ </summary>
+ <remarks>
+ See <see cref="M:log4net.Appender.AppenderSkeleton.Close"/> for more information.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_recursiveGuard">
+ <summary>
+ The guard prevents an appender from repeatedly calling its own DoAppend method
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AppenderSkeleton.m_renderWriter">
+ <summary>
+ StringWriter used to render events
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Threshold">
+ <summary>
+ Gets or sets the threshold <see cref="T:log4net.Core.Level"/> of this appender.
+ </summary>
+ <value>
+ The threshold <see cref="T:log4net.Core.Level"/> of the appender.
+ </value>
+ <remarks>
+ <para>
+ All log events with lower level than the threshold level are ignored
+ by the appender.
+ </para>
+ <para>
+ In configuration files this option is specified by setting the
+ value of the <see cref="P:log4net.Appender.AppenderSkeleton.Threshold"/> option to a level
+ string, such as "DEBUG", "INFO" and so on.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.ErrorHandler">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.IErrorHandler"/> for this appender.
+ </summary>
+ <value>The <see cref="T:log4net.Core.IErrorHandler"/> of the appender</value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Appender.AppenderSkeleton"/> provides a default
+ implementation for the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.FilterHead">
+ <summary>
+ The filter chain.
+ </summary>
+ <value>The head of the filter chain filter chain.</value>
+ <remarks>
+ <para>
+ Returns the head Filter. The Filters are organized in a linked list
+ and so all Filters on this Appender are available through the result.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Layout">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Layout.ILayout"/> for this appender.
+ </summary>
+ <value>The layout of the appender.</value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/> for more information.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Appender.AppenderSkeleton.RequiresLayout"/>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.Name">
+ <summary>
+ Gets or sets the name of this appender.
+ </summary>
+ <value>The name of the appender.</value>
+ <remarks>
+ <para>
+ The name uniquely identifies the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AppenderSkeleton.RequiresLayout">
+ <summary>
+ Tests if this appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </summary>
+ <remarks>
+ <para>
+ In the rather exceptional case, where the appender
+ implementation admits a layout but can also work without it,
+ then the appender should return <c>true</c>.
+ </para>
+ <para>
+ This default implementation always returns <c>true</c>.
+ </para>
+ </remarks>
+ <returns>
+ <c>true</c> if the appender requires a layout object, otherwise <c>false</c>.
+ </returns>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE">
+ <summary>
+ The default buffer size.
+ </summary>
+ <remarks>
+ The default size of the cyclic buffer used to store events.
+ This is set to 512 by default.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Protected default constructor to allow subclassing.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.#ctor(System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> class.
+ </summary>
+ <param name="eventMustBeFixed">the events passed through this appender must be
+ fixed by the time that they arrive in the derived class' <c>SendBuffer</c> method.</param>
+ <remarks>
+ <para>
+ Protected constructor to allow subclassing.
+ </para>
+ <para>
+ The <paramref name="eventMustBeFixed"/> should be set if the subclass
+ expects the events delivered to be fixed even if the
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to zero, i.e. when no buffering occurs.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush">
+ <summary>
+ Flush the currently buffered events
+ </summary>
+ <remarks>
+ <para>
+ Flushes any events that have been buffered.
+ </para>
+ <para>
+ If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+ of the buffer will NOT be flushed to the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Flush(System.Boolean)">
+ <summary>
+ Flush the currently buffered events
+ </summary>
+ <param name="flushLossyBuffer">set to <c>true</c> to flush the buffer of lossy events</param>
+ <remarks>
+ <para>
+ Flushes events that have been buffered. If <paramref name="flushLossyBuffer"/> is
+ <c>false</c> then events will only be flushed if this buffer is non-lossy mode.
+ </para>
+ <para>
+ If the appender is buffering in <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> mode then the contents
+ of the buffer will only be flushed if <paramref name="flushLossyBuffer"/> is <c>true</c>.
+ In this case the contents of the buffer will be tested against the
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator"/> and if triggering will be output. All other buffered
+ events will be discarded.
+ </para>
+ <para>
+ If <paramref name="flushLossyBuffer"/> is <c>true</c> then the buffer will always
+ be emptied by calling this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.BufferingAppenderSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.OnClose">
+ <summary>
+ Close this appender instance.
+ </summary>
+ <remarks>
+ <para>
+ Close this appender instance. If this appender is marked
+ as not <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> then the remaining events in
+ the buffer must be sent when the appender is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Stores the <paramref name="loggingEvent"/> in the cyclic buffer.
+ </para>
+ <para>
+ The buffer will be sent (i.e. passed to the <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>
+ method) if one of the following conditions is met:
+ </para>
+ <list type="bullet">
+ <item>
+ <description>The cyclic buffer is full and this appender is
+ marked as not lossy (see <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>)</description>
+ </item>
+ <item>
+ <description>An <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> is set and
+ it is triggered for the <paramref name="loggingEvent"/>
+ specified.</description>
+ </item>
+ </list>
+ <para>
+ Before the event is stored in the buffer it is fixed
+ (see <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/>) to ensure that
+ any data referenced by the event will be valid when the buffer
+ is processed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendFromBuffer(log4net.Core.LoggingEvent,log4net.Util.CyclicBuffer)">
+ <summary>
+ Sends the contents of the buffer.
+ </summary>
+ <param name="firstLoggingEvent">The first logging event.</param>
+ <param name="buffer">The buffer containing the events that need to be send.</param>
+ <remarks>
+ <para>
+ The subclass must override <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the events.
+ </summary>
+ <param name="events">The events that need to be send.</param>
+ <remarks>
+ <para>
+ The subclass must override this method to process the buffered events.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_bufferSize">
+ <summary>
+ The size of the cyclic buffer used to hold the logging events.
+ </summary>
+ <remarks>
+ Set to <see cref="F:log4net.Appender.BufferingAppenderSkeleton.DEFAULT_BUFFER_SIZE"/> by default.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_cb">
+ <summary>
+ The cyclic buffer used to store the logging events.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_evaluator">
+ <summary>
+ The triggering event evaluator that causes the buffer to be sent immediately.
+ </summary>
+ <remarks>
+ The object that is used to determine if an event causes the entire
+ buffer to be sent immediately. This field can be <c>null</c>, which
+ indicates that event triggering is not to be done. The evaluator
+ can be set using the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> property. If this appender
+ has the <see cref="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy"/> (<see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> property) set to
+ <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be set.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossy">
+ <summary>
+ Indicates if the appender should overwrite events in the cyclic buffer
+ when it becomes full, or if the buffer should be flushed when the
+ buffer is full.
+ </summary>
+ <remarks>
+ If this field is set to <c>true</c> then an <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must
+ be set.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_lossyEvaluator">
+ <summary>
+ The triggering event evaluator filters discarded events.
+ </summary>
+ <remarks>
+ The object that is used to determine if an event that is discarded should
+ really be discarded or if it should be sent to the appenders.
+ This field can be <c>null</c>, which indicates that all discarded events will
+ be discarded.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_fixFlags">
+ <summary>
+ Value indicating which fields in the event should be fixed
+ </summary>
+ <remarks>
+ By default all fields are fixed
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingAppenderSkeleton.m_eventMustBeFixed">
+ <summary>
+ The events delivered to the subclass must be fixed.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Lossy">
+ <summary>
+ Gets or sets a value that indicates whether the appender is lossy.
+ </summary>
+ <value>
+ <c>true</c> if the appender is lossy, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ This appender uses a buffer to store logging events before
+ delivering them. A triggering event causes the whole buffer
+ to be send to the remote sink. If the buffer overruns before
+ a triggering event then logging events could be lost. Set
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> to <c>false</c> to prevent logging events
+ from being lost.
+ </para>
+ <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize">
+ <summary>
+ Gets or sets the size of the cyclic buffer used to hold the
+ logging events.
+ </summary>
+ <value>
+ The size of the cyclic buffer used to hold the logging events.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option takes a positive integer
+ representing the maximum number of logging events to collect in
+ a cyclic buffer. When the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is reached,
+ oldest events are deleted as new events are added to the
+ buffer. By default the size of the cyclic buffer is 512 events.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> is set to a value less than
+ or equal to 1 then no buffering will occur. The logging event
+ will be delivered synchronously (depending on the <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/>
+ and <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> properties). Otherwise the event will
+ be buffered.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the
+ buffer to be sent immediately.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> that causes the buffer to be
+ sent immediately.
+ </value>
+ <remarks>
+ <para>
+ The evaluator will be called for each event that is appended to this
+ appender. If the evaluator triggers then the current buffer will
+ immediately be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+ </para>
+ <para>If <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Lossy"/> is set to <c>true</c> then an
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.Evaluator"/> must be specified.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.LossyEvaluator">
+ <summary>
+ Gets or sets the value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+ </summary>
+ <value>
+ The value of the <see cref="T:log4net.Core.ITriggeringEventEvaluator"/> to use.
+ </value>
+ <remarks>
+ <para>
+ The evaluator will be called for each event that is discarded from this
+ appender. If the evaluator triggers then the current buffer will immediately
+ be sent (see <see cref="M:log4net.Appender.BufferingAppenderSkeleton.SendBuffer(log4net.Core.LoggingEvent[])"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.OnlyFixPartialEventData">
+ <summary>
+ Gets or sets a value indicating if only part of the logging event data
+ should be fixed.
+ </summary>
+ <value>
+ <c>true</c> if the appender should only fix part of the logging event
+ data, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Setting this property to <c>true</c> will cause only part of the
+ event data to be fixed and serialized. This will improve performance.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.BufferingAppenderSkeleton.Fix">
+ <summary>
+ Gets or sets a the fields that will be fixed in the event
+ </summary>
+ <value>
+ The event fields that will be fixed before the event is buffered
+ </value>
+ <remarks>
+ <para>
+ The logging event needs to have certain thread specific values
+ captured before it can be buffered. See <see cref="P:log4net.Core.LoggingEvent.Fix"/>
+ for details.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Core.LoggingEvent.Fix"/>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppender"/> class.
+ </summary>
+ <remarks>
+ Public default constructor to initialize a new instance of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.AdoNetAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.OnClose">
+ <summary>
+ Override the parent method to close the database
+ </summary>
+ <remarks>
+ <para>
+ Closes the database command and database connection.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Inserts the events into the database.
+ </summary>
+ <param name="events">The events to insert into the database.</param>
+ <remarks>
+ <para>
+ Insert all the events specified in the <paramref name="events"/>
+ array into the database.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.AddParameter(log4net.Appender.AdoNetAppenderParameter)">
+ <summary>
+ Adds a parameter to the command.
+ </summary>
+ <param name="parameter">The parameter to add to the command.</param>
+ <remarks>
+ <para>
+ Adds a parameter to the ordered list of command parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.SendBuffer(System.Data.IDbTransaction,log4net.Core.LoggingEvent[])">
+ <summary>
+ Writes the events to the database using the transaction specified.
+ </summary>
+ <param name="dbTran">The transaction that the events will be executed under.</param>
+ <param name="events">The array of events to insert into the database.</param>
+ <remarks>
+ <para>
+ The transaction argument can be <c>null</c> if the appender has been
+ configured not to use transactions. See <see cref="P:log4net.Appender.AdoNetAppender.UseTransactions"/>
+ property for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.GetLogStatement(log4net.Core.LoggingEvent)">
+ <summary>
+ Formats the log message into database statement text.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ This method can be overridden by subclasses to provide
+ more control over the format of the database statement.
+ </remarks>
+ <returns>
+ Text that can be passed to a <see cref="T:System.Data.IDbCommand"/>.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseConnection">
+ <summary>
+ Connects to the database.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.ResolveConnectionType">
+ <summary>
+ Retrieves the class type of the ADO.NET provider.
+ </summary>
+ <remarks>
+ <para>
+ Gets the Type of the ADO.NET provider to use to connect to the
+ database. This method resolves the type specified in the
+ <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> property.
+ </para>
+ <para>
+ Subclasses can override this method to return a different type
+ if necessary.
+ </para>
+ </remarks>
+ <returns>The <see cref="T:System.Type"/> of the ADO.NET provider</returns>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppender.InitializeDatabaseCommand">
+ <summary>
+ Prepares the database command and initialize the parameters.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_usePreparedCommand">
+ <summary>
+ Flag to indicate if we are using a command object
+ </summary>
+ <remarks>
+ <para>
+ Set to <c>true</c> when the appender is to use a prepared
+ statement or stored procedure to insert into the database.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_parameters">
+ <summary>
+ The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+ </summary>
+ <remarks>
+ <para>
+ The list of <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_dbConnection">
+ <summary>
+ The <see cref="T:System.Data.IDbConnection"/> that will be used
+ to insert logging events into a database.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_dbCommand">
+ <summary>
+ The database command.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_connectionString">
+ <summary>
+ Database connection string.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_connectionType">
+ <summary>
+ String type name of the <see cref="T:System.Data.IDbConnection"/> type name.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_commandText">
+ <summary>
+ The text of the command.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_commandType">
+ <summary>
+ The command type.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_useTransactions">
+ <summary>
+ Indicates whether to use transactions when writing to the database.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppender.m_reconnectOnError">
+ <summary>
+ Indicates whether to use transactions when writing to the database.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ConnectionString">
+ <summary>
+ Gets or sets the database connection string that is used to connect to
+ the database.
+ </summary>
+ <value>
+ The database connection string used to connect to the database.
+ </value>
+ <remarks>
+ <para>
+ The connections string is specific to the connection type.
+ See <see cref="P:log4net.Appender.AdoNetAppender.ConnectionType"/> for more information.
+ </para>
+ </remarks>
+ <example>Connection string for MS Access via ODBC:
+ <code>"DSN=MS Access Database;UID=admin;PWD=;SystemDB=C:\data\System.mdw;SafeTransactions = 0;FIL=MS Access;DriverID = 25;DBQ=C:\data\train33.mdb"</code>
+ </example>
+ <example>Another connection string for MS Access via ODBC:
+ <code>"Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Work\cvs_root\log4net-1.2\access.mdb;UID=;PWD=;"</code>
+ </example>
+ <example>Connection string for MS Access via OLE DB:
+ <code>"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Work\cvs_root\log4net-1.2\access.mdb;User Id=;Password=;"</code>
+ </example>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ConnectionType">
+ <summary>
+ Gets or sets the type name of the <see cref="T:System.Data.IDbConnection"/> connection
+ that should be created.
+ </summary>
+ <value>
+ The type name of the <see cref="T:System.Data.IDbConnection"/> connection.
+ </value>
+ <remarks>
+ <para>
+ The type name of the ADO.NET provider to use.
+ </para>
+ <para>
+ The default is to use the OLE DB provider.
+ </para>
+ </remarks>
+ <example>Use the OLE DB Provider. This is the default value.
+ <code>System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ </example>
+ <example>Use the MS SQL Server Provider.
+ <code>System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ </example>
+ <example>Use the ODBC Provider.
+ <code>Microsoft.Data.Odbc.OdbcConnection,Microsoft.Data.Odbc,version=1.0.3300.0,publicKeyToken=b77a5c561934e089,culture=neutral</code>
+ This is an optional package that you can download from
+ <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a>
+ search for <b>ODBC .NET Data Provider</b>.
+ </example>
+ <example>Use the Oracle Provider.
+ <code>System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</code>
+ This is an optional package that you can download from
+ <a href="http://msdn.microsoft.com/downloads">http://msdn.microsoft.com/downloads</a>
+ search for <b>.NET Managed Provider for Oracle</b>.
+ </example>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.CommandText">
+ <summary>
+ Gets or sets the command text that is used to insert logging events
+ into the database.
+ </summary>
+ <value>
+ The command text used to insert logging events into the database.
+ </value>
+ <remarks>
+ <para>
+ Either the text of the prepared statement or the
+ name of the stored procedure to execute to write into
+ the database.
+ </para>
+ <para>
+ The <see cref="P:log4net.Appender.AdoNetAppender.CommandType"/> property determines if
+ this text is a prepared statement or a stored procedure.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.CommandType">
+ <summary>
+ Gets or sets the command type to execute.
+ </summary>
+ <value>
+ The command type to execute.
+ </value>
+ <remarks>
+ <para>
+ This value may be either <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>) to specify
+ that the <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> is a prepared statement to execute,
+ or <see cref="F:System.Data.CommandType.StoredProcedure"/> (<c>System.Data.CommandType.StoredProcedure</c>) to specify that the
+ <see cref="P:log4net.Appender.AdoNetAppender.CommandText"/> property is the name of a stored procedure
+ to execute.
+ </para>
+ <para>
+ The default value is <see cref="F:System.Data.CommandType.Text"/> (<c>System.Data.CommandType.Text</c>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.UseTransactions">
+ <summary>
+ Should transactions be used to insert logging events in the database.
+ </summary>
+ <value>
+ <c>true</c> if transactions should be used to insert logging events in
+ the database, otherwise <c>false</c>. The default value is <c>true</c>.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets a value that indicates whether transactions should be used
+ to insert logging events in the database.
+ </para>
+ <para>
+ When set a single transaction will be used to insert the buffered events
+ into the database. Otherwise each event will be inserted without using
+ an explicit transaction.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> used to call the NetSend method.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.AdoNetAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.ReconnectOnError">
+ <summary>
+ Should this appender try to reconnect to the database on error.
+ </summary>
+ <value>
+ <c>true</c> if the appender should try to reconnect to the database after an
+ error has occurred, otherwise <c>false</c>. The default value is <c>false</c>,
+ i.e. not to try to reconnect.
+ </value>
+ <remarks>
+ <para>
+ The default behaviour is for the appender not to try to reconnect to the
+ database if an error occurs. Subsequent logging events are discarded.
+ </para>
+ <para>
+ To force the appender to attempt to reconnect to the database set this
+ property to <c>true</c>.
+ </para>
+ <note>
+ When the appender attempts to connect to the database there may be a
+ delay of up to the connection timeout specified in the connection string.
+ This delay will block the calling application's thread.
+ Until the connection can be reestablished this potential delay may occur multiple times.
+ </note>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppender.Connection">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.Data.IDbConnection"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.Data.IDbConnection"/>.
+ </value>
+ <remarks>
+ <see cref="T:log4net.Appender.AdoNetAppender"/> creates a <see cref="T:System.Data.IDbConnection"/> to insert
+ logging events into a database. Classes deriving from <see cref="T:log4net.Appender.AdoNetAppender"/>
+ can use this property to get or set this <see cref="T:System.Data.IDbConnection"/>. Use the
+ underlying <see cref="T:System.Data.IDbConnection"/> returned from <see cref="P:log4net.Appender.AdoNetAppender.Connection"/> if
+ you require access beyond that which <see cref="T:log4net.Appender.AdoNetAppender"/> provides.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AdoNetAppenderParameter">
+ <summary>
+ Parameter type used by the <see cref="T:log4net.Appender.AdoNetAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ This class provides the basic database parameter properties
+ as defined by the <see cref="T:System.Data.IDbDataParameter"/> interface.
+ </para>
+ <para>This type can be subclassed to provide database specific
+ functionality. The two methods that are called externally are
+ <see cref="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)"/> and <see cref="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AdoNetAppenderParameter"/> class.
+ </summary>
+ <remarks>
+ Default constructor for the AdoNetAppenderParameter class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.Prepare(System.Data.IDbCommand)">
+ <summary>
+ Prepare the specified database command object.
+ </summary>
+ <param name="command">The command to prepare.</param>
+ <remarks>
+ <para>
+ Prepares the database command object by adding
+ this parameter to its collection of parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AdoNetAppenderParameter.FormatValue(System.Data.IDbCommand,log4net.Core.LoggingEvent)">
+ <summary>
+ Renders the logging event and set the parameter value in the command.
+ </summary>
+ <param name="command">The command containing the parameter.</param>
+ <param name="loggingEvent">The event to be rendered.</param>
+ <remarks>
+ <para>
+ Renders the logging event using this parameters layout
+ object. Sets the value of the parameter on the command object.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_parameterName">
+ <summary>
+ The name of this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_dbType">
+ <summary>
+ The database type for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_inferType">
+ <summary>
+ Flag to infer type rather than use the DbType
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_precision">
+ <summary>
+ The precision for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_scale">
+ <summary>
+ The scale for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_size">
+ <summary>
+ The size for this parameter.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AdoNetAppenderParameter.m_layout">
+ <summary>
+ The <see cref="T:log4net.Layout.IRawLayout"/> to use to render the
+ logging event into an object for this parameter.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.ParameterName">
+ <summary>
+ Gets or sets the name of this parameter.
+ </summary>
+ <value>
+ The name of this parameter.
+ </value>
+ <remarks>
+ <para>
+ The name of this parameter. The parameter name
+ must match up to a named parameter to the SQL stored procedure
+ or prepared statement.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.DbType">
+ <summary>
+ Gets or sets the database type for this parameter.
+ </summary>
+ <value>
+ The database type for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The database type for this parameter. This property should
+ be set to the database type from the <see cref="P:log4net.Appender.AdoNetAppenderParameter.DbType"/>
+ enumeration. See <see cref="P:System.Data.IDataParameter.DbType"/>.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the type from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDataParameter.DbType"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Precision">
+ <summary>
+ Gets or sets the precision for this parameter.
+ </summary>
+ <value>
+ The precision for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The maximum number of digits used to represent the Value.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the precision from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Precision"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Scale">
+ <summary>
+ Gets or sets the scale for this parameter.
+ </summary>
+ <value>
+ The scale for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The number of decimal places to which Value is resolved.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the scale from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Scale"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Size">
+ <summary>
+ Gets or sets the size for this parameter.
+ </summary>
+ <value>
+ The size for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The maximum size, in bytes, of the data within the column.
+ </para>
+ <para>
+ This property is optional. If not specified the ADO.NET provider
+ will attempt to infer the size from the value.
+ </para>
+ </remarks>
+ <seealso cref="P:System.Data.IDbDataParameter.Size"/>
+ </member>
+ <member name="P:log4net.Appender.AdoNetAppenderParameter.Layout">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Layout.IRawLayout"/> to use to
+ render the logging event into an object for this
+ parameter.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Layout.IRawLayout"/> used to render the
+ logging event into an object for this parameter.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Layout.IRawLayout"/> that renders the value for this
+ parameter.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.RawLayoutConverter"/> can be used to adapt
+ any <see cref="T:log4net.Layout.ILayout"/> into a <see cref="T:log4net.Layout.IRawLayout"/>
+ for use in the property.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender">
+ <summary>
+ Appends logging events to the terminal using ANSI color escape sequences.
+ </summary>
+ <remarks>
+ <para>
+ AnsiColorTerminalAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user. It also allows the color of a specific level of message to be set.
+ </para>
+ <note>
+ This appender expects the terminal to understand the VT100 control set
+ in order to interpret the color codes. If the terminal or console does not
+ understand the control codes the behavior is not defined.
+ </note>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes each message to the <c>System.Console.Out</c> or
+ <c>System.Console.Error</c> that is set at the time the event is appended.
+ Therefore it is possible to programmatically redirect the output of this appender
+ (for example NUnit does this to capture program output). While this is the desired
+ behavior of this appender it may have security implications in your application.
+ </para>
+ <para>
+ When configuring the ANSI colored terminal appender, a mapping should be
+ specified to map a logging level to a color. For example:
+ </para>
+ <code lang="XML" escaped="true">
+ <mapping>
+ <level value="ERROR"/>
+ <foreColor value="White"/>
+ <backColor value="Red"/>
+ <attributes value="Bright,Underscore"/>
+ </mapping>
+ <mapping>
+ <level value="DEBUG"/>
+ <backColor value="Green"/>
+ </mapping>
+ </code>
+ <para>
+ The Level is the standard log4net logging level and ForeColor and BackColor can be any
+ of the following values:
+ <list type="bullet">
+ <item><term>Blue</term><description></description></item>
+ <item><term>Green</term><description></description></item>
+ <item><term>Red</term><description></description></item>
+ <item><term>White</term><description></description></item>
+ <item><term>Yellow</term><description></description></item>
+ <item><term>Purple</term><description></description></item>
+ <item><term>Cyan</term><description></description></item>
+ </list>
+ These color values cannot be combined together to make new colors.
+ </para>
+ <para>
+ The attributes can be any combination of the following:
+ <list type="bullet">
+ <item><term>Bright</term><description>foreground is brighter</description></item>
+ <item><term>Dim</term><description>foreground is dimmer</description></item>
+ <item><term>Underscore</term><description>message is underlined</description></item>
+ <item><term>Blink</term><description>foreground is blinking (does not work on all terminals)</description></item>
+ <item><term>Reverse</term><description>foreground and background are reversed</description></item>
+ <item><term>Hidden</term><description>output is hidden</description></item>
+ <item><term>Strikethrough</term><description>message has a line through it</description></item>
+ </list>
+ While any of these attributes may be combined together not all combinations
+ work well together, for example setting both <i>Bright</i> and <i>Dim</i> attributes makes
+ no sense.
+ </para>
+ </remarks>
+ <author>Patrick Wagstrom</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.AnsiColorTerminalAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.PostEventCodes">
+ <summary>
+ Ansi code to reset terminal
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.AnsiColorTerminalAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.AddMapping(log4net.Appender.AnsiColorTerminalAppender.LevelColors)">
+ <summary>
+ Add a mapping of level to color
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors"/> mapping to this appender.
+ Each mapping defines the foreground and background colours
+ for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to color mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_writeToErrorStream">
+ <summary>
+ Flag to write output to the error stream rather than the standard output stream
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to color value
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes">
+ <summary>
+ The enum of possible display attributes
+ </summary>
+ <remarks>
+ <para>
+ The following flags can be combined together to
+ form the ANSI color attributes.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Bright">
+ <summary>
+ text is bright
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Dim">
+ <summary>
+ text is dim
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Underscore">
+ <summary>
+ text is underlined
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Blink">
+ <summary>
+ text is blinking
+ </summary>
+ <remarks>
+ Not all terminals support this attribute
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Reverse">
+ <summary>
+ text and background colors are reversed
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Hidden">
+ <summary>
+ text is hidden
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiAttributes.Strikethrough">
+ <summary>
+ text is displayed with a strikethrough
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.AnsiColor">
+ <summary>
+ The enum of possible foreground or background color values for
+ use with the color mapping method
+ </summary>
+ <remarks>
+ <para>
+ The output can be in one for the following ANSI colors.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.AnsiColorTerminalAppender"/>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Black">
+ <summary>
+ color is black
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Red">
+ <summary>
+ color is red
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Green">
+ <summary>
+ color is green
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Yellow">
+ <summary>
+ color is yellow
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Blue">
+ <summary>
+ color is blue
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Magenta">
+ <summary>
+ color is magenta
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.Cyan">
+ <summary>
+ color is cyan
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.AnsiColorTerminalAppender.AnsiColor.White">
+ <summary>
+ color is white
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AnsiColorTerminalAppender.LevelColors">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and the color it should be displayed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LevelMappingEntry">
+ <summary>
+ An entry in the <see cref="T:log4net.Util.LevelMapping"/>
+ </summary>
+ <remarks>
+ <para>
+ This is an abstract base class for types that are stored in the
+ <see cref="T:log4net.Util.LevelMapping"/> object.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LevelMappingEntry.#ctor">
+ <summary>
+ Default protected constructor
+ </summary>
+ <remarks>
+ <para>
+ Default protected constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMappingEntry.ActivateOptions">
+ <summary>
+ Initialize any options defined on this entry
+ </summary>
+ <remarks>
+ <para>
+ Should be overridden by any classes that need to initialise based on their options
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LevelMappingEntry.Level">
+ <summary>
+ The level that is the key for this mapping
+ </summary>
+ <value>
+ The <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this mapping
+ </value>
+ <remarks>
+ <para>
+ Get or set the <see cref="P:log4net.Util.LevelMappingEntry.Level"/> that is the key for this
+ mapping subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ActivateOptions">
+ <summary>
+ Initialize the options for the object
+ </summary>
+ <remarks>
+ <para>
+ Combine the <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> together
+ and append the attributes.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor">
+ <summary>
+ The mapped foreground color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped foreground color for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor">
+ <summary>
+ The mapped background color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped background color for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes">
+ <summary>
+ The color attributes for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The color attributes for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.CombinedColor">
+ <summary>
+ The combined <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.ForeColor"/>, <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.BackColor"/> and
+ <see cref="P:log4net.Appender.AnsiColorTerminalAppender.LevelColors.Attributes"/> suitable for setting the ansi terminal color.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Appender.IAppender"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ReadOnly(log4net.Appender.AppenderCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>AppenderCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ An <c>AppenderCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="F:log4net.Appender.AppenderCollection.EmptyCollection">
+ <summary>
+ An empty readonly static AppenderCollection
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>AppenderCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <c>AppenderCollection</c>.
+ </summary>
+ <param name="c">The <c>AppenderCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.IAppender[])">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Appender.IAppender"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>AppenderCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Appender.IAppender"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.#ctor(log4net.Appender.AppenderCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[])">
+ <summary>
+ Copies the entire <c>AppenderCollection</c> to a one-dimensional
+ <see cref="T:log4net.Appender.IAppender"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.CopyTo(log4net.Appender.IAppender[],System.Int32)">
+ <summary>
+ Copies the entire <c>AppenderCollection</c> to a one-dimensional
+ <see cref="T:log4net.Appender.IAppender"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Appender.IAppender"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Add(log4net.Appender.IAppender)">
+ <summary>
+ Adds a <see cref="T:log4net.Appender.IAppender"/> to the end of the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Clear">
+ <summary>
+ Removes all elements from the <c>AppenderCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Appender.AppenderCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Contains(log4net.Appender.IAppender)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Appender.IAppender"/> is in the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>AppenderCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IndexOf(log4net.Appender.IAppender)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Appender.IAppender"/>
+ in the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to locate in the <c>AppenderCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>AppenderCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Insert(System.Int32,log4net.Appender.IAppender)">
+ <summary>
+ Inserts an element into the <c>AppenderCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Remove(log4net.Appender.IAppender)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Appender.IAppender"/> from the <c>AppenderCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Appender.IAppender"/> to remove from the <c>AppenderCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Appender.IAppender"/> was not found in the <c>AppenderCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>AppenderCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>AppenderCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Appender.AppenderCollection.Enumerator"/> for the entire <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.AppenderCollection)">
+ <summary>
+ Adds the elements of another <c>AppenderCollection</c> to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="x">The <c>AppenderCollection</c> whose elements should be added to the end of the current <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(log4net.Appender.IAppender[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> array to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Appender.IAppender"/> array whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Appender.IAppender"/> collection to the current <c>AppenderCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Appender.IAppender"/> collection whose elements should be added to the end of the <c>AppenderCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Appender.AppenderCollection.Count"/> of the <c>AppenderCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ToArray">
+ <summary>
+ Return the collection elements as an array
+ </summary>
+ <returns>the array</returns>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>AppenderCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <returns>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</returns>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Appender.IAppender"/> at the specified index.
+ </summary>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Appender.AppenderCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value>true if the collection is read-only; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>AppenderCollection</c> can contain.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.IAppenderCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ <exclude/>
+ </member>
+ <member name="F:log4net.Appender.AppenderCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Appender.AppenderCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.#ctor(log4net.Appender.AppenderCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Appender.AppenderCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.AppenderCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.AppenderCollection.ReadOnlyAppenderCollection">
+ <exclude/>
+ </member>
+ <member name="T:log4net.Appender.AspNetTraceAppender">
+ <summary>
+ <para>
+ Appends log events to the ASP.NET <see cref="T:System.Web.TraceContext"/> system.
+ </para>
+ </summary>
+ <remarks>
+ <para>
+ Diagnostic information and tracing messages that you specify are appended to the output
+ of the page that is sent to the requesting browser. Optionally, you can view this information
+ from a separate trace viewer (Trace.axd) that displays trace information for every page in a
+ given application.
+ </para>
+ <para>
+ Trace statements are processed and displayed only when tracing is enabled. You can control
+ whether tracing is displayed to a page, to the trace viewer, or both.
+ </para>
+ <para>
+ The logging event is passed to the <see cref="M:System.Web.TraceContext.Write(System.String)"/> or
+ <see cref="M:System.Web.TraceContext.Warn(System.String)"/> method depending on the level of the logging event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.AspNetTraceAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.AspNetTraceAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.AspNetTraceAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write the logging event to the ASP.NET trace
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Write the logging event to the ASP.NET trace
+ <c>HttpContext.Current.Trace</c>
+ (<see cref="T:System.Web.TraceContext"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.AspNetTraceAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.BufferingForwardingAppender">
+ <summary>
+ Buffers events and then forwards them to attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ The events are buffered in this appender until conditions are
+ met to allow the appender to deliver the events to the attached
+ appenders. See <see cref="T:log4net.Appender.BufferingAppenderSkeleton"/> for the
+ conditions that cause the buffer to be sent.
+ </para>
+ <para>The forwarding appender can be used to specify different
+ thresholds and filters for the same appender at different locations
+ within the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Core.IAppenderAttachable">
+ <summary>
+ Interface for attaching appenders to objects.
+ </summary>
+ <remarks>
+ <para>
+ Interface for attaching, removing and retrieving appenders.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Attaches an appender.
+ </summary>
+ <param name="appender">The appender to add.</param>
+ <remarks>
+ <para>
+ Add the specified appender. The implementation may
+ choose to allow or deny duplicate appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.GetAppender(System.String)">
+ <summary>
+ Gets an attached appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to get.</param>
+ <returns>
+ The appender with the name specified, or <c>null</c> if no appender with the
+ specified name is found.
+ </returns>
+ <remarks>
+ <para>
+ Returns an attached appender with the <paramref name="name"/> specified.
+ If no appender with the specified name is found <c>null</c> will be
+ returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAllAppenders">
+ <summary>
+ Removes all attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ Removes and closes all attached appenders
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of attached appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IAppenderAttachable.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.IAppenderAttachable.Appenders">
+ <summary>
+ Gets all attached appenders.
+ </summary>
+ <value>
+ A collection of attached appenders.
+ </value>
+ <remarks>
+ <para>
+ Gets a collection of attached appenders.
+ If there are no attached appenders the
+ implementation should return an empty
+ collection rather than <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.BufferingForwardingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.OnClose">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Send the events.
+ </summary>
+ <param name="events">The events that need to be send.</param>
+ <remarks>
+ <para>
+ Forwards the events to the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Adds an <see cref="T:log4net.Appender.IAppender"/> to the list of appenders of this
+ instance.
+ </summary>
+ <param name="newAppender">The <see cref="T:log4net.Appender.IAppender"/> to add to this appender.</param>
+ <remarks>
+ <para>
+ If the specified <see cref="T:log4net.Appender.IAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.GetAppender(System.String)">
+ <summary>
+ Looks for the appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to lookup.</param>
+ <returns>
+ The appender with the specified name, or <c>null</c>.
+ </returns>
+ <remarks>
+ <para>
+ Get the named appender attached to this buffering appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAllAppenders">
+ <summary>
+ Removes all previously added appenders from this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.BufferingForwardingAppender.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.BufferingForwardingAppender.m_appenderAttachedImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.BufferingForwardingAppender.Appenders">
+ <summary>
+ Gets the appenders contained in this appender as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ If no appenders can be found, then an <see cref="T:log4net.Util.EmptyCollection"/>
+ is returned.
+ </remarks>
+ <returns>
+ A collection of the appenders in this appender.
+ </returns>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender">
+ <summary>
+ Appends logging events to the console.
+ </summary>
+ <remarks>
+ <para>
+ ColoredConsoleAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user. It also allows the color of a specific type of message to be set.
+ </para>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes directly to the application's attached console
+ not to the <c>System.Console.Out</c> or <c>System.Console.Error</c> <c>TextWriter</c>.
+ The <c>System.Console.Out</c> and <c>System.Console.Error</c> streams can be
+ programmatically redirected (for example NUnit does this to capture program output).
+ This appender will ignore these redirections because it needs to use Win32
+ API calls to colorize the output. To respect these redirections the <see cref="T:log4net.Appender.ConsoleAppender"/>
+ must be used.
+ </para>
+ <para>
+ When configuring the colored console appender, mapping should be
+ specified to map a logging level to a color. For example:
+ </para>
+ <code lang="XML" escaped="true">
+ <mapping>
+ <level value="ERROR"/>
+ <foreColor value="White"/>
+ <backColor value="Red, HighIntensity"/>
+ </mapping>
+ <mapping>
+ <level value="DEBUG"/>
+ <backColor value="Green"/>
+ </mapping>
+ </code>
+ <para>
+ The Level is the standard log4net logging level and ForeColor and BackColor can be any
+ combination of the following values:
+ <list type="bullet">
+ <item><term>Blue</term><description></description></item>
+ <item><term>Green</term><description></description></item>
+ <item><term>Red</term><description></description></item>
+ <item><term>White</term><description></description></item>
+ <item><term>Yellow</term><description></description></item>
+ <item><term>Purple</term><description></description></item>
+ <item><term>Cyan</term><description></description></item>
+ <item><term>HighIntensity</term><description></description></item>
+ </list>
+ </para>
+ </remarks>
+ <author>Rick Hobbs</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ColoredConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.#ctor(log4net.Layout.ILayout,System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ColoredConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <param name="writeToErrorStream">flag set to <c>true</c> to write to the console error stream</param>
+ <remarks>
+ When <paramref name="writeToErrorStream"/> is set to <c>true</c>, output is written to
+ the standard error output stream. Otherwise, output is written to the standard
+ output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.AddMapping(log4net.Appender.ColoredConsoleAppender.LevelColors)">
+ <summary>
+ Add a mapping of level to color - done by the config file
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.ColoredConsoleAppender.LevelColors"/> mapping to this appender.
+ Each mapping defines the foreground and background colors
+ for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to color mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_writeToErrorStream">
+ <summary>
+ Flag to write output to the error stream rather than the standard output stream
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to color value
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.m_consoleOutputWriter">
+ <summary>
+ The console output stream writer to write to
+ </summary>
+ <remarks>
+ <para>
+ This writer is not thread safe.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender.Colors">
+ <summary>
+ The enum of possible color values for use with the color mapping method
+ </summary>
+ <remarks>
+ <para>
+ The following flags can be combined together to
+ form the colors.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.ColoredConsoleAppender"/>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Blue">
+ <summary>
+ color is blue
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Green">
+ <summary>
+ color is green
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Red">
+ <summary>
+ color is red
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.White">
+ <summary>
+ color is white
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Yellow">
+ <summary>
+ color is yellow
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Purple">
+ <summary>
+ color is purple
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.Cyan">
+ <summary>
+ color is cyan
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.ColoredConsoleAppender.Colors.HighIntensity">
+ <summary>
+ color is intensified
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.ColoredConsoleAppender.LevelColors">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and the color it should be displayed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ColoredConsoleAppender.LevelColors.ActivateOptions">
+ <summary>
+ Initialize the options for the object
+ </summary>
+ <remarks>
+ <para>
+ Combine the <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor"/> together.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor">
+ <summary>
+ The mapped foreground color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped foreground color for the specified level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor">
+ <summary>
+ The mapped background color for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped background color for the specified level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ColoredConsoleAppender.LevelColors.CombinedColor">
+ <summary>
+ The combined <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.ForeColor"/> and <see cref="P:log4net.Appender.ColoredConsoleAppender.LevelColors.BackColor"/> suitable for
+ setting the console color.
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.ConsoleAppender">
+ <summary>
+ Appends logging events to the console.
+ </summary>
+ <remarks>
+ <para>
+ ConsoleAppender appends log events to the standard output stream
+ or the error output stream using a layout specified by the
+ user.
+ </para>
+ <para>
+ By default, all output is written to the console's standard output stream.
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> property can be set to direct the output to the
+ error stream.
+ </para>
+ <para>
+ NOTE: This appender writes each message to the <c>System.Console.Out</c> or
+ <c>System.Console.Error</c> that is set at the time the event is appended.
+ Therefore it is possible to programmatically redirect the output of this appender
+ (for example NUnit does this to capture program output). While this is the desired
+ behavior of this appender it may have security implications in your application.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Appender.ConsoleAppender.ConsoleOut">
+ <summary>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ConsoleAppender.ConsoleError">
+ <summary>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.ConsoleAppender.Target"/> to use when writing to the Console
+ standard error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class.
+ </summary>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <remarks>
+ The instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class is set up to write
+ to the standard output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.#ctor(log4net.Layout.ILayout,System.Boolean)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ConsoleAppender"/> class
+ with the specified layout.
+ </summary>
+ <param name="layout">the layout to use for this appender</param>
+ <param name="writeToErrorStream">flag set to <c>true</c> to write to the console error stream</param>
+ <remarks>
+ When <paramref name="writeToErrorStream"/> is set to <c>true</c>, output is written to
+ the standard error output stream. Otherwise, output is written to the standard
+ output stream.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ConsoleAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to the console.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ConsoleAppender.Target">
+ <summary>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </summary>
+ <value>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </value>
+ <remarks>
+ <para>
+ Target is the value of the console output stream.
+ This is either <c>"Console.Out"</c> or <c>"Console.Error"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.ConsoleAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.DebugAppender">
+ <summary>
+ Appends log events to the <see cref="T:System.Diagnostics.Debug"/> system.
+ </summary>
+ <remarks>
+ <para>
+ The application configuration file can be used to control what listeners
+ are actually used. See the MSDN documentation for the
+ <see cref="T:System.Diagnostics.Debug"/> class for details on configuring the
+ debug system.
+ </para>
+ <para>
+ Events are written using the <see cref="M:System.Diagnostics.Debug.Write(System.String,System.String)"/>
+ method. The event's logger name is passed as the value for the category name to the Write method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.DebugAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.DebugAppender"/>
+ with a specified layout.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.DebugAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Debug"/> system.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Debug"/> system.
+ If <see cref="P:log4net.Appender.DebugAppender.ImmediateFlush"/> is <c>true</c> then the <see cref="M:System.Diagnostics.Debug.Flush"/>
+ is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.DebugAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying writer or output stream
+ will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.DebugAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logs events are not actually written to persistent media if and
+ when the application crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.DebugAppender.ImmediateFlush">
+ <summary>
+ Gets or sets a value that indicates whether the appender will
+ flush at the end of each write.
+ </summary>
+ <remarks>
+ <para>The default behavior is to flush at the end of each
+ write. If the option is set to<c>false</c>, then the underlying
+ stream can defer writing to physical medium to a later time.
+ </para>
+ <para>
+ Avoiding the flush operation at the end of each append results
+ in a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.DebugAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.EventLogAppender">
+ <summary>
+ Writes events to the system event log.
+ </summary>
+ <remarks>
+ <para>
+ The <c>EventID</c> of the event log entry can be
+ set using the <c>EventLogEventID</c> property (<see cref="P:log4net.Core.LoggingEvent.Properties"/>)
+ on the <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ <para>
+ There is a limit of 32K characters for an event log message
+ </para>
+ <para>
+ When configuring the EventLogAppender a mapping can be
+ specified to map a logging level to an event log entry type. For example:
+ </para>
+ <code lang="XML">
+ &lt;mapping&gt;
+ &lt;level value="ERROR" /&gt;
+ &lt;eventLogEntryType value="Error" /&gt;
+ &lt;/mapping&gt;
+ &lt;mapping&gt;
+ &lt;level value="DEBUG" /&gt;
+ &lt;eventLogEntryType value="Information" /&gt;
+ &lt;/mapping&gt;
+ </code>
+ <para>
+ The Level is the standard log4net logging level and eventLogEntryType can be any value
+ from the <see cref="T:System.Diagnostics.EventLogEntryType"/> enum, i.e.:
+ <list type="bullet">
+ <item><term>Error</term><description>an error event</description></item>
+ <item><term>Warning</term><description>a warning event</description></item>
+ <item><term>Information</term><description>an informational event</description></item>
+ </list>
+ </para>
+ </remarks>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Thomas Voss</author>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.EventLogAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.EventLogAppender"/> class
+ with the specified <see cref="T:log4net.Layout.ILayout"/>.
+ </summary>
+ <param name="layout">The <see cref="T:log4net.Layout.ILayout"/> to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.AddMapping(log4net.Appender.EventLogAppender.Level2EventLogEntryType)">
+ <summary>
+ Add a mapping of level to <see cref="T:System.Diagnostics.EventLogEntryType"/> - done by the config file
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.EventLogAppender.Level2EventLogEntryType"/> mapping to this appender.
+ Each mapping defines the event log entry type for a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.EventLogAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.CreateEventSource(System.String,System.String,System.String)">
+ <summary>
+ Create an event log source
+ </summary>
+ <remarks>
+ Uses different API calls under NET_2_0
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>Writes the event to the system event log using the
+ <see cref="P:log4net.Appender.EventLogAppender.ApplicationName"/>.</para>
+
+ <para>If the event has an <c>EventID</c> property (see <see cref="P:log4net.Core.LoggingEvent.Properties"/>)
+ set then this integer will be used as the event log event id.</para>
+
+ <para>
+ There is a limit of 32K characters for an event log message
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.EventLogAppender.GetEntryType(log4net.Core.Level)">
+ <summary>
+ Get the equivalent <see cref="T:System.Diagnostics.EventLogEntryType"/> for a <see cref="T:log4net.Core.Level"/> <paramref name="p"/>
+ </summary>
+ <param name="level">the Level to convert to an EventLogEntryType</param>
+ <returns>The equivalent <see cref="T:System.Diagnostics.EventLogEntryType"/> for a <see cref="T:log4net.Core.Level"/> <paramref name="p"/></returns>
+ <remarks>
+ Because there are fewer applicable <see cref="T:System.Diagnostics.EventLogEntryType"/>
+ values to use in logging levels than there are in the
+ <see cref="T:log4net.Core.Level"/> this is a one way mapping. There is
+ a loss of information during the conversion.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_logName">
+ <summary>
+ The log name is the section in the event logs where the messages
+ are stored.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_applicationName">
+ <summary>
+ Name of the application to use when logging. This appears in the
+ application column of the event log named by <see cref="F:log4net.Appender.EventLogAppender.m_logName"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_machineName">
+ <summary>
+ The name of the machine which holds the event log. This is
+ currently only allowed to be '.' i.e. the current machine.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to EventLogEntryType
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.EventLogAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.LogName">
+ <summary>
+ The name of the log where messages will be stored.
+ </summary>
+ <value>
+ The string name of the log where messages will be stored.
+ </value>
+ <remarks>
+ <para>This is the name of the log as it appears in the Event Viewer
+ tree. The default value is to log into the <c>Application</c>
+ log, this is where most applications write their events. However
+ if you need a separate log for your application (or applications)
+ then you should set the <see cref="P:log4net.Appender.EventLogAppender.LogName"/> appropriately.</para>
+ <para>This should not be used to distinguish your event log messages
+ from those of other applications, the <see cref="P:log4net.Appender.EventLogAppender.ApplicationName"/>
+ property should be used to distinguish events. This property should be
+ used to group together events into a single log.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.ApplicationName">
+ <summary>
+ Property used to set the Application name. This appears in the
+ event logs when logging.
+ </summary>
+ <value>
+ The string used to distinguish events from different sources.
+ </value>
+ <remarks>
+ Sets the event log source property.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.MachineName">
+ <summary>
+ This property is used to return the name of the computer to use
+ when accessing the event logs. Currently, this is the current
+ computer, denoted by a dot "."
+ </summary>
+ <value>
+ The string name of the machine holding the event log that
+ will be logged into.
+ </value>
+ <remarks>
+ This property cannot be changed. It is currently set to '.'
+ i.e. the local machine. This may be changed in future.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> used to write to the EventLog.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> used to write to the EventLog.
+ </value>
+ <remarks>
+ <para>
+ The system security context used to write to the EventLog.
+ </para>
+ <para>
+ Unless a <see cref="P:log4net.Appender.EventLogAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.EventLogAppender.Level2EventLogEntryType">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the color it should be displayed as.
+ </summary>
+ <remarks>
+ <para>
+ Defines the mapping between a level and its event log entry type.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType">
+ <summary>
+ The <see cref="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType"/> for this entry
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The <see cref="P:log4net.Appender.EventLogAppender.Level2EventLogEntryType.EventLogEntryType"/> for this entry
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender">
+ <summary>
+ Appends logging events to a file.
+ </summary>
+ <remarks>
+ <para>
+ Logging events are sent to the file specified by
+ the <see cref="P:log4net.Appender.FileAppender.File"/> property.
+ </para>
+ <para>
+ The file can be opened in either append or overwrite mode
+ by specifying the <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property.
+ If the file path is relative it is taken as relative from
+ the application base directory. The file encoding can be
+ specified by setting the <see cref="P:log4net.Appender.FileAppender.Encoding"/> property.
+ </para>
+ <para>
+ The layout's <see cref="P:log4net.Layout.ILayout.Header"/> and <see cref="P:log4net.Layout.ILayout.Footer"/>
+ values will be written each time the file is opened and closed
+ respectively. If the <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property is <see langword="true"/>
+ then the file may contain multiple copies of the header and footer.
+ </para>
+ <para>
+ This appender will first try to open the file for writing when <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/>
+ is called. This will typically be during configuration.
+ If the file cannot be opened for writing the appender will attempt
+ to open the file again each time a message is logged to the appender.
+ If the file cannot be opened for writing when a message is logged then
+ the message will be discarded by this appender.
+ </para>
+ <para>
+ The <see cref="T:log4net.Appender.FileAppender"/> supports pluggable file locking models via
+ the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> property.
+ The default behavior, implemented by <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/>
+ is to obtain an exclusive write lock on the file until this appender is closed.
+ The alternative model, <see cref="T:log4net.Appender.FileAppender.MinimalLock"/>, only holds a
+ write lock while the appender is writing a logging event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Rodrigo B. de Oliveira</author>
+ <author>Douglas de la Torre</author>
+ <author>Niall Daley</author>
+ </member>
+ <member name="T:log4net.Appender.TextWriterAppender">
+ <summary>
+ Sends logging events to a <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ An Appender that writes to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ <para>
+ This appender may be used stand alone if initialized with an appropriate
+ writer, however it is typically used as a base class for an appender that
+ can open a <see cref="T:System.IO.TextWriter"/> to write to.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor(log4net.Layout.ILayout,System.IO.Stream)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class and
+ sets the output destination to a new <see cref="T:System.IO.StreamWriter"/> initialized
+ with the specified <see cref="T:System.IO.Stream"/>.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <param name="os">The <see cref="T:System.IO.Stream"/> to output to.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.#ctor(log4net.Layout.ILayout,System.IO.TextWriter)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TextWriterAppender"/> class and sets
+ the output destination to the specified <see cref="T:System.IO.StreamWriter"/>.
+ </summary>
+ <param name="layout">The layout to use with this appender</param>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to output to</param>
+ <remarks>
+ The <see cref="T:System.IO.TextWriter"/> must have been previously opened.
+ </remarks>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.PreAppendCheck">
+ <summary>
+ This method determines if there is a sense in attempting to append.
+ </summary>
+ <remarks>
+ <para>
+ This method checked if an output target has been set and if a
+ layout has been set.
+ </para>
+ </remarks>
+ <returns><c>false</c> if any of the preconditions fail.</returns>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes a log statement to the output stream if the output stream exists
+ and is writable.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])"/>
+ method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ This method writes all the bulk logged events to the output writer
+ before flushing the stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.OnClose">
+ <summary>
+ Close this appender instance. The underlying stream or writer is also closed.
+ </summary>
+ <remarks>
+ Closed appenders cannot be reused.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteFooterAndCloseWriter">
+ <summary>
+ Writes the footer and closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Writes the footer and closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.CloseWriter">
+ <summary>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.Reset">
+ <summary>
+ Clears internal references to the underlying <see cref="T:System.IO.TextWriter"/>
+ and other variables.
+ </summary>
+ <remarks>
+ <para>
+ Subclasses can override this method for an alternate closing behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteFooter">
+ <summary>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.WriteHeader">
+ <summary>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TextWriterAppender.PrepareWriter">
+ <summary>
+ Called to allow a subclass to lazily initialize the writer
+ </summary>
+ <remarks>
+ <para>
+ This method is called when an event is logged and the <see cref="P:log4net.Appender.TextWriterAppender.Writer"/> or
+ <see cref="P:log4net.Appender.TextWriterAppender.QuietWriter"/> have not been set. This allows a subclass to
+ attempt to initialize the writer multiple times.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.TextWriterAppender.m_qtw">
+ <summary>
+ This is the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.TextWriterAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying <see cref="T:System.IO.TextWriter"/>
+ or output stream will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.TextWriterAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logging events are not actually persisted if and when the application
+ crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.ImmediateFlush">
+ <summary>
+ Gets or set whether the appender will flush at the end
+ of each append operation.
+ </summary>
+ <value>
+ <para>
+ The default behavior is to flush at the end of each
+ append operation.
+ </para>
+ <para>
+ If this option is set to <c>false</c>, then the underlying
+ stream can defer persisting the logging event to a later
+ time.
+ </para>
+ </value>
+ <remarks>
+ Avoiding the flush operation at the end of each append results in
+ a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.Writer">
+ <summary>
+ Sets the <see cref="T:System.IO.TextWriter"/> where the log output will go.
+ </summary>
+ <remarks>
+ <para>
+ The specified <see cref="T:System.IO.TextWriter"/> must be open and writable.
+ </para>
+ <para>
+ The <see cref="T:System.IO.TextWriter"/> will be closed when the appender
+ instance is closed.
+ </para>
+ <para>
+ <b>Note:</b> Logging to an unopened <see cref="T:System.IO.TextWriter"/> will fail.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.ErrorHandler">
+ <summary>
+ Gets or set the <see cref="T:log4net.Core.IErrorHandler"/> and the underlying
+ <see cref="T:log4net.Util.QuietTextWriter"/>, if any, for this appender.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.IErrorHandler"/> for this appender.
+ </value>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TextWriterAppender.QuietWriter">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Util.QuietTextWriter"/> where logging events are written.
+ </value>
+ <remarks>
+ <para>
+ This is the <see cref="T:log4net.Util.QuietTextWriter"/> where logging events
+ will be written to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor(log4net.Layout.ILayout,System.String,System.Boolean)">
+ <summary>
+ Construct a new appender using the layout, file and append mode.
+ </summary>
+ <param name="layout">the layout to use with this appender</param>
+ <param name="filename">the full path to the file to write to</param>
+ <param name="append">flag to indicate if the file should be appended to</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.#ctor(log4net.Layout.ILayout,System.String)">
+ <summary>
+ Construct a new appender using the layout and file specified.
+ The file will be appended to.
+ </summary>
+ <param name="layout">the layout to use with this appender</param>
+ <param name="filename">the full path to the file to write to</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ActivateOptions">
+ <summary>
+ Activate the options on the file appender.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.FileAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ This will cause the file to be opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Reset">
+ <summary>
+ Closes any previously opened file and calls the parent's <see cref="M:log4net.Appender.TextWriterAppender.Reset"/>.
+ </summary>
+ <remarks>
+ <para>
+ Resets the filename and the file stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.PrepareWriter">
+ <summary>
+ Called to initialize the file writer
+ </summary>
+ <remarks>
+ <para>
+ Will be called for each logged message until the file is
+ successfully opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/>
+ method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes a log statement to the output stream if the output stream exists
+ and is writable.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent[])"/>
+ method.
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ Acquires the output file locks once before writing all the events to
+ the stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.WriteFooter">
+ <summary>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a footer as produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Footer"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.WriteHeader">
+ <summary>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </summary>
+ <remarks>
+ <para>
+ Writes a header produced by the embedded layout's <see cref="P:log4net.Layout.ILayout.Header"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.CloseWriter">
+ <summary>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.CloseFile">
+ <summary>
+ Closes the previously opened file.
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Layout.ILayout.Footer"/> to the file and then
+ closes the file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SafeOpenFile(System.String,System.Boolean)">
+ <summary>
+ Sets and <i>opens</i> the file where the log output will go. The specified file must be writable.
+ </summary>
+ <param name="fileName">The path to the log file. Must be a fully qualified path.</param>
+ <param name="append">If true will append to fileName. Otherwise will truncate fileName</param>
+ <remarks>
+ <para>
+ Calls <see cref="M:log4net.Appender.FileAppender.OpenFile(System.String,System.Boolean)"/> but guarantees not to throw an exception.
+ Errors are passed to the <see cref="P:log4net.Appender.TextWriterAppender.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.OpenFile(System.String,System.Boolean)">
+ <summary>
+ Sets and <i>opens</i> the file where the log output will go. The specified file must be writable.
+ </summary>
+ <param name="fileName">The path to the log file. Must be a fully qualified path.</param>
+ <param name="append">If true will append to fileName. Otherwise will truncate fileName</param>
+ <remarks>
+ <para>
+ If there was already an opened file, then the previous file
+ is closed first.
+ </para>
+ <para>
+ This method will ensure that the directory structure
+ for the <paramref name="fileName"/> specified exists.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.Stream)">
+ <summary>
+ Sets the quiet writer used for file output
+ </summary>
+ <param name="fileStream">the file stream that has been opened for writing</param>
+ <remarks>
+ <para>
+ This implementation of <see cref="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.Stream)"/> creates a <see cref="T:System.IO.StreamWriter"/>
+ over the <paramref name="fileStream"/> and passes it to the
+ <see cref="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.TextWriter)"/> method.
+ </para>
+ <para>
+ This method can be overridden by sub classes that want to wrap the
+ <see cref="T:System.IO.Stream"/> in some way, for example to encrypt the output
+ data using a <c>System.Security.Cryptography.CryptoStream</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.SetQWForFiles(System.IO.TextWriter)">
+ <summary>
+ Sets the quiet writer being used.
+ </summary>
+ <param name="writer">the writer over the file stream that has been opened for writing</param>
+ <remarks>
+ <para>
+ This method can be overridden by sub classes that want to
+ wrap the <see cref="T:System.IO.TextWriter"/> in some way.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_appendToFile">
+ <summary>
+ Flag to indicate if we should append to the file
+ or overwrite the file. The default is to append.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_fileName">
+ <summary>
+ The name of the log file.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_encoding">
+ <summary>
+ The encoding to use for the file stream.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_stream">
+ <summary>
+ The stream to log to. Has added locking semantics
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.FileAppender.m_lockingModel">
+ <summary>
+ The locking model to use
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.File">
+ <summary>
+ Gets or sets the path to the file that logging will be written to.
+ </summary>
+ <value>
+ The path to the file that logging will be written to.
+ </value>
+ <remarks>
+ <para>
+ If the path is relative it is taken as relative from
+ the application base directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.AppendToFile">
+ <summary>
+ Gets or sets a flag that indicates whether the file should be
+ appended to or overwritten.
+ </summary>
+ <value>
+ Indicates whether the file should be appended to or overwritten.
+ </value>
+ <remarks>
+ <para>
+ If the value is set to false then the file will be overwritten, if
+ it is set to true then the file will be appended to.
+ </para>
+ The default value is true.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.Encoding">
+ <summary>
+ Gets or sets <see cref="P:log4net.Appender.FileAppender.Encoding"/> used to write to the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.Encoding"/> used to write to the file.
+ </value>
+ <remarks>
+ <para>
+ The default encoding set is <see cref="P:System.Text.Encoding.Default"/>
+ which is the encoding for the system's current ANSI code page.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> used to write to the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> used to write to the file.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.FileAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.LockingModel">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to handle locking of the file.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to lock the file.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the <see cref="P:log4net.Appender.FileAppender.LockingModel"/> used to handle locking of the file.
+ </para>
+ <para>
+ There are two built in locking models, <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/> and <see cref="T:log4net.Appender.FileAppender.MinimalLock"/>.
+ The former locks the file from the start of logging to the end and the
+ later lock only for the minimal amount of time when logging each message.
+ </para>
+ <para>
+ The default locking model is the <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.LockingStream">
+ <summary>
+ Write only <see cref="T:System.IO.Stream"/> that uses the <see cref="T:log4net.Appender.FileAppender.LockingModelBase"/>
+ to manage access to an underlying resource.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingStream.BeginWrite(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)">
+ <summary>
+ True asynchronous writes are not supported, the implementation forces a synchronous write.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LogException">
+ <summary>
+ Exception base type for log4net.
+ </summary>
+ <remarks>
+ <para>
+ This type extends <see cref="T:System.ApplicationException"/>. It
+ does not add any new functionality but does differentiate the
+ type of exception being thrown.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class with
+ the specified message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.String,System.Exception)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class
+ with the specified message and inner exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LogException"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.LockingModelBase">
+ <summary>
+ Locking model base class
+ </summary>
+ <remarks>
+ <para>
+ Base class for the locking models available to the <see cref="T:log4net.Appender.FileAppender"/> derived loggers.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Open the output file
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.LockingModelBase.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Acquire the lock on the file in preparation for writing to it.
+ Return a stream pointing to the file. <see cref="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock"/>
+ must be called to release the lock on the output file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.LockingModelBase.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Release the lock on the file. No further writes will be made to the
+ stream until <see cref="M:log4net.Appender.FileAppender.LockingModelBase.AcquireLock"/> is called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.FileAppender.LockingModelBase.CurrentAppender">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Appender.FileAppender"/> for this LockingModel
+ </summary>
+ <value>
+ The <see cref="T:log4net.Appender.FileAppender"/> for this LockingModel
+ </value>
+ <remarks>
+ <para>
+ The file appender this locking model is attached to and working on
+ behalf of.
+ </para>
+ <para>
+ The file appender is used to locate the security context and the error handler to use.
+ </para>
+ <para>
+ The value of this property will be set before <see cref="M:log4net.Appender.FileAppender.LockingModelBase.OpenFile(System.String,System.Boolean,System.Text.Encoding)"/> is
+ called.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.ExclusiveLock">
+ <summary>
+ Hold an exclusive lock on the output file
+ </summary>
+ <remarks>
+ <para>
+ Open the file once for writing and hold it open until <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile"/> is called.
+ Maintains an exclusive lock on the file during this time.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Open the file specified and prepare for logging.
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Does nothing. The lock is already taken
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.ExclusiveLock.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Does nothing. The lock will be released when the file is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.FileAppender.MinimalLock">
+ <summary>
+ Acquires the file lock for each write
+ </summary>
+ <remarks>
+ <para>
+ Opens the file once for each <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/>/<see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/> cycle,
+ thus holding the lock for the minimal amount of time. This method of locking
+ is considerably slower than <see cref="T:log4net.Appender.FileAppender.ExclusiveLock"/> but allows
+ other processes to move/delete the log file whilst logging continues.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.OpenFile(System.String,System.Boolean,System.Text.Encoding)">
+ <summary>
+ Prepares to open the file when the first message is logged.
+ </summary>
+ <param name="filename">The filename to use</param>
+ <param name="append">Whether to append to the file, or overwrite</param>
+ <param name="encoding">The encoding to use</param>
+ <remarks>
+ <para>
+ Open the file specified and prepare for logging.
+ No writes will be made until <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/> is called.
+ Must be called before any calls to <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/>,
+ <see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/> and <see cref="M:log4net.Appender.FileAppender.MinimalLock.CloseFile"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.CloseFile">
+ <summary>
+ Close the file
+ </summary>
+ <remarks>
+ <para>
+ Close the file. No further writes will be made.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock">
+ <summary>
+ Acquire the lock on the file
+ </summary>
+ <returns>A stream that is ready to be written to.</returns>
+ <remarks>
+ <para>
+ Acquire the lock on the file in preparation for writing to it.
+ Return a stream pointing to the file. <see cref="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock"/>
+ must be called to release the lock on the output file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.FileAppender.MinimalLock.ReleaseLock">
+ <summary>
+ Release the lock on the file
+ </summary>
+ <remarks>
+ <para>
+ Release the lock on the file. No further writes will be made to the
+ stream until <see cref="M:log4net.Appender.FileAppender.MinimalLock.AcquireLock"/> is called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.ForwardingAppender">
+ <summary>
+ This appender forwards logging events to attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ The forwarding appender can be used to specify different thresholds
+ and filters for the same appender at different locations within the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.ForwardingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.OnClose">
+ <summary>
+ Closes the appender and releases resources.
+ </summary>
+ <remarks>
+ <para>
+ Releases any resources allocated within the appender such as file handles,
+ network connections, etc.
+ </para>
+ <para>
+ It is a programming error to append to a closed appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Forward the logging event to the attached appenders
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Delivers the logging event to all the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Forward the logging events to the attached appenders
+ </summary>
+ <param name="loggingEvents">The array of events to log.</param>
+ <remarks>
+ <para>
+ Delivers the logging events to all the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Adds an <see cref="T:log4net.Appender.IAppender"/> to the list of appenders of this
+ instance.
+ </summary>
+ <param name="newAppender">The <see cref="T:log4net.Appender.IAppender"/> to add to this appender.</param>
+ <remarks>
+ <para>
+ If the specified <see cref="T:log4net.Appender.IAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.GetAppender(System.String)">
+ <summary>
+ Looks for the appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to lookup.</param>
+ <returns>
+ The appender with the specified name, or <c>null</c>.
+ </returns>
+ <remarks>
+ <para>
+ Get the named appender attached to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAllAppenders">
+ <summary>
+ Removes all previously added appenders from this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.ForwardingAppender.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.ForwardingAppender.m_appenderAttachedImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.ForwardingAppender.Appenders">
+ <summary>
+ Gets the appenders contained in this appender as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ If no appenders can be found, then an <see cref="T:log4net.Util.EmptyCollection"/>
+ is returned.
+ </remarks>
+ <returns>
+ A collection of the appenders in this appender.
+ </returns>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender">
+ <summary>
+ Logs events to a local syslog service.
+ </summary>
+ <remarks>
+ <note>
+ This appender uses the POSIX libc library functions <c>openlog</c>, <c>syslog</c>, and <c>closelog</c>.
+ If these functions are not available on the local system then this appender will not work!
+ </note>
+ <para>
+ The functions <c>openlog</c>, <c>syslog</c>, and <c>closelog</c> are specified in SUSv2 and
+ POSIX 1003.1-2001 standards. These are used to log messages to the local syslog service.
+ </para>
+ <para>
+ This appender talks to a local syslog service. If you need to log to a remote syslog
+ daemon and you cannot configure your local syslog service to do this you may be
+ able to use the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> to log via UDP.
+ </para>
+ <para>
+ Syslog messages must have a facility and and a severity. The severity
+ is derived from the Level of the logging event.
+ The facility must be chosen from the set of defined syslog
+ <see cref="T:log4net.Appender.LocalSyslogAppender.SyslogFacility"/> values. The facilities list is predefined
+ and cannot be extended.
+ </para>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.LocalSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Util.SystemInfo.ApplicationFriendlyName"/>).
+ </para>
+ </remarks>
+ <author>Rob Lyon</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.LocalSyslogAppender"/> class.
+ </summary>
+ <remarks>
+ This instance of the <see cref="T:log4net.Appender.LocalSyslogAppender"/> class is set up to write
+ to a local syslog service.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.AddMapping(log4net.Appender.LocalSyslogAppender.LevelSeverity)">
+ <summary>
+ Add a mapping of level to severity
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Adds a <see cref="T:log4net.Appender.LocalSyslogAppender.LevelSeverity"/> to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.LocalSyslogAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to a remote syslog daemon.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.OnClose">
+ <summary>
+ Close the syslog when the appender is closed
+ </summary>
+ <remarks>
+ <para>
+ Close the syslog when the appender is closed
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.GetSeverity(log4net.Core.Level)">
+ <summary>
+ Translates a log4net level to a syslog severity.
+ </summary>
+ <param name="level">A log4net level.</param>
+ <returns>A syslog severity.</returns>
+ <remarks>
+ <para>
+ Translates a log4net level to a syslog severity.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.GeneratePriority(log4net.Appender.LocalSyslogAppender.SyslogFacility,log4net.Appender.LocalSyslogAppender.SyslogSeverity)">
+ <summary>
+ Generate a syslog priority.
+ </summary>
+ <param name="facility">The syslog facility.</param>
+ <param name="severity">The syslog severity.</param>
+ <returns>A syslog priority.</returns>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_facility">
+ <summary>
+ The facility. The default facility is <see cref="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_identity">
+ <summary>
+ The message identity
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_handleToIdentity">
+ <summary>
+ Marshaled handle to the identity string. We have to hold on to the
+ string as the <c>openlog</c> and <c>syslog</c> APIs just hold the
+ pointer to the ident and dereference it for each log message.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to syslog severity
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.openlog(System.IntPtr,System.Int32,log4net.Appender.LocalSyslogAppender.SyslogFacility)">
+ <summary>
+ Open connection to system logger.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.syslog(System.Int32,System.String,System.String)">
+ <summary>
+ Generate a log message.
+ </summary>
+ <remarks>
+ <para>
+ The libc syslog method takes a format string and a variable argument list similar
+ to the classic printf function. As this type of vararg list is not supported
+ by C# we need to specify the arguments explicitly. Here we have specified the
+ format string with a single message argument. The caller must set the format
+ string to <c>"%s"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.LocalSyslogAppender.closelog">
+ <summary>
+ Close descriptor used to write to system logger.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.Identity">
+ <summary>
+ Message identity
+ </summary>
+ <remarks>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.LocalSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Util.SystemInfo.ApplicationFriendlyName"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.Facility">
+ <summary>
+ Syslog facility
+ </summary>
+ <remarks>
+ Set to one of the <see cref="T:log4net.Appender.LocalSyslogAppender.SyslogFacility"/> values. The list of
+ facilities is predefined and cannot be extended. The default value
+ is <see cref="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User"/>.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="P:log4net.Appender.AppenderSkeleton.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.SyslogSeverity">
+ <summary>
+ syslog severities
+ </summary>
+ <remarks>
+ <para>
+ The log4net Level maps to a syslog severity using the
+ <see cref="M:log4net.Appender.LocalSyslogAppender.AddMapping(log4net.Appender.LocalSyslogAppender.LevelSeverity)"/> method and the <see cref="T:log4net.Appender.LocalSyslogAppender.LevelSeverity"/>
+ class. The severity is set on <see cref="P:log4net.Appender.LocalSyslogAppender.LevelSeverity.Severity"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Emergency">
+ <summary>
+ system is unusable
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Alert">
+ <summary>
+ action must be taken immediately
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Critical">
+ <summary>
+ critical conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Error">
+ <summary>
+ error conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Warning">
+ <summary>
+ warning conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Notice">
+ <summary>
+ normal but significant condition
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Informational">
+ <summary>
+ informational
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogSeverity.Debug">
+ <summary>
+ debug-level messages
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.SyslogFacility">
+ <summary>
+ syslog facilities
+ </summary>
+ <remarks>
+ <para>
+ The syslog facility defines which subsystem the logging comes from.
+ This is set on the <see cref="P:log4net.Appender.LocalSyslogAppender.Facility"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Kernel">
+ <summary>
+ kernel messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.User">
+ <summary>
+ random user-level messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Mail">
+ <summary>
+ mail system
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Daemons">
+ <summary>
+ system daemons
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Authorization">
+ <summary>
+ security/authorization messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Syslog">
+ <summary>
+ messages generated internally by syslogd
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Printer">
+ <summary>
+ line printer subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.News">
+ <summary>
+ network news subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Uucp">
+ <summary>
+ UUCP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Clock">
+ <summary>
+ clock (cron/at) daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Authorization2">
+ <summary>
+ security/authorization messages (private)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Ftp">
+ <summary>
+ ftp daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Ntp">
+ <summary>
+ NTP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Audit">
+ <summary>
+ log audit
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Alert">
+ <summary>
+ log alert
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Clock2">
+ <summary>
+ clock daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local0">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local1">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local2">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local3">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local4">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local5">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local6">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.LocalSyslogAppender.SyslogFacility.Local7">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.LocalSyslogAppender.LevelSeverity">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </summary>
+ <remarks>
+ <para>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.LocalSyslogAppender.LevelSeverity.Severity">
+ <summary>
+ The mapped syslog severity for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped syslog severity for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.MemoryAppender">
+ <summary>
+ Stores logging events in an array.
+ </summary>
+ <remarks>
+ <para>
+ The memory appender stores all the logging events
+ that are appended in an in-memory array.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Appender.MemoryAppender.GetEvents"/> method to get
+ the current list of events that have been appended.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Appender.MemoryAppender.Clear"/> method to clear the
+ current list of events.
+ </para>
+ </remarks>
+ <author>Julian Biddle</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.MemoryAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.GetEvents">
+ <summary>
+ Gets the events that have been logged.
+ </summary>
+ <returns>The events that have been logged</returns>
+ <remarks>
+ <para>
+ Gets the events that have been logged.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>Stores the <paramref name="loggingEvent"/> in the events list.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.MemoryAppender.Clear">
+ <summary>
+ Clear the list of events
+ </summary>
+ <remarks>
+ Clear the list of events
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.MemoryAppender.m_eventsList">
+ <summary>
+ The list of events that have been appended.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.MemoryAppender.m_fixFlags">
+ <summary>
+ Value indicating which fields in the event should be fixed
+ </summary>
+ <remarks>
+ By default all fields are fixed
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.MemoryAppender.OnlyFixPartialEventData">
+ <summary>
+ Gets or sets a value indicating whether only part of the logging event
+ data should be fixed.
+ </summary>
+ <value>
+ <c>true</c> if the appender should only fix part of the logging event
+ data, otherwise <c>false</c>. The default is <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Setting this property to <c>true</c> will cause only part of the event
+ data to be fixed and stored in the appender, hereby improving performance.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.MemoryAppender.Fix">
+ <summary>
+ Gets or sets the fields that will be fixed in the event
+ </summary>
+ <remarks>
+ <para>
+ The logging event needs to have certain thread specific values
+ captured before it can be buffered. See <see cref="P:log4net.Core.LoggingEvent.Fix"/>
+ for details.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.NetSendAppender">
+ <summary>
+ Logs entries by sending network messages using the
+ <see cref="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)"/> native function.
+ </summary>
+ <remarks>
+ <para>
+ You can send messages only to names that are active
+ on the network. If you send the message to a user name,
+ that user must be logged on and running the Messenger
+ service to receive the message.
+ </para>
+ <para>
+ The receiver will get a top most window displaying the
+ messages one at a time, therefore this appender should
+ not be used to deliver a high volume of messages.
+ </para>
+ <para>
+ The following table lists some possible uses for this appender :
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>Action</term>
+ <description>Property Value(s)</description>
+ </listheader>
+ <item>
+ <term>Send a message to a user account on the local machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the local machine&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to a user account on a remote machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the remote machine&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to a domain user account</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of a domain controller | uninitialized&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;user name&gt;
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message to all the names in a workgroup or domain</term>
+ <description>
+ <para>
+ <paramref name="Recipient"/> = &lt;workgroup name | domain name&gt;*
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Send a message from the local machine to a remote machine</term>
+ <description>
+ <para>
+ <paramref name="Server"/> = &lt;name of the local machine | uninitialized&gt;
+ </para>
+ <para>
+ <paramref name="Recipient"/> = &lt;name of the remote machine&gt;
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ <b>Note :</b> security restrictions apply for sending
+ network messages, see <see cref="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)"/>
+ for more information.
+ </para>
+ </remarks>
+ <example>
+ <para>
+ An example configuration section to log information
+ using this appender from the local machine, named
+ LOCAL_PC, to machine OPERATOR_PC :
+ </para>
+ <code lang="XML" escaped="true">
+ <appender name="NetSendAppender_Operator" type="log4net.Appender.NetSendAppender">
+ <server value="LOCAL_PC"/>
+ <recipient value="OPERATOR_PC"/>
+ <layout type="log4net.Layout.PatternLayout" value="%-5p %c [%x] - %m%n"/>
+ </appender>
+ </code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_server">
+ <summary>
+ The DNS or NetBIOS name of the server on which the function is to execute.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_sender">
+ <summary>
+ The sender of the network message.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_recipient">
+ <summary>
+ The message alias to which the message should be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.NetSendAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.#ctor">
+ <summary>
+ Initializes the appender.
+ </summary>
+ <remarks>
+ The default constructor initializes all fields to their default values.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.NetSendAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The appender will be ignored if no <see cref="P:log4net.Appender.NetSendAppender.Recipient"/> was specified.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required property <see cref="P:log4net.Appender.NetSendAppender.Recipient"/> was not specified.</exception>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Sends the event using a network message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.NetSendAppender.NetMessageBufferSend(System.String,System.String,System.String,System.String,System.Int32)">
+ <summary>
+ Sends a buffer of information to a registered message alias.
+ </summary>
+ <param name="serverName">The DNS or NetBIOS name of the server on which the function is to execute.</param>
+ <param name="msgName">The message alias to which the message buffer should be sent</param>
+ <param name="fromName">The originator of the message.</param>
+ <param name="buffer">The message text.</param>
+ <param name="bufferSize">The length, in bytes, of the message text.</param>
+ <remarks>
+ <para>
+ The following restrictions apply for sending network messages:
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>Platform</term>
+ <description>Requirements</description>
+ </listheader>
+ <item>
+ <term>Windows NT</term>
+ <description>
+ <para>
+ No special group membership is required to send a network message.
+ </para>
+ <para>
+ Admin, Accounts, Print, or Server Operator group membership is required to
+ successfully send a network message on a remote server.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>Windows 2000 or later</term>
+ <description>
+ <para>
+ If you send a message on a domain controller that is running Active Directory,
+ access is allowed or denied based on the access control list (ACL) for the securable
+ object. The default ACL permits only Domain Admins and Account Operators to send a network message.
+ </para>
+ <para>
+ On a member server or workstation, only Administrators and Server Operators can send a network message.
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ For more information see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/security_requirements_for_the_network_management_functions.asp">Security Requirements for the Network Management Functions</a>.
+ </para>
+ </remarks>
+ <returns>
+ <para>
+ If the function succeeds, the return value is zero.
+ </para>
+ </returns>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Sender">
+ <summary>
+ Gets or sets the sender of the message.
+ </summary>
+ <value>
+ The sender of the message.
+ </value>
+ <remarks>
+ If this property is not specified, the message is sent from the local computer.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Recipient">
+ <summary>
+ Gets or sets the message alias to which the message should be sent.
+ </summary>
+ <value>
+ The recipient of the message.
+ </value>
+ <remarks>
+ This property should always be specified in order to send a message.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.Server">
+ <summary>
+ Gets or sets the DNS or NetBIOS name of the remote server on which the function is to execute.
+ </summary>
+ <value>
+ DNS or NetBIOS name of the remote server on which the function is to execute.
+ </value>
+ <remarks>
+ <para>
+ For Windows NT 4.0 and earlier, the string should begin with \\.
+ </para>
+ <para>
+ If this property is not specified, the local computer is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> used to call the NetSend method.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> used to call the NetSend method.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.NetSendAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.NetSendAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.OutputDebugStringAppender">
+ <summary>
+ Appends log events to the OutputDebugString system.
+ </summary>
+ <remarks>
+ <para>
+ OutputDebugStringAppender appends log events to the
+ OutputDebugString system.
+ </para>
+ <para>
+ The string is passed to the native <c>OutputDebugString</c>
+ function.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.OutputDebugStringAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write the logging event to the output debug string API
+ </summary>
+ <param name="loggingEvent">the event to log</param>
+ <remarks>
+ <para>
+ Write the logging event to the output debug string API
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.OutputDebugStringAppender.OutputDebugString(System.String)">
+ <summary>
+ Stub for OutputDebugString native method
+ </summary>
+ <param name="message">the string to output</param>
+ <remarks>
+ <para>
+ Stub for OutputDebugString native method
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.OutputDebugStringAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender">
+ <summary>
+ Logs events to a remote syslog daemon.
+ </summary>
+ <remarks>
+ <para>
+ The BSD syslog protocol is used to remotely log to
+ a syslog daemon. The syslogd listens for for messages
+ on UDP port 514.
+ </para>
+ <para>
+ The syslog UDP protocol is not authenticated. Most syslog daemons
+ do not accept remote log messages because of the security implications.
+ You may be able to use the LocalSyslogAppender to talk to a local
+ syslog service.
+ </para>
+ <para>
+ There is an RFC 3164 that claims to document the BSD Syslog Protocol.
+ This RFC can be seen here: http://www.faqs.org/rfcs/rfc3164.html.
+ This appender generates what the RFC calls an "Original Device Message",
+ i.e. does not include the TIMESTAMP or HOSTNAME fields. By observation
+ this format of message will be accepted by all current syslog daemon
+ implementations. The daemon will attach the current time and the source
+ hostname or IP address to any messages received.
+ </para>
+ <para>
+ Syslog messages must have a facility and and a severity. The severity
+ is derived from the Level of the logging event.
+ The facility must be chosen from the set of defined syslog
+ <see cref="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility"/> values. The facilities list is predefined
+ and cannot be extended.
+ </para>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.RemoteSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Core.LoggingEvent.Domain"/>).
+ </para>
+ </remarks>
+ <author>Rob Lyon</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Appender.UdpAppender">
+ <summary>
+ Sends logging events as connectionless UDP datagrams to a remote host or a
+ multicast group using an <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </summary>
+ <remarks>
+ <para>
+ UDP guarantees neither that messages arrive, nor that they arrive in the correct order.
+ </para>
+ <para>
+ To view the logging results, a custom application can be developed that listens for logging
+ events.
+ </para>
+ <para>
+ When decoding events send via this appender remember to use the same encoding
+ to decode the events as was used to send the events. See the <see cref="P:log4net.Appender.UdpAppender.Encoding"/>
+ property to specify the encoding to use.
+ </para>
+ </remarks>
+ <example>
+ This example shows how to log receive logging events that are sent
+ on IP address 244.0.0.1 and port 8080 to the console. The event is
+ encoded in the packet as a unicode string and it is decoded as such.
+ <code lang="C#">
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
+ UdpClient udpClient;
+ byte[] buffer;
+ string loggingEvent;
+
+ try
+ {
+ udpClient = new UdpClient(8080);
+
+ while(true)
+ {
+ buffer = udpClient.Receive(ref remoteEndPoint);
+ loggingEvent = System.Text.Encoding.Unicode.GetString(buffer);
+ Console.WriteLine(loggingEvent);
+ }
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e.ToString());
+ }
+ </code>
+ <code lang="Visual Basic">
+ Dim remoteEndPoint as IPEndPoint
+ Dim udpClient as UdpClient
+ Dim buffer as Byte()
+ Dim loggingEvent as String
+
+ Try
+ remoteEndPoint = new IPEndPoint(IPAddress.Any, 0)
+ udpClient = new UdpClient(8080)
+
+ While True
+ buffer = udpClient.Receive(ByRef remoteEndPoint)
+ loggingEvent = System.Text.Encoding.Unicode.GetString(buffer)
+ Console.WriteLine(loggingEvent)
+ Wend
+ Catch e As Exception
+ Console.WriteLine(e.ToString())
+ End Try
+ </code>
+ <para>
+ An example configuration section to log information using this appender to the
+ IP 224.0.0.1 on port 8080:
+ </para>
+ <code lang="XML" escaped="true">
+ <appender name="UdpAppender" type="log4net.Appender.UdpAppender">
+ <remoteAddress value="224.0.0.1"/>
+ <remotePort value="8080"/>
+ <layout type="log4net.Layout.PatternLayout" value="%-5level %logger [%ndc] - %message%newline"/>
+ </appender>
+ </code>
+ </example>
+ <author>Gert Driesen</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.UdpAppender"/> class.
+ </summary>
+ <remarks>
+ The default constructor initializes all fields to their default values.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The appender will be ignored if no <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> was specified or
+ an invalid remote or local TCP port number was specified.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required property <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> was not specified.</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException">The TCP port number assigned to <see cref="P:log4net.Appender.UdpAppender.LocalPort"/> or <see cref="P:log4net.Appender.UdpAppender.RemotePort"/> is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Sends the event using an UDP datagram.
+ </para>
+ <para>
+ Exceptions are passed to the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.OnClose">
+ <summary>
+ Closes the UDP connection and releases all resources associated with
+ this <see cref="T:log4net.Appender.UdpAppender"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Disables the underlying <see cref="T:System.Net.Sockets.UdpClient"/> and releases all managed
+ and unmanaged resources associated with the <see cref="T:log4net.Appender.UdpAppender"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.UdpAppender.InitializeClientConnection">
+ <summary>
+ Initializes the underlying <see cref="T:System.Net.Sockets.UdpClient"/> connection.
+ </summary>
+ <remarks>
+ <para>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> is initialized and binds to the
+ port number from which you intend to communicate.
+ </para>
+ <para>
+ Exceptions are passed to the <see cref="P:log4net.Appender.AppenderSkeleton.ErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remoteAddress">
+ <summary>
+ The IP address of the remote host or multicast group to which
+ the logging event will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remotePort">
+ <summary>
+ The TCP port number of the remote host or multicast group to
+ which the logging event will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_remoteEndPoint">
+ <summary>
+ The cached remote endpoint to which the logging events will be sent.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_localPort">
+ <summary>
+ The TCP port number from which the <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_client">
+ <summary>
+ The <see cref="T:System.Net.Sockets.UdpClient"/> instance that will be used for sending the
+ logging events.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.UdpAppender.m_encoding">
+ <summary>
+ The encoding to use for the packet.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemoteAddress">
+ <summary>
+ Gets or sets the IP address of the remote host or multicast group to which
+ the underlying <see cref="T:System.Net.Sockets.UdpClient"/> should sent the logging event.
+ </summary>
+ <value>
+ The IP address of the remote host or multicast group to which the logging event
+ will be sent.
+ </value>
+ <remarks>
+ <para>
+ Multicast addresses are identified by IP class <b>D</b> addresses (in the range 224.0.0.0 to
+ 239.255.255.255). Multicast packets can pass across different networks through routers, so
+ it is possible to use multicasts in an Internet scenario as long as your network provider
+ supports multicasting.
+ </para>
+ <para>
+ Hosts that want to receive particular multicast messages must register their interest by joining
+ the multicast group. Multicast messages are not sent to networks where no host has joined
+ the multicast group. Class <b>D</b> IP addresses are used for multicast groups, to differentiate
+ them from normal host addresses, allowing nodes to easily detect if a message is of interest.
+ </para>
+ <para>
+ Static multicast addresses that are needed globally are assigned by IANA. A few examples are listed in the table below:
+ </para>
+ <para>
+ <list type="table">
+ <listheader>
+ <term>IP Address</term>
+ <description>Description</description>
+ </listheader>
+ <item>
+ <term>224.0.0.1</term>
+ <description>
+ <para>
+ Sends a message to all system on the subnet.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>224.0.0.2</term>
+ <description>
+ <para>
+ Sends a message to all routers on the subnet.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>224.0.0.12</term>
+ <description>
+ <para>
+ The DHCP server answers messages on the IP address 224.0.0.12, but only on a subnet.
+ </para>
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ A complete list of actually reserved multicast addresses and their owners in the ranges
+ defined by RFC 3171 can be found at the <A href="http://www.iana.org/assignments/multicast-addresses">IANA web site</A>.
+ </para>
+ <para>
+ The address range 239.0.0.0 to 239.255.255.255 is reserved for administrative scope-relative
+ addresses. These addresses can be reused with other local groups. Routers are typically
+ configured with filters to prevent multicast traffic in this range from flowing outside
+ of the local network.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemotePort">
+ <summary>
+ Gets or sets the TCP port number of the remote host or multicast group to which
+ the underlying <see cref="T:System.Net.Sockets.UdpClient"/> should sent the logging event.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number of the remote host or multicast group to which the logging event
+ will be sent.
+ </value>
+ <remarks>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> will send messages to this TCP port number
+ on the remote host or multicast group.
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.LocalPort">
+ <summary>
+ Gets or sets the TCP port number from which the underlying <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number from which the underlying <see cref="T:System.Net.Sockets.UdpClient"/> will communicate.
+ </value>
+ <remarks>
+ <para>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/> will bind to this port for sending messages.
+ </para>
+ <para>
+ Setting the value to 0 (the default) will cause the udp client not to bind to
+ a local port.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/> or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.Encoding">
+ <summary>
+ Gets or sets <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Appender.UdpAppender.Encoding"/> used to write the packets.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.Client">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.Net.Sockets.UdpClient"/>.
+ </value>
+ <remarks>
+ <see cref="T:log4net.Appender.UdpAppender"/> creates a <see cref="T:System.Net.Sockets.UdpClient"/> to send logging events
+ over a network. Classes deriving from <see cref="T:log4net.Appender.UdpAppender"/> can use this
+ property to get or set this <see cref="T:System.Net.Sockets.UdpClient"/>. Use the underlying <see cref="T:System.Net.Sockets.UdpClient"/>
+ returned from <see cref="P:log4net.Appender.UdpAppender.Client"/> if you require access beyond that which
+ <see cref="T:log4net.Appender.UdpAppender"/> provides.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RemoteEndPoint">
+ <summary>
+ Gets or sets the cached remote endpoint to which the logging events should be sent.
+ </summary>
+ <value>
+ The cached remote endpoint to which the logging events will be sent.
+ </value>
+ <remarks>
+ The <see cref="M:log4net.Appender.UdpAppender.ActivateOptions"/> method will initialize the remote endpoint
+ with the values of the <see cref="P:log4net.Appender.UdpAppender.RemoteAddress"/> and <see cref="P:log4net.Appender.UdpAppender.RemotePort"/>
+ properties.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.UdpAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.DefaultSyslogPort">
+ <summary>
+ Syslog port 514
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> class.
+ </summary>
+ <remarks>
+ This instance of the <see cref="T:log4net.Appender.RemoteSyslogAppender"/> class is set up to write
+ to a remote syslog daemon.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.AddMapping(log4net.Appender.RemoteSyslogAppender.LevelSeverity)">
+ <summary>
+ Add a mapping of level to severity
+ </summary>
+ <param name="mapping">The mapping to add</param>
+ <remarks>
+ <para>
+ Add a <see cref="T:log4net.Appender.RemoteSyslogAppender.LevelSeverity"/> mapping to this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ This method is called by the <see cref="M:log4net.Appender.AppenderSkeleton.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the event to a remote syslog daemon.
+ </para>
+ <para>
+ The format of the output will depend on the appender's layout.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.ActivateOptions">
+ <summary>
+ Initialize the options for this appender
+ </summary>
+ <remarks>
+ <para>
+ Initialize the level to syslog severity mappings set on this appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.GetSeverity(log4net.Core.Level)">
+ <summary>
+ Translates a log4net level to a syslog severity.
+ </summary>
+ <param name="level">A log4net level.</param>
+ <returns>A syslog severity.</returns>
+ <remarks>
+ <para>
+ Translates a log4net level to a syslog severity.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemoteSyslogAppender.GeneratePriority(log4net.Appender.RemoteSyslogAppender.SyslogFacility,log4net.Appender.RemoteSyslogAppender.SyslogSeverity)">
+ <summary>
+ Generate a syslog priority.
+ </summary>
+ <param name="facility">The syslog facility.</param>
+ <param name="severity">The syslog severity.</param>
+ <returns>A syslog priority.</returns>
+ <remarks>
+ <para>
+ Generate a syslog priority.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_facility">
+ <summary>
+ The facility. The default facility is <see cref="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User"/>.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_identity">
+ <summary>
+ The message identity
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.m_levelMapping">
+ <summary>
+ Mapping from level object to syslog severity
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.Identity">
+ <summary>
+ Message identity
+ </summary>
+ <remarks>
+ <para>
+ An identifier is specified with each log message. This can be specified
+ by setting the <see cref="P:log4net.Appender.RemoteSyslogAppender.Identity"/> property. The identity (also know
+ as the tag) must not contain white space. The default value for the
+ identity is the application name (from <see cref="P:log4net.Core.LoggingEvent.Domain"/>).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.Facility">
+ <summary>
+ Syslog facility
+ </summary>
+ <remarks>
+ Set to one of the <see cref="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility"/> values. The list of
+ facilities is predefined and cannot be extended. The default value
+ is <see cref="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User"/>.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.SyslogSeverity">
+ <summary>
+ syslog severities
+ </summary>
+ <remarks>
+ <para>
+ The syslog severities.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Emergency">
+ <summary>
+ system is unusable
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Alert">
+ <summary>
+ action must be taken immediately
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Critical">
+ <summary>
+ critical conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Error">
+ <summary>
+ error conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Warning">
+ <summary>
+ warning conditions
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Notice">
+ <summary>
+ normal but significant condition
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Informational">
+ <summary>
+ informational
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogSeverity.Debug">
+ <summary>
+ debug-level messages
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.SyslogFacility">
+ <summary>
+ syslog facilities
+ </summary>
+ <remarks>
+ <para>
+ The syslog facilities
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Kernel">
+ <summary>
+ kernel messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.User">
+ <summary>
+ random user-level messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Mail">
+ <summary>
+ mail system
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Daemons">
+ <summary>
+ system daemons
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Authorization">
+ <summary>
+ security/authorization messages
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Syslog">
+ <summary>
+ messages generated internally by syslogd
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Printer">
+ <summary>
+ line printer subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.News">
+ <summary>
+ network news subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Uucp">
+ <summary>
+ UUCP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Clock">
+ <summary>
+ clock (cron/at) daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Authorization2">
+ <summary>
+ security/authorization messages (private)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Ftp">
+ <summary>
+ ftp daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Ntp">
+ <summary>
+ NTP subsystem
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Audit">
+ <summary>
+ log audit
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Alert">
+ <summary>
+ log alert
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Clock2">
+ <summary>
+ clock daemon
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local0">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local1">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local2">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local3">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local4">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local5">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local6">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemoteSyslogAppender.SyslogFacility.Local7">
+ <summary>
+ reserved for local use
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RemoteSyslogAppender.LevelSeverity">
+ <summary>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </summary>
+ <remarks>
+ <para>
+ A class to act as a mapping between the level that a logging call is made at and
+ the syslog severity that is should be logged at.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemoteSyslogAppender.LevelSeverity.Severity">
+ <summary>
+ The mapped syslog severity for the specified level
+ </summary>
+ <remarks>
+ <para>
+ Required property.
+ The mapped syslog severity for the specified level
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemotingAppender">
+ <summary>
+ Delivers logging events to a remote logging sink.
+ </summary>
+ <remarks>
+ <para>
+ This Appender is designed to deliver events to a remote sink.
+ That is any object that implements the <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ interface. It delivers the events using .NET remoting. The
+ object to deliver events to is specified by setting the
+ appenders <see cref="P:log4net.Appender.RemotingAppender.Sink"/> property.</para>
+ <para>
+ The RemotingAppender buffers events before sending them. This allows it to
+ make more efficient use of the remoting infrastructure.</para>
+ <para>
+ Once the buffer is full the events are still not sent immediately.
+ They are scheduled to be sent using a pool thread. The effect is that
+ the send occurs asynchronously. This is very important for a
+ number of non obvious reasons. The remoting infrastructure will
+ flow thread local variables (stored in the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>),
+ if they are marked as <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>, across the
+ remoting boundary. If the server is not contactable then
+ the remoting infrastructure will clear the <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>
+ objects from the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>. To prevent a logging failure from
+ having side effects on the calling application the remoting call must be made
+ from a separate thread to the one used by the application. A <see cref="T:System.Threading.ThreadPool"/>
+ thread is used for this. If no <see cref="T:System.Threading.ThreadPool"/> thread is available then
+ the events will block in the thread pool manager until a thread is available.</para>
+ <para>
+ Because the events are sent asynchronously using pool threads it is possible to close
+ this appender before all the queued events have been sent.
+ When closing the appender attempts to wait until all the queued events have been sent, but
+ this will timeout after 30 seconds regardless.</para>
+ <para>
+ If this appender is being closed because the <see cref="E:System.AppDomain.ProcessExit"/>
+ event has fired it may not be possible to send all the queued events. During process
+ exit the runtime limits the time that a <see cref="E:System.AppDomain.ProcessExit"/>
+ event handler is allowed to run for. If the runtime terminates the threads before
+ the queued events have been sent then they will be lost. To ensure that all events
+ are sent the appender must be closed before the application exits. See
+ <see cref="M:log4net.Core.LoggerManager.Shutdown"/> for details on how to shutdown
+ log4net programmatically.</para>
+ </remarks>
+ <seealso cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RemotingAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.RemotingAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Send the contents of the buffer to the remote sink.
+ </summary>
+ <remarks>
+ The events are not sent immediately. They are scheduled to be sent
+ using a pool thread. The effect is that the send occurs asynchronously.
+ This is very important for a number of non obvious reasons. The remoting
+ infrastructure will flow thread local variables (stored in the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>),
+ if they are marked as <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>, across the
+ remoting boundary. If the server is not contactable then
+ the remoting infrastructure will clear the <see cref="T:System.Runtime.Remoting.Messaging.ILogicalThreadAffinative"/>
+ objects from the <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/>. To prevent a logging failure from
+ having side effects on the calling application the remoting call must be made
+ from a separate thread to the one used by the application. A <see cref="T:System.Threading.ThreadPool"/>
+ thread is used for this. If no <see cref="T:System.Threading.ThreadPool"/> thread is available then
+ the events will block in the thread pool manager until a thread is available.
+ </remarks>
+ <param name="events">The events to send.</param>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.OnClose">
+ <summary>
+ Override base class close.
+ </summary>
+ <remarks>
+ <para>
+ This method waits while there are queued work items. The events are
+ sent asynchronously using <see cref="T:System.Threading.ThreadPool"/> work items. These items
+ will be sent once a thread pool thread is available to send them, therefore
+ it is possible to close the appender before all the queued events have been
+ sent.</para>
+ <para>
+ This method attempts to wait until all the queued events have been sent, but this
+ method will timeout after 30 seconds regardless.</para>
+ <para>
+ If the appender is being closed because the <see cref="E:System.AppDomain.ProcessExit"/>
+ event has fired it may not be possible to send all the queued events. During process
+ exit the runtime limits the time that a <see cref="E:System.AppDomain.ProcessExit"/>
+ event handler is allowed to run for.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.BeginAsyncSend">
+ <summary>
+ A work item is being queued into the thread pool
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.EndAsyncSend">
+ <summary>
+ A work item from the thread pool has completed
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.SendBufferCallback(System.Object)">
+ <summary>
+ Send the contents of the buffer to the remote sink.
+ </summary>
+ <remarks>
+ This method is designed to be used with the <see cref="T:System.Threading.ThreadPool"/>.
+ This method expects to be passed an array of <see cref="T:log4net.Core.LoggingEvent"/>
+ objects in the state param.
+ </remarks>
+ <param name="state">the logging events to send</param>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_sinkUrl">
+ <summary>
+ The URL of the remote sink.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_sinkObj">
+ <summary>
+ The local proxy (.NET remoting) for the remote logging sink.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_queuedCallbackCount">
+ <summary>
+ The number of queued callbacks currently waiting or executing
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RemotingAppender.m_workQueueEmptyEvent">
+ <summary>
+ Event used to signal when there are no queued work items
+ </summary>
+ <remarks>
+ This event is set when there are no queued work items. In this
+ state it is safe to close the appender.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RemotingAppender.Sink">
+ <summary>
+ Gets or sets the URL of the well-known object that will accept
+ the logging events.
+ </summary>
+ <value>
+ The well-known URL of the remote sink.
+ </value>
+ <remarks>
+ <para>
+ The URL of the remoting sink that will accept logging events.
+ The sink must implement the <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ interface.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink">
+ <summary>
+ Interface used to deliver <see cref="T:log4net.Core.LoggingEvent"/> objects to a remote sink.
+ </summary>
+ <remarks>
+ This interface must be implemented by a remoting sink
+ if the <see cref="T:log4net.Appender.RemotingAppender"/> is to be used
+ to deliver logging events to the sink.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RemotingAppender.IRemoteLoggingSink.LogEvents(log4net.Core.LoggingEvent[])">
+ <summary>
+ Delivers logging events to the remote sink
+ </summary>
+ <param name="events">Array of events to log.</param>
+ <remarks>
+ <para>
+ Delivers logging events to the remote sink
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender">
+ <summary>
+ Appender that rolls log files based on size or date or both.
+ </summary>
+ <remarks>
+ <para>
+ RollingFileAppender can roll log files based on size or date or both
+ depending on the setting of the <see cref="P:log4net.Appender.RollingFileAppender.RollingStyle"/> property.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Size"/> the log file will be rolled
+ once its size exceeds the <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/>.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Date"/> the log file will be rolled
+ once the date boundary specified in the <see cref="P:log4net.Appender.RollingFileAppender.DatePattern"/> property
+ is crossed.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Composite"/> the log file will be
+ rolled once the date boundary specified in the <see cref="P:log4net.Appender.RollingFileAppender.DatePattern"/> property
+ is crossed, but within a date boundary the file will also be rolled
+ once its size exceeds the <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/>.
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Once"/> the log file will be rolled when
+ the appender is configured. This effectively means that the log file can be
+ rolled once per program execution.
+ </para>
+ <para>
+ A of few additional optional features have been added:
+ <list type="bullet">
+ <item>Attach date pattern for current log file <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/></item>
+ <item>Backup number increments for newer files <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/></item>
+ <item>Infinite number of backups by file size <see cref="P:log4net.Appender.RollingFileAppender.MaxSizeRollBackups"/></item>
+ </list>
+ </para>
+
+ <note>
+ <para>
+ For large or infinite numbers of backup files a <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/>
+ greater than zero is highly recommended, otherwise all the backup files need
+ to be renamed each time a new backup is created.
+ </para>
+ <para>
+ When Date/Time based rolling is used setting <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/>
+ to <see langword="true"/> will reduce the number of file renamings to few or none.
+ </para>
+ </note>
+
+ <note type="caution">
+ <para>
+ Changing <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/> or <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> without clearing
+ the log file directory of backup files will cause unexpected and unwanted side effects.
+ </para>
+ </note>
+
+ <para>
+ If Date/Time based rolling is enabled this appender will attempt to roll existing files
+ in the directory without a Date/Time tag based on the last write date of the base log file.
+ The appender only rolls the log file when a message is logged. If Date/Time based rolling
+ is enabled then the appender will not roll the log file at the Date/Time boundary but
+ at the point when the next message is logged after the boundary has been crossed.
+ </para>
+
+ <para>
+ The <see cref="T:log4net.Appender.RollingFileAppender"/> extends the <see cref="T:log4net.Appender.FileAppender"/> and
+ has the same behavior when opening the log file.
+ The appender will first try to open the file for writing when <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>
+ is called. This will typically be during configuration.
+ If the file cannot be opened for writing the appender will attempt
+ to open the file again each time a message is logged to the appender.
+ If the file cannot be opened for writing when a message is logged then
+ the message will be discarded by this appender.
+ </para>
+ <para>
+ When rolling a backup file necessitates deleting an older backup file the
+ file to be deleted is moved to a temporary name before being deleted.
+ </para>
+
+ <note type="caution">
+ <para>
+ A maximum number of backup files when rolling on date/time boundaries is not supported.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ <author>Edward Smit</author>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.RollingFileAppender"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.SetQWForFiles(System.IO.TextWriter)">
+ <summary>
+ Sets the quiet writer being used.
+ </summary>
+ <remarks>
+ This method can be overridden by sub classes.
+ </remarks>
+ <param name="writer">the writer to set</param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Write out a logging event.
+ </summary>
+ <param name="loggingEvent">the event to write to file.</param>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.Append(log4net.Core.LoggingEvent[])">
+ <summary>
+ Write out an array of logging events.
+ </summary>
+ <param name="loggingEvents">the events to write to file.</param>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.AdjustFileBeforeAppend">
+ <summary>
+ Performs any required rolling before outputting the next event
+ </summary>
+ <remarks>
+ <para>
+ Handles append time behavior for RollingFileAppender. This checks
+ if a roll over either by date (checked first) or time (checked second)
+ is need and then appends to the file last.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.OpenFile(System.String,System.Boolean)">
+ <summary>
+ Creates and opens the file for logging. If <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/>
+ is false then the fully qualified name is determined and used.
+ </summary>
+ <param name="fileName">the name of the file to open</param>
+ <param name="append">true to append to existing file</param>
+ <remarks>
+ <para>This method will ensure that the directory structure
+ for the <paramref name="fileName"/> specified exists.</para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetNextOutputFileName(System.String)">
+ <summary>
+ Get the current output file name
+ </summary>
+ <param name="fileName">the base file name</param>
+ <returns>the output file name</returns>
+ <remarks>
+ The output file name is based on the base fileName specified.
+ If <see cref="P:log4net.Appender.RollingFileAppender.StaticLogFileName"/> is set then the output
+ file name is the same as the base file passed in. Otherwise
+ the output file depends on the date pattern, on the count
+ direction or both.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.DetermineCurSizeRollBackups">
+ <summary>
+ Determines curSizeRollBackups (only within the current roll point)
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetWildcardPatternForFile(System.String)">
+ <summary>
+ Generates a wildcard pattern that can be used to find all files
+ that are similar to the base file name.
+ </summary>
+ <param name="baseFileName"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.GetExistingFiles(System.String)">
+ <summary>
+ Builds a list of filenames for all files matching the base filename plus a file
+ pattern.
+ </summary>
+ <param name="baseFilePath"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverIfDateBoundaryCrossing">
+ <summary>
+ Initiates a roll over if needed for crossing a date boundary since the last run.
+ </summary>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ExistingInit">
+ <summary>
+ Initializes based on existing conditions at time of <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>.
+ </summary>
+ <remarks>
+ <para>
+ Initializes based on existing conditions at time of <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/>.
+ The following is done
+ <list type="bullet">
+ <item>determine curSizeRollBackups (only within the current roll point)</item>
+ <item>initiates a roll over if needed for crossing a date boundary since the last run.</item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.InitializeFromOneFile(System.String,System.String)">
+ <summary>
+ Does the work of bumping the 'current' file counter higher
+ to the highest count when an incremental file name is seen.
+ The highest count is either the first file (when count direction
+ is greater than 0) or the last file (when count direction less than 0).
+ In either case, we want to know the highest count that is present.
+ </summary>
+ <param name="baseFile"></param>
+ <param name="curFileName"></param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.InitializeRollBackups(System.String,System.Collections.ArrayList)">
+ <summary>
+ Takes a list of files and a base file name, and looks for
+ 'incremented' versions of the base file. Bumps the max
+ count up to the highest count seen.
+ </summary>
+ <param name="baseFile"></param>
+ <param name="arrayFiles"></param>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ComputeCheckPeriod(System.String)">
+ <summary>
+ Calculates the RollPoint for the datePattern supplied.
+ </summary>
+ <param name="datePattern">the date pattern to calculate the check period for</param>
+ <returns>The RollPoint that is most accurate for the date pattern supplied</returns>
+ <remarks>
+ Essentially the date pattern is examined to determine what the
+ most suitable roll point is. The roll point chosen is the roll point
+ with the smallest period that can be detected using the date pattern
+ supplied. i.e. if the date pattern only outputs the year, month, day
+ and hour then the smallest roll point that can be detected would be
+ and hourly roll point as minutes could not be detected.
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.RollingFileAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Sets initial conditions including date/time roll over information, first check,
+ scheduledFilename, and calls <see cref="M:log4net.Appender.RollingFileAppender.ExistingInit"/> to initialize
+ the current number of backups.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverTime(System.Boolean)">
+ <summary>
+ Rollover the file(s) to date/time tagged file(s).
+ </summary>
+ <param name="fileIsOpen">set to true if the file to be rolled is currently open</param>
+ <remarks>
+ <para>
+ Rollover the file(s) to date/time tagged file(s).
+ Resets curSizeRollBackups.
+ If fileIsOpen is set then the new file is opened (through SafeOpenFile).
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollFile(System.String,System.String)">
+ <summary>
+ Renames file <paramref name="fromFile"/> to file <paramref name="toFile"/>.
+ </summary>
+ <param name="fromFile">Name of existing file to roll.</param>
+ <param name="toFile">New name for file.</param>
+ <remarks>
+ <para>
+ Renames file <paramref name="fromFile"/> to file <paramref name="toFile"/>. It
+ also checks for existence of target file and deletes if it does.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.FileExists(System.String)">
+ <summary>
+ Test if a file exists at a specified path
+ </summary>
+ <param name="path">the path to the file</param>
+ <returns>true if the file exists</returns>
+ <remarks>
+ <para>
+ Test if a file exists at a specified path
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.DeleteFile(System.String)">
+ <summary>
+ Deletes the specified file if it exists.
+ </summary>
+ <param name="fileName">The file to delete.</param>
+ <remarks>
+ <para>
+ Delete a file if is exists.
+ The file is first moved to a new filename then deleted.
+ This allows the file to be removed even when it cannot
+ be deleted, but it still can be moved.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverSize">
+ <summary>
+ Implements file roll base on file size.
+ </summary>
+ <remarks>
+ <para>
+ If the maximum number of size based backups is reached
+ (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
+ file is deleted -- its index determined by the sign of countDirection.
+ If <c>countDirection</c> &lt; 0, then files
+ {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
+ are renamed to {<c>File.2</c>, ...,
+ <c>File.curSizeRollBackups</c>}. Moreover, <c>File</c> is
+ renamed <c>File.1</c> and closed.
+ </para>
+ <para>
+ A new file is created to receive further log output.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> is equal to zero, then the
+ <c>File</c> is truncated with no backup files created.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
+ renamed if needed and no files are deleted.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.RollOverRenameFiles(System.String)">
+ <summary>
+ Implements file roll.
+ </summary>
+ <param name="baseFileName">the base name to rename</param>
+ <remarks>
+ <para>
+ If the maximum number of size based backups is reached
+ (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the oldest
+ file is deleted -- its index determined by the sign of countDirection.
+ If <c>countDirection</c> &lt; 0, then files
+ {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
+ are renamed to {<c>File.2</c>, ...,
+ <c>File.curSizeRollBackups</c>}.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> is equal to zero, then the
+ <c>File</c> is truncated with no backup files created.
+ </para>
+ <para>
+ If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
+ renamed if needed and no files are deleted.
+ </para>
+ <para>
+ This is called by <see cref="M:log4net.Appender.RollingFileAppender.RollOverSize"/> to rename the files.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.RollingFileAppender.NextCheckDate(System.DateTime,log4net.Appender.RollingFileAppender.RollPoint)">
+ <summary>
+ Get the start time of the next window for the current rollpoint
+ </summary>
+ <param name="currentDateTime">the current date</param>
+ <param name="rollPoint">the type of roll point we are working with</param>
+ <returns>the start time for the next roll point an interval after the currentDateTime date</returns>
+ <remarks>
+ <para>
+ Returns the date of the next roll point after the currentDateTime date passed to the method.
+ </para>
+ <para>
+ The basic strategy is to subtract the time parts that are less significant
+ than the rollpoint from the current time. This should roll the time back to
+ the start of the time window for the current rollpoint. Then we add 1 window
+ worth of time and get the start time of the next window for the rollpoint.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_dateTime">
+ <summary>
+ This object supplies the current date/time. Allows test code to plug in
+ a method to control this class when testing date/time based rolling.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_datePattern">
+ <summary>
+ The date pattern. By default, the pattern is set to <c>".yyyy-MM-dd"</c>
+ meaning daily rollover.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_scheduledFilename">
+ <summary>
+ The actual formatted filename that is currently being written to
+ or will be the file transferred to on roll over
+ (based on staticLogFileName).
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_nextCheck">
+ <summary>
+ The timestamp when we shall next recompute the filename.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_now">
+ <summary>
+ Holds date of last roll over
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollPoint">
+ <summary>
+ The type of rolling done
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_maxFileSize">
+ <summary>
+ The default maximum file size is 10MB
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_maxSizeRollBackups">
+ <summary>
+ There is zero backup files by default
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_curSizeRollBackups">
+ <summary>
+ How many sized based backups have been made so far
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_countDirection">
+ <summary>
+ The rolling file count direction.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollingStyle">
+ <summary>
+ The rolling mode used in this appender.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollDate">
+ <summary>
+ Cache flag set if we are rolling by date.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_rollSize">
+ <summary>
+ Cache flag set if we are rolling by size.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_staticLogFileName">
+ <summary>
+ Value indicating whether to always log to the same file.
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.m_baseFileName">
+ <summary>
+ FileName provided in configuration. Used for rolling properly
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.s_date1970">
+ <summary>
+ The 1st of January 1970 in UTC
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.DatePattern">
+ <summary>
+ Gets or sets the date pattern to be used for generating file names
+ when rolling over on date.
+ </summary>
+ <value>
+ The date pattern to be used for generating file names when rolling
+ over on date.
+ </value>
+ <remarks>
+ <para>
+ Takes a string in the same format as expected by
+ <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/>.
+ </para>
+ <para>
+ This property determines the rollover schedule when rolling over
+ on date.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaxSizeRollBackups">
+ <summary>
+ Gets or sets the maximum number of backup files that are kept before
+ the oldest is erased.
+ </summary>
+ <value>
+ The maximum number of backup files that are kept before the oldest is
+ erased.
+ </value>
+ <remarks>
+ <para>
+ If set to zero, then there will be no backup files and the log file
+ will be truncated when it reaches <see cref="P:log4net.Appender.RollingFileAppender.MaxFileSize"/>.
+ </para>
+ <para>
+ If a negative number is supplied then no deletions will be made. Note
+ that this could result in very slow performance as a large number of
+ files are rolled over unless <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> is used.
+ </para>
+ <para>
+ The maximum applies to <b>each</b> time based group of files and
+ <b>not</b> the total.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaxFileSize">
+ <summary>
+ Gets or sets the maximum size that the output file is allowed to reach
+ before being rolled over to backup files.
+ </summary>
+ <value>
+ The maximum size in bytes that the output file is allowed to reach before being
+ rolled over to backup files.
+ </value>
+ <remarks>
+ <para>
+ This property is equivalent to <see cref="P:log4net.Appender.RollingFileAppender.MaximumFileSize"/> except
+ that it is required for differentiating the setter taking a
+ <see cref="T:System.Int64"/> argument from the setter taking a <see cref="T:System.String"/>
+ argument.
+ </para>
+ <para>
+ The default maximum file size is 10MB (10*1024*1024).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.MaximumFileSize">
+ <summary>
+ Gets or sets the maximum size that the output file is allowed to reach
+ before being rolled over to backup files.
+ </summary>
+ <value>
+ The maximum size that the output file is allowed to reach before being
+ rolled over to backup files.
+ </value>
+ <remarks>
+ <para>
+ This property allows you to specify the maximum size with the
+ suffixes "KB", "MB" or "GB" so that the size is interpreted being
+ expressed respectively in kilobytes, megabytes or gigabytes.
+ </para>
+ <para>
+ For example, the value "10KB" will be interpreted as 10240 bytes.
+ </para>
+ <para>
+ The default maximum file size is 10MB.
+ </para>
+ <para>
+ If you have the option to set the maximum file size programmatically
+ consider using the <see cref="P:log4net.Appender.RollingFileAppender.MaxFileSize"/> property instead as this
+ allows you to set the size in bytes as a <see cref="T:System.Int64"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.CountDirection">
+ <summary>
+ Gets or sets the rolling file count direction.
+ </summary>
+ <value>
+ The rolling file count direction.
+ </value>
+ <remarks>
+ <para>
+ Indicates if the current file is the lowest numbered file or the
+ highest numbered file.
+ </para>
+ <para>
+ By default newer files have lower numbers (<see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &lt; 0),
+ i.e. log.1 is most recent, log.5 is the 5th backup, etc...
+ </para>
+ <para>
+ <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &gt;= 0 does the opposite i.e.
+ log.1 is the first backup made, log.5 is the 5th backup made, etc.
+ For infinite backups use <see cref="P:log4net.Appender.RollingFileAppender.CountDirection"/> &gt;= 0 to reduce
+ rollover costs.
+ </para>
+ <para>The default file count direction is -1.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.RollingStyle">
+ <summary>
+ Gets or sets the rolling style.
+ </summary>
+ <value>The rolling style.</value>
+ <remarks>
+ <para>
+ The default rolling style is <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Composite"/>.
+ </para>
+ <para>
+ When set to <see cref="F:log4net.Appender.RollingFileAppender.RollingMode.Once"/> this appender's
+ <see cref="P:log4net.Appender.FileAppender.AppendToFile"/> property is set to <c>false</c>, otherwise
+ the appender would append to a single file rather than rolling
+ the file each time it is opened.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.StaticLogFileName">
+ <summary>
+ Gets or sets a value indicating whether to always log to
+ the same file.
+ </summary>
+ <value>
+ <c>true</c> if always should be logged to the same file, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ By default file.log is always the current file. Optionally
+ file.log.yyyy-mm-dd for current formatted datePattern can by the currently
+ logging file (or file.log.curSizeRollBackup or even
+ file.log.yyyy-mm-dd.curSizeRollBackup).
+ </para>
+ <para>
+ This will make time based rollovers with a large number of backups
+ much faster as the appender it won't have to rename all the backups!
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.RollingMode">
+ <summary>
+ Style of rolling to use
+ </summary>
+ <remarks>
+ <para>
+ Style of rolling to use
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Once">
+ <summary>
+ Roll files once per program execution
+ </summary>
+ <remarks>
+ <para>
+ Roll files once per program execution.
+ Well really once each time this appender is
+ configured.
+ </para>
+ <para>
+ Setting this option also sets <c>AppendToFile</c> to
+ <c>false</c> on the <c>RollingFileAppender</c>, otherwise
+ this appender would just be a normal file appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Size">
+ <summary>
+ Roll files based only on the size of the file
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Date">
+ <summary>
+ Roll files based only on the date
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollingMode.Composite">
+ <summary>
+ Roll files based on both the size and date of the file
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.RollPoint">
+ <summary>
+ The code assumes that the following 'time' constants are in a increasing sequence.
+ </summary>
+ <remarks>
+ <para>
+ The code assumes that the following 'time' constants are in a increasing sequence.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.InvalidRollPoint">
+ <summary>
+ Roll the log not based on the date
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfMinute">
+ <summary>
+ Roll the log for each minute
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfHour">
+ <summary>
+ Roll the log for each hour
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.HalfDay">
+ <summary>
+ Roll the log twice a day (midday and midnight)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfDay">
+ <summary>
+ Roll the log each day (midnight)
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfWeek">
+ <summary>
+ Roll the log each week
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.RollingFileAppender.RollPoint.TopOfMonth">
+ <summary>
+ Roll the log each month
+ </summary>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.IDateTime">
+ <summary>
+ This interface is used to supply Date/Time information to the <see cref="T:log4net.Appender.RollingFileAppender"/>.
+ </summary>
+ <remarks>
+ This interface is used to supply Date/Time information to the <see cref="T:log4net.Appender.RollingFileAppender"/>.
+ Used primarily to allow test classes to plug themselves in so they can
+ supply test date/times.
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.IDateTime.Now">
+ <summary>
+ Gets the <i>current</i> time.
+ </summary>
+ <value>The <i>current</i> time.</value>
+ <remarks>
+ <para>
+ Gets the <i>current</i> time.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.RollingFileAppender.DefaultDateTime">
+ <summary>
+ Default implementation of <see cref="T:log4net.Appender.RollingFileAppender.IDateTime"/> that returns the current time.
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.RollingFileAppender.DefaultDateTime.Now">
+ <summary>
+ Gets the <b>current</b> time.
+ </summary>
+ <value>The <b>current</b> time.</value>
+ <remarks>
+ <para>
+ Gets the <b>current</b> time.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpAppender">
+ <summary>
+ Send an e-mail when a specific logging event occurs, typically on errors
+ or fatal errors.
+ </summary>
+ <remarks>
+ <para>
+ The number of logging events delivered in this e-mail depend on
+ the value of <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option. The
+ <see cref="T:log4net.Appender.SmtpAppender"/> keeps only the last
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> logging events in its
+ cyclic buffer. This keeps memory requirements at a reasonable level while
+ still delivering useful application context.
+ </para>
+ <note type="caution">
+ Authentication and setting the server Port are only available on the MS .NET 1.1 runtime.
+ For these features to be enabled you need to ensure that you are using a version of
+ the log4net assembly that is built against the MS .NET 1.1 framework and that you are
+ running the your application on the MS .NET 1.1 runtime. On all other platforms only sending
+ unauthenticated messages to a server listening on port 25 (the default) is supported.
+ </note>
+ <para>
+ Authentication is supported by setting the <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> property to
+ either <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> or <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/>.
+ If using <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> authentication then the <see cref="P:log4net.Appender.SmtpAppender.Username"/>
+ and <see cref="P:log4net.Appender.SmtpAppender.Password"/> properties must also be set.
+ </para>
+ <para>
+ To set the SMTP server port use the <see cref="P:log4net.Appender.SmtpAppender.Port"/> property. The default port is 25.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </summary>
+ <param name="events">The logging events to send.</param>
+ </member>
+ <member name="M:log4net.Appender.SmtpAppender.SendEmail(System.String)">
+ <summary>
+ Send the email message
+ </summary>
+ <param name="messageBody">the body text to include in the mail</param>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.To">
+ <summary>
+ Gets or sets a semicolon-delimited list of recipient e-mail addresses.
+ </summary>
+ <value>
+ A semicolon-delimited list of e-mail addresses.
+ </value>
+ <remarks>
+ <para>
+ A semicolon-delimited list of recipient e-mail addresses.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.From">
+ <summary>
+ Gets or sets the e-mail address of the sender.
+ </summary>
+ <value>
+ The e-mail address of the sender.
+ </value>
+ <remarks>
+ <para>
+ The e-mail address of the sender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Subject">
+ <summary>
+ Gets or sets the subject line of the e-mail message.
+ </summary>
+ <value>
+ The subject line of the e-mail message.
+ </value>
+ <remarks>
+ <para>
+ The subject line of the e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.SmtpHost">
+ <summary>
+ Gets or sets the name of the SMTP relay mail server to use to send
+ the e-mail messages.
+ </summary>
+ <value>
+ The name of the e-mail relay server. If SmtpServer is not set, the
+ name of the local SMTP server is used.
+ </value>
+ <remarks>
+ <para>
+ The name of the e-mail relay server. If SmtpServer is not set, the
+ name of the local SMTP server is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.LocationInfo">
+ <summary>
+ Obsolete
+ </summary>
+ <remarks>
+ Use the BufferingAppenderSkeleton Fix methods instead
+ </remarks>
+ <remarks>
+ <para>
+ Obsolete property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Authentication">
+ <summary>
+ The mode to use to authentication with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ Valid Authentication mode values are: <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None"/>,
+ <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>, and <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/>.
+ The default value is <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None"/>. When using
+ <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/> you must specify the <see cref="P:log4net.Appender.SmtpAppender.Username"/>
+ and <see cref="P:log4net.Appender.SmtpAppender.Password"/> to use to authenticate.
+ When using <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm"/> the Windows credentials for the current
+ thread, if impersonating, or the process will be used to authenticate.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Username">
+ <summary>
+ The username to use to authenticate with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ A <see cref="P:log4net.Appender.SmtpAppender.Username"/> and <see cref="P:log4net.Appender.SmtpAppender.Password"/> must be specified when
+ <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> is set to <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>,
+ otherwise the username will be ignored.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Password">
+ <summary>
+ The password to use to authenticate with the SMTP server
+ </summary>
+ <remarks>
+ <note type="caution">Authentication is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ A <see cref="P:log4net.Appender.SmtpAppender.Username"/> and <see cref="P:log4net.Appender.SmtpAppender.Password"/> must be specified when
+ <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> is set to <see cref="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic"/>,
+ otherwise the password will be ignored.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Port">
+ <summary>
+ The port on which the SMTP server is listening
+ </summary>
+ <remarks>
+ <note type="caution">Server Port is only available on the MS .NET 1.1 runtime.</note>
+ <para>
+ The port on which the SMTP server is listening. The default
+ port is <c>25</c>. The Port can only be changed when running on
+ the MS .NET 1.1 runtime.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.Priority">
+ <summary>
+ Gets or sets the priority of the e-mail message
+ </summary>
+ <value>
+ One of the <see cref="T:System.Web.Mail.MailPriority"/> values.
+ </value>
+ <remarks>
+ <para>
+ Sets the priority of the e-mails generated by this
+ appender. The default priority is <see cref="F:System.Web.Mail.MailPriority.Normal"/>.
+ </para>
+ <para>
+ If you are using this appender to report errors then
+ you may want to set the priority to <see cref="F:System.Web.Mail.MailPriority.High"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpAppender.SmtpAuthentication">
+ <summary>
+ Values for the <see cref="P:log4net.Appender.SmtpAppender.Authentication"/> property.
+ </summary>
+ <remarks>
+ <para>
+ SMTP authentication modes.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.None">
+ <summary>
+ No authentication
+ </summary>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Basic">
+ <summary>
+ Basic authentication.
+ </summary>
+ <remarks>
+ Requires a username and password to be supplied
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpAppender.SmtpAuthentication.Ntlm">
+ <summary>
+ Integrated authentication
+ </summary>
+ <remarks>
+ Uses the Windows credentials from the current thread or process to authenticate.
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.SmtpPickupDirAppender">
+ <summary>
+ Send an email when a specific logging event occurs, typically on errors
+ or fatal errors. Rather than sending via smtp it writes a file into the
+ directory specified by <see cref="P:log4net.Appender.SmtpPickupDirAppender.PickupDir"/>. This allows services such
+ as the IIS SMTP agent to manage sending the messages.
+ </summary>
+ <remarks>
+ <para>
+ The configuration for this appender is identical to that of the <c>SMTPAppender</c>,
+ except that instead of specifying the <c>SMTPAppender.SMTPHost</c> you specify
+ <see cref="P:log4net.Appender.SmtpPickupDirAppender.PickupDir"/>.
+ </para>
+ <para>
+ The number of logging events delivered in this e-mail depend on
+ the value of <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> option. The
+ <see cref="T:log4net.Appender.SmtpPickupDirAppender"/> keeps only the last
+ <see cref="P:log4net.Appender.BufferingAppenderSkeleton.BufferSize"/> logging events in its
+ cyclic buffer. This keeps memory requirements at a reasonable level while
+ still delivering useful application context.
+ </para>
+ </remarks>
+ <author>Niall Daley</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.SendBuffer(log4net.Core.LoggingEvent[])">
+ <summary>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </summary>
+ <param name="events">The logging events to send.</param>
+ <remarks>
+ <para>
+ Sends the contents of the cyclic buffer as an e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions">
+ <summary>
+ Activate the options on this appender.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.SmtpPickupDirAppender.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.SmtpPickupDirAppender.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.SmtpPickupDirAppender.m_securityContext">
+ <summary>
+ The security context to use for privileged calls
+ </summary>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.To">
+ <summary>
+ Gets or sets a semicolon-delimited list of recipient e-mail addresses.
+ </summary>
+ <value>
+ A semicolon-delimited list of e-mail addresses.
+ </value>
+ <remarks>
+ <para>
+ A semicolon-delimited list of e-mail addresses.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.From">
+ <summary>
+ Gets or sets the e-mail address of the sender.
+ </summary>
+ <value>
+ The e-mail address of the sender.
+ </value>
+ <remarks>
+ <para>
+ The e-mail address of the sender.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.Subject">
+ <summary>
+ Gets or sets the subject line of the e-mail message.
+ </summary>
+ <value>
+ The subject line of the e-mail message.
+ </value>
+ <remarks>
+ <para>
+ The subject line of the e-mail message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.PickupDir">
+ <summary>
+ Gets or sets the path to write the messages to.
+ </summary>
+ <remarks>
+ <para>
+ Gets or sets the path to write the messages to. This should be the same
+ as that used by the agent sending the messages.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> used to write to the pickup directory.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> used to write to the pickup directory.
+ </value>
+ <remarks>
+ <para>
+ Unless a <see cref="P:log4net.Appender.SmtpPickupDirAppender.SecurityContext"/> specified here for this appender
+ the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is queried for the
+ security context to use. The default behavior is to use the security context
+ of the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.SmtpPickupDirAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender">
+ <summary>
+ Appender that allows clients to connect via Telnet to receive log messages
+ </summary>
+ <remarks>
+ <para>
+ The TelnetAppender accepts socket connections and streams logging messages
+ back to the client.
+ The output is provided in a telnet-friendly way so that a log can be monitored
+ over a TCP/IP socket.
+ This allows simple remote monitoring of application logging.
+ </para>
+ <para>
+ The default <see cref="P:log4net.Appender.TelnetAppender.Port"/> is 23 (the telnet port).
+ </para>
+ </remarks>
+ <author>Keith Long</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.OnClose">
+ <summary>
+ Overrides the parent method to close the socket handler
+ </summary>
+ <remarks>
+ <para>
+ Closes all the outstanding connections.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.ActivateOptions">
+ <summary>
+ Initialize the appender based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Appender.TelnetAppender.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Create the socket handler and wait for connections
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to each connected client.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to each connected client.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.Port">
+ <summary>
+ Gets or sets the TCP port number on which this <see cref="T:log4net.Appender.TelnetAppender"/> will listen for connections.
+ </summary>
+ <value>
+ An integer value in the range <see cref="F:System.Net.IPEndPoint.MinPort"/> to <see cref="F:System.Net.IPEndPoint.MaxPort"/>
+ indicating the TCP port number on which this <see cref="T:log4net.Appender.TelnetAppender"/> will listen for connections.
+ </value>
+ <remarks>
+ <para>
+ The default value is 23 (the telnet port).
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The value specified is less than <see cref="F:System.Net.IPEndPoint.MinPort"/>
+ or greater than <see cref="F:System.Net.IPEndPoint.MaxPort"/>.</exception>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender.SocketHandler">
+ <summary>
+ Helper class to manage connected clients
+ </summary>
+ <remarks>
+ <para>
+ The SocketHandler class is used to accept connections from
+ clients. It is threaded so that clients can connect/disconnect
+ asynchronously.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.#ctor(System.Int32)">
+ <summary>
+ Opens a new server port on <paramref ref="port"/>
+ </summary>
+ <param name="port">the local port to listen on for connections</param>
+ <remarks>
+ <para>
+ Creates a socket handler on the specified local server port.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.Send(System.String)">
+ <summary>
+ Sends a string message to each of the connected clients
+ </summary>
+ <param name="message">the text to send</param>
+ <remarks>
+ <para>
+ Sends a string message to each of the connected clients
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.AddClient(log4net.Appender.TelnetAppender.SocketHandler.SocketClient)">
+ <summary>
+ Add a client to the internal clients list
+ </summary>
+ <param name="client">client to add</param>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.RemoveClient(log4net.Appender.TelnetAppender.SocketHandler.SocketClient)">
+ <summary>
+ Remove a client from the internal clients list
+ </summary>
+ <param name="client">client to remove</param>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.OnConnect(System.IAsyncResult)">
+ <summary>
+ Callback used to accept a connection on the server socket
+ </summary>
+ <param name="asyncResult">The result of the asynchronous operation</param>
+ <remarks>
+ <para>
+ On connection adds to the list of connections
+ if there are two many open connections you will be disconnected
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.Dispose">
+ <summary>
+ Close all network connections
+ </summary>
+ <remarks>
+ <para>
+ Make sure we close all network connections
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TelnetAppender.SocketHandler.HasConnections">
+ <summary>
+ Test if this handler has active connections
+ </summary>
+ <value>
+ <c>true</c> if this handler has active connections
+ </value>
+ <remarks>
+ <para>
+ This property will be <c>true</c> while this handler has
+ active connections, that is at least one connection that
+ the handler will attempt to send a message to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TelnetAppender.SocketHandler.SocketClient">
+ <summary>
+ Class that represents a client connected to this handler
+ </summary>
+ <remarks>
+ <para>
+ Class that represents a client connected to this handler
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.#ctor(System.Net.Sockets.Socket)">
+ <summary>
+ Create this <see cref="T:log4net.Appender.TelnetAppender.SocketHandler.SocketClient"/> for the specified <see cref="T:System.Net.Sockets.Socket"/>
+ </summary>
+ <param name="socket">the client's socket</param>
+ <remarks>
+ <para>
+ Opens a stream writer on the socket.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.Send(System.String)">
+ <summary>
+ Write a string to the client
+ </summary>
+ <param name="message">string to send</param>
+ <remarks>
+ <para>
+ Write a string to the client
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TelnetAppender.SocketHandler.SocketClient.Dispose">
+ <summary>
+ Cleanup the clients connection
+ </summary>
+ <remarks>
+ <para>
+ Close the socket connection.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Appender.TraceAppender">
+ <summary>
+ Appends log events to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </summary>
+ <remarks>
+ <para>
+ The application configuration file can be used to control what listeners
+ are actually used. See the MSDN documentation for the
+ <see cref="T:System.Diagnostics.Trace"/> class for details on configuring the
+ trace system.
+ </para>
+ <para>
+ Events are written using the <c>System.Diagnostics.Trace.Write(string,string)</c>
+ method. The event's logger name is passed as the value for the category name to the Write method.
+ </para>
+ <para>
+ <b>Compact Framework</b><br/>
+ The Compact Framework does not support the <see cref="T:System.Diagnostics.Trace"/>
+ class for any operation except <c>Assert</c>. When using the Compact Framework this
+ appender will write to the <see cref="T:System.Diagnostics.Debug"/> system rather than
+ the Trace system. This appender will therefore behave like the <see cref="T:log4net.Appender.DebugAppender"/>.
+ </para>
+ </remarks>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TraceAppender"/>.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Appender.TraceAppender"/>
+ with a specified layout.
+ </summary>
+ <param name="layout">The layout to use with this appender.</param>
+ <remarks>
+ <para>
+ Obsolete constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Appender.TraceAppender.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Writes the logging event to the <see cref="T:System.Diagnostics.Trace"/> system.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Appender.TraceAppender.m_immediateFlush">
+ <summary>
+ Immediate flush means that the underlying writer or output stream
+ will be flushed at the end of each append operation.
+ </summary>
+ <remarks>
+ <para>
+ Immediate flush is slower but ensures that each append request is
+ actually written. If <see cref="P:log4net.Appender.TraceAppender.ImmediateFlush"/> is set to
+ <c>false</c>, then there is a good chance that the last few
+ logs events are not actually written to persistent media if and
+ when the application crashes.
+ </para>
+ <para>
+ The default value is <c>true</c>.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TraceAppender.ImmediateFlush">
+ <summary>
+ Gets or sets a value that indicates whether the appender will
+ flush at the end of each write.
+ </summary>
+ <remarks>
+ <para>The default behavior is to flush at the end of each
+ write. If the option is set to<c>false</c>, then the underlying
+ stream can defer writing to physical medium to a later time.
+ </para>
+ <para>
+ Avoiding the flush operation at the end of each append results
+ in a performance gain of 10 to 20 percent. However, there is safety
+ trade-off involved in skipping flushing. Indeed, when flushing is
+ skipped, then it is likely that the last few log events will not
+ be recorded on disk when the application exits. This is a high
+ price to pay even for a 20% performance gain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Appender.TraceAppender.RequiresLayout">
+ <summary>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ This appender requires a <see cref="N:log4net.Layout"/> to be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.AliasDomainAttribute">
+ <summary>
+ Assembly level attribute that specifies a domain to alias to this assembly's repository.
+ </summary>
+ <remarks>
+ <para>
+ <b>AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute.</b>
+ </para>
+ <para>
+ An assembly's logger repository is defined by its <see cref="T:log4net.Config.DomainAttribute"/>,
+ however this can be overridden by an assembly loaded before the target assembly.
+ </para>
+ <para>
+ An assembly can alias another assembly's domain to its repository by
+ specifying this attribute with the name of the target domain.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may be used
+ as many times as necessary to alias all the required domains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.AliasRepositoryAttribute">
+ <summary>
+ Assembly level attribute that specifies a repository to alias to this assembly's repository.
+ </summary>
+ <remarks>
+ <para>
+ An assembly's logger repository is defined by its <see cref="T:log4net.Config.RepositoryAttribute"/>,
+ however this can be overridden by an assembly loaded before the target assembly.
+ </para>
+ <para>
+ An assembly can alias another assembly's repository to its repository by
+ specifying this attribute with the name of the target repository.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may be used
+ as many times as necessary to alias all the required repositories.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.AliasRepositoryAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasRepositoryAttribute"/> class with
+ the specified repository to alias to this assembly's repository.
+ </summary>
+ <param name="name">The repository to alias to this assemby's repository.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasRepositoryAttribute"/> class with
+ the specified repository to alias to this assembly's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.AliasRepositoryAttribute.Name">
+ <summary>
+ Gets or sets the repository to alias to this assemby's repository.
+ </summary>
+ <value>
+ The repository to alias to this assemby's repository.
+ </value>
+ <remarks>
+ <para>
+ The name of the repository to alias to this assemby's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.AliasDomainAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.AliasDomainAttribute"/> class with
+ the specified domain to alias to this assembly's repository.
+ </summary>
+ <param name="name">The domain to alias to this assemby's repository.</param>
+ <remarks>
+ <para>
+ Obsolete. Use <see cref="T:log4net.Config.AliasRepositoryAttribute"/> instead of <see cref="T:log4net.Config.AliasDomainAttribute"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.BasicConfigurator">
+ <summary>
+ Use this class to quickly configure a <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </summary>
+ <remarks>
+ <para>
+ Allows very simple programmatic configuration of log4net.
+ </para>
+ <para>
+ Only one appender can be configured using this configurator.
+ The appender is set at the root of the hierarchy and all logging
+ events will be delivered to that appender.
+ </para>
+ <para>
+ Appenders can also implement the <see cref="T:log4net.Core.IOptionHandler"/> interface. Therefore
+ they would require that the <see cref="M:log4net.Core.IOptionHandler.ActivateOptions"/> method
+ be called after the appenders properties have been configured.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.BasicConfigurator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure">
+ <summary>
+ Initializes the log4net system with a default configuration.
+ </summary>
+ <remarks>
+ <para>
+ Initializes the log4net logging system using a <see cref="T:log4net.Appender.ConsoleAppender"/>
+ that will write to <c>Console.Out</c>. The log messages are
+ formatted using the <see cref="T:log4net.Layout.PatternLayout"/> layout object
+ with the <see cref="F:log4net.Layout.PatternLayout.DetailConversionPattern"/>
+ layout style.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initializes the log4net system using the specified appender.
+ </summary>
+ <param name="appender">The appender to use to log all logging events.</param>
+ <remarks>
+ <para>
+ Initializes the log4net system using the specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> with a default configuration.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Initializes the specified repository using a <see cref="T:log4net.Appender.ConsoleAppender"/>
+ that will write to <c>Console.Out</c>. The log messages are
+ formatted using the <see cref="T:log4net.Layout.PatternLayout"/> layout object
+ with the <see cref="F:log4net.Layout.PatternLayout.DetailConversionPattern"/>
+ layout style.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.BasicConfigurator.Configure(log4net.Repository.ILoggerRepository,log4net.Appender.IAppender)">
+ <summary>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified appender.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="appender">The appender to use to log all logging events.</param>
+ <remarks>
+ <para>
+ Initializes the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.ConfiguratorAttribute">
+ <summary>
+ Base class for all log4net configuration attributes.
+ </summary>
+ <remarks>
+ This is an abstract class that must be extended by
+ specific configurators. This attribute allows the
+ configurator to be parameterized by an assembly level
+ attribute.
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.#ctor(System.Int32)">
+ <summary>
+ Constructor used by subclasses.
+ </summary>
+ <param name="priority">the ordering priority for this configurator</param>
+ <remarks>
+ <para>
+ The <paramref name="priority"/> is used to order the configurator
+ attributes before they are invoked. Higher priority configurators are executed
+ before lower priority ones.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Abstract method implemented by a subclass. When this method is called
+ the subclass should configure the <paramref name="targetRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.ConfiguratorAttribute.CompareTo(System.Object)">
+ <summary>
+ Compare this instance to another ConfiguratorAttribute
+ </summary>
+ <param name="obj">the object to compare to</param>
+ <returns>see <see cref="M:System.IComparable.CompareTo(System.Object)"/></returns>
+ <remarks>
+ <para>
+ Compares the priorities of the two <see cref="T:log4net.Config.ConfiguratorAttribute"/> instances.
+ Sorts by priority in descending order. Objects with the same priority are
+ randomly ordered.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.DomainAttribute">
+ <summary>
+ Assembly level attribute that specifies the logging domain for the assembly.
+ </summary>
+ <remarks>
+ <para>
+ <b>DomainAttribute is obsolete. Use RepositoryAttribute instead of DomainAttribute.</b>
+ </para>
+ <para>
+ Assemblies are mapped to logging domains. Each domain has its own
+ logging repository. This attribute specified on the assembly controls
+ the configuration of the domain. The <see cref="P:log4net.Config.RepositoryAttribute.Name"/> property specifies the name
+ of the domain that this assembly is a part of. The <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/>
+ specifies the type of the repository objects to create for the domain. If
+ this attribute is not specified and a <see cref="P:log4net.Config.RepositoryAttribute.Name"/> is not specified
+ then the assembly will be part of the default shared logging domain.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may only be used
+ once per assembly.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.RepositoryAttribute">
+ <summary>
+ Assembly level attribute that specifies the logging repository for the assembly.
+ </summary>
+ <remarks>
+ <para>
+ Assemblies are mapped to logging repository. This attribute specified
+ on the assembly controls
+ the configuration of the repository. The <see cref="P:log4net.Config.RepositoryAttribute.Name"/> property specifies the name
+ of the repository that this assembly is a part of. The <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/>
+ specifies the type of the <see cref="T:log4net.Repository.ILoggerRepository"/> object
+ to create for the assembly. If this attribute is not specified or a <see cref="P:log4net.Config.RepositoryAttribute.Name"/>
+ is not specified then the assembly will be part of the default shared logging repository.
+ </para>
+ <para>
+ This attribute can only be specified on the assembly and may only be used
+ once per assembly.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.RepositoryAttribute.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.RepositoryAttribute"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.RepositoryAttribute.#ctor(System.String)">
+ <summary>
+ Initialize a new instance of the <see cref="T:log4net.Config.RepositoryAttribute"/> class
+ with the name of the repository.
+ </summary>
+ <param name="name">The name of the repository.</param>
+ <remarks>
+ <para>
+ Initialize the attribute with the name for the assembly's repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.RepositoryAttribute.Name">
+ <summary>
+ Gets or sets the name of the logging repository.
+ </summary>
+ <value>
+ The string name to use as the name of the repository associated with this
+ assembly.
+ </value>
+ <remarks>
+ <para>
+ This value does not have to be unique. Several assemblies can share the
+ same repository. They will share the logging configuration of the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.RepositoryAttribute.RepositoryType">
+ <summary>
+ Gets or sets the type of repository to create for this assembly.
+ </summary>
+ <value>
+ The type of repository to create for this assembly.
+ </value>
+ <remarks>
+ <para>
+ The type of the repository to create for the assembly.
+ The type must implement the <see cref="T:log4net.Repository.ILoggerRepository"/>
+ interface.
+ </para>
+ <para>
+ This will be the type of repository created when
+ the repository is created. If multiple assemblies reference the
+ same repository then the repository is only created once using the
+ <see cref="P:log4net.Config.RepositoryAttribute.RepositoryType"/> of the first assembly to call into the
+ repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DomainAttribute.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.DomainAttribute"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Obsolete. Use RepositoryAttribute instead of DomainAttribute.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DomainAttribute.#ctor(System.String)">
+ <summary>
+ Initialize a new instance of the <see cref="T:log4net.Config.DomainAttribute"/> class
+ with the name of the domain.
+ </summary>
+ <param name="name">The name of the domain.</param>
+ <remarks>
+ <para>
+ Obsolete. Use RepositoryAttribute instead of DomainAttribute.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.DOMConfigurator">
+ <summary>
+ Use this class to initialize the log4net environment using an Xml tree.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ Configures a <see cref="T:log4net.Repository.ILoggerRepository"/> using an Xml tree.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure">
+ <summary>
+ Automatically configures the log4net system based on the
+ application's configuration settings.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Automatically configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using settings
+ stored in the application's configuration file.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configures log4net using a <c>log4net</c> element
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified XML
+ element.
+ </summary>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(System.IO.Stream)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configStream">A stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ DOMConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.Stream)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configStream">The stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.ConfigureAndWatch(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the file specified, monitors the file for changes
+ and reloads the configuration if a change is detected.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.DOMConfigurator.ConfigureAndWatch(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the file specified,
+ monitors the file for changes and reloads the configuration if a change
+ is detected.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ <b>DOMConfigurator is obsolete. Use XmlConfigurator instead of DOMConfigurator.</b>
+ </para>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.DOMConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="T:log4net.Config.DOMConfiguratorAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </summary>
+ <remarks>
+ <para>
+ <b>AliasDomainAttribute is obsolete. Use AliasRepositoryAttribute instead of AliasDomainAttribute.</b>
+ </para>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Config.XmlConfiguratorAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </summary>
+ <remarks>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ <para>
+ If neither of the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> or <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>
+ properties are set the configuration is loaded from the application's .config file.
+ If set the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> property takes priority over the
+ <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> property. The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> property
+ specifies a path to a file to load the config from. The path is relative to the
+ application's base directory; <see cref="P:System.AppDomain.BaseDirectory"/>.
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> property is used as a postfix to the assembly file name.
+ The config file must be located in the application's base directory; <see cref="P:System.AppDomain.BaseDirectory"/>.
+ For example in a console application setting the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> to
+ <c>config</c> has the same effect as not specifying the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> or
+ <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> properties.
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.Watch"/> property can be set to cause the <see cref="T:log4net.Config.XmlConfigurator"/>
+ to watch the configuration file for changes.
+ </para>
+ <note>
+ <para>
+ Log4net will only look for assembly level configuration attributes once.
+ When using the log4net assembly level attributes to control the configuration
+ of log4net you must ensure that the first call to any of the
+ <see cref="T:log4net.Core.LoggerManager"/> methods is made from the assembly with the configuration
+ attributes.
+ </para>
+ <para>
+ If you cannot guarantee the order in which log4net calls will be made from
+ different assemblies you must use programmatic configuration instead, i.e.
+ call the <see cref="M:log4net.Config.XmlConfigurator.Configure"/> method directly.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Configure the repository using the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ The <paramref name="targetRepository"/> specified must extend the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>
+ class otherwise the <see cref="T:log4net.Config.XmlConfigurator"/> will not be able to
+ configure it.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="repository"/> does not extend <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.</exception>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromFile(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attempt to load configuration from the local file system
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromFile(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configure the specified repository using a <see cref="T:System.IO.FileInfo"/>
+ </summary>
+ <param name="targetRepository">The repository to configure.</param>
+ <param name="configFile">the FileInfo pointing to the config file</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfiguratorAttribute.ConfigureFromUri(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attempt to load configuration from a URI
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile">
+ <summary>
+ Gets or sets the filename of the configuration file.
+ </summary>
+ <value>
+ The filename of the configuration file.
+ </value>
+ <remarks>
+ <para>
+ If specified, this is the name of the configuration file to use with
+ the <see cref="T:log4net.Config.XmlConfigurator"/>. This file path is relative to the
+ <b>application base</b> directory (<see cref="P:System.AppDomain.BaseDirectory"/>).
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> takes priority over the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension">
+ <summary>
+ Gets or sets the extension of the configuration file.
+ </summary>
+ <value>
+ The extension of the configuration file.
+ </value>
+ <remarks>
+ <para>
+ If specified this is the extension for the configuration file.
+ The path to the config file is built by using the <b>application
+ base</b> directory (<see cref="P:System.AppDomain.BaseDirectory"/>),
+ the <b>assembly file name</b> and the config file extension.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/> is set to <c>MyExt</c> then
+ possible config file names would be: <c>MyConsoleApp.exe.MyExt</c> or
+ <c>MyClassLibrary.dll.MyExt</c>.
+ </para>
+ <para>
+ The <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFile"/> takes priority over the <see cref="P:log4net.Config.XmlConfiguratorAttribute.ConfigFileExtension"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.XmlConfiguratorAttribute.Watch">
+ <summary>
+ Gets or sets a value indicating whether to watch the configuration file.
+ </summary>
+ <value>
+ <c>true</c> if the configuration should be watched, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ If this flag is specified and set to <c>true</c> then the framework
+ will watch the configuration file and will reload the config each time
+ the file is modified.
+ </para>
+ <para>
+ The config file can only be watched if it is loaded from local disk.
+ In a No-Touch (Smart Client) deployment where the application is downloaded
+ from a web server the config file may not reside on the local disk
+ and therefore it may not be able to watch it.
+ </para>
+ <note>
+ Watching configuration is not supported on the SSCLI.
+ </note>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.Log4NetConfigurationSectionHandler">
+ <summary>
+ Class to register for the log4net section of the configuration file
+ </summary>
+ <remarks>
+ The log4net section of the configuration file needs to have a section
+ handler registered. This is the section handler used. It simply returns
+ the XML element that is the root of the section.
+ </remarks>
+ <example>
+ Example of registering the log4net section handler :
+ <code lang="XML" escaped="true">
+ <configuration>
+ <configSections>
+ <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
+ </configSections>
+ <log4net>
+ log4net configuration XML goes here
+ </log4net>
+ </configuration>
+ </code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.Log4NetConfigurationSectionHandler.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.Log4NetConfigurationSectionHandler.Create(System.Object,System.Object,System.Xml.XmlNode)">
+ <summary>
+ Parses the configuration section.
+ </summary>
+ <param name="parent">The configuration settings in a corresponding parent configuration section.</param>
+ <param name="configContext">The configuration context when called from the ASP.NET configuration system. Otherwise, this parameter is reserved and is a null reference.</param>
+ <param name="section">The <see cref="T:System.Xml.XmlNode"/> for the log4net section.</param>
+ <returns>The <see cref="T:System.Xml.XmlNode"/> for the log4net section.</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="T:System.Xml.XmlNode"/> containing the configuration data,
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.PluginAttribute">
+ <summary>
+ Assembly level attribute that specifies a plugin to attach to
+ the repository.
+ </summary>
+ <remarks>
+ <para>
+ Specifies the type of a plugin to create and attach to the
+ assembly's repository. The plugin type must implement the
+ <see cref="T:log4net.Plugin.IPlugin"/> interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Plugin.IPluginFactory">
+ <summary>
+ Interface used to create plugins.
+ </summary>
+ <remarks>
+ <para>
+ Interface used to create a plugin.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.IPluginFactory.CreatePlugin">
+ <summary>
+ Creates the plugin object.
+ </summary>
+ <returns>the new plugin instance</returns>
+ <remarks>
+ <para>
+ Create and return a new plugin instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.#ctor(System.String)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.PluginAttribute"/> class
+ with the specified type.
+ </summary>
+ <param name="typeName">The type name of plugin to create.</param>
+ <remarks>
+ <para>
+ Create the attribute with the plugin type specified.
+ </para>
+ <para>
+ Where possible use the constructor that takes a <see cref="T:System.Type"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.#ctor(System.Type)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.PluginAttribute"/> class
+ with the specified type.
+ </summary>
+ <param name="type">The type of plugin to create.</param>
+ <remarks>
+ <para>
+ Create the attribute with the plugin type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.CreatePlugin">
+ <summary>
+ Creates the plugin object defined by this attribute.
+ </summary>
+ <remarks>
+ <para>
+ Creates the instance of the <see cref="T:log4net.Plugin.IPlugin"/> object as
+ specified by this attribute.
+ </para>
+ </remarks>
+ <returns>The plugin object.</returns>
+ </member>
+ <member name="M:log4net.Config.PluginAttribute.ToString">
+ <summary>
+ Returns a representation of the properties of this object.
+ </summary>
+ <remarks>
+ <para>
+ Overrides base class <see cref="M:System.Object.ToString"/> method to
+ return a representation of the properties of this object.
+ </para>
+ </remarks>
+ <returns>A representation of the properties of this object</returns>
+ </member>
+ <member name="P:log4net.Config.PluginAttribute.Type">
+ <summary>
+ Gets or sets the type for the plugin.
+ </summary>
+ <value>
+ The type for the plugin.
+ </value>
+ <remarks>
+ <para>
+ The type for the plugin.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.PluginAttribute.TypeName">
+ <summary>
+ Gets or sets the type name for the plugin.
+ </summary>
+ <value>
+ The type name for the plugin.
+ </value>
+ <remarks>
+ <para>
+ The type name for the plugin.
+ </para>
+ <para>
+ Where possible use the <see cref="P:log4net.Config.PluginAttribute.Type"/> property instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.SecurityContextProviderAttribute">
+ <summary>
+ Assembly level attribute to configure the <see cref="T:log4net.Core.SecurityContextProvider"/>.
+ </summary>
+ <remarks>
+ <para>
+ This attribute may only be used at the assembly scope and can only
+ be used once per assembly.
+ </para>
+ <para>
+ Use this attribute to configure the <see cref="T:log4net.Config.XmlConfigurator"/>
+ without calling one of the <see cref="M:log4net.Config.XmlConfigurator.Configure"/>
+ methods.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Config.SecurityContextProviderAttribute.#ctor(System.Type)">
+ <summary>
+ Construct provider attribute with type specified
+ </summary>
+ <param name="providerType">the type of the provider to use</param>
+ <remarks>
+ <para>
+ The provider specified must subclass the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.SecurityContextProviderAttribute.Configure(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the SecurityContextProvider
+ </summary>
+ <param name="sourceAssembly">The assembly that this attribute was defined on.</param>
+ <param name="targetRepository">The repository to configure.</param>
+ <remarks>
+ <para>
+ Creates a provider instance from the <see cref="P:log4net.Config.SecurityContextProviderAttribute.ProviderType"/> specified.
+ Sets this as the default security context provider <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Config.SecurityContextProviderAttribute.ProviderType">
+ <summary>
+ Gets or sets the type of the provider to use.
+ </summary>
+ <value>
+ the type of the provider to use.
+ </value>
+ <remarks>
+ <para>
+ The provider specified must subclass the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ class.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.XmlConfigurator">
+ <summary>
+ Use this class to initialize the log4net environment using an Xml tree.
+ </summary>
+ <remarks>
+ <para>
+ Configures a <see cref="T:log4net.Repository.ILoggerRepository"/> using an Xml tree.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure">
+ <summary>
+ Automatically configures the log4net system based on the
+ application's configuration settings.
+ </summary>
+ <remarks>
+ <para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </para>
+ <para>
+ To use this method to configure log4net you must specify
+ the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> section
+ handler for the <c>log4net</c> configuration section. See the
+ <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> for an example.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Automatically configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using settings
+ stored in the application's configuration file.
+ </summary>
+ <remarks>
+ <para>
+ Each application has a configuration file. This has the
+ same name as the application with '.config' appended.
+ This file is XML and calling this function prompts the
+ configurator to look in that file for a section called
+ <c>log4net</c> that contains the configuration data.
+ </para>
+ <para>
+ To use this method to configure log4net you must specify
+ the <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> section
+ handler for the <c>log4net</c> configuration section. See the
+ <see cref="T:log4net.Config.Log4NetConfigurationSectionHandler"/> for an example.
+ </para>
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configures log4net using a <c>log4net</c> element
+ </summary>
+ <remarks>
+ <para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </para>
+ </remarks>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified XML
+ element.
+ </summary>
+ <remarks>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </remarks>
+ <param name="repository">The repository to configure.</param>
+ <param name="element">The element to parse.</param>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the specified configuration file.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <para>
+ The first element matching <c>&lt;configuration&gt;</c> will be read as the
+ configuration. If this file is also a .NET .config file then you must specify
+ a configuration section for the <c>log4net</c> element otherwise .NET will
+ complain. Set the type for the section handler to <see cref="T:System.Configuration.IgnoreSectionHandler"/>, for example:
+ <code lang="XML" escaped="true">
+ <configSections>
+ <section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
+ </configSections>
+ </code>
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.Uri)">
+ <summary>
+ Configures log4net using the specified configuration URI.
+ </summary>
+ <param name="configUri">A URI to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ The <see cref="T:System.Net.WebRequest"/> must support the URI scheme specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(System.IO.Stream)">
+ <summary>
+ Configures log4net using the specified configuration data stream.
+ </summary>
+ <param name="configStream">A stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the log4net configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The log4net configuration file can possible be specified in the application's
+ configuration file (either <c>MyAppName.exe.config</c> for a
+ normal application on <c>Web.config</c> for an ASP.NET application).
+ </para>
+ <para>
+ The first element matching <c>&lt;configuration&gt;</c> will be read as the
+ configuration. If this file is also a .NET .config file then you must specify
+ a configuration section for the <c>log4net</c> element otherwise .NET will
+ complain. Set the type for the section handler to <see cref="T:System.Configuration.IgnoreSectionHandler"/>, for example:
+ <code lang="XML" escaped="true">
+ <configSections>
+ <section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
+ </configSections>
+ </code>
+ </para>
+ <example>
+ The following example configures log4net using a configuration file, of which the
+ location is stored in the application's configuration file :
+ </example>
+ <code lang="C#">
+ using log4net.Config;
+ using System.IO;
+ using System.Configuration;
+
+ ...
+
+ XmlConfigurator.Configure(new FileInfo(ConfigurationSettings.AppSettings["log4net-config-file"]));
+ </code>
+ <para>
+ In the <c>.config</c> file, the path to the log4net can be specified like this :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net-config-file" value="log.config"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.Uri)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ URI.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configUri">A URI to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The <see cref="T:System.Net.WebRequest"/> must support the URI scheme specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.Configure(log4net.Repository.ILoggerRepository,System.IO.Stream)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the specified configuration
+ file.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configStream">The stream to load the XML configuration from.</param>
+ <remarks>
+ <para>
+ The configuration data must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ Note that this method will NOT close the stream parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)">
+ <summary>
+ Configures log4net using the file specified, monitors the file for changes
+ and reloads the configuration if a change is detected.
+ </summary>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatch(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Configures the <see cref="T:log4net.Repository.ILoggerRepository"/> using the file specified,
+ monitors the file for changes and reloads the configuration if a change
+ is detected.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The XML file to load the configuration from.</param>
+ <remarks>
+ <para>
+ The configuration file must be valid XML. It must contain
+ at least one element called <c>log4net</c> that holds
+ the configuration data.
+ </para>
+ <para>
+ The configuration file will be monitored using a <see cref="T:System.IO.FileSystemWatcher"/>
+ and depends on the behavior of that class.
+ </para>
+ <para>
+ For more information on how to configure log4net using
+ a separate configuration file, see <see cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Config.XmlConfigurator.Configure(System.IO.FileInfo)"/>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureFromXml(log4net.Repository.ILoggerRepository,System.Xml.XmlElement)">
+ <summary>
+ Configures the specified repository using a <c>log4net</c> element.
+ </summary>
+ <param name="repository">The hierarchy to configure.</param>
+ <param name="element">The element to parse.</param>
+ <remarks>
+ <para>
+ Loads the log4net configuration from the XML element
+ supplied as <paramref name="element"/>.
+ </para>
+ <para>
+ This method is ultimately called by one of the Configure methods
+ to load the configuration from an <see cref="T:System.Xml.XmlElement"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler">
+ <summary>
+ Class used to watch config files.
+ </summary>
+ <remarks>
+ <para>
+ Uses the <see cref="T:System.IO.FileSystemWatcher"/> to monitor
+ changes to a specified file. Because multiple change notifications
+ may be raised when the file is modified, a timer is used to
+ compress the notifications into a single event. The timer
+ waits for <see cref="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis"/> time before delivering
+ the event notification. If any further <see cref="T:System.IO.FileSystemWatcher"/>
+ change notifications arrive while the timer is waiting it
+ is reset and waits again for <see cref="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis"/> to
+ elapse.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.TimeoutMillis">
+ <summary>
+ The default amount of time to wait after receiving notification
+ before reloading the config file.
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.StartWatching(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Watch a specified config file used to configure a repository
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The configuration file to watch.</param>
+ <remarks>
+ <para>
+ Watch a specified config file used to configure a repository
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_configFile">
+ <summary>
+ Holds the FileInfo used to configure the XmlConfigurator
+ </summary>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_repository">
+ <summary>
+ Holds the repository being configured.
+ </summary>
+ </member>
+ <member name="F:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.m_timer">
+ <summary>
+ The timer used to compress the notification events.
+ </summary>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.#ctor(log4net.Repository.ILoggerRepository,System.IO.FileInfo)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/> class.
+ </summary>
+ <param name="repository">The repository to configure.</param>
+ <param name="configFile">The configuration file to watch.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.ConfigureAndWatchHandler_OnChanged(System.Object,System.IO.FileSystemEventArgs)">
+ <summary>
+ Event handler used by <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/>.
+ </summary>
+ <param name="source">The <see cref="T:System.IO.FileSystemWatcher"/> firing the event.</param>
+ <param name="e">The argument indicates the file that caused the event to be fired.</param>
+ <remarks>
+ <para>
+ This handler reloads the configuration from the file when the event is fired.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.ConfigureAndWatchHandler_OnRenamed(System.Object,System.IO.RenamedEventArgs)">
+ <summary>
+ Event handler used by <see cref="T:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler"/>.
+ </summary>
+ <param name="source">The <see cref="T:System.IO.FileSystemWatcher"/> firing the event.</param>
+ <param name="e">The argument indicates the file that caused the event to be fired.</param>
+ <remarks>
+ <para>
+ This handler reloads the configuration from the file when the event is fired.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Config.XmlConfigurator.ConfigureAndWatchHandler.OnWatchedFileChange(System.Object)">
+ <summary>
+ Called by the timer when the configuration has been updated.
+ </summary>
+ <param name="state">null</param>
+ </member>
+ <member name="T:log4net.Core.CompactRepositorySelector">
+ <summary>
+ The implementation of the <see cref="T:log4net.Core.IRepositorySelector"/> interface suitable
+ for use with the compact framework
+ </summary>
+ <remarks>
+ <para>
+ This <see cref="T:log4net.Core.IRepositorySelector"/> implementation is a simple
+ mapping between repository name and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ object.
+ </para>
+ <para>
+ The .NET Compact Framework 1.0 does not support retrieving assembly
+ level attributes therefore unlike the <c>DefaultRepositorySelector</c>
+ this selector does not examine the calling assembly for attributes.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Core.IRepositorySelector">
+ <summary>
+ Interface used by the <see cref="T:log4net.LogManager"/> to select the <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.LogManager"/> uses a <see cref="T:log4net.Core.IRepositorySelector"/>
+ to specify the policy for selecting the correct <see cref="T:log4net.Repository.ILoggerRepository"/>
+ to return to the caller.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="assembly">The assembly to use to lookup to the <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the assembly.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </para>
+ <para>
+ How the association between <see cref="T:System.Reflection.Assembly"/> and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ is made is not defined. The implementation may choose any method for
+ this association. The results of this method must be repeatable, i.e.
+ when called again with the same arguments the result must be the
+ save value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Gets the named <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repositoryName">The name to use to lookup to the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The named <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ Lookup a named <see cref="T:log4net.Repository.ILoggerRepository"/>. This is the repository created by
+ calling <see cref="M:log4net.Core.IRepositorySelector.CreateRepository(System.String,System.Type)"/>.
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a new repository for the assembly specified.
+ </summary>
+ <param name="assembly">The assembly to use to create the domain to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the domain
+ specified such that a call to <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ How the association between <see cref="T:System.Reflection.Assembly"/> and <see cref="T:log4net.Repository.ILoggerRepository"/>
+ is made is not defined. The implementation may choose any method for
+ this association.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a new repository with the name specified.
+ </summary>
+ <param name="repositoryName">The name to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the name
+ specified such that a call to <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.String)"/> with the
+ same name will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.IRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.IRepositorySelector.GetRepository(System.Reflection.Assembly)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets an array of all currently defined repositories.
+ </summary>
+ <returns>
+ An array of the <see cref="T:log4net.Repository.ILoggerRepository"/> instances created by
+ this <see cref="T:log4net.Core.IRepositorySelector"/>.</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.#ctor(System.Type)">
+ <summary>
+ Create a new repository selector
+ </summary>
+ <param name="defaultRepositoryType">the type of the repositories to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <remarks>
+ <para>
+ Create an new compact repository selector.
+ The default type for repositories must be specified,
+ an appropriate value would be <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="defaultRepositoryType"/> is null</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException">throw if <paramref name="defaultRepositoryType"/> does not implement <see cref="T:log4net.Repository.ILoggerRepository"/></exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Get the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly
+ </summary>
+ <param name="assembly">not used</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ <para>
+ The <paramref name="assembly"/> argument is not used. This selector does not create a
+ separate repository for each assembly.
+ </para>
+ <para>
+ As a named repository is not specified the default repository is
+ returned. The default repository is named <c>log4net-default-repository</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Get the named <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </summary>
+ <param name="repositoryName">the name of the repository to lookup</param>
+ <returns>The named <see cref="T:log4net.Repository.ILoggerRepository"/></returns>
+ <remarks>
+ <para>
+ Get the named <see cref="T:log4net.Repository.ILoggerRepository"/>. The default
+ repository is <c>log4net-default-repository</c>. Other repositories
+ must be created using the <see cref="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)"/>.
+ If the named repository does not exist an exception is thrown.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
+ <exception cref="T:log4net.Core.LogException">throw if the <paramref name="repositoryName"/> does not exist</exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Create a new repository for the assembly specified
+ </summary>
+ <param name="assembly">not used</param>
+ <param name="repositoryType">the type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <returns>the repository created</returns>
+ <remarks>
+ <para>
+ The <paramref name="assembly"/> argument is not used. This selector does not create a
+ separate repository for each assembly.
+ </para>
+ <para>
+ If the <paramref name="repositoryType"/> is <c>null</c> then the
+ default repository type specified to the constructor is used.
+ </para>
+ <para>
+ As a named repository is not specified the default repository is
+ returned. The default repository is named <c>log4net-default-repository</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Create a new repository for the repository specified
+ </summary>
+ <param name="repositoryName">the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <param name="repositoryType">the type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ If this param is null then the default repository type is used.</param>
+ <returns>the repository created</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)"/> with the
+ same repository specified will return the same repository instance.
+ </para>
+ <para>
+ If the named repository already exists an exception will be thrown.
+ </para>
+ <para>
+ If <paramref name="repositoryType"/> is <c>null</c> then the default
+ repository type specified to the constructor is used.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">throw if <paramref name="repositoryName"/> is null</exception>
+ <exception cref="T:log4net.Core.LogException">throw if the <paramref name="repositoryName"/> already exists</exception>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.CompactRepositorySelector.CreateRepository(System.String,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.CompactRepositorySelector.GetRepository(System.String)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets a list of <see cref="T:log4net.Repository.ILoggerRepository"/> objects
+ </summary>
+ <returns>an array of all known <see cref="T:log4net.Repository.ILoggerRepository"/> objects</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.CompactRepositorySelector.OnLoggerRepositoryCreatedEvent(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Notify the registered listeners that the repository has been created
+ </summary>
+ <param name="repository">The repository that has been created</param>
+ <remarks>
+ <para>
+ Raises the <event cref="E:log4net.Core.CompactRepositorySelector.LoggerRepositoryCreatedEvent">LoggerRepositoryCreatedEvent</event>
+ event.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Core.CompactRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.DefaultRepositorySelector">
+ <summary>
+ The default implementation of the <see cref="T:log4net.Core.IRepositorySelector"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ Uses attributes defined on the calling assembly to determine how to
+ configure the hierarchy for the repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.#ctor(System.Type)">
+ <summary>
+ Creates a new repository selector.
+ </summary>
+ <param name="defaultRepositoryType">The type of the repositories to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/></param>
+ <remarks>
+ <para>
+ Create an new repository selector.
+ The default type for repositories must be specified,
+ an appropriate value would be <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="defaultRepositoryType"/> is <see langword="null"/>.</exception>
+ <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="defaultRepositoryType"/> does not implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified assembly.
+ </summary>
+ <param name="repositoryAssembly">The assembly use to lookup the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <remarks>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and the repository
+ to create can be overridden by specifying the <see cref="T:log4net.Config.RepositoryAttribute"/>
+ attribute on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ The default values are to use the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>
+ implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically configured using
+ any <see cref="T:log4net.Config.ConfiguratorAttribute"/> attributes defined on
+ the <paramref name="repositoryAssembly"/>.
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the assembly</returns>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified repository.
+ </summary>
+ <param name="repositoryName">The repository to use to lookup the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> for the specified repository.</returns>
+ <remarks>
+ <para>
+ Returns the named repository. If <paramref name="repositoryName"/> is <c>null</c>
+ a <see cref="T:System.ArgumentNullException"/> is thrown. If the repository
+ does not exist a <see cref="T:log4net.Core.LogException"/> is thrown.
+ </para>
+ <para>
+ Use <see cref="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)"/> to create a repository.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryName"/> is <see langword="null"/>.</exception>
+ <exception cref="T:log4net.Core.LogException"><paramref name="repositoryName"/> does not exist.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Create a new repository for the assembly specified
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to create the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and
+ the repository to create can be overridden by specifying the
+ <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ <paramref name="repositoryAssembly"/>. The default values are to use the
+ <paramref name="repositoryType"/> implementation of the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically
+ configured using any <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes defined on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ If a repository for the <paramref name="repositoryAssembly"/> already exists
+ that repository will be returned. An error will not be raised and that
+ repository may be of a different type to that specified in <paramref name="repositoryType"/>.
+ Also the <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ assembly may be used to override the repository type specified in
+ <paramref name="repositoryType"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.Reflection.Assembly,System.Type,System.String,System.Boolean)">
+ <summary>
+ Creates a new repository for the assembly specified.
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to create the repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryName">The name to assign to the created repository</param>
+ <param name="readAssemblyAttributes">Set to <c>true</c> to read and apply the assembly attributes</param>
+ <returns>The repository created.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ <para>
+ The type of the <see cref="T:log4net.Repository.ILoggerRepository"/> created and
+ the repository to create can be overridden by specifying the
+ <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ <paramref name="repositoryAssembly"/>. The default values are to use the
+ <paramref name="repositoryType"/> implementation of the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface and to use the
+ <see cref="P:System.Reflection.AssemblyName.Name"/> as the name of the repository.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be automatically
+ configured using any <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes defined on the <paramref name="repositoryAssembly"/>.
+ </para>
+ <para>
+ If a repository for the <paramref name="repositoryAssembly"/> already exists
+ that repository will be returned. An error will not be raised and that
+ repository may be of a different type to that specified in <paramref name="repositoryType"/>.
+ Also the <see cref="T:log4net.Config.RepositoryAttribute"/> attribute on the
+ assembly may be used to override the repository type specified in
+ <paramref name="repositoryType"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryAssembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a new repository for the specified repository.
+ </summary>
+ <param name="repositoryName">The repository to associate with the <see cref="T:log4net.Repository.ILoggerRepository"/>.</param>
+ <param name="repositoryType">The type of repository to create, must implement <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ If this param is <see langword="null"/> then the default repository type is used.</param>
+ <returns>The new repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)"/> with the
+ same repository specified will return the same repository instance.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException"><paramref name="repositoryName"/> is <see langword="null"/>.</exception>
+ <exception cref="T:log4net.Core.LogException"><paramref name="repositoryName"/> already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.ExistsRepository(System.String)">
+ <summary>
+ Test if a named repository exists
+ </summary>
+ <param name="repositoryName">the named repository to check</param>
+ <returns><c>true</c> if the repository exists</returns>
+ <remarks>
+ <para>
+ Test if a named repository exists. Use <see cref="M:log4net.Core.DefaultRepositorySelector.CreateRepository(System.String,System.Type)"/>
+ to create a new repository and <see cref="M:log4net.Core.DefaultRepositorySelector.GetRepository(System.String)"/> to retrieve
+ a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetAllRepositories">
+ <summary>
+ Gets a list of <see cref="T:log4net.Repository.ILoggerRepository"/> objects
+ </summary>
+ <returns>an array of all known <see cref="T:log4net.Repository.ILoggerRepository"/> objects</returns>
+ <remarks>
+ <para>
+ Gets an array of all of the repositories created by this selector.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.AliasRepository(System.String,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Aliases a repository to an existing repository.
+ </summary>
+ <param name="repositoryAlias">The repository to alias.</param>
+ <param name="repositoryTarget">The repository that the repository is aliased to.</param>
+ <remarks>
+ <para>
+ The repository specified will be aliased to the repository when created.
+ The repository must not already exist.
+ </para>
+ <para>
+ When the repository is created it must utilize the same repository type as
+ the repository it is aliased to, otherwise the aliasing will fail.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="repositoryAlias"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repositoryTarget"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.OnLoggerRepositoryCreatedEvent(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Notifies the registered listeners that the repository has been created.
+ </summary>
+ <param name="repository">The repository that has been created.</param>
+ <remarks>
+ <para>
+ Raises the <see cref="E:log4net.Core.DefaultRepositorySelector.LoggerRepositoryCreatedEvent"/> event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.GetInfoForAssembly(System.Reflection.Assembly,System.String@,System.Type@)">
+ <summary>
+ Gets the repository name and repository type for the specified assembly.
+ </summary>
+ <param name="assembly">The assembly that has a <see cref="T:log4net.Config.RepositoryAttribute"/>.</param>
+ <param name="repositoryName">in/out param to hold the repository name to use for the assembly, caller should set this to the default value before calling.</param>
+ <param name="repositoryType">in/out param to hold the type of the repository to create for the assembly, caller should set this to the default value before calling.</param>
+ <exception cref="T:System.ArgumentNullException"><paramref name="assembly"/> is <see langword="null"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.ConfigureRepository(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Configures the repository using information from the assembly.
+ </summary>
+ <param name="assembly">The assembly containing <see cref="T:log4net.Config.ConfiguratorAttribute"/>
+ attributes which define the configuration for the repository.</param>
+ <param name="repository">The repository to configure.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.LoadPlugins(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Loads the attribute defined plugins on the assembly.
+ </summary>
+ <param name="assembly">The assembly that contains the attributes.</param>
+ <param name="repository">The repository to add the plugins to.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.DefaultRepositorySelector.LoadAliases(System.Reflection.Assembly,log4net.Repository.ILoggerRepository)">
+ <summary>
+ Loads the attribute defined aliases on the assembly.
+ </summary>
+ <param name="assembly">The assembly that contains the attributes.</param>
+ <param name="repository">The repository to alias to.</param>
+ <exception cref="T:System.ArgumentNullException">
+ <para><paramref name="assembly"/> is <see langword="null"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="repository"/> is <see langword="null"/>.</para>
+ </exception>
+ </member>
+ <member name="E:log4net.Core.DefaultRepositorySelector.LoggerRepositoryCreatedEvent">
+ <summary>
+ Event to notify that a logger repository has been created.
+ </summary>
+ <value>
+ Event to notify that a logger repository has been created.
+ </value>
+ <remarks>
+ <para>
+ Event raised when a new repository is created.
+ The event source will be this selector. The event args will
+ be a <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> which
+ holds the newly created <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ErrorCode">
+ <summary>
+ Defined error codes that can be passed to the <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ Values passed to the <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.GenericFailure">
+ <summary>
+ A general error
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.WriteFailure">
+ <summary>
+ Error while writing output
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.FlushFailure">
+ <summary>
+ Failed to flush file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.CloseFailure">
+ <summary>
+ Failed to close file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.FileOpenFailure">
+ <summary>
+ Unable to open output file
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.MissingLayout">
+ <summary>
+ No layout specified
+ </summary>
+ </member>
+ <member name="F:log4net.Core.ErrorCode.AddressParseFailure">
+ <summary>
+ Failed to parse address
+ </summary>
+ </member>
+ <member name="T:log4net.Core.IErrorHandler">
+ <summary>
+ Appenders may delegate their error handling to an <see cref="T:log4net.Core.IErrorHandler"/>.
+ </summary>
+ <remarks>
+ <para>
+ Error handling is a particularly tedious to get right because by
+ definition errors are hard to predict and to reproduce.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)">
+ <summary>
+ Handles the error and information about the error condition is passed as
+ a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <param name="e">The <see cref="T:System.Exception"/> that was thrown when the error occurred.</param>
+ <param name="errorCode">The error code associated with the error.</param>
+ <remarks>
+ <para>
+ Handles the error and information about the error condition is passed as
+ a parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception)">
+ <summary>
+ Prints the error message passed as a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <param name="e">The <see cref="T:System.Exception"/> that was thrown when the error occurred.</param>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.IErrorHandler.Error(System.String)">
+ <summary>
+ Prints the error message passed as a parameter.
+ </summary>
+ <param name="message">The message associated with the error.</param>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.IErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.IFixingRequired">
+ <summary>
+ Interface for objects that require fixing.
+ </summary>
+ <remarks>
+ <para>
+ Interface that indicates that the object requires fixing before it
+ can be taken outside the context of the appender's
+ <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method.
+ </para>
+ <para>
+ When objects that implement this interface are stored
+ in the context properties maps <see cref="T:log4net.GlobalContext"/>
+ <see cref="P:log4net.GlobalContext.Properties"/> and <see cref="T:log4net.ThreadContext"/>
+ <see cref="P:log4net.ThreadContext.Properties"/> are fixed
+ (see <see cref="P:log4net.Core.LoggingEvent.Fix"/>) the <see cref="M:log4net.Core.IFixingRequired.GetFixedObject"/>
+ method will be called.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.IFixingRequired.GetFixedObject">
+ <summary>
+ Get a portable version of this object
+ </summary>
+ <returns>the portable instance of this object</returns>
+ <remarks>
+ <para>
+ Get a portable instance object that represents the current
+ state of this object. The portable object can be stored
+ and logged from any thread with identical results.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ILogger">
+ <summary>
+ Interface that all loggers implement
+ </summary>
+ <remarks>
+ <para>
+ This interface supports logging events and testing if a level
+ is enabled for logging.
+ </para>
+ <para>
+ These methods will not throw exceptions. Note to implementor, ensure
+ that the implementation of these methods cannot allow an exception
+ to be thrown to the caller.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.ILogger.Log(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This generic form is intended to be used by wrappers.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">the exception to log, including its stack trace. Pass <c>null</c> to not log an exception.</param>
+ <remarks>
+ <para>
+ Generates a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/> and <paramref name="exception"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.ILogger.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ This is the most generic printing method that is intended to be used
+ by wrappers.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Logs the specified logging event through this logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.ILogger.IsEnabledFor(log4net.Core.Level)">
+ <summary>
+ Checks if this logger is enabled for a given <see cref="T:log4net.Core.Level"/> passed as parameter.
+ </summary>
+ <param name="level">The level to check.</param>
+ <returns>
+ <c>true</c> if this logger is enabled for <c>level</c>, otherwise <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Test if this logger is going to log events of the specified <paramref name="level"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.ILogger.Name">
+ <summary>
+ Gets the name of the logger.
+ </summary>
+ <value>
+ The name of the logger.
+ </value>
+ <remarks>
+ <para>
+ The name of this logger
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.ILogger.Repository">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this logger belongs to.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ILoggerWrapper">
+ <summary>
+ Base interface for all wrappers
+ </summary>
+ <remarks>
+ <para>
+ Base interface for all wrappers.
+ </para>
+ <para>
+ All wrappers must implement this interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="P:log4net.Core.ILoggerWrapper.Logger">
+ <summary>
+ Get the implementation behind this wrapper object.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ILogger"/> object that in implementing this object.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Core.ILogger"/> object that in implementing this
+ object. The <c>Logger</c> object may not
+ be the same object as this object because of logger decorators.
+ This gets the actual underlying objects that is used to process
+ the log events.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerRepositoryCreationEventHandler">
+ <summary>
+ Delegate used to handle logger repository creation event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Core.IRepositorySelector"/> which created the repository.</param>
+ <param name="e">The <see cref="T:log4net.Core.LoggerRepositoryCreationEventArgs"/> event args
+ that holds the <see cref="T:log4net.Repository.ILoggerRepository"/> instance that has been created.</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository creation event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerRepositoryCreationEventArgs">
+ <summary>
+ Provides data for the <see cref="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent"/> event.
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="E:log4net.Core.IRepositorySelector.LoggerRepositoryCreatedEvent"/>
+ event is raised every time a <see cref="T:log4net.Repository.ILoggerRepository"/> is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerRepositoryCreationEventArgs.m_repository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LoggerRepositoryCreationEventArgs.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Construct instance using <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ </summary>
+ <param name="repository">the <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created</param>
+ <remarks>
+ <para>
+ Construct instance using <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggerRepositoryCreationEventArgs.LoggerRepository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </value>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that has been created
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.ITriggeringEventEvaluator">
+ <summary>
+ Test if an <see cref="T:log4net.Core.LoggingEvent"/> triggers an action
+ </summary>
+ <remarks>
+ <para>
+ Implementations of this interface allow certain appenders to decide
+ when to perform an appender specific action.
+ </para>
+ <para>
+ The action or behavior triggered is defined by the implementation.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.ITriggeringEventEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Test if this event triggers the action
+ </summary>
+ <param name="loggingEvent">The event to check</param>
+ <returns><c>true</c> if this event triggers the action, otherwise <c>false</c></returns>
+ <remarks>
+ <para>
+ Return <c>true</c> if this event triggers the action
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.Level">
+ <summary>
+ Defines the default set of levels recognized by the system.
+ </summary>
+ <remarks>
+ <para>
+ Each <see cref="T:log4net.Core.LoggingEvent"/> has an associated <see cref="T:log4net.Core.Level"/>.
+ </para>
+ <para>
+ Levels have a numeric <see cref="P:log4net.Core.Level.Value"/> that defines the relative
+ ordering between levels. Two Levels with the same <see cref="P:log4net.Core.Level.Value"/>
+ are deemed to be equivalent.
+ </para>
+ <para>
+ The levels that are recognized by log4net are set for each <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and each repository can have different levels defined. The levels are stored
+ in the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/> on the repository. Levels are
+ looked up by name from the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>.
+ </para>
+ <para>
+ When logging at level INFO the actual level used is not <see cref="F:log4net.Core.Level.Info"/> but
+ the value of <c>LoggerRepository.LevelMap["INFO"]</c>. The default value for this is
+ <see cref="F:log4net.Core.Level.Info"/>, but this can be changed by reconfiguring the level map.
+ </para>
+ <para>
+ Each level has a <see cref="P:log4net.Core.Level.DisplayName"/> in addition to its <see cref="P:log4net.Core.Level.Name"/>. The
+ <see cref="P:log4net.Core.Level.DisplayName"/> is the string that is written into the output log. By default
+ the display name is the same as the level name, but this can be used to alias levels
+ or to localize the log output.
+ </para>
+ <para>
+ Some of the predefined levels recognized by the system are:
+ </para>
+ <list type="bullet">
+ <item>
+ <description><see cref="F:log4net.Core.Level.Off"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Fatal"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Error"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Warn"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Info"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.Debug"/>.</description>
+ </item>
+ <item>
+ <description><see cref="F:log4net.Core.Level.All"/>.</description>
+ </item>
+ </list>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.Level.#ctor(System.Int32,System.String,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="level">Integer value for this level, higher values represent more severe levels.</param>
+ <param name="levelName">The string name of this level.</param>
+ <param name="displayName">The display name for this level. This may be localized or otherwise different from the name</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.Level"/> class with
+ the specified level name and value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.#ctor(System.Int32,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="level">Integer value for this level, higher values represent more severe levels.</param>
+ <param name="levelName">The string name of this level.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.Level"/> class with
+ the specified level name and value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.ToString">
+ <summary>
+ Returns the <see cref="T:System.String"/> representation of the current
+ <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <returns>
+ A <see cref="T:System.String"/> representation of the current <see cref="T:log4net.Core.Level"/>.
+ </returns>
+ <remarks>
+ <para>
+ Returns the level <see cref="P:log4net.Core.Level.Name"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.Equals(System.Object)">
+ <summary>
+ Compares levels.
+ </summary>
+ <param name="o">The object to compare against.</param>
+ <returns><c>true</c> if the objects are equal.</returns>
+ <remarks>
+ <para>
+ Compares the levels of <see cref="T:log4net.Core.Level"/> instances, and
+ defers to base class if the target object is not a <see cref="T:log4net.Core.Level"/>
+ instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.GetHashCode">
+ <summary>
+ Returns a hash code
+ </summary>
+ <returns>A hash code for the current <see cref="T:log4net.Core.Level"/>.</returns>
+ <remarks>
+ <para>
+ Returns a hash code suitable for use in hashing algorithms and data
+ structures like a hash table.
+ </para>
+ <para>
+ Returns the hash code of the level <see cref="P:log4net.Core.Level.Value"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.CompareTo(System.Object)">
+ <summary>
+ Compares this instance to a specified object and returns an
+ indication of their relative values.
+ </summary>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> instance or <see langword="null"/> to compare with this instance.</param>
+ <returns>
+ A 32-bit signed integer that indicates the relative order of the
+ values compared. The return value has these meanings:
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Meaning</description>
+ </listheader>
+ <item>
+ <term>Less than zero</term>
+ <description>This instance is less than <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Zero</term>
+ <description>This instance is equal to <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Greater than zero</term>
+ <description>
+ <para>This instance is greater than <paramref name="r"/>.</para>
+ <para>-or-</para>
+ <para><paramref name="r"/> is <see langword="null"/>.</para>
+ </description>
+ </item>
+ </list>
+ </returns>
+ <remarks>
+ <para>
+ <paramref name="r"/> must be an instance of <see cref="T:log4net.Core.Level"/>
+ or <see langword="null"/>; otherwise, an exception is thrown.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException"><paramref name="r"/> is not a <see cref="T:log4net.Core.Level"/>.</exception>
+ </member>
+ <member name="M:log4net.Core.Level.op_GreaterThan(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is greater than another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is greater than
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_LessThan(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is less than another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is less than
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_GreaterThanOrEqual(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is greater than or equal to another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is greater than or equal to
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_LessThanOrEqual(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether a specified <see cref="T:log4net.Core.Level"/>
+ is less than or equal to another specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/></param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/></param>
+ <returns>
+ <c>true</c> if <paramref name="l"/> is less than or equal to
+ <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_Equality(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether two specified <see cref="T:log4net.Core.Level"/>
+ objects have the same value.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <returns>
+ <c>true</c> if the value of <paramref name="l"/> is the same as the
+ value of <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.op_Inequality(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Returns a value indicating whether two specified <see cref="T:log4net.Core.Level"/>
+ objects have different values.
+ </summary>
+ <param name="l">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <param name="r">A <see cref="T:log4net.Core.Level"/> or <see langword="null"/>.</param>
+ <returns>
+ <c>true</c> if the value of <paramref name="l"/> is different from
+ the value of <paramref name="r"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.Level.Compare(log4net.Core.Level,log4net.Core.Level)">
+ <summary>
+ Compares two specified <see cref="T:log4net.Core.Level"/> instances.
+ </summary>
+ <param name="l">The first <see cref="T:log4net.Core.Level"/> to compare.</param>
+ <param name="r">The second <see cref="T:log4net.Core.Level"/> to compare.</param>
+ <returns>
+ A 32-bit signed integer that indicates the relative order of the
+ two values compared. The return value has these meanings:
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Meaning</description>
+ </listheader>
+ <item>
+ <term>Less than zero</term>
+ <description><paramref name="l"/> is less than <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Zero</term>
+ <description><paramref name="l"/> is equal to <paramref name="r"/>.</description>
+ </item>
+ <item>
+ <term>Greater than zero</term>
+ <description><paramref name="l"/> is greater than <paramref name="r"/>.</description>
+ </item>
+ </list>
+ </returns>
+ <remarks>
+ <para>
+ Compares two levels.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.Level.Off">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Off"/> level designates a higher level than all the rest.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Emergency">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Emergency"/> level designates very severe error events.
+ System unusable, emergencies.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Fatal">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Fatal"/> level designates very severe error events
+ that will presumably lead the application to abort.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Alert">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Alert"/> level designates very severe error events.
+ Take immediate action, alerts.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Critical">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Critical"/> level designates very severe error events.
+ Critical condition, critical.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Severe">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Severe"/> level designates very severe error events.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Error">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Error"/> level designates error events that might
+ still allow the application to continue running.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Warn">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Warn"/> level designates potentially harmful
+ situations.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Notice">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Notice"/> level designates informational messages
+ that highlight the progress of the application at the highest level.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Info">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Info"/> level designates informational messages that
+ highlight the progress of the application at coarse-grained level.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Debug">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Debug"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Fine">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Fine"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Trace">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Trace"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Finer">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Finer"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Verbose">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Verbose"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.Finest">
+ <summary>
+ The <see cref="F:log4net.Core.Level.Finest"/> level designates fine-grained informational
+ events that are most useful to debug an application.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.Level.All">
+ <summary>
+ The <see cref="F:log4net.Core.Level.All"/> level designates the lowest level possible.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.Level.Name">
+ <summary>
+ Gets the name of this level.
+ </summary>
+ <value>
+ The name of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the name of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.Level.Value">
+ <summary>
+ Gets the value of this level.
+ </summary>
+ <value>
+ The value of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the value of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.Level.DisplayName">
+ <summary>
+ Gets the display name of this level.
+ </summary>
+ <value>
+ The display name of this level.
+ </value>
+ <remarks>
+ <para>
+ Gets the display name of this level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LevelCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Core.Level"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ReadOnly(log4net.Core.LevelCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>LevelCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ A <c>LevelCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>LevelCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.LevelCollection)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <c>LevelCollection</c>.
+ </summary>
+ <param name="c">The <c>LevelCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.Level[])">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Core.Level"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Core.Level"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>LevelCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Core.Level"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Core.Level"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.#ctor(log4net.Core.LevelCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.CopyTo(log4net.Core.Level[])">
+ <summary>
+ Copies the entire <c>LevelCollection</c> to a one-dimensional
+ <see cref="T:log4net.Core.Level"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Core.Level"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.CopyTo(log4net.Core.Level[],System.Int32)">
+ <summary>
+ Copies the entire <c>LevelCollection</c> to a one-dimensional
+ <see cref="T:log4net.Core.Level"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Core.Level"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Add(log4net.Core.Level)">
+ <summary>
+ Adds a <see cref="T:log4net.Core.Level"/> to the end of the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Clear">
+ <summary>
+ Removes all elements from the <c>LevelCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Core.LevelCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Contains(log4net.Core.Level)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Core.Level"/> is in the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>LevelCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.IndexOf(log4net.Core.Level)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Core.Level"/>
+ in the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to locate in the <c>LevelCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>LevelCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Insert(System.Int32,log4net.Core.Level)">
+ <summary>
+ Inserts an element into the <c>LevelCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Remove(log4net.Core.Level)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Core.Level"/> from the <c>LevelCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Core.Level"/> to remove from the <c>LevelCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Core.Level"/> was not found in the <c>LevelCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>LevelCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>LevelCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Core.LevelCollection.Enumerator"/> for the entire <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(log4net.Core.LevelCollection)">
+ <summary>
+ Adds the elements of another <c>LevelCollection</c> to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="x">The <c>LevelCollection</c> whose elements should be added to the end of the current <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(log4net.Core.Level[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Core.Level"/> array to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Core.Level"/> array whose elements should be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Core.Level"/> collection to the current <c>LevelCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Core.Level"/> collection whose elements should be added to the end of the <c>LevelCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Core.LevelCollection.Count"/> of the <c>LevelCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>LevelCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <value>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Core.Level"/> at the specified index.
+ </summary>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Core.LevelCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value>true if the collection has a fixed size; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value>true if the collection is read-only; otherwise, false. The default is false</value>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>LevelCollection</c> can contain.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.ILevelCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ILevelCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.ILevelCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.ILevelCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LevelCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Core.LevelCollection"/>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.#ctor(log4net.Core.LevelCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Core.LevelCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LevelCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Core.LevelEvaluator">
+ <summary>
+ An evaluator that triggers at a threshold level
+ </summary>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LevelEvaluator.m_threshold">
+ <summary>
+ The threshold for triggering
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.#ctor">
+ <summary>
+ Create a new evaluator using the <see cref="F:log4net.Core.Level.Off"/> threshold.
+ </summary>
+ <remarks>
+ <para>
+ Create a new evaluator using the <see cref="F:log4net.Core.Level.Off"/> threshold.
+ </para>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.#ctor(log4net.Core.Level)">
+ <summary>
+ Create a new evaluator using the specified <see cref="T:log4net.Core.Level"/> threshold.
+ </summary>
+ <param name="threshold">the threshold to trigger at</param>
+ <remarks>
+ <para>
+ Create a new evaluator using the specified <see cref="T:log4net.Core.Level"/> threshold.
+ </para>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)">
+ <summary>
+ Is this <paramref name="loggingEvent"/> the triggering event?
+ </summary>
+ <param name="loggingEvent">The event to check</param>
+ <returns>This method returns <c>true</c>, if the event level
+ is equal or higher than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>.
+ Otherwise it returns <c>false</c></returns>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelEvaluator.Threshold">
+ <summary>
+ the threshold to trigger at
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.Level"/> that will cause this evaluator to trigger
+ </value>
+ <remarks>
+ <para>
+ This evaluator will trigger if the level of the event
+ passed to <see cref="M:log4net.Core.LevelEvaluator.IsTriggeringEvent(log4net.Core.LoggingEvent)"/>
+ is equal to or greater than the <see cref="P:log4net.Core.LevelEvaluator.Threshold"/>
+ level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LevelMap">
+ <summary>
+ Mapping between string name and Level object
+ </summary>
+ <remarks>
+ <para>
+ Mapping between string name and <see cref="T:log4net.Core.Level"/> object.
+ This mapping is held separately for each <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ The level name is case insensitive.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LevelMap.m_mapName2Level">
+ <summary>
+ Mapping from level name to Level object. The
+ level name is case insensitive
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LevelMap.#ctor">
+ <summary>
+ Construct the level map
+ </summary>
+ <remarks>
+ <para>
+ Construct the level map.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Clear">
+ <summary>
+ Clear the internal maps of all levels
+ </summary>
+ <remarks>
+ <para>
+ Clear the internal maps of all levels
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(System.String,System.Int32)">
+ <summary>
+ Create a new Level and add it to the map
+ </summary>
+ <param name="name">the string to display for the Level</param>
+ <param name="value">the level value to give to the Level</param>
+ <remarks>
+ <para>
+ Create a new Level and add it to the map
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LevelMap.Add(System.String,System.Int32,System.String)"/>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(System.String,System.Int32,System.String)">
+ <summary>
+ Create a new Level and add it to the map
+ </summary>
+ <param name="name">the string to display for the Level</param>
+ <param name="value">the level value to give to the Level</param>
+ <param name="displayName">the display name to give to the Level</param>
+ <remarks>
+ <para>
+ Create a new Level and add it to the map
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.Add(log4net.Core.Level)">
+ <summary>
+ Add a Level to the map
+ </summary>
+ <param name="level">the Level to add</param>
+ <remarks>
+ <para>
+ Add a Level to the map
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LevelMap.LookupWithDefault(log4net.Core.Level)">
+ <summary>
+ Lookup a named level from the map
+ </summary>
+ <param name="defaultLevel">the name of the level to lookup is taken from this level.
+ If the level is not set on the map then this level is added</param>
+ <returns>the level in the map with the name specified</returns>
+ <remarks>
+ <para>
+ Lookup a named level from the map. The name of the level to lookup is taken
+ from the <see cref="P:log4net.Core.Level.Name"/> property of the <paramref name="defaultLevel"/>
+ argument.
+ </para>
+ <para>
+ If no level with the specified name is found then the
+ <paramref name="defaultLevel"/> argument is added to the level map
+ and returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelMap.Item(System.String)">
+ <summary>
+ Lookup a <see cref="T:log4net.Core.Level"/> by name
+ </summary>
+ <param name="name">The name of the Level to lookup</param>
+ <returns>a Level from the map with the name specified</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="T:log4net.Core.Level"/> from the
+ map with the name specified. If the no level is
+ found then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LevelMap.AllLevels">
+ <summary>
+ Return all possible levels as a list of Level objects.
+ </summary>
+ <returns>all possible levels as a list of Level objects</returns>
+ <remarks>
+ <para>
+ Return all possible levels as a list of Level objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LocationInfo">
+ <summary>
+ The internal representation of caller location information.
+ </summary>
+ <remarks>
+ <para>
+ This class uses the <c>System.Diagnostics.StackTrace</c> class to generate
+ a call stack. The caller's information is then extracted from this stack.
+ </para>
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class is not supported on the
+ .NET Compact Framework 1.0 therefore caller location information is not
+ available on that framework.
+ </para>
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
+ </para>
+ <para>
+ "StackTrace information will be most informative with Debug build configurations.
+ By default, Debug builds include debug symbols, while Release builds do not. The
+ debug symbols contain most of the file, method name, line number, and column
+ information used in constructing StackFrame and StackTrace objects. StackTrace
+ might not report as many method calls as expected, due to code transformations
+ that occur during optimization."
+ </para>
+ <para>
+ This means that in a Release build the caller information may be incomplete or may
+ not exist at all! Therefore caller location information cannot be relied upon in a Release build.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Core.LocationInfo.NA">
+ <summary>
+ When location information is not available the constant
+ <c>NA</c> is returned. Current value of this string
+ constant is <b>?</b>.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LocationInfo.#ctor(System.Type)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LocationInfo"/>
+ class based on the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LocationInfo.#ctor(System.String,System.String,System.String,System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="className">The fully qualified class name.</param>
+ <param name="methodName">The method name.</param>
+ <param name="fileName">The file name.</param>
+ <param name="lineNumber">The line number of the method within the file.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LocationInfo"/>
+ class with the specified data.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.ClassName">
+ <summary>
+ Gets the fully qualified class name of the caller making the logging
+ request.
+ </summary>
+ <value>
+ The fully qualified class name of the caller making the logging
+ request.
+ </value>
+ <remarks>
+ <para>
+ Gets the fully qualified class name of the caller making the logging
+ request.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.FileName">
+ <summary>
+ Gets the file name of the caller.
+ </summary>
+ <value>
+ The file name of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the file name of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.LineNumber">
+ <summary>
+ Gets the line number of the caller.
+ </summary>
+ <value>
+ The line number of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the line number of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.MethodName">
+ <summary>
+ Gets the method name of the caller.
+ </summary>
+ <value>
+ The method name of the caller.
+ </value>
+ <remarks>
+ <para>
+ Gets the method name of the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LocationInfo.FullInfo">
+ <summary>
+ Gets all available caller information
+ </summary>
+ <value>
+ All available caller information, in the format
+ <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+ </value>
+ <remarks>
+ <para>
+ Gets all available caller information, in the format
+ <c>fully.qualified.classname.of.caller.methodName(Filename:line)</c>
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerManager">
+ <summary>
+ Static manager that controls the creation of repositories
+ </summary>
+ <remarks>
+ <para>
+ Static manager that controls the creation of repositories
+ </para>
+ <para>
+ This class is used by the wrapper managers (e.g. <see cref="T:log4net.LogManager"/>)
+ to provide access to the <see cref="T:log4net.Core.ILogger"/> objects.
+ </para>
+ <para>
+ This manager also holds the <see cref="T:log4net.Core.IRepositorySelector"/> that is used to
+ lookup and create repositories. The selector can be set either programmatically using
+ the <see cref="P:log4net.Core.LoggerManager.RepositorySelector"/> property, or by setting the <c>log4net.RepositorySelector</c>
+ AppSetting in the applications config file to the fully qualified type name of the
+ selector to use.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.#ctor">
+ <summary>
+ Private constructor to prevent instances. Only static methods should be used.
+ </summary>
+ <remarks>
+ <para>
+ Private constructor to prevent instances. Only static methods should be used.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.#cctor">
+ <summary>
+ Hook the shutdown event
+ </summary>
+ <remarks>
+ <para>
+ On the full .NET runtime, the static constructor hooks up the
+ <c>AppDomain.ProcessExit</c> and <c>AppDomain.DomainUnload</c>> events.
+ These are used to shutdown the log4net system as the application exits.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.RegisterAppDomainEvents">
+ <summary>
+ Register for ProcessExit and DomainUnload events on the AppDomain
+ </summary>
+ <remarks>
+ <para>
+ This needs to be in a separate method because the events make
+ a LinkDemand for the ControlAppDomain SecurityPermission. Because
+ this is a LinkDemand it is demanded at JIT time. Therefore we cannot
+ catch the exception in the method itself, we have to catch it in the
+ caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLoggerRepository(System.String)">
+ <summary>
+ Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repository">the repository to lookup in</param>
+ <returns>Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLoggerRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetRepository(System.String)">
+ <summary>
+ Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repository">the repository to lookup in</param>
+ <returns>Return the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Exists(System.String,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the named logger does not exist in the
+ specified repository.
+ </returns>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Exists(System.Reflection.Assembly,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the named logger does not exist in the
+ specified assembly's repository.
+ </returns>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified assembly's repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetCurrentLoggers(System.String)">
+ <summary>
+ Returns all the currently defined loggers in the specified repository.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <returns>All the defined loggers.</returns>
+ <remarks>
+ <para>
+ The root logger is <b>not</b> included in the returned array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetCurrentLoggers(System.Reflection.Assembly)">
+ <summary>
+ Returns all the currently defined loggers in the specified assembly's repository.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <returns>All the defined loggers.</returns>
+ <remarks>
+ <para>
+ The root logger is <b>not</b> included in the returned array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.String,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.Reflection.Assembly,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.String,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Gets the logger for the fully qualified name of the type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetLogger(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <param name="repositoryAssembly">the assembly to use to lookup the repository</param>
+ <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ <remarks>
+ <para>
+ Gets the logger for the fully qualified name of the type specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.Shutdown">
+ <summary>
+ Shuts down the log4net system.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in all the
+ default repositories.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ShutdownRepository(System.String)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <param name="repository">The repository to shutdown.</param>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository for the <paramref name="repository"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ShutdownRepository(System.Reflection.Assembly)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository for the repository. The repository is looked up using
+ the <paramref name="repositoryAssembly"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ResetConfiguration(System.String)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <param name="repository">The repository to reset.</param>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.ResetConfiguration(System.Reflection.Assembly)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository to reset.</param>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An Exception will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An Exception will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateDomain(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.Core.LoggerManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetAllRepositories">
+ <summary>
+ Gets an array of all currently defined repositories.
+ </summary>
+ <returns>An array of all the known <see cref="T:log4net.Repository.ILoggerRepository"/> objects.</returns>
+ <remarks>
+ <para>
+ Gets an array of all currently defined repositories.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.GetVersionInfo">
+ <summary>
+ Internal method to get pertinent version info.
+ </summary>
+ <returns>A string of version info.</returns>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.OnDomainUnload(System.Object,System.EventArgs)">
+ <summary>
+ Called when the <see cref="E:System.AppDomain.DomainUnload"/> event fires
+ </summary>
+ <param name="sender">the <see cref="T:System.AppDomain"/> that is exiting</param>
+ <param name="e">null</param>
+ <remarks>
+ <para>
+ Called when the <see cref="E:System.AppDomain.DomainUnload"/> event fires.
+ </para>
+ <para>
+ When the event is triggered the log4net system is <see cref="M:log4net.Core.LoggerManager.Shutdown"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggerManager.OnProcessExit(System.Object,System.EventArgs)">
+ <summary>
+ Called when the <see cref="E:System.AppDomain.ProcessExit"/> event fires
+ </summary>
+ <param name="sender">the <see cref="T:System.AppDomain"/> that is exiting</param>
+ <param name="e">null</param>
+ <remarks>
+ <para>
+ Called when the <see cref="E:System.AppDomain.ProcessExit"/> event fires.
+ </para>
+ <para>
+ When the event is triggered the log4net system is <see cref="M:log4net.Core.LoggerManager.Shutdown"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerManager.s_repositorySelector">
+ <summary>
+ Initialize the default repository selector
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LoggerManager.RepositorySelector">
+ <summary>
+ Gets or sets the repository selector used by the <see cref="T:log4net.LogManager"/>.
+ </summary>
+ <value>
+ The repository selector used by the <see cref="T:log4net.LogManager"/>.
+ </value>
+ <remarks>
+ <para>
+ The repository selector (<see cref="T:log4net.Core.IRepositorySelector"/>) is used by
+ the <see cref="T:log4net.LogManager"/> to create and select repositories
+ (<see cref="T:log4net.Repository.ILoggerRepository"/>).
+ </para>
+ <para>
+ The caller to <see cref="T:log4net.LogManager"/> supplies either a string name
+ or an assembly (if not supplied the assembly is inferred using
+ <see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ <para>
+ This context is used by the selector to lookup a specific repository.
+ </para>
+ <para>
+ For the full .NET Framework, the default repository is <c>DefaultRepositorySelector</c>;
+ for the .NET Compact Framework <c>CompactRepositorySelector</c> is the default
+ repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggerWrapperImpl">
+ <summary>
+ Implementation of the <see cref="T:log4net.Core.ILoggerWrapper"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ This class should be used as the base for all wrapper implementations.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.LoggerWrapperImpl.#ctor(log4net.Core.ILogger)">
+ <summary>
+ Constructs a new wrapper for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <remarks>
+ <para>
+ Constructs a new wrapper for the specified logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggerWrapperImpl.m_logger">
+ <summary>
+ The logger that this object is wrapping
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LoggerWrapperImpl.Logger">
+ <summary>
+ Gets the implementation behind this wrapper object.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Core.ILogger"/> object that this object is implementing.
+ </value>
+ <remarks>
+ <para>
+ The <c>Logger</c> object may not be the same object as this object
+ because of logger decorators.
+ </para>
+ <para>
+ This gets the actual underlying objects that is used to process
+ the log events.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggingEventData">
+ <summary>
+ Portable data structure used by <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Portable data structure used by <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.LoggerName">
+ <summary>
+ The logger name.
+ </summary>
+ <remarks>
+ <para>
+ The logger name.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Level">
+ <summary>
+ Level of logging event.
+ </summary>
+ <remarks>
+ <para>
+ Level of logging event. Level cannot be Serializable
+ because it is a flyweight. Due to its special serialization it
+ cannot be declared final either.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Message">
+ <summary>
+ The application supplied message.
+ </summary>
+ <remarks>
+ <para>
+ The application supplied message of logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.ThreadName">
+ <summary>
+ The name of thread
+ </summary>
+ <remarks>
+ <para>
+ The name of thread in which this logging event was generated
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.TimeStamp">
+ <summary>
+ The time the event was logged
+ </summary>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.LocationInfo">
+ <summary>
+ Location information for the caller.
+ </summary>
+ <remarks>
+ <para>
+ Location information for the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.UserName">
+ <summary>
+ String representation of the user
+ </summary>
+ <remarks>
+ <para>
+ String representation of the user's windows name,
+ like DOMAIN\username
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Identity">
+ <summary>
+ String representation of the identity.
+ </summary>
+ <remarks>
+ <para>
+ String representation of the current thread's principal identity.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.ExceptionString">
+ <summary>
+ The string representation of the exception
+ </summary>
+ <remarks>
+ <para>
+ The string representation of the exception
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Domain">
+ <summary>
+ String representation of the AppDomain.
+ </summary>
+ <remarks>
+ <para>
+ String representation of the AppDomain.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEventData.Properties">
+ <summary>
+ Additional event specific properties
+ </summary>
+ <remarks>
+ <para>
+ A logger or an appender may attach additional
+ properties to specific events. These properties
+ have a string key and an object value.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.FixFlags">
+ <summary>
+ Flags passed to the <see cref="P:log4net.Core.LoggingEvent.Fix"/> property
+ </summary>
+ <remarks>
+ <para>
+ Flags passed to the <see cref="P:log4net.Core.LoggingEvent.Fix"/> property
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Mdc">
+ <summary>
+ Fix the MDC
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Ndc">
+ <summary>
+ Fix the NDC
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Message">
+ <summary>
+ Fix the rendered message
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.ThreadName">
+ <summary>
+ Fix the thread name
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.LocationInfo">
+ <summary>
+ Fix the callers location information
+ </summary>
+ <remarks>
+ CAUTION: Very slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.UserName">
+ <summary>
+ Fix the callers windows user name
+ </summary>
+ <remarks>
+ CAUTION: Slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Domain">
+ <summary>
+ Fix the domain friendly name
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Identity">
+ <summary>
+ Fix the callers principal name
+ </summary>
+ <remarks>
+ CAUTION: May be slow to generate
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Exception">
+ <summary>
+ Fix the exception text
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Properties">
+ <summary>
+ Fix the event properties
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.None">
+ <summary>
+ No fields fixed
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.All">
+ <summary>
+ All fields fixed
+ </summary>
+ </member>
+ <member name="F:log4net.Core.FixFlags.Partial">
+ <summary>
+ Partial fields fixed
+ </summary>
+ <remarks>
+ <para>
+ This set of partial fields gives good performance. The following fields are fixed:
+ </para>
+ <list type="bullet">
+ <item><description><see cref="F:log4net.Core.FixFlags.Message"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.ThreadName"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Exception"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Domain"/></description></item>
+ <item><description><see cref="F:log4net.Core.FixFlags.Properties"/></description></item>
+ </list>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LoggingEvent">
+ <summary>
+ The internal representation of logging events.
+ </summary>
+ <remarks>
+ <para>
+ When an affirmative decision is made to log then a
+ <see cref="T:log4net.Core.LoggingEvent"/> instance is created. This instance
+ is passed around to the different log4net components.
+ </para>
+ <para>
+ This class is of concern to those wishing to extend log4net.
+ </para>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ for incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.HostNameProperty">
+ <summary>
+ The key into the Properties map for the host name value.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.IdentityProperty">
+ <summary>
+ The key into the Properties map for the thread identity value.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.UserNameProperty">
+ <summary>
+ The key into the Properties map for the user name value.
+ </summary>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,System.String,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ from the supplied parameters.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="loggerName">The name of the logger of this event.</param>
+ <param name="level">The level of this event.</param>
+ <param name="message">The message of this event.</param>
+ <param name="exception">The exception for this event.</param>
+ <remarks>
+ <para>
+ Except <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>, <see cref="P:log4net.Core.LoggingEvent.Level"/> and <see cref="P:log4net.Core.LoggingEvent.LoggerName"/>,
+ all fields of <c>LoggingEvent</c> are filled when actually needed. Call
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> to cache all data locally
+ to prevent inconsistencies.
+ </para>
+ <para>This method is called by the log4net framework
+ to create a logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,log4net.Core.LoggingEventData,log4net.Core.FixFlags)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="data">Data used to initialize the logging event.</param>
+ <param name="fixedData">The fields in the <paranref name="data"/> struct that have already been fixed.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ The <paramref name="fixedData"/> parameter should be used to specify which fields in the
+ <paramref name="data"/> struct have been preset. Fields not specified in the <paramref name="fixedData"/>
+ will be captured from the environment if requested or fixed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Type,log4net.Repository.ILoggerRepository,log4net.Core.LoggingEventData)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="repository">The repository this event is logged in.</param>
+ <param name="data">Data used to initialize the logging event.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ This constructor sets this objects <see cref="P:log4net.Core.LoggingEvent.Fix"/> flags to <see cref="F:log4net.Core.FixFlags.All"/>,
+ this assumes that all the data relating to this event is passed in via the <paramref name="data"/>
+ parameter and no other data should be captured from the environment.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(log4net.Core.LoggingEventData)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ using specific data.
+ </summary>
+ <param name="data">Data used to initialize the logging event.</param>
+ <remarks>
+ <para>
+ This constructor is provided to allow a <see cref="T:log4net.Core.LoggingEvent"/>
+ to be created independently of the log4net framework. This can
+ be useful if you require a custom serialization scheme.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)"/> method to obtain an
+ instance of the <see cref="T:log4net.Core.LoggingEventData"/> class.
+ </para>
+ <para>
+ This constructor sets this objects <see cref="P:log4net.Core.LoggingEvent.Fix"/> flags to <see cref="F:log4net.Core.FixFlags.All"/>,
+ this assumes that all the data relating to this event is passed in via the <paramref name="data"/>
+ parameter and no other data should be captured from the environment.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.LoggingEvent"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.EnsureRepository(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Ensure that the repository is set.
+ </summary>
+ <param name="repository">the value for the repository</param>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)">
+ <summary>
+ Write the rendered message to a TextWriter
+ </summary>
+ <param name="writer">the writer to write the message to</param>
+ <remarks>
+ <para>
+ Unlike the <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property this method
+ does store the message data in the internal cache. Therefore
+ if called only once this method should be faster than the
+ <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property, however if the message is
+ to be accessed multiple times then the property will be more efficient.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
+ <param name="context">The destination for this serialization.</param>
+ <remarks>
+ <para>
+ The data in this event must be fixed before it can be serialized.
+ </para>
+ <para>
+ The <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> method must be called during the
+ <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method call if this event
+ is to be used outside that method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetLoggingEventData">
+ <summary>
+ Gets the portable data for this <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <returns>The <see cref="T:log4net.Core.LoggingEventData"/> for this event.</returns>
+ <remarks>
+ <para>
+ A new <see cref="T:log4net.Core.LoggingEvent"/> can be constructed using a
+ <see cref="T:log4net.Core.LoggingEventData"/> instance.
+ </para>
+ <para>
+ Does a <see cref="F:log4net.Core.FixFlags.Partial"/> fix of the data
+ in the logging event before returning the event data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetLoggingEventData(log4net.Core.FixFlags)">
+ <summary>
+ Gets the portable data for this <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <param name="fixFlags">The set of data to ensure is fixed in the LoggingEventData</param>
+ <returns>The <see cref="T:log4net.Core.LoggingEventData"/> for this event.</returns>
+ <remarks>
+ <para>
+ A new <see cref="T:log4net.Core.LoggingEvent"/> can be constructed using a
+ <see cref="T:log4net.Core.LoggingEventData"/> instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetExceptionStrRep">
+ <summary>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <returns>
+ This event's exception's rendered using the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </returns>
+ <remarks>
+ <para>
+ <b>Obsolete. Use <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/> instead.</b>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetExceptionString">
+ <summary>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <returns>
+ This event's exception's rendered using the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </returns>
+ <remarks>
+ <para>
+ Returns this event's exception's rendered using the
+ <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData">
+ <summary>
+ Fix instance fields that hold volatile data.
+ </summary>
+ <remarks>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ <para>
+ Calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> is equivalent to
+ calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> passing the parameter
+ <c>false</c>.
+ </para>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)"/> for more
+ information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData(System.Boolean)">
+ <summary>
+ Fixes instance fields that hold volatile data.
+ </summary>
+ <param name="fastButLoose">Set to <c>true</c> to not fix data that takes a long time to fix.</param>
+ <remarks>
+ <para>
+ Some of the values in instances of <see cref="T:log4net.Core.LoggingEvent"/>
+ are considered volatile, that is the values are correct at the
+ time the event is delivered to appenders, but will not be consistent
+ at any time afterwards. If an event is to be stored and then processed
+ at a later time these volatile values must be fixed by calling
+ <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/>. There is a performance penalty
+ for incurred by calling <see cref="M:log4net.Core.LoggingEvent.FixVolatileData"/> but it
+ is essential to maintaining data consistency.
+ </para>
+ <para>
+ The <paramref name="fastButLoose"/> param controls the data that
+ is fixed. Some of the data that can be fixed takes a long time to
+ generate, therefore if you do not require those settings to be fixed
+ they can be ignored by setting the <paramref name="fastButLoose"/> param
+ to <c>true</c>. This setting will ignore the <see cref="P:log4net.Core.LoggingEvent.LocationInformation"/>
+ and <see cref="P:log4net.Core.LoggingEvent.UserName"/> settings.
+ </para>
+ <para>
+ Set <paramref name="fastButLoose"/> to <c>false</c> to ensure that all
+ settings are fixed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.FixVolatileData(log4net.Core.FixFlags)">
+ <summary>
+ Fix the fields specified by the <see cref="T:log4net.Core.FixFlags"/> parameter
+ </summary>
+ <param name="flags">the fields to fix</param>
+ <remarks>
+ <para>
+ Only fields specified in the <paramref name="flags"/> will be fixed.
+ Fields will not be fixed if they have previously been fixed.
+ It is not possible to 'unfix' a field.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.LookupProperty(System.String)">
+ <summary>
+ Lookup a composite property in this event
+ </summary>
+ <param name="key">the key for the property to lookup</param>
+ <returns>the value for the property</returns>
+ <remarks>
+ <para>
+ This event has composite properties that combine together properties from
+ several different contexts in the following order:
+ <list type="definition">
+ <item>
+ <term>this events properties</term>
+ <description>
+ This event has <see cref="P:log4net.Core.LoggingEvent.Properties"/> that can be set. These
+ properties are specific to this event only.
+ </description>
+ </item>
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LoggingEvent.GetProperties">
+ <summary>
+ Get all the composite properties in this event
+ </summary>
+ <returns>the <see cref="T:log4net.Util.PropertiesDictionary"/> containing all the properties</returns>
+ <remarks>
+ <para>
+ See <see cref="M:log4net.Core.LoggingEvent.LookupProperty(System.String)"/> for details of the composite properties
+ stored by the event.
+ </para>
+ <para>
+ This method returns a single <see cref="T:log4net.Util.PropertiesDictionary"/> containing all the
+ properties defined for this event.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_data">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_compositeProperties">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_eventProperties">
+ <summary>
+ The internal logging event data.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_callerStackBoundaryDeclaringType">
+ <summary>
+ The fully qualified Type of the calling
+ logger class in the stack frame (i.e. the declaring type of the method).
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_message">
+ <summary>
+ The application supplied message of logging event.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_thrownException">
+ <summary>
+ The exception that was thrown.
+ </summary>
+ <remarks>
+ This is not serialized. The string representation
+ is serialized instead.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_repository">
+ <summary>
+ The repository that generated the logging event
+ </summary>
+ <remarks>
+ This is not serialized.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_fixFlags">
+ <summary>
+ The fix state for this event
+ </summary>
+ <remarks>
+ These flags indicate which fields have been fixed.
+ Not serialized.
+ </remarks>
+ </member>
+ <member name="F:log4net.Core.LoggingEvent.m_cacheUpdatable">
+ <summary>
+ Indicated that the internal cache is updateable (ie not fixed)
+ </summary>
+ <remarks>
+ This is a seperate flag to m_fixFlags as it allows incrementel fixing and simpler
+ changes in the caching strategy.
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.StartTime">
+ <summary>
+ Gets the time when the current process started.
+ </summary>
+ <value>
+ This is the time when this process started.
+ </value>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ <para>
+ Tries to get the start time for the current process.
+ Failing that it returns the time of the first call to
+ this property.
+ </para>
+ <para>
+ Note that AppDomains may be loaded and unloaded within the
+ same process without the process terminating and therefore
+ without the process start time being reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Level">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.Level"/> of the logging event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.TimeStamp">
+ <summary>
+ Gets the time of the logging event.
+ </summary>
+ <value>
+ The time of the logging event.
+ </value>
+ <remarks>
+ <para>
+ The TimeStamp is stored in the local time zone for this computer.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.LoggerName">
+ <summary>
+ Gets the name of the logger that logged the event.
+ </summary>
+ <value>
+ The name of the logger that logged the event.
+ </value>
+ <remarks>
+ <para>
+ Gets the name of the logger that logged the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.LocationInformation">
+ <summary>
+ Gets the location information for this logging event.
+ </summary>
+ <value>
+ The location information for this logging event.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Core.LocationInfo"/> class for more information on
+ supported frameworks and the different behavior in Debug and
+ Release builds.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.MessageObject">
+ <summary>
+ Gets the message object used to initialize this event.
+ </summary>
+ <value>
+ The message object used to initialize this event.
+ </value>
+ <remarks>
+ <para>
+ Gets the message object used to initialize this event.
+ Note that this event may not have a valid message object.
+ If the event is serialized the message object will not
+ be transferred. To get the text of the message the
+ <see cref="P:log4net.Core.LoggingEvent.RenderedMessage"/> property must be used
+ not this property.
+ </para>
+ <para>
+ If there is no defined message object for this event then
+ null will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.ExceptionObject">
+ <summary>
+ Gets the exception object used to initialize this event.
+ </summary>
+ <value>
+ The exception object used to initialize this event.
+ </value>
+ <remarks>
+ <para>
+ Gets the exception object used to initialize this event.
+ Note that this event may not have a valid exception object.
+ If the event is serialized the exception object will not
+ be transferred. To get the text of the exception the
+ <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/> method must be used
+ not this property.
+ </para>
+ <para>
+ If there is no defined exception object for this event then
+ null will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Repository">
+ <summary>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this event was created in.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this event was created in.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.RenderedMessage">
+ <summary>
+ Gets the message, rendered through the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </summary>
+ <value>
+ The message rendered through the <see cref="P:log4net.Repository.ILoggerRepository.RendererMap"/>.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.ThreadName">
+ <summary>
+ Gets the name of the current thread.
+ </summary>
+ <value>
+ The name of the current thread, or the thread ID when
+ the name is not available.
+ </value>
+ <remarks>
+ <para>
+ The collected information is cached for future use.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.UserName">
+ <summary>
+ Gets the name of the current user.
+ </summary>
+ <value>
+ The name of the current user, or <c>NOT AVAILABLE</c> when the
+ underlying runtime has no support for retrieving the name of the
+ current user.
+ </value>
+ <remarks>
+ <para>
+ Calls <c>WindowsIdentity.GetCurrent().Name</c> to get the name of
+ the current windows user.
+ </para>
+ <para>
+ To improve performance, we could cache the string representation of
+ the name, and reuse that as long as the identity stayed constant.
+ Once the identity changed, we would need to re-assign and re-render
+ the string.
+ </para>
+ <para>
+ However, the <c>WindowsIdentity.GetCurrent()</c> call seems to
+ return different objects every time, so the current implementation
+ doesn't do this type of caching.
+ </para>
+ <para>
+ Timing for these operations:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Method</term>
+ <description>Results</description>
+ </listheader>
+ <item>
+ <term><c>WindowsIdentity.GetCurrent()</c></term>
+ <description>10000 loops, 00:00:00.2031250 seconds</description>
+ </item>
+ <item>
+ <term><c>WindowsIdentity.GetCurrent().Name</c></term>
+ <description>10000 loops, 00:00:08.0468750 seconds</description>
+ </item>
+ </list>
+ <para>
+ This means we could speed things up almost 40 times by caching the
+ value of the <c>WindowsIdentity.GetCurrent().Name</c> property, since
+ this takes (8.04-0.20) = 7.84375 seconds.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Identity">
+ <summary>
+ Gets the identity of the current thread principal.
+ </summary>
+ <value>
+ The string name of the identity of the current thread principal.
+ </value>
+ <remarks>
+ <para>
+ Calls <c>System.Threading.Thread.CurrentPrincipal.Identity.Name</c> to get
+ the name of the current thread principal.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Domain">
+ <summary>
+ Gets the AppDomain friendly name.
+ </summary>
+ <value>
+ The AppDomain friendly name.
+ </value>
+ <remarks>
+ <para>
+ Gets the AppDomain friendly name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Properties">
+ <summary>
+ Additional event specific properties.
+ </summary>
+ <value>
+ Additional event specific properties.
+ </value>
+ <remarks>
+ <para>
+ A logger or an appender may attach additional
+ properties to specific events. These properties
+ have a string key and an object value.
+ </para>
+ <para>
+ This property is for events that have been added directly to
+ this event. The aggregate properties (which include these
+ event properties) can be retrieved using <see cref="M:log4net.Core.LoggingEvent.LookupProperty(System.String)"/>
+ and <see cref="M:log4net.Core.LoggingEvent.GetProperties"/>.
+ </para>
+ <para>
+ Once the properties have been fixed <see cref="P:log4net.Core.LoggingEvent.Fix"/> this property
+ returns the combined cached properties. This ensures that updates to
+ this property are always reflected in the underlying storage. When
+ returning the combined properties there may be more keys in the
+ Dictionary than expected.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LoggingEvent.Fix">
+ <summary>
+ The fixed fields in this event
+ </summary>
+ <value>
+ The set of fields that are fixed in this event
+ </value>
+ <remarks>
+ <para>
+ Fields will not be fixed if they have previously been fixed.
+ It is not possible to 'unfix' a field.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.LogImpl">
+ <summary>
+ Implementation of <see cref="T:log4net.ILog"/> wrapper interface.
+ </summary>
+ <remarks>
+ <para>
+ This implementation of the <see cref="T:log4net.ILog"/> interface
+ forwards to the <see cref="T:log4net.Core.ILogger"/> held by the base class.
+ </para>
+ <para>
+ This logger has methods to allow the caller to log at the following
+ levels:
+ </para>
+ <list type="definition">
+ <item>
+ <term>DEBUG</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>DEBUG</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Debug"/>. The <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>INFO</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>INFO</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Info"/>. The <see cref="P:log4net.Core.LogImpl.IsInfoEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>WARN</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>WARN</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Warn"/>. The <see cref="P:log4net.Core.LogImpl.IsWarnEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>ERROR</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>ERROR</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Error"/>. The <see cref="P:log4net.Core.LogImpl.IsErrorEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ <item>
+ <term>FATAL</term>
+ <description>
+ The <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/> and <see cref="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object[])"/> methods log messages
+ at the <c>FATAL</c> level. That is the level with that name defined in the
+ repositories <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/>. The default value
+ for this level is <see cref="F:log4net.Core.Level.Fatal"/>. The <see cref="P:log4net.Core.LogImpl.IsFatalEnabled"/>
+ property tests if this level is enabled for logging.
+ </description>
+ </item>
+ </list>
+ <para>
+ The values for these levels and their semantic meanings can be changed by
+ configuring the <see cref="P:log4net.Repository.ILoggerRepository.LevelMap"/> for the repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.ILog">
+ <summary>
+ The ILog interface is use by application to log messages into
+ the log4net framework.
+ </summary>
+ <remarks>
+ <para>
+ Use the <see cref="T:log4net.LogManager"/> to obtain logger instances
+ that implement this interface. The <see cref="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)"/>
+ static method is used to get logger instances.
+ </para>
+ <para>
+ This class contains methods for logging at different levels and also
+ has properties for determining if those logging levels are
+ enabled in the current configuration.
+ </para>
+ <para>
+ This interface can be implemented in different ways. This documentation
+ specifies reasonable behavior that a caller can expect from the actual
+ implementation, however different implementations reserve the right to
+ do things differently.
+ </para>
+ </remarks>
+ <example>Simple example of logging messages
+ <code lang="C#">
+ ILog log = LogManager.GetLogger("application-log");
+
+ log.Info("Application Start");
+ log.Debug("This is a debug message");
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is another debug message");
+ }
+ </code>
+ </example>
+ <seealso cref="T:log4net.LogManager"/>
+ <seealso cref="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ILog.Debug(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>DEBUG</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Debug"/> level. If this logger is
+ <c>DEBUG</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of
+ the additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Debug(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Debug"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Debug(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object[])">
+ <overloads>Log a formatted string with the <see cref="F:log4net.Core.Level.Debug"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.DebugFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Debug(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Info(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Info"/> level.</overloads>
+ <summary>
+ Logs a message object with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>INFO</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Info"/> level. If this logger is
+ <c>INFO</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Info(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Info(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.InfoFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsInfoEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Warn(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>WARN</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Warn"/> level. If this logger is
+ <c>WARN</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Warn(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Warn"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Warn(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.WarnFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsWarnEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Error(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Error"/> level.</overloads>
+ <summary>
+ Logs a message object with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>ERROR</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Error"/> level. If this logger is
+ <c>ERROR</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Error(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Error"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Error(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.ErrorFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsErrorEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Fatal(System.Object)">
+ <overloads>Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level.</overloads>
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>FATAL</c>
+ enabled by comparing the level of this logger with the
+ <see cref="F:log4net.Core.Level.Fatal"/> level. If this logger is
+ <c>FATAL</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para><b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ <param name="message">The message object to log.</param>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.Fatal(System.Object,System.Exception)">
+ <summary>
+ Log a message object with the <see cref="F:log4net.Core.Level.Fatal"/> level including
+ the stack trace of the <see cref="T:System.Exception"/> passed
+ as a parameter.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ See the <see cref="M:log4net.ILog.Fatal(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object[])">
+ <overloads>Log a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.</overloads>
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="M:log4net.ILog.FatalFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <c>String.Format</c> method. See
+ <see cref="M:System.String.Format(System.String,System.Object[])"/> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.ILog.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object,System.Exception)"/>
+ <seealso cref="P:log4net.ILog.IsFatalEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsDebugEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Debug"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Debug"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ This function is intended to lessen the computational cost of
+ disabled log debug statements.
+ </para>
+ <para> For some ILog interface <c>log</c>, when you write:</para>
+ <code lang="C#">
+ log.Debug("This is entry number: " + i );
+ </code>
+ <para>
+ You incur the cost constructing the message, string construction and concatenation in
+ this case, regardless of whether the message is logged or not.
+ </para>
+ <para>
+ If you are worried about speed (who isn't), then you should write:
+ </para>
+ <code lang="C#">
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way you will not incur the cost of parameter
+ construction if debugging is disabled for <c>log</c>. On
+ the other hand, if the <c>log</c> is debug enabled, you
+ will incur the cost of evaluating whether the logger is debug
+ enabled twice. Once in <see cref="P:log4net.ILog.IsDebugEnabled"/> and once in
+ the <see cref="M:log4net.ILog.Debug(System.Object)"/>. This is an insignificant overhead
+ since evaluating a logger takes about 1% of the time it
+ takes to actually log. This is the preferred style of logging.
+ </para>
+ <para>Alternatively if your logger is available statically then the is debug
+ enabled state can be stored in a static variable like this:
+ </para>
+ <code lang="C#">
+ private static readonly bool isDebugEnabled = log.IsDebugEnabled;
+ </code>
+ <para>
+ Then when you come to log you can write:
+ </para>
+ <code lang="C#">
+ if (isDebugEnabled)
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way the debug enabled state is only queried once
+ when the class is loaded. Using a <c>private static readonly</c>
+ variable is the most efficient because it is a run time constant
+ and can be heavily optimized by the JIT compiler.
+ </para>
+ <para>
+ Of course if you use a static readonly variable to
+ hold the enabled state of the logger then you cannot
+ change the enabled state at runtime to vary the logging
+ that is produced. You have to decide if you need absolute
+ speed or runtime flexibility.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.ILog.Debug(System.Object)"/>
+ <seealso cref="M:log4net.ILog.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ </member>
+ <member name="P:log4net.ILog.IsInfoEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Info"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Info"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Info(System.Object)"/>
+ <seealso cref="M:log4net.ILog.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsWarnEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Warn"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Warn"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Warn(System.Object)"/>
+ <seealso cref="M:log4net.ILog.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsErrorEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Error"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Error"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Error(System.Object)"/>
+ <seealso cref="M:log4net.ILog.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.ILog.IsFatalEnabled">
+ <summary>
+ Checks if this logger is enabled for the <see cref="F:log4net.Core.Level.Fatal"/> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <see cref="F:log4net.Core.Level.Fatal"/> events, <c>false</c> otherwise.
+ </value>
+ <remarks>
+ For more information see <see cref="P:log4net.ILog.IsDebugEnabled"/>.
+ </remarks>
+ <seealso cref="M:log4net.ILog.Fatal(System.Object)"/>
+ <seealso cref="M:log4net.ILog.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.#ctor(log4net.Core.ILogger)">
+ <summary>
+ Construct a new wrapper for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <remarks>
+ <para>
+ Construct a new wrapper for the specified logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ReloadLevels(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Virtual method called when the configuration of the repository changes
+ </summary>
+ <param name="repository">the repository holding the levels</param>
+ <remarks>
+ <para>
+ Virtual method called when the configuration of the repository changes
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Debug(System.Object)">
+ <summary>
+ Logs a message object with the <c>DEBUG</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>DEBUG</c>
+ enabled by comparing the level of this logger with the
+ <c>DEBUG</c> level. If this logger is
+ <c>DEBUG</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Debug(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Debug(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>DEBUG</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>DEBUG</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/> passed
+ as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.DebugFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>DEBUG</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Debug(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Info(System.Object)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>INFO</c>
+ enabled by comparing the level of this logger with the
+ <c>INFO</c> level. If this logger is
+ <c>INFO</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger
+ and also higher in the hierarchy depending on the value of
+ the additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/>
+ to this method will print the name of the <see cref="T:System.Exception"/>
+ but no stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Info(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Info(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>INFO</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>INFO</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.InfoFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>INFO</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Info(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Warn(System.Object)">
+ <summary>
+ Logs a message object with the <c>WARN</c> level.
+ </summary>
+ <param name="message">the message object to log</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>WARN</c>
+ enabled by comparing the level of this logger with the
+ <c>WARN</c> level. If this logger is
+ <c>WARN</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Warn(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Warn(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>WARN</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>WARN</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.WarnFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>WARN</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Warn(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Error(System.Object)">
+ <summary>
+ Logs a message object with the <c>ERROR</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>ERROR</c>
+ enabled by comparing the level of this logger with the
+ <c>ERROR</c> level. If this logger is
+ <c>ERROR</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Error(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Error(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>ERROR</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>ERROR</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.ErrorFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>ERROR</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Error(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Fatal(System.Object)">
+ <summary>
+ Logs a message object with the <c>FATAL</c> level.
+ </summary>
+ <param name="message">The message object to log.</param>
+ <remarks>
+ <para>
+ This method first checks if this logger is <c>FATAL</c>
+ enabled by comparing the level of this logger with the
+ <c>FATAL</c> level. If this logger is
+ <c>FATAL</c> enabled, then it converts the message object
+ (passed as parameter) to a string by invoking the appropriate
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>. It then
+ proceeds to call all the registered appenders in this logger and
+ also higher in the hierarchy depending on the value of the
+ additivity flag.
+ </para>
+ <para>
+ <b>WARNING</b> Note that passing an <see cref="T:System.Exception"/> to this
+ method will print the name of the <see cref="T:System.Exception"/> but no
+ stack trace. To print a stack trace use the
+ <see cref="M:log4net.Core.LogImpl.Fatal(System.Object,System.Exception)"/> form instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.Fatal(System.Object,System.Exception)">
+ <summary>
+ Logs a message object with the <c>FATAL</c> level
+ </summary>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Logs a message object with the <c>FATAL</c> level including
+ the stack trace of the <see cref="T:System.Exception"/> <paramref name="exception"/>
+ passed as a parameter.
+ </para>
+ <para>
+ See the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/> form for more detailed information.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.String,System.Object,System.Object,System.Object)">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="arg0">An Object to format</param>
+ <param name="arg1">An Object to format</param>
+ <param name="arg2">An Object to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ The string is formatted using the <see cref="P:System.Globalization.CultureInfo.InvariantCulture"/>
+ format provider. To specify a localized provider use the
+ <see cref="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])"/> method.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.FatalFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Logs a formatted message string with the <c>FATAL</c> level.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information</param>
+ <param name="format">A String containing zero or more format items</param>
+ <param name="args">An Object array containing zero or more objects to format</param>
+ <remarks>
+ <para>
+ The message is formatted using the <see cref="M:System.String.Format(System.IFormatProvider,System.String,System.Object[])"/> method. See
+ <c>String.Format</c> for details of the syntax of the format string and the behavior
+ of the formatting.
+ </para>
+ <para>
+ This method does not take an <see cref="T:System.Exception"/> object to include in the
+ log event. To pass an <see cref="T:System.Exception"/> use one of the <see cref="M:log4net.Core.LogImpl.Fatal(System.Object)"/>
+ methods instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.LogImpl.LoggerRepositoryConfigurationChanged(System.Object,System.EventArgs)">
+ <summary>
+ Event handler for the <see cref="E:log4net.Repository.ILoggerRepository.ConfigurationChanged"/> event
+ </summary>
+ <param name="sender">the repository</param>
+ <param name="e">Empty</param>
+ </member>
+ <member name="F:log4net.Core.LogImpl.ThisDeclaringType">
+ <summary>
+ The fully qualified name of this declaring type not the type of any subclass.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsDebugEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>DEBUG</c>
+ level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>DEBUG</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ This function is intended to lessen the computational cost of
+ disabled log debug statements.
+ </para>
+ <para>
+ For some <c>log</c> Logger object, when you write:
+ </para>
+ <code lang="C#">
+ log.Debug("This is entry number: " + i );
+ </code>
+ <para>
+ You incur the cost constructing the message, concatenation in
+ this case, regardless of whether the message is logged or not.
+ </para>
+ <para>
+ If you are worried about speed, then you should write:
+ </para>
+ <code lang="C#">
+ if (log.IsDebugEnabled())
+ {
+ log.Debug("This is entry number: " + i );
+ }
+ </code>
+ <para>
+ This way you will not incur the cost of parameter
+ construction if debugging is disabled for <c>log</c>. On
+ the other hand, if the <c>log</c> is debug enabled, you
+ will incur the cost of evaluating whether the logger is debug
+ enabled twice. Once in <c>IsDebugEnabled</c> and once in
+ the <c>Debug</c>. This is an insignificant overhead
+ since evaluating a logger takes about 1% of the time it
+ takes to actually log.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsInfoEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>INFO</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>INFO</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples
+ of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.Core.LogImpl.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsWarnEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>WARN</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>WARN</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples
+ of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsErrorEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>ERROR</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>ERROR</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="P:log4net.Core.LogImpl.IsFatalEnabled">
+ <summary>
+ Checks if this logger is enabled for the <c>FATAL</c> level.
+ </summary>
+ <value>
+ <c>true</c> if this logger is enabled for <c>FATAL</c> events,
+ <c>false</c> otherwise.
+ </value>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Core.LogImpl.IsDebugEnabled"/> for more information and examples of using this method.
+ </para>
+ </remarks>
+ <seealso cref="P:log4net.ILog.IsDebugEnabled"/>
+ </member>
+ <member name="T:log4net.Core.SecurityContext">
+ <summary>
+ A SecurityContext used by log4net when interacting with protected resources
+ </summary>
+ <remarks>
+ <para>
+ A SecurityContext used by log4net when interacting with protected resources
+ for example with operating system services. This can be used to impersonate
+ a principal that has been granted privileges on the system resources.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Core.SecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate this SecurityContext
+ </summary>
+ <param name="state">State supplied by the caller</param>
+ <returns>An <see cref="T:System.IDisposable"/> instance that will
+ revoke the impersonation of this SecurityContext, or <c>null</c></returns>
+ <remarks>
+ <para>
+ Impersonate this security context. Further calls on the current
+ thread should now be made in the security context provided
+ by this object. When the <see cref="T:System.IDisposable"/> result
+ <see cref="M:System.IDisposable.Dispose"/> method is called the security
+ context of the thread should be reverted to the state it was in
+ before <see cref="M:log4net.Core.SecurityContext.Impersonate(System.Object)"/> was called.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.SecurityContextProvider">
+ <summary>
+ The <see cref="T:log4net.Core.SecurityContextProvider"/> providers default <see cref="T:log4net.Core.SecurityContext"/> instances.
+ </summary>
+ <remarks>
+ <para>
+ A configured component that interacts with potentially protected system
+ resources uses a <see cref="T:log4net.Core.SecurityContext"/> to provide the elevated
+ privileges required. If the <see cref="T:log4net.Core.SecurityContext"/> object has
+ been not been explicitly provided to the component then the component
+ will request one from this <see cref="T:log4net.Core.SecurityContextProvider"/>.
+ </para>
+ <para>
+ By default the <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> is
+ an instance of <see cref="T:log4net.Core.SecurityContextProvider"/> which returns only
+ <see cref="T:log4net.Util.NullSecurityContext"/> objects. This is a reasonable default
+ where the privileges required are not know by the system.
+ </para>
+ <para>
+ This default behavior can be overridden by subclassing the <see cref="T:log4net.Core.SecurityContextProvider"/>
+ and overriding the <see cref="M:log4net.Core.SecurityContextProvider.CreateSecurityContext(System.Object)"/> method to return
+ the desired <see cref="T:log4net.Core.SecurityContext"/> objects. The default provider
+ can be replaced by programmatically setting the value of the
+ <see cref="P:log4net.Core.SecurityContextProvider.DefaultProvider"/> property.
+ </para>
+ <para>
+ An alternative is to use the <c>log4net.Config.SecurityContextProviderAttribute</c>
+ This attribute can be applied to an assembly in the same way as the
+ <c>log4net.Config.XmlConfiguratorAttribute"</c>. The attribute takes
+ the type to use as the <see cref="T:log4net.Core.SecurityContextProvider"/> as an argument.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Core.SecurityContextProvider.s_defaultProvider">
+ <summary>
+ The default provider
+ </summary>
+ </member>
+ <member name="M:log4net.Core.SecurityContextProvider.#ctor">
+ <summary>
+ Protected default constructor to allow subclassing
+ </summary>
+ <remarks>
+ <para>
+ Protected default constructor to allow subclassing
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.SecurityContextProvider.CreateSecurityContext(System.Object)">
+ <summary>
+ Create a SecurityContext for a consumer
+ </summary>
+ <param name="consumer">The consumer requesting the SecurityContext</param>
+ <returns>An impersonation context</returns>
+ <remarks>
+ <para>
+ The default implementation is to return a <see cref="T:log4net.Util.NullSecurityContext"/>.
+ </para>
+ <para>
+ Subclasses should override this method to provide their own
+ behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Core.SecurityContextProvider.DefaultProvider">
+ <summary>
+ Gets or sets the default SecurityContextProvider
+ </summary>
+ <value>
+ The default SecurityContextProvider
+ </value>
+ <remarks>
+ <para>
+ The default provider is used by configured components that
+ require a <see cref="T:log4net.Core.SecurityContext"/> and have not had one
+ given to them.
+ </para>
+ <para>
+ By default this is an instance of <see cref="T:log4net.Core.SecurityContextProvider"/>
+ that returns <see cref="T:log4net.Util.NullSecurityContext"/> objects.
+ </para>
+ <para>
+ The default provider can be set programmatically by setting
+ the value of this property to a sub class of <see cref="T:log4net.Core.SecurityContextProvider"/>
+ that has the desired behavior.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.WrapperCreationHandler">
+ <summary>
+ Delegate used to handle creation of new wrappers.
+ </summary>
+ <param name="logger">The logger to wrap in a wrapper.</param>
+ <remarks>
+ <para>
+ Delegate used to handle creation of new wrappers. This delegate
+ is called from the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/>
+ method to construct the wrapper for the specified logger.
+ </para>
+ <para>
+ The delegate to use is supplied to the <see cref="T:log4net.Core.WrapperMap"/>
+ constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Core.WrapperMap">
+ <summary>
+ Maps between logger objects and wrapper objects.
+ </summary>
+ <remarks>
+ <para>
+ This class maintains a mapping between <see cref="T:log4net.Core.ILogger"/> objects and
+ <see cref="T:log4net.Core.ILoggerWrapper"/> objects. Use the <see cref="M:log4net.Core.WrapperMap.GetWrapper(log4net.Core.ILogger)"/> method to
+ lookup the <see cref="T:log4net.Core.ILoggerWrapper"/> for the specified <see cref="T:log4net.Core.ILogger"/>.
+ </para>
+ <para>
+ New wrapper instances are created by the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/>
+ method. The default behavior is for this method to delegate construction
+ of the wrapper to the <see cref="T:log4net.Core.WrapperCreationHandler"/> delegate supplied
+ to the constructor. This allows specialization of the behavior without
+ requiring subclassing of this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.#ctor(log4net.Core.WrapperCreationHandler)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Core.WrapperMap"/>
+ </summary>
+ <param name="createWrapperHandler">The handler to use to create the wrapper objects.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Core.WrapperMap"/> class with
+ the specified handler to create the wrapper objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.GetWrapper(log4net.Core.ILogger)">
+ <summary>
+ Gets the wrapper object for the specified logger.
+ </summary>
+ <returns>The wrapper object for the specified logger</returns>
+ <remarks>
+ <para>
+ If the logger is null then the corresponding wrapper is null.
+ </para>
+ <para>
+ Looks up the wrapper it it has previously been requested and
+ returns it. If the wrapper has never been requested before then
+ the <see cref="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)"/> virtual method is
+ called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.CreateNewWrapperObject(log4net.Core.ILogger)">
+ <summary>
+ Creates the wrapper object for the specified logger.
+ </summary>
+ <param name="logger">The logger to wrap in a wrapper.</param>
+ <returns>The wrapper object for the logger.</returns>
+ <remarks>
+ <para>
+ This implementation uses the <see cref="T:log4net.Core.WrapperCreationHandler"/>
+ passed to the constructor to create the wrapper. This method
+ can be overridden in a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.RepositoryShutdown(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Called when a monitored repository shutdown event is received.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that is shutting down</param>
+ <remarks>
+ <para>
+ This method is called when a <see cref="T:log4net.Repository.ILoggerRepository"/> that this
+ <see cref="T:log4net.Core.WrapperMap"/> is holding loggers for has signaled its shutdown
+ event <see cref="E:log4net.Repository.ILoggerRepository.ShutdownEvent"/>. The default
+ behavior of this method is to release the references to the loggers
+ and their wrappers generated for this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Core.WrapperMap.ILoggerRepository_Shutdown(System.Object,System.EventArgs)">
+ <summary>
+ Event handler for repository shutdown event.
+ </summary>
+ <param name="sender">The sender of the event.</param>
+ <param name="e">The event args.</param>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_repositories">
+ <summary>
+ Map of logger repositories to hashtables of ILogger to ILoggerWrapper mappings
+ </summary>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_createWrapperHandler">
+ <summary>
+ The handler to use to create the extension wrapper objects.
+ </summary>
+ </member>
+ <member name="F:log4net.Core.WrapperMap.m_shutdownHandler">
+ <summary>
+ Internal reference to the delegate used to register for repository shutdown events.
+ </summary>
+ </member>
+ <member name="P:log4net.Core.WrapperMap.Repositories">
+ <summary>
+ Gets the map of logger repositories.
+ </summary>
+ <value>
+ Map of logger repositories.
+ </value>
+ <remarks>
+ <para>
+ Gets the hashtable that is keyed on <see cref="T:log4net.Repository.ILoggerRepository"/>. The
+ values are hashtables keyed on <see cref="T:log4net.Core.ILogger"/> with the
+ value being the corresponding <see cref="T:log4net.Core.ILoggerWrapper"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.DateFormatter.AbsoluteTimeDateFormatter">
+ <summary>
+ Formats a <see cref="T:System.DateTime"/> as <c>"HH:mm:ss,fff"</c>.
+ </summary>
+ <remarks>
+ <para>
+ Formats a <see cref="T:System.DateTime"/> in the format <c>"HH:mm:ss,fff"</c> for example, <c>"15:49:37,459"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.DateFormatter.IDateFormatter">
+ <summary>
+ Render a <see cref="T:System.DateTime"/> as a string.
+ </summary>
+ <remarks>
+ <para>
+ Interface to abstract the rendering of a <see cref="T:System.DateTime"/>
+ instance into a string.
+ </para>
+ <para>
+ The <see cref="M:log4net.DateFormatter.IDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)"/> method is used to render the
+ date to a text writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.IDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Formats the specified date as a string.
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Format the <see cref="T:System.DateTime"/> as a string and write it
+ to the <see cref="T:System.IO.TextWriter"/> provided.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.AbsoluteTimeDateFormat">
+ <summary>
+ String constant used to specify AbsoluteTimeDateFormat in layouts. Current value is <b>ABSOLUTE</b>.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.DateAndTimeDateFormat">
+ <summary>
+ String constant used to specify DateTimeDateFormat in layouts. Current value is <b>DATE</b>.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.Iso8601TimeDateFormat">
+ <summary>
+ String constant used to specify ISO8601DateFormat in layouts. Current value is <b>ISO8601</b>.
+ </summary>
+ </member>
+ <member name="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Renders the date into a string. Format is <c>"HH:mm:ss"</c>.
+ </summary>
+ <param name="dateToFormat">The date to render into a string.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Subclasses should override this method to render the date
+ into a string using a precision up to the second. This method
+ will be called at most once per second and the result will be
+ reused if it is needed again during the same second.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Renders the date into a string. Format is "HH:mm:ss,fff".
+ </summary>
+ <param name="dateToFormat">The date to render into a string.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> method to generate the
+ time string up to the seconds and then appends the current
+ milliseconds. The results from <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> are
+ cached and <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/> is called at most once
+ per second.
+ </para>
+ <para>
+ Sub classes should override <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)"/>
+ rather than <see cref="M:log4net.DateFormatter.AbsoluteTimeDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeToTheSecond">
+ <summary>
+ Last stored time with precision up to the second.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeBuf">
+ <summary>
+ Last stored time with precision up to the second, formatted
+ as a string.
+ </summary>
+ </member>
+ <member name="F:log4net.DateFormatter.AbsoluteTimeDateFormatter.s_lastTimeString">
+ <summary>
+ Last stored time with precision up to the second, formatted
+ as a string.
+ </summary>
+ </member>
+ <member name="T:log4net.DateFormatter.DateTimeDateFormatter">
+ <summary>
+ Formats a <see cref="T:System.DateTime"/> as <c>"dd MMM yyyy HH:mm:ss,fff"</c>
+ </summary>
+ <remarks>
+ <para>
+ Formats a <see cref="T:System.DateTime"/> in the format
+ <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example,
+ <c>"06 Nov 1994 15:49:37,459"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Angelika Schnagl</author>
+ </member>
+ <member name="M:log4net.DateFormatter.DateTimeDateFormatter.#ctor">
+ <summary>
+ Default constructor.
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.DateTimeDateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Formats the date without the milliseconds part
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Formats a DateTime in the format <c>"dd MMM yyyy HH:mm:ss"</c>
+ for example, <c>"06 Nov 1994 15:49:37"</c>.
+ </para>
+ <para>
+ The base class will append the <c>",fff"</c> milliseconds section.
+ This method will only be called at most once per second.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.DateTimeDateFormatter.m_dateTimeFormatInfo">
+ <summary>
+ The format info for the invariant culture.
+ </summary>
+ </member>
+ <member name="T:log4net.DateFormatter.Iso8601DateFormatter">
+ <summary>
+ Formats the <see cref="T:System.DateTime"/> as <c>"yyyy-MM-dd HH:mm:ss,fff"</c>.
+ </summary>
+ <remarks>
+ <para>
+ Formats the <see cref="T:System.DateTime"/> specified as a string: <c>"yyyy-MM-dd HH:mm:ss,fff"</c>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.Iso8601DateFormatter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.Iso8601DateFormatter.FormatDateWithoutMillis(System.DateTime,System.Text.StringBuilder)">
+ <summary>
+ Formats the date without the milliseconds part
+ </summary>
+ <param name="dateToFormat">The date to format.</param>
+ <param name="buffer">The string builder to write to.</param>
+ <remarks>
+ <para>
+ Formats the date specified as a string: <c>"yyyy-MM-dd HH:mm:ss"</c>.
+ </para>
+ <para>
+ The base class will append the <c>",fff"</c> milliseconds section.
+ This method will only be called at most once per second.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.DateFormatter.SimpleDateFormatter">
+ <summary>
+ Formats the <see cref="T:System.DateTime"/> using the <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ Formats the <see cref="T:System.DateTime"/> using the <see cref="T:System.DateTime"/> <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.DateFormatter.SimpleDateFormatter.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="format">The format string.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> class
+ with the specified format string.
+ </para>
+ <para>
+ The format string must be compatible with the options
+ that can be supplied to <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.DateFormatter.SimpleDateFormatter.FormatDate(System.DateTime,System.IO.TextWriter)">
+ <summary>
+ Formats the date using <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </summary>
+ <param name="dateToFormat">The date to convert to a string.</param>
+ <param name="writer">The writer to write to.</param>
+ <remarks>
+ <para>
+ Uses the date format string supplied to the constructor to call
+ the <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/> method to format the date.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.DateFormatter.SimpleDateFormatter.m_formatString">
+ <summary>
+ The format string used to format the <see cref="T:System.DateTime"/>.
+ </summary>
+ <remarks>
+ <para>
+ The format string must be compatible with the options
+ that can be supplied to <see cref="M:System.DateTime.ToString(System.String,System.IFormatProvider)"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.DenyAllFilter">
+ <summary>
+ This filter drops all <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <remarks>
+ <para>
+ You can add this filter to the end of a filter chain to
+ switch from the default "accept all unless instructed otherwise"
+ filtering behavior to a "deny all unless instructed otherwise"
+ behavior.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.FilterSkeleton">
+ <summary>
+ Subclass this type to implement customized logging event filtering
+ </summary>
+ <remarks>
+ <para>
+ Users should extend this class to implement customized logging
+ event filtering. Note that <see cref="T:log4net.Repository.Hierarchy.Logger"/> and
+ <see cref="T:log4net.Appender.AppenderSkeleton"/>, the parent class of all standard
+ appenders, have built-in filtering rules. It is suggested that you
+ first use and understand the built-in rules before rushing to write
+ your own custom filters.
+ </para>
+ <para>
+ This abstract class assumes and also imposes that filters be
+ organized in a linear chain. The <see cref="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)"/>
+ method of each filter is called sequentially, in the order of their
+ addition to the chain.
+ </para>
+ <para>
+ The <see cref="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)"/> method must return one
+ of the integer constants <see cref="F:log4net.Filter.FilterDecision.Deny"/>,
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> or <see cref="F:log4net.Filter.FilterDecision.Accept"/>.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned, then the log event is dropped
+ immediately without consulting with the remaining filters.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned, then the next filter
+ in the chain is consulted. If there are no more filters in the
+ chain, then the log event is logged. Thus, in the presence of no
+ filters, the default behavior is to log all logging events.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, then the log
+ event is logged without consulting the remaining filters.
+ </para>
+ <para>
+ The philosophy of log4net filters is largely inspired from the
+ Linux ipchains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.IFilter">
+ <summary>
+ Implement this interface to provide customized logging event filtering
+ </summary>
+ <remarks>
+ <para>
+ Users should implement this interface to implement customized logging
+ event filtering. Note that <see cref="T:log4net.Repository.Hierarchy.Logger"/> and
+ <see cref="T:log4net.Appender.AppenderSkeleton"/>, the parent class of all standard
+ appenders, have built-in filtering rules. It is suggested that you
+ first use and understand the built-in rules before rushing to write
+ your own custom filters.
+ </para>
+ <para>
+ This abstract class assumes and also imposes that filters be
+ organized in a linear chain. The <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ method of each filter is called sequentially, in the order of their
+ addition to the chain.
+ </para>
+ <para>
+ The <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/> method must return one
+ of the integer constants <see cref="F:log4net.Filter.FilterDecision.Deny"/>,
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> or <see cref="F:log4net.Filter.FilterDecision.Accept"/>.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned, then the log event is dropped
+ immediately without consulting with the remaining filters.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned, then the next filter
+ in the chain is consulted. If there are no more filters in the
+ chain, then the log event is logged. Thus, in the presence of no
+ filters, the default behavior is to log all logging events.
+ </para>
+ <para>
+ If the value <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, then the log
+ event is logged without consulting the remaining filters.
+ </para>
+ <para>
+ The philosophy of log4net filters is largely inspired from the
+ Linux ipchains.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Decide if the logging event should be logged through an appender.
+ </summary>
+ <param name="loggingEvent">The LoggingEvent to decide upon</param>
+ <returns>The decision of the filter</returns>
+ <remarks>
+ <para>
+ If the decision is <see cref="F:log4net.Filter.FilterDecision.Deny"/>, then the event will be
+ dropped. If the decision is <see cref="F:log4net.Filter.FilterDecision.Neutral"/>, then the next
+ filter, if any, will be invoked. If the decision is <see cref="F:log4net.Filter.FilterDecision.Accept"/> then
+ the event will be logged without consulting with other filters in
+ the chain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.IFilter.Next">
+ <summary>
+ Property to get and set the next filter
+ </summary>
+ <value>
+ The next filter in the chain
+ </value>
+ <remarks>
+ <para>
+ Filters are typically composed into chains. This property allows the next filter in
+ the chain to be accessed.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.FilterSkeleton.m_next">
+ <summary>
+ Points to the next filter in the filter chain.
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Filter.FilterSkeleton.Next"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.FilterSkeleton.ActivateOptions">
+ <summary>
+ Initialize the filter with the options set
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Filter.FilterSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Typically filter's options become active immediately on set,
+ however this method must still be called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.FilterSkeleton.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Decide if the <see cref="T:log4net.Core.LoggingEvent"/> should be logged through an appender.
+ </summary>
+ <param name="loggingEvent">The <see cref="T:log4net.Core.LoggingEvent"/> to decide upon</param>
+ <returns>The decision of the filter</returns>
+ <remarks>
+ <para>
+ If the decision is <see cref="F:log4net.Filter.FilterDecision.Deny"/>, then the event will be
+ dropped. If the decision is <see cref="F:log4net.Filter.FilterDecision.Neutral"/>, then the next
+ filter, if any, will be invoked. If the decision is <see cref="F:log4net.Filter.FilterDecision.Accept"/> then
+ the event will be logged without consulting with other filters in
+ the chain.
+ </para>
+ <para>
+ This method is marked <c>abstract</c> and must be implemented
+ in a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.FilterSkeleton.Next">
+ <summary>
+ Property to get and set the next filter
+ </summary>
+ <value>
+ The next filter in the chain
+ </value>
+ <remarks>
+ <para>
+ Filters are typically composed into chains. This property allows the next filter in
+ the chain to be accessed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.DenyAllFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.DenyAllFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Always returns the integer constant <see cref="F:log4net.Filter.FilterDecision.Deny"/>
+ </summary>
+ <param name="loggingEvent">the LoggingEvent to filter</param>
+ <returns>Always returns <see cref="F:log4net.Filter.FilterDecision.Deny"/></returns>
+ <remarks>
+ <para>
+ Ignores the event being logged and just returns
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/>. This can be used to change the default filter
+ chain behavior from <see cref="F:log4net.Filter.FilterDecision.Accept"/> to <see cref="F:log4net.Filter.FilterDecision.Deny"/>. This filter
+ should only be used as the last filter in the chain
+ as any further filters will be ignored!
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.FilterDecision">
+ <summary>
+ The return result from <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ </summary>
+ <remarks>
+ <para>
+ The return result from <see cref="M:log4net.Filter.IFilter.Decide(log4net.Core.LoggingEvent)"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Deny">
+ <summary>
+ The log event must be dropped immediately without
+ consulting with the remaining filters, if any, in the chain.
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Neutral">
+ <summary>
+ This filter is neutral with respect to the log event.
+ The remaining filters, if any, should be consulted for a final decision.
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.FilterDecision.Accept">
+ <summary>
+ The log event must be logged immediately without
+ consulting with the remaining filters, if any, in the chain.
+ </summary>
+ </member>
+ <member name="T:log4net.Filter.LevelMatchFilter">
+ <summary>
+ This is a very simple filter based on <see cref="T:log4net.Core.Level"/> matching.
+ </summary>
+ <remarks>
+ <para>
+ The filter admits two options <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/> and
+ <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>. If there is an exact match between the value
+ of the <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/> option and the <see cref="T:log4net.Core.Level"/> of the
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the <see cref="M:log4net.Filter.LevelMatchFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in
+ case the <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/> option value is set
+ to <c>true</c>, if it is <c>false</c> then
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned. If the <see cref="T:log4net.Core.Level"/> does not match then
+ the result will be <see cref="F:log4net.Filter.FilterDecision.Neutral"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.LevelMatchFilter.m_acceptOnMatch">
+ <summary>
+ flag to indicate if the filter should <see cref="F:log4net.Filter.FilterDecision.Accept"/> on a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelMatchFilter.m_levelToMatch">
+ <summary>
+ the <see cref="T:log4net.Core.Level"/> to match against
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Tests if the <see cref="T:log4net.Core.Level"/> of the logging event matches that of the filter
+ </summary>
+ <param name="loggingEvent">the event to filter</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ If the <see cref="T:log4net.Core.Level"/> of the event matches the level of the
+ filter then the result of the function depends on the
+ value of <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>. If it is true then
+ the function will return <see cref="F:log4net.Filter.FilterDecision.Accept"/>, it it is false then it
+ will return <see cref="F:log4net.Filter.FilterDecision.Deny"/>. If the <see cref="T:log4net.Core.Level"/> does not match then
+ the result will be <see cref="F:log4net.Filter.FilterDecision.Neutral"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LevelMatchFilter.LevelToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Deny"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelMatchFilter.LevelToMatch">
+ <summary>
+ The <see cref="T:log4net.Core.Level"/> that the filter will match
+ </summary>
+ <remarks>
+ <para>
+ The level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelMatchFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.LevelRangeFilter">
+ <summary>
+ This is a simple filter based on <see cref="T:log4net.Core.Level"/> matching.
+ </summary>
+ <remarks>
+ <para>
+ The filter admits three options <see cref="P:log4net.Filter.LevelRangeFilter.LevelMin"/> and <see cref="P:log4net.Filter.LevelRangeFilter.LevelMax"/>
+ that determine the range of priorities that are matched, and
+ <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>. If there is a match between the range
+ of priorities and the <see cref="T:log4net.Core.Level"/> of the <see cref="T:log4net.Core.LoggingEvent"/>, then the
+ <see cref="M:log4net.Filter.LevelRangeFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in case the <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>
+ option value is set to <c>true</c>, if it is <c>false</c>
+ then <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned. If there is no match, <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when matching a <see cref="T:log4net.Core.Level"/>
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_levelMin">
+ <summary>
+ the minimum <see cref="T:log4net.Core.Level"/> value to match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LevelRangeFilter.m_levelMax">
+ <summary>
+ the maximum <see cref="T:log4net.Core.Level"/> value to match
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelRangeFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LevelRangeFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if the event should be logged.
+ </summary>
+ <param name="loggingEvent">the logging event to check</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ If the <see cref="T:log4net.Core.Level"/> of the logging event is outside the range
+ matched by this filter then <see cref="F:log4net.Filter.FilterDecision.Deny"/>
+ is returned. If the <see cref="T:log4net.Core.Level"/> is matched then the value of
+ <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/> is checked. If it is true then
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned, otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Neutral"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LevelRangeFilter.LevelMin"/> and <see cref="P:log4net.Filter.LevelRangeFilter.LevelMax"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Neutral"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.LevelMin">
+ <summary>
+ Set the minimum matched <see cref="T:log4net.Core.Level"/>
+ </summary>
+ <remarks>
+ <para>
+ The minimum level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LevelRangeFilter.LevelMax">
+ <summary>
+ Sets the maximum matched <see cref="T:log4net.Core.Level"/>
+ </summary>
+ <remarks>
+ <para>
+ The maximum level that this filter will attempt to match against the
+ <see cref="T:log4net.Core.LoggingEvent"/> level. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LevelRangeFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.LoggerMatchFilter">
+ <summary>
+ Simple filter to match a string in the event's logger name.
+ </summary>
+ <remarks>
+ <para>
+ The works very similar to the <see cref="T:log4net.Filter.LevelMatchFilter"/>. It admits two
+ options <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> and <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/>. If the
+ <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the <see cref="T:log4net.Core.LoggingEvent"/> starts
+ with the value of the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> option, then the
+ <see cref="M:log4net.Filter.LoggerMatchFilter.Decide(log4net.Core.LoggingEvent)"/> method returns <see cref="F:log4net.Filter.FilterDecision.Accept"/> in
+ case the <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> option value is set to <c>true</c>,
+ if it is <c>false</c> then <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Filter.LoggerMatchFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when we have a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.LoggerMatchFilter.m_loggerToMatch">
+ <summary>
+ The logger name string to substring match against the event
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LoggerMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.LoggerMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The rendered message is matched against the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/>.
+ If the <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/> equals the beginning of
+ the incoming <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> (<see cref="M:System.String.StartsWith(System.String)"/>)
+ then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Deny"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.LoggerMatchFilter.LoggerToMatch">
+ <summary>
+ The <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> that the filter will match
+ </summary>
+ <remarks>
+ <para>
+ This filter will attempt to match this value against logger name in
+ the following way. The match will be done against the beginning of the
+ logger name (using <see cref="M:System.String.StartsWith(System.String)"/>). The match is
+ case sensitive. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.LoggerMatchFilter.AcceptOnMatch"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.MdcFilter">
+ <summary>
+ Simple filter to match a keyed string in the <see cref="T:log4net.MDC"/>
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a keyed string in the <see cref="T:log4net.MDC"/>
+ </para>
+ <para>
+ As the MDC has been replaced with layered properties the
+ <see cref="T:log4net.Filter.PropertyFilter"/> should be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Filter.PropertyFilter">
+ <summary>
+ Simple filter to match a string an event property
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the value for a
+ specific event property
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Filter.StringMatchFilter">
+ <summary>
+ Simple filter to match a string in the rendered message
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the rendered message
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_acceptOnMatch">
+ <summary>
+ Flag to indicate the behavior when we have a match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_stringToMatch">
+ <summary>
+ The string to substring match against the message
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_stringRegexToMatch">
+ <summary>
+ A string regex to match
+ </summary>
+ </member>
+ <member name="F:log4net.Filter.StringMatchFilter.m_regexToMatch">
+ <summary>
+ A regex object to match (generated from m_stringRegexToMatch)
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.ActivateOptions">
+ <summary>
+ Initialize and precompile the Regex if required
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Filter.StringMatchFilter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Filter.StringMatchFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The rendered message is matched against the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/>.
+ If the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> occurs as a substring within
+ the message then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.AcceptOnMatch">
+ <summary>
+ <see cref="F:log4net.Filter.FilterDecision.Accept"/> when matching <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> property is a flag that determines
+ the behavior when a matching <see cref="T:log4net.Core.Level"/> is found. If the
+ flag is set to true then the filter will <see cref="F:log4net.Filter.FilterDecision.Accept"/> the
+ logging event, otherwise it will <see cref="F:log4net.Filter.FilterDecision.Neutral"/> the event.
+ </para>
+ <para>
+ The default is <c>true</c> i.e. to <see cref="F:log4net.Filter.FilterDecision.Accept"/> the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.StringToMatch">
+ <summary>
+ Sets the static string to match
+ </summary>
+ <remarks>
+ <para>
+ The string that will be substring matched against
+ the rendered message. If the message contains this
+ string then the filter will match. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/>.
+ </para>
+ <para>
+ One of <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ must be specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.StringMatchFilter.RegexToMatch">
+ <summary>
+ Sets the regular expression to match
+ </summary>
+ <remarks>
+ <para>
+ The regular expression pattern that will be matched against
+ the rendered message. If the message matches this
+ pattern then the filter will match. If a match is found then
+ the result depends on the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/>.
+ </para>
+ <para>
+ One of <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> or <see cref="P:log4net.Filter.StringMatchFilter.RegexToMatch"/>
+ must be specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Filter.PropertyFilter.m_key">
+ <summary>
+ The key to use to lookup the string from the event properties
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.PropertyFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Filter.PropertyFilter.Decide(log4net.Core.LoggingEvent)">
+ <summary>
+ Check if this filter should allow the event to be logged
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>see remarks</returns>
+ <remarks>
+ <para>
+ The event property for the <see cref="P:log4net.Filter.PropertyFilter.Key"/> is matched against
+ the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/>.
+ If the <see cref="P:log4net.Filter.StringMatchFilter.StringToMatch"/> occurs as a substring within
+ the property value then a match will have occurred. If no match occurs
+ this function will return <see cref="F:log4net.Filter.FilterDecision.Neutral"/>
+ allowing other filters to check the event. If a match occurs then
+ the value of <see cref="P:log4net.Filter.StringMatchFilter.AcceptOnMatch"/> is checked. If it is
+ true then <see cref="F:log4net.Filter.FilterDecision.Accept"/> is returned otherwise
+ <see cref="F:log4net.Filter.FilterDecision.Deny"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Filter.PropertyFilter.Key">
+ <summary>
+ The key to lookup in the event properties and then match against.
+ </summary>
+ <remarks>
+ <para>
+ The key name to use to lookup in the properties map of the
+ <see cref="T:log4net.Core.LoggingEvent"/>. The match will be performed against
+ the value of this property if it exists.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Filter.NdcFilter">
+ <summary>
+ Simple filter to match a string in the <see cref="T:log4net.NDC"/>
+ </summary>
+ <remarks>
+ <para>
+ Simple filter to match a string in the <see cref="T:log4net.NDC"/>
+ </para>
+ <para>
+ As the MDC has been replaced with named stacks stored in the
+ properties collections the <see cref="T:log4net.Filter.PropertyFilter"/> should
+ be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Filter.NdcFilter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Sets the <see cref="P:log4net.Filter.PropertyFilter.Key"/> to <c>"NDC"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.AppDomainPatternConverter">
+ <summary>
+ Write the event appdomain name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.Domain"/> to the output writer.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Layout.Pattern.PatternLayoutConverter">
+ <summary>
+ Abstract class that provides the formatting functionality that
+ derived classes need.
+ </summary>
+ <remarks>
+ Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting a logging event in a converter specific manner.
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Util.PatternConverter">
+ <summary>
+ Abstract class that provides the formatting functionality that
+ derived classes need.
+ </summary>
+ <remarks>
+ <para>
+ Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting a logging event in a converter specific manner.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.c_renderBufferSize">
+ <summary>
+ Initial buffer size
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.c_renderBufferMaxCapacity">
+ <summary>
+ Maximum buffer size before it is recycled
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.#ctor">
+ <summary>
+ Protected constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PatternConverter"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Evaluate this pattern converter and write the output to a writer.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ <remarks>
+ <para>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the appropriate way.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.SetNext(log4net.Util.PatternConverter)">
+ <summary>
+ Set the next pattern converter in the chains
+ </summary>
+ <param name="patternConverter">the pattern converter that should follow this converter in the chain</param>
+ <returns>the next converter</returns>
+ <remarks>
+ <para>
+ The PatternConverter can merge with its neighbor during this method (or a sub class).
+ Therefore the return value may or may not be the value of the argument passed in.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.Format(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the pattern converter to the writer with appropriate formatting
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ <remarks>
+ <para>
+ This method calls <see cref="M:log4net.Util.PatternConverter.Convert(System.IO.TextWriter,System.Object)"/> to allow the subclass to perform
+ appropriate conversion of the pattern converter. If formatting options have
+ been specified via the <see cref="P:log4net.Util.PatternConverter.FormattingInfo"/> then this method will
+ apply those formattings before writing the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.SpacePad(System.IO.TextWriter,System.Int32)">
+ <summary>
+ Fast space padding method.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> to which the spaces will be appended.</param>
+ <param name="length">The number of spaces to be padded.</param>
+ <remarks>
+ <para>
+ Fast space padding method.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.PatternConverter.m_option">
+ <summary>
+ The option string to the converter
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.WriteDictionary(System.IO.TextWriter,log4net.Repository.ILoggerRepository,System.Collections.IDictionary)">
+ <summary>
+ Write an dictionary to a <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="repository">a <see cref="T:log4net.Repository.ILoggerRepository"/> to use for object conversion</param>
+ <param name="value">the value to write to the writer</param>
+ <remarks>
+ <para>
+ Writes the <see cref="T:System.Collections.IDictionary"/> to a writer in the form:
+ </para>
+ <code>
+ {key1=value1, key2=value2, key3=value3}
+ </code>
+ <para>
+ If the <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ is not null then it is used to render the key and value to text, otherwise
+ the object's ToString method is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternConverter.WriteObject(System.IO.TextWriter,log4net.Repository.ILoggerRepository,System.Object)">
+ <summary>
+ Write an object to a <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="repository">a <see cref="T:log4net.Repository.ILoggerRepository"/> to use for object conversion</param>
+ <param name="value">the value to write to the writer</param>
+ <remarks>
+ <para>
+ Writes the Object to a writer. If the <see cref="T:log4net.Repository.ILoggerRepository"/> specified
+ is not null then it is used to render the object to text, otherwise
+ the object's ToString method is called.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.Next">
+ <summary>
+ Get the next pattern converter in the chain
+ </summary>
+ <value>
+ the next pattern converter in the chain
+ </value>
+ <remarks>
+ <para>
+ Get the next pattern converter in the chain
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.FormattingInfo">
+ <summary>
+ Gets or sets the formatting info for this converter
+ </summary>
+ <value>
+ The formatting info for this converter
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the formatting info for this converter
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternConverter.Option">
+ <summary>
+ Gets or sets the option value for this converter
+ </summary>
+ <summary>
+ The option for this converter
+ </summary>
+ <remarks>
+ <para>
+ Gets or sets the option value for this converter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Layout.Pattern.PatternLayoutConverter"/> class.
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the correct way.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">The <see cref="T:log4net.Core.LoggingEvent"/> on which the pattern converter should be executed.</param>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PatternLayoutConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the correct way.
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">The state object on which the pattern converter should be executed.</param>
+ </member>
+ <member name="F:log4net.Layout.Pattern.PatternLayoutConverter.m_ignoresException">
+ <summary>
+ Flag indicating if this converter handles exceptions
+ </summary>
+ <remarks>
+ <c>false</c> if this converter handles exceptions
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.Pattern.PatternLayoutConverter.IgnoresException">
+ <summary>
+ Flag indicating if this converter handles the logging event exception
+ </summary>
+ <value><c>false</c> if this converter handles the logging event exception</value>
+ <remarks>
+ <para>
+ If this converter handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then this property should be set to
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the property should be set to <c>true</c>.
+ </para>
+ <para>
+ Set this value to override a this default setting. The default
+ value is <c>true</c>, this converter does not handle the exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.AppDomainPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event appdomain name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.Domain"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.DatePatternConverter">
+ <summary>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the date of a <see cref="T:log4net.Core.LoggingEvent"/>.
+ </summary>
+ <remarks>
+ <para>
+ Render the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the writer as a string.
+ </para>
+ <para>
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the formatting of the date. The following values are allowed:
+ <list type="definition">
+ <listheader>
+ <term>Option value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>ISO8601</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> formatter.
+ Formats using the <c>"yyyy-MM-dd HH:mm:ss,fff"</c> pattern.
+ </description>
+ </item>
+ <item>
+ <term>DATE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> formatter.
+ Formats using the <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example, <c>"06 Nov 1994 15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>ABSOLUTE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/> formatter.
+ Formats using the <c>"HH:mm:ss,yyyy"</c> for example, <c>"15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ Any other pattern string uses the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> formatter.
+ This formatter passes the pattern string to the <see cref="T:System.DateTime"/>
+ <see cref="M:System.DateTime.ToString(System.String)"/> method.
+ For details on valid patterns see
+ <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">DateTimeFormatInfo Class</a>.
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> is in the local time zone and is rendered in that zone.
+ To output the time in Universal time see <see cref="T:log4net.Layout.Pattern.UtcDatePatternConverter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Layout.Pattern.DatePatternConverter.m_dateFormatter">
+ <summary>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter pattern based on the <see cref="P:log4net.Util.PatternConverter.Option"/> property.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.Pattern.DatePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.DatePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern into the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Pass the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> passed is in the local time zone.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.ExceptionPatternConverter">
+ <summary>
+ Write the exception text to the output
+ </summary>
+ <remarks>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ </para>
+ <para>
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ExceptionPatternConverter.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ExceptionPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the exception text to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ </para>
+ <para>
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.FileLocationPatternConverter">
+ <summary>
+ Writes the caller location file name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.FileName"/> for
+ the event to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.FileLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location file name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.FileName"/> for
+ the <paramref name="loggingEvent"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.FullLocationPatternConverter">
+ <summary>
+ Write the caller location info to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LocationInfo.FullInfo"/> to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.FullLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location info to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LocationInfo.FullInfo"/> to the output writer.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.IdentityPatternConverter">
+ <summary>
+ Writes the event identity to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LoggingEvent.Identity"/> to
+ the output writer.
+ </para>
+ </remarks>
+ <author>Daniel Cazzulino</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.IdentityPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the event identity to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <paramref name="loggingEvent"/>
+ <see cref="P:log4net.Core.LoggingEvent.Identity"/> to
+ the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LevelPatternConverter">
+ <summary>
+ Write the event level to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the display name of the event <see cref="P:log4net.Core.LoggingEvent.Level"/>
+ to the writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LevelPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event level to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.Level.DisplayName"/> of the <paramref name="loggingEvent"/> <see cref="P:log4net.Core.LoggingEvent.Level"/>
+ to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LineLocationPatternConverter">
+ <summary>
+ Write the caller location line number to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.LineNumber"/> for
+ the event to the output writer.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LineLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the caller location line number to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the value of the <see cref="P:log4net.Core.LocationInfo.LineNumber"/> for
+ the <paramref name="loggingEvent"/> to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.LoggerPatternConverter">
+ <summary>
+ Converter for logger name
+ </summary>
+ <remarks>
+ <para>
+ Outputs the <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="T:log4net.Layout.Pattern.NamedPatternConverter">
+ <summary>
+ Converter to output and truncate <c>'.'</c> separated strings
+ </summary>
+ <remarks>
+ <para>
+ This abstract class supports truncating a <c>'.'</c> separated string
+ to show a specified number of elements from the right hand side.
+ This is used to truncate class names that are fully qualified.
+ </para>
+ <para>
+ Subclasses should override the <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)"/> method to
+ return the fully qualified string.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Get the fully qualified string data
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>the fully qualified name</returns>
+ <remarks>
+ <para>
+ Overridden by subclasses to get the fully qualified name before the
+ precision is applied to it.
+ </para>
+ <para>
+ Return the fully qualified <c>'.'</c> (dot/period) separated string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NamedPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern to the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ Render the <see cref="M:log4net.Layout.Pattern.NamedPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)"/> to the precision
+ specified by the <see cref="P:log4net.Util.PatternConverter.Option"/> property.
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.LoggerPatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the fully qualified name of the logger
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>The fully qualified logger name</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="P:log4net.Core.LoggingEvent.LoggerName"/> of the <paramref name="loggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.MessagePatternConverter">
+ <summary>
+ Writes the event message to the output
+ </summary>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)"/> method
+ to write out the event message.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.MessagePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Writes the event message to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Core.LoggingEvent.WriteRenderedMessage(System.IO.TextWriter)"/> method
+ to write out the event message.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.MethodLocationPatternConverter">
+ <summary>
+ Write the method name to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the caller location <see cref="P:log4net.Core.LocationInfo.MethodName"/> to
+ the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.MethodLocationPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the method name to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the caller location <see cref="P:log4net.Core.LocationInfo.MethodName"/> to
+ the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.NdcPatternConverter">
+ <summary>
+ Converter to include event NDC
+ </summary>
+ <remarks>
+ <para>
+ Outputs the value of the event property named <c>NDC</c>.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.Pattern.PropertyPatternConverter"/> should be used instead.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.NdcPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the event NDC to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ As the thread context stacks are now stored in named event properties
+ this converter simply looks up the value of the <c>NDC</c> property.
+ </para>
+ <para>
+ The <see cref="T:log4net.Layout.Pattern.PropertyPatternConverter"/> should be used instead.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.PropertyPatternConverter">
+ <summary>
+ Property pattern converter
+ </summary>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.PropertyPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the property value to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.RelativeTimePatternConverter">
+ <summary>
+ Converter to output the relative time of the event
+ </summary>
+ <remarks>
+ <para>
+ Converter to output the time of the event relative to the start of the program.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.RelativeTimePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the relative time to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes out the relative time of the event in milliseconds.
+ That is the number of milliseconds between the event <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>
+ and the <see cref="P:log4net.Core.LoggingEvent.StartTime"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Pattern.RelativeTimePatternConverter.TimeDifferenceInMillis(System.DateTime,System.DateTime)">
+ <summary>
+ Helper method to get the time difference between two DateTime objects
+ </summary>
+ <param name="start">start time (in the current local time zone)</param>
+ <param name="end">end time (in the current local time zone)</param>
+ <returns>the time difference in milliseconds</returns>
+ </member>
+ <member name="T:log4net.Layout.Pattern.ThreadPatternConverter">
+ <summary>
+ Converter to include event thread name
+ </summary>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.ThreadName"/> to the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.ThreadPatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the ThreadName to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Writes the <see cref="P:log4net.Core.LoggingEvent.ThreadName"/> to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.TypeNamePatternConverter">
+ <summary>
+ Pattern converter for the class name
+ </summary>
+ <remarks>
+ <para>
+ Outputs the <see cref="P:log4net.Core.LocationInfo.ClassName"/> of the event.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.TypeNamePatternConverter.GetFullyQualifiedName(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the fully qualified name of the class
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <returns>The fully qualified type name for the caller location</returns>
+ <remarks>
+ <para>
+ Returns the <see cref="P:log4net.Core.LocationInfo.ClassName"/> of the <paramref name="loggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Pattern.UserNamePatternConverter">
+ <summary>
+ Converter to include event user name
+ </summary>
+ <author>Douglas de la Torre</author>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.UserNamePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Convert the pattern to the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ </member>
+ <member name="T:log4net.Layout.Pattern.UtcDatePatternConverter">
+ <summary>
+ Write the TimeStamp to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the date of a <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ <para>
+ Uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/>
+ in Universal time.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Layout.Pattern.DatePatternConverter"/> for details on the date pattern syntax.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Layout.Pattern.DatePatternConverter"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.Pattern.UtcDatePatternConverter.Convert(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Write the TimeStamp to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Pass the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> passed is in the local time zone, this is converted
+ to Universal time before it is rendered.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Layout.Pattern.DatePatternConverter"/>
+ </member>
+ <member name="T:log4net.Layout.ExceptionLayout">
+ <summary>
+ A Layout that renders only the Exception text from the logging event
+ </summary>
+ <remarks>
+ <para>
+ A Layout that renders only the Exception text from the logging event.
+ </para>
+ <para>
+ This Layout should only be used with appenders that utilize multiple
+ layouts (e.g. <see cref="T:log4net.Appender.AdoNetAppender"/>).
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.LayoutSkeleton">
+ <summary>
+ Extend this abstract class to create your own log layout format.
+ </summary>
+ <remarks>
+ <para>
+ This is the base implementation of the <see cref="T:log4net.Layout.ILayout"/>
+ interface. Most layout objects should extend this class.
+ </para>
+ </remarks>
+ <remarks>
+ <note type="inheritinfo">
+ <para>
+ Subclasses must implement the <see cref="M:log4net.Layout.LayoutSkeleton.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/>
+ method.
+ </para>
+ <para>
+ Subclasses should set the <see cref="P:log4net.Layout.LayoutSkeleton.IgnoresException"/> in their default
+ constructor.
+ </para>
+ </note>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.ILayout">
+ <summary>
+ Interface implemented by layout objects
+ </summary>
+ <remarks>
+ <para>
+ An <see cref="T:log4net.Layout.ILayout"/> object is used to format a <see cref="T:log4net.Core.LoggingEvent"/>
+ as text. The <see cref="M:log4net.Layout.ILayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/> method is called by an
+ appender to transform the <see cref="T:log4net.Core.LoggingEvent"/> into a string.
+ </para>
+ <para>
+ The layout can also supply <see cref="P:log4net.Layout.ILayout.Header"/> and <see cref="P:log4net.Layout.ILayout.Footer"/>
+ text that is appender before any events and after all the events respectively.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.ILayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">The event to format</param>
+ <remarks>
+ <para>
+ This method is called by an appender to format
+ the <paramref name="loggingEvent"/> as text and output to a writer.
+ </para>
+ <para>
+ If the caller does not have a <see cref="T:System.IO.TextWriter"/> and prefers the
+ event to be formatted as a <see cref="T:System.String"/> then the following
+ code can be used to format the event into a <see cref="T:System.IO.StringWriter"/>.
+ </para>
+ <code lang="C#">
+ StringWriter writer = new StringWriter();
+ Layout.Format(writer, loggingEvent);
+ string formattedEvent = writer.ToString();
+ </code>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.ContentType">
+ <summary>
+ The content type output by this layout.
+ </summary>
+ <value>The content type</value>
+ <remarks>
+ <para>
+ The content type output by this layout.
+ </para>
+ <para>
+ This is a MIME type e.g. <c>"text/plain"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.Header">
+ <summary>
+ The header for the layout format.
+ </summary>
+ <value>the layout header</value>
+ <remarks>
+ <para>
+ The Header text will be appended before any logging events
+ are formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.Footer">
+ <summary>
+ The footer for the layout format.
+ </summary>
+ <value>the layout footer</value>
+ <remarks>
+ <para>
+ The Footer text will be appended after all the logging events
+ have been formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.ILayout.IgnoresException">
+ <summary>
+ Flag indicating if this layout handle exceptions
+ </summary>
+ <value><c>false</c> if this layout handles exceptions</value>
+ <remarks>
+ <para>
+ If this layout handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the layout should return
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the layout should return <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_header">
+ <summary>
+ The header text
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Layout.LayoutSkeleton.Header"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_footer">
+ <summary>
+ The footer text
+ </summary>
+ <remarks>
+ <para>
+ See <see cref="P:log4net.Layout.LayoutSkeleton.Footer"/> for more information.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.LayoutSkeleton.m_ignoresException">
+ <summary>
+ Flag indicating if this layout handles exceptions
+ </summary>
+ <remarks>
+ <para>
+ <c>false</c> if this layout handles exceptions
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.#ctor">
+ <summary>
+ Empty default constructor
+ </summary>
+ <remarks>
+ <para>
+ Empty default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.ActivateOptions">
+ <summary>
+ Activate component options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.LayoutSkeleton.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ This method must be implemented by the subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.LayoutSkeleton.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">The event to format</param>
+ <remarks>
+ <para>
+ This method is called by an appender to format
+ the <paramref name="loggingEvent"/> as text.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.ContentType">
+ <summary>
+ The content type output by this layout.
+ </summary>
+ <value>The content type is <c>"text/plain"</c></value>
+ <remarks>
+ <para>
+ The content type output by this layout.
+ </para>
+ <para>
+ This base class uses the value <c>"text/plain"</c>.
+ To change this value a subclass must override this
+ property.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.Header">
+ <summary>
+ The header for the layout format.
+ </summary>
+ <value>the layout header</value>
+ <remarks>
+ <para>
+ The Header text will be appended before any logging events
+ are formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.Footer">
+ <summary>
+ The footer for the layout format.
+ </summary>
+ <value>the layout footer</value>
+ <remarks>
+ <para>
+ The Footer text will be appended after all the logging events
+ have been formatted and appended.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.LayoutSkeleton.IgnoresException">
+ <summary>
+ Flag indicating if this layout handles exceptions
+ </summary>
+ <value><c>false</c> if this layout handles exceptions</value>
+ <remarks>
+ <para>
+ If this layout handles the exception object contained within
+ <see cref="T:log4net.Core.LoggingEvent"/>, then the layout should return
+ <c>false</c>. Otherwise, if the layout ignores the exception
+ object, then the layout should return <c>true</c>.
+ </para>
+ <para>
+ Set this value to override a this default setting. The default
+ value is <c>true</c>, this layout does not handle the exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Constructs a ExceptionLayout
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.ActivateOptions">
+ <summary>
+ Activate component options
+ </summary>
+ <remarks>
+ <para>
+ Part of the <see cref="T:log4net.Core.IOptionHandler"/> component activation
+ framework.
+ </para>
+ <para>
+ This method does nothing as options become effective immediately.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.ExceptionLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the exception text from the logging event
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <param name="loggingEvent">the event being logged</param>
+ <remarks>
+ <para>
+ Write the exception string to the <see cref="T:System.IO.TextWriter"/>.
+ The exception string is retrieved from <see cref="M:log4net.Core.LoggingEvent.GetExceptionString"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.IRawLayout">
+ <summary>
+ Interface for raw layout objects
+ </summary>
+ <remarks>
+ <para>
+ Interface used to format a <see cref="T:log4net.Core.LoggingEvent"/>
+ to an object.
+ </para>
+ <para>
+ This interface should not be confused with the
+ <see cref="T:log4net.Layout.ILayout"/> interface. This interface is used in
+ only certain specialized situations where a raw object is
+ required rather than a formatted string. The <see cref="T:log4net.Layout.ILayout"/>
+ is not generally useful than this interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.IRawLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Implement this method to create your own layout format.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the formatted event</returns>
+ <remarks>
+ <para>
+ Implement this method to create your own layout format.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.Layout2RawLayoutAdapter">
+ <summary>
+ Adapts any <see cref="T:log4net.Layout.ILayout"/> to a <see cref="T:log4net.Layout.IRawLayout"/>
+ </summary>
+ <remarks>
+ <para>
+ Where an <see cref="T:log4net.Layout.IRawLayout"/> is required this adapter
+ allows a <see cref="T:log4net.Layout.ILayout"/> to be specified.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Layout.Layout2RawLayoutAdapter.m_layout">
+ <summary>
+ The layout to adapt
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.Layout2RawLayoutAdapter.#ctor(log4net.Layout.ILayout)">
+ <summary>
+ Construct a new adapter
+ </summary>
+ <param name="layout">the layout to adapt</param>
+ <remarks>
+ <para>
+ Create the adapter for the specified <paramref name="layout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.Layout2RawLayoutAdapter.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Format the logging event as an object.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the formatted event</returns>
+ <remarks>
+ <para>
+ Format the logging event as an object.
+ </para>
+ <para>
+ Uses the <see cref="T:log4net.Layout.ILayout"/> object supplied to
+ the constructor to perform the formatting.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.PatternLayout">
+ <summary>
+ A flexible layout configurable with pattern string.
+ </summary>
+ <remarks>
+ <para>
+ The goal of this class is to <see cref="M:log4net.Layout.PatternLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)"/> a
+ <see cref="T:log4net.Core.LoggingEvent"/> as a string. The results
+ depend on the <i>conversion pattern</i>.
+ </para>
+ <para>
+ The conversion pattern is closely related to the conversion
+ pattern of the printf function in C. A conversion pattern is
+ composed of literal text and format control expressions called
+ <i>conversion specifiers</i>.
+ </para>
+ <para>
+ <i>You are free to insert any literal text within the conversion
+ pattern.</i>
+ </para>
+ <para>
+ Each conversion specifier starts with a percent sign (%) and is
+ followed by optional <i>format modifiers</i> and a <i>conversion
+ pattern name</i>. The conversion pattern name specifies the type of
+ data, e.g. logger, level, date, thread name. The format
+ modifiers control such things as field width, padding, left and
+ right justification. The following is a simple example.
+ </para>
+ <para>
+ Let the conversion pattern be <b>"%-5level [%thread]: %message%newline"</b> and assume
+ that the log4net environment was set to use a PatternLayout. Then the
+ statements
+ </para>
+ <code lang="C#">
+ ILog log = LogManager.GetLogger(typeof(TestApp));
+ log.Debug("Message 1");
+ log.Warn("Message 2");
+ </code>
+ <para>would yield the output</para>
+ <code>
+ DEBUG [main]: Message 1
+ WARN [main]: Message 2
+ </code>
+ <para>
+ Note that there is no explicit separator between text and
+ conversion specifiers. The pattern parser knows when it has reached
+ the end of a conversion specifier when it reads a conversion
+ character. In the example above the conversion specifier
+ <b>%-5level</b> means the level of the logging event should be left
+ justified to a width of five characters.
+ </para>
+ <para>
+ The recognized conversion pattern names are:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Conversion Pattern Name</term>
+ <description>Effect</description>
+ </listheader>
+ <item>
+ <term>a</term>
+ <description>Equivalent to <b>appdomain</b></description>
+ </item>
+ <item>
+ <term>appdomain</term>
+ <description>
+ Used to output the friendly name of the AppDomain where the
+ logging event was generated.
+ </description>
+ </item>
+ <item>
+ <term>c</term>
+ <description>Equivalent to <b>logger</b></description>
+ </item>
+ <item>
+ <term>C</term>
+ <description>Equivalent to <b>type</b></description>
+ </item>
+ <item>
+ <term>class</term>
+ <description>Equivalent to <b>type</b></description>
+ </item>
+ <item>
+ <term>d</term>
+ <description>Equivalent to <b>date</b></description>
+ </item>
+ <item>
+ <term>date</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in the local time zone.
+ To output the date in universal time use the <c>%utcdate</c> pattern.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
+ <b>%date{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>exception</term>
+ <description>
+ <para>
+ Used to output the exception passed in with the log message.
+ </para>
+ <para>
+ If an exception object is stored in the logging event
+ it will be rendered into the pattern output with a
+ trailing newline.
+ If there is no exception then nothing will be output
+ and no trailing newline will be appended.
+ It is typical to put a newline before the exception
+ and to have the exception as the last data in the pattern.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>F</term>
+ <description>Equivalent to <b>file</b></description>
+ </item>
+ <item>
+ <term>file</term>
+ <description>
+ <para>
+ Used to output the file name where the logging request was
+ issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>identity</term>
+ <description>
+ <para>
+ Used to output the user name for the currently active user
+ (Principal.Identity.Name).
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>l</term>
+ <description>Equivalent to <b>location</b></description>
+ </item>
+ <item>
+ <term>L</term>
+ <description>Equivalent to <b>line</b></description>
+ </item>
+ <item>
+ <term>location</term>
+ <description>
+ <para>
+ Used to output location information of the caller which generated
+ the logging event.
+ </para>
+ <para>
+ The location information depends on the CLI implementation but
+ usually consists of the fully qualified name of the calling
+ method followed by the callers source the file name and line
+ number between parentheses.
+ </para>
+ <para>
+ The location information can be very useful. However, its
+ generation is <b>extremely</b> slow. Its use should be avoided
+ unless execution speed is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>level</term>
+ <description>
+ <para>
+ Used to output the level of the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>line</term>
+ <description>
+ <para>
+ Used to output the line number from where the logging request
+ was issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>logger</term>
+ <description>
+ <para>
+ Used to output the logger of the logging event. The
+ logger conversion specifier can be optionally followed by
+ <i>precision specifier</i>, that is a decimal constant in
+ brackets.
+ </para>
+ <para>
+ If a precision specifier is given, then only the corresponding
+ number of right most components of the logger name will be
+ printed. By default the logger name is printed in full.
+ </para>
+ <para>
+ For example, for the logger name "a.b.c" the pattern
+ <b>%logger{2}</b> will output "b.c".
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>m</term>
+ <description>Equivalent to <b>message</b></description>
+ </item>
+ <item>
+ <term>M</term>
+ <description>Equivalent to <b>method</b></description>
+ </item>
+ <item>
+ <term>message</term>
+ <description>
+ <para>
+ Used to output the application supplied message associated with
+ the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>mdc</term>
+ <description>
+ <para>
+ The MDC (old name for the ThreadContext.Properties) is now part of the
+ combined event properties. This pattern is supported for compatibility
+ but is equivalent to <b>property</b>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>method</term>
+ <description>
+ <para>
+ Used to output the method name where the logging request was
+ issued.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller location information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>n</term>
+ <description>Equivalent to <b>newline</b></description>
+ </item>
+ <item>
+ <term>newline</term>
+ <description>
+ <para>
+ Outputs the platform dependent line separator character or
+ characters.
+ </para>
+ <para>
+ This conversion pattern offers the same performance as using
+ non-portable line separator strings such as "\n", or "\r\n".
+ Thus, it is the preferred way of specifying a line separator.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>ndc</term>
+ <description>
+ <para>
+ Used to output the NDC (nested diagnostic context) associated
+ with the thread that generated the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>p</term>
+ <description>Equivalent to <b>level</b></description>
+ </item>
+ <item>
+ <term>P</term>
+ <description>Equivalent to <b>property</b></description>
+ </item>
+ <item>
+ <term>properties</term>
+ <description>Equivalent to <b>property</b></description>
+ </item>
+ <item>
+ <term>property</term>
+ <description>
+ <para>
+ Used to output the an event specific property. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%property{user}</b> would include the value
+ from the property that is keyed by the string 'user'. Each property value
+ that is to be included in the log must be specified separately.
+ Properties are added to events by loggers or appenders. By default
+ the <c>log4net:HostName</c> property is set to the name of machine on
+ which the event was originally logged.
+ </para>
+ <para>
+ If no key is specified, e.g. <b>%property</b> then all the keys and their
+ values are printed in a comma separated list.
+ </para>
+ <para>
+ The properties of an event are combined from a number of different
+ contexts. These are listed below in the order in which they are searched.
+ </para>
+ <list type="definition">
+ <item>
+ <term>the event properties</term>
+ <description>
+ The event has <see cref="P:log4net.Core.LoggingEvent.Properties"/> that can be set. These
+ properties are specific to this event only.
+ </description>
+ </item>
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+
+ </description>
+ </item>
+ <item>
+ <term>r</term>
+ <description>Equivalent to <b>timestamp</b></description>
+ </item>
+ <item>
+ <term>t</term>
+ <description>Equivalent to <b>thread</b></description>
+ </item>
+ <item>
+ <term>timestamp</term>
+ <description>
+ <para>
+ Used to output the number of milliseconds elapsed since the start
+ of the application until the creation of the logging event.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>thread</term>
+ <description>
+ <para>
+ Used to output the name of the thread that generated the
+ logging event. Uses the thread number if no name is available.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>type</term>
+ <description>
+ <para>
+ Used to output the fully qualified type name of the caller
+ issuing the logging request. This conversion specifier
+ can be optionally followed by <i>precision specifier</i>, that
+ is a decimal constant in brackets.
+ </para>
+ <para>
+ If a precision specifier is given, then only the corresponding
+ number of right most components of the class name will be
+ printed. By default the class name is output in fully qualified form.
+ </para>
+ <para>
+ For example, for the class name "log4net.Layout.PatternLayout", the
+ pattern <b>%type{1}</b> will output "PatternLayout".
+ </para>
+ <para>
+ <b>WARNING</b> Generating the caller class information is
+ slow. Thus, its use should be avoided unless execution speed is
+ not an issue.
+ </para>
+ <para>
+ See the note below on the availability of caller location information.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>u</term>
+ <description>Equivalent to <b>identity</b></description>
+ </item>
+ <item>
+ <term>username</term>
+ <description>
+ <para>
+ Used to output the WindowsIdentity for the currently
+ active user.
+ </para>
+ <para>
+ <b>WARNING</b> Generating caller WindowsIdentity information is
+ extremely slow. Its use should be avoided unless execution speed
+ is not an issue.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>utcdate</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in universal time.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
+ <b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>w</term>
+ <description>Equivalent to <b>username</b></description>
+ </item>
+ <item>
+ <term>x</term>
+ <description>Equivalent to <b>ndc</b></description>
+ </item>
+ <item>
+ <term>X</term>
+ <description>Equivalent to <b>mdc</b></description>
+ </item>
+ <item>
+ <term>%</term>
+ <description>
+ <para>
+ The sequence %% outputs a single percent sign.
+ </para>
+ </description>
+ </item>
+ </list>
+ <para>
+ The single letter patterns are deprecated in favor of the
+ longer more descriptive pattern names.
+ </para>
+ <para>
+ By default the relevant information is output as is. However,
+ with the aid of format modifiers it is possible to change the
+ minimum field width, the maximum field width and justification.
+ </para>
+ <para>
+ The optional format modifier is placed between the percent sign
+ and the conversion pattern name.
+ </para>
+ <para>
+ The first optional format modifier is the <i>left justification
+ flag</i> which is just the minus (-) character. Then comes the
+ optional <i>minimum field width</i> modifier. This is a decimal
+ constant that represents the minimum number of characters to
+ output. If the data item requires fewer characters, it is padded on
+ either the left or the right until the minimum width is
+ reached. The default is to pad on the left (right justify) but you
+ can specify right padding with the left justification flag. The
+ padding character is space. If the data item is larger than the
+ minimum field width, the field is expanded to accommodate the
+ data. The value is never truncated.
+ </para>
+ <para>
+ This behavior can be changed using the <i>maximum field
+ width</i> modifier which is designated by a period followed by a
+ decimal constant. If the data item is longer than the maximum
+ field, then the extra characters are removed from the
+ <i>beginning</i> of the data item and not from the end. For
+ example, it the maximum field width is eight and the data item is
+ ten characters long, then the first two characters of the data item
+ are dropped. This behavior deviates from the printf function in C
+ where truncation is done from the end.
+ </para>
+ <para>
+ Below are various format modifier examples for the logger
+ conversion specifier.
+ </para>
+ <div class="tablediv">
+ <table class="dtTABLE" cellspacing="0">
+ <tr>
+ <th>Format modifier</th>
+ <th>left justify</th>
+ <th>minimum width</th>
+ <th>maximum width</th>
+ <th>comment</th>
+ </tr>
+ <tr>
+ <td align="center">%20logger</td>
+ <td align="center">false</td>
+ <td align="center">20</td>
+ <td align="center">none</td>
+ <td>
+ <para>
+ Left pad with spaces if the logger name is less than 20
+ characters long.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%-20logger</td>
+ <td align="center">true</td>
+ <td align="center">20</td>
+ <td align="center">none</td>
+ <td>
+ <para>
+ Right pad with spaces if the logger
+ name is less than 20 characters long.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%.30logger</td>
+ <td align="center">NA</td>
+ <td align="center">none</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Truncate from the beginning if the logger
+ name is longer than 30 characters.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center"><nobr>%20.30logger</nobr></td>
+ <td align="center">false</td>
+ <td align="center">20</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Left pad with spaces if the logger name is shorter than 20
+ characters. However, if logger name is longer than 30 characters,
+ then truncate from the beginning.
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td align="center">%-20.30logger</td>
+ <td align="center">true</td>
+ <td align="center">20</td>
+ <td align="center">30</td>
+ <td>
+ <para>
+ Right pad with spaces if the logger name is shorter than 20
+ characters. However, if logger name is longer than 30 characters,
+ then truncate from the beginning.
+ </para>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <para>
+ <b>Note about caller location information.</b><br/>
+ The following patterns <c>%type %file %line %method %location %class %C %F %L %l %M</c>
+ all generate caller location information.
+ Location information uses the <c>System.Diagnostics.StackTrace</c> class to generate
+ a call stack. The caller's information is then extracted from this stack.
+ </para>
+ <note type="caution">
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class is not supported on the
+ .NET Compact Framework 1.0 therefore caller location information is not
+ available on that framework.
+ </para>
+ </note>
+ <note type="caution">
+ <para>
+ The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
+ </para>
+ <para>
+ "StackTrace information will be most informative with Debug build configurations.
+ By default, Debug builds include debug symbols, while Release builds do not. The
+ debug symbols contain most of the file, method name, line number, and column
+ information used in constructing StackFrame and StackTrace objects. StackTrace
+ might not report as many method calls as expected, due to code transformations
+ that occur during optimization."
+ </para>
+ <para>
+ This means that in a Release build the caller information may be incomplete or may
+ not exist at all! Therefore caller location information cannot be relied upon in a Release build.
+ </para>
+ </note>
+ <para>
+ Additional pattern converters may be registered with a specific <see cref="T:log4net.Layout.PatternLayout"/>
+ instance using the <see cref="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ <example>
+ This is a more detailed pattern.
+ <code><b>%timestamp [%thread] %level %logger %ndc - %message%newline</b></code>
+ </example>
+ <example>
+ A similar pattern except that the relative time is
+ right padded if less than 6 digits, thread name is right padded if
+ less than 15 characters and truncated if longer and the logger
+ name is left padded if shorter than 30 characters and truncated if
+ longer.
+ <code><b>%-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline</b></code>
+ </example>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Douglas de la Torre</author>
+ <author>Daniel Cazzulino</author>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.DefaultConversionPattern">
+ <summary>
+ Default pattern string for log output.
+ </summary>
+ <remarks>
+ <para>
+ Default pattern string for log output.
+ Currently set to the string <b>"%message%newline"</b>
+ which just prints the application supplied message.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.DetailConversionPattern">
+ <summary>
+ A detailed conversion pattern
+ </summary>
+ <remarks>
+ <para>
+ A conversion pattern which includes Time, Thread, Logger, and Nested Context.
+ Current value is <b>%timestamp [%thread] %level %logger %ndc - %message%newline</b>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.s_globalRulesRegistry">
+ <summary>
+ Internal map of converter identifiers to converter types.
+ </summary>
+ <remarks>
+ <para>
+ This static map is overridden by the m_converterRegistry instance map
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_pattern">
+ <summary>
+ the pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_head">
+ <summary>
+ the head of the pattern converter chain
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.PatternLayout.m_instanceRulesRegistry">
+ <summary>
+ patterns defined on this PatternLayout only
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#cctor">
+ <summary>
+ Initialize the global registry
+ </summary>
+ <remarks>
+ <para>
+ Defines the builtin global rules.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#ctor">
+ <summary>
+ Constructs a PatternLayout using the DefaultConversionPattern
+ </summary>
+ <remarks>
+ <para>
+ The default pattern just produces the application supplied message.
+ </para>
+ <para>
+ Note to Inheritors: This constructor calls the virtual method
+ <see cref="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)"/>. If you override this method be
+ aware that it will be called before your is called constructor.
+ </para>
+ <para>
+ As per the <see cref="T:log4net.Core.IOptionHandler"/> contract the <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/>
+ method must be called after the properties on this object have been
+ configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.#ctor(System.String)">
+ <summary>
+ Constructs a PatternLayout using the supplied conversion pattern
+ </summary>
+ <param name="pattern">the pattern to use</param>
+ <remarks>
+ <para>
+ Note to Inheritors: This constructor calls the virtual method
+ <see cref="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)"/>. If you override this method be
+ aware that it will be called before your is called constructor.
+ </para>
+ <para>
+ When using this constructor the <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> method
+ need not be called. This may not be the case when using a subclass.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.CreatePatternParser(System.String)">
+ <summary>
+ Create the pattern parser instance
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <returns>The <see cref="T:log4net.Util.PatternParser"/> that will format the event</returns>
+ <remarks>
+ <para>
+ Creates the <see cref="T:log4net.Util.PatternParser"/> used to parse the conversion string. Sets the
+ global and instance rules on the <see cref="T:log4net.Util.PatternParser"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a formatted string as specified by the conversion pattern.
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Parse the <see cref="T:log4net.Core.LoggingEvent"/> using the patter format
+ specified in the <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.AddConverter(log4net.Layout.PatternLayout.ConverterInfo)">
+ <summary>
+ Add a converter to this PatternLayout
+ </summary>
+ <param name="converterInfo">the converter info</param>
+ <remarks>
+ <para>
+ This version of the method is used by the configurator.
+ Programmatic users should use the alternative <see cref="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.AddConverter(System.String,System.Type)">
+ <summary>
+ Add a converter to this PatternLayout
+ </summary>
+ <param name="name">the name of the conversion pattern for this converter</param>
+ <param name="type">the type of the converter</param>
+ <remarks>
+ <para>
+ Add a named pattern converter to this instance. This
+ converter will be used in the formatting of the event.
+ This method must be called before <see cref="M:log4net.Layout.PatternLayout.ActivateOptions"/>.
+ </para>
+ <para>
+ The <paramref name="type"/> specified must extend the
+ <see cref="T:log4net.Util.PatternConverter"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConversionPattern">
+ <summary>
+ The pattern formatting string
+ </summary>
+ <remarks>
+ <para>
+ The <b>ConversionPattern</b> option. This is the string which
+ controls formatting and consists of a mix of literal content and
+ conversion specifiers.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.PatternLayout.ConverterInfo">
+ <summary>
+ Wrapper class used to map converter names to converter types
+ </summary>
+ <remarks>
+ <para>
+ Pattern converter info class used during configuration to
+ pass to the <see cref="M:log4net.Layout.PatternLayout.AddConverter(log4net.Layout.PatternLayout.ConverterInfo)"/>
+ method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.PatternLayout.ConverterInfo.#ctor">
+ <summary>
+ default constructor
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConverterInfo.Name">
+ <summary>
+ Gets or sets the name of the conversion pattern
+ </summary>
+ <remarks>
+ <para>
+ The name of the pattern in the format string
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.PatternLayout.ConverterInfo.Type">
+ <summary>
+ Gets or sets the type of the converter
+ </summary>
+ <remarks>
+ <para>
+ The value specified must extend the
+ <see cref="T:log4net.Util.PatternConverter"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawLayoutConverter">
+ <summary>
+ Type converter for the <see cref="T:log4net.Layout.IRawLayout"/> interface
+ </summary>
+ <remarks>
+ <para>
+ Used to convert objects to the <see cref="T:log4net.Layout.IRawLayout"/> interface.
+ Supports converting from the <see cref="T:log4net.Layout.ILayout"/> interface to
+ the <see cref="T:log4net.Layout.IRawLayout"/> interface using the <see cref="T:log4net.Layout.Layout2RawLayoutAdapter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IConvertFrom">
+ <summary>
+ Interface supported by type converters
+ </summary>
+ <remarks>
+ <para>
+ This interface supports conversion from arbitrary types
+ to a single target type. See <see cref="T:log4net.Util.TypeConverters.TypeConverterAttribute"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertFrom.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Test if the <paramref name="sourceType"/> can be converted to the
+ type supported by this converter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertFrom.ConvertFrom(System.Object)">
+ <summary>
+ Convert the source object to the type supported by this object
+ </summary>
+ <param name="source">the object to convert</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Converts the <paramref name="source"/> to the type supported
+ by this converter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.RawLayoutConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the sourceType be converted to an <see cref="T:log4net.Layout.IRawLayout"/>
+ </summary>
+ <param name="sourceType">the source to be to be converted</param>
+ <returns><c>true</c> if the source type can be converted to <see cref="T:log4net.Layout.IRawLayout"/></returns>
+ <remarks>
+ <para>
+ Test if the <paramref name="sourceType"/> can be converted to a
+ <see cref="T:log4net.Layout.IRawLayout"/>. Only <see cref="T:log4net.Layout.ILayout"/> is supported
+ as the <paramref name="sourceType"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.RawLayoutConverter.ConvertFrom(System.Object)">
+ <summary>
+ Convert the value to a <see cref="T:log4net.Layout.IRawLayout"/> object
+ </summary>
+ <param name="source">the value to convert</param>
+ <returns>the <see cref="T:log4net.Layout.IRawLayout"/> object</returns>
+ <remarks>
+ <para>
+ Convert the <paramref name="source"/> object to a
+ <see cref="T:log4net.Layout.IRawLayout"/> object. If the <paramref name="source"/> object
+ is a <see cref="T:log4net.Layout.ILayout"/> then the <see cref="T:log4net.Layout.Layout2RawLayoutAdapter"/>
+ is used to adapt between the two interfaces, otherwise an
+ exception is thrown.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawPropertyLayout">
+ <summary>
+ Extract the value of a property from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the value of a property from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Layout.RawPropertyLayout.#ctor">
+ <summary>
+ Constructs a RawPropertyLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawPropertyLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Lookup the property for <see cref="P:log4net.Layout.RawPropertyLayout.Key"/>
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns property value</returns>
+ <remarks>
+ <para>
+ Looks up and returns the object value of the property
+ named <see cref="P:log4net.Layout.RawPropertyLayout.Key"/>. If there is no property defined
+ with than name then <c>null</c> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.RawPropertyLayout.Key">
+ <summary>
+ The name of the value to lookup in the LoggingEvent Properties collection.
+ </summary>
+ <value>
+ Value to lookup in the LoggingEvent Properties collection
+ </value>
+ <remarks>
+ <para>
+ String name of the property to lookup in the <see cref="T:log4net.Core.LoggingEvent"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawTimeStampLayout">
+ <summary>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.RawTimeStampLayout.#ctor">
+ <summary>
+ Constructs a RawTimeStampLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawTimeStampLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the time stamp</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </para>
+ <para>
+ The time stamp is in local time. To format the time stamp
+ in universal time use <see cref="T:log4net.Layout.RawUtcTimeStampLayout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.RawUtcTimeStampLayout">
+ <summary>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </summary>
+ <remarks>
+ <para>
+ Extract the date from the <see cref="T:log4net.Core.LoggingEvent"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.RawUtcTimeStampLayout.#ctor">
+ <summary>
+ Constructs a RawUtcTimeStampLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.RawUtcTimeStampLayout.Format(log4net.Core.LoggingEvent)">
+ <summary>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </summary>
+ <param name="loggingEvent">The event to format</param>
+ <returns>returns the time stamp</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="P:log4net.Core.LoggingEvent.TimeStamp"/> as a <see cref="T:System.DateTime"/>.
+ </para>
+ <para>
+ The time stamp is in universal time. To format the time stamp
+ in local time use <see cref="T:log4net.Layout.RawTimeStampLayout"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.SimpleLayout">
+ <summary>
+ A very simple layout
+ </summary>
+ <remarks>
+ <para>
+ SimpleLayout consists of the level of the log statement,
+ followed by " - " and then the log message itself. For example,
+ <code>
+ DEBUG - Hello world
+ </code>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.#ctor">
+ <summary>
+ Constructs a SimpleLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.SimpleLayout.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.SimpleLayout.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a simple formatted output.
+ </summary>
+ <param name="loggingEvent">the event being logged</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Formats the event as the level of the even,
+ followed by " - " and then the log message itself. The
+ output is terminated by a newline.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.XmlLayout">
+ <summary>
+ Layout that formats the log events as XML elements.
+ </summary>
+ <remarks>
+ <para>
+ The output of the <see cref="T:log4net.Layout.XmlLayout"/> consists of a series of
+ log4net:event elements. It does not output a complete well-formed XML
+ file. The output is designed to be included as an <em>external entity</em>
+ in a separate file to form a correct XML file.
+ </para>
+ <para>
+ For example, if <c>abc</c> is the name of the file where
+ the <see cref="T:log4net.Layout.XmlLayout"/> output goes, then a well-formed XML file would
+ be:
+ </para>
+ <code lang="XML">
+ &lt;?xml version="1.0" ?&gt;
+
+ &lt;!DOCTYPE log4net:events SYSTEM "log4net-events.dtd" [&lt;!ENTITY data SYSTEM "abc"&gt;]&gt;
+
+ &lt;log4net:events version="1.2" xmlns:log4net="http://logging.apache.org/log4net/schemas/log4net-events-1.2&gt;
+ &amp;data;
+ &lt;/log4net:events&gt;
+ </code>
+ <para>
+ This approach enforces the independence of the <see cref="T:log4net.Layout.XmlLayout"/>
+ and the appender where it is embedded.
+ </para>
+ <para>
+ The <c>version</c> attribute helps components to correctly
+ interpret output generated by <see cref="T:log4net.Layout.XmlLayout"/>. The value of
+ this attribute should be "1.2" for release 1.2 and later.
+ </para>
+ <para>
+ Alternatively the <c>Header</c> and <c>Footer</c> properties can be
+ configured to output the correct XML header, open tag and close tag.
+ When setting the <c>Header</c> and <c>Footer</c> properties it is essential
+ that the underlying data store not be appendable otherwise the data
+ will become invalid XML.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Layout.XmlLayoutBase">
+ <summary>
+ Layout that formats the log events as XML elements.
+ </summary>
+ <remarks>
+ <para>
+ This is an abstract class that must be subclassed by an implementation
+ to conform to a specific schema.
+ </para>
+ <para>
+ Deriving classes must implement the <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.#ctor">
+ <summary>
+ Protected constructor to support subclasses
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Layout.XmlLayoutBase"/> class
+ with no location info.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.#ctor(System.Boolean)">
+ <summary>
+ Protected constructor to support subclasses
+ </summary>
+ <remarks>
+ <para>
+ The <paramref name="locationInfo" /> parameter determines whether
+ location information will be output by the layout. If
+ <paramref name="locationInfo" /> is set to <c>true</c>, then the
+ file name and line number of the statement at the origin of the log
+ statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SMTPAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.XmlLayoutBase.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.Format(System.IO.TextWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Produces a formatted string.
+ </summary>
+ <param name="loggingEvent">The event being logged.</param>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Format the <see cref="T:log4net.Core.LoggingEvent"/> and write it to the <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ <para>
+ This method creates an <see cref="T:System.Xml.XmlTextWriter"/> that writes to the
+ <paramref name="writer"/>. The <see cref="T:System.Xml.XmlTextWriter"/> is passed
+ to the <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method. Subclasses should override the
+ <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method rather than this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Does the actual writing of the XML.
+ </summary>
+ <param name="writer">The writer to use to output the event to.</param>
+ <param name="loggingEvent">The event to write.</param>
+ <remarks>
+ <para>
+ Subclasses should override this method to format
+ the <see cref="T:log4net.Core.LoggingEvent"/> as XML.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_locationInfo">
+ <summary>
+ Flag to indicate if location information should be included in
+ the XML events.
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_protectCloseTextWriter">
+ <summary>
+ Writer adapter that ignores Close
+ </summary>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutBase.m_invalidCharReplacement">
+ <summary>
+ The string to replace invalid chars with
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.LocationInfo">
+ <summary>
+ Gets a value indicating whether to include location information in
+ the XML events.
+ </summary>
+ <value>
+ <c>true</c> if location information should be included in the XML
+ events; otherwise, <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ If <see cref="P:log4net.Layout.XmlLayoutBase.LocationInfo"/> is set to <c>true</c>, then the file
+ name and line number of the statement at the origin of the log
+ statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an <c>SMTPAppender</c>
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement">
+ <summary>
+ The string to replace characters that can not be expressed in XML with.
+ <remarks>
+ <para>
+ Not all characters may be expressed in XML. This property contains the
+ string to replace those that can not with. This defaults to a ?. Set it
+ to the empty string to simply remove offending characters. For more
+ details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets
+ Character replacement will occur in the log message, the property names
+ and the property values.
+ </para>
+ </remarks>
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutBase.ContentType">
+ <summary>
+ Gets the content type output by this layout.
+ </summary>
+ <value>
+ As this is the XML layout, the value is always <c>"text/xml"</c>.
+ </value>
+ <remarks>
+ <para>
+ As this is the XML layout, the value is always <c>"text/xml"</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.#ctor">
+ <summary>
+ Constructs an XmlLayout
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.#ctor(System.Boolean)">
+ <summary>
+ Constructs an XmlLayout.
+ </summary>
+ <remarks>
+ <para>
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SmtpAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.ActivateOptions">
+ <summary>
+ Initialize layout options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Layout.XmlLayout.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ Builds a cache of the element names
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayout.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Does the actual writing of the XML.
+ </summary>
+ <param name="writer">The writer to use to output the event to.</param>
+ <param name="loggingEvent">The event to write.</param>
+ <remarks>
+ <para>
+ Override the base class <see cref="M:log4net.Layout.XmlLayoutBase.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)"/> method
+ to write the <see cref="T:log4net.Core.LoggingEvent"/> to the <see cref="T:System.Xml.XmlWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Layout.XmlLayout.m_prefix">
+ <summary>
+ The prefix to use for all generated element names
+ </summary>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Prefix">
+ <summary>
+ The prefix to use for all element names
+ </summary>
+ <remarks>
+ <para>
+ The default prefix is <b>log4net</b>. Set this property
+ to change the prefix. If the prefix is set to an empty string
+ then no prefix will be written.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Base64EncodeMessage">
+ <summary>
+ Set whether or not to base64 encode the message.
+ </summary>
+ <remarks>
+ <para>
+ By default the log message will be written as text to the xml
+ output. This can cause problems when the message contains binary
+ data. By setting this to true the contents of the message will be
+ base64 encoded. If this is set then invalid character replacement
+ (see <see cref="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement"/>) will not be performed
+ on the log message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayout.Base64EncodeProperties">
+ <summary>
+ Set whether or not to base64 encode the property values.
+ </summary>
+ <remarks>
+ <para>
+ By default the properties will be written as text to the xml
+ output. This can cause problems when one or more properties contain
+ binary data. By setting this to true the values of the properties
+ will be base64 encoded. If this is set then invalid character replacement
+ (see <see cref="P:log4net.Layout.XmlLayoutBase.InvalidCharReplacement"/>) will not be performed
+ on the property values.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Layout.XmlLayoutSchemaLog4j">
+ <summary>
+ Layout that formats the log events as XML elements compatible with the log4j schema
+ </summary>
+ <remarks>
+ <para>
+ Formats the log events according to the http://logging.apache.org/log4j schema.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Layout.XmlLayoutSchemaLog4j.s_date1970">
+ <summary>
+ The 1st of January 1970 in UTC
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.#ctor">
+ <summary>
+ Constructs an XMLLayoutSchemaLog4j
+ </summary>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.#ctor(System.Boolean)">
+ <summary>
+ Constructs an XMLLayoutSchemaLog4j.
+ </summary>
+ <remarks>
+ <para>
+ The <b>LocationInfo</b> option takes a boolean value. By
+ default, it is set to false which means there will be no location
+ information output by this layout. If the the option is set to
+ true, then the file name and line number of the statement
+ at the origin of the log statement will be output.
+ </para>
+ <para>
+ If you are embedding this layout within an SMTPAppender
+ then make sure to set the <b>LocationInfo</b> option of that
+ appender as well.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Layout.XmlLayoutSchemaLog4j.FormatXml(System.Xml.XmlWriter,log4net.Core.LoggingEvent)">
+ <summary>
+ Actually do the writing of the xml
+ </summary>
+ <param name="writer">the writer to use</param>
+ <param name="loggingEvent">the event to write</param>
+ <remarks>
+ <para>
+ Generate XML that is compatible with the log4j schema.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Layout.XmlLayoutSchemaLog4j.Version">
+ <summary>
+ The version of the log4j schema to use.
+ </summary>
+ <remarks>
+ <para>
+ Only version 1.2 of the log4j schema is supported.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.ObjectRenderer.DefaultRenderer">
+ <summary>
+ The default object Renderer.
+ </summary>
+ <remarks>
+ <para>
+ The default renderer supports rendering objects and collections to strings.
+ </para>
+ <para>
+ See the <see cref="M:log4net.ObjectRenderer.DefaultRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)"/> method for details of the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.ObjectRenderer.IObjectRenderer">
+ <summary>
+ Implement this interface in order to render objects as strings
+ </summary>
+ <remarks>
+ <para>
+ Certain types require special case conversion to
+ string form. This conversion is done by an object renderer.
+ Object renderers implement the <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>
+ interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ObjectRenderer.IObjectRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)">
+ <summary>
+ Render the object <paramref name="obj"/> to a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="obj">The object to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the object <paramref name="obj"/> to a
+ string.
+ </para>
+ <para>
+ The <paramref name="rendererMap"/> parameter is
+ provided to lookup and render other objects. This is
+ very useful where <paramref name="obj"/> contains
+ nested objects of unknown type. The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)"/>
+ method can be used to render these objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderObject(log4net.ObjectRenderer.RendererMap,System.Object,System.IO.TextWriter)">
+ <summary>
+ Render the object <paramref name="obj"/> to a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="obj">The object to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the object <paramref name="obj"/> to a string.
+ </para>
+ <para>
+ The <paramref name="rendererMap"/> parameter is
+ provided to lookup and render other objects. This is
+ very useful where <paramref name="obj"/> contains
+ nested objects of unknown type. The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)"/>
+ method can be used to render these objects.
+ </para>
+ <para>
+ The default renderer supports rendering objects to strings as follows:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Value</term>
+ <description>Rendered String</description>
+ </listheader>
+ <item>
+ <term><c>null</c></term>
+ <description>
+ <para>"(null)"</para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Array"/></term>
+ <description>
+ <para>
+ For a one dimensional array this is the
+ array type name, an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace.
+ </para>
+ <para>
+ For example: <c>int[] {1, 2, 3}</c>.
+ </para>
+ <para>
+ If the array is not one dimensional the
+ <c>Array.ToString()</c> is returned.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Collections.IEnumerable"/>, <see cref="T:System.Collections.ICollection"/> &amp; <see cref="T:System.Collections.IEnumerator"/></term>
+ <description>
+ <para>
+ Rendered as an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace.
+ </para>
+ <para>
+ For example: <c>{a, b, c}</c>.
+ </para>
+ <para>
+ All collection classes that implement <see cref="T:System.Collections.ICollection"/> its subclasses,
+ or generic equivalents all implement the <see cref="T:System.Collections.IEnumerable"/> interface.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term><see cref="T:System.Collections.DictionaryEntry"/></term>
+ <description>
+ <para>
+ Rendered as the key, an equals sign ('='), and the value (using the appropriate
+ renderer).
+ </para>
+ <para>
+ For example: <c>key=value</c>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ <para><c>Object.ToString()</c></para>
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderArray(log4net.ObjectRenderer.RendererMap,System.Array,System.IO.TextWriter)">
+ <summary>
+ Render the array argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="array">the array to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ For a one dimensional array this is the
+ array type name, an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace. For example:
+ <c>int[] {1, 2, 3}</c>.
+ </para>
+ <para>
+ If the array is not one dimensional the
+ <c>Array.ToString()</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderEnumerator(log4net.ObjectRenderer.RendererMap,System.Collections.IEnumerator,System.IO.TextWriter)">
+ <summary>
+ Render the enumerator argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="enumerator">the enumerator to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Rendered as an open brace, followed by a comma
+ separated list of the elements (using the appropriate
+ renderer), followed by a close brace. For example:
+ <c>{a, b, c}</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.DefaultRenderer.RenderDictionaryEntry(log4net.ObjectRenderer.RendererMap,System.Collections.DictionaryEntry,System.IO.TextWriter)">
+ <summary>
+ Render the DictionaryEntry argument into a string
+ </summary>
+ <param name="rendererMap">The map used to lookup renderers</param>
+ <param name="entry">the DictionaryEntry to render</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Render the key, an equals sign ('='), and the value (using the appropriate
+ renderer). For example: <c>key=value</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.ObjectRenderer.RendererMap">
+ <summary>
+ Map class objects to an <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/>.
+ </summary>
+ <remarks>
+ <para>
+ Maintains a mapping between types that require special
+ rendering and the <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> that
+ is used to render them.
+ </para>
+ <para>
+ The <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)"/> method is used to render an
+ <c>object</c> using the appropriate renderers defined in this map.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object)">
+ <summary>
+ Render <paramref name="obj"/> using the appropriate renderer.
+ </summary>
+ <param name="obj">the object to render to a string</param>
+ <returns>the object rendered as a string</returns>
+ <remarks>
+ <para>
+ This is a convenience method used to render an object to a string.
+ The alternative method <see cref="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)"/>
+ should be used when streaming output to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.FindAndRender(System.Object,System.IO.TextWriter)">
+ <summary>
+ Render <paramref name="obj"/> using the appropriate renderer.
+ </summary>
+ <param name="obj">the object to render to a string</param>
+ <param name="writer">The writer to render to</param>
+ <remarks>
+ <para>
+ Find the appropriate renderer for the type of the
+ <paramref name="obj"/> parameter. This is accomplished by calling the
+ <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/> method. Once a renderer is found, it is
+ applied on the object <paramref name="obj"/> and the result is returned
+ as a <see cref="T:System.String"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Get(System.Object)">
+ <summary>
+ Gets the renderer for the specified object type
+ </summary>
+ <param name="obj">the object to lookup the renderer for</param>
+ <returns>the renderer for <paramref name="obj"/></returns>
+ <remarks>
+ <param>
+ Gets the renderer for the specified object type.
+ </param>
+ <param>
+ Syntactic sugar method that calls <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/>
+ with the type of the object parameter.
+ </param>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)">
+ <summary>
+ Gets the renderer for the specified type
+ </summary>
+ <param name="type">the type to lookup the renderer for</param>
+ <returns>the renderer for the specified type</returns>
+ <remarks>
+ <para>
+ Returns the renderer for the specified type.
+ If no specific renderer has been defined the
+ <see cref="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer"/> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.SearchTypeAndInterfaces(System.Type)">
+ <summary>
+ Internal function to recursively search interfaces
+ </summary>
+ <param name="type">the type to lookup the renderer for</param>
+ <returns>the renderer for the specified type</returns>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Clear">
+ <summary>
+ Clear the map of renderers
+ </summary>
+ <remarks>
+ <para>
+ Clear the custom renderers defined by using
+ <see cref="M:log4net.ObjectRenderer.RendererMap.Put(System.Type,log4net.ObjectRenderer.IObjectRenderer)"/>. The <see cref="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer"/>
+ cannot be removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.ObjectRenderer.RendererMap.Put(System.Type,log4net.ObjectRenderer.IObjectRenderer)">
+ <summary>
+ Register an <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> for <paramref name="typeToRender"/>.
+ </summary>
+ <param name="typeToRender">the type that will be rendered by <paramref name="renderer"/></param>
+ <param name="renderer">the renderer for <paramref name="typeToRender"/></param>
+ <remarks>
+ <para>
+ Register an object renderer for a specific source type.
+ This renderer will be returned from a call to <see cref="M:log4net.ObjectRenderer.RendererMap.Get(System.Type)"/>
+ specifying the same <paramref name="typeToRender"/> as an argument.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.ObjectRenderer.RendererMap.DefaultRenderer">
+ <summary>
+ Get the default renderer instance
+ </summary>
+ <value>the default renderer</value>
+ <remarks>
+ <para>
+ Get the default renderer
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.IPlugin">
+ <summary>
+ Interface implemented by logger repository plugins.
+ </summary>
+ <remarks>
+ <para>
+ Plugins define additional behavior that can be associated
+ with a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ The <see cref="T:log4net.Plugin.PluginMap"/> held by the <see cref="P:log4net.Repository.ILoggerRepository.PluginMap"/>
+ property is used to store the plugins for a repository.
+ </para>
+ <para>
+ The <c>log4net.Config.PluginAttribute</c> can be used to
+ attach plugins to repositories created using configuration
+ attributes.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.IPlugin.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches the plugin to the specified <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.IPlugin.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ This method is called to notify the plugin that
+ it should stop operating and should detach from
+ the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.IPlugin.Name">
+ <summary>
+ Gets the name of the plugin.
+ </summary>
+ <value>
+ The name of the plugin.
+ </value>
+ <remarks>
+ <para>
+ Plugins are stored in the <see cref="T:log4net.Plugin.PluginMap"/>
+ keyed by name. Each plugin instance attached to a
+ repository must be a unique name.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection">
+ <summary>
+ A strongly-typed collection of <see cref="T:log4net.Plugin.IPlugin"/> objects.
+ </summary>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ReadOnly(log4net.Plugin.PluginCollection)">
+ <summary>
+ Creates a read-only wrapper for a <c>PluginCollection</c> instance.
+ </summary>
+ <param name="list">list to create a readonly wrapper arround</param>
+ <returns>
+ A <c>PluginCollection</c> wrapper that is read-only.
+ </returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that is empty and has the default initial capacity.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(System.Int32)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that has the specified initial capacity.
+ </summary>
+ <param name="capacity">
+ The number of elements that the new <c>PluginCollection</c> is initially capable of storing.
+ </param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.PluginCollection)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <c>PluginCollection</c>.
+ </summary>
+ <param name="c">The <c>PluginCollection</c> whose elements are copied to the new collection.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.IPlugin[])">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Plugin.IPlugin"/> array.
+ </summary>
+ <param name="a">The <see cref="T:log4net.Plugin.IPlugin"/> array whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(System.Collections.ICollection)">
+ <summary>
+ Initializes a new instance of the <c>PluginCollection</c> class
+ that contains elements copied from the specified <see cref="T:log4net.Plugin.IPlugin"/> collection.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Plugin.IPlugin"/> collection whose elements are copied to the new list.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.#ctor(log4net.Plugin.PluginCollection.Tag)">
+ <summary>
+ Allow subclasses to avoid our default constructors
+ </summary>
+ <param name="tag"></param>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.CopyTo(log4net.Plugin.IPlugin[])">
+ <summary>
+ Copies the entire <c>PluginCollection</c> to a one-dimensional
+ <see cref="T:log4net.Plugin.IPlugin"/> array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Plugin.IPlugin"/> array to copy to.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.CopyTo(log4net.Plugin.IPlugin[],System.Int32)">
+ <summary>
+ Copies the entire <c>PluginCollection</c> to a one-dimensional
+ <see cref="T:log4net.Plugin.IPlugin"/> array, starting at the specified index of the target array.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:log4net.Plugin.IPlugin"/> array to copy to.</param>
+ <param name="start">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Add(log4net.Plugin.IPlugin)">
+ <summary>
+ Adds a <see cref="T:log4net.Plugin.IPlugin"/> to the end of the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The index at which the value has been added.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Clear">
+ <summary>
+ Removes all elements from the <c>PluginCollection</c>.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Clone">
+ <summary>
+ Creates a shallow copy of the <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <returns>A new <see cref="T:log4net.Plugin.PluginCollection"/> with a shallow copy of the collection data.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Contains(log4net.Plugin.IPlugin)">
+ <summary>
+ Determines whether a given <see cref="T:log4net.Plugin.IPlugin"/> is in the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to check for.</param>
+ <returns><c>true</c> if <paramref name="item"/> is found in the <c>PluginCollection</c>; otherwise, <c>false</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IndexOf(log4net.Plugin.IPlugin)">
+ <summary>
+ Returns the zero-based index of the first occurrence of a <see cref="T:log4net.Plugin.IPlugin"/>
+ in the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to locate in the <c>PluginCollection</c>.</param>
+ <returns>
+ The zero-based index of the first occurrence of <paramref name="item"/>
+ in the entire <c>PluginCollection</c>, if found; otherwise, -1.
+ </returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Insert(System.Int32,log4net.Plugin.IPlugin)">
+ <summary>
+ Inserts an element into the <c>PluginCollection</c> at the specified index.
+ </summary>
+ <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to insert.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Remove(log4net.Plugin.IPlugin)">
+ <summary>
+ Removes the first occurrence of a specific <see cref="T:log4net.Plugin.IPlugin"/> from the <c>PluginCollection</c>.
+ </summary>
+ <param name="item">The <see cref="T:log4net.Plugin.IPlugin"/> to remove from the <c>PluginCollection</c>.</param>
+ <exception cref="T:System.ArgumentException">
+ The specified <see cref="T:log4net.Plugin.IPlugin"/> was not found in the <c>PluginCollection</c>.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.RemoveAt(System.Int32)">
+ <summary>
+ Removes the element at the specified index of the <c>PluginCollection</c>.
+ </summary>
+ <param name="index">The zero-based index of the element to remove.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through the <c>PluginCollection</c>.
+ </summary>
+ <returns>An <see cref="T:log4net.Plugin.PluginCollection.Enumerator"/> for the entire <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(log4net.Plugin.PluginCollection)">
+ <summary>
+ Adds the elements of another <c>PluginCollection</c> to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="x">The <c>PluginCollection</c> whose elements should be added to the end of the current <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(log4net.Plugin.IPlugin[])">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Plugin.IPlugin"/> array to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="x">The <see cref="T:log4net.Plugin.IPlugin"/> array whose elements should be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.AddRange(System.Collections.ICollection)">
+ <summary>
+ Adds the elements of a <see cref="T:log4net.Plugin.IPlugin"/> collection to the current <c>PluginCollection</c>.
+ </summary>
+ <param name="col">The <see cref="T:log4net.Plugin.IPlugin"/> collection whose elements should be added to the end of the <c>PluginCollection</c>.</param>
+ <returns>The new <see cref="P:log4net.Plugin.PluginCollection.Count"/> of the <c>PluginCollection</c>.</returns>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.TrimToSize">
+ <summary>
+ Sets the capacity to the actual number of elements.
+ </summary>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ValidateIndex(System.Int32)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.ValidateIndex(System.Int32,System.Boolean)">
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Count">
+ <summary>
+ Gets the number of elements actually contained in the <c>PluginCollection</c>.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating whether access to the collection is synchronized (thread-safe).
+ </summary>
+ <returns>true if access to the ICollection is synchronized (thread-safe); otherwise, false.</returns>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the collection.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the collection.
+ </value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Item(System.Int32)">
+ <summary>
+ Gets or sets the <see cref="T:log4net.Plugin.IPlugin"/> at the specified index.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Plugin.IPlugin"/> at the specified index.
+ </value>
+ <param name="index">The zero-based index of the element to get or set.</param>
+ <exception cref="T:System.ArgumentOutOfRangeException">
+ <para><paramref name="index"/> is less than zero.</para>
+ <para>-or-</para>
+ <para><paramref name="index"/> is equal to or greater than <see cref="P:log4net.Plugin.PluginCollection.Count"/>.</para>
+ </exception>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the collection has a fixed size.
+ </summary>
+ <value><c>true</c> if the collection has a fixed size; otherwise, <c>false</c>. The default is <c>false</c>.</value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the IList is read-only.
+ </summary>
+ <value><c>true</c> if the collection is read-only; otherwise, <c>false</c>. The default is <c>false</c>.</value>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Capacity">
+ <summary>
+ Gets or sets the number of elements the <c>PluginCollection</c> can contain.
+ </summary>
+ <value>
+ The number of elements the <c>PluginCollection</c> can contain.
+ </value>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator">
+ <summary>
+ Supports type-safe iteration over a <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.IPluginCollectionEnumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.Tag">
+ <summary>
+ Type visible only to our subclasses
+ Used to access protected constructor
+ </summary>
+ <exclude/>
+ </member>
+ <member name="F:log4net.Plugin.PluginCollection.Tag.Default">
+ <summary>
+ A value
+ </summary>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.Enumerator">
+ <summary>
+ Supports simple iteration over a <see cref="T:log4net.Plugin.PluginCollection"/>.
+ </summary>
+ <exclude/>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.#ctor(log4net.Plugin.PluginCollection)">
+ <summary>
+ Initializes a new instance of the <c>Enumerator</c> class.
+ </summary>
+ <param name="tc"></param>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.MoveNext">
+ <summary>
+ Advances the enumerator to the next element in the collection.
+ </summary>
+ <returns>
+ <c>true</c> if the enumerator was successfully advanced to the next element;
+ <c>false</c> if the enumerator has passed the end of the collection.
+ </returns>
+ <exception cref="T:System.InvalidOperationException">
+ The collection was modified after the enumerator was created.
+ </exception>
+ </member>
+ <member name="M:log4net.Plugin.PluginCollection.Enumerator.Reset">
+ <summary>
+ Sets the enumerator to its initial position, before the first element in the collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginCollection.Enumerator.Current">
+ <summary>
+ Gets the current element in the collection.
+ </summary>
+ <value>
+ The current element in the collection.
+ </value>
+ </member>
+ <member name="T:log4net.Plugin.PluginCollection.ReadOnlyPluginCollection">
+ <exclude/>
+ </member>
+ <member name="T:log4net.Plugin.PluginMap">
+ <summary>
+ Map of repository plugins.
+ </summary>
+ <remarks>
+ <para>
+ This class is a name keyed map of the plugins that are
+ attached to a repository.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="repository">The repository that the plugins should be attached to.</param>
+ <remarks>
+ <para>
+ Initialize a new instance of the <see cref="T:log4net.Plugin.PluginMap"/> class with a
+ repository that the plugins should be attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.Add(log4net.Plugin.IPlugin)">
+ <summary>
+ Adds a <see cref="T:log4net.Plugin.IPlugin"/> to the map.
+ </summary>
+ <param name="plugin">The <see cref="T:log4net.Plugin.IPlugin"/> to add to the map.</param>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Plugin.IPlugin"/> will be attached to the repository when added.
+ </para>
+ <para>
+ If there already exists a plugin with the same name
+ attached to the repository then the old plugin will
+ be <see cref="M:log4net.Plugin.IPlugin.Shutdown"/> and replaced with
+ the new plugin.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginMap.Remove(log4net.Plugin.IPlugin)">
+ <summary>
+ Removes a <see cref="T:log4net.Plugin.IPlugin"/> from the map.
+ </summary>
+ <param name="plugin">The <see cref="T:log4net.Plugin.IPlugin"/> to remove from the map.</param>
+ <remarks>
+ <para>
+ Remove a specific plugin from this map.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginMap.Item(System.String)">
+ <summary>
+ Gets a <see cref="T:log4net.Plugin.IPlugin"/> by name.
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Plugin.IPlugin"/> to lookup.</param>
+ <returns>
+ The <see cref="T:log4net.Plugin.IPlugin"/> from the map with the name specified, or
+ <c>null</c> if no plugin is found.
+ </returns>
+ <remarks>
+ <para>
+ Lookup a plugin by name. If the plugin is not found <c>null</c>
+ will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginMap.AllPlugins">
+ <summary>
+ Gets all possible plugins as a list of <see cref="T:log4net.Plugin.IPlugin"/> objects.
+ </summary>
+ <value>All possible plugins as a list of <see cref="T:log4net.Plugin.IPlugin"/> objects.</value>
+ <remarks>
+ <para>
+ Get a collection of all the plugins defined in this map.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.PluginSkeleton">
+ <summary>
+ Base implementation of <see cref="T:log4net.Plugin.IPlugin"/>
+ </summary>
+ <remarks>
+ <para>
+ Default abstract implementation of the <see cref="T:log4net.Plugin.IPlugin"/>
+ interface. This base class can be used by implementors
+ of the <see cref="T:log4net.Plugin.IPlugin"/> interface.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="name">the name of the plugin</param>
+ <remarks>
+ Initializes a new Plugin with the specified name.
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches this plugin to a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.PluginSkeleton.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ This method is called to notify the plugin that
+ it should stop operating and should detach from
+ the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Plugin.PluginSkeleton.m_name">
+ <summary>
+ The name of this plugin.
+ </summary>
+ </member>
+ <member name="F:log4net.Plugin.PluginSkeleton.m_repository">
+ <summary>
+ The repository this plugin is attached to.
+ </summary>
+ </member>
+ <member name="P:log4net.Plugin.PluginSkeleton.Name">
+ <summary>
+ Gets or sets the name of the plugin.
+ </summary>
+ <value>
+ The name of the plugin.
+ </value>
+ <remarks>
+ <para>
+ Plugins are stored in the <see cref="T:log4net.Plugin.PluginMap"/>
+ keyed by name. Each plugin instance attached to a
+ repository must be a unique name.
+ </para>
+ <para>
+ The name of the plugin must not change one the
+ plugin has been attached to a repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.PluginSkeleton.LoggerRepository">
+ <summary>
+ The repository for this plugin
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin is attached to.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin is
+ attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.RemoteLoggingServerPlugin">
+ <summary>
+ Plugin that listens for events from the <see cref="T:log4net.Appender.RemotingAppender"/>
+ </summary>
+ <remarks>
+ <para>
+ This plugin publishes an instance of <see cref="T:log4net.Appender.RemotingAppender.IRemoteLoggingSink"/>
+ on a specified <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/>. This listens for logging events delivered from
+ a remote <see cref="T:log4net.Appender.RemotingAppender"/>.
+ </para>
+ <para>
+ When an event is received it is relogged within the attached repository
+ as if it had been raised locally.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin"/> class.
+ </para>
+ <para>
+ The <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/> property must be set.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.#ctor(System.String)">
+ <summary>
+ Construct with sink Uri.
+ </summary>
+ <param name="sinkUri">The name to publish the sink under in the remoting infrastructure.
+ See <see cref="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri"/> for more details.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin"/> class
+ with specified name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.Attach(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Attaches this plugin to a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </summary>
+ <param name="repository">The <see cref="T:log4net.Repository.ILoggerRepository"/> that this plugin should be attached to.</param>
+ <remarks>
+ <para>
+ A plugin may only be attached to a single repository.
+ </para>
+ <para>
+ This method is called when the plugin is attached to the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.Shutdown">
+ <summary>
+ Is called when the plugin is to shutdown.
+ </summary>
+ <remarks>
+ <para>
+ When the plugin is shutdown the remote logging
+ sink is disconnected.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Plugin.RemoteLoggingServerPlugin.SinkUri">
+ <summary>
+ Gets or sets the URI of this sink.
+ </summary>
+ <value>
+ The URI of this sink.
+ </value>
+ <remarks>
+ <para>
+ This is the name under which the object is marshaled.
+ <see cref="M:System.Runtime.Remoting.RemotingServices.Marshal(System.MarshalByRefObject,System.String,System.Type)"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl">
+ <summary>
+ Delivers <see cref="T:log4net.Core.LoggingEvent"/> objects to a remote sink.
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to listen for logging events
+ and deliver them to the local repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.#ctor(log4net.Repository.ILoggerRepository)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="repository">The repository to log to.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl"/> for the
+ specified <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.LogEvents(log4net.Core.LoggingEvent[])">
+ <summary>
+ Logs the events to the repository.
+ </summary>
+ <param name="events">The events to log.</param>
+ <remarks>
+ <para>
+ The events passed are logged to the <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.InitializeLifetimeService">
+ <summary>
+ Obtains a lifetime service object to control the lifetime
+ policy for this instance.
+ </summary>
+ <returns><c>null</c> to indicate that this instance should live forever.</returns>
+ <remarks>
+ <para>
+ Obtains a lifetime service object to control the lifetime
+ policy for this instance. This object should live forever
+ therefore this implementation returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Plugin.RemoteLoggingServerPlugin.RemoteLoggingSinkImpl.m_repository">
+ <summary>
+ The underlying <see cref="T:log4net.Repository.ILoggerRepository"/> that events should
+ be logged to.
+ </summary>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.DefaultLoggerFactory">
+ <summary>
+ Default implementation of <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ </summary>
+ <remarks>
+ <para>
+ This default implementation of the <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ interface is used to create the default subclass
+ of the <see cref="T:log4net.Repository.Hierarchy.Logger"/> object.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.ILoggerFactory">
+ <summary>
+ Interface abstracts creation of <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances
+ </summary>
+ <remarks>
+ <para>
+ This interface is used by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to
+ create new <see cref="T:log4net.Repository.Hierarchy.Logger"/> objects.
+ </para>
+ <para>
+ The <see cref="M:log4net.Repository.Hierarchy.ILoggerFactory.CreateLogger(System.String)"/> method is called
+ to create a named <see cref="T:log4net.Repository.Hierarchy.Logger"/>.
+ </para>
+ <para>
+ Implement this interface to create new subclasses of <see cref="T:log4net.Repository.Hierarchy.Logger"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.ILoggerFactory.CreateLogger(System.String)">
+ <summary>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance for the specified name.</returns>
+ <remarks>
+ <para>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance with the
+ specified name.
+ </para>
+ <para>
+ Called by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to create
+ new named <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances.
+ </para>
+ <para>
+ If the <paramref name="name"/> is <c>null</c> then the root logger
+ must be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.CreateLogger(System.String)">
+ <summary>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <returns>The <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance for the specified name.</returns>
+ <remarks>
+ <para>
+ Create a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance with the
+ specified name.
+ </para>
+ <para>
+ Called by the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> to create
+ new named <see cref="T:log4net.Repository.Hierarchy.Logger"/> instances.
+ </para>
+ <para>
+ If the <paramref name="name"/> is <c>null</c> then the root logger
+ must be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl">
+ <summary>
+ Default internal subclass of <see cref="T:log4net.Repository.Hierarchy.Logger"/>
+ </summary>
+ <remarks>
+ <para>
+ This subclass has no additional behavior over the
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> class but does allow instances
+ to be created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Logger">
+ <summary>
+ Implementation of <see cref="T:log4net.Core.ILogger"/> used by <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to provide implementation of <see cref="T:log4net.Core.ILogger"/>
+ interface. Applications should use <see cref="T:log4net.LogManager"/> to get
+ logger instances.
+ </para>
+ <para>
+ This is one of the central classes in the log4net implementation. One of the
+ distinctive features of log4net are hierarchical loggers and their
+ evaluation. The <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/> organizes the <see cref="T:log4net.Repository.Hierarchy.Logger"/>
+ instances into a rooted tree hierarchy.
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.Hierarchy.Logger"/> class is abstract. Only concrete subclasses of
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> can be created. The <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ is used to create instances of this type for the <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Aspi Havewala</author>
+ <author>Douglas de la Torre</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.#ctor(System.String)">
+ <summary>
+ This constructor created a new <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance and
+ sets its name.
+ </summary>
+ <param name="name">The name of the <see cref="T:log4net.Repository.Hierarchy.Logger"/>.</param>
+ <remarks>
+ <para>
+ This constructor is protected and designed to be used by
+ a subclass that is not abstract.
+ </para>
+ <para>
+ Loggers are constructed by <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>
+ objects. See <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory"/> for the default
+ logger creator.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Add <paramref name="newAppender"/> to the list of appenders of this
+ Logger instance.
+ </summary>
+ <param name="newAppender">An appender to add to this logger</param>
+ <remarks>
+ <para>
+ Add <paramref name="newAppender"/> to the list of appenders of this
+ Logger instance.
+ </para>
+ <para>
+ If <paramref name="newAppender"/> is already in the list of
+ appenders, then it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.GetAppender(System.String)">
+ <summary>
+ Look for the appender named as <c>name</c>
+ </summary>
+ <param name="name">The name of the appender to lookup</param>
+ <returns>The appender with the name specified, or <c>null</c>.</returns>
+ <remarks>
+ <para>
+ Returns the named appender, or null if the appender is not found.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAllAppenders">
+ <summary>
+ Remove all previously added appenders from this Logger instance.
+ </summary>
+ <remarks>
+ <para>
+ Remove all previously added appenders from this Logger instance.
+ </para>
+ <para>
+ This is useful when re-reading configuration information.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Remove the appender passed as parameter form the list of appenders.
+ </summary>
+ <param name="appender">The appender to remove</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ Remove the appender passed as parameter form the list of appenders.
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.RemoveAppender(System.String)">
+ <summary>
+ Remove the appender passed as parameter form the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ Remove the named appender passed as parameter form the list of appenders.
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This generic form is intended to be used by wrappers.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generate a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/> and <paramref name="exception"/>.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ This is the most generic printing method that is intended to be used
+ by wrappers.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Logs the specified logging event through this logger.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.IsEnabledFor(log4net.Core.Level)">
+ <summary>
+ Checks if this logger is enabled for a given <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> passed as parameter.
+ </summary>
+ <param name="level">The level to check.</param>
+ <returns>
+ <c>true</c> if this logger is enabled for <c>level</c>, otherwise <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Test if this logger is going to log events of the specified <paramref name="level"/>.
+ </para>
+ <para>
+ This method must not throw any exception to the caller.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.CallAppenders(log4net.Core.LoggingEvent)">
+ <summary>
+ Deliver the <see cref="T:log4net.Core.LoggingEvent"/> to the attached appenders.
+ </summary>
+ <param name="loggingEvent">The event to log.</param>
+ <remarks>
+ <para>
+ Call the appenders in the hierarchy starting at
+ <c>this</c>. If no appenders could be found, emit a
+ warning.
+ </para>
+ <para>
+ This method calls all the appenders inherited from the
+ hierarchy circumventing any evaluation of whether to log or not
+ to log the particular log request.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.CloseNestedAppenders">
+ <summary>
+ Closes all attached appenders implementing the <see cref="T:log4net.Core.IAppenderAttachable"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ Used to ensure that the appenders are correctly shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.Log(log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ This is the most generic printing method. This generic form is intended to be used by wrappers
+ </summary>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generate a logging event for the specified <paramref name="level"/> using
+ the <paramref name="message"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.ForcedLog(System.Type,log4net.Core.Level,System.Object,System.Exception)">
+ <summary>
+ Creates a new logging event and logs the event without further checks.
+ </summary>
+ <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
+ the stack boundary into the logging system for this call.</param>
+ <param name="level">The level of the message to be logged.</param>
+ <param name="message">The message object to log.</param>
+ <param name="exception">The exception to log, including its stack trace.</param>
+ <remarks>
+ <para>
+ Generates a logging event and delivers it to the attached
+ appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Logger.ForcedLog(log4net.Core.LoggingEvent)">
+ <summary>
+ Creates a new logging event and logs the event without further checks.
+ </summary>
+ <param name="logEvent">The event being logged.</param>
+ <remarks>
+ <para>
+ Delivers the logging event to the attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.ThisDeclaringType">
+ <summary>
+ The fully qualified type of the Logger class.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_name">
+ <summary>
+ The name of this logger.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_level">
+ <summary>
+ The assigned level of this logger.
+ </summary>
+ <remarks>
+ <para>
+ The <c>level</c> variable need not be
+ assigned a value in which case it is inherited
+ form the hierarchy.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_parent">
+ <summary>
+ The parent of this logger.
+ </summary>
+ <remarks>
+ <para>
+ The parent of this logger.
+ All loggers have at least one ancestor which is the root logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_hierarchy">
+ <summary>
+ Loggers need to know what Hierarchy they are in.
+ </summary>
+ <remarks>
+ <para>
+ Loggers need to know what Hierarchy they are in.
+ The hierarchy that this logger is a member of is stored
+ here.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_appenderAttachedImpl">
+ <summary>
+ Helper implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_additive">
+ <summary>
+ Flag indicating if child loggers inherit their parents appenders
+ </summary>
+ <remarks>
+ <para>
+ Additivity is set to true by default, that is children inherit
+ the appenders of their ancestors by default. If this variable is
+ set to <c>false</c> then the appenders found in the
+ ancestors of this logger are not used. However, the children
+ of this logger will inherit its appenders, unless the children
+ have their additivity flag set to <c>false</c> too. See
+ the user manual for more details.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.Logger.m_appenderLock">
+ <summary>
+ Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl
+ </summary>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Parent">
+ <summary>
+ Gets or sets the parent logger in the hierarchy.
+ </summary>
+ <value>
+ The parent logger in the hierarchy.
+ </value>
+ <remarks>
+ <para>
+ Part of the Composite pattern that makes the hierarchy.
+ The hierarchy is parent linked rather than child linked.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Additivity">
+ <summary>
+ Gets or sets a value indicating if child loggers inherit their parent's appenders.
+ </summary>
+ <value>
+ <c>true</c> if child loggers inherit their parent's appenders.
+ </value>
+ <remarks>
+ <para>
+ Additivity is set to <c>true</c> by default, that is children inherit
+ the appenders of their ancestors by default. If this variable is
+ set to <c>false</c> then the appenders found in the
+ ancestors of this logger are not used. However, the children
+ of this logger will inherit its appenders, unless the children
+ have their additivity flag set to <c>false</c> too. See
+ the user manual for more details.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.EffectiveLevel">
+ <summary>
+ Gets the effective level for this logger.
+ </summary>
+ <returns>The nearest level in the logger hierarchy.</returns>
+ <remarks>
+ <para>
+ Starting from this logger, searches the logger hierarchy for a
+ non-null level and returns it. Otherwise, returns the level of the
+ root logger.
+ </para>
+ <para>The Logger class is designed so that this method executes as
+ quickly as possible.</para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Hierarchy">
+ <summary>
+ Gets or sets the <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>The hierarchy that this logger belongs to.</value>
+ <remarks>
+ <para>
+ This logger must be attached to a single <see cref="P:log4net.Repository.Hierarchy.Logger.Hierarchy"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Level">
+ <summary>
+ Gets or sets the assigned <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/>, if any, for this Logger.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> of this logger.
+ </value>
+ <remarks>
+ <para>
+ The assigned <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/> can be <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Appenders">
+ <summary>
+ Get the appenders contained in this logger as an
+ <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <returns>A collection of the appenders in this logger</returns>
+ <remarks>
+ <para>
+ Get the appenders contained in this logger as an
+ <see cref="T:System.Collections.ICollection"/>. If no appenders
+ can be found, then a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Name">
+ <summary>
+ Gets the logger name.
+ </summary>
+ <value>
+ The name of the logger.
+ </value>
+ <remarks>
+ <para>
+ The name of this logger
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Logger.Repository">
+ <summary>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </summary>
+ <value>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> that this logger belongs to.
+ </value>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> where this
+ <c>Logger</c> instance is attached to.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl.#ctor(System.String)">
+ <summary>
+ Construct a new Logger
+ </summary>
+ <param name="name">the name of the logger</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.DefaultLoggerFactory.LoggerImpl"/> class
+ with the specified name.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerCreationEventHandler">
+ <summary>
+ Delegate used to handle logger creation event notifications.
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> in which the <see cref="T:log4net.Repository.Hierarchy.Logger"/> has been created.</param>
+ <param name="e">The <see cref="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs"/> event args that hold the <see cref="T:log4net.Repository.Hierarchy.Logger"/> instance that has been created.</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger creation event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs">
+ <summary>
+ Provides data for the <see cref="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent"/> event.
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent"/> event is raised every time a
+ <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.LoggerCreationEventArgs.m_log">
+ <summary>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> created
+ </summary>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerCreationEventArgs.#ctor(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="log">The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.LoggerCreationEventArgs"/> event argument
+ class,with the specified <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger">
+ <summary>
+ Gets the <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </value>
+ <remarks>
+ <para>
+ The <see cref="P:log4net.Repository.Hierarchy.LoggerCreationEventArgs.Logger"/> that has been created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy">
+ <summary>
+ Hierarchical organization of loggers
+ </summary>
+ <remarks>
+ <para>
+ <i>The casual user should not have to deal with this class
+ directly.</i>
+ </para>
+ <para>
+ This class is specialized in retrieving loggers by name and
+ also maintaining the logger hierarchy. Implements the
+ <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ </para>
+ <para>
+ The structure of the logger hierarchy is maintained by the
+ <see cref="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String)"/> method. The hierarchy is such that children
+ link to their parent but parents do not have any references to their
+ children. Moreover, loggers can be instantiated in any order, in
+ particular descendant before ancestor.
+ </para>
+ <para>
+ In case a descendant is created before a particular ancestor,
+ then it creates a provision node for the ancestor and adds itself
+ to the provision node. Other descendants of the same ancestor add
+ themselves to the previously created provision node.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositorySkeleton">
+ <summary>
+ Base implementation of <see cref="T:log4net.Repository.ILoggerRepository"/>
+ </summary>
+ <remarks>
+ <para>
+ Default abstract implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ </para>
+ <para>
+ Skeleton implementation of the <see cref="T:log4net.Repository.ILoggerRepository"/> interface.
+ All <see cref="T:log4net.Repository.ILoggerRepository"/> types can extend this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Repository.ILoggerRepository">
+ <summary>
+ Interface implemented by logger repositories.
+ </summary>
+ <remarks>
+ <para>
+ This interface is implemented by logger repositories. e.g.
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ <para>
+ This interface is used by the <see cref="T:log4net.LogManager"/>
+ to obtain <see cref="T:log4net.ILog"/> interfaces.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Exists(System.String)">
+ <summary>
+ Check if the named logger exists in the repository. If so return
+ its reference, otherwise returns <c>null</c>.
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ If the names logger exists it is returned, otherwise
+ <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers as an Array.
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetLogger(System.String)">
+ <summary>
+ Returns a named logger instance
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Returns a named logger instance.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Shutdown">
+ <summary>Shutdown the repository</summary>
+ <remarks>
+ <para>
+ Shutting down a repository will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </para>
+ <para>
+ Some appenders need to be closed before the
+ application exists. Otherwise, pending logging events might be
+ lost.
+ </para>
+ <para>
+ The <see cref="M:log4net.Repository.ILoggerRepository.Shutdown"/> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.ResetConfiguration">
+ <summary>
+ Reset the repositories configuration to a default state
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this instance to their
+ default state.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the <see cref="T:log4net.Core.LoggingEvent"/> through this repository.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.ILoggerRepository.GetAppenders">
+ <summary>
+ Returns all the Appenders that are configured as an Array.
+ </summary>
+ <returns>All the Appenders</returns>
+ <remarks>
+ <para>
+ Returns all the Appenders that are configured as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Name">
+ <summary>
+ The name of the repository
+ </summary>
+ <value>
+ The name of the repository
+ </value>
+ <remarks>
+ <para>
+ The name of the repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.RendererMap">
+ <summary>
+ RendererMap accesses the object renderer map for this repository.
+ </summary>
+ <value>
+ RendererMap accesses the object renderer map for this repository.
+ </value>
+ <remarks>
+ <para>
+ RendererMap accesses the object renderer map for this repository.
+ </para>
+ <para>
+ The RendererMap holds a mapping between types and
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.PluginMap">
+ <summary>
+ The plugin map for this repository.
+ </summary>
+ <value>
+ The plugin map for this repository.
+ </value>
+ <remarks>
+ <para>
+ The plugin map holds the <see cref="T:log4net.Plugin.IPlugin"/> instances
+ that have been attached to this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.LevelMap">
+ <summary>
+ Get the level map for the Repository.
+ </summary>
+ <remarks>
+ <para>
+ Get the level map for the Repository.
+ </para>
+ <para>
+ The level map defines the mappings between
+ level names and <see cref="T:log4net.Core.Level"/> objects in
+ this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Threshold">
+ <summary>
+ The threshold for all events in this repository
+ </summary>
+ <value>
+ The threshold for all events in this repository
+ </value>
+ <remarks>
+ <para>
+ The threshold for all events in this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Configured">
+ <summary>
+ Flag indicates if this repository has been configured.
+ </summary>
+ <value>
+ Flag indicates if this repository has been configured.
+ </value>
+ <remarks>
+ <para>
+ Flag indicates if this repository has been configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ShutdownEvent">
+ <summary>
+ Event to notify that the repository has been shutdown.
+ </summary>
+ <value>
+ Event to notify that the repository has been shutdown.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository has been shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ConfigurationReset">
+ <summary>
+ Event to notify that the repository has had its configuration reset.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration reset.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been
+ reset to default.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.ILoggerRepository.ConfigurationChanged">
+ <summary>
+ Event to notify that the repository has had its configuration changed.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration changed.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.ILoggerRepository.Properties">
+ <summary>
+ Repository specific properties
+ </summary>
+ <value>
+ Repository specific properties
+ </value>
+ <remarks>
+ <para>
+ These properties can be specified on a repository specific basis.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes the repository with default (empty) properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.#ctor(log4net.Util.PropertiesDictionary)">
+ <summary>
+ Construct the repository using specific properties
+ </summary>
+ <param name="properties">the properties to set for this repository</param>
+ <remarks>
+ <para>
+ Initializes the repository with specified properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Exists(System.String)">
+ <summary>
+ Test if logger exists
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Check if the named logger exists in the repository. If so return
+ its reference, otherwise returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers in the repository
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers in the repository as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetLogger(System.String)">
+ <summary>
+ Return a new logger instance
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Return a new logger instance.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Shutdown">
+ <summary>
+ Shutdown the repository
+ </summary>
+ <remarks>
+ <para>
+ Shutdown the repository. Can be overridden in a subclass.
+ This base class implementation notifies the <see cref="E:log4net.Repository.LoggerRepositorySkeleton.ShutdownEvent"/>
+ listeners and all attached plugins of the shutdown event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.ResetConfiguration">
+ <summary>
+ Reset the repositories configuration to a default state
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this instance to their
+ default state.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logEvent through this repository.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.GetAppenders">
+ <summary>
+ Returns all the Appenders that are configured as an Array.
+ </summary>
+ <returns>All the Appenders</returns>
+ <remarks>
+ <para>
+ Returns all the Appenders that are configured as an Array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.AddRenderer(System.Type,log4net.ObjectRenderer.IObjectRenderer)">
+ <summary>
+ Adds an object renderer for a specific class.
+ </summary>
+ <param name="typeToRender">The type that will be rendered by the renderer supplied.</param>
+ <param name="rendererInstance">The object renderer used to render the object.</param>
+ <remarks>
+ <para>
+ Adds an object renderer for a specific class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnShutdown(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository is shutting down
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository is shutting down.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnConfigurationReset(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository has had its configuration reset
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository's configuration has been reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.OnConfigurationChanged(System.EventArgs)">
+ <summary>
+ Notify the registered listeners that the repository has had its configuration changed
+ </summary>
+ <param name="e">Empty EventArgs</param>
+ <remarks>
+ <para>
+ Notify any listeners that this repository's configuration has changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.LoggerRepositorySkeleton.RaiseConfigurationChanged(System.EventArgs)">
+ <summary>
+ Raise a configuration changed event on this repository
+ </summary>
+ <param name="e">EventArgs.Empty</param>
+ <remarks>
+ <para>
+ Applications that programmatically change the configuration of the repository should
+ raise this event notification to notify listeners.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Name">
+ <summary>
+ The name of the repository
+ </summary>
+ <value>
+ The string name of the repository
+ </value>
+ <remarks>
+ <para>
+ The name of this repository. The name is
+ used to store and lookup the repositories
+ stored by the <see cref="T:log4net.Core.IRepositorySelector"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Threshold">
+ <summary>
+ The threshold for all events in this repository
+ </summary>
+ <value>
+ The threshold for all events in this repository
+ </value>
+ <remarks>
+ <para>
+ The threshold for all events in this repository
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.RendererMap">
+ <summary>
+ RendererMap accesses the object renderer map for this repository.
+ </summary>
+ <value>
+ RendererMap accesses the object renderer map for this repository.
+ </value>
+ <remarks>
+ <para>
+ RendererMap accesses the object renderer map for this repository.
+ </para>
+ <para>
+ The RendererMap holds a mapping between types and
+ <see cref="T:log4net.ObjectRenderer.IObjectRenderer"/> objects.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.PluginMap">
+ <summary>
+ The plugin map for this repository.
+ </summary>
+ <value>
+ The plugin map for this repository.
+ </value>
+ <remarks>
+ <para>
+ The plugin map holds the <see cref="T:log4net.Plugin.IPlugin"/> instances
+ that have been attached to this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.LevelMap">
+ <summary>
+ Get the level map for the Repository.
+ </summary>
+ <remarks>
+ <para>
+ Get the level map for the Repository.
+ </para>
+ <para>
+ The level map defines the mappings between
+ level names and <see cref="T:log4net.Core.Level"/> objects in
+ this repository.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Configured">
+ <summary>
+ Flag indicates if this repository has been configured.
+ </summary>
+ <value>
+ Flag indicates if this repository has been configured.
+ </value>
+ <remarks>
+ <para>
+ Flag indicates if this repository has been configured.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ShutdownEvent">
+ <summary>
+ Event to notify that the repository has been shutdown.
+ </summary>
+ <value>
+ Event to notify that the repository has been shutdown.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository has been shutdown.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ConfigurationReset">
+ <summary>
+ Event to notify that the repository has had its configuration reset.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration reset.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been
+ reset to default.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.LoggerRepositorySkeleton.ConfigurationChanged">
+ <summary>
+ Event to notify that the repository has had its configuration changed.
+ </summary>
+ <value>
+ Event to notify that the repository has had its configuration changed.
+ </value>
+ <remarks>
+ <para>
+ Event raised when the repository's configuration has been changed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.LoggerRepositorySkeleton.Properties">
+ <summary>
+ Repository specific properties
+ </summary>
+ <value>
+ Repository specific properties
+ </value>
+ <remarks>
+ These properties can be specified on a repository specific basis
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.IBasicRepositoryConfigurator">
+ <summary>
+ Basic Configurator interface for repositories
+ </summary>
+ <remarks>
+ <para>
+ Interface used by basic configurator to configure a <see cref="T:log4net.Repository.ILoggerRepository"/>
+ with a default <see cref="T:log4net.Appender.IAppender"/>.
+ </para>
+ <para>
+ A <see cref="T:log4net.Repository.ILoggerRepository"/> should implement this interface to support
+ configuration by the <see cref="T:log4net.Config.BasicConfigurator"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the repository using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ <remarks>
+ <para>
+ Configure the repository to route all logging events to the
+ specified appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.IXmlRepositoryConfigurator">
+ <summary>
+ Configure repository using XML
+ </summary>
+ <remarks>
+ <para>
+ Interface used by Xml configurator to configure a <see cref="T:log4net.Repository.ILoggerRepository"/>.
+ </para>
+ <para>
+ A <see cref="T:log4net.Repository.ILoggerRepository"/> should implement this interface to support
+ configuration by the <see cref="T:log4net.Config.XmlConfigurator"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.IXmlRepositoryConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the repository using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ <remarks>
+ <para>
+ The schema for the XML configuration data is defined by
+ the implementation.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Util.PropertiesDictionary)">
+ <summary>
+ Construct with properties
+ </summary>
+ <param name="properties">The properties to pass to this repository.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Construct with a logger factory
+ </summary>
+ <param name="loggerFactory">The factory to use to create new logger instances.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class with
+ the specified <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.#ctor(log4net.Util.PropertiesDictionary,log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Construct with properties and a logger factory
+ </summary>
+ <param name="properties">The properties to pass to this repository.</param>
+ <param name="loggerFactory">The factory to use to create new logger instances.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> class with
+ the specified <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Exists(System.String)">
+ <summary>
+ Test if a logger exists
+ </summary>
+ <param name="name">The name of the logger to lookup</param>
+ <returns>The Logger object with the name specified</returns>
+ <remarks>
+ <para>
+ Check if the named logger exists in the hierarchy. If so return
+ its reference, otherwise returns <c>null</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetCurrentLoggers">
+ <summary>
+ Returns all the currently defined loggers in the hierarchy as an Array
+ </summary>
+ <returns>All the defined loggers</returns>
+ <remarks>
+ <para>
+ Returns all the currently defined loggers in the hierarchy as an Array.
+ The root logger is <b>not</b> included in the returned
+ enumeration.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String)">
+ <summary>
+ Return a new logger instance named as the first parameter using
+ the default factory.
+ </summary>
+ <remarks>
+ <para>
+ Return a new logger instance named as the first parameter using
+ the default factory.
+ </para>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated and
+ then linked with its existing ancestors as well as children.
+ </para>
+ </remarks>
+ <param name="name">The name of the logger to retrieve</param>
+ <returns>The logger object with the name specified</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Shutdown">
+ <summary>
+ Shutting down a hierarchy will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </summary>
+ <remarks>
+ <para>
+ Shutting down a hierarchy will <i>safely</i> close and remove
+ all appenders in all loggers including the root logger.
+ </para>
+ <para>
+ Some appenders need to be closed before the
+ application exists. Otherwise, pending logging events might be
+ lost.
+ </para>
+ <para>
+ The <c>Shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.ResetConfiguration">
+ <summary>
+ Reset all values contained in this hierarchy instance to their default.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in this hierarchy instance to their
+ default. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set its default "off" value.
+ </para>
+ <para>
+ Existing loggers are not removed. They are just reset.
+ </para>
+ <para>
+ This method should be used sparingly and with care as it will
+ block all logging until it is completed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Log(log4net.Core.LoggingEvent)">
+ <summary>
+ Log the logEvent through this hierarchy.
+ </summary>
+ <param name="logEvent">the event to log</param>
+ <remarks>
+ <para>
+ This method should not normally be used to log.
+ The <see cref="T:log4net.ILog"/> interface should be used
+ for routine logging. This interface can be obtained
+ using the <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method.
+ </para>
+ <para>
+ The <c>logEvent</c> is delivered to the appropriate logger and
+ that logger is then responsible for logging the event.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetAppenders">
+ <summary>
+ Returns all the Appenders that are currently configured
+ </summary>
+ <returns>An array containing all the currently configured appenders</returns>
+ <remarks>
+ <para>
+ Returns all the <see cref="T:log4net.Appender.IAppender"/> instances that are currently configured.
+ All the loggers are searched for appenders. The appenders may also be containers
+ for appenders and these are also searched for additional loggers.
+ </para>
+ <para>
+ The list returned is unordered but does not contain duplicates.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.CollectAppender(System.Collections.ArrayList,log4net.Appender.IAppender)">
+ <summary>
+ Collect the appenders from an <see cref="T:log4net.Core.IAppenderAttachable"/>.
+ The appender may also be a container.
+ </summary>
+ <param name="appenderList"></param>
+ <param name="appender"></param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.CollectAppenders(System.Collections.ArrayList,log4net.Core.IAppenderAttachable)">
+ <summary>
+ Collect the appenders from an <see cref="T:log4net.Core.IAppenderAttachable"/> container
+ </summary>
+ <param name="appenderList"></param>
+ <param name="container"></param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.log4net#Repository#IBasicRepositoryConfigurator#Configure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the log4net system using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.BasicRepositoryConfigure(log4net.Appender.IAppender)">
+ <summary>
+ Initialize the log4net system using the specified appender
+ </summary>
+ <param name="appender">the appender to use to log all logging events</param>
+ <remarks>
+ <para>
+ This method provides the same functionality as the
+ <see cref="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)"/> method implemented
+ on this object, but it is protected and therefore can be called by subclasses.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.log4net#Repository#IXmlRepositoryConfigurator#Configure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the log4net system using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.XmlRepositoryConfigure(System.Xml.XmlElement)">
+ <summary>
+ Initialize the log4net system using the specified config
+ </summary>
+ <param name="element">the element containing the root of the config</param>
+ <remarks>
+ <para>
+ This method provides the same functionality as the
+ <see cref="M:log4net.Repository.IBasicRepositoryConfigurator.Configure(log4net.Appender.IAppender)"/> method implemented
+ on this object, but it is protected and therefore can be called by subclasses.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.IsDisabled(log4net.Core.Level)">
+ <summary>
+ Test if this hierarchy is disabled for the specified <see cref="T:log4net.Core.Level"/>.
+ </summary>
+ <param name="level">The level to check against.</param>
+ <returns>
+ <c>true</c> if the repository is disabled for the level argument, <c>false</c> otherwise.
+ </returns>
+ <remarks>
+ <para>
+ If this hierarchy has not been configured then this method will
+ always return <c>true</c>.
+ </para>
+ <para>
+ This method will return <c>true</c> if this repository is
+ disabled for <c>level</c> object passed as parameter and
+ <c>false</c> otherwise.
+ </para>
+ <para>
+ See also the <see cref="P:log4net.Repository.ILoggerRepository.Threshold"/> property.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.Clear">
+ <summary>
+ Clear all logger definitions from the internal hashtable
+ </summary>
+ <remarks>
+ <para>
+ This call will clear all logger definitions from the internal
+ hashtable. Invoking this method will irrevocably mess up the
+ logger hierarchy.
+ </para>
+ <para>
+ You should <b>really</b> know what you are doing before
+ invoking this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.GetLogger(System.String,log4net.Repository.Hierarchy.ILoggerFactory)">
+ <summary>
+ Return a new logger instance named as the first parameter using
+ <paramref name="factory"/>.
+ </summary>
+ <param name="name">The name of the logger to retrieve</param>
+ <param name="factory">The factory that will make the new logger instance</param>
+ <returns>The logger object with the name specified</returns>
+ <remarks>
+ <para>
+ If a logger of that name already exists, then it will be
+ returned. Otherwise, a new logger will be instantiated by the
+ <paramref name="factory"/> parameter and linked with its existing
+ ancestors as well as children.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.OnLoggerCreationEvent(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Sends a logger creation event to all registered listeners
+ </summary>
+ <param name="logger">The newly created logger</param>
+ <remarks>
+ Raises the logger creation event.
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.UpdateParents(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Updates all the parents of the specified logger
+ </summary>
+ <param name="log">The logger to update the parents for</param>
+ <remarks>
+ <para>
+ This method loops through all the <i>potential</i> parents of
+ <paramref name="log"/>. There 3 possible cases:
+ </para>
+ <list type="number">
+ <item>
+ <term>No entry for the potential parent of <paramref name="log"/> exists</term>
+ <description>
+ We create a ProvisionNode for this potential
+ parent and insert <paramref name="log"/> in that provision node.
+ </description>
+ </item>
+ <item>
+ <term>The entry is of type Logger for the potential parent.</term>
+ <description>
+ The entry is <paramref name="log"/>'s nearest existing parent. We
+ update <paramref name="log"/>'s parent field with this entry. We also break from
+ he loop because updating our parent's parent is our parent's
+ responsibility.
+ </description>
+ </item>
+ <item>
+ <term>The entry is of type ProvisionNode for this potential parent.</term>
+ <description>
+ We add <paramref name="log"/> to the list of children for this
+ potential parent.
+ </description>
+ </item>
+ </list>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.UpdateChildren(log4net.Repository.Hierarchy.ProvisionNode,log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Replace a <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> with a <see cref="T:log4net.Repository.Hierarchy.Logger"/> in the hierarchy.
+ </summary>
+ <param name="pn"></param>
+ <param name="log"></param>
+ <remarks>
+ <para>
+ We update the links for all the children that placed themselves
+ in the provision node 'pn'. The second argument 'log' is a
+ reference for the newly created Logger, parent of all the
+ children in 'pn'.
+ </para>
+ <para>
+ We loop on all the children 'c' in 'pn'.
+ </para>
+ <para>
+ If the child 'c' has been already linked to a child of
+ 'log' then there is no need to update 'c'.
+ </para>
+ <para>
+ Otherwise, we set log's parent field to c's parent and set
+ c's parent field to log.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.AddLevel(log4net.Repository.Hierarchy.Hierarchy.LevelEntry)">
+ <summary>
+ Define or redefine a Level using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </summary>
+ <param name="levelEntry">the level values</param>
+ <remarks>
+ <para>
+ Define or redefine a Level using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </para>
+ <para>
+ Supports setting levels via the configuration file.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.AddProperty(log4net.Repository.Hierarchy.Hierarchy.PropertyEntry)">
+ <summary>
+ Set a Property using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument
+ </summary>
+ <param name="propertyEntry">the property value</param>
+ <remarks>
+ <para>
+ Set a Property using the values in the <see cref="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry"/> argument.
+ </para>
+ <para>
+ Supports setting property values via the configuration file.
+ </para>
+ </remarks>
+ </member>
+ <member name="E:log4net.Repository.Hierarchy.Hierarchy.LoggerCreatedEvent">
+ <summary>
+ Event used to notify that a logger has been created.
+ </summary>
+ <remarks>
+ <para>
+ Event raised when a logger is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.EmittedNoAppenderWarning">
+ <summary>
+ Has no appender warning been emitted
+ </summary>
+ <remarks>
+ <para>
+ Flag to indicate if we have already issued a warning
+ about not having an appender warning.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.Root">
+ <summary>
+ Get the root of this hierarchy
+ </summary>
+ <remarks>
+ <para>
+ Get the root of this hierarchy.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LoggerFactory">
+ <summary>
+ Gets or sets the default <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/> instance.
+ </summary>
+ <value>The default <see cref="T:log4net.Repository.Hierarchy.ILoggerFactory"/></value>
+ <remarks>
+ <para>
+ The logger factory is used to create logger instances.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy.LevelEntry">
+ <summary>
+ A class to hold the value, name and display name for a level
+ </summary>
+ <remarks>
+ <para>
+ A class to hold the value, name and display name for a level
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.ToString">
+ <summary>
+ Override <c>Object.ToString</c> to return sensible debug info
+ </summary>
+ <returns>string info about this object</returns>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.Value">
+ <summary>
+ Value of the level
+ </summary>
+ <remarks>
+ <para>
+ If the value is not set (defaults to -1) the value will be looked
+ up for the current level with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.Name">
+ <summary>
+ Name of the level
+ </summary>
+ <value>
+ The name of the level
+ </value>
+ <remarks>
+ <para>
+ The name of the level.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.LevelEntry.DisplayName">
+ <summary>
+ Display name for the level
+ </summary>
+ <value>
+ The display name of the level
+ </value>
+ <remarks>
+ <para>
+ The display name of the level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry">
+ <summary>
+ A class to hold the key and data for a property set in the config file
+ </summary>
+ <remarks>
+ <para>
+ A class to hold the key and data for a property set in the config file
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.ToString">
+ <summary>
+ Override <c>Object.ToString</c> to return sensible debug info
+ </summary>
+ <returns>string info about this object</returns>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.Key">
+ <summary>
+ Property Key
+ </summary>
+ <value>
+ Property Key
+ </value>
+ <remarks>
+ <para>
+ Property Key.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.Hierarchy.PropertyEntry.Value">
+ <summary>
+ Property Value
+ </summary>
+ <value>
+ Property Value
+ </value>
+ <remarks>
+ <para>
+ Property Value.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.LoggerKey">
+ <summary>
+ Used internally to accelerate hash table searches.
+ </summary>
+ <remarks>
+ <para>
+ Internal class used to improve performance of
+ string keyed hashtables.
+ </para>
+ <para>
+ The hashcode of the string is cached for reuse.
+ The string is stored as an interned value.
+ When comparing two <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> objects for equality
+ the reference equality of the interned strings is compared.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.#ctor(System.String)">
+ <summary>
+ Construct key with string name
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> class
+ with the specified name.
+ </para>
+ <para>
+ Stores the hashcode of the string and interns
+ the string key to optimize comparisons.
+ </para>
+ <note>
+ The Compact Framework 1.0 the <see cref="M:System.String.Intern(System.String)"/>
+ method does not work. On the Compact Framework
+ the string keys are not interned nor are they
+ compared by reference.
+ </note>
+ </remarks>
+ <param name="name">The name of the logger.</param>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.GetHashCode">
+ <summary>
+ Returns a hash code for the current instance.
+ </summary>
+ <returns>A hash code for the current instance.</returns>
+ <remarks>
+ <para>
+ Returns the cached hashcode.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.LoggerKey.Equals(System.Object)">
+ <summary>
+ Determines whether two <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/> instances
+ are equal.
+ </summary>
+ <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/>.</param>
+ <returns>
+ <c>true</c> if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:log4net.Repository.Hierarchy.LoggerKey"/>; otherwise, <c>false</c>.
+ </returns>
+ <remarks>
+ <para>
+ Compares the references of the interned strings.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.ProvisionNode">
+ <summary>
+ Provision nodes are used where no logger instance has been specified
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> instances are used in the
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> when there is no specified
+ <see cref="T:log4net.Repository.Hierarchy.Logger"/> for that node.
+ </para>
+ <para>
+ A provision node holds a list of child loggers on behalf of
+ a logger that does not exist.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.ProvisionNode.#ctor(log4net.Repository.Hierarchy.Logger)">
+ <summary>
+ Create a new provision node with child node
+ </summary>
+ <param name="log">A child logger to add to this node.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.ProvisionNode"/> class
+ with the specified child logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.RootLogger">
+ <summary>
+ The <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> sits at the root of the logger hierarchy tree.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> is a regular <see cref="T:log4net.Repository.Hierarchy.Logger"/> except
+ that it provides several guarantees.
+ </para>
+ <para>
+ First, it cannot be assigned a <c>null</c>
+ level. Second, since the root logger cannot have a parent, the
+ <see cref="P:log4net.Repository.Hierarchy.RootLogger.EffectiveLevel"/> property always returns the value of the
+ level field without walking the hierarchy.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.RootLogger.#ctor(log4net.Core.Level)">
+ <summary>
+ Construct a <see cref="T:log4net.Repository.Hierarchy.RootLogger"/>
+ </summary>
+ <param name="level">The level to assign to the root logger.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.RootLogger"/> class with
+ the specified logging level.
+ </para>
+ <para>
+ The root logger names itself as "root". However, the root
+ logger cannot be retrieved by name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.RootLogger.EffectiveLevel">
+ <summary>
+ Gets the assigned level value without walking the logger hierarchy.
+ </summary>
+ <value>The assigned level value without walking the logger hierarchy.</value>
+ <remarks>
+ <para>
+ Because the root logger cannot have a parent and its level
+ must not be <c>null</c> this property just returns the
+ value of <see cref="P:log4net.Repository.Hierarchy.Logger.Level"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Repository.Hierarchy.RootLogger.Level">
+ <summary>
+ Gets or sets the assigned <see cref="P:log4net.Repository.Hierarchy.RootLogger.Level"/> for the root logger.
+ </summary>
+ <value>
+ The <see cref="P:log4net.Repository.Hierarchy.RootLogger.Level"/> of the root logger.
+ </value>
+ <remarks>
+ <para>
+ Setting the level of the root logger to a <c>null</c> reference
+ may have catastrophic results. We prevent this here.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.Hierarchy.XmlHierarchyConfigurator">
+ <summary>
+ Initializes the log4net environment using an XML DOM.
+ </summary>
+ <remarks>
+ <para>
+ Configures a <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> using an XML DOM.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.#ctor(log4net.Repository.Hierarchy.Hierarchy)">
+ <summary>
+ Construct the configurator for a hierarchy
+ </summary>
+ <param name="hierarchy">The hierarchy to build.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Repository.Hierarchy.XmlHierarchyConfigurator"/> class
+ with the specified <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.Configure(System.Xml.XmlElement)">
+ <summary>
+ Configure the hierarchy by parsing a DOM tree of XML elements.
+ </summary>
+ <param name="element">The root element to parse.</param>
+ <remarks>
+ <para>
+ Configure the hierarchy by parsing a DOM tree of XML elements.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.FindAppenderByReference(System.Xml.XmlElement)">
+ <summary>
+ Parse appenders by IDREF.
+ </summary>
+ <param name="appenderRef">The appender ref element.</param>
+ <returns>The instance of the appender that the ref refers to.</returns>
+ <remarks>
+ <para>
+ Parse an XML element that represents an appender and return
+ the appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(System.Xml.XmlElement)">
+ <summary>
+ Parses an appender element.
+ </summary>
+ <param name="appenderElement">The appender element.</param>
+ <returns>The appender instance or <c>null</c> when parsing failed.</returns>
+ <remarks>
+ <para>
+ Parse an XML element that represents an appender and return
+ the appender instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseLogger(System.Xml.XmlElement)">
+ <summary>
+ Parses a logger element.
+ </summary>
+ <param name="loggerElement">The logger element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseRoot(System.Xml.XmlElement)">
+ <summary>
+ Parses the root logger element.
+ </summary>
+ <param name="rootElement">The root element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents the root logger.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseChildrenOfLoggerElement(System.Xml.XmlElement,log4net.Repository.Hierarchy.Logger,System.Boolean)">
+ <summary>
+ Parses the children of a logger element.
+ </summary>
+ <param name="catElement">The category element.</param>
+ <param name="log">The logger instance.</param>
+ <param name="isRoot">Flag to indicate if the logger is the root logger.</param>
+ <remarks>
+ <para>
+ Parse the child elements of a &lt;logger&gt; element.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseRenderer(System.Xml.XmlElement)">
+ <summary>
+ Parses an object renderer.
+ </summary>
+ <param name="element">The renderer element.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a renderer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseLevel(System.Xml.XmlElement,log4net.Repository.Hierarchy.Logger,System.Boolean)">
+ <summary>
+ Parses a level element.
+ </summary>
+ <param name="element">The level element.</param>
+ <param name="log">The logger object to set the level on.</param>
+ <param name="isRoot">Flag to indicate if the logger is the root logger.</param>
+ <remarks>
+ <para>
+ Parse an XML element that represents a level.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.SetParameter(System.Xml.XmlElement,System.Object)">
+ <summary>
+ Sets a parameter on an object.
+ </summary>
+ <param name="element">The parameter element.</param>
+ <param name="target">The object to set the parameter on.</param>
+ <remarks>
+ The parameter name must correspond to a writable property
+ on the object. The value of the parameter is a string,
+ therefore this function will attempt to set a string
+ property first. If unable to set a string property it
+ will inspect the property and its argument type. It will
+ attempt to call a static method called <c>Parse</c> on the
+ type of the property. This method will take a single
+ string argument and return a value that can be used to
+ set the property.
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.HasAttributesOrElements(System.Xml.XmlElement)">
+ <summary>
+ Test if an element has no attributes or child elements
+ </summary>
+ <param name="element">the element to inspect</param>
+ <returns><c>true</c> if the element has any attributes or child elements, <c>false</c> otherwise</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.IsTypeConstructible(System.Type)">
+ <summary>
+ Test if a <see cref="T:System.Type"/> is constructible with <c>Activator.CreateInstance</c>.
+ </summary>
+ <param name="type">the type to inspect</param>
+ <returns><c>true</c> if the type is creatable using a default constructor, <c>false</c> otherwise</returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.FindMethodInfo(System.Type,System.String)">
+ <summary>
+ Look for a method on the <paramref name="targetType"/> that matches the <paramref name="name"/> supplied
+ </summary>
+ <param name="targetType">the type that has the method</param>
+ <param name="name">the name of the method</param>
+ <returns>the method info found</returns>
+ <remarks>
+ <para>
+ The method must be a public instance method on the <paramref name="targetType"/>.
+ The method must be named <paramref name="name"/> or "Add" followed by <paramref name="name"/>.
+ The method must take a single parameter.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ConvertStringTo(System.Type,System.String)">
+ <summary>
+ Converts a string value to a target type.
+ </summary>
+ <param name="type">The type of object to convert the string to.</param>
+ <param name="value">The string value to use as the value of the object.</param>
+ <returns>
+ <para>
+ An object of type <paramref name="type"/> with value <paramref name="value"/> or
+ <c>null</c> when the conversion could not be performed.
+ </para>
+ </returns>
+ </member>
+ <member name="M:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.CreateObjectFromXml(System.Xml.XmlElement,System.Type,System.Type)">
+ <summary>
+ Creates an object as specified in XML.
+ </summary>
+ <param name="element">The XML element that contains the definition of the object.</param>
+ <param name="defaultTargetType">The object type to use if not explicitly specified.</param>
+ <param name="typeConstraint">The type that the returned object must be or must inherit from.</param>
+ <returns>The object or <c>null</c></returns>
+ <remarks>
+ <para>
+ Parse an XML element and create an object instance based on the configuration
+ data.
+ </para>
+ <para>
+ The type of the instance may be specified in the XML. If not
+ specified then the <paramref name="defaultTargetType"/> is used
+ as the type. However the type is specified it must support the
+ <paramref name="typeConstraint"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.m_appenderBag">
+ <summary>
+ key: appenderName, value: appender.
+ </summary>
+ </member>
+ <member name="F:log4net.Repository.Hierarchy.XmlHierarchyConfigurator.m_hierarchy">
+ <summary>
+ The Hierarchy being configured.
+ </summary>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryShutdownEventHandler">
+ <summary>
+ Delegate used to handle logger repository shutdown event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that is shutting down.</param>
+ <param name="e">Empty event args</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository shutdown event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryConfigurationResetEventHandler">
+ <summary>
+ Delegate used to handle logger repository configuration reset event notifications
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that has had its configuration reset.</param>
+ <param name="e">Empty event args</param>
+ <remarks>
+ <para>
+ Delegate used to handle logger repository configuration reset event notifications.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Repository.LoggerRepositoryConfigurationChangedEventHandler">
+ <summary>
+ Delegate used to handle event notifications for logger repository configuration changes.
+ </summary>
+ <param name="sender">The <see cref="T:log4net.Repository.ILoggerRepository"/> that has had its configuration changed.</param>
+ <param name="e">Empty event arguments.</param>
+ <remarks>
+ <para>
+ Delegate used to handle event notifications for logger repository configuration changes.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.AppDomainPatternConverter">
+ <summary>
+ Write the name of the current AppDomain to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the name of the current AppDomain to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.AppDomainPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the name of the current AppDomain to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes name of the current AppDomain to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.DatePatternConverter">
+ <summary>
+ Write the current date to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the current date and time to the writer as a string.
+ </para>
+ <para>
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the formatting of the date. The following values are allowed:
+ <list type="definition">
+ <listheader>
+ <term>Option value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>ISO8601</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/> formatter.
+ Formats using the <c>"yyyy-MM-dd HH:mm:ss,fff"</c> pattern.
+ </description>
+ </item>
+ <item>
+ <term>DATE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> formatter.
+ Formats using the <c>"dd MMM yyyy HH:mm:ss,fff"</c> for example, <c>"06 Nov 1994 15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>ABSOLUTE</term>
+ <description>
+ Uses the <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/> formatter.
+ Formats using the <c>"HH:mm:ss,fff"</c> for example, <c>"15:49:37,459"</c>.
+ </description>
+ </item>
+ <item>
+ <term>other</term>
+ <description>
+ Any other pattern string uses the <see cref="T:log4net.DateFormatter.SimpleDateFormatter"/> formatter.
+ This formatter passes the pattern string to the <see cref="T:System.DateTime"/>
+ <see cref="M:System.DateTime.ToString(System.String)"/> method.
+ For details on valid patterns see
+ <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationdatetimeformatinfoclasstopic.asp">DateTimeFormatInfo Class</a>.
+ </description>
+ </item>
+ </list>
+ </para>
+ <para>
+ The date and time is in the local time zone and is rendered in that zone.
+ To output the time in Universal time see <see cref="T:log4net.Util.PatternStringConverters.UtcDatePatternConverter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.DatePatternConverter.m_dateFormatter">
+ <summary>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.DateFormatter.IDateFormatter"/> used to render the date to a string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.DatePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.DatePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current date to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Pass the current date and time to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The date and time passed is in the local time zone.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.EnvironmentPatternConverter">
+ <summary>
+ Write an environment variable to the output
+ </summary>
+ <remarks>
+ <para>
+ Write an environment variable to the output writer.
+ The value of the <see cref="P:log4net.Util.PatternConverter.Option"/> determines
+ the name of the variable to output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.EnvironmentPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write an environment variable to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes the environment variable to the output <paramref name="writer"/>.
+ The name of the environment variable to output must be set
+ using the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.IdentityPatternConverter">
+ <summary>
+ Write the current thread identity to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current thread identity to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.IdentityPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current thread identity to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes the current thread identity to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.LiteralPatternConverter">
+ <summary>
+ Pattern converter for literal string instances in the pattern
+ </summary>
+ <remarks>
+ <para>
+ Writes the literal string value specified in the
+ <see cref="P:log4net.Util.PatternConverter.Option"/> property to
+ the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.SetNext(log4net.Util.PatternConverter)">
+ <summary>
+ Set the next converter in the chain
+ </summary>
+ <param name="pc">The next pattern converter in the chain</param>
+ <returns>The next pattern converter</returns>
+ <remarks>
+ <para>
+ Special case the building of the pattern converter chain
+ for <see cref="T:log4net.Util.PatternStringConverters.LiteralPatternConverter"/> instances. Two adjacent
+ literals in the pattern can be represented by a single combined
+ pattern converter. This implementation detects when a
+ <see cref="T:log4net.Util.PatternStringConverters.LiteralPatternConverter"/> is added to the chain
+ after this converter and combines its value with this converter's
+ literal value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.Format(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the literal to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, not set</param>
+ <remarks>
+ <para>
+ Override the formatting behavior to ignore the FormattingInfo
+ because we have a literal instead.
+ </para>
+ <para>
+ Writes the value of <see cref="P:log4net.Util.PatternConverter.Option"/>
+ to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.LiteralPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Convert this pattern into the rendered message
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, not set</param>
+ <remarks>
+ <para>
+ This method is not used.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.NewLinePatternConverter">
+ <summary>
+ Writes a newline to the output
+ </summary>
+ <remarks>
+ <para>
+ Writes the system dependent line terminator to the output.
+ This behavior can be overridden by setting the <see cref="P:log4net.Util.PatternConverter.Option"/>:
+ </para>
+ <list type="definition">
+ <listheader>
+ <term>Option Value</term>
+ <description>Output</description>
+ </listheader>
+ <item>
+ <term>DOS</term>
+ <description>DOS or Windows line terminator <c>"\r\n"</c></description>
+ </item>
+ <item>
+ <term>UNIX</term>
+ <description>UNIX line terminator <c>"\n"</c></description>
+ </item>
+ </list>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.NewLinePatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.ProcessIdPatternConverter">
+ <summary>
+ Write the current process ID to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current process ID to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.ProcessIdPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current process ID to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write the current process ID to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.PropertyPatternConverter">
+ <summary>
+ Property pattern converter
+ </summary>
+ <remarks>
+ <para>
+ This pattern converter reads the thread and global properties.
+ The thread properties take priority over global properties.
+ See <see cref="P:log4net.ThreadContext.Properties"/> for details of the
+ thread properties. See <see cref="P:log4net.GlobalContext.Properties"/> for
+ details of the global properties.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is specified then that will be used to
+ lookup a single property. If no <see cref="P:log4net.Util.PatternConverter.Option"/> is specified
+ then all properties will be dumped as a list of key value pairs.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.PropertyPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the property value to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Writes out the value of a named property. The property name
+ should be set in the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ property.
+ </para>
+ <para>
+ If the <see cref="P:log4net.Util.PatternConverter.Option"/> is set to <c>null</c>
+ then all the properties are written as key value pairs.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.RandomStringPatternConverter">
+ <summary>
+ A Pattern converter that generates a string of random characters
+ </summary>
+ <remarks>
+ <para>
+ The converter generates a string of random characters. By default
+ the string is length 4. This can be changed by setting the <see cref="P:log4net.Util.PatternConverter.Option"/>
+ to the string value of the length required.
+ </para>
+ <para>
+ The random characters in the string are limited to uppercase letters
+ and numbers only.
+ </para>
+ <para>
+ The random number generator used by this class is not cryptographically secure.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.RandomStringPatternConverter.s_random">
+ <summary>
+ Shared random number generator
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternStringConverters.RandomStringPatternConverter.m_length">
+ <summary>
+ Length of random string to generate. Default length 4.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions">
+ <summary>
+ Initialize the converter options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.RandomStringPatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write a randoim string to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write a randoim string to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.UserNamePatternConverter">
+ <summary>
+ Write the current threads username to the output
+ </summary>
+ <remarks>
+ <para>
+ Write the current threads username to the output writer
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.UserNamePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current threads username to the output
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Write the current threads username to the output <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternStringConverters.UtcDatePatternConverter">
+ <summary>
+ Write the UTC date time to the output
+ </summary>
+ <remarks>
+ <para>
+ Date pattern converter, uses a <see cref="T:log4net.DateFormatter.IDateFormatter"/> to format
+ the current date and time in Universal time.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/> for details on the date pattern syntax.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.PatternStringConverters.UtcDatePatternConverter.Convert(System.IO.TextWriter,System.Object)">
+ <summary>
+ Write the current date and time to the output
+ </summary>
+ <param name="writer"><see cref="T:System.IO.TextWriter"/> that will receive the formatted result.</param>
+ <param name="state">null, state is not set</param>
+ <remarks>
+ <para>
+ Pass the current date and time to the <see cref="T:log4net.DateFormatter.IDateFormatter"/>
+ for it to render it to the writer.
+ </para>
+ <para>
+ The date is in Universal time when it is rendered.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.PatternStringConverters.DatePatternConverter"/>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.BooleanConverter">
+ <summary>
+ Type converter for Boolean.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <c>bool</c> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.BooleanConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.BooleanConverter.ConvertFrom(System.Object)">
+ <summary>
+ Convert the source object to the type supported by this object
+ </summary>
+ <param name="source">the object to convert</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Boolean.Parse(System.String)"/> method to convert the
+ <see cref="T:System.String"/> argument to a <see cref="T:System.Boolean"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.BooleanConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ <summary>
+ Exception base type for conversion errors.
+ </summary>
+ <remarks>
+ <para>
+ This type extends <see cref="T:System.ApplicationException"/>. It
+ does not add any new functionality but does differentiate the
+ type of exception being thrown.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with the specified message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.String,System.Exception)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">A message to include with the exception.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with the specified message and inner exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.Create(System.Type,System.Object)">
+ <summary>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </summary>
+ <param name="destinationType">The conversion destination type.</param>
+ <param name="sourceValue">The value to convert.</param>
+ <returns>An instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/>.</returns>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConversionNotSupportedException.Create(System.Type,System.Object,System.Exception)">
+ <summary>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </summary>
+ <param name="destinationType">The conversion destination type.</param>
+ <param name="sourceValue">The value to convert.</param>
+ <param name="innerException">A nested exception to include.</param>
+ <returns>An instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/>.</returns>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.ConverterRegistry">
+ <summary>
+ Register of type converters for specific types.
+ </summary>
+ <remarks>
+ <para>
+ Maintains a registry of type converters used to convert between
+ types.
+ </para>
+ <para>
+ Use the <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Object)"/> and
+ <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Type)"/> methods to register new converters.
+ The <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertTo(System.Type,System.Type)"/> and <see cref="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertFrom(System.Type)"/> methods
+ lookup appropriate converters to use.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ <remarks>
+ Initializes a new instance of the <see cref="T:log4net.Util.TypeConverters.ConverterRegistry"/> class.
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.#cctor">
+ <summary>
+ Static constructor.
+ </summary>
+ <remarks>
+ <para>
+ This constructor defines the intrinsic type converters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Object)">
+ <summary>
+ Adds a converter for a specific type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <param name="converter">The type converter to use to convert to the destination type.</param>
+ <remarks>
+ <para>
+ Adds a converter instance for a specific type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.AddConverter(System.Type,System.Type)">
+ <summary>
+ Adds a converter for a specific type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <param name="converterType">The type of the type converter to use to convert to the destination type.</param>
+ <remarks>
+ <para>
+ Adds a converter <see cref="T:System.Type"/> for a specific type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertTo(System.Type,System.Type)">
+ <summary>
+ Gets the type converter to use to convert values to the destination type.
+ </summary>
+ <param name="sourceType">The type being converted from.</param>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ Gets the type converter to use to convert values to the destination type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConvertFrom(System.Type)">
+ <summary>
+ Gets the type converter to use to convert values to the destination type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ Gets the type converter to use to convert values to the destination type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.GetConverterFromAttribute(System.Type)">
+ <summary>
+ Lookups the type converter to use as specified by the attributes on the
+ destination type.
+ </summary>
+ <param name="destinationType">The type being converted to.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.ConverterRegistry.CreateConverterInstance(System.Type)">
+ <summary>
+ Creates the instance of the type converter.
+ </summary>
+ <param name="converterType">The type of the type converter.</param>
+ <returns>
+ The type converter instance to use for type conversions or <c>null</c>
+ if no type converter is found.
+ </returns>
+ <remarks>
+ <para>
+ The type specified for the type converter must implement
+ the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/> or <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces
+ and must have a public default (no argument) constructor.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.ConverterRegistry.s_type2converter">
+ <summary>
+ Mapping from <see cref="T:System.Type"/> to type converter.
+ </summary>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.EncodingConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Text.Encoding"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Text.Encoding"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.EncodingConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.EncodingConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to an encoding</param>
+ <returns>the encoding</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Text.Encoding.GetEncoding(System.String)"/> method to
+ convert the <see cref="T:System.String"/> argument to an <see cref="T:System.Text.Encoding"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.EncodingConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IConvertTo">
+ <summary>
+ Interface supported by type converters
+ </summary>
+ <remarks>
+ <para>
+ This interface supports conversion from a single type to arbitrary types.
+ See <see cref="T:log4net.Util.TypeConverters.TypeConverterAttribute"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertTo.CanConvertTo(System.Type)">
+ <summary>
+ Returns whether this converter can convert the object to the specified type
+ </summary>
+ <param name="targetType">A Type that represents the type you want to convert to</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Test if the type supported by this converter can be converted to the
+ <paramref name="targetType"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IConvertTo.ConvertTo(System.Object,System.Type)">
+ <summary>
+ Converts the given value object to the specified type, using the arguments
+ </summary>
+ <param name="source">the object to convert</param>
+ <param name="targetType">The Type to convert the value parameter to</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Converts the <paramref name="source"/> (which must be of the type supported
+ by this converter) to the <paramref name="targetType"/> specified..
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.IPAddressConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Net.IPAddress"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Net.IPAddress"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IPAddressConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.IPAddressConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to an IPAddress</param>
+ <returns>the IPAddress</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Net.IPAddress.Parse(System.String)"/> method to convert the
+ <see cref="T:System.String"/> argument to an <see cref="T:System.Net.IPAddress"/>.
+ If that fails then the string is resolved as a DNS hostname.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.IPAddressConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.IPAddressConverter.validIpAddressChars">
+ <summary>
+ Valid characters in an IPv4 or IPv6 address string. (Does not support subnets)
+ </summary>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.PatternLayoutConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:log4net.Layout.PatternLayout"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:log4net.Layout.PatternLayout"/> type.
+ </para>
+ <para>
+ The string is used as the <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/>
+ of the <see cref="T:log4net.Layout.PatternLayout"/>.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternLayoutConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternLayoutConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a PatternLayout</param>
+ <returns>the PatternLayout</returns>
+ <remarks>
+ <para>
+ Creates and returns a new <see cref="T:log4net.Layout.PatternLayout"/> using
+ the <paramref name="source"/> <see cref="T:System.String"/> as the
+ <see cref="P:log4net.Layout.PatternLayout.ConversionPattern"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.PatternLayoutConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.PatternStringConverter">
+ <summary>
+ Convert between string and <see cref="T:log4net.Util.PatternString"/>
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:log4net.Util.PatternString"/> type,
+ and from a <see cref="T:log4net.Util.PatternString"/> type to a string.
+ </para>
+ <para>
+ The string is used as the <see cref="P:log4net.Util.PatternString.ConversionPattern"/>
+ of the <see cref="T:log4net.Util.PatternString"/>.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertTo(System.Type)">
+ <summary>
+ Can the target type be converted to the type supported by this object
+ </summary>
+ <param name="targetType">A <see cref="T:System.Type"/> that represents the type you want to convert to</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="targetType"/> is
+ assignable from a <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.ConvertTo(System.Object,System.Type)">
+ <summary>
+ Converts the given value object to the specified type, using the arguments
+ </summary>
+ <param name="source">the object to convert</param>
+ <param name="targetType">The Type to convert the value parameter to</param>
+ <returns>the converted object</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:log4net.Util.PatternString.Format"/> method to convert the
+ <see cref="T:log4net.Util.PatternString"/> argument to a <see cref="T:System.String"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ <paramref name="targetType"/>. To check for this condition use the
+ <see cref="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertTo(System.Type)"/> method.
+ </exception>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.PatternStringConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a PatternString</param>
+ <returns>the PatternString</returns>
+ <remarks>
+ <para>
+ Creates and returns a new <see cref="T:log4net.Util.PatternString"/> using
+ the <paramref name="source"/> <see cref="T:System.String"/> as the
+ <see cref="P:log4net.Util.PatternString.ConversionPattern"/>.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.PatternStringConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.TypeConverter">
+ <summary>
+ Supports conversion from string to <see cref="T:System.Type"/> type.
+ </summary>
+ <remarks>
+ <para>
+ Supports conversion from string to <see cref="T:System.Type"/> type.
+ </para>
+ </remarks>
+ <seealso cref="T:log4net.Util.TypeConverters.ConverterRegistry"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ <seealso cref="T:log4net.Util.TypeConverters.IConvertTo"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverter.CanConvertFrom(System.Type)">
+ <summary>
+ Can the source type be converted to the type supported by this object
+ </summary>
+ <param name="sourceType">the type to convert</param>
+ <returns>true if the conversion is possible</returns>
+ <remarks>
+ <para>
+ Returns <c>true</c> if the <paramref name="sourceType"/> is
+ the <see cref="T:System.String"/> type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverter.ConvertFrom(System.Object)">
+ <summary>
+ Overrides the ConvertFrom method of IConvertFrom.
+ </summary>
+ <param name="source">the object to convert to a Type</param>
+ <returns>the Type</returns>
+ <remarks>
+ <para>
+ Uses the <see cref="M:System.Type.GetType(System.String,System.Boolean)"/> method to convert the
+ <see cref="T:System.String"/> argument to a <see cref="T:System.Type"/>.
+ Additional effort is made to locate partially specified types
+ by searching the loaded assemblies.
+ </para>
+ </remarks>
+ <exception cref="T:log4net.Util.TypeConverters.ConversionNotSupportedException">
+ The <paramref name="source"/> object cannot be converted to the
+ target type. To check for this condition use the <see cref="M:log4net.Util.TypeConverters.TypeConverter.CanConvertFrom(System.Type)"/>
+ method.
+ </exception>
+ </member>
+ <member name="T:log4net.Util.TypeConverters.TypeConverterAttribute">
+ <summary>
+ Attribute used to associate a type converter
+ </summary>
+ <remarks>
+ <para>
+ Class and Interface level attribute that specifies a type converter
+ to use with the associated type.
+ </para>
+ <para>
+ To associate a type converter with a target type apply a
+ <c>TypeConverterAttribute</c> to the target type. Specify the
+ type of the type converter on the attribute.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.TypeConverters.TypeConverterAttribute.m_typeName">
+ <summary>
+ The string type name of the type converter
+ </summary>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor(System.String)">
+ <summary>
+ Create a new type converter attribute for the specified type name
+ </summary>
+ <param name="typeName">The string type name of the type converter</param>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TypeConverters.TypeConverterAttribute.#ctor(System.Type)">
+ <summary>
+ Create a new type converter attribute for the specified type
+ </summary>
+ <param name="converterType">The type of the type converter</param>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TypeConverters.TypeConverterAttribute.ConverterTypeName">
+ <summary>
+ The string type name of the type converter
+ </summary>
+ <value>
+ The string type name of the type converter
+ </value>
+ <remarks>
+ <para>
+ The type specified must implement the <see cref="T:log4net.Util.TypeConverters.IConvertFrom"/>
+ or the <see cref="T:log4net.Util.TypeConverters.IConvertTo"/> interfaces.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.AppenderAttachedImpl">
+ <summary>
+ A straightforward implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface.
+ </summary>
+ <remarks>
+ <para>
+ This is the default implementation of the <see cref="T:log4net.Core.IAppenderAttachable"/>
+ interface. Implementors of the <see cref="T:log4net.Core.IAppenderAttachable"/> interface
+ should aggregate an instance of this type.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.AppenderAttachedImpl"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AppendLoopOnAppenders(log4net.Core.LoggingEvent)">
+ <summary>
+ Append on on all attached appenders.
+ </summary>
+ <param name="loggingEvent">The event being logged.</param>
+ <returns>The number of appenders called.</returns>
+ <remarks>
+ <para>
+ Calls the <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method on all
+ attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AppendLoopOnAppenders(log4net.Core.LoggingEvent[])">
+ <summary>
+ Append on on all attached appenders.
+ </summary>
+ <param name="loggingEvents">The array of events being logged.</param>
+ <returns>The number of appenders called.</returns>
+ <remarks>
+ <para>
+ Calls the <see cref="M:log4net.Appender.IAppender.DoAppend(log4net.Core.LoggingEvent)"/> method on all
+ attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.CallAppend(log4net.Appender.IAppender,log4net.Core.LoggingEvent[])">
+ <summary>
+ Calls the DoAppende method on the <see cref="T:log4net.Appender.IAppender"/> with
+ the <see cref="T:log4net.Core.LoggingEvent"/> objects supplied.
+ </summary>
+ <param name="appender">The appender</param>
+ <param name="loggingEvents">The events</param>
+ <remarks>
+ <para>
+ If the <paramref name="appender"/> supports the <see cref="T:log4net.Appender.IBulkAppender"/>
+ interface then the <paramref name="loggingEvents"/> will be passed
+ through using that interface. Otherwise the <see cref="T:log4net.Core.LoggingEvent"/>
+ objects in the array will be passed one at a time.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.AddAppender(log4net.Appender.IAppender)">
+ <summary>
+ Attaches an appender.
+ </summary>
+ <param name="newAppender">The appender to add.</param>
+ <remarks>
+ <para>
+ If the appender is already in the list it won't be added again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.GetAppender(System.String)">
+ <summary>
+ Gets an attached appender with the specified name.
+ </summary>
+ <param name="name">The name of the appender to get.</param>
+ <returns>
+ The appender with the name specified, or <c>null</c> if no appender with the
+ specified name is found.
+ </returns>
+ <remarks>
+ <para>
+ Lookup an attached appender by name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAllAppenders">
+ <summary>
+ Removes all attached appenders.
+ </summary>
+ <remarks>
+ <para>
+ Removes and closes all attached appenders
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAppender(log4net.Appender.IAppender)">
+ <summary>
+ Removes the specified appender from the list of attached appenders.
+ </summary>
+ <param name="appender">The appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.AppenderAttachedImpl.RemoveAppender(System.String)">
+ <summary>
+ Removes the appender with the specified name from the list of appenders.
+ </summary>
+ <param name="name">The name of the appender to remove.</param>
+ <returns>The appender removed from the list</returns>
+ <remarks>
+ <para>
+ The appender removed is not closed.
+ If you are discarding the appender you must call
+ <see cref="M:log4net.Appender.IAppender.Close"/> on the appender removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.AppenderAttachedImpl.m_appenderList">
+ <summary>
+ List of appenders
+ </summary>
+ </member>
+ <member name="F:log4net.Util.AppenderAttachedImpl.m_appenderArray">
+ <summary>
+ Array of appenders, used to cache the m_appenderList
+ </summary>
+ </member>
+ <member name="P:log4net.Util.AppenderAttachedImpl.Appenders">
+ <summary>
+ Gets all attached appenders.
+ </summary>
+ <returns>
+ A collection of attached appenders, or <c>null</c> if there
+ are no attached appenders.
+ </returns>
+ <remarks>
+ <para>
+ The read only collection of all currently attached appenders.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CompositeProperties">
+ <summary>
+ This class aggregates several PropertiesDictionary collections together.
+ </summary>
+ <remarks>
+ <para>
+ Provides a dictionary style lookup over an ordered list of
+ <see cref="T:log4net.Util.PropertiesDictionary"/> collections.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.CompositeProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.Add(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Add a Properties Dictionary to this composite collection
+ </summary>
+ <param name="properties">the properties to add</param>
+ <remarks>
+ <para>
+ Properties dictionaries added first take precedence over dictionaries added
+ later.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CompositeProperties.Flatten">
+ <summary>
+ Flatten this composite collection into a single properties dictionary
+ </summary>
+ <returns>the flattened dictionary</returns>
+ <remarks>
+ <para>
+ Reduces the collection of ordered dictionaries to a single dictionary
+ containing the resultant values for the keys.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CompositeProperties.Item(System.String)">
+ <summary>
+ Gets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Looks up the value for the <paramref name="key"/> specified.
+ The <see cref="T:log4net.Util.PropertiesDictionary"/> collections are searched
+ in the order in which they were added to this collection. The value
+ returned is the value held by the first collection that contains
+ the specified key.
+ </para>
+ <para>
+ If none of the collections contain the specified key then
+ <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ContextPropertiesBase">
+ <summary>
+ Base class for Context Properties implementations
+ </summary>
+ <remarks>
+ <para>
+ This class defines a basic property get set accessor
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="P:log4net.Util.ContextPropertiesBase.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the value of a property
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CountingQuietTextWriter">
+ <summary>
+ Subclass of <see cref="T:log4net.Util.QuietTextWriter"/> that maintains a count of
+ the number of bytes written.
+ </summary>
+ <remarks>
+ <para>
+ This writer counts the number of bytes written.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.QuietTextWriter">
+ <summary>
+ <see cref="T:System.IO.TextWriter"/> that does not leak exceptions
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:log4net.Util.QuietTextWriter"/> does not throw exceptions when things go wrong.
+ Instead, it delegates error handling to its <see cref="T:log4net.Core.IErrorHandler"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.TextWriterAdapter">
+ <summary>
+ Adapter that extends <see cref="T:System.IO.TextWriter"/> and forwards all
+ messages to an instance of <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <remarks>
+ <para>
+ Adapter that extends <see cref="T:System.IO.TextWriter"/> and forwards all
+ messages to an instance of <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.TextWriterAdapter.m_writer">
+ <summary>
+ The writer to forward messages to
+ </summary>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.#ctor(System.IO.TextWriter)">
+ <summary>
+ Create an instance of <see cref="T:log4net.Util.TextWriterAdapter"/> that forwards all
+ messages to a <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to forward to</param>
+ <remarks>
+ <para>
+ Create an instance of <see cref="T:log4net.Util.TextWriterAdapter"/> that forwards all
+ messages to a <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Close">
+ <summary>
+ Closes the writer and releases any system resources associated with the writer
+ </summary>
+ <remarks>
+ <para>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Dispose(System.Boolean)">
+ <summary>
+ Dispose this writer
+ </summary>
+ <param name="disposing">flag indicating if we are being disposed</param>
+ <remarks>
+ <para>
+ Dispose this writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Flush">
+ <summary>
+ Flushes any buffered output
+ </summary>
+ <remarks>
+ <para>
+ Clears all buffers for the writer and causes any buffered data to be written
+ to the underlying device
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.Char)">
+ <summary>
+ Writes a character to the wrapped TextWriter
+ </summary>
+ <param name="value">the value to write to the TextWriter</param>
+ <remarks>
+ <para>
+ Writes a character to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a character buffer to the wrapped TextWriter
+ </summary>
+ <param name="buffer">the data buffer</param>
+ <param name="index">the start index</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Writes a character buffer to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.TextWriterAdapter.Write(System.String)">
+ <summary>
+ Writes a string to the wrapped TextWriter
+ </summary>
+ <param name="value">the value to write to the TextWriter</param>
+ <remarks>
+ <para>
+ Writes a string to the wrapped TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.Writer">
+ <summary>
+ Gets or sets the underlying <see cref="T:System.IO.TextWriter"/>.
+ </summary>
+ <value>
+ The underlying <see cref="T:System.IO.TextWriter"/>.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the underlying <see cref="T:System.IO.TextWriter"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.Encoding">
+ <summary>
+ The Encoding in which the output is written
+ </summary>
+ <value>
+ The <see cref="P:log4net.Util.TextWriterAdapter.Encoding"/>
+ </value>
+ <remarks>
+ <para>
+ The Encoding in which the output is written
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.FormatProvider">
+ <summary>
+ Gets an object that controls formatting
+ </summary>
+ <value>
+ The format provider
+ </value>
+ <remarks>
+ <para>
+ Gets an object that controls formatting
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.TextWriterAdapter.NewLine">
+ <summary>
+ Gets or sets the line terminator string used by the TextWriter
+ </summary>
+ <value>
+ The line terminator to use
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the line terminator string used by the TextWriter
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.#ctor(System.IO.TextWriter,log4net.Core.IErrorHandler)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">the writer to actually write to</param>
+ <param name="errorHandler">the error handler to report error to</param>
+ <remarks>
+ <para>
+ Create a new QuietTextWriter using a writer and error handler
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.Char)">
+ <summary>
+ Writes a character to the underlying writer
+ </summary>
+ <param name="value">the char to write</param>
+ <remarks>
+ <para>
+ Writes a character to the underlying writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a buffer to the underlying writer
+ </summary>
+ <param name="buffer">the buffer to write</param>
+ <param name="index">the start index to write from</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Writes a buffer to the underlying writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Write(System.String)">
+ <summary>
+ Writes a string to the output.
+ </summary>
+ <param name="value">The string data to write to the output.</param>
+ <remarks>
+ <para>
+ Writes a string to the output.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.QuietTextWriter.Close">
+ <summary>
+ Closes the underlying output writer.
+ </summary>
+ <remarks>
+ <para>
+ Closes the underlying output writer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.QuietTextWriter.m_errorHandler">
+ <summary>
+ The error handler instance to pass all errors to
+ </summary>
+ </member>
+ <member name="F:log4net.Util.QuietTextWriter.m_closed">
+ <summary>
+ Flag to indicate if this writer is closed
+ </summary>
+ </member>
+ <member name="P:log4net.Util.QuietTextWriter.ErrorHandler">
+ <summary>
+ Gets or sets the error handler that all errors are passed to.
+ </summary>
+ <value>
+ The error handler that all errors are passed to.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the error handler that all errors are passed to.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.QuietTextWriter.Closed">
+ <summary>
+ Gets a value indicating whether this writer is closed.
+ </summary>
+ <value>
+ <c>true</c> if this writer is closed, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ Gets a value indicating whether this writer is closed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.#ctor(System.IO.TextWriter,log4net.Core.IErrorHandler)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">The <see cref="T:System.IO.TextWriter"/> to actually write to.</param>
+ <param name="errorHandler">The <see cref="T:log4net.Core.IErrorHandler"/> to report errors to.</param>
+ <remarks>
+ <para>
+ Creates a new instance of the <see cref="T:log4net.Util.CountingQuietTextWriter"/> class
+ with the specified <see cref="T:System.IO.TextWriter"/> and <see cref="T:log4net.Core.IErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.Char)">
+ <summary>
+ Writes a character to the underlying writer and counts the number of bytes written.
+ </summary>
+ <param name="value">the char to write</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.Char[],System.Int32,System.Int32)">
+ <summary>
+ Writes a buffer to the underlying writer and counts the number of bytes written.
+ </summary>
+ <param name="buffer">the buffer to write</param>
+ <param name="index">the start index to write from</param>
+ <param name="count">the number of characters to write</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CountingQuietTextWriter.Write(System.String)">
+ <summary>
+ Writes a string to the output and counts the number of bytes written.
+ </summary>
+ <param name="str">The string data to write to the output.</param>
+ <remarks>
+ <para>
+ Overrides implementation of <see cref="T:log4net.Util.QuietTextWriter"/>. Counts
+ the number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.CountingQuietTextWriter.m_countBytes">
+ <summary>
+ Total number of bytes written.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.CountingQuietTextWriter.Count">
+ <summary>
+ Gets or sets the total number of bytes written.
+ </summary>
+ <value>
+ The total number of bytes written.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the total number of bytes written.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.CyclicBuffer">
+ <summary>
+ A fixed size rolling buffer of logging events.
+ </summary>
+ <remarks>
+ <para>
+ An array backed fixed size leaky bucket.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.#ctor(System.Int32)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="maxSize">The maximum number of logging events in the buffer.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.CyclicBuffer"/> class with
+ the specified maximum number of buffered logging events.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="maxSize"/> argument is not a positive integer.</exception>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.Append(log4net.Core.LoggingEvent)">
+ <summary>
+ Appends a <paramref name="loggingEvent"/> to the buffer.
+ </summary>
+ <param name="loggingEvent">The event to append to the buffer.</param>
+ <returns>The event discarded from the buffer, if the buffer is full, otherwise <c>null</c>.</returns>
+ <remarks>
+ <para>
+ Append an event to the buffer. If the buffer still contains free space then
+ <c>null</c> is returned. If the buffer is full then an event will be dropped
+ to make space for the new event, the event dropped is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.PopOldest">
+ <summary>
+ Get and remove the oldest event in the buffer.
+ </summary>
+ <returns>The oldest logging event in the buffer</returns>
+ <remarks>
+ <para>
+ Gets the oldest (first) logging event in the buffer and removes it
+ from the buffer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.PopAll">
+ <summary>
+ Pops all the logging events from the buffer into an array.
+ </summary>
+ <returns>An array of all the logging events in the buffer.</returns>
+ <remarks>
+ <para>
+ Get all the events in the buffer and clear the buffer.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.CyclicBuffer.Clear">
+ <summary>
+ Clear the buffer
+ </summary>
+ <remarks>
+ <para>
+ Clear the buffer of all events. The events in the buffer are lost.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.Item(System.Int32)">
+ <summary>
+ Gets the <paramref name="i"/>th oldest event currently in the buffer.
+ </summary>
+ <value>The <paramref name="i"/>th oldest event currently in the buffer.</value>
+ <remarks>
+ <para>
+ If <paramref name="i"/> is outside the range 0 to the number of events
+ currently in the buffer, then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.MaxSize">
+ <summary>
+ Gets the maximum size of the buffer.
+ </summary>
+ <value>The maximum size of the buffer.</value>
+ <remarks>
+ <para>
+ Gets the maximum size of the buffer
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.CyclicBuffer.Length">
+ <summary>
+ Gets the number of logging events in the buffer.
+ </summary>
+ <value>The number of logging events in the buffer.</value>
+ <remarks>
+ <para>
+ This number is guaranteed to be in the range 0 to <see cref="P:log4net.Util.CyclicBuffer.MaxSize"/>
+ (inclusive).
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.EmptyCollection">
+ <summary>
+ An always empty <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.ICollection"/>
+ interface that always represents an empty collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.EmptyCollection"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.CopyTo(System.Array,System.Int32)">
+ <summary>
+ Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an
+ <see cref="T:System.Array"/>, starting at a particular Array index.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:System.Array"/>
+ that is the destination of the elements copied from
+ <see cref="T:System.Collections.ICollection"/>. The Array must have zero-based
+ indexing.</param>
+ <param name="index">The zero-based index in array at which
+ copying begins.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values are copied into the array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyCollection.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.EmptyCollection.s_instance">
+ <summary>
+ The singleton instance of the empty collection.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.Instance">
+ <summary>
+ Gets the singleton instance of the empty collection.
+ </summary>
+ <returns>The singleton instance of the empty collection.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the empty collection.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.IsSynchronized">
+ <summary>
+ Gets a value indicating if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe).
+ </summary>
+ <value>
+ <b>true</b> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe); otherwise, <b>false</b>.
+ </value>
+ <remarks>
+ <para>
+ For the <see cref="T:log4net.Util.EmptyCollection"/> this property is always <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.Count">
+ <summary>
+ Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="P:log4net.Util.EmptyCollection.Count"/> is always <c>0</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyCollection.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty and thread safe and synchronized this instance is also
+ the <see cref="P:log4net.Util.EmptyCollection.SyncRoot"/> object.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.EmptyDictionary">
+ <summary>
+ An always empty <see cref="T:System.Collections.IDictionary"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IDictionary"/>
+ interface that always represents an empty collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.EmptyDictionary"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.CopyTo(System.Array,System.Int32)">
+ <summary>
+ Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an
+ <see cref="T:System.Array"/>, starting at a particular Array index.
+ </summary>
+ <param name="array">The one-dimensional <see cref="T:System.Array"/>
+ that is the destination of the elements copied from
+ <see cref="T:System.Collections.ICollection"/>. The Array must have zero-based
+ indexing.</param>
+ <param name="index">The zero-based index in array at which
+ copying begins.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values are copied into the array.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Add(System.Object,System.Object)">
+ <summary>
+ Adds an element with the provided key and value to the
+ <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <param name="key">The <see cref="T:System.Object"/> to use as the key of the element to add.</param>
+ <param name="value">The <see cref="T:System.Object"/> to use as the value of the element to add.</param>
+ <remarks>
+ <para>
+ As the collection is empty no new values can be added. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Clear">
+ <summary>
+ Removes all elements from the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <remarks>
+ <para>
+ As the collection is empty no values can be removed. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Contains(System.Object)">
+ <summary>
+ Determines whether the <see cref="T:log4net.Util.EmptyDictionary"/> contains an element
+ with the specified key.
+ </summary>
+ <param name="key">The key to locate in the <see cref="T:log4net.Util.EmptyDictionary"/>.</param>
+ <returns><c>false</c></returns>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="M:log4net.Util.EmptyDictionary.Contains(System.Object)"/> method always returns <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.GetEnumerator">
+ <summary>
+ Returns an enumerator that can iterate through a collection.
+ </summary>
+ <returns>
+ An <see cref="T:System.Collections.IEnumerator"/> that can be used to
+ iterate through the collection.
+ </returns>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.NullEnumerator"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.EmptyDictionary.Remove(System.Object)">
+ <summary>
+ Removes the element with the specified key from the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <param name="key">The key of the element to remove.</param>
+ <remarks>
+ <para>
+ As the collection is empty no values can be removed. A <see cref="T:System.InvalidOperationException"/>
+ is thrown if this method is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="F:log4net.Util.EmptyDictionary.s_instance">
+ <summary>
+ The singleton instance of the empty dictionary.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Instance">
+ <summary>
+ Gets the singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsSynchronized">
+ <summary>
+ Gets a value indicating if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe).
+ </summary>
+ <value>
+ <b>true</b> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread-safe); otherwise, <b>false</b>.
+ </value>
+ <remarks>
+ <para>
+ For the <see cref="T:log4net.Util.EmptyCollection"/> this property is always <b>true</b>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Count">
+ <summary>
+ Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>
+ </summary>
+ <value>
+ The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty the <see cref="P:log4net.Util.EmptyDictionary.Count"/> is always <c>0</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.SyncRoot">
+ <summary>
+ Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </summary>
+ <value>
+ An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
+ </value>
+ <remarks>
+ <para>
+ As the collection is empty and thread safe and synchronized this instance is also
+ the <see cref="P:log4net.Util.EmptyDictionary.SyncRoot"/> object.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsFixedSize">
+ <summary>
+ Gets a value indicating whether the <see cref="T:log4net.Util.EmptyDictionary"/> has a fixed size.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ As the collection is empty <see cref="P:log4net.Util.EmptyDictionary.IsFixedSize"/> always returns <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.IsReadOnly">
+ <summary>
+ Gets a value indicating whether the <see cref="T:log4net.Util.EmptyDictionary"/> is read-only.
+ </summary>
+ <value><c>true</c></value>
+ <remarks>
+ <para>
+ As the collection is empty <see cref="P:log4net.Util.EmptyDictionary.IsReadOnly"/> always returns <c>true</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Keys">
+ <summary>
+ Gets an <see cref="T:System.Collections.ICollection"/> containing the keys of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <value>An <see cref="T:System.Collections.ICollection"/> containing the keys of the <see cref="T:log4net.Util.EmptyDictionary"/>.</value>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Values">
+ <summary>
+ Gets an <see cref="T:System.Collections.ICollection"/> containing the values of the <see cref="T:log4net.Util.EmptyDictionary"/>.
+ </summary>
+ <value>An <see cref="T:System.Collections.ICollection"/> containing the values of the <see cref="T:log4net.Util.EmptyDictionary"/>.</value>
+ <remarks>
+ <para>
+ As the collection is empty a <see cref="T:log4net.Util.EmptyCollection"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.EmptyDictionary.Item(System.Object)">
+ <summary>
+ Gets or sets the element with the specified key.
+ </summary>
+ <param name="key">The key of the element to get or set.</param>
+ <value><c>null</c></value>
+ <remarks>
+ <para>
+ As the collection is empty no values can be looked up or stored.
+ If the index getter is called then <c>null</c> is returned.
+ A <see cref="T:System.InvalidOperationException"/> is thrown if the setter is called.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">This dictionary is always empty and cannot be modified.</exception>
+ </member>
+ <member name="T:log4net.Util.FormattingInfo">
+ <summary>
+ Contain the information obtained when parsing formatting modifiers
+ in conversion modifiers.
+ </summary>
+ <remarks>
+ <para>
+ Holds the formatting information extracted from the format string by
+ the <see cref="T:log4net.Util.PatternParser"/>. This is used by the <see cref="T:log4net.Util.PatternConverter"/>
+ objects when rendering the output.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.FormattingInfo.#ctor">
+ <summary>
+ Defaut Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.FormattingInfo"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.FormattingInfo.#ctor(System.Int32,System.Int32,System.Boolean)">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.FormattingInfo"/> class
+ with the specified parameters.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.Min">
+ <summary>
+ Gets or sets the minimum value.
+ </summary>
+ <value>
+ The minimum value.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the minimum value.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.Max">
+ <summary>
+ Gets or sets the maximum value.
+ </summary>
+ <value>
+ The maximum value.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the maximum value.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.FormattingInfo.LeftAlign">
+ <summary>
+ Gets or sets a flag indicating whether left align is enabled
+ or not.
+ </summary>
+ <value>
+ A flag indicating whether left align is enabled or not.
+ </value>
+ <remarks>
+ <para>
+ Gets or sets a flag indicating whether left align is enabled or not.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.GlobalContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.GlobalContext"/>
+ </summary>
+ <remarks>
+ <para>
+ This class implements a properties collection that is thread safe and supports both
+ storing properties and capturing a read only copy of the current propertied.
+ </para>
+ <para>
+ This class is optimized to the scenario where the properties are read frequently
+ and are modified infrequently.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.GlobalContextProperties.m_readOnlyProperties">
+ <summary>
+ The read only copy of the properties.
+ </summary>
+ <remarks>
+ <para>
+ This variable is declared <c>volatile</c> to prevent the compiler and JIT from
+ reordering reads and writes of this thread performed on different threads.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.GlobalContextProperties.m_syncRoot">
+ <summary>
+ Lock object used to synchronize updates within this instance
+ </summary>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.GlobalContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property from the global context
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Removing an entry from the global context properties is relatively expensive compared
+ with reading a value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.Clear">
+ <summary>
+ Clear the global context properties
+ </summary>
+ </member>
+ <member name="M:log4net.Util.GlobalContextProperties.GetReadOnlyProperties">
+ <summary>
+ Get a readonly immutable copy of the properties
+ </summary>
+ <returns>the current global context properties</returns>
+ <remarks>
+ <para>
+ This implementation is fast because the GlobalContextProperties class
+ stores a readonly copy of the properties.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.GlobalContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Reading the value for a key is faster than setting the value.
+ When the value is written a new read only copy of
+ the properties is created.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LevelMapping">
+ <summary>
+ Manages a mapping from levels to <see cref="T:log4net.Util.LevelMappingEntry"/>
+ </summary>
+ <remarks>
+ <para>
+ Manages an ordered mapping from <see cref="T:log4net.Core.Level"/> instances
+ to <see cref="T:log4net.Util.LevelMappingEntry"/> subclasses.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initialise a new instance of <see cref="T:log4net.Util.LevelMapping"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.Add(log4net.Util.LevelMappingEntry)">
+ <summary>
+ Add a <see cref="T:log4net.Util.LevelMappingEntry"/> to this mapping
+ </summary>
+ <param name="entry">the entry to add</param>
+ <remarks>
+ <para>
+ If a <see cref="T:log4net.Util.LevelMappingEntry"/> has previously been added
+ for the same <see cref="T:log4net.Core.Level"/> then that entry will be
+ overwritten.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.Lookup(log4net.Core.Level)">
+ <summary>
+ Lookup the mapping for the specified level
+ </summary>
+ <param name="level">the level to lookup</param>
+ <returns>the <see cref="T:log4net.Util.LevelMappingEntry"/> for the level or <c>null</c> if no mapping found</returns>
+ <remarks>
+ <para>
+ Lookup the value for the specified level. Finds the nearest
+ mapping value for the level that is equal to or less than the
+ <paramref name="level"/> specified.
+ </para>
+ <para>
+ If no mapping could be found then <c>null</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LevelMapping.ActivateOptions">
+ <summary>
+ Initialize options
+ </summary>
+ <remarks>
+ <para>
+ Caches the sorted list of <see cref="T:log4net.Util.LevelMappingEntry"/> in an array
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LogicalThreadContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.LogicalThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Class implements a collection of properties that is specific to each thread.
+ The class is not synchronized as each thread has its own <see cref="T:log4net.Util.PropertiesDictionary"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.LogicalThreadContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove the value for the specified <paramref name="key"/> from the context.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.Clear">
+ <summary>
+ Clear all the context properties
+ </summary>
+ <remarks>
+ <para>
+ Clear all the context properties
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogicalThreadContextProperties.GetProperties(System.Boolean)">
+ <summary>
+ Get the PropertiesDictionary stored in the LocalDataStoreSlot for this thread.
+ </summary>
+ <param name="create">create the dictionary if it does not exist, otherwise return null if is does not exist</param>
+ <returns>the properties for this thread</returns>
+ <remarks>
+ <para>
+ The collection returned is only to be used on the calling thread. If the
+ caller needs to share the collection between different threads then the
+ caller must clone the collection before doings so.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogicalThreadContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Get or set the property value for the <paramref name="key"/> specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.LogLog">
+ <summary>
+ Outputs log statements from within the log4net assembly.
+ </summary>
+ <remarks>
+ <para>
+ Log4net components cannot make log4net logging calls. However, it is
+ sometimes useful for the user to learn about what log4net is
+ doing.
+ </para>
+ <para>
+ All log4net internal debug calls go to the standard output stream
+ whereas internal error messages are sent to the standard error output
+ stream.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.LogLog.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.LogLog"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.#cctor">
+ <summary>
+ Static constructor that initializes logging by reading
+ settings from the application configuration file.
+ </summary>
+ <remarks>
+ <para>
+ The <c>log4net.Internal.Debug</c> application setting
+ controls internal debugging. This setting should be set
+ to <c>true</c> to enable debugging.
+ </para>
+ <para>
+ The <c>log4net.Internal.Quiet</c> application setting
+ suppresses all internal logging including error messages.
+ This setting should be set to <c>true</c> to enable message
+ suppression.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Debug(System.String)">
+ <summary>
+ Writes log4net internal debug messages to the
+ standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net: ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Debug(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal debug messages to the
+ standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net: ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Warn(System.String)">
+ <summary>
+ Writes log4net internal warning messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal warning messages are prepended with
+ the string "log4net:WARN ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Warn(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal warning messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal warning messages are prepended with
+ the string "log4net:WARN ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Error(System.String)">
+ <summary>
+ Writes log4net internal error messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ All internal error messages are prepended with
+ the string "log4net:ERROR ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.Error(System.String,System.Exception)">
+ <summary>
+ Writes log4net internal error messages to the
+ standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <param name="exception">An exception to log.</param>
+ <remarks>
+ <para>
+ All internal debug messages are prepended with
+ the string "log4net:ERROR ".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.EmitOutLine(System.String)">
+ <summary>
+ Writes output to the standard output stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ Writes to both Console.Out and System.Diagnostics.Trace.
+ Note that the System.Diagnostics.Trace is not supported
+ on the Compact Framework.
+ </para>
+ <para>
+ If the AppDomain is not configured with a config file then
+ the call to System.Diagnostics.Trace may fail. This is only
+ an issue if you are programmatically creating your own AppDomains.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.LogLog.EmitErrorLine(System.String)">
+ <summary>
+ Writes output to the standard error stream.
+ </summary>
+ <param name="message">The message to log.</param>
+ <remarks>
+ <para>
+ Writes to both Console.Error and System.Diagnostics.Trace.
+ Note that the System.Diagnostics.Trace is not supported
+ on the Compact Framework.
+ </para>
+ <para>
+ If the AppDomain is not configured with a config file then
+ the call to System.Diagnostics.Trace may fail. This is only
+ an issue if you are programmatically creating your own AppDomains.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.LogLog.s_debugEnabled">
+ <summary>
+ Default debug level
+ </summary>
+ </member>
+ <member name="F:log4net.Util.LogLog.s_quietMode">
+ <summary>
+ In quietMode not even errors generate any output.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.LogLog.InternalDebugging">
+ <summary>
+ Gets or sets a value indicating whether log4net internal logging
+ is enabled or disabled.
+ </summary>
+ <value>
+ <c>true</c> if log4net internal logging is enabled, otherwise
+ <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ When set to <c>true</c>, internal debug level logging will be
+ displayed.
+ </para>
+ <para>
+ This value can be set by setting the application setting
+ <c>log4net.Internal.Debug</c> in the application configuration
+ file.
+ </para>
+ <para>
+ The default value is <c>false</c>, i.e. debugging is
+ disabled.
+ </para>
+ </remarks>
+ <example>
+ <para>
+ The following example enables internal debugging using the
+ application configuration file :
+ </para>
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net.Internal.Debug" value="true" />
+ </appSettings>
+ </configuration>
+ </code>
+ </example>
+ </member>
+ <member name="P:log4net.Util.LogLog.QuietMode">
+ <summary>
+ Gets or sets a value indicating whether log4net should generate no output
+ from internal logging, not even for errors.
+ </summary>
+ <value>
+ <c>true</c> if log4net should generate no output at all from internal
+ logging, otherwise <c>false</c>.
+ </value>
+ <remarks>
+ <para>
+ When set to <c>true</c> will cause internal logging at all levels to be
+ suppressed. This means that no warning or error reports will be logged.
+ This option overrides the <see cref="P:log4net.Util.LogLog.InternalDebugging"/> setting and
+ disables all debug also.
+ </para>
+ <para>This value can be set by setting the application setting
+ <c>log4net.Internal.Quiet</c> in the application configuration file.
+ </para>
+ <para>
+ The default value is <c>false</c>, i.e. internal logging is not
+ disabled.
+ </para>
+ </remarks>
+ <example>
+ The following example disables internal logging using the
+ application configuration file :
+ <code lang="XML" escaped="true">
+ <configuration>
+ <appSettings>
+ <add key="log4net.Internal.Quiet" value="true"/>
+ </appSettings>
+ </configuration>
+ </code>
+ </example>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsDebugEnabled">
+ <summary>
+ Test if LogLog.Debug is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Debug is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Debug is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsWarnEnabled">
+ <summary>
+ Test if LogLog.Warn is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Warn is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Warn is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.LogLog.IsErrorEnabled">
+ <summary>
+ Test if LogLog.Error is enabled for output.
+ </summary>
+ <value>
+ <c>true</c> if Error is enabled
+ </value>
+ <remarks>
+ <para>
+ Test if LogLog.Error is enabled for output.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.NativeError">
+ <summary>
+ Represents a native error code and message.
+ </summary>
+ <remarks>
+ <para>
+ Represents a Win32 platform native error.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NativeError.#ctor(System.Int32,System.String)">
+ <summary>
+ Create an instance of the <see cref="T:log4net.Util.NativeError"/> class with the specified
+ error number and message.
+ </summary>
+ <param name="number">The number of the native error.</param>
+ <param name="message">The message of the native error.</param>
+ <remarks>
+ <para>
+ Create an instance of the <see cref="T:log4net.Util.NativeError"/> class with the specified
+ error number and message.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetLastError">
+ <summary>
+ Create a new instance of the <see cref="T:log4net.Util.NativeError"/> class for the last Windows error.
+ </summary>
+ <returns>
+ An instance of the <see cref="T:log4net.Util.NativeError"/> class for the last windows error.
+ </returns>
+ <remarks>
+ <para>
+ The message for the <see cref="M:System.Runtime.InteropServices.Marshal.GetLastWin32Error"/> error number is lookup up using the
+ native Win32 <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetError(System.Int32)">
+ <summary>
+ Create a new instance of the <see cref="T:log4net.Util.NativeError"/> class.
+ </summary>
+ <param name="number">the error number for the native error</param>
+ <returns>
+ An instance of the <see cref="T:log4net.Util.NativeError"/> class for the specified
+ error number.
+ </returns>
+ <remarks>
+ <para>
+ The message for the specified error number is lookup up using the
+ native Win32 <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.GetErrorMessage(System.Int32)">
+ <summary>
+ Retrieves the message corresponding with a Win32 message identifier.
+ </summary>
+ <param name="messageId">Message identifier for the requested message.</param>
+ <returns>
+ The message corresponding with the specified message identifier.
+ </returns>
+ <remarks>
+ <para>
+ The message will be searched for in system message-table resource(s)
+ using the native <c>FormatMessage</c> function.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.ToString">
+ <summary>
+ Return error information string
+ </summary>
+ <returns>error information string</returns>
+ <remarks>
+ <para>
+ Return error information string
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NativeError.FormatMessage(System.Int32,System.IntPtr@,System.Int32,System.Int32,System.String@,System.Int32,System.IntPtr)">
+ <summary>
+ Formats a message string.
+ </summary>
+ <param name="dwFlags">Formatting options, and how to interpret the <paramref name="lpSource"/> parameter.</param>
+ <param name="lpSource">Location of the message definition.</param>
+ <param name="dwMessageId">Message identifier for the requested message.</param>
+ <param name="dwLanguageId">Language identifier for the requested message.</param>
+ <param name="lpBuffer">If <paramref name="dwFlags"/> includes FORMAT_MESSAGE_ALLOCATE_BUFFER, the function allocates a buffer using the <c>LocalAlloc</c> function, and places the pointer to the buffer at the address specified in <paramref name="lpBuffer"/>.</param>
+ <param name="nSize">If the FORMAT_MESSAGE_ALLOCATE_BUFFER flag is not set, this parameter specifies the maximum number of TCHARs that can be stored in the output buffer. If FORMAT_MESSAGE_ALLOCATE_BUFFER is set, this parameter specifies the minimum number of TCHARs to allocate for an output buffer.</param>
+ <param name="Arguments">Pointer to an array of values that are used as insert values in the formatted message.</param>
+ <remarks>
+ <para>
+ The function requires a message definition as input. The message definition can come from a
+ buffer passed into the function. It can come from a message table resource in an
+ already-loaded module. Or the caller can ask the function to search the system's message
+ table resource(s) for the message definition. The function finds the message definition
+ in a message table resource based on a message identifier and a language identifier.
+ The function copies the formatted message text to an output buffer, processing any embedded
+ insert sequences if requested.
+ </para>
+ <para>
+ To prevent the usage of unsafe code, this stub does not support inserting values in the formatted message.
+ </para>
+ </remarks>
+ <returns>
+ <para>
+ If the function succeeds, the return value is the number of TCHARs stored in the output
+ buffer, excluding the terminating null character.
+ </para>
+ <para>
+ If the function fails, the return value is zero. To get extended error information,
+ call <see cref="M:System.Runtime.InteropServices.Marshal.GetLastWin32Error"/>.
+ </para>
+ </returns>
+ </member>
+ <member name="P:log4net.Util.NativeError.Number">
+ <summary>
+ Gets the number of the native error.
+ </summary>
+ <value>
+ The number of the native error.
+ </value>
+ <remarks>
+ <para>
+ Gets the number of the native error.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NativeError.Message">
+ <summary>
+ Gets the message of the native error.
+ </summary>
+ <value>
+ The message of the native error.
+ </value>
+ <remarks>
+ <para>
+ </para>
+ Gets the message of the native error.
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.NullDictionaryEnumerator">
+ <summary>
+ An always empty <see cref="T:System.Collections.IDictionaryEnumerator"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IDictionaryEnumerator"/> over a collection
+ that is empty and not modifiable.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.MoveNext">
+ <summary>
+ Test if the enumerator can advance, if so advance.
+ </summary>
+ <returns><c>false</c> as the <see cref="T:log4net.Util.NullDictionaryEnumerator"/> cannot advance.</returns>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="M:log4net.Util.NullDictionaryEnumerator.MoveNext"/>
+ will always return <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullDictionaryEnumerator.Reset">
+ <summary>
+ Resets the enumerator back to the start.
+ </summary>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection <see cref="M:log4net.Util.NullDictionaryEnumerator.Reset"/> does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.NullDictionaryEnumerator.s_instance">
+ <summary>
+ The singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Instance">
+ <summary>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Current">
+ <summary>
+ Gets the current object from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Key">
+ <summary>
+ Gets the current key from the enumerator.
+ </summary>
+ <remarks>
+ Throws an exception because the <see cref="T:log4net.Util.NullDictionaryEnumerator"/>
+ never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Key"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Value">
+ <summary>
+ Gets the current value from the enumerator.
+ </summary>
+ <value>The current value from the enumerator.</value>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Value"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="P:log4net.Util.NullDictionaryEnumerator.Entry">
+ <summary>
+ Gets the current entry from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current entry.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullDictionaryEnumerator.Entry"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullDictionaryEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="T:log4net.Util.NullEnumerator">
+ <summary>
+ An always empty <see cref="T:System.Collections.IEnumerator"/>.
+ </summary>
+ <remarks>
+ <para>
+ A singleton implementation of the <see cref="T:System.Collections.IEnumerator"/> over a collection
+ that is empty and not modifiable.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.NullEnumerator"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to enforce the singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.MoveNext">
+ <summary>
+ Test if the enumerator can advance, if so advance
+ </summary>
+ <returns><c>false</c> as the <see cref="T:log4net.Util.NullEnumerator"/> cannot advance.</returns>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="M:log4net.Util.NullEnumerator.MoveNext"/>
+ will always return <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullEnumerator.Reset">
+ <summary>
+ Resets the enumerator back to the start.
+ </summary>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection <see cref="M:log4net.Util.NullEnumerator.Reset"/> does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.NullEnumerator.s_instance">
+ <summary>
+ The singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.NullEnumerator.Instance">
+ <summary>
+ Get the singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </summary>
+ <returns>The singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.</returns>
+ <remarks>
+ <para>
+ Gets the singleton instance of the <see cref="T:log4net.Util.NullEnumerator"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.NullEnumerator.Current">
+ <summary>
+ Gets the current object from the enumerator.
+ </summary>
+ <remarks>
+ Throws an <see cref="T:System.InvalidOperationException"/> because the
+ <see cref="T:log4net.Util.NullDictionaryEnumerator"/> never has a current value.
+ </remarks>
+ <remarks>
+ <para>
+ As the enumerator is over an empty collection its <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ value cannot be moved over a valid position, therefore <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ will throw an <see cref="T:System.InvalidOperationException"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.InvalidOperationException">The collection is empty and <see cref="P:log4net.Util.NullEnumerator.Current"/>
+ cannot be positioned over a valid location.</exception>
+ </member>
+ <member name="T:log4net.Util.NullSecurityContext">
+ <summary>
+ A SecurityContext used when a SecurityContext is not required
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Util.NullSecurityContext"/> is a no-op implementation of the
+ <see cref="T:log4net.Core.SecurityContext"/> base class. It is used where a <see cref="T:log4net.Core.SecurityContext"/>
+ is required but one has not been provided.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.NullSecurityContext.Instance">
+ <summary>
+ Singleton instance of <see cref="T:log4net.Util.NullSecurityContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Singleton instance of <see cref="T:log4net.Util.NullSecurityContext"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullSecurityContext.#ctor">
+ <summary>
+ Private constructor
+ </summary>
+ <remarks>
+ <para>
+ Private constructor for singleton pattern.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.NullSecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate this SecurityContext
+ </summary>
+ <param name="state">State supplied by the caller</param>
+ <returns><c>null</c></returns>
+ <remarks>
+ <para>
+ No impersonation is done and <c>null</c> is always returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.OnlyOnceErrorHandler">
+ <summary>
+ Implements log4net's default error handling policy which consists
+ of emitting a message for the first error in an appender and
+ ignoring all subsequent errors.
+ </summary>
+ <remarks>
+ <para>
+ The error message is printed on the standard error output stream.
+ </para>
+ <para>
+ This policy aims at protecting an otherwise working application
+ from being flooded with error messages when logging fails.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.#ctor">
+ <summary>
+ Default Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="prefix">The prefix to use for each message.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/> class
+ with the specified prefix.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String,System.Exception,log4net.Core.ErrorCode)">
+ <summary>
+ Log an Error
+ </summary>
+ <param name="message">The error message.</param>
+ <param name="e">The exception.</param>
+ <param name="errorCode">The internal error code.</param>
+ <remarks>
+ <para>
+ Prints the message and the stack trace of the exception on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String,System.Exception)">
+ <summary>
+ Log an Error
+ </summary>
+ <param name="message">The error message.</param>
+ <param name="e">The exception.</param>
+ <remarks>
+ <para>
+ Prints the message and the stack trace of the exception on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OnlyOnceErrorHandler.Error(System.String)">
+ <summary>
+ Log an error
+ </summary>
+ <param name="message">The error message.</param>
+ <remarks>
+ <para>
+ Print a the error message passed as parameter on the standard
+ error output stream.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.OnlyOnceErrorHandler.m_firstTime">
+ <summary>
+ Flag to indicate if it is the first error
+ </summary>
+ </member>
+ <member name="F:log4net.Util.OnlyOnceErrorHandler.m_prefix">
+ <summary>
+ String to prefix each message with
+ </summary>
+ </member>
+ <member name="P:log4net.Util.OnlyOnceErrorHandler.IsEnabled">
+ <summary>
+ Is error logging enabled
+ </summary>
+ <remarks>
+ <para>
+ Is error logging enabled. Logging is only enabled for the
+ first error delivered to the <see cref="T:log4net.Util.OnlyOnceErrorHandler"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.OptionConverter">
+ <summary>
+ A convenience class to convert property values to specific types.
+ </summary>
+ <remarks>
+ <para>
+ Utility functions for converting types and parsing values.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.OptionConverter"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ToBoolean(System.String,System.Boolean)">
+ <summary>
+ Converts a string to a <see cref="T:System.Boolean"/> value.
+ </summary>
+ <param name="argValue">String to convert.</param>
+ <param name="defaultValue">The default value.</param>
+ <returns>The <see cref="T:System.Boolean"/> value of <paramref name="argValue"/>.</returns>
+ <remarks>
+ <para>
+ If <paramref name="argValue"/> is "true", then <c>true</c> is returned.
+ If <paramref name="argValue"/> is "false", then <c>false</c> is returned.
+ Otherwise, <paramref name="defaultValue"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ToFileSize(System.String,System.Int64)">
+ <summary>
+ Parses a file size into a number.
+ </summary>
+ <param name="argValue">String to parse.</param>
+ <param name="defaultValue">The default value.</param>
+ <returns>The <see cref="T:System.Int64"/> value of <paramref name="argValue"/>.</returns>
+ <remarks>
+ <para>
+ Parses a file size of the form: number[KB|MB|GB] into a
+ long value. It is scaled with the appropriate multiplier.
+ </para>
+ <para>
+ <paramref name="defaultValue"/> is returned when <paramref name="argValue"/>
+ cannot be converted to a <see cref="T:System.Int64"/> value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ConvertStringTo(System.Type,System.String)">
+ <summary>
+ Converts a string to an object.
+ </summary>
+ <param name="target">The target type to convert to.</param>
+ <param name="txt">The string to convert to an object.</param>
+ <returns>
+ The object converted from a string or <c>null</c> when the
+ conversion failed.
+ </returns>
+ <remarks>
+ <para>
+ Converts a string to an object. Uses the converter registry to try
+ to convert the string value into the specified target type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.CanConvertTypeTo(System.Type,System.Type)">
+ <summary>
+ Checks if there is an appropriate type conversion from the source type to the target type.
+ </summary>
+ <param name="sourceType">The type to convert from.</param>
+ <param name="targetType">The type to convert to.</param>
+ <returns><c>true</c> if there is a conversion from the source type to the target type.</returns>
+ <remarks>
+ Checks if there is an appropriate type conversion from the source type to the target type.
+ <para>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ConvertTypeTo(System.Object,System.Type)">
+ <summary>
+ Converts an object to the target type.
+ </summary>
+ <param name="sourceInstance">The object to convert to the target type.</param>
+ <param name="targetType">The type to convert to.</param>
+ <returns>The converted object.</returns>
+ <remarks>
+ <para>
+ Converts an object to the target type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.InstantiateByClassName(System.String,System.Type,System.Object)">
+ <summary>
+ Instantiates an object given a class name.
+ </summary>
+ <param name="className">The fully qualified class name of the object to instantiate.</param>
+ <param name="superClass">The class to which the new object should belong.</param>
+ <param name="defaultValue">The object to return in case of non-fulfillment.</param>
+ <returns>
+ An instance of the <paramref name="className"/> or <paramref name="defaultValue"/>
+ if the object could not be instantiated.
+ </returns>
+ <remarks>
+ <para>
+ Checks that the <paramref name="className"/> is a subclass of
+ <paramref name="superClass"/>. If that test fails or the object could
+ not be instantiated, then <paramref name="defaultValue"/> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.SubstituteVariables(System.String,System.Collections.IDictionary)">
+ <summary>
+ Performs variable substitution in string <paramref name="val"/> from the
+ values of keys found in <paramref name="props"/>.
+ </summary>
+ <param name="value">The string on which variable substitution is performed.</param>
+ <param name="props">The dictionary to use to lookup variables.</param>
+ <returns>The result of the substitutions.</returns>
+ <remarks>
+ <para>
+ The variable substitution delimiters are <b>${</b> and <b>}</b>.
+ </para>
+ <para>
+ For example, if props contains <c>key=value</c>, then the call
+ </para>
+ <para>
+ <code lang="C#">
+ string s = OptionConverter.SubstituteVariables("Value of key is ${key}.");
+ </code>
+ </para>
+ <para>
+ will set the variable <c>s</c> to "Value of key is value.".
+ </para>
+ <para>
+ If no value could be found for the specified key, then substitution
+ defaults to an empty string.
+ </para>
+ <para>
+ For example, if system properties contains no value for the key
+ "nonExistentKey", then the call
+ </para>
+ <para>
+ <code lang="C#">
+ string s = OptionConverter.SubstituteVariables("Value of nonExistentKey is [${nonExistentKey}]");
+ </code>
+ </para>
+ <para>
+ will set <s>s</s> to "Value of nonExistentKey is []".
+ </para>
+ <para>
+ An Exception is thrown if <paramref name="value"/> contains a start
+ delimiter "${" which is not balanced by a stop delimiter "}".
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.OptionConverter.ParseEnum(System.Type,System.String,System.Boolean)">
+ <summary>
+ Converts the string representation of the name or numeric value of one or
+ more enumerated constants to an equivalent enumerated object.
+ </summary>
+ <param name="enumType">The type to convert to.</param>
+ <param name="value">The enum string value.</param>
+ <param name="ignoreCase">If <c>true</c>, ignore case; otherwise, regard case.</param>
+ <returns>An object of type <paramref name="enumType" /> whose value is represented by <paramref name="value" />.</returns>
+ </member>
+ <member name="T:log4net.Util.PatternParser">
+ <summary>
+ Most of the work of the <see cref="T:log4net.Layout.PatternLayout"/> class
+ is delegated to the PatternParser class.
+ </summary>
+ <remarks>
+ <para>
+ The <c>PatternParser</c> processes a pattern string and
+ returns a chain of <see cref="T:log4net.Util.PatternConverter"/> objects.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.PatternParser.#ctor(System.String)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="pattern">The pattern to parse.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PatternParser"/> class
+ with the specified pattern string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.Parse">
+ <summary>
+ Parses the pattern into a chain of pattern converters.
+ </summary>
+ <returns>The head of a chain of pattern converters.</returns>
+ <remarks>
+ <para>
+ Parses the pattern into a chain of pattern converters.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.BuildCache">
+ <summary>
+ Build the unified cache of converters from the static and instance maps
+ </summary>
+ <returns>the list of all the converter names</returns>
+ <remarks>
+ <para>
+ Build the unified cache of converters from the static and instance maps
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ParseInternal(System.String,System.String[])">
+ <summary>
+ Internal method to parse the specified pattern to find specified matches
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <param name="matches">the converter names to match in the pattern</param>
+ <remarks>
+ <para>
+ The matches param must be sorted such that longer strings come before shorter ones.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ProcessLiteral(System.String)">
+ <summary>
+ Process a parsed literal
+ </summary>
+ <param name="text">the literal text</param>
+ </member>
+ <member name="M:log4net.Util.PatternParser.ProcessConverter(System.String,System.String,log4net.Util.FormattingInfo)">
+ <summary>
+ Process a parsed converter pattern
+ </summary>
+ <param name="converterName">the name of the converter</param>
+ <param name="option">the optional option for the converter</param>
+ <param name="formattingInfo">the formatting info for the converter</param>
+ </member>
+ <member name="M:log4net.Util.PatternParser.AddConverter(log4net.Util.PatternConverter)">
+ <summary>
+ Resets the internal state of the parser and adds the specified pattern converter
+ to the chain.
+ </summary>
+ <param name="pc">The pattern converter to add.</param>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_head">
+ <summary>
+ The first pattern converter in the chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_tail">
+ <summary>
+ the last pattern converter in the chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_pattern">
+ <summary>
+ The pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternParser.m_patternConverters">
+ <summary>
+ Internal map of converter identifiers to converter types
+ </summary>
+ <remarks>
+ <para>
+ This map overrides the static s_globalRulesRegistry map.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternParser.PatternConverters">
+ <summary>
+ Get the converter registry used by this parser
+ </summary>
+ <value>
+ The converter registry used by this parser
+ </value>
+ <remarks>
+ <para>
+ Get the converter registry used by this parser
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternParser.StringLengthComparer">
+ <summary>
+ Sort strings by length
+ </summary>
+ <remarks>
+ <para>
+ <see cref="T:System.Collections.IComparer"/> that orders strings by string length.
+ The longest strings are placed first
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternString">
+ <summary>
+ This class implements a patterned string.
+ </summary>
+ <remarks>
+ <para>
+ This string has embedded patterns that are resolved and expanded
+ when the string is formatted.
+ </para>
+ <para>
+ This class functions similarly to the <see cref="T:log4net.Layout.PatternLayout"/>
+ in that it accepts a pattern and renders it to a string. Unlike the
+ <see cref="T:log4net.Layout.PatternLayout"/> however the <c>PatternString</c>
+ does not render the properties of a specific <see cref="T:log4net.Core.LoggingEvent"/> but
+ of the process in general.
+ </para>
+ <para>
+ The recognized conversion pattern names are:
+ </para>
+ <list type="table">
+ <listheader>
+ <term>Conversion Pattern Name</term>
+ <description>Effect</description>
+ </listheader>
+ <item>
+ <term>appdomain</term>
+ <description>
+ <para>
+ Used to output the friendly name of the current AppDomain.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>date</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in the local time zone.
+ To output the date in universal time use the <c>%utcdate</c> pattern.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
+ <b>%date{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>env</term>
+ <description>
+ <para>
+ Used to output the a specific environment variable. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%env{COMPUTERNAME}</b> would include the value
+ of the <c>COMPUTERNAME</c> environment variable.
+ </para>
+ <para>
+ The <c>env</c> pattern is not supported on the .NET Compact Framework.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>identity</term>
+ <description>
+ <para>
+ Used to output the user name for the currently active user
+ (Principal.Identity.Name).
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>newline</term>
+ <description>
+ <para>
+ Outputs the platform dependent line separator character or
+ characters.
+ </para>
+ <para>
+ This conversion pattern name offers the same performance as using
+ non-portable line separator strings such as "\n", or "\r\n".
+ Thus, it is the preferred way of specifying a line separator.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>processid</term>
+ <description>
+ <para>
+ Used to output the system process ID for the current process.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>property</term>
+ <description>
+ <para>
+ Used to output a specific context property. The key to
+ lookup must be specified within braces and directly following the
+ pattern specifier, e.g. <b>%property{user}</b> would include the value
+ from the property that is keyed by the string 'user'. Each property value
+ that is to be included in the log must be specified separately.
+ Properties are stored in logging contexts. By default
+ the <c>log4net:HostName</c> property is set to the name of machine on
+ which the event was originally logged.
+ </para>
+ <para>
+ If no key is specified, e.g. <b>%property</b> then all the keys and their
+ values are printed in a comma separated list.
+ </para>
+ <para>
+ The properties of an event are combined from a number of different
+ contexts. These are listed below in the order in which they are searched.
+ </para>
+ <list type="definition">
+ <item>
+ <term>the thread properties</term>
+ <description>
+ The <see cref="P:log4net.ThreadContext.Properties"/> that are set on the current
+ thread. These properties are shared by all events logged on this thread.
+ </description>
+ </item>
+ <item>
+ <term>the global properties</term>
+ <description>
+ The <see cref="P:log4net.GlobalContext.Properties"/> that are set globally. These
+ properties are shared by all the threads in the AppDomain.
+ </description>
+ </item>
+ </list>
+ </description>
+ </item>
+ <item>
+ <term>random</term>
+ <description>
+ <para>
+ Used to output a random string of characters. The string is made up of
+ uppercase letters and numbers. By default the string is 4 characters long.
+ The length of the string can be specified within braces directly following the
+ pattern specifier, e.g. <b>%random{8}</b> would output an 8 character string.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>username</term>
+ <description>
+ <para>
+ Used to output the WindowsIdentity for the currently
+ active user.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>utcdate</term>
+ <description>
+ <para>
+ Used to output the date of the logging event in universal time.
+ The date conversion
+ specifier may be followed by a <i>date format specifier</i> enclosed
+ between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
+ <b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
+ given then ISO8601 format is
+ assumed (<see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>).
+ </para>
+ <para>
+ The date format specifier admits the same syntax as the
+ time pattern string of the <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ <para>
+ For better results it is recommended to use the log4net date
+ formatters. These can be specified using one of the strings
+ "ABSOLUTE", "DATE" and "ISO8601" for specifying
+ <see cref="T:log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
+ <see cref="T:log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
+ <see cref="T:log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
+ <b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
+ </para>
+ <para>
+ These dedicated date formatters perform significantly
+ better than <see cref="M:System.DateTime.ToString(System.String)"/>.
+ </para>
+ </description>
+ </item>
+ <item>
+ <term>%</term>
+ <description>
+ <para>
+ The sequence %% outputs a single percent sign.
+ </para>
+ </description>
+ </item>
+ </list>
+ <para>
+ Additional pattern converters may be registered with a specific <see cref="T:log4net.Util.PatternString"/>
+ instance using <see cref="M:log4net.Util.PatternString.AddConverter(log4net.Util.PatternString.ConverterInfo)"/> or
+ <see cref="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)"/>.
+ </para>
+ <para>
+ See the <see cref="T:log4net.Layout.PatternLayout"/> for details on the
+ <i>format modifiers</i> supported by the patterns.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.PatternString.s_globalRulesRegistry">
+ <summary>
+ Internal map of converter identifiers to converter types.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_pattern">
+ <summary>
+ the pattern
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_head">
+ <summary>
+ the head of the pattern converter chain
+ </summary>
+ </member>
+ <member name="F:log4net.Util.PatternString.m_instanceRulesRegistry">
+ <summary>
+ patterns defined on this PatternString only
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternString.#cctor">
+ <summary>
+ Initialize the global registry
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PatternString.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Initialize a new instance of <see cref="T:log4net.Util.PatternString"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.#ctor(System.String)">
+ <summary>
+ Constructs a PatternString
+ </summary>
+ <param name="pattern">The pattern to use with this PatternString</param>
+ <remarks>
+ <para>
+ Initialize a new instance of <see cref="T:log4net.Util.PatternString"/> with the pattern specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.ActivateOptions">
+ <summary>
+ Initialize object options
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.PatternString.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.PatternString.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.PatternString.ActivateOptions"/> must be called again.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.CreatePatternParser(System.String)">
+ <summary>
+ Create the <see cref="T:log4net.Util.PatternParser"/> used to parse the pattern
+ </summary>
+ <param name="pattern">the pattern to parse</param>
+ <returns>The <see cref="T:log4net.Util.PatternParser"/></returns>
+ <remarks>
+ <para>
+ Returns PatternParser used to parse the conversion string. Subclasses
+ may override this to return a subclass of PatternParser which recognize
+ custom conversion pattern name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.Format(System.IO.TextWriter)">
+ <summary>
+ Produces a formatted string as specified by the conversion pattern.
+ </summary>
+ <param name="writer">The TextWriter to write the formatted event to</param>
+ <remarks>
+ <para>
+ Format the pattern to the <paramref name="writer"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.Format">
+ <summary>
+ Format the pattern as a string
+ </summary>
+ <returns>the pattern formatted as a string</returns>
+ <remarks>
+ <para>
+ Format the pattern to a string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.AddConverter(log4net.Util.PatternString.ConverterInfo)">
+ <summary>
+ Add a converter to this PatternString
+ </summary>
+ <param name="converterInfo">the converter info</param>
+ <remarks>
+ <para>
+ This version of the method is used by the configurator.
+ Programmatic users should use the alternative <see cref="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)"/> method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.AddConverter(System.String,System.Type)">
+ <summary>
+ Add a converter to this PatternString
+ </summary>
+ <param name="name">the name of the conversion pattern for this converter</param>
+ <param name="type">the type of the converter</param>
+ <remarks>
+ <para>
+ Add a converter to this PatternString
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConversionPattern">
+ <summary>
+ Gets or sets the pattern formatting string
+ </summary>
+ <value>
+ The pattern formatting string
+ </value>
+ <remarks>
+ <para>
+ The <b>ConversionPattern</b> option. This is the string which
+ controls formatting and consists of a mix of literal content and
+ conversion specifiers.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PatternString.ConverterInfo">
+ <summary>
+ Wrapper class used to map converter names to converter types
+ </summary>
+ <remarks>
+ <para>
+ Wrapper class used to map converter names to converter types
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PatternString.ConverterInfo.#ctor">
+ <summary>
+ default constructor
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConverterInfo.Name">
+ <summary>
+ Gets or sets the name of the conversion pattern
+ </summary>
+ <value>
+ The name of the conversion pattern
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the name of the conversion pattern
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PatternString.ConverterInfo.Type">
+ <summary>
+ Gets or sets the type of the converter
+ </summary>
+ <value>
+ The type of the converter
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the type of the converter
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.PropertiesDictionary">
+ <summary>
+ String keyed object map.
+ </summary>
+ <remarks>
+ <para>
+ While this collection is serializable only member
+ objects that are serializable will
+ be serialized along with this collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="T:log4net.Util.ReadOnlyPropertiesDictionary">
+ <summary>
+ String keyed object map that is read only.
+ </summary>
+ <remarks>
+ <para>
+ This collection is readonly and cannot be modified.
+ </para>
+ <para>
+ While this collection is serializable only member
+ objects that are serializable will
+ be serialized along with this collection.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="F:log4net.Util.ReadOnlyPropertiesDictionary.m_hashtable">
+ <summary>
+ The Hashtable used to store the properties data
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Copy Constructor
+ </summary>
+ <param name="propertiesDictionary">properties to copy</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Deserialization constructor
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReadOnlyPropertiesDictionary"/> class
+ with serialized data.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.GetKeys">
+ <summary>
+ Gets the key names.
+ </summary>
+ <returns>An array of all the keys.</returns>
+ <remarks>
+ <para>
+ Gets the key names.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.Contains(System.String)">
+ <summary>
+ Test if the dictionary contains a specified key
+ </summary>
+ <param name="key">the key to look for</param>
+ <returns>true if the dictionary contains the specified key</returns>
+ <remarks>
+ <para>
+ Test if the dictionary contains a specified key
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data.</param>
+ <param name="context">The destination for this serialization.</param>
+ <remarks>
+ <para>
+ Serializes this object into the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> provided.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Remove(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Remove(System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Contains(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Contains(System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ <returns></returns>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.Clear">
+ <summary>
+ Remove all properties from the properties collection
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Add(System.Object,System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Add(System.Object,System.Object)"/>
+ </summary>
+ <param name="key"></param>
+ <param name="value"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
+ <summary>
+ See <see cref="M:System.Collections.ICollection.CopyTo(System.Array,System.Int32)"/>
+ </summary>
+ <param name="array"></param>
+ <param name="index"></param>
+ </member>
+ <member name="M:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IEnumerable.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.Item(System.String)">
+ <summary>
+ Gets or sets the value of the property with the specified key.
+ </summary>
+ <value>
+ The value of the property with the specified key.
+ </value>
+ <param name="key">The key of the property to get or set.</param>
+ <remarks>
+ <para>
+ The property value will only be serialized if it is serializable.
+ If it cannot be serialized it will be silently ignored if
+ a serialization operation is performed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.InnerHashtable">
+ <summary>
+ The hashtable used to store the properties
+ </summary>
+ <value>
+ The internal collection used to store the properties
+ </value>
+ <remarks>
+ <para>
+ The hashtable used to store the properties
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#IsReadOnly">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsReadOnly"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Item(System.Object)">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Item(System.Object)"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Values">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Values"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#Keys">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Keys"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#IDictionary#IsFixedSize">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsFixedSize"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#IsSynchronized">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.IsSynchronized"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.Count">
+ <summary>
+ The number of properties in this collection
+ </summary>
+ </member>
+ <member name="P:log4net.Util.ReadOnlyPropertiesDictionary.System#Collections#ICollection#SyncRoot">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.SyncRoot"/>
+ </summary>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor(log4net.Util.ReadOnlyPropertiesDictionary)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="propertiesDictionary">properties to copy</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.PropertiesDictionary"/> class
+ with serialized data.
+ </summary>
+ <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data.</param>
+ <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ <remarks>
+ <para>
+ Because this class is sealed the serialization constructor is private.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.Remove(System.String)">
+ <summary>
+ Remove the entry with the specified key from this dictionary
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove the entry with the specified key from this dictionary
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.GetEnumerator"/>
+ </summary>
+ <returns>an enumerator</returns>
+ <remarks>
+ <para>
+ Returns a <see cref="T:System.Collections.IDictionaryEnumerator"/> over the contest of this collection.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Remove(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Remove(System.Object)"/>
+ </summary>
+ <param name="key">the key to remove</param>
+ <remarks>
+ <para>
+ Remove the entry with the specified key from this dictionary
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Contains(System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Contains(System.Object)"/>
+ </summary>
+ <param name="key">the key to lookup in the collection</param>
+ <returns><c>true</c> if the collection contains the specified key</returns>
+ <remarks>
+ <para>
+ Test if this collection contains a specified key.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.Clear">
+ <summary>
+ Remove all properties from the properties collection
+ </summary>
+ <remarks>
+ <para>
+ Remove all properties from the properties collection
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Add(System.Object,System.Object)">
+ <summary>
+ See <see cref="M:System.Collections.IDictionary.Add(System.Object,System.Object)"/>
+ </summary>
+ <param name="key">the key</param>
+ <param name="value">the value to store for the key</param>
+ <remarks>
+ <para>
+ Store a value for the specified <see cref="T:System.String"/> <paramref name="key"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">Thrown if the <paramref name="key"/> is not a string</exception>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
+ <summary>
+ See <see cref="M:System.Collections.ICollection.CopyTo(System.Array,System.Int32)"/>
+ </summary>
+ <param name="array"></param>
+ <param name="index"></param>
+ </member>
+ <member name="M:log4net.Util.PropertiesDictionary.System#Collections#IEnumerable#GetEnumerator">
+ <summary>
+ See <see cref="M:System.Collections.IEnumerable.GetEnumerator"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.Item(System.String)">
+ <summary>
+ Gets or sets the value of the property with the specified key.
+ </summary>
+ <value>
+ The value of the property with the specified key.
+ </value>
+ <param name="key">The key of the property to get or set.</param>
+ <remarks>
+ <para>
+ The property value will only be serialized if it is serializable.
+ If it cannot be serialized it will be silently ignored if
+ a serialization operation is performed.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#IsReadOnly">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsReadOnly"/>
+ </summary>
+ <value>
+ <c>false</c>
+ </value>
+ <remarks>
+ <para>
+ This collection is modifiable. This property always
+ returns <c>false</c>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Item(System.Object)">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Item(System.Object)"/>
+ </summary>
+ <value>
+ The value for the key specified.
+ </value>
+ <remarks>
+ <para>
+ Get or set a value for the specified <see cref="T:System.String"/> <paramref name="key"/>.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentException">Thrown if the <paramref name="key"/> is not a string</exception>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Values">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Values"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#Keys">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.Keys"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#IDictionary#IsFixedSize">
+ <summary>
+ See <see cref="P:System.Collections.IDictionary.IsFixedSize"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#ICollection#IsSynchronized">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.IsSynchronized"/>
+ </summary>
+ </member>
+ <member name="P:log4net.Util.PropertiesDictionary.System#Collections#ICollection#SyncRoot">
+ <summary>
+ See <see cref="P:System.Collections.ICollection.SyncRoot"/>
+ </summary>
+ </member>
+ <member name="T:log4net.Util.ProtectCloseTextWriter">
+ <summary>
+ A <see cref="T:System.IO.TextWriter"/> that ignores the <see cref="M:log4net.Util.ProtectCloseTextWriter.Close"/> message
+ </summary>
+ <remarks>
+ <para>
+ This writer is used in special cases where it is necessary
+ to protect a writer from being closed by a client.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.#ctor(System.IO.TextWriter)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="writer">the writer to actually write to</param>
+ <remarks>
+ <para>
+ Create a new ProtectCloseTextWriter using a writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.Attach(System.IO.TextWriter)">
+ <summary>
+ Attach this instance to a different underlying <see cref="T:System.IO.TextWriter"/>
+ </summary>
+ <param name="writer">the writer to attach to</param>
+ <remarks>
+ <para>
+ Attach this instance to a different underlying <see cref="T:System.IO.TextWriter"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ProtectCloseTextWriter.Close">
+ <summary>
+ Does not close the underlying output writer.
+ </summary>
+ <remarks>
+ <para>
+ Does not close the underlying output writer.
+ This method does nothing.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ReaderWriterLock">
+ <summary>
+ Defines a lock that supports single writers and multiple readers
+ </summary>
+ <remarks>
+ <para>
+ <c>ReaderWriterLock</c> is used to synchronize access to a resource.
+ At any given time, it allows either concurrent read access for
+ multiple threads, or write access for a single thread. In a
+ situation where a resource is changed infrequently, a
+ <c>ReaderWriterLock</c> provides better throughput than a simple
+ one-at-a-time lock, such as <see cref="T:System.Threading.Monitor"/>.
+ </para>
+ <para>
+ If a platform does not support a <c>System.Threading.ReaderWriterLock</c>
+ implementation then all readers and writers are serialized. Therefore
+ the caller must not rely on multiple simultaneous readers.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.#ctor">
+ <summary>
+ Constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ReaderWriterLock"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.AcquireReaderLock">
+ <summary>
+ Acquires a reader lock
+ </summary>
+ <remarks>
+ <para>
+ <see cref="M:log4net.Util.ReaderWriterLock.AcquireReaderLock"/> blocks if a different thread has the writer
+ lock, or if at least one thread is waiting for the writer lock.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.ReleaseReaderLock">
+ <summary>
+ Decrements the lock count
+ </summary>
+ <remarks>
+ <para>
+ <see cref="M:log4net.Util.ReaderWriterLock.ReleaseReaderLock"/> decrements the lock count. When the count
+ reaches zero, the lock is released.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.AcquireWriterLock">
+ <summary>
+ Acquires the writer lock
+ </summary>
+ <remarks>
+ <para>
+ This method blocks if another thread has a reader lock or writer lock.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReaderWriterLock.ReleaseWriterLock">
+ <summary>
+ Decrements the lock count on the writer lock
+ </summary>
+ <remarks>
+ <para>
+ ReleaseWriterLock decrements the writer lock count.
+ When the count reaches zero, the writer lock is released.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ReusableStringWriter">
+ <summary>
+ A <see cref="T:System.IO.StringWriter"/> that can be <see cref="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)"/> and reused
+ </summary>
+ <remarks>
+ <para>
+ A <see cref="T:System.IO.StringWriter"/> that can be <see cref="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)"/> and reused.
+ This uses a single buffer for string operations.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.#ctor(System.IFormatProvider)">
+ <summary>
+ Create an instance of <see cref="T:log4net.Util.ReusableStringWriter"/>
+ </summary>
+ <param name="formatProvider">the format provider to use</param>
+ <remarks>
+ <para>
+ Create an instance of <see cref="T:log4net.Util.ReusableStringWriter"/>
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.Dispose(System.Boolean)">
+ <summary>
+ Override Dispose to prevent closing of writer
+ </summary>
+ <param name="disposing">flag</param>
+ <remarks>
+ <para>
+ Override Dispose to prevent closing of writer
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ReusableStringWriter.Reset(System.Int32,System.Int32)">
+ <summary>
+ Reset this string writer so that it can be reused.
+ </summary>
+ <param name="maxCapacity">the maximum buffer capacity before it is trimmed</param>
+ <param name="defaultSize">the default size to make the buffer</param>
+ <remarks>
+ <para>
+ Reset this string writer so that it can be reused.
+ The internal buffers are cleared and reset.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.SystemInfo">
+ <summary>
+ Utility class for system specific information.
+ </summary>
+ <remarks>
+ <para>
+ Utility class of static methods for system specific information.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ <author>Alexey Solofnenko</author>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.#ctor">
+ <summary>
+ Private constructor to prevent instances.
+ </summary>
+ <remarks>
+ <para>
+ Only static methods are exposed from this type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.#cctor">
+ <summary>
+ Initialize default values for private static fields.
+ </summary>
+ <remarks>
+ <para>
+ Only static methods are exposed from this type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyLocationInfo(System.Reflection.Assembly)">
+ <summary>
+ Gets the assembly location path for the specified assembly.
+ </summary>
+ <param name="myAssembly">The assembly to get the location for.</param>
+ <returns>The location of the assembly.</returns>
+ <remarks>
+ <para>
+ This method does not guarantee to return the correct path
+ to the assembly. If only tries to give an indication as to
+ where the assembly was loaded from.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyQualifiedName(System.Type)">
+ <summary>
+ Gets the fully qualified name of the <see cref="T:System.Type"/>, including
+ the name of the assembly from which the <see cref="T:System.Type"/> was
+ loaded.
+ </summary>
+ <param name="type">The <see cref="T:System.Type"/> to get the fully qualified name for.</param>
+ <returns>The fully qualified name for the <see cref="T:System.Type"/>.</returns>
+ <remarks>
+ <para>
+ This is equivalent to the <c>Type.AssemblyQualifiedName</c> property,
+ but this method works on the .NET Compact Framework 1.0 as well as
+ the full .NET runtime.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyShortName(System.Reflection.Assembly)">
+ <summary>
+ Gets the short name of the <see cref="T:System.Reflection.Assembly"/>.
+ </summary>
+ <param name="myAssembly">The <see cref="T:System.Reflection.Assembly"/> to get the name for.</param>
+ <returns>The short name of the <see cref="T:System.Reflection.Assembly"/>.</returns>
+ <remarks>
+ <para>
+ The short name of the assembly is the <see cref="P:System.Reflection.Assembly.FullName"/>
+ without the version, culture, or public key. i.e. it is just the
+ assembly's file name without the extension.
+ </para>
+ <para>
+ Use this rather than <c>Assembly.GetName().Name</c> because that
+ is not available on the Compact Framework.
+ </para>
+ <para>
+ Because of a FileIOPermission security demand we cannot do
+ the obvious Assembly.GetName().Name. We are allowed to get
+ the <see cref="P:System.Reflection.Assembly.FullName"/> of the assembly so we
+ start from there and strip out just the assembly name.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.AssemblyFileName(System.Reflection.Assembly)">
+ <summary>
+ Gets the file name portion of the <see cref="T:System.Reflection.Assembly"/>, including the extension.
+ </summary>
+ <param name="myAssembly">The <see cref="T:System.Reflection.Assembly"/> to get the file name for.</param>
+ <returns>The file name of the assembly.</returns>
+ <remarks>
+ <para>
+ Gets the file name portion of the <see cref="T:System.Reflection.Assembly"/>, including the extension.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.Type,System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="relativeType">A sibling type to use to load the type.</param>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified, it will be loaded from the assembly
+ containing the specified relative type. If the type is not found in the assembly
+ then all the loaded assemblies will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified it will be loaded from the
+ assembly that is directly calling this method. If the type is not found
+ in the assembly then all the loaded assemblies will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetTypeFromString(System.Reflection.Assembly,System.String,System.Boolean,System.Boolean)">
+ <summary>
+ Loads the type specified in the type string.
+ </summary>
+ <param name="relativeAssembly">An assembly to load the type from.</param>
+ <param name="typeName">The name of the type to load.</param>
+ <param name="throwOnError">Flag set to <c>true</c> to throw an exception if the type cannot be loaded.</param>
+ <param name="ignoreCase"><c>true</c> to ignore the case of the type name; otherwise, <c>false</c></param>
+ <returns>The type loaded or <c>null</c> if it could not be loaded.</returns>
+ <remarks>
+ <para>
+ If the type name is fully qualified, i.e. if contains an assembly name in
+ the type name, the type will be loaded from the system using
+ <see cref="M:System.Type.GetType(System.String,System.Boolean)"/>.
+ </para>
+ <para>
+ If the type name is not fully qualified it will be loaded from the specified
+ assembly. If the type is not found in the assembly then all the loaded assemblies
+ will be searched for the type.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.NewGuid">
+ <summary>
+ Generate a new guid
+ </summary>
+ <returns>A new Guid</returns>
+ <remarks>
+ <para>
+ Generate a new guid
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.CreateArgumentOutOfRangeException(System.String,System.Object,System.String)">
+ <summary>
+ Create an <see cref="T:System.ArgumentOutOfRangeException"/>
+ </summary>
+ <param name="parameterName">The name of the parameter that caused the exception</param>
+ <param name="actualValue">The value of the argument that causes this exception</param>
+ <param name="message">The message that describes the error</param>
+ <returns>the ArgumentOutOfRangeException object</returns>
+ <remarks>
+ <para>
+ Create a new instance of the <see cref="T:System.ArgumentOutOfRangeException"/> class
+ with a specified error message, the parameter name, and the value
+ of the argument.
+ </para>
+ <para>
+ The Compact Framework does not support the 3 parameter constructor for the
+ <see cref="T:System.ArgumentOutOfRangeException"/> type. This method provides an
+ implementation that works for all platforms.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.TryParse(System.String,System.Int32@)">
+ <summary>
+ Parse a string into an <see cref="T:System.Int32"/> value
+ </summary>
+ <param name="s">the string to parse</param>
+ <param name="val">out param where the parsed value is placed</param>
+ <returns><c>true</c> if the string was able to be parsed into an integer</returns>
+ <remarks>
+ <para>
+ Attempts to parse the string into an integer. If the string cannot
+ be parsed then this method returns <c>false</c>. The method does not throw an exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.TryParse(System.String,System.Int64@)">
+ <summary>
+ Parse a string into an <see cref="T:System.Int64"/> value
+ </summary>
+ <param name="s">the string to parse</param>
+ <param name="val">out param where the parsed value is placed</param>
+ <returns><c>true</c> if the string was able to be parsed into an integer</returns>
+ <remarks>
+ <para>
+ Attempts to parse the string into an integer. If the string cannot
+ be parsed then this method returns <c>false</c>. The method does not throw an exception.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.GetAppSetting(System.String)">
+ <summary>
+ Lookup an application setting
+ </summary>
+ <param name="key">the application settings key to lookup</param>
+ <returns>the value for the key, or <c>null</c></returns>
+ <remarks>
+ <para>
+ Configuration APIs are not supported under the Compact Framework
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.ConvertToFullPath(System.String)">
+ <summary>
+ Convert a path into a fully qualified local file path.
+ </summary>
+ <param name="path">The path to convert.</param>
+ <returns>The fully qualified path.</returns>
+ <remarks>
+ <para>
+ Converts the path specified to a fully
+ qualified path. If the path is relative it is
+ taken as relative from the application base
+ directory.
+ </para>
+ <para>
+ The path specified must be a local file path, a URI is not supported.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemInfo.CreateCaseInsensitiveHashtable">
+ <summary>
+ Creates a new case-insensitive instance of the <see cref="T:System.Collections.Hashtable"/> class with the default initial capacity.
+ </summary>
+ <returns>A new case-insensitive instance of the <see cref="T:System.Collections.Hashtable"/> class with the default initial capacity</returns>
+ <remarks>
+ <para>
+ The new Hashtable instance uses the default load factor, the CaseInsensitiveHashCodeProvider, and the CaseInsensitiveComparer.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.EmptyTypes">
+ <summary>
+ Gets an empty array of types.
+ </summary>
+ <remarks>
+ <para>
+ The <c>Type.EmptyTypes</c> field is not available on
+ the .NET Compact Framework 1.0.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_hostName">
+ <summary>
+ Cache the host name for the current machine
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_appFriendlyName">
+ <summary>
+ Cache the application friendly name
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_nullText">
+ <summary>
+ Text to output when a <c>null</c> is encountered.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_notAvailableText">
+ <summary>
+ Text to output when an unsupported feature is requested.
+ </summary>
+ </member>
+ <member name="F:log4net.Util.SystemInfo.s_processStartTime">
+ <summary>
+ Start time for the current process.
+ </summary>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NewLine">
+ <summary>
+ Gets the system dependent line terminator.
+ </summary>
+ <value>
+ The system dependent line terminator.
+ </value>
+ <remarks>
+ <para>
+ Gets the system dependent line terminator.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ApplicationBaseDirectory">
+ <summary>
+ Gets the base directory for this <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The base directory path for the current <see cref="T:System.AppDomain"/>.</value>
+ <remarks>
+ <para>
+ Gets the base directory for this <see cref="T:System.AppDomain"/>.
+ </para>
+ <para>
+ The value returned may be either a local file path or a URI.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ConfigurationFileLocation">
+ <summary>
+ Gets the path to the configuration file for the current <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The path to the configuration file for the current <see cref="T:System.AppDomain"/>.</value>
+ <remarks>
+ <para>
+ The .NET Compact Framework 1.0 does not have a concept of a configuration
+ file. For this runtime, we use the entry assembly location as the root for
+ the configuration file name.
+ </para>
+ <para>
+ The value returned may be either a local file path or a URI.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.EntryAssemblyLocation">
+ <summary>
+ Gets the path to the file that first executed in the current <see cref="T:System.AppDomain"/>.
+ </summary>
+ <value>The path to the entry assembly.</value>
+ <remarks>
+ <para>
+ Gets the path to the file that first executed in the current <see cref="T:System.AppDomain"/>.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.CurrentThreadId">
+ <summary>
+ Gets the ID of the current thread.
+ </summary>
+ <value>The ID of the current thread.</value>
+ <remarks>
+ <para>
+ On the .NET framework, the <c>AppDomain.GetCurrentThreadId</c> method
+ is used to obtain the thread ID for the current thread. This is the
+ operating system ID for the thread.
+ </para>
+ <para>
+ On the .NET Compact Framework 1.0 it is not possible to get the
+ operating system thread ID for the current thread. The native method
+ <c>GetCurrentThreadId</c> is implemented inline in a header file
+ and cannot be called.
+ </para>
+ <para>
+ On the .NET Framework 2.0 the <c>Thread.ManagedThreadId</c> is used as this
+ gives a stable id unrelated to the operating system thread ID which may
+ change if the runtime is using fibers.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.HostName">
+ <summary>
+ Get the host name or machine name for the current machine
+ </summary>
+ <value>
+ The hostname or machine name
+ </value>
+ <remarks>
+ <para>
+ Get the host name or machine name for the current machine
+ </para>
+ <para>
+ The host name (<see cref="M:System.Net.Dns.GetHostName"/>) or
+ the machine name (<c>Environment.MachineName</c>) for
+ the current machine, or if neither of these are available
+ then <c>NOT AVAILABLE</c> is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ApplicationFriendlyName">
+ <summary>
+ Get this application's friendly name
+ </summary>
+ <value>
+ The friendly name of this application as a string
+ </value>
+ <remarks>
+ <para>
+ If available the name of the application is retrieved from
+ the <c>AppDomain</c> using <c>AppDomain.CurrentDomain.FriendlyName</c>.
+ </para>
+ <para>
+ Otherwise the file name of the entry assembly is used.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.ProcessStartTime">
+ <summary>
+ Get the start time for the current process.
+ </summary>
+ <remarks>
+ <para>
+ This is the time at which the log4net library was loaded into the
+ AppDomain. Due to reports of a hang in the call to <c>System.Diagnostics.Process.StartTime</c>
+ this is not the start time for the current process.
+ </para>
+ <para>
+ The log4net library should be loaded by an application early during its
+ startup, therefore this start time should be a good approximation for
+ the actual start time.
+ </para>
+ <para>
+ Note that AppDomains may be loaded and unloaded within the
+ same process without the process terminating, however this start time
+ will be set per AppDomain.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NullText">
+ <summary>
+ Text to output when a <c>null</c> is encountered.
+ </summary>
+ <remarks>
+ <para>
+ Use this value to indicate a <c>null</c> has been encountered while
+ outputting a string representation of an item.
+ </para>
+ <para>
+ The default value is <c>(null)</c>. This value can be overridden by specifying
+ a value for the <c>log4net.NullText</c> appSetting in the application's
+ .config file.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.SystemInfo.NotAvailableText">
+ <summary>
+ Text to output when an unsupported feature is requested.
+ </summary>
+ <remarks>
+ <para>
+ Use this value when an unsupported feature is requested.
+ </para>
+ <para>
+ The default value is <c>NOT AVAILABLE</c>. This value can be overridden by specifying
+ a value for the <c>log4net.NotAvailableText</c> appSetting in the application's
+ .config file.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.SystemStringFormat">
+ <summary>
+ Utility class that represents a format string.
+ </summary>
+ <remarks>
+ <para>
+ Utility class that represents a format string.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.#ctor(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Initialise the <see cref="T:log4net.Util.SystemStringFormat"/>
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information.</param>
+ <param name="format">A <see cref="T:System.String"/> containing zero or more format items.</param>
+ <param name="args">An <see cref="T:System.Object"/> array containing zero or more objects to format.</param>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.ToString">
+ <summary>
+ Format the string and arguments
+ </summary>
+ <returns>the formatted string</returns>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.StringFormat(System.IFormatProvider,System.String,System.Object[])">
+ <summary>
+ Replaces the format item in a specified <see cref="T:System.String"/> with the text equivalent
+ of the value of a corresponding <see cref="T:System.Object"/> instance in a specified array.
+ A specified parameter supplies culture-specific formatting information.
+ </summary>
+ <param name="provider">An <see cref="T:System.IFormatProvider"/> that supplies culture-specific formatting information.</param>
+ <param name="format">A <see cref="T:System.String"/> containing zero or more format items.</param>
+ <param name="args">An <see cref="T:System.Object"/> array containing zero or more objects to format.</param>
+ <returns>
+ A copy of format in which the format items have been replaced by the <see cref="T:System.String"/>
+ equivalent of the corresponding instances of <see cref="T:System.Object"/> in args.
+ </returns>
+ <remarks>
+ <para>
+ This method does not throw exceptions. If an exception thrown while formatting the result the
+ exception and arguments are returned in the result string.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.StringFormatError(System.Exception,System.String,System.Object[])">
+ <summary>
+ Process an error during StringFormat
+ </summary>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.RenderArray(System.Array,System.Text.StringBuilder)">
+ <summary>
+ Dump the contents of an array into a string builder
+ </summary>
+ </member>
+ <member name="M:log4net.Util.SystemStringFormat.RenderObject(System.Object,System.Text.StringBuilder)">
+ <summary>
+ Dump an object to a string
+ </summary>
+ </member>
+ <member name="T:log4net.Util.ThreadContextProperties">
+ <summary>
+ Implementation of Properties collection for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Class implements a collection of properties that is specific to each thread.
+ The class is not synchronized as each thread has its own <see cref="T:log4net.Util.PropertiesDictionary"/>.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.ThreadContextProperties.s_threadLocalSlot">
+ <summary>
+ The thread local data slot to use to store a PropertiesDictionary.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.#ctor">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextProperties"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.Remove(System.String)">
+ <summary>
+ Remove a property
+ </summary>
+ <param name="key">the key for the entry to remove</param>
+ <remarks>
+ <para>
+ Remove a property
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.Clear">
+ <summary>
+ Clear all properties
+ </summary>
+ <remarks>
+ <para>
+ Clear all properties
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextProperties.GetProperties(System.Boolean)">
+ <summary>
+ Get the <c>PropertiesDictionary</c> for this thread.
+ </summary>
+ <param name="create">create the dictionary if it does not exist, otherwise return null if is does not exist</param>
+ <returns>the properties for this thread</returns>
+ <remarks>
+ <para>
+ The collection returned is only to be used on the calling thread. If the
+ caller needs to share the collection between different threads then the
+ caller must clone the collection before doing so.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextProperties.Item(System.String)">
+ <summary>
+ Gets or sets the value of a property
+ </summary>
+ <value>
+ The value for the property with the specified key
+ </value>
+ <remarks>
+ <para>
+ Gets or sets the value of a property
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack">
+ <summary>
+ Implementation of Stack for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Implementation of Stack for the <see cref="T:log4net.ThreadContext"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.m_stack">
+ <summary>
+ The stack store.
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.#ctor">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Clear">
+ <summary>
+ Clears all the contextual information held in this stack.
+ </summary>
+ <remarks>
+ <para>
+ Clears all the contextual information held in this stack.
+ Only call this if you think that this tread is being reused after
+ a previous call execution which may not have completed correctly.
+ You do not need to use this method if you always guarantee to call
+ the <see cref="M:System.IDisposable.Dispose"/> method of the <see cref="T:System.IDisposable"/>
+ returned from <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> even in exceptional circumstances,
+ for example by using the <c>using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message"))</c>
+ syntax.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Pop">
+ <summary>
+ Removes the top context from this stack.
+ </summary>
+ <returns>The message in the context that was removed from the top of this stack.</returns>
+ <remarks>
+ <para>
+ Remove the top context from this stack, and return
+ it to the caller. If this stack is empty then an
+ empty string (not <see langword="null"/>) is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.Push(System.String)">
+ <summary>
+ Pushes a new context message into this stack.
+ </summary>
+ <param name="message">The new context message.</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> that can be used to clean up the context stack.
+ </returns>
+ <remarks>
+ <para>
+ Pushes a new context onto this stack. An <see cref="T:System.IDisposable"/>
+ is returned that can be used to clean up this stack. This
+ can be easily combined with the <c>using</c> keyword to scope the
+ context.
+ </para>
+ </remarks>
+ <example>Simple example of using the <c>Push</c> method with the <c>using</c> keyword.
+ <code lang="C#">
+ using(log4net.ThreadContext.Stacks["NDC"].Push("Stack_Message"))
+ {
+ log.Warn("This should have an ThreadContext Stack message");
+ }
+ </code>
+ </example>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.GetFullMessage">
+ <summary>
+ Gets the current context information for this stack.
+ </summary>
+ <returns>The current context information.</returns>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.ToString">
+ <summary>
+ Gets the current context information for this stack.
+ </summary>
+ <returns>Gets the current context information</returns>
+ <remarks>
+ <para>
+ Gets the current context information for this stack.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.log4net#Core#IFixingRequired#GetFixedObject">
+ <summary>
+ Get a portable version of this object
+ </summary>
+ <returns>the portable instance of this object</returns>
+ <remarks>
+ <para>
+ Get a cross thread portable version of this object
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.Count">
+ <summary>
+ The number of messages in the stack
+ </summary>
+ <value>
+ The current number of messages in the stack
+ </value>
+ <remarks>
+ <para>
+ The current number of messages in the stack. That is
+ the number of times <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> has been called
+ minus the number of times <see cref="M:log4net.Util.ThreadContextStack.Pop"/> has been called.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.InternalStack">
+ <summary>
+ Gets and sets the internal stack used by this <see cref="T:log4net.Util.ThreadContextStack"/>
+ </summary>
+ <value>The internal storage stack</value>
+ <remarks>
+ <para>
+ This property is provided only to support backward compatability
+ of the <see cref="T:log4net.NDC"/>. Tytpically the internal stack should not
+ be modified.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack.StackFrame">
+ <summary>
+ Inner class used to represent a single context frame in the stack.
+ </summary>
+ <remarks>
+ <para>
+ Inner class used to represent a single context frame in the stack.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.StackFrame.#ctor(System.String,log4net.Util.ThreadContextStack.StackFrame)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="message">The message for this context.</param>
+ <param name="parent">The parent context in the chain.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack.StackFrame"/> class
+ with the specified message and parent context.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.StackFrame.Message">
+ <summary>
+ Get the message.
+ </summary>
+ <value>The message.</value>
+ <remarks>
+ <para>
+ Get the message.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStack.StackFrame.FullMessage">
+ <summary>
+ Gets the full text of the context down to the root level.
+ </summary>
+ <value>
+ The full text of the context down to the root level.
+ </value>
+ <remarks>
+ <para>
+ Gets the full text of the context down to the root level.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStack.AutoPopStackFrame">
+ <summary>
+ Struct returned from the <see cref="M:log4net.Util.ThreadContextStack.Push(System.String)"/> method.
+ </summary>
+ <remarks>
+ <para>
+ This struct implements the <see cref="T:System.IDisposable"/> and is designed to be used
+ with the <see langword="using"/> pattern to remove the stack frame at the end of the scope.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.AutoPopStackFrame.m_frameStack">
+ <summary>
+ The ThreadContextStack internal stack
+ </summary>
+ </member>
+ <member name="F:log4net.Util.ThreadContextStack.AutoPopStackFrame.m_frameDepth">
+ <summary>
+ The depth to trim the stack to when this instance is disposed
+ </summary>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.AutoPopStackFrame.#ctor(System.Collections.Stack,System.Int32)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="frameStack">The internal stack used by the ThreadContextStack.</param>
+ <param name="frameDepth">The depth to return the stack to when this object is disposed.</param>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStack.AutoPopStackFrame"/> class with
+ the specified stack and return depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStack.AutoPopStackFrame.Dispose">
+ <summary>
+ Returns the stack to the correct depth.
+ </summary>
+ <remarks>
+ <para>
+ Returns the stack to the correct depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.ThreadContextStacks">
+ <summary>
+ Implementation of Stacks collection for the <see cref="T:log4net.ThreadContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Implementation of Stacks collection for the <see cref="T:log4net.ThreadContext"/>
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.Util.ThreadContextStacks.#ctor(log4net.Util.ContextPropertiesBase)">
+ <summary>
+ Internal constructor
+ </summary>
+ <remarks>
+ <para>
+ Initializes a new instance of the <see cref="T:log4net.Util.ThreadContextStacks"/> class.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.ThreadContextStacks.Item(System.String)">
+ <summary>
+ Gets the named thread context stack
+ </summary>
+ <value>
+ The named stack
+ </value>
+ <remarks>
+ <para>
+ Gets the named thread context stack
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.Transform">
+ <summary>
+ Utility class for transforming strings.
+ </summary>
+ <remarks>
+ <para>
+ Utility class for transforming strings.
+ </para>
+ </remarks>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.Util.Transform.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.Util.Transform"/> class.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.WriteEscapedXmlString(System.Xml.XmlWriter,System.String,System.String)">
+ <summary>
+ Write a string to an <see cref="T:System.Xml.XmlWriter"/>
+ </summary>
+ <param name="writer">the writer to write to</param>
+ <param name="textData">the string to write</param>
+ <param name="invalidCharReplacement">The string to replace non XML compliant chars with</param>
+ <remarks>
+ <para>
+ The test is escaped either using XML escape entities
+ or using CDATA sections.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.MaskXmlInvalidCharacters(System.String,System.String)">
+ <summary>
+ Replace invalid XML characters in text string
+ </summary>
+ <param name="textData">the XML text input string</param>
+ <param name="mask">the string to use in place of invalid characters</param>
+ <returns>A string that does not contain invalid XML characters.</returns>
+ <remarks>
+ <para>
+ Certain Unicode code points are not allowed in the XML InfoSet, for
+ details see: <a href="http://www.w3.org/TR/REC-xml/#charsets">http://www.w3.org/TR/REC-xml/#charsets</a>.
+ </para>
+ <para>
+ This method replaces any illegal characters in the input string
+ with the mask string specified.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.Transform.CountSubstrings(System.String,System.String)">
+ <summary>
+ Count the number of times that the substring occurs in the text
+ </summary>
+ <param name="text">the text to search</param>
+ <param name="substring">the substring to find</param>
+ <returns>the number of times the substring occurs in the text</returns>
+ <remarks>
+ <para>
+ The substring is assumed to be non repeating within itself.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext">
+ <summary>
+ Impersonate a Windows Account
+ </summary>
+ <remarks>
+ <para>
+ This <see cref="T:log4net.Core.SecurityContext"/> impersonates a Windows account.
+ </para>
+ <para>
+ How the impersonation is done depends on the value of <see cref="M:log4net.Util.WindowsSecurityContext.Impersonate(System.Object)"/>.
+ This allows the context to either impersonate a set of user credentials specified
+ using username, domain name and password or to revert to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.#ctor">
+ <summary>
+ Default constructor
+ </summary>
+ <remarks>
+ <para>
+ Default constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.ActivateOptions">
+ <summary>
+ Initialize the SecurityContext based on the options set.
+ </summary>
+ <remarks>
+ <para>
+ This is part of the <see cref="T:log4net.Core.IOptionHandler"/> delayed object
+ activation scheme. The <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> method must
+ be called on this object after the configuration properties have
+ been set. Until <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> is called this
+ object is in an undefined state and must not be used.
+ </para>
+ <para>
+ If any of the configuration properties are modified then
+ <see cref="M:log4net.Util.WindowsSecurityContext.ActivateOptions"/> must be called again.
+ </para>
+ <para>
+ The security context will try to Logon the specified user account and
+ capture a primary token for impersonation.
+ </para>
+ </remarks>
+ <exception cref="T:System.ArgumentNullException">The required <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/>,
+ <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> or <see cref="P:log4net.Util.WindowsSecurityContext.Password"/> properties were not specified.</exception>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.Impersonate(System.Object)">
+ <summary>
+ Impersonate the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </summary>
+ <param name="state">caller provided state</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> instance that will revoke the impersonation of this SecurityContext
+ </returns>
+ <remarks>
+ <para>
+ Depending on the <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/> property either
+ impersonate a user using credentials supplied or revert
+ to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.LogonUser(System.String,System.String,System.String)">
+ <summary>
+ Create a <see cref="T:System.Security.Principal.WindowsIdentity"/> given the userName, domainName and password.
+ </summary>
+ <param name="userName">the user name</param>
+ <param name="domainName">the domain name</param>
+ <param name="password">the password</param>
+ <returns>the <see cref="T:System.Security.Principal.WindowsIdentity"/> for the account specified</returns>
+ <remarks>
+ <para>
+ Uses the Windows API call LogonUser to get a principal token for the account. This
+ token is used to initialize the WindowsIdentity.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.Credentials">
+ <summary>
+ Gets or sets the impersonation mode for this security context
+ </summary>
+ <value>
+ The impersonation mode for this security context
+ </value>
+ <remarks>
+ <para>
+ Impersonate either a user with user credentials or
+ revert this thread to the credentials of the process.
+ The value is one of the <see cref="T:log4net.Util.WindowsSecurityContext.ImpersonationMode"/>
+ enum.
+ </para>
+ <para>
+ The default value is <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/>
+ </para>
+ <para>
+ When the mode is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/>
+ the user's credentials are established using the
+ <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/>, <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.Password"/>
+ values.
+ </para>
+ <para>
+ When the mode is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.Process"/>
+ no other properties need to be set. If the calling thread is
+ impersonating then it will be reverted back to the process credentials.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.UserName">
+ <summary>
+ Gets or sets the Windows username for this security context
+ </summary>
+ <value>
+ The Windows username for this security context
+ </value>
+ <remarks>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.DomainName">
+ <summary>
+ Gets or sets the Windows domain name for this security context
+ </summary>
+ <value>
+ The Windows domain name for this security context
+ </value>
+ <remarks>
+ <para>
+ The default value for <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> is the local machine name
+ taken from the <see cref="P:System.Environment.MachineName"/> property.
+ </para>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.Util.WindowsSecurityContext.Password">
+ <summary>
+ Sets the password for the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </summary>
+ <value>
+ The password for the Windows account specified by the <see cref="P:log4net.Util.WindowsSecurityContext.UserName"/> and <see cref="P:log4net.Util.WindowsSecurityContext.DomainName"/> properties.
+ </value>
+ <remarks>
+ <para>
+ This property must be set if <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/>
+ is set to <see cref="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User"/> (the default setting).
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext.ImpersonationMode">
+ <summary>
+ The impersonation modes for the <see cref="T:log4net.Util.WindowsSecurityContext"/>
+ </summary>
+ <remarks>
+ <para>
+ See the <see cref="P:log4net.Util.WindowsSecurityContext.Credentials"/> property for
+ details.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.User">
+ <summary>
+ Impersonate a user using the credentials supplied
+ </summary>
+ </member>
+ <member name="F:log4net.Util.WindowsSecurityContext.ImpersonationMode.Process">
+ <summary>
+ Revert this the thread to the credentials of the process
+ </summary>
+ </member>
+ <member name="T:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext">
+ <summary>
+ Adds <see cref="T:System.IDisposable"/> to <see cref="T:System.Security.Principal.WindowsImpersonationContext"/>
+ </summary>
+ <remarks>
+ <para>
+ Helper class to expose the <see cref="T:System.Security.Principal.WindowsImpersonationContext"/>
+ through the <see cref="T:System.IDisposable"/> interface.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext.#ctor(System.Security.Principal.WindowsImpersonationContext)">
+ <summary>
+ Constructor
+ </summary>
+ <param name="impersonationContext">the impersonation context being wrapped</param>
+ <remarks>
+ <para>
+ Constructor
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.Util.WindowsSecurityContext.DisposableImpersonationContext.Dispose">
+ <summary>
+ Revert the impersonation
+ </summary>
+ <remarks>
+ <para>
+ Revert the impersonation
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.GlobalContext">
+ <summary>
+ The log4net Global Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>GlobalContext</c> provides a location for global debugging
+ information to be stored.
+ </para>
+ <para>
+ The global context has a properties map and these properties can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputing these properties.
+ </para>
+ <para>
+ By default the <c>log4net:HostName</c> property is set to the name of
+ the current machine.
+ </para>
+ </remarks>
+ <example>
+ <code lang="C#">
+ GlobalContext.Properties["hostname"] = Environment.MachineName;
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.GlobalContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="F:log4net.GlobalContext.s_properties">
+ <summary>
+ The global context properties instance
+ </summary>
+ </member>
+ <member name="P:log4net.GlobalContext.Properties">
+ <summary>
+ The global properties map.
+ </summary>
+ <value>
+ The global properties map.
+ </value>
+ <remarks>
+ <para>
+ The global properties map.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.LogicalThreadContext">
+ <summary>
+ The log4net Logical Thread Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>LogicalThreadContext</c> provides a location for <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/> specific debugging
+ information to be stored.
+ The <c>LogicalThreadContext</c> properties override any <see cref="T:log4net.ThreadContext"/> or <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ <para>
+ The Logical Thread Context has a properties map and a stack.
+ The properties and stack can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputting these properties.
+ </para>
+ <para>
+ The Logical Thread Context provides a diagnostic context for the current call context.
+ This is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The Logical Thread Context is managed on a per <see cref="T:System.Runtime.Remoting.Messaging.CallContext"/> basis.
+ </para>
+ </remarks>
+ <example>Example of using the thread context properties to store a username.
+ <code lang="C#">
+ LogicalThreadContext.Properties["user"] = userName;
+ log.Info("This log message has a LogicalThreadContext Property called 'user'");
+ </code>
+ </example>
+ <example>Example of how to push a message into the context stack
+ <code lang="C#">
+ using(LogicalThreadContext.Stacks["LDC"].Push("my context message"))
+ {
+ log.Info("This log message has a LogicalThreadContext Stack message that includes 'my context message'");
+
+ } // at the end of the using block the message is automatically popped
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.LogicalThreadContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.LogicalThreadContext.s_properties">
+ <summary>
+ The thread context properties instance
+ </summary>
+ </member>
+ <member name="F:log4net.LogicalThreadContext.s_stacks">
+ <summary>
+ The thread context stacks instance
+ </summary>
+ </member>
+ <member name="P:log4net.LogicalThreadContext.Properties">
+ <summary>
+ The thread properties map
+ </summary>
+ <value>
+ The thread properties map
+ </value>
+ <remarks>
+ <para>
+ The <c>LogicalThreadContext</c> properties override any <see cref="T:log4net.ThreadContext"/>
+ or <see cref="T:log4net.GlobalContext"/> properties with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.LogicalThreadContext.Stacks">
+ <summary>
+ The thread stacks
+ </summary>
+ <value>
+ stack map
+ </value>
+ <remarks>
+ <para>
+ The logical thread stacks.
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.LogManager">
+ <summary>
+ This class is used by client applications to request logger instances.
+ </summary>
+ <remarks>
+ <para>
+ This class has static methods that are used by a client to request
+ a logger instance. The <see cref="M:log4net.LogManager.GetLogger(System.String)"/> method is
+ used to retrieve a logger.
+ </para>
+ <para>
+ See the <see cref="T:log4net.ILog"/> interface for more details.
+ </para>
+ </remarks>
+ <example>Simple example of logging messages
+ <code lang="C#">
+ ILog log = LogManager.GetLogger("application-log");
+
+ log.Info("Application Start");
+ log.Debug("This is a debug message");
+
+ if (log.IsDebugEnabled)
+ {
+ log.Debug("This is another debug message");
+ }
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <seealso cref="T:log4net.ILog"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.LogManager.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.LogManager"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.String)">
+ <overloads>Returns the named logger if it exists.</overloads>
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the default repository) then it
+ returns a reference to the logger, otherwise it returns <c>null</c>.
+ </para>
+ </remarks>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>The logger found, or <c>null</c> if no logger could be found.</returns>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.String,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the specified repository) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger found, or <c>null</c> if the logger doesn't exist in the specified
+ repository.
+ </returns>
+ </member>
+ <member name="M:log4net.LogManager.Exists(System.Reflection.Assembly,System.String)">
+ <summary>
+ Returns the named logger if it exists.
+ </summary>
+ <remarks>
+ <para>
+ If the named logger exists (in the repository for the specified assembly) then it
+ returns a reference to the logger, otherwise it returns
+ <c>null</c>.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The fully qualified logger name to look for.</param>
+ <returns>
+ The logger, or <c>null</c> if the logger doesn't exist in the specified
+ assembly's repository.
+ </returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers">
+ <overloads>Get the currently defined loggers.</overloads>
+ <summary>
+ Returns all the currently defined loggers in the default repository.
+ </summary>
+ <remarks>
+ <para>The root logger is <b>not</b> included in the returned array.</para>
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers(System.String)">
+ <summary>
+ Returns all the currently defined loggers in the specified repository.
+ </summary>
+ <param name="repository">The repository to lookup in.</param>
+ <remarks>
+ The root logger is <b>not</b> included in the returned array.
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetCurrentLoggers(System.Reflection.Assembly)">
+ <summary>
+ Returns all the currently defined loggers in the specified assembly's repository.
+ </summary>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <remarks>
+ The root logger is <b>not</b> included in the returned array.
+ </remarks>
+ <returns>All the defined loggers.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String)">
+ <overloads>Get or create a logger.</overloads>
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieves a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieve a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.String)">
+ <summary>
+ Retrieves or creates a named logger.
+ </summary>
+ <remarks>
+ <para>
+ Retrieve a logger named as the <paramref name="name"/>
+ parameter. If the named logger already exists, then the
+ existing instance will be returned. Otherwise, a new instance is
+ created.
+ </para>
+ <para>
+ By default, loggers do not have a set level but inherit
+ it from the hierarchy. This is one of the central features of
+ log4net.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="name">The name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Get the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.String,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Gets the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLogger(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Shorthand for <see cref="M:log4net.LogManager.GetLogger(System.String)"/>.
+ </summary>
+ <remarks>
+ Gets the logger for the fully qualified name of the type specified.
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ <param name="type">The full name of <paramref name="type"/> will be used as the name of the logger to retrieve.</param>
+ <returns>The logger with the name specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.Shutdown">
+ <summary>
+ Shuts down the log4net system.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in all the
+ default repositories.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository">
+ <overloads>Shutdown a logger repository.</overloads>
+ <summary>
+ Shuts down the default repository.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ default repository.
+ </para>
+ <para>Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository(System.String)">
+ <summary>
+ Shuts down the repository for the repository specified.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ <paramref name="repository"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ <param name="repository">The repository to shutdown.</param>
+ </member>
+ <member name="M:log4net.LogManager.ShutdownRepository(System.Reflection.Assembly)">
+ <summary>
+ Shuts down the repository specified.
+ </summary>
+ <remarks>
+ <para>
+ Calling this method will <b>safely</b> close and remove all
+ appenders in all the loggers including root contained in the
+ repository. The repository is looked up using
+ the <paramref name="repositoryAssembly"/> specified.
+ </para>
+ <para>
+ Some appenders need to be closed before the application exists.
+ Otherwise, pending logging events might be lost.
+ </para>
+ <para>
+ The <c>shutdown</c> method is careful to close nested
+ appenders before closing regular appenders. This is allows
+ configurations where a regular appender is attached to a logger
+ and again to a nested appender.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration">
+ <overloads>Reset the configuration of a repository</overloads>
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Resets all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration(System.String)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ <param name="repository">The repository to reset.</param>
+ </member>
+ <member name="M:log4net.LogManager.ResetConfiguration(System.Reflection.Assembly)">
+ <summary>
+ Resets all values contained in this repository instance to their defaults.
+ </summary>
+ <remarks>
+ <para>
+ Reset all values contained in the repository instance to their
+ defaults. This removes all appenders from all loggers, sets
+ the level of all non-root loggers to <c>null</c>,
+ sets their additivity flag to <c>true</c> and sets the level
+ of the root logger to <see cref="F:log4net.Core.Level.Debug"/>. Moreover,
+ message disabling is set to its default "off" value.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository to reset.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository">
+ <overloads>Get the logger repository.</overloads>
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the callers assembly (<see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> instance for the default repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository(System.String)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetLoggerRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repositoryAssembly"/> argument.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository">
+ <overloads>Get a logger repository.</overloads>
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the callers assembly (<see cref="M:System.Reflection.Assembly.GetCallingAssembly"/>).
+ </para>
+ </remarks>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> instance for the default repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository(System.String)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repository"/> argument.
+ </para>
+ </remarks>
+ <param name="repository">The repository to lookup in.</param>
+ </member>
+ <member name="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)">
+ <summary>
+ Returns the default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.
+ </summary>
+ <returns>The default <see cref="T:log4net.Repository.ILoggerRepository"/> instance.</returns>
+ <remarks>
+ <para>
+ Gets the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified
+ by the <paramref name="repositoryAssembly"/> argument.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.Type)">
+ <overloads>Create a domain</overloads>
+ <summary>
+ Creates a repository with the specified repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository"/> will return
+ the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.Type)">
+ <overloads>Create a logger repository.</overloads>
+ <summary>
+ Creates a repository with the specified repository type.
+ </summary>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository"/> will return
+ the same repository instance.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.String)">
+ <summary>
+ Creates a repository with the specified name.
+ </summary>
+ <remarks>
+ <para>
+ Creates the default type of <see cref="T:log4net.Repository.ILoggerRepository"/> which is a
+ <see cref="T:log4net.Repository.Hierarchy.Hierarchy"/> object.
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.String,System.Type)">
+ <summary>
+ Creates a repository with the specified name and repository type.
+ </summary>
+ <remarks>
+ <para>
+ The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
+ An <see cref="T:System.Exception"/> will be thrown if the repository already exists.
+ </para>
+ </remarks>
+ <param name="repository">The name of the repository, this must be unique to the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ <exception cref="T:log4net.Core.LogException">The specified repository already exists.</exception>
+ </member>
+ <member name="M:log4net.LogManager.CreateDomain(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <remarks>
+ <para>
+ <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
+ </para>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.CreateRepository(System.Reflection.Assembly,System.Type)">
+ <summary>
+ Creates a repository for the specified assembly and repository type.
+ </summary>
+ <remarks>
+ <para>
+ The <see cref="T:log4net.Repository.ILoggerRepository"/> created will be associated with the repository
+ specified such that a call to <see cref="M:log4net.LogManager.GetRepository(System.Reflection.Assembly)"/> with the
+ same assembly specified will return the same repository instance.
+ </para>
+ </remarks>
+ <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
+ <param name="repositoryType">A <see cref="T:System.Type"/> that implements <see cref="T:log4net.Repository.ILoggerRepository"/>
+ and has a no arg constructor. An instance of this type will be created to act
+ as the <see cref="T:log4net.Repository.ILoggerRepository"/> for the repository specified.</param>
+ <returns>The <see cref="T:log4net.Repository.ILoggerRepository"/> created for the repository.</returns>
+ </member>
+ <member name="M:log4net.LogManager.GetAllRepositories">
+ <summary>
+ Gets the list of currently defined repositories.
+ </summary>
+ <remarks>
+ <para>
+ Get an array of all the <see cref="T:log4net.Repository.ILoggerRepository"/> objects that have been created.
+ </para>
+ </remarks>
+ <returns>An array of all the known <see cref="T:log4net.Repository.ILoggerRepository"/> objects.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapLogger(log4net.Core.ILogger)">
+ <summary>
+ Looks up the wrapper object for the logger specified.
+ </summary>
+ <param name="logger">The logger to get the wrapper for.</param>
+ <returns>The wrapper for the logger specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapLoggers(log4net.Core.ILogger[])">
+ <summary>
+ Looks up the wrapper objects for the loggers specified.
+ </summary>
+ <param name="loggers">The loggers to get the wrappers for.</param>
+ <returns>The wrapper objects for the loggers specified.</returns>
+ </member>
+ <member name="M:log4net.LogManager.WrapperCreationHandler(log4net.Core.ILogger)">
+ <summary>
+ Create the <see cref="T:log4net.Core.ILoggerWrapper"/> objects used by
+ this manager.
+ </summary>
+ <param name="logger">The logger to wrap.</param>
+ <returns>The wrapper for the logger specified.</returns>
+ </member>
+ <member name="F:log4net.LogManager.s_wrapperMap">
+ <summary>
+ The wrapper map to use to hold the <see cref="T:log4net.Core.LogImpl"/> objects.
+ </summary>
+ </member>
+ <member name="T:log4net.MDC">
+ <summary>
+ Implementation of Mapped Diagnostic Contexts.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ The MDC class is similar to the <see cref="T:log4net.NDC"/> class except that it is
+ based on a map instead of a stack. It provides <i>mapped
+ diagnostic contexts</i>. A <i>Mapped Diagnostic Context</i>, or
+ MDC in short, is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The MDC is managed on a per thread basis.
+ </para>
+ </remarks>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.MDC.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.MDC"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Get(System.String)">
+ <summary>
+ Gets the context value identified by the <paramref name="key"/> parameter.
+ </summary>
+ <param name="key">The key to lookup in the MDC.</param>
+ <returns>The string value held for the key, or a <c>null</c> reference if no corresponding value is found.</returns>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ If the <paramref name="key"/> parameter does not look up to a
+ previously defined context then <c>null</c> will be returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Set(System.String,System.String)">
+ <summary>
+ Add an entry to the MDC
+ </summary>
+ <param name="key">The key to store the value under.</param>
+ <param name="value">The value to store.</param>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Puts a context value (the <paramref name="val"/> parameter) as identified
+ with the <paramref name="key"/> parameter into the current thread's
+ context map.
+ </para>
+ <para>
+ If a value is already defined for the <paramref name="key"/>
+ specified then the value will be replaced. If the <paramref name="val"/>
+ is specified as <c>null</c> then the key value mapping will be removed.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Remove(System.String)">
+ <summary>
+ Removes the key value mapping for the key specified.
+ </summary>
+ <param name="key">The key to remove.</param>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Remove the specified entry from this thread's MDC
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.MDC.Clear">
+ <summary>
+ Clear all entries in the MDC
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The MDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Properties"/>.
+ The current MDC implementation forwards to the <c>ThreadContext.Properties</c>.
+ </para>
+ </note>
+ <para>
+ Remove all the entries from this thread's MDC
+ </para>
+ </remarks>
+ </member>
+ <member name="T:log4net.NDC">
+ <summary>
+ Implementation of Nested Diagnostic Contexts.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ A Nested Diagnostic Context, or NDC in short, is an instrument
+ to distinguish interleaved log output from different sources. Log
+ output is typically interleaved when a server handles multiple
+ clients near-simultaneously.
+ </para>
+ <para>
+ Interleaved log output can still be meaningful if each log entry
+ from different contexts had a distinctive stamp. This is where NDCs
+ come into play.
+ </para>
+ <para>
+ Note that NDCs are managed on a per thread basis. The NDC class
+ is made up of static methods that operate on the context of the
+ calling thread.
+ </para>
+ </remarks>
+ <example>How to push a message into the context
+ <code lang="C#">
+ using(NDC.Push("my context message"))
+ {
+ ... all log calls will have 'my context message' included ...
+
+ } // at the end of the using block the message is automatically removed
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ <author>Gert Driesen</author>
+ </member>
+ <member name="M:log4net.NDC.#ctor">
+ <summary>
+ Initializes a new instance of the <see cref="T:log4net.NDC"/> class.
+ </summary>
+ <remarks>
+ Uses a private access modifier to prevent instantiation of this class.
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Clear">
+ <summary>
+ Clears all the contextual information held on the current thread.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Clears the stack of NDC data held on the current thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.CloneStack">
+ <summary>
+ Creates a clone of the stack of context information.
+ </summary>
+ <returns>A clone of the context info for this thread.</returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ The results of this method can be passed to the <see cref="M:log4net.NDC.Inherit(System.Collections.Stack)"/>
+ method to allow child threads to inherit the context of their
+ parent thread.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Inherit(System.Collections.Stack)">
+ <summary>
+ Inherits the contextual information from another thread.
+ </summary>
+ <param name="stack">The context stack to inherit.</param>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ This thread will use the context information from the stack
+ supplied. This can be used to initialize child threads with
+ the same contextual information as their parent threads. These
+ contexts will <b>NOT</b> be shared. Any further contexts that
+ are pushed onto the stack will not be visible to the other.
+ Call <see cref="M:log4net.NDC.CloneStack"/> to obtain a stack to pass to
+ this method.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Pop">
+ <summary>
+ Removes the top context from the stack.
+ </summary>
+ <returns>
+ The message in the context that was removed from the top
+ of the stack.
+ </returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Remove the top context from the stack, and return
+ it to the caller. If the stack is empty then an
+ empty string (not <c>null</c>) is returned.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.Push(System.String)">
+ <summary>
+ Pushes a new context message.
+ </summary>
+ <param name="message">The new context message.</param>
+ <returns>
+ An <see cref="T:System.IDisposable"/> that can be used to clean up
+ the context stack.
+ </returns>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Pushes a new context onto the context stack. An <see cref="T:System.IDisposable"/>
+ is returned that can be used to clean up the context stack. This
+ can be easily combined with the <c>using</c> keyword to scope the
+ context.
+ </para>
+ </remarks>
+ <example>Simple example of using the <c>Push</c> method with the <c>using</c> keyword.
+ <code lang="C#">
+ using(log4net.NDC.Push("NDC_Message"))
+ {
+ log.Warn("This should have an NDC message");
+ }
+ </code>
+ </example>
+ </member>
+ <member name="M:log4net.NDC.Remove">
+ <summary>
+ Removes the context information for this thread. It is
+ not required to call this method.
+ </summary>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ This method is not implemented.
+ </para>
+ </remarks>
+ </member>
+ <member name="M:log4net.NDC.SetMaxDepth(System.Int32)">
+ <summary>
+ Forces the stack depth to be at most <paramref name="maxDepth"/>.
+ </summary>
+ <param name="maxDepth">The maximum depth of the stack</param>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ Forces the stack depth to be at most <paramref name="maxDepth"/>.
+ This may truncate the head of the stack. This only affects the
+ stack in the current thread. Also it does not prevent it from
+ growing, it only sets the maximum depth at the time of the
+ call. This can be used to return to a known context depth.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.NDC.Depth">
+ <summary>
+ Gets the current context depth.
+ </summary>
+ <value>The current context depth.</value>
+ <remarks>
+ <note>
+ <para>
+ The NDC is deprecated and has been replaced by the <see cref="P:log4net.ThreadContext.Stacks"/>.
+ The current NDC implementation forwards to the <c>ThreadContext.Stacks["NDC"]</c>.
+ </para>
+ </note>
+ <para>
+ The number of context values pushed onto the context stack.
+ </para>
+ <para>
+ Used to record the current depth of the context. This can then
+ be restored using the <see cref="M:log4net.NDC.SetMaxDepth(System.Int32)"/> method.
+ </para>
+ </remarks>
+ <seealso cref="M:log4net.NDC.SetMaxDepth(System.Int32)"/>
+ </member>
+ <member name="T:log4net.ThreadContext">
+ <summary>
+ The log4net Thread Context.
+ </summary>
+ <remarks>
+ <para>
+ The <c>ThreadContext</c> provides a location for thread specific debugging
+ information to be stored.
+ The <c>ThreadContext</c> properties override any <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ <para>
+ The thread context has a properties map and a stack.
+ The properties and stack can
+ be included in the output of log messages. The <see cref="T:log4net.Layout.PatternLayout"/>
+ supports selecting and outputting these properties.
+ </para>
+ <para>
+ The Thread Context provides a diagnostic context for the current thread.
+ This is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+ </para>
+ <para>
+ The Thread Context is managed on a per thread basis.
+ </para>
+ </remarks>
+ <example>Example of using the thread context properties to store a username.
+ <code lang="C#">
+ ThreadContext.Properties["user"] = userName;
+ log.Info("This log message has a ThreadContext Property called 'user'");
+ </code>
+ </example>
+ <example>Example of how to push a message into the context stack
+ <code lang="C#">
+ using(ThreadContext.Stacks["NDC"].Push("my context message"))
+ {
+ log.Info("This log message has a ThreadContext Stack message that includes 'my context message'");
+
+ } // at the end of the using block the message is automatically popped
+ </code>
+ </example>
+ <threadsafety static="true" instance="true"/>
+ <author>Nicko Cadell</author>
+ </member>
+ <member name="M:log4net.ThreadContext.#ctor">
+ <summary>
+ Private Constructor.
+ </summary>
+ <remarks>
+ <para>
+ Uses a private access modifier to prevent instantiation of this class.
+ </para>
+ </remarks>
+ </member>
+ <member name="F:log4net.ThreadContext.s_properties">
+ <summary>
+ The thread context properties instance
+ </summary>
+ </member>
+ <member name="F:log4net.ThreadContext.s_stacks">
+ <summary>
+ The thread context stacks instance
+ </summary>
+ </member>
+ <member name="P:log4net.ThreadContext.Properties">
+ <summary>
+ The thread properties map
+ </summary>
+ <value>
+ The thread properties map
+ </value>
+ <remarks>
+ <para>
+ The <c>ThreadContext</c> properties override any <see cref="T:log4net.GlobalContext"/>
+ properties with the same name.
+ </para>
+ </remarks>
+ </member>
+ <member name="P:log4net.ThreadContext.Stacks">
+ <summary>
+ The thread stacks
+ </summary>
+ <value>
+ stack map
+ </value>
+ <remarks>
+ <para>
+ The thread local stacks.
+ </para>
+ </remarks>
+ </member>
+ </members>
+</doc>
diff --git a/dotnet/client-010/lib/nunit/nunit-licence.txt b/dotnet/client-010/lib/nunit/nunit-licence.txt
new file mode 100644
index 0000000000..b2316295d3
--- /dev/null
+++ b/dotnet/client-010/lib/nunit/nunit-licence.txt
@@ -0,0 +1,23 @@
+Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov,
+ Charlie Poole
+Copyright © 2000-2004 Philip A. Craig
+
+This software is provided 'as-is', without any express or implied warranty. In
+no event will the authors be held liable for any damages arising from the use
+of this software.
+
+Permission is granted to anyone to use this software for any purpose, including
+commercial applications, and to alter it and redistribute it freely, subject to
+the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a product, an
+ acknowledgment (see the following) in the product documentation is required.
+
+ Portions Copyright © 2002 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
+ or Copyright © 2000-2002 Philip A. Craig
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/dotnet/client-010/lib/nunit/nunit.framework.dll b/dotnet/client-010/lib/nunit/nunit.framework.dll
new file mode 100644
index 0000000000..53666e74c9
--- /dev/null
+++ b/dotnet/client-010/lib/nunit/nunit.framework.dll
Binary files differ
diff --git a/dotnet/client-010/lib/plossum/C5-License.txt b/dotnet/client-010/lib/plossum/C5-License.txt
new file mode 100644
index 0000000000..5649c70cf3
--- /dev/null
+++ b/dotnet/client-010/lib/plossum/C5-License.txt
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+
+The following license applies to the C5 library (found in C5.dll and C5.pdb)
+The source code for this library together with more information can be found on
+http://www.itu.dk/research/c5/.
+
+-----------------------------------------------------------------------------
+
+Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/dotnet/client-010/lib/plossum/C5.dll b/dotnet/client-010/lib/plossum/C5.dll
new file mode 100644
index 0000000000..08362849c9
--- /dev/null
+++ b/dotnet/client-010/lib/plossum/C5.dll
Binary files differ
diff --git a/dotnet/client-010/lib/plossum/Plossum CommandLine.dll b/dotnet/client-010/lib/plossum/Plossum CommandLine.dll
new file mode 100644
index 0000000000..d3aad9485d
--- /dev/null
+++ b/dotnet/client-010/lib/plossum/Plossum CommandLine.dll
Binary files differ
diff --git a/dotnet/client-010/lib/plossum/license.txt b/dotnet/client-010/lib/plossum/license.txt
new file mode 100644
index 0000000000..532b9c11a3
--- /dev/null
+++ b/dotnet/client-010/lib/plossum/license.txt
@@ -0,0 +1,28 @@
+Copyright (c) Peter Palotas 2007
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/dotnet/client-010/log.xml b/dotnet/client-010/log.xml
new file mode 100644
index 0000000000..cda84d7c7b
--- /dev/null
+++ b/dotnet/client-010/log.xml
@@ -0,0 +1,46 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<log4net>
+ <appender name="Console" type="log4net.Appender.ConsoleAppender">
+ <layout type="log4net.Layout.PatternLayout">
+ <!-- Pattern to output the caller's file name and line number -->
+ <conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
+ </layout>
+ </appender>
+
+ <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
+ <file value="logs/mylogfile.log" />
+ <appendToFile value="true" />
+ <maximumFileSize value="8192KB" />
+ <maxSizeRollBackups value="2" />
+
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %-5level %ndc - %message%newline" />
+ <!--<conversionPattern value="%level %thread %logger - %message%newline" />-->
+ </layout>
+ </appender>
+
+ <root>
+ <level value="DEBUG" />
+ <appender-ref ref="Console" />
+ <appender-ref ref="RollingFile" />
+ </root>
+</log4net>
diff --git a/dotnet/client-010/management/console/AbstractConsole.cs b/dotnet/client-010/management/console/AbstractConsole.cs
new file mode 100644
index 0000000000..315b2b6d48
--- /dev/null
+++ b/dotnet/client-010/management/console/AbstractConsole.cs
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+namespace org.apache.qpid.console
+{
+ public class AbstractConsole : Console
+ {
+ public AbstractConsole(){}
+ public virtual void NewAgent(Agent agent) {}
+ public virtual void AgentRemoved(Agent agent) {}
+ public virtual void BrokerConnected(Broker broker) {}
+ public virtual void BrokerDisconnected(Broker broker) {}
+ public virtual void BrokerInformation(Broker broker) {}
+ public virtual void NewPackage(String packageName) {}
+ public virtual void NewClass(short kind, ClassKey key) {}
+ public virtual void ObjectProperties(Broker broker, QMFObject obj) {}
+ public virtual void ObjectStatistics(Broker broker, QMFObject obj) {}
+ public virtual void MethodResponse(Broker broker, long seq, MethodResult response) {}
+ public virtual void EventRecieved(Broker broker, QMFEvent anEvent) {}
+ public virtual void HearbeatRecieved(Agent agent, long timestamp) {}
+ public virtual Type TypeMapping(ClassKey key) {
+ return typeof(QMFObject) ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/Agent.cs b/dotnet/client-010/management/console/Agent.cs
new file mode 100644
index 0000000000..df544a4dd0
--- /dev/null
+++ b/dotnet/client-010/management/console/Agent.cs
@@ -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.
+ *
+ */
+
+using System;
+using log4net ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Local representation of a remote agent which has been found on the bus.
+ */
+ public class Agent
+ {
+ public static ILog log = LogManager.GetLogger(typeof(Agent)) ;
+
+ public Broker Broker {get;set;}
+ public long BrokerBank {get;set;}
+ public long AgentBank {get;set;}
+ public string label {get;set;}
+
+ public Agent(Broker broker, long agentBank, string label)
+ {
+ this.Broker = broker ;
+ this.BrokerBank = broker.BrokerBank() ;
+ this.AgentBank = agentBank ;
+ this.label = label ;
+ }
+
+ public string AgentKey() {
+ return Agent.AgentKey(AgentBank, BrokerBank) ;
+ }
+
+ public string RoutingCode() {
+ return Agent.RoutingCode(AgentBank, BrokerBank) ;
+ }
+
+ public static string AgentKey(long AgentBank, long BrokerBank) {
+ return String.Format("{0}:{1}", AgentBank, BrokerBank) ;
+ }
+
+ public static string RoutingCode(long AgentBank, long BrokerBank) {
+ return String.Format("agent.{0}.{1}", BrokerBank, AgentBank) ;
+ }
+
+ public static long GetBrokerBank(string routingKey) {
+ string delim = "." ;
+ return long.Parse(routingKey.Split(delim.ToCharArray())[2]) ;
+ }
+
+ public static long GetAgentBank(string routingKey) {
+ string delim = "." ;
+ return long.Parse(routingKey.Split(delim.ToCharArray())[3]) ;
+ }
+
+ }
+}
diff --git a/dotnet/client-010/management/console/Broker.cs b/dotnet/client-010/management/console/Broker.cs
new file mode 100644
index 0000000000..7684da9e12
--- /dev/null
+++ b/dotnet/client-010/management/console/Broker.cs
@@ -0,0 +1,351 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using System.Threading ;
+using org.apache.qpid.client ;
+using org.apache.qpid.transport ;
+using org.apache.qpid.transport.codec ;
+using log4net ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Controls all communication with a broker. Works with the session to provide
+ * synhchronous method calls across the asynchronous QMF bus.
+ */
+ public class Broker : IMessageListener
+ {
+ public static ILog log = LogManager.GetLogger(typeof(Broker)) ;
+ public static int SYNC_TIME = 60000 ;
+
+ public BrokerURL url ;
+ public Dictionary<string, Agent> Agents = new Dictionary<string, Agent>() ;
+
+ private IClient client ;
+ private IClientSession clientSession ;
+ //FIXME This second session should not be needed. There is a bug in the underlieing code.
+ private IClientSession outSession ;
+ private int timeout = 50000 ;
+ private string replyName ;
+ private string topicName ;
+ private bool connected = false ;
+ private bool syncInFlight = false ;
+ private bool topicBound = false ;
+ private int reqsOutstanding = 0 ;
+ private org.apache.qpid.console.Session consoleSession ;
+ private object lockObject = new Object() ;
+
+
+ public Broker(org.apache.qpid.console.Session session, BrokerURL url)
+ {
+ log.Debug("Creating a new Broker for url " + url) ;
+ this.url = url;
+ consoleSession = session ;
+ this.TryToConnect() ;
+ }
+
+ ~Broker() {
+ if (connected) {
+ this.Shutdown() ;
+ }
+ }
+
+ public int BrokerBank() {
+ return 1 ;
+ }
+
+ public bool IsConnected() {
+ return connected ;
+ }
+
+ protected void TryToConnect() {
+ reqsOutstanding = 1 ;
+ Agent newAgent = new Agent(this,0,"BrokerAgent") ;
+ Agents.Add(newAgent.AgentKey(), newAgent) ;
+ client = new Client() ;
+ client.Connect(url.Hostname, url.Port, null, url.AuthName, url.AuthPassword) ;
+ clientSession = client.CreateSession(timeout) ;
+ //clientSession.SetAutoSync(false) ;
+ string name = System.Text.Encoding.UTF8.GetString(clientSession.GetName()) ;
+ replyName = "reply-" + name ;
+ topicName = "topic-" + name ;
+ clientSession.SetAutoSync(true) ;
+ Option[] options = new Option[] {Option.EXCLUSIVE, Option.AUTO_DELETE} ;
+
+ // This queue is used for responses to messages which are sent.
+ clientSession.QueueDeclare(replyName,options) ;
+ clientSession.ExchangeBind(replyName,"amq.direct",replyName) ;
+ clientSession.AttachMessageListener(this, "rdest") ;
+ clientSession.MessageSubscribe(replyName,"rdest",MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0,null) ;
+ clientSession.MessageSetFlowMode("rdest", MessageFlowMode.WINDOW);
+ clientSession.MessageFlow("rdest", MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ clientSession.MessageFlow("rdest", MessageCreditUnit.MESSAGE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+
+ // This queue is used for unsolicited messages sent to this class.
+ clientSession.QueueDeclare(topicName, options) ;
+ clientSession.AttachMessageListener(this, "tdest") ;
+ clientSession.MessageSubscribe(topicName,"tdest",MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0,null) ;
+ clientSession.MessageSetFlowMode("tdest", MessageFlowMode.WINDOW);
+ clientSession.MessageFlow("tdest", MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ clientSession.MessageFlow("tdest", MessageCreditUnit.MESSAGE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+
+ outSession = client.CreateSession(timeout) ;
+ outSession.ExchangeBind(replyName,"amq.direct",replyName) ;
+
+ connected = true ;
+ consoleSession.HandleBrokerConnect(this) ;
+
+
+ IEncoder encoder = CreateEncoder() ;
+ this.SetHeader(encoder, 'B', 0) ;
+ this.Send(encoder) ;
+ }
+
+ public void Shutdown() {
+ if (connected) {
+ this.WaitForStable() ;
+ clientSession.MessageStop("rdest") ;
+ clientSession.MessageStop("tdest") ;
+ clientSession.Close() ;
+ client.Close() ;
+ this.connected = false ;
+ }
+ }
+
+ public void UpdateAgent(QMFObject obj) {
+ long agentBank = (long)obj.GetProperty("agentBank") ;
+ long brokerBank = (long)obj.GetProperty("brokerBank") ;
+ String key = Agent.AgentKey(agentBank, brokerBank) ;
+ if (obj.IsDeleted()) {
+ if (Agents.ContainsKey(key)) {
+ Agent agent = Agents[key] ;
+ Agents.Remove(key) ;
+ consoleSession.HandleAgentRemoved(agent) ;
+ }
+ }
+ else {
+ if (! Agents.ContainsKey(key)) {
+ Agent newAgent = new Agent(this, agentBank, (string)obj.GetProperty("label")) ;
+ Agents.Add(key, newAgent) ;
+ consoleSession.HandleNewAgent(newAgent) ;
+ }
+ }
+ }
+
+ public IEncoder CreateEncoder() {
+ return new MSEncoder(1000) ;
+ }
+
+
+ public IEncoder CreateEncoder(char opcode, long sequence) {
+ return SetHeader(this.CreateEncoder(), opcode, sequence) ;
+ }
+
+ public IEncoder SetHeader(IEncoder enc, char opcode, long sequence) {
+ enc.WriteUint8((short)'A') ;
+ enc.WriteUint8((short)'M') ;
+ enc.WriteUint8((short)'2') ;
+ enc.WriteUint8((short)opcode) ;
+ enc.WriteUint32(sequence) ;
+ return enc ;
+ }
+
+ public Message CreateMessage(IEncoder enc) {
+ return this.CreateMessage(enc, "broker", -1) ;
+ }
+
+ public Message CreateMessage(IEncoder enc, string routingKey) {
+ return this.CreateMessage(enc, routingKey, -1) ;
+ }
+
+ public Message CreateMessage(IEncoder enc, string routingKey, long ttl) {
+ Message msg = new Message() ;
+ msg.Body = ((MSEncoder)enc).Segment() ;
+ msg.DeliveryProperties.SetRoutingKey(routingKey) ;
+ if (-1 != ttl) {
+ msg.DeliveryProperties.SetTtl(ttl) ;
+ }
+ msg.MessageProperties.SetContentType("x-application/qmf") ;
+ msg.MessageProperties.SetReplyTo(new ReplyTo("amq.direct", replyName)) ;
+ return msg ;
+ }
+
+ public void Send(IEncoder enc) {
+ this.Send(this.CreateMessage(enc)) ;
+ }
+
+ public void Send(Message msg) {
+
+ lock (lockObject) {
+ log.Debug(String.Format("Sending message to routing key '{0}'", msg.DeliveryProperties.GetRoutingKey())) ;
+ //log.Debug(System.Text.Encoding.UTF8.GetString(msg.Body.ToArray())) ;
+ outSession.MessageTransfer("qpid.management", msg) ;
+ //clientSession.sync() ;
+ }
+ }
+
+ protected bool CheckHeader(IDecoder decoder, out char opcode, out long sequence) {
+ bool returnValue = false ;
+ opcode = 'x' ;
+ sequence = -1 ;
+ if(decoder.HasRemaining()) {
+ char character = (char) decoder.ReadUint8() ;
+ if (character != 'A') {
+ return returnValue ;
+ }
+ character = (char) decoder.ReadUint8() ;
+ if (character != 'M') {
+ return returnValue ;
+ }
+ character = (char) decoder.ReadUint8() ;
+ if (character != '2') {
+ return returnValue ;
+ }
+ returnValue = true ;
+ opcode = (char) decoder.ReadUint8() ;
+ sequence = decoder.ReadUint32() ;
+ }
+ return returnValue ;
+ }
+
+ public void MessageTransfer(IMessage msg) {
+ MSDecoder decoder = new MSDecoder() ;
+ decoder.Init(msg.Body) ;
+ RangeSet rangeSet = new RangeSet() ;
+ rangeSet.Add(msg.Id) ;
+ char opcode = 'x' ;
+ long seq = -1 ;
+ while (this.CheckHeader(decoder, out opcode, out seq)) {
+ //log.Debug("Message recieved with opcode " + opcode + " and sequence " + seq) ;
+ //log.Debug(System.Text.Encoding.UTF8.GetString(msg.Body.ToArray())) ;
+ switch (opcode) {
+ case 'b':
+ consoleSession.HandleBrokerResponse(this, decoder, seq) ;
+ break ;
+ case 'p':
+ consoleSession.HandlePackageIndicator(this, decoder, seq) ;
+ break ;
+ case 'z':
+ consoleSession.HandleCommandComplete(this, decoder, seq) ;
+ break ;
+ case 'q':
+ consoleSession.HandleClassIndicator(this, decoder, seq) ;
+ break ;
+ case 'm':
+ consoleSession.HandleMethodResponse(this, decoder, seq) ;
+ break ;
+ case 'h':
+ consoleSession.HandleHeartbeatIndicator(this, decoder, seq, msg) ;
+ break ;
+ case 'e':
+ consoleSession.HandleEventIndicator(this, decoder, seq) ;
+ break ;
+ case 's':
+ consoleSession.HandleSchemaResponse(this, decoder, seq) ;
+ break ;
+ case 'c':
+ consoleSession.HandleContentIndicator(this, decoder, seq, true, false) ;
+ break ;
+ case 'i':
+ consoleSession.HandleContentIndicator(this, decoder, seq, false, true) ;
+ break ;
+ case 'g':
+ consoleSession.HandleContentIndicator(this, decoder, seq, true, true) ;
+ break ;
+ default:
+ log.Error("Invalid message type recieved with opcode " + opcode) ;
+ break ;
+ }
+ }
+ lock (lockObject) {
+ outSession.MessageAccept(rangeSet) ;
+ }
+ }
+
+ public void IncrementOutstanding() {
+ lock (lockObject) {
+ this.reqsOutstanding += 1 ;
+ }
+ }
+
+ public void DecrementOutstanding() {
+ lock (lockObject) {
+ this.reqsOutstanding -= 1 ;
+ if ((reqsOutstanding == 0) & !topicBound) {
+ foreach (string key in consoleSession.BindingKeys()) {
+ //this.clientSession.ExchangeBind(topicName, "qpid.mannagement", key) ;
+ log.Debug("Setting Topic Binding " + key) ;
+ this.outSession.ExchangeBind(topicName, "qpid.management", key) ;
+ }
+ topicBound = true ;
+ }
+ if ((reqsOutstanding == 0) & syncInFlight) {
+ syncInFlight = false ;
+ Monitor.PulseAll(lockObject) ;
+ }
+ }
+ }
+
+ public void WaitForStable() {
+ lock (lockObject) {
+ if (connected) {
+ DateTime start = DateTime.Now ;
+ syncInFlight = true ;
+ while (reqsOutstanding != 0) {
+ log.Debug("Waiting to recieve messages") ;
+ Monitor.Wait(lockObject,SYNC_TIME) ;
+ TimeSpan duration = DateTime.Now - start;
+ if (duration.TotalMilliseconds > SYNC_TIME) {
+ throw new Exception("Timeout waiting for Broker to Sync") ;
+ }
+ }
+ }
+ }
+ }
+
+ public void SetSyncInFlight(bool inFlight) {
+ lock(lockObject) {
+ syncInFlight = inFlight ;
+ Monitor.PulseAll(lockObject) ;
+ }
+ }
+
+ public bool GetSyncInFlight() {
+ return syncInFlight ;
+ }
+
+ public void WaitForSync(int timeout) {
+ lock(lockObject) {
+ DateTime start = DateTime.Now ;
+ while (syncInFlight) {
+ Monitor.Wait(lockObject,timeout) ;
+ }
+ TimeSpan duration = DateTime.Now - start;
+ if (duration.TotalMilliseconds > timeout) {
+ throw new Exception("Timeout waiting for Broker to Sync") ;
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/BrokerURL.cs b/dotnet/client-010/management/console/BrokerURL.cs
new file mode 100644
index 0000000000..77318e4295
--- /dev/null
+++ b/dotnet/client-010/management/console/BrokerURL.cs
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * URL which defines the connection to the broker to hook up to the QMF
+ * Bus.
+ */
+ public class BrokerURL
+ {
+ public string Hostname {get;set;}
+ public int Port {get;set;}
+ public string AuthName {get;set;}
+ public string AuthPassword {get;set;}
+ public string AuthMechanism {get;set;}
+ protected bool ssl = false ;
+
+ public BrokerURL(string str)
+ {
+ Uri uri = new Uri(str) ;
+ this.Hostname = uri.Host ;
+ if (uri.Scheme.Equals("amqp")) {
+ Port=5672 ;
+ } else {
+ ssl = true ;
+ Port=5673 ;
+ }
+
+ //FIXME Make this more robust
+ this.AuthName = "guest" ;
+ this.AuthPassword = "guest" ;
+ this.AuthMechanism = "PLAIN" ;
+ }
+
+ public string GetURI() {
+ return Hostname ;
+ }
+
+ public override string ToString ()
+ {
+ if (ssl) {
+ return String.Format("amqps://{0}:{1}", Hostname, Port) ;
+ } else {
+ return String.Format("amqp://{0}:{1}", Hostname, Port) ;
+ }
+ }
+
+ }
+}
diff --git a/dotnet/client-010/management/console/ClassKey.cs b/dotnet/client-010/management/console/ClassKey.cs
new file mode 100644
index 0000000000..a3aba2761a
--- /dev/null
+++ b/dotnet/client-010/management/console/ClassKey.cs
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Globalization ;
+using org.apache.qpid.transport.util;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Identifies a specific class and version on the bus.
+ */
+ public class ClassKey
+ {
+ public string PackageName { get; set; }
+ public string ClassName { get; set; }
+ public long[] Hash = new long[4] ;
+
+ public ClassKey(String keyString) {
+ string delims = ":()" ;
+ string[] parts = keyString.Split(delims.ToCharArray()) ;
+ if (parts.Length < 3) {
+ throw new Exception("Invalid class key format. Format should be package:class(bytes)") ;
+ }
+ PackageName = parts[0] ;
+ ClassName = parts[1] ;
+ delims = "-" ;
+ string[] bytes = parts[2].Split(delims.ToCharArray()) ;
+ if (bytes.Length != 4) {
+ throw new Exception("Invalid class key format. Bytes should be in the format HEX-HEX-HEX-HEX") ;
+ }
+ Hash[0] = long.Parse(bytes[0], NumberStyles.HexNumber) ;
+ Hash[1] = long.Parse(bytes[1], NumberStyles.HexNumber) ;
+ Hash[2] = long.Parse(bytes[2], NumberStyles.HexNumber) ;
+ Hash[3] = long.Parse(bytes[3], NumberStyles.HexNumber) ;
+ }
+
+ public ClassKey(IDecoder dec) {
+ PackageName = dec.ReadStr8() ;
+ ClassName = dec.ReadStr8() ;
+ Hash[0] = dec.ReadUint32() ;
+ Hash[1] = dec.ReadUint32() ;
+ Hash[2] = dec.ReadUint32() ;
+ Hash[3] = dec.ReadUint32() ;
+
+ }
+
+ public string GetKeyString() {
+ string hashString = GetHashString() ;
+ return String.Format("{0}:{1}({2})", PackageName, ClassName, hashString) ;
+ }
+
+ public string GetHashString() {
+ return String.Format("{0:x8}-{1:x8}-{2:x8}-{3:x8}", (long) Hash[0],Hash[1], Hash[2],Hash[3]) ;
+ }
+
+ public void encode(IEncoder enc) {
+ enc.WriteStr8(PackageName) ;
+ enc.WriteStr8(ClassName) ;
+ enc.WriteUint32(Hash[0]) ;
+ enc.WriteUint32(Hash[1]) ;
+ enc.WriteUint32(Hash[2]) ;
+ enc.WriteUint32(Hash[3]) ;
+ }
+
+ override public string ToString() {
+ return String.Format("ClassKey: {0}", GetKeyString()) ;
+ }
+
+ public override int GetHashCode ()
+ {
+ return GetKeyString().GetHashCode() ;
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj.GetType().Equals(this.GetType())) {
+ ClassKey other = (ClassKey) obj ;
+ return (other.GetKeyString().Equals(this.GetKeyString())) ;
+ }
+ else {
+ return false ;
+ }
+ }
+
+ }
+}
diff --git a/dotnet/client-010/management/console/Console.cs b/dotnet/client-010/management/console/Console.cs
new file mode 100644
index 0000000000..8ff201c676
--- /dev/null
+++ b/dotnet/client-010/management/console/Console.cs
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+
+namespace org.apache.qpid.console
+{
+ /**
+ * Callbacks which are exposed by the Session. Clients should create anm implementaiton of this
+ * for more fine grained interaction with the bus.
+ */
+ public interface Console
+ {
+ void NewAgent(Agent agent) ;
+ void AgentRemoved(Agent agent) ;
+ void BrokerConnected(Broker broker) ;
+ void BrokerDisconnected(Broker broker) ;
+ void BrokerInformation(Broker broker) ;
+ void NewPackage(String packageName) ;
+ void NewClass(short kind, ClassKey key) ;
+ void ObjectProperties(Broker broker, QMFObject obj) ;
+ void ObjectStatistics(Broker broker, QMFObject obj) ;
+ void MethodResponse(Broker broker, long seq, MethodResult response) ;
+ void EventRecieved(Broker broker, QMFEvent anEvent) ;
+ void HearbeatRecieved(Agent agent, long timestamp) ;
+ Type TypeMapping(ClassKey key) ;
+ }
+}
diff --git a/dotnet/client-010/management/console/MethodResult.cs b/dotnet/client-010/management/console/MethodResult.cs
new file mode 100644
index 0000000000..7215f5dcbc
--- /dev/null
+++ b/dotnet/client-010/management/console/MethodResult.cs
@@ -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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+
+namespace org.apache.qpid.console
+{
+ /**
+ * The result on invoking a method on a managed object
+ */
+ public class MethodResult
+ {
+
+ public long ReturnCode {get;set;}
+ public string Text {get;set;}
+ protected Dictionary<string, object> ReturnValues ;
+
+ public MethodResult(long aCode, string aMsg, Dictionary<string, object> args)
+ {
+ ReturnCode = aCode ;
+ Text = aMsg ;
+ ReturnValues = args ;
+ }
+
+ public object GetReturnValue(string name) {
+ object returnValue = null ;
+ if (ReturnValues.ContainsKey(name)) {
+ returnValue = ReturnValues[name] ;
+ }
+ return returnValue ;
+ }
+
+ public Dictionary<string, object> GetReturnValues() {
+ return ReturnValues ;
+ }
+
+ public override string ToString()
+ {
+ string returnString = "" ;
+ foreach (KeyValuePair<string, object> pair in ReturnValues) {
+ returnString = returnString + String.Format("(Key: '{0}' Value: '{1}')", pair.Key, pair.Value) ;
+ }
+
+ return string.Format("MethodResult: ReturnCode={0}, Text={1} Values=[{2}]", ReturnCode, Text, returnString);
+ }
+
+ }
+}
diff --git a/dotnet/client-010/management/console/ObjectID.cs b/dotnet/client-010/management/console/ObjectID.cs
new file mode 100644
index 0000000000..9532c8e64c
--- /dev/null
+++ b/dotnet/client-010/management/console/ObjectID.cs
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Uniquely identifies an object on the bus.
+ */
+ public class ObjectID
+ {
+
+ protected long first ;
+ protected long second ;
+
+ public ObjectID() {
+ }
+
+ public ObjectID(IDecoder dec)
+ {
+ first = (long)dec.ReadUint64() ;
+ second = (long)dec.ReadUint64() ;
+ }
+
+ public ObjectID(long first, long second) {
+ this.first = first ;
+ this.second = second ;
+ }
+
+ public long Flags() {
+ return (long) ((ulong)this.first & 0xF000000000000000) >> 60 ;
+ }
+
+ public long Sequence() {
+ return (long)((ulong)this.first & 0x0FFF000000000000) >> 48 ;
+ }
+
+ public long BrokerBank() {
+ return (long)((ulong)this.first & 0x0000FFFFF0000000) >> 28 ;
+ }
+
+ public long AgentBank() {
+ return (this.first & 0x000000000FFFFFFF) ;
+ }
+
+ public long Object() {
+ return second ;
+ }
+
+ public bool IsDurable() {
+ return Sequence() == 0 ;
+ }
+
+ public void encode(IEncoder enc) {
+ enc.WriteUint64((long)first) ;
+ enc.WriteUint64((long)second) ;
+ }
+
+ override public string ToString() {
+ return "" + Flags() + "-" + Sequence() + "-" + BrokerBank() + "-" + AgentBank() + "-" + Object() ;
+ }
+
+ public string RoutingCode() {
+ return Agent.RoutingCode((long)AgentBank(), (long)BrokerBank()) ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/QMFEvent.cs b/dotnet/client-010/management/console/QMFEvent.cs
new file mode 100644
index 0000000000..73e1a34c43
--- /dev/null
+++ b/dotnet/client-010/management/console/QMFEvent.cs
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.transport.codec ;
+
+
+namespace org.apache.qpid.console
+{
+ public enum EventSeverity : short {
+ EMER = 0 ,
+ ALERT = 1 ,
+ CRIT = 2 ,
+ ERROR = 3 ,
+ WARN = 4 ,
+ NOTIC = 5 ,
+ INFO = 6 ,
+ DEBUG = 7
+ }
+
+ /**
+ * An event raised by an agent on the bus.
+ */
+ public class QMFEvent
+ {
+ public Session Session { get;set; }
+ public ClassKey ClassKey {get;set;}
+ //FIXME time?
+ public long Timestamp {get;set;}
+ public EventSeverity Severity {get;set;}
+ public Dictionary<string, object> Arguments {get;set;}
+
+ public QMFEvent(Session session, IDecoder dec)
+ {
+ Session = session ;
+ ClassKey = new ClassKey(dec) ;
+ Timestamp = dec.ReadInt64() ;
+ Severity = (EventSeverity) dec.ReadUint8() ;
+ SchemaClass sClass = Session.GetSchema(ClassKey) ;
+ Arguments = new Dictionary<string, object>() ;
+
+ if (sClass != null) {
+ foreach (SchemaArgument arg in sClass.Arguments) {
+ Arguments[arg.Name] = Session.DecodeValue(dec, arg.Type) ;
+ }
+ }
+ }
+
+ public object GetArgument(string argName) {
+ object returnValue = null ;
+ Arguments.TryGetValue(argName, out returnValue) ;
+ return returnValue ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/QMFObject.cs b/dotnet/client-010/management/console/QMFObject.cs
new file mode 100644
index 0000000000..905422efd9
--- /dev/null
+++ b/dotnet/client-010/management/console/QMFObject.cs
@@ -0,0 +1,294 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using log4net ;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * An object which is returned from an agent by the Session. It can have
+ * methods, properties, and statistics.
+ */
+ public class QMFObject
+ {
+
+ public static ILog log = LogManager.GetLogger(typeof(QMFObject)) ;
+
+ public Session Session {get;set;}
+ protected SchemaClass _Schema ;
+ virtual public SchemaClass Schema {get {return _Schema;} set {_Schema=value;}}
+ bool Managed ;
+ public DateTime CurrentTime {get;set;}
+ public DateTime CreateTime {get;set;}
+ public DateTime DeleteTime {get;set;}
+ public ObjectID ObjectID {get;set;}
+ public Dictionary<string, object> Properties = new Dictionary<string, object>() ;
+ public Dictionary<string, object> Statistics = new Dictionary<string, object>() ;
+
+
+ // This constructor is the "naked" constructor which creates
+ // an object without a session or a schema. It is used by
+ // subclasses which are auto generated
+ public QMFObject() {
+ }
+
+ public QMFObject(QMFObject source) {
+ this.Session = source.Session ;
+ this.Schema = source.Schema ;
+ this.Managed = source.Managed ;
+ this.CurrentTime = source.CurrentTime ;
+ this.CreateTime = source.CreateTime ;
+ this.DeleteTime = source.DeleteTime ;
+ this.ObjectID = source.ObjectID ;
+ this.Properties = source.Properties ;
+ this.Statistics = source.Statistics ;
+ }
+
+ // This constructor is used by a session make object call to
+ // create a blank object from a schema.
+ public QMFObject(Session session, SchemaClass schema, bool hasProperties, bool hasStats , bool isManaged) {
+ Session = session ;
+ Schema = schema ;
+ Managed = isManaged ;
+
+ if (hasProperties) {
+ foreach (SchemaProperty prop in Schema.GetAllProperties()) {
+ object propValue = null ;
+ if (!prop.Optional) {
+ propValue = Util.DefaultValue(prop.Type) ;
+ }
+ this.SetProperty(prop.Name, propValue) ;
+ }
+ }
+
+ if (hasStats) {
+ foreach (SchemaStatistic stat in Schema.Statistics) {
+ SetStatistic(stat.Name, Util.DefaultValue(stat.Type)) ;
+ }
+ }
+ }
+
+ // This constructor is used by the session to create an object based on a data
+ // stream by the agent.
+ public QMFObject(Session session, SchemaClass schema, IDecoder dec, bool hasProperties, bool hasStats , bool isManaged)
+ {
+ Session = session ;
+ Schema = schema ;
+ Managed = isManaged ;
+
+ if (Managed) {
+ // FIXME DateTime or Uint64??
+ CurrentTime = new DateTime(dec.ReadDatetime()) ;
+ CreateTime = new DateTime(dec.ReadDatetime()) ;
+ DeleteTime = new DateTime(dec.ReadDatetime()) ;
+ ObjectID = new ObjectID(dec) ;
+ }
+
+ if (hasProperties) {
+ List<string> excluded = ProcessPresenceMasks(dec, Schema) ;
+
+ foreach (SchemaProperty prop in Schema.GetAllProperties()) {
+ if (excluded.Contains(prop.Name)) {
+ log.Debug(String.Format("Setting Property Default {0}", prop.Name)) ;
+ safeAddProperty(prop.Name, null) ;
+ } else {
+ //log.Debug(String.Format("Setting Property {0}", prop.Name)) ;
+ safeAddProperty(prop.Name, session.DecodeValue(dec, prop.Type)) ;
+ }
+ }
+ }
+
+ if (hasStats) {
+ foreach (SchemaStatistic stat in Schema.GetAllStatistics()) {
+ //log.Debug(String.Format("Setting Statistic {0}", stat.Name)) ;
+ Statistics.Add(stat.Name, session.DecodeValue(dec, stat.Type)) ;
+ }
+ }
+
+ }
+
+ protected List<string> ProcessPresenceMasks(IDecoder dec, SchemaClass schema) {
+ List<string> excludes = new List<string> () ;
+ short bit = 0 ;
+ short mask = 0 ;
+ foreach (SchemaProperty prop in Schema.GetAllProperties()) {
+ if (prop.Optional) {
+ //log.Debug(String.Format("Property named {0} is optional", prop.Name)) ;
+ if (bit == 0) {
+ mask=dec.ReadUint8() ;
+ bit = 1 ;
+ }
+
+ if ((mask & bit) == 0) {
+ //log.Debug(String.Format("Property named {0} is not present", prop.Name)) ;
+ excludes.Add(prop.Name) ;
+ }
+ bit *= 2 ;
+ if (bit == 256) {
+ bit = 0 ;
+ }
+ }
+ }
+ return excludes ;
+ }
+
+ protected List<SchemaMethod> getMethods() {
+ return Schema.GetAllMethods() ;
+ }
+
+ public object GetProperty(string attributeName) {
+ //FIXME any object refs?
+ object returnValue = null ;
+ Properties.TryGetValue(attributeName, out returnValue) ;
+ return returnValue ;
+ }
+
+ protected void SetStatistic(string attributeName, object newValue) {
+ Statistics.Remove(attributeName) ;
+ Statistics.Add(attributeName, newValue) ;
+ }
+
+ public void SetProperty(string attributeName, object newValue) {
+ Properties.Remove(attributeName) ;
+ Properties.Add(attributeName, newValue) ;
+ }
+
+ public bool IsDeleted() {
+ return !DeleteTime.Equals(new DateTime(0)) ;
+ }
+
+ public string RoutingKey() {
+ return ObjectID.RoutingCode() ;
+ }
+
+ public long AgentBank() {
+ return ObjectID.AgentBank() ;
+ }
+
+ public long BrokerBank() {
+ return ObjectID.BrokerBank() ;
+ }
+
+ override public string ToString() {
+ string propertyString = "" ;
+ foreach (KeyValuePair<string, object> pair in Properties) {
+ propertyString = propertyString + String.Format("(Name: '{0}' Value: '{1}')", pair.Key, pair.Value) ;
+ }
+
+ string statsString = "" ;
+ foreach (KeyValuePair<string, object> sPair in Statistics) {
+ statsString = statsString + String.Format("(Name: '{0}' Value: '{1}')", sPair.Key, sPair.Value) ;
+ }
+ if (Managed) {
+ return String.Format("Managed QMFObject {0}:{1}({2}) Properties: [{3}] Statistics: [{4}])", Schema.PackageName, Schema.ClassName, ObjectID, propertyString, statsString) ;
+ } else {
+ return String.Format("QMFObject {0}:{1} Properties: [{2}] Statistics: [{3}]", Schema.PackageName, Schema.ClassName, propertyString, statsString) ;
+ }
+ }
+
+ public MethodResult InvokeMethod(string name, params object[] args) {
+ return this.InternalInvokeMethod(name, new List<object>(args), true, Broker.SYNC_TIME ) ;
+ }
+
+ public MethodResult InvokeMethod(string name, int timeToLive, params object[] args) {
+ return this.InternalInvokeMethod(name, new List<object>(args), true, timeToLive) ;
+ }
+
+ public MethodResult InvokeMethod(string name, bool synchronous, int timeToLive, params object[] args) {
+ return this.InternalInvokeMethod(name, new List<object>(args), synchronous, timeToLive ) ;
+ }
+
+ public MethodResult InvokeMethod(string name, bool synchronous, params object[] args) {
+ return this.InternalInvokeMethod(name, new List<object>(args), synchronous, Broker.SYNC_TIME) ;
+ }
+
+ protected MethodResult InternalInvokeMethod(string name, List<object> args, bool synchronous, int timeToLive) {
+ if (!Managed) {
+ throw new Exception ("Object is not Managed") ;
+ }
+ if (Schema.GetMethod(name) == null) {
+ throw new Exception (String.Format("Method named '{0}' does not exist", name)) ;
+ }
+ return Session.InvokeMethod(this, name, args, synchronous, timeToLive) ;
+ }
+
+ public void Encode (IEncoder enc) {
+ int mask = 0 ;
+ int bit = 0 ;
+ List<SchemaProperty> propsToEncode = new List<SchemaProperty>() ;
+ log.Debug(String.Format("Encoding class {0}:{1}", Schema.PackageName, Schema.ClassName)) ;
+
+ enc.WriteUint8(20) ;
+ Schema.Key.encode(enc) ;
+
+ foreach (SchemaProperty prop in Schema.GetAllProperties()) {
+ if (prop.Optional) {
+ if (bit == 0) {
+ bit =1 ;
+ }
+ if ((Properties.ContainsKey(prop.Name)) && (Properties[prop.Name] != null)) {
+ mask |= bit ;
+ propsToEncode.Add(prop) ;
+ } else {
+ }
+ bit = bit << 1 ;
+ if (bit == 256) {
+ bit = 0 ;
+ enc.WriteUint8((short)mask) ;
+ mask = 0 ;
+ }
+ } else {
+ propsToEncode.Add(prop) ;
+ }
+ }
+ if (bit != 0) {
+ enc.WriteUint8((short)mask) ;
+ }
+
+ foreach (SchemaProperty prop in propsToEncode) {
+ object obj = Properties[prop.Name] ;
+ //log.Debug(String.Format("Encoding property {0}", prop.Name)) ;
+ Session.EncodeValue(enc, prop.Type, obj) ;
+ }
+ foreach (SchemaStatistic stat in Schema.Statistics) {
+ object obj = Statistics[stat.Name] ;
+ Session.EncodeValue(enc, stat.Type, obj) ;
+ }
+ log.Debug("Done") ;
+
+ }
+
+
+ protected void safeAddProperty(string propName, object value) {
+ if (Properties.ContainsKey(propName)) {
+ Properties[propName] = value ;
+ } else {
+ Properties.Add(propName, value) ;
+ }
+ }
+
+
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaArgument.cs b/dotnet/client-010/management/console/SchemaArgument.cs
new file mode 100644
index 0000000000..d3ee508b31
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaArgument.cs
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata that describes the mapping of a method parameter to a QMF Object
+ */
+ public class SchemaArgument : SchemaVariable
+ {
+
+ public string Direction {get;set;}
+
+ public SchemaArgument(IDecoder dec, bool methodArg)
+ {
+ Dictionary<string, Object> map = dec.ReadMap() ;
+ base.PopulateData(map) ;
+
+ if (map.ContainsKey("dir")) {
+ Direction = (string) map["dir"] ;
+ }
+ }
+
+ public bool IsInput() {
+ return Direction.Equals("I") | Direction.Equals("IO") ;
+ }
+
+ public bool IsOutput() {
+ return Direction.Equals("O") | Direction.Equals("IO") ;
+ }
+
+ public bool IsBidirectional() {
+ return Direction.Equals("IO") ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaClass.cs b/dotnet/client-010/management/console/SchemaClass.cs
new file mode 100644
index 0000000000..320312b61d
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaClass.cs
@@ -0,0 +1,141 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.codec ;
+
+using log4net ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata that describes the mapping of a class to a QMF Object
+ */
+ public class SchemaClass
+ {
+ public static int CLASS_KIND_TABLE = 1 ;
+ public static int CLASS_KIND_EVENT = 2 ;
+
+ public static ILog log = LogManager.GetLogger(typeof(SchemaClass)) ;
+
+
+ public ClassKey Key {get;set;}
+ public ClassKey SuperType {get;set;}
+ public int Kind {get;set;}
+ public List<SchemaMethod> Methods = new List<SchemaMethod>() ;
+ public List<SchemaArgument> Arguments = new List<SchemaArgument>() ;
+ public List<SchemaProperty> Properties = new List<SchemaProperty>() ;
+ public List<SchemaStatistic> Statistics = new List<SchemaStatistic>() ;
+
+ public string ClassName { get { return Key.ClassName;}}
+ public string PackageName { get { return Key.PackageName;}}
+ public string ClassKeyString { get { return Key.GetKeyString();}}
+
+ protected Session Session {get;set;}
+
+ public SchemaClass(int kind, ClassKey key, IDecoder dec, Session session)
+ {
+ log.Debug(String.Format("New schema class {0}", key)) ;
+ Kind = kind ;
+ Session = session ;
+ this.Key = key ;
+ bool hasSupertype = false ;
+
+ if (kind == CLASS_KIND_TABLE) {
+ int propCount = dec.ReadUint16() ;
+ int statCount = dec.ReadUint16() ;
+ int methodCount = dec.ReadUint16() ;
+
+ if (hasSupertype) {
+ SuperType = new ClassKey(dec) ;
+ }
+
+ for(int x = 0 ; x < propCount ; x++) {
+ Properties.Add(new SchemaProperty(dec)) ;
+ }
+ for(int x = 0 ; x < statCount ; x++) {
+ Statistics.Add(new SchemaStatistic(dec)) ;
+ }
+ for(int x = 0 ; x < methodCount ; x++) {
+ Methods.Add(new SchemaMethod(dec)) ;
+ }
+ }
+
+ if (kind == CLASS_KIND_EVENT) {
+ int argCount = dec.ReadUint16() ;
+ if (hasSupertype) {
+ SuperType = new ClassKey(dec) ;
+ }
+ for(int x = 0 ; x < argCount ; x++) {
+ Arguments.Add(new SchemaArgument(dec, false)) ;
+ }
+ }
+ }
+
+ public SchemaMethod GetMethod(string name) {
+ SchemaMethod returnValue = null ;
+ foreach(SchemaMethod method in Methods) {
+ if (method.Name.Equals(name)) {
+ returnValue = method ;
+ break ;
+ }
+ }
+ return returnValue ;
+ }
+
+ public List<SchemaProperty> GetAllProperties() {
+ if (SuperType == null) {
+ return Properties ;
+ } else {
+ List<SchemaProperty> allProperties = new List<SchemaProperty>(Properties) ;
+ allProperties.AddRange(Session.GetSchema(SuperType).GetAllProperties()) ;
+ return allProperties ;
+ }
+ }
+
+ public List<SchemaStatistic> GetAllStatistics() {
+ if (SuperType == null) {
+ return Statistics ;
+ } else {
+ List<SchemaStatistic> allStats = new List<SchemaStatistic>(Statistics) ;
+ allStats.AddRange(Session.GetSchema(SuperType).GetAllStatistics()) ;
+ return allStats ;
+ }
+ }
+
+ public List<SchemaMethod> GetAllMethods() {
+ if (SuperType == null) {
+ return Methods ;
+ } else {
+ List<SchemaMethod> allMethods = new List<SchemaMethod>(Methods) ;
+ allMethods.AddRange(Session.GetSchema(SuperType).GetAllMethods()) ;
+ return allMethods ;
+ }
+ }
+
+ public bool HasSuperType() {
+ return SuperType != null ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaMethod.cs b/dotnet/client-010/management/console/SchemaMethod.cs
new file mode 100644
index 0000000000..0a843262a4
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaMethod.cs
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata that describes the mapping of a method to a QMF Object
+ */
+ public class SchemaMethod
+ {
+ public string Name {get;set;}
+ public int ArgCount {get;set;}
+ public int InputArgCount {get;set;}
+ public int OutputArgCount {get;set;}
+ public int BidirectionalArgCount {get;set;}
+ public string Description {get;set;}
+ public List<SchemaArgument> Arguments = new List<SchemaArgument>();
+
+ public SchemaMethod(IDecoder dec)
+ {
+ Dictionary<string, Object> map = dec.ReadMap() ;
+ Name = (string) map["name"] ;
+ ArgCount = (int) map["argCount"] ;
+ if (map.ContainsKey("desc")) {
+ Description = (string) map["desc"] ;
+ }
+ for (int x = 0 ; x < ArgCount ; x++) {
+ SchemaArgument arg = new SchemaArgument(dec, true) ;
+ Arguments.Add(arg) ;
+ if (arg.IsInput()) {
+ InputArgCount += 1 ;
+ }
+ if (arg.IsOutput()) {
+ OutputArgCount += 1 ;
+ }
+ if (arg.IsBidirectional()) {
+ BidirectionalArgCount += 1 ;
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaProperty.cs b/dotnet/client-010/management/console/SchemaProperty.cs
new file mode 100644
index 0000000000..50d3c62f8d
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaProperty.cs
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata that describes the mapping of an object property to a QMF Object
+ */
+ public class SchemaProperty : SchemaVariable
+ {
+ public int Access {get;set;}
+ public bool Index {get;set;}
+ public bool Optional {get;set;}
+
+ public SchemaProperty(IDecoder dec)
+ {
+ Dictionary<string, Object> map = dec.ReadMap() ;
+ base.PopulateData(map) ;
+ Name = (string) map["name"] ;
+
+ if (map.ContainsKey("optional")) {
+ //System.Console.WriteLine("optional") ;
+ Optional = (int)map["optional"] != 0 ;
+ }
+ if (map.ContainsKey("index")) {
+ //System.Console.WriteLine("index") ;
+ Index = (int)map["index"] != 0 ;
+ }
+ if (map.ContainsKey("access")) {
+ //System.Console.WriteLine("access") ;
+ Access = (int) map["access"] ;
+ }
+
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaStatistic.cs b/dotnet/client-010/management/console/SchemaStatistic.cs
new file mode 100644
index 0000000000..ff96b98388
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaStatistic.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata that describes the mapping of an object Statistic
+ */
+ public class SchemaStatistic
+ {
+
+ public string Name {get;set;}
+ public short Type {get;set;}
+ public string Description {get;set;}
+ public string Unit {get;set;}
+
+ public SchemaStatistic(IDecoder dec)
+ {
+ Dictionary<string, Object> map = dec.ReadMap() ;
+ Name = (string) map["name"] ;
+ Type = (short) short.Parse(""+map["type"]) ;
+
+ if (map.ContainsKey("unit")) {
+ Unit = (string) map["unit"] ;
+ }
+ if (map.ContainsKey("description")) {
+ Description = (string) map["description"] ;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SchemaVariable.cs b/dotnet/client-010/management/console/SchemaVariable.cs
new file mode 100644
index 0000000000..50455ab38a
--- /dev/null
+++ b/dotnet/client-010/management/console/SchemaVariable.cs
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic ;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Metadata for mapping properties, arguments, and statistics
+ */
+ public abstract class SchemaVariable
+ {
+ public string Name {get;set;}
+ public short Type {get;set;}
+ public string Description {get;set;}
+ public string Unit {get;set;}
+ public int? Min {get;set;}
+ public int? Max {get;set;}
+ public int? MaxLength {get;set;}
+ public string Default {get;set;}
+ public string RefPackage {get;set;}
+ public string RefClass {get;set;}
+
+ public SchemaVariable() {
+ }
+
+ protected void PopulateData(Dictionary<string, Object> map)
+ {
+
+ if (map.ContainsKey("name")) {
+ Name = (string) map["name"] ;
+ }
+ if (map.ContainsKey("type")) {
+ Type = short.Parse((""+ map["type"])) ;
+ }
+
+ if (map.ContainsKey("unit")) {
+ Unit = (string) map["unit"] ;
+ }
+ if (map.ContainsKey("min")) {
+ Min = (int) map["min"] ;
+ }
+ if (map.ContainsKey("max")) {
+ Max = (int) map["max"] ;
+ }
+ if (map.ContainsKey("maxlen")) {
+ MaxLength = (int) map["maxlen"] ;
+ }
+ if (map.ContainsKey("description")) {
+ Description = (string) map["description"] ;
+ }
+ if (map.ContainsKey("refClass")) {
+ RefClass = (string) map["refClass"] ;
+ }
+ if (map.ContainsKey("refPackage")) {
+ RefPackage = (string) map["refPackage"] ;
+ }
+ if (map.ContainsKey("Default")) {
+ Default = (string) map["default"] ;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/SequenceManager.cs b/dotnet/client-010/management/console/SequenceManager.cs
new file mode 100644
index 0000000000..29f1ba26b0
--- /dev/null
+++ b/dotnet/client-010/management/console/SequenceManager.cs
@@ -0,0 +1,62 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Threading ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Holds state during asynchronous calls to the broker.
+ */
+ public class SequenceManager
+ {
+ long sequence = 0 ;
+ Dictionary<long, Object> pending = new Dictionary<long, Object>() ;
+ Object lockObject = new Object() ;
+
+ public SequenceManager()
+ {
+ }
+
+ public long Reserve(Object data) {
+ long returnValue = 0 ;
+ lock(lockObject) {
+ returnValue = sequence ;
+ sequence += 1 ;
+ pending.Add(returnValue, data) ;
+ }
+ return returnValue;
+ }
+
+ public Object Release(long seq) {
+ Object returnValue = null ;
+ lock(lockObject) {
+ returnValue = pending[seq] ;
+ pending.Remove(seq) ;
+ }
+
+ return returnValue ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/Session.cs b/dotnet/client-010/management/console/Session.cs
new file mode 100644
index 0000000000..d9c5948e57
--- /dev/null
+++ b/dotnet/client-010/management/console/Session.cs
@@ -0,0 +1,796 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO ;
+using System.Reflection ;
+using System.Threading ;
+using log4net ;
+using org.apache.qpid.client ;
+using org.apache.qpid.transport.util;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+
+ /**
+ * Main Interaction point for interaction with the bus. Can be used to locate objects
+ * on the bus, and invoke messages on them.
+ */
+ public class Session
+ {
+ public static ILog log = LogManager.GetLogger(typeof(Session)) ;
+
+ public static int CONTEXT_SYNC = 1 ;
+ public static int CONTEXT_STARTUP = 2 ;
+ public static int CONTEXT_MULTIGET = 3 ;
+ public static int DEFAULT_GET_WAIT_TIME = 60000 ;
+
+ public bool RecieveObjects = true ;
+ public bool RecieveEvents = true ;
+ public bool RecieveHeartbeat = true ;
+ public bool UserBindings = false ;
+ public Console Console ;
+
+ protected Dictionary<string, Dictionary<string, SchemaClass>> Packages = new Dictionary<string, Dictionary<string, SchemaClass>>() ;
+ protected List<Broker> Brokers = new List<Broker>() ;
+ protected SequenceManager SequenceManager = new SequenceManager() ;
+ protected object LockObject = new Object();
+ protected List<long> SyncSequenceList = new List<long>() ;
+ protected List<QMFObject> GetResult ;
+ protected Object SyncResult ;
+
+ public Session()
+ {
+ }
+
+ public Session(Console console) {
+ Console = console ;
+ }
+
+ public void AddBroker(string url) {
+ BrokerURL brokerurl = GetBrokerURL(url) ;
+ Broker broker = new Broker(this, brokerurl) ;
+ Brokers.Add(broker) ;
+
+ Dictionary<string, object> args = new Dictionary<string, object>() ;
+ args.Add("_class", "agent") ;
+ args.Add("_broker", broker) ;
+ this.GetObjects(args) ;
+ }
+
+ public void RemoveBroker(Broker broker) {
+ if (Brokers.Contains(broker)) {
+ Brokers.Remove(broker) ;
+ }
+
+ broker.Shutdown() ;
+ }
+
+ public void Close() {
+ foreach (Broker broker in Brokers.ToArray()) {
+ this.RemoveBroker(broker) ;
+ }
+ }
+
+ protected BrokerURL GetBrokerURL(string url) {
+ return new BrokerURL(url) ;
+ }
+
+
+ public List<QMFObject> GetObjects(Dictionary<string, object> args) {
+ List<Broker> brokerList = null ;
+ List<Agent> agentList = new List<Agent>() ;
+
+ if (args.ContainsKey("_broker")) {
+ brokerList = new List<Broker>() ;
+ brokerList.Add((Broker)args["_broker"]) ;
+ } else {
+ brokerList = this.Brokers ;
+ }
+
+ foreach (Broker broker in brokerList) {
+ broker.WaitForStable() ;
+ }
+
+ if (args.ContainsKey("_agent")) {
+ Agent agent = (Agent)args["_agent"] ;
+ if (brokerList.Contains(agent.Broker)) {
+ agentList.Add(agent) ;
+ } else {
+ throw new Exception("Agent is not managed by this console or the supplied broker") ;
+ }
+ } else {
+ if (args.ContainsKey("_objectId")) {
+ ObjectID oid = (ObjectID) args["_objectId"] ;
+ foreach (Broker broker in Brokers) {
+ foreach (Agent agent in broker.Agents.Values) {
+ if ((agent.AgentBank == oid.AgentBank()) && (agent.BrokerBank == oid.BrokerBank())) {
+ agentList.Add(agent) ;
+ }
+ }
+ }
+ }
+ else {
+ foreach (Broker broker in brokerList) {
+ foreach (Agent agent in broker.Agents.Values) {
+ if (agent.Broker.IsConnected()) {
+ agentList.Add(agent) ;
+ }
+ }
+ }
+ }
+ }
+
+ GetResult = new List<QMFObject>() ;
+
+ if (agentList.Count > 0) {
+ //FIXME Add a bunch of other suff too
+ foreach (Agent agent in agentList) {
+ Dictionary<string, object> getParameters = new Dictionary<string, object>() ;
+ Broker broker = agent.Broker ;
+ long seq = -1 ;
+ lock(LockObject) {
+ seq = SequenceManager.Reserve(Session.CONTEXT_MULTIGET) ;
+ SyncSequenceList.Add(seq) ;
+ }
+ object packageName = null ;
+ object className = null ;
+ object key = null ;
+ object sClass = null ;
+ object oid = null ;
+ object hash = null ;
+
+ args.TryGetValue("_schema", out sClass) ;
+ args.TryGetValue("_key", out key) ;
+ args.TryGetValue("_class", out className) ;
+ args.TryGetValue("_package", out packageName) ;
+ args.TryGetValue("_objectID", out oid) ;
+ args.TryGetValue("_hash", out hash) ;
+
+ if ((className == null) && (oid == null) && (oid == null)) {
+ throw new Exception("No class supplied, use '_schema', '_key', '_class', or '_objectId' argument") ;
+ }
+
+ if (oid != null) {
+ getParameters.Add("_objectID", oid) ;
+ }
+ else {
+ if (sClass != null) {
+ key = key ?? ((SchemaClass)sClass).Key ;
+ }
+ if (key != null) {
+ ClassKey cKey = (ClassKey)key ;
+ className = className ?? cKey.ClassName ;
+ packageName = packageName ?? cKey.PackageName ;
+ hash = hash ?? cKey.Hash ;
+ }
+
+ if (packageName != null) {
+ getParameters.Add("_package", packageName) ;
+ }
+ if (className != null) {
+ getParameters.Add("_class", className) ;
+ }
+ if (hash != null) {
+ getParameters.Add("_hash", hash) ;
+ }
+ foreach (KeyValuePair<string, object> pair in args) {
+ if (!pair.Key.StartsWith("_")) {
+ getParameters.Add(pair.Key, pair.Value) ;
+ }
+ }
+ }
+
+ IEncoder enc = broker.CreateEncoder('G', seq) ;
+ enc.WriteMap(getParameters) ;
+ string routingKey = String.Format("agent.{0}.{1}", agent.BrokerBank, agent.AgentBank) ;
+ Message msg = broker.CreateMessage(enc, routingKey) ;
+ log.Debug("Get Object Keys: ") ;
+ foreach (string pKey in getParameters.Keys) {
+ log.Debug(String.Format("\tKey: '{0}' Value: '{1}'", pKey, getParameters[pKey])) ;
+ }
+ broker.Send(msg) ;
+ }
+
+ int waittime = DEFAULT_GET_WAIT_TIME ;
+ bool timeout = false ;
+ if (args.ContainsKey("_timeout")) {
+ waittime = (int) args["_timeout"] ;
+ }
+ DateTime start = DateTime.Now ;
+ lock (LockObject) {
+ // FIXME ERROR
+ while (SyncSequenceList.Count > 0){
+ Monitor.Wait(LockObject,waittime) ;
+ TimeSpan duration = DateTime.Now - start;
+ if (duration.TotalMilliseconds > waittime) {
+ foreach (long pendingSeq in SyncSequenceList) {
+ SequenceManager.Release(pendingSeq) ;
+ }
+ SyncSequenceList.Clear() ;
+ timeout = true ;
+ }
+ }
+ }
+
+ //FIXME Add the error logic
+ if ((GetResult.Count == 0) && timeout) {
+ throw new Exception ("Get Request timed out") ;
+ }
+ }
+ return GetResult ;
+ }
+
+ public List<string> GetPackages() {
+ this.WaitForStable() ;
+ List<string> returnValue = new List<string>() ;
+ foreach (String name in Packages.Keys) {
+ returnValue.Add(name) ;
+ }
+
+ return returnValue ;
+ }
+
+ public List<ClassKey> GetClasses(string packageName) {
+ List<ClassKey> returnValue = new List<ClassKey>() ;
+ this.WaitForStable() ;
+
+ if (Packages.ContainsKey(packageName)) {
+ foreach (SchemaClass sClass in Packages[packageName].Values) {
+ returnValue.Add(sClass.Key) ;
+ }
+ }
+
+ return returnValue ;
+ }
+
+ public SchemaClass GetSchema(ClassKey key) {
+ return GetSchema(key, true) ;
+ }
+
+ protected SchemaClass GetSchema(ClassKey key, bool waitForStable) {
+ if (waitForStable) {
+ this.WaitForStable() ;
+ }
+
+ SchemaClass returnValue = null ;
+
+ try {
+ returnValue = Packages[key.PackageName][key.GetKeyString()] ;
+ }
+ catch (KeyNotFoundException) {
+ // eat it
+ }
+
+ return returnValue ;
+ }
+
+
+ protected void WaitForStable() {
+ foreach (Broker broker in Brokers) {
+ broker.WaitForStable() ;
+ }
+ }
+
+
+ public Broker GetBroker(long BrokerBank) {
+ Broker returnValue = null ;
+
+ foreach (Broker broker in Brokers) {
+ if (broker.BrokerBank() == BrokerBank) {
+ returnValue = broker ;
+ break ;
+ }
+ }
+
+ return returnValue ;
+ }
+
+ public MethodResult InvokeMethod(QMFObject obj, string name, List<object> args, bool synchronous, int timeToLive) {
+ Broker aBroker = this.GetBroker(obj.BrokerBank()) ;
+
+ long seq = this.SendMethodRequest(obj, aBroker, name, args, synchronous, timeToLive) ;
+ if (seq != 0) {
+ if (!synchronous) {
+ return null ;
+ }
+ try {
+ aBroker.WaitForSync(timeToLive) ;
+ } catch (Exception e) {
+ SequenceManager.Release(seq) ;
+ throw e ;
+ }
+
+ // FIXME missing error logic in the broker
+ return (MethodResult) SyncResult ;
+ }
+
+ return null ;
+ }
+
+ protected long SendMethodRequest(QMFObject obj, Broker aBroker, string name, List<object> args, bool synchronous, int timeToLive) {
+
+ SchemaMethod method = obj.Schema.GetMethod(name) ;
+ if (args == null) {
+ args = new List<object>() ;
+ }
+
+ long seq = 0 ;
+ if (method != null) {
+ KeyValuePair<SchemaMethod, bool> pair = new KeyValuePair<SchemaMethod, bool>(method, synchronous) ;
+ seq = SequenceManager.Reserve(pair) ;
+ IEncoder enc = aBroker.CreateEncoder('M', seq) ;
+ obj.ObjectID.encode(enc) ;
+ obj.Schema.Key.encode(enc) ;
+ enc.WriteStr8(name) ;
+
+ if (args.Count < method.InputArgCount) {
+ throw new Exception(String.Format("Incorrect number of arguments: expected {0}, got{1}", method.InputArgCount, args.Count)) ;
+ }
+
+ int argIndex = 0 ;
+ foreach (SchemaArgument arg in method.Arguments) {
+ if (arg.IsInput()) {;
+ this.EncodeValue(enc, arg.Type, args[argIndex]) ;
+ argIndex += 1 ;
+ }
+ }
+
+ Message msg = aBroker.CreateMessage(enc,obj.RoutingKey(),timeToLive) ;
+
+ if (synchronous) {
+ aBroker.SetSyncInFlight(true) ;
+ }
+ aBroker.Send(msg) ;
+ }
+ return seq ;
+ }
+
+ public QMFObject MakeObject(ClassKey key) {
+ SchemaClass sClass = this.GetSchema(key) ;
+ if (sClass == null) {
+ throw new Exception("No schema found for class " + key.ToString()) ;
+ }
+
+ return this.CreateQMFObject(sClass, true, true, false) ;
+ }
+
+ public QMFObject MakeObject(String keyString) {
+ return this.MakeObject(new ClassKey(keyString)) ;
+ }
+
+ // Callback Methods
+ public void HandleNewAgent(Agent agent) {
+ if (Console != null) {
+ Console.NewAgent(agent) ;
+ }
+ }
+
+ public void HandleAgentRemoved(Agent agent) {
+ if (Console != null) {
+ Console.AgentRemoved(agent) ;
+ }
+ }
+
+ public void HandleBrokerConnect(Broker broker) {
+ if (Console != null) {
+ Console.BrokerConnected(broker) ;
+ }
+ }
+
+ public void HandleBrokerDisconnect(Broker broker) {
+ if (Console != null) {
+ Console.BrokerDisconnected(broker) ;
+ }
+ }
+
+ public void HandleBrokerResponse(Broker broker, IDecoder decoder, long sequence) {
+ if (Console != null) {
+ Console.BrokerInformation(broker) ;
+ }
+
+ long seq = SequenceManager.Reserve(CONTEXT_STARTUP) ;
+ IEncoder endocder = broker.CreateEncoder('P', seq) ;
+ broker.Send(endocder) ;
+ }
+
+ public void HandlePackageIndicator(Broker broker, IDecoder decoder, long sequence) {
+ string packageName = decoder.ReadStr8() ;
+ bool notify = false ;
+ if (!Packages.ContainsKey(packageName)) {
+ lock (LockObject) {
+ Packages[packageName] = new Dictionary<string, SchemaClass>() ;
+ notify = true ;
+ }
+ }
+
+ if (notify && Console != null) {
+ Console.NewPackage(packageName) ;
+ }
+
+ broker.IncrementOutstanding() ;
+ long seq = SequenceManager.Reserve(Session.CONTEXT_STARTUP) ;
+ IEncoder enc = broker.CreateEncoder('Q', seq) ;
+ enc.WriteStr8(packageName) ;
+ broker.Send(enc) ;
+ }
+
+ public void HandleCommandComplete(Broker broker, IDecoder decoder, long sequence) {
+
+ long code = decoder.ReadUint32() ;
+ string text = decoder.ReadStr8() ;
+ Object context = this.SequenceManager.Release(sequence) ;
+
+ if (context.Equals(CONTEXT_STARTUP)) {
+ broker.DecrementOutstanding() ;
+ } else {
+ if ((context.Equals(CONTEXT_SYNC)) & broker.GetSyncInFlight()) {
+ broker.SetSyncInFlight(false) ;
+ } else {
+ if (context.Equals(CONTEXT_MULTIGET) && SyncSequenceList.Contains(sequence)) {
+ lock(LockObject) {
+ SyncSequenceList.Remove(sequence) ;
+ if (SyncSequenceList.Count == 0) {
+ Monitor.PulseAll(LockObject) ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void HandleClassIndicator(Broker broker, IDecoder decoder, long sequence) {
+ short kind = decoder.ReadUint8() ;
+ ClassKey classKey = new ClassKey(decoder) ;
+ bool unknown = false ;
+
+
+ lock (LockObject) {
+ if (Packages.ContainsKey(classKey.PackageName)) {
+ if (!Packages[classKey.PackageName].ContainsKey(classKey.GetKeyString())) {
+ unknown = true ;
+ }
+ }
+ }
+
+ if (unknown) {
+ broker.IncrementOutstanding() ;
+ long seq = SequenceManager.Reserve(Session.CONTEXT_STARTUP) ;
+ IEncoder enc = broker.CreateEncoder('S', seq) ;
+ classKey.encode(enc) ;
+ broker.Send(enc) ;
+ }
+ }
+
+ public void HandleMethodResponse(Broker broker, IDecoder decoder, long sequence) {
+ long code = decoder.ReadUint32() ;
+ string text = decoder.ReadStr16() ;
+
+ Dictionary<string, object> outArgs = new Dictionary<string, object>() ;
+ object obj = SequenceManager.Release(sequence) ;
+
+ if (obj == null) {
+ return ;
+ }
+
+ KeyValuePair<SchemaMethod, bool> pair = (KeyValuePair<SchemaMethod, bool>) obj ;
+ if (code == 0) {
+ foreach (SchemaArgument arg in pair.Key.Arguments) {
+ if (arg.IsOutput()) {
+ outArgs.Add(arg.Name, this.DecodeValue(decoder, arg.Type)) ;
+ }
+ }
+ }
+
+ MethodResult result = new MethodResult(code, text, outArgs) ;
+
+ if (pair.Value) {
+ this.SyncResult = result;
+ broker.SetSyncInFlight(false) ;
+ }
+
+ if (Console != null) {
+ Console.MethodResponse(broker, sequence, result) ;
+ }
+ }
+
+ public void HandleHeartbeatIndicator(Broker broker, IDecoder decoder, long sequence, IMessage msg) {
+ if (Console != null) {
+ long brokerBank = 1 ;
+ long agentBank = 0 ;
+ try {
+ string routingKey = msg.DeliveryProperties.GetRoutingKey() ;
+ if (routingKey != null) {
+ agentBank = Agent.GetBrokerBank(routingKey) ;
+ brokerBank = Agent.GetBrokerBank(routingKey) ;
+ }
+ }
+ catch (Exception e) {
+ log.Warn("Internal QPID error", e) ;
+ }
+
+ string agentKey = Agent.AgentKey(agentBank, brokerBank) ;
+ long timestamp = decoder.ReadUint64() ;
+ if (broker.Agents.ContainsKey(agentKey)) {
+ Agent agent = broker.Agents[agentKey] ;
+ Console.HearbeatRecieved(agent, timestamp) ;
+ }
+ }
+
+ }
+
+ public void HandleEventIndicator(Broker broker, IDecoder decoder, long sequence) {
+ if (Console != null) {
+ QMFEvent newEvent = new QMFEvent(this, decoder) ;
+ Console.EventRecieved(broker, newEvent) ;
+ }
+ }
+
+ public void HandleSchemaResponse(Broker broker, IDecoder decoder, long sequence) {
+ short kind = decoder.ReadUint8() ;
+ ClassKey classKey = new ClassKey(decoder) ;
+ SchemaClass sClass = new SchemaClass(kind, classKey, decoder, this) ;
+ lock(LockObject) {
+ Dictionary<string, SchemaClass> classMappings = Packages[sClass.PackageName] ;
+ classMappings.Remove(sClass.ClassKeyString) ;
+ classMappings.Add(sClass.ClassKeyString, sClass) ;
+ }
+
+ SequenceManager.Release(sequence) ;
+ broker.DecrementOutstanding() ;
+ if (Console != null) {
+ this.Console.NewClass(kind, classKey) ;
+ }
+ }
+
+ public void HandleContentIndicator(Broker broker, IDecoder decoder, long sequence, bool hasProperties, bool hasStatistics) {
+
+ ClassKey key = new ClassKey(decoder) ;
+ SchemaClass sClass = null ;;
+ lock (LockObject) {
+ sClass = GetSchema(key, false) ;
+ }
+ if (sClass != null) {
+ QMFObject obj = this.CreateQMFObject(sClass, decoder, hasProperties, hasStatistics, true) ;
+
+ if (key.PackageName.Equals("org.apache.qpid.broker") && key.ClassName.Equals("agent") && hasProperties) {
+ broker.UpdateAgent(obj) ;
+ }
+
+ lock (LockObject) {
+ if (SyncSequenceList.Contains(sequence)) {
+ if (!obj.IsDeleted() && this.SelectMatch(obj)) {
+ GetResult.Add(obj) ;
+ }
+ }
+ }
+
+ if (Console != null) {
+ if (hasProperties) {
+ Console.ObjectProperties(broker, obj) ;
+ }
+ if (hasStatistics) {
+ Console.ObjectStatistics(broker, obj) ;
+ }
+ }
+ }
+ }
+
+ public bool SelectMatch(QMFObject obj) {
+ return true ;
+ }
+
+ public object DecodeValue(IDecoder dec, short type) {
+
+ switch (type) {
+ case 1: return dec.ReadUint8() ; // U8
+ case 2: return dec.ReadUint16() ; // U16
+ case 3: return dec.ReadUint32() ; // U32
+ case 4: return dec.ReadUint64() ; // U64
+ case 6: return dec.ReadStr8() ; // SSTR
+ case 7: return dec.ReadStr16() ; // LSTR
+ case 8: return dec.ReadDatetime() ; // ABSTIME
+ case 9: return dec.ReadUint32() ; // DELTATIME
+ case 10: return new ObjectID(dec) ; // ref
+ case 11: return dec.ReadUint8() != 0 ; // bool
+ case 12: return dec.ReadFloat() ; // float
+ case 13: return dec.ReadDouble() ; // double
+ case 14: return dec.ReadUuid() ; // UUID
+ case 15: return dec.ReadMap() ; // Ftable
+ case 16: return dec.ReadInt8() ; // int8
+ case 17: return dec.ReadInt16() ; // int16
+ case 18: return dec.ReadInt32() ; // int32
+ case 19: return dec.ReadInt64() ; // int64
+ case 20: // Object
+ // Peek into the inner type code, make sure
+ // it is actually an object
+ object returnValue = null ;
+ short innerTypeCode = dec.ReadUint8() ;
+ if (innerTypeCode != 20) {
+ returnValue = this.DecodeValue(dec, innerTypeCode) ;
+ }
+ else {
+ ClassKey classKey = new ClassKey(dec) ;
+ lock(LockObject) {
+ SchemaClass sClass = GetSchema(classKey) ;
+ if (sClass != null) {
+ returnValue = this.CreateQMFObject(sClass, dec, true, true, false) ;
+ }
+ }
+ }
+ return returnValue;
+ case 21: // List
+ {
+ MSDecoder lDec = new MSDecoder();
+ lDec.Init(new MemoryStream(dec.ReadVbin32()));
+ long count = lDec.ReadUint32();
+ List<object> newList = new List<object>();
+ while (count > 0)
+ {
+ short innerType = lDec.ReadUint8();
+ newList.Add(this.DecodeValue(lDec, innerType));
+ count -= 1;
+ }
+ return newList;
+ }
+ case 22: // Array
+ {
+ MSDecoder aDec = new MSDecoder();
+ aDec.Init(new MemoryStream(dec.ReadVbin32()));
+ long cnt = aDec.ReadUint32();
+ short innerType = aDec.ReadUint8();
+ List<object> aList = new List<object>();
+ while (cnt > 0)
+ {
+ aList.Add(this.DecodeValue(aDec, innerType));
+ cnt -= 1;
+ }
+ return aList;
+ }
+ default:
+ throw new Exception(String.Format("Invalid Type Code: {0}", type)) ;
+ }
+ }
+
+
+ public void EncodeValue(IEncoder enc, short type, object val) {
+ try {
+ switch ((int)type) {
+ case 1: enc.WriteUint8((short) val) ; break; // U8
+ case 2: enc.WriteUint16((int) val) ; break; // U16
+ case 3: enc.WriteUint32((long) val) ; break; // U32
+ case 4: enc.WriteUint64((long) val) ; break; // U64
+ case 6: enc.WriteStr8((string) val) ; break; // SSTR
+ case 7: enc.WriteStr16((string) val) ; break; // LSTR
+ case 8: enc.WriteDatetime((long) val); break; // ABSTIME
+ case 9: enc.WriteUint32((long) val); break; // DELTATIME
+ case 10: ((ObjectID)val).encode(enc) ; break; // ref
+ case 11:
+ if ((bool) val) {
+ enc.WriteUint8(1) ;
+ } else {
+ enc.WriteUint8(0) ;
+ }
+ break ;
+ case 12: enc.WriteFloat((float) val); break; // FLOAT
+ case 13: enc.WriteDouble((double) val); break; // DOUBLE
+ case 14: enc.WriteUuid((UUID) val) ; break ; // UUID
+ case 15: enc.WriteMap((Dictionary<string, object>) val) ; break ; // Ftable
+ case 16: enc.WriteInt8((short) val) ; break; // int8
+ case 17: enc.WriteInt16((int) val) ; break; // int16
+ case 18: enc.WriteInt32(long.Parse(""+ val)) ; break; // int32
+ case 19: enc.WriteInt64(long.Parse("" + val)) ; break; // int64
+ case 20: // Object
+ // Check that the object has a session, if not
+ // take ownership of it
+ QMFObject qObj = (QMFObject) val ;
+ if (qObj.Session == null) {
+ qObj.Session = this ;
+ }
+ qObj.Encode(enc) ;
+ break;
+ case 21: // List
+ List<object> items = (List<object>) val ;
+ MSEncoder lEnc = new MSEncoder(1) ;
+ lEnc.Init() ;
+ lEnc.WriteUint32(items.Count) ;
+ foreach (object obj in items) {
+ short innerType = Util.QMFType(obj) ;
+ lEnc.WriteUint8(innerType) ;
+ this.EncodeValue(lEnc,innerType,obj) ;
+ }
+ enc.WriteVbin32(lEnc.Segment().ToArray()) ;
+ break ;
+ case 22: // Array
+ List<object> aItems = (List<object>) val ;
+ MSEncoder aEnc = new MSEncoder(1) ;
+ aEnc.Init() ;
+ long aCount = aItems.Count ;
+ aEnc.WriteUint32(aCount) ;
+ if (aCount > 0) {
+ Object anObj = aItems[0] ;
+ short innerType = Util.QMFType(anObj) ;
+ aEnc.WriteUint8(innerType) ;
+ foreach (object obj in aItems) {
+ this.EncodeValue(aEnc,innerType,obj) ;
+ }
+ }
+ enc.WriteVbin32(aEnc.Segment().ToArray()) ;
+ break ;
+ default:
+ throw new Exception(String.Format("Invalid Type Code: {0}", type)) ;
+ }
+ }
+ catch (System.InvalidCastException e) {
+ string msg = String.Format("Class cast exception for typecode {0}, type {1} ", type, val.GetType()) ;
+ log.Error(msg) ;
+ throw new Exception(msg + type, e) ;
+ }
+ }
+
+ public List<string> BindingKeys() {
+ List<string> bindings = new List<string>() ;
+ bindings.Add("schema.#") ;
+ if (RecieveObjects & RecieveEvents & RecieveHeartbeat & !UserBindings) {
+ bindings.Add("console.#") ;
+ }
+ else {
+ if (RecieveObjects & !UserBindings) {
+ bindings.Add("console.obj.#") ;
+ }
+ else {
+ bindings.Add("console.obj.*.*.org.apache.qpid.broker.agent") ;
+ }
+ if (RecieveEvents) {
+ bindings.Add("console.event.#") ;
+ }
+ if (RecieveHeartbeat) {
+ bindings.Add("console.heartbeat.#") ;
+ }
+ }
+ return bindings ;
+ }
+
+ protected QMFObject CreateQMFObject(SchemaClass schema, bool hasProperties, bool hasStats , bool isManaged) {
+ Type realClass = typeof(QMFObject) ;
+ if (Console != null) {
+ realClass = Console.TypeMapping(schema.Key) ;
+ }
+ Type[] types = new Type[] {typeof(Session), typeof(SchemaClass), typeof(bool), typeof(bool),typeof(bool)} ;
+ object[] args = new object[] {this, schema, hasProperties, hasStats, isManaged} ;
+ ConstructorInfo ci = realClass.GetConstructor(types);
+ return (QMFObject) ci.Invoke(args) ;
+ }
+
+ protected QMFObject CreateQMFObject(SchemaClass schema, IDecoder dec, bool hasProperties, bool hasStats , bool isManaged) {
+ Type realClass = typeof(QMFObject) ;
+ if (Console != null) {
+ realClass = Console.TypeMapping(schema.Key) ;
+ }
+ Type[] types = new Type[] {typeof(Session), typeof(SchemaClass), typeof(IDecoder), typeof(bool), typeof(bool),typeof(bool)} ;
+ object[] args = new object[] {this, schema, dec, hasProperties, hasStats, isManaged} ;
+ ConstructorInfo ci = realClass.GetConstructor(types);
+ return (QMFObject) ci.Invoke(args) ;
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/Util.cs b/dotnet/client-010/management/console/Util.cs
new file mode 100644
index 0000000000..4a06f4e6af
--- /dev/null
+++ b/dotnet/client-010/management/console/Util.cs
@@ -0,0 +1,150 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.client ;
+using org.apache.qpid.transport.util;
+using org.apache.qpid.transport.codec ;
+
+namespace org.apache.qpid.console
+{
+ public class Util
+ {
+ static Dictionary<Type, short> ENCODINGS = new Dictionary<Type, short>() ;
+
+
+ static Util() {
+ ENCODINGS.Add(typeof(string), 7) ;
+ ENCODINGS.Add(typeof(short), 1) ;
+ //ENCODINGS.Add(typeof(int), 2) ;
+ //ENCODINGS.Add(typeof(long), 3) ;
+ ENCODINGS.Add(typeof(float), 13) ;
+ ENCODINGS.Add(typeof(QMFObject), 20) ;
+ ENCODINGS.Add(typeof(int), 17) ;
+ ENCODINGS.Add(typeof(long), 18) ;
+ ENCODINGS.Add(typeof(System.Collections.Generic.List<>), 21) ;
+ }
+
+ /**
+ * Converts type numbers to schema type names
+ */
+ public static string TypeName(short type) {
+ switch(type) {
+ //case 0: return "UNKNOWN" ;
+ case 1: return "uint8" ;
+ case 2: return "uint16" ;
+ case 3: return "uint32" ;
+ case 4: return "uint64" ;
+ case 5: return "bool" ;
+ case 6: return "short-string" ;
+ case 7: return "long-string" ;
+ case 8: return "abs-time" ;
+ case 9: return "delta-time" ;
+ case 10: return "reference" ;
+ case 11: return "boolean" ;
+ case 12: return "float" ;
+ case 13: return "double" ;
+ case 14: return "uuid" ;
+ case 15: return "field-table" ;
+ case 16: return "int8" ;
+ case 17: return "int16" ;
+ case 18: return "int32" ;
+ case 19: return "int64" ;
+ case 20: return "object" ;
+ case 21: return "list" ;
+ case 22: return "array" ;
+ }
+
+ throw new Exception(String.Format("Invalid Type Code: {0}", type)) ;
+ }
+
+ /**
+ * Converts schema numbers to schema access names
+ */
+ public static string AccessName(int type) {
+ switch(type) {
+ //case 0: return "UNKNOWN" ;
+ case 1: return "ReadCreate" ;
+ case 2: return "ReadWrite" ;
+ case 3: return "ReadOnly" ;
+ }
+
+ throw new Exception(String.Format("Invalid Access Code: {0}", type)) ;
+ }
+
+ /**
+ * Default values per schema type
+ */
+ public static object DefaultValue(short type) {
+ switch(type) {
+ //case 0: return "UNKNOWN" ;
+ case 1: return 0 ;
+ case 2: return 0 ;
+ case 3: return 0l ;
+ case 4: return 0l ;
+ case 5: return false ;
+ case 6: return "" ;
+ case 7: return "" ;
+ case 8: return 0l ;
+ case 9: return 0l ;
+ case 10: return new ObjectID() ;
+ case 11: return false ;
+ case 12: return 0f ;
+ case 13: return 0d ;
+ case 14: return new UUID(0,0) ;
+ case 15: return new Dictionary<string, object>();
+ case 16: return 0 ;
+ case 17: return 0 ;
+ case 18: return 0l ;
+ case 19: return 0l ;
+ case 20: return null ;
+ case 21: return new List<object>() ;
+ case 22: return new List<object>() ;
+ }
+
+ throw new Exception(String.Format("Invalid Type Code: {0}", type)) ;
+ }
+
+ /**
+ * Returns a QMF type based on C# object type
+ */
+ public static short QMFType(object obj) {
+ if (ENCODINGS.ContainsKey(obj.GetType())) {
+ return ENCODINGS[obj.GetType()] ;
+ } else {
+ throw new Exception (String.Format("Unkown Type of {0}", obj.GetType())) ;
+ }
+ }
+
+ /**
+ * Grabs a friendly string version of bytes.
+ */
+ public static string ByteString(byte[] bytes) {
+ return System.Text.Encoding.UTF8.GetString(bytes) ;
+ }
+
+ protected Util()
+ {
+
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/XMLUtil.cs b/dotnet/client-010/management/console/XMLUtil.cs
new file mode 100644
index 0000000000..b24ad51747
--- /dev/null
+++ b/dotnet/client-010/management/console/XMLUtil.cs
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+
+using System;
+using System.Collections.Generic;
+using org.apache.qpid.client ;
+
+namespace org.apache.qpid.console
+{
+
+
+ public class XMLUtil
+ {
+
+ public static string CommonAttributes(SchemaVariable var) {
+ string returnString = "" ;
+ if (var.Description != null){
+ returnString = returnString + String.Format(" desc='{0}'", var.Description) ;
+ }
+
+ if (var.RefPackage != null){
+ returnString = returnString + String.Format(" refPackage='{0}'", var.RefPackage) ;
+ }
+
+ if (var.RefClass != null){
+ returnString = returnString + String.Format(" refClass='{0}'", var.RefClass) ;
+ }
+
+ if (var.Unit != null){
+ returnString = returnString + String.Format(" unit='{0}'", var.Unit) ;
+ }
+
+ if (var.Min != null){
+ returnString = returnString + String.Format(" min='{0}'", var.Min) ;
+ }
+ if (var.Max != null){
+ returnString = returnString + String.Format(" max='{0}'", var.Max) ;
+ }
+ if (var.MaxLength != null){
+ returnString = returnString + String.Format(" maxLength='{0}'", var.MaxLength) ;
+ }
+
+ return returnString ;
+ }
+
+ public static string SchemaXML(Session sess, string packageName) {
+ string returnValue = String.Format("<schema package='{0}'>\n", packageName) ;
+ foreach (ClassKey key in sess.GetClasses(packageName)) {
+ SchemaClass schema = sess.GetSchema(key) ;
+ if (schema.Kind == 1) {
+ if (schema.SuperType == null)
+ returnValue += String.Format("\t<class name='{0}' hash='{1}'>\n", key.ClassName, key.GetHashString()) ;
+ else
+ returnValue += String.Format("\t<class name='{0}' hash='{1}' extends='{2}'>\n", key.ClassName, key.GetHashString(), schema.SuperType.GetKeyString()) ;
+ foreach (SchemaProperty prop in schema.Properties) {
+ object[] attributes = new object[5] ;
+ attributes[0] = prop.Name ;
+ attributes[1] = Util.TypeName(prop.Type) ;
+ attributes[2] = Util.AccessName(prop.Access) ;
+ attributes[3] = prop.Optional ;
+ attributes[4] = XMLUtil.CommonAttributes(prop);
+ returnValue += String.Format("\t\t<property name='{0}' type='{1}' access='{2}' optional='{3}'{4}/>\n", attributes) ;
+ }
+ foreach (SchemaMethod meth in schema.Methods) {
+ returnValue += String.Format("\t\t<method name='{0}'/>\n", meth.Name) ;
+ foreach (SchemaArgument arg in meth.Arguments) {
+ object[] attributes = new object[4] ;
+ attributes[0] = arg.Name ;
+ attributes[1] = arg.Direction ;
+ attributes[2] = Util.TypeName(arg.Type) ;
+ attributes[3] = XMLUtil.CommonAttributes(arg);
+ returnValue += String.Format("\t\t\t<arg name='{0}' dir='{1}' type='{2}'{3}/>\n", attributes) ;
+ }
+ returnValue += String.Format("\t\t</method>\n") ;
+ }
+ returnValue += String.Format("\t</class>\n") ;
+ } else {
+ returnValue += String.Format("\t<event name='{0}' hash='{1}'>\n", key.ClassName, key.GetHashString()) ;
+ foreach (SchemaArgument arg in schema.Arguments) {
+ object[] attributes = new object[4] ;
+ attributes[0] = arg.Name ;
+ attributes[1] = Util.TypeName(arg.Type) ;
+ attributes[2] = XMLUtil.CommonAttributes(arg);
+ returnValue += String.Format("\t\t\t<arg name='{0}' type='{1}'{2}/>\n", attributes) ;
+ }
+ returnValue += String.Format("\t</event>\n") ;
+ }
+ }
+ returnValue += String.Format("</schema>\n") ;
+
+ return returnValue ;
+ }
+
+ public static string SchemaXML(Session sess, string[] packageNames) {
+ string returnValue = "<schemas>\n" ;
+ foreach (string package in packageNames) {
+ returnValue += XMLUtil.SchemaXML(sess, package) ;
+ returnValue += "\n" ;
+ }
+ returnValue += "</schemas>\n" ;
+ return returnValue ;
+ }
+
+ protected XMLUtil()
+ {
+ }
+ }
+}
diff --git a/dotnet/client-010/management/console/console.csproj b/dotnet/client-010/management/console/console.csproj
new file mode 100644
index 0000000000..3cc84e6073
--- /dev/null
+++ b/dotnet/client-010/management/console/console.csproj
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E8D2202F-3959-4F29-AA0D-875CD37905CA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Console</RootNamespace>
+ <AssemblyName>Console</AssemblyName>
+ <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AbstractConsole.cs" />
+ <Compile Include="Agent.cs" />
+ <Compile Include="Broker.cs" />
+ <Compile Include="BrokerURL.cs" />
+ <Compile Include="ClassKey.cs" />
+ <Compile Include="Console.cs" />
+ <Compile Include="MethodResult.cs" />
+ <Compile Include="ObjectID.cs" />
+ <Compile Include="QMFEvent.cs" />
+ <Compile Include="QMFObject.cs" />
+ <Compile Include="SchemaArgument.cs" />
+ <Compile Include="SchemaClass.cs" />
+ <Compile Include="SchemaMethod.cs" />
+ <Compile Include="SchemaProperty.cs" />
+ <Compile Include="SchemaStatistic.cs" />
+ <Compile Include="SchemaVariable.cs" />
+ <Compile Include="SequenceManager.cs" />
+ <Compile Include="Session.cs" />
+ <Compile Include="Util.cs" />
+ <Compile Include="XMLUtil.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/management/console/console.sln b/dotnet/client-010/management/console/console.sln
new file mode 100644
index 0000000000..1cfc056302
--- /dev/null
+++ b/dotnet/client-010/management/console/console.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+
+#
+# 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.
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "Console.csproj", "{E8D2202F-3959-4F29-AA0D-875CD37905CA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "..\..\client\Client.csproj", "{B911FFD7-754F-4735-A188-218D5065BE79}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E8D2202F-3959-4F29-AA0D-875CD37905CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8D2202F-3959-4F29-AA0D-875CD37905CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8D2202F-3959-4F29-AA0D-875CD37905CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8D2202F-3959-4F29-AA0D-875CD37905CA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B911FFD7-754F-4735-A188-218D5065BE79}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/client-010/management/console/default.build b/dotnet/client-010/management/console/default.build
new file mode 100644
index 0000000000..c71e695569
--- /dev/null
+++ b/dotnet/client-010/management/console/default.build
@@ -0,0 +1,54 @@
+<?xml version="1.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.
+
+-->
+
+<project name="qpid.console" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <property name="build.config" value="debug" />
+ <property name="build.debug" value="true" />
+ <property name="build.defines" value="DEBUG;TRACE"/>
+ <property name="base.dir" value="${project::get-base-directory()}/../.." />
+ <property name="build.dir" value="${base.dir}/bin/${framework::get-target-framework()}/${build.config}" />
+
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="***.cs" />
+ <exclude name="test/*.cs"/>
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ </references>
+ </csc>
+ </target>
+</project>
diff --git a/dotnet/client-010/perftest/PerfTest.cs b/dotnet/client-010/perftest/PerfTest.cs
new file mode 100644
index 0000000000..c94dd865d5
--- /dev/null
+++ b/dotnet/client-010/perftest/PerfTest.cs
@@ -0,0 +1,715 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using common.org.apache.qpid.transport.util;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+using Plossum.CommandLine;
+
+namespace PerfTest
+{
+ [CommandLineManager(ApplicationName = "Qpid Perf Tests", Copyright = "Apache Software Foundation")]
+ public class Options
+ {
+ [CommandLineOption(Description = "Displays this help text")]
+ public bool Help;
+
+ [CommandLineOption(Description = "Create shared queues.", MinOccurs = 0)]
+ public Boolean Setup;
+
+ [CommandLineOption(Description = "Run test, print report.", MinOccurs = 0)]
+ public Boolean Control;
+
+ [CommandLineOption(Description = "Publish messages.", MinOccurs = 0)]
+ public Boolean Publish;
+
+ [CommandLineOption(Description = "Subscribe for messages.", MinOccurs = 0)]
+ public Boolean Subscribe;
+
+ [CommandLineOption(Description = "Test mode: [shared|fanout|topic]", MinOccurs = 0)]
+ public string Mode
+ {
+ get { return _mMode; }
+ set
+ {
+ if (! value.Equals("shared") && ! value.Equals("fanout") && ! value.Equals("topic"))
+ throw new InvalidOptionValueException(
+ "The mode must not be shared|fanout|topic", false);
+ _mMode = value;
+ }
+ }
+
+ private string _mMode = "shared";
+
+ [CommandLineOption(Description = "Specifies the broler name", MinOccurs = 0)]
+ public string Broker
+ {
+ get { return _broker; }
+ set
+ {
+ if (String.IsNullOrEmpty(value))
+ throw new InvalidOptionValueException(
+ "The broker name must not be empty", false);
+ _broker = value;
+ }
+ }
+
+ private string _broker = "localhost";
+
+ [CommandLineOption(Description = "Specifies the port name", MinOccurs = 0)]
+ public int Port
+ {
+ get { return _port; }
+ set { _port = value; }
+ }
+
+ private int _port = 5672;
+
+ #region Publisher
+
+ [CommandLineOption(Description = "Create N publishers.", MinOccurs = 0)]
+ public int Pubs
+ {
+ get { return _pubs; }
+ set { _pubs = value; }
+ }
+
+ private int _pubs = 1;
+
+ [CommandLineOption(Description = "Each publisher sends N messages.", MinOccurs = 0)]
+ public double Count
+ {
+ get { return _count; }
+ set { _count = value; }
+ }
+
+ private double _count = 5000;
+
+ [CommandLineOption(Description = "Size of messages in bytes.", MinOccurs = 0)]
+ public long Size
+ {
+ get { return _size; }
+ set { _size = value; }
+ }
+
+ private long _size = 1024;
+
+ [CommandLineOption(Description = "Publisher use confirm-mode.", MinOccurs = 0)]
+ public Boolean Confirm = true;
+
+ [CommandLineOption(Description = "Publish messages as durable.", MinOccurs = 0)]
+ public Boolean Durable;
+
+ [CommandLineOption(Description = "Make data for each message unique.", MinOccurs = 0)]
+ public Boolean UniqueData;
+
+ [CommandLineOption(Description = "Wait for confirmation of each message before sending the next one.",
+ MinOccurs = 0)]
+ public Boolean SyncPub;
+
+ [CommandLineOption(Description = ">=0 delay between msg publish.", MinOccurs = 0)]
+ public double IntervalPub
+ {
+ get { return _interval_pub; }
+ set { _interval_pub = value; }
+ }
+
+ private double _interval_pub;
+
+ #endregion
+
+ #region Subscriber
+
+ [CommandLineOption(Description = "Create N subscribers.", MinOccurs = 0)]
+ public int Subs
+ {
+ get { return _subs; }
+ set { _subs = value; }
+ }
+
+ private int _subs = 1;
+
+ [CommandLineOption(Description = "N>0: Subscriber acks batches of N.\n N==0: Subscriber uses unconfirmed mode",
+ MinOccurs = 0)]
+ public int SubAck
+ {
+ get { return _suback; }
+ set { _suback = value; }
+ }
+
+ private int _suback;
+
+ [CommandLineOption(Description = ">=0 delay between msg consume", MinOccurs = 0)]
+ public double IntervalSub
+ {
+ get { return _interval_sub; }
+ set { _interval_sub = value; }
+ }
+
+ private double _interval_sub;
+
+ #endregion
+
+ [CommandLineOption(Description = "Create N queues.", MinOccurs = 0)]
+ public int Queues
+ {
+ get { return _qt; }
+ set { _qt = value; }
+ }
+
+ private int _qt = 1;
+
+ [CommandLineOption(Description = "Desired number of iterations of the test.", MinOccurs = 0)]
+ public int Iterations
+ {
+ get { return _iterations; }
+ set { _iterations = value; }
+ }
+
+ private int _iterations = 1;
+
+ [CommandLineOption(Description = "If non-zero, the transaction batch size.", MinOccurs = 0)]
+ public int Tx
+ {
+ get { return _tx; }
+ set { _tx = value; }
+ }
+
+ private int _tx;
+
+ [CommandLineOption(Description = "Make queue durable (implied if durable set.", MinOccurs = 0)]
+ public Boolean QueueDurable;
+
+ [CommandLineOption(Description = "Queue policy: count to trigger 'flow to disk'", MinOccurs = 0)]
+ public double QueueMaxCount
+ {
+ get { return _queueMaxCount; }
+ set { _queueMaxCount = value; }
+ }
+
+ private double _queueMaxCount;
+
+ [CommandLineOption(Description = "Queue policy: accumulated size to trigger 'flow to disk'", MinOccurs = 0)]
+ public double QueueMaxSize
+ {
+ get { return _queueMaxSize; }
+ set { _queueMaxSize = value; }
+ }
+
+ private double _queueMaxSize;
+
+ public double SubQuota
+ {
+ get { return _subQuota; }
+ set { _subQuota = value; }
+ }
+
+ private double _subQuota;
+ }
+
+ internal interface Startable
+ {
+ void Start();
+ }
+
+ public abstract class PerfTestClient : Startable
+ {
+ private readonly IClient _connection;
+ private readonly IClientSession _session;
+ private readonly Options _options;
+
+ public IClientSession Session
+ {
+ get { return _session; }
+ }
+
+ public Options Options
+ {
+ get { return _options; }
+ }
+
+ protected PerfTestClient(Options options)
+ {
+ _options = options;
+ _connection = new Client();
+ _connection.Connect(options.Broker, options.Port, "test", "guest", "guest");
+ _session = _connection.CreateSession(50000);
+ }
+
+ public abstract void Start();
+ }
+
+ public class SetupTest : PerfTestClient
+ {
+ public SetupTest(Options options)
+ : base(options)
+ {
+ }
+
+ private void queueInit(String name, Boolean durable, Dictionary<String, Object> arguments)
+ {
+ Session.QueueDeclare(name, null, arguments, durable ? Option.DURABLE : Option.NONE);
+ Session.QueuePurge(name);
+ Session.ExchangeBind(name, "amq.direct", name);
+ Session.Sync();
+ }
+
+ public override void Start()
+ {
+ queueInit("pub_start", false, null);
+ queueInit("pub_done", false, null);
+ queueInit("sub_ready", false, null);
+ queueInit("sub_done", false, null);
+ if (Options.Mode.Equals("shared"))
+ {
+ Dictionary<String, Object> settings = new Dictionary<string, object>();
+ if (Options.QueueMaxCount > 0)
+ settings.Add("qpid.max_count", Options.QueueMaxCount);
+ if (Options.QueueMaxSize > 0)
+ settings.Add("qpid.max_size", Options.QueueMaxSize);
+ for (int i = 0; i < Options.Queues; ++i)
+ {
+ string qname = "perftest" + i;
+ queueInit(qname, Options.Durable || Options.QueueDurable, settings);
+ }
+ }
+ }
+ }
+
+ public class SubscribeThread : PerfTestClient
+ {
+ private readonly string _queue;
+
+ public SubscribeThread(Options options, string key, string exchange)
+ : base(options)
+ {
+ _queue = "perftest" + (new UUID(10, 10));
+ Session.QueueDeclare(_queue, null, null, Option.EXCLUSIVE, Option.AUTO_DELETE,
+ Options.Durable ? Option.DURABLE : Option.NONE);
+ Session.ExchangeBind(_queue, exchange, key);
+ }
+
+ public SubscribeThread(Options options, string key)
+ : base(options)
+ {
+ _queue = key;
+ }
+
+ public override void Start()
+ {
+ if (Options.Tx > 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+ CircularBuffer<IMessage> buffer = new CircularBuffer<IMessage>(100);
+ // Create a listener and subscribe it to the queue named "message_queue"
+ IMessageListener listener = new SyncListener(buffer);
+
+ string dest = "dest" + UUID.RandomUuid();
+ Session.AttachMessageListener(listener, dest);
+ Session.MessageSubscribe(_queue, dest,
+ Options.Tx > 0 || Options.SubAck > 0
+ ? MessageAcceptMode.EXPLICIT
+ : MessageAcceptMode.NONE,
+ MessageAcquireMode.PRE_ACQUIRED, null, 0, null);
+ // issue credits
+ Session.MessageSetFlowMode(dest, MessageFlowMode.WINDOW);
+ Session.MessageFlow(dest, MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+
+ // Notify controller we are ready.
+ IMessage message = new Message();
+ message.DeliveryProperties.SetRoutingKey("sub_ready");
+
+ message.AppendData(Encoding.UTF8.GetBytes("ready"));
+ Session.MessageTransfer("amq.direct", message);
+
+ if (Options.Tx > 0)
+ {
+ Session.TxCommit();
+ Session.Sync();
+ }
+
+
+ for (int j = 0; j < Options.Iterations; ++j)
+ {
+
+ //need to allocate some more credit
+ Session.MessageFlow(dest, MessageCreditUnit.MESSAGE, (long)Options.SubQuota);
+
+ RangeSet range = new RangeSet();
+ IMessage msg;
+ DateTime start = DateTime.Now;
+ for (long i = 0; i < Options.SubQuota; ++i)
+ {
+ msg = buffer.Dequeue();
+ if (Options.Tx > 0 && ((i + 1)%Options.Tx == 0))
+ {
+ Session.TxCommit();
+ Session.Sync();
+ }
+ if (Options.IntervalSub > 0)
+ {
+ Thread.Sleep((int) Options.IntervalSub*1000);
+ }
+ range.Add(msg.Id);
+ }
+ if (Options.Tx > 0 || Options.SubAck > 0)
+ Session.MessageAccept(range);
+ range.Clear();
+ if (Options.Tx > 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+ DateTime end = DateTime.Now;
+
+ // Report to publisher.
+ message.DeliveryProperties.SetRoutingKey("sub_done");
+ message.ClearData();
+ message.AppendData(BitConverter.GetBytes(Options.SubQuota / end.Subtract(start).TotalMilliseconds ));
+ Session.MessageTransfer("amq.direct", message);
+ if (Options.Tx > 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+ }
+ Session.Close();
+ }
+ }
+
+ public class SyncListener : IMessageListener
+ {
+ private readonly CircularBuffer<IMessage> _buffer;
+
+ public SyncListener(CircularBuffer<IMessage> buffer)
+ {
+ _buffer = buffer;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ _buffer.Enqueue(m);
+ }
+ }
+
+
+ public class PublishThread : PerfTestClient
+ {
+ private readonly string _exchange;
+ private readonly string _key;
+
+ public PublishThread(Options options, string key, string exchange)
+ : base(options)
+ {
+ _key = key;
+ _exchange = exchange;
+ }
+
+
+ public override void Start()
+ {
+ byte[] data = new byte[Options.Size];
+ // randomly populate data
+ Random r = new Random(34);
+ r.NextBytes(data);
+ IMessage message = new Message();
+ message.AppendData(data);
+
+ message.DeliveryProperties.SetRoutingKey(_key);
+
+ if (Options.Durable)
+ message.DeliveryProperties.SetDeliveryMode(MessageDeliveryMode.PERSISTENT);
+
+ if (Options.Tx > 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+
+ CircularBuffer<IMessage> buffer = new CircularBuffer<IMessage>(100);
+ // Create a listener and subscribe it to the queue named "pub_start"
+ IMessageListener listener = new SyncListener(buffer);
+ string localQueue = "localQueue-" + UUID.RandomUuid().ToString();
+ Session.QueueDeclare(localQueue, null, null, Option.AUTO_DELETE);
+ Session.ExchangeBind(localQueue, "amq.direct", "pub_start");
+ Session.AttachMessageListener(listener, localQueue);
+ Session.MessageSubscribe(localQueue);
+ if (Options.Tx > 0)
+ {
+ Session.TxCommit();
+ Session.Sync();
+ }
+ buffer.Dequeue();
+
+ for (int j = 0; j < Options.Iterations; ++j)
+ {
+ DateTime start = DateTime.Now;
+ for (long i = 0; i < Options.Count; ++i)
+ {
+ Session.MessageTransfer(_exchange, message);
+
+ if (Options.SyncPub)
+ {
+ Session.Sync();
+ }
+ if (Options.Tx > 0 && (i + 1)%Options.Tx == 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+ if (Options.IntervalPub > 0)
+ {
+ Thread.Sleep((int) Options.IntervalSub*1000);
+ }
+ }
+ Session.Sync();
+ DateTime end = DateTime.Now;
+
+ // Report to publisher.
+ message.DeliveryProperties.SetRoutingKey("pub_done");
+ message.ClearData();
+ double time = end.Subtract(start).TotalMilliseconds;
+ byte[] rate = BitConverter.GetBytes( Options.Count / time );
+ message.AppendData(rate);
+ Session.MessageTransfer("amq.direct", message);
+ if (Options.Tx > 0)
+ {
+ Session.TxSelect();
+ Session.Sync();
+ }
+ }
+ Session.Close();
+ }
+ }
+
+ public class Controller : PerfTestClient
+ {
+ public Controller(Options options)
+ : base(options)
+ {
+ }
+
+ private void process(int size, string queue)
+ {
+ CircularBuffer<IMessage> buffer = new CircularBuffer<IMessage>(100);
+ IMessageListener listener = new SyncListener(buffer);
+ string localQueue = "queue-" + UUID.RandomUuid();
+ Session.QueueDeclare(localQueue, null, null, Option.AUTO_DELETE);
+ Session.ExchangeBind(localQueue, "amq.direct", queue);
+ Session.AttachMessageListener(listener, localQueue);
+ Session.MessageSubscribe(localQueue);
+ for (int i = 0; i < size; ++i)
+ {
+ buffer.Dequeue();
+ }
+ }
+
+ private double processRate(int size, string queue)
+ {
+ CircularBuffer<IMessage> buffer = new CircularBuffer<IMessage>(100);
+ IMessageListener listener = new SyncListener(buffer);
+ string localQueue = "queue-" + UUID.RandomUuid();
+ Session.QueueDeclare(localQueue, null, null, Option.AUTO_DELETE);
+ Session.ExchangeBind(localQueue, "amq.direct", queue);
+ Session.AttachMessageListener(listener, localQueue);
+ Session.MessageSubscribe(localQueue);
+ double rate = 0;
+ RangeSet range = new RangeSet();
+ for (int i = 0; i < size; ++i)
+ {
+ IMessage m = buffer.Dequeue();
+ range.Add(m.Id);
+ BinaryReader reader = new BinaryReader(m.Body, Encoding.UTF8);
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ rate += BitConverter.ToDouble(body,0);
+ }
+ Session.MessageAccept(range);
+ return rate;
+ }
+
+ private void send(int size, string queue, string data)
+ {
+ IMessage message = new Message();
+ message.DeliveryProperties.SetRoutingKey(queue);
+ message.AppendData(Encoding.UTF8.GetBytes(data));
+ for (int i = 0; i < size; ++i)
+ {
+ Session.MessageTransfer("amq.direct", message);
+ }
+ }
+
+ public override void Start()
+ {
+ process(Options.Subs, "sub_ready");
+ for (int j = 0; j < Options.Iterations; ++j)
+ {
+ DateTime start = DateTime.Now;
+ send(Options.Pubs, "pub_start", "start"); // Start publishers
+ double pubrate = processRate(Options.Pubs, "pub_done");
+ double subrate = processRate(Options.Subs, "sub_done");
+ DateTime end = DateTime.Now;
+
+ double transfers = (Options.Pubs*Options.Count) + (Options.Subs*Options.SubQuota);
+ double time = end.Subtract(start).TotalSeconds;
+ double txrate = transfers/time;
+ double mbytes = (txrate*Options.Size) / (1024 * 1024) ;
+
+ Console.WriteLine("Total: " + transfers + " transfers of " + Options.Size + " bytes in "
+ + time + " seconds.\n" +
+ "Publish transfers/sec: " + pubrate * 1000 + "\n" +
+ "Subscribe transfers/sec: " + subrate * 1000 + "\n" +
+ "Total transfers/sec: " + txrate + "\n" +
+ "Total Mbytes/sec: " + mbytes);
+ Console.WriteLine("done");
+ }
+
+ }
+ }
+
+
+ public class PerfTest
+ {
+ private static int Main(string[] args)
+ {
+ Options options = new Options();
+ CommandLineParser parser = new CommandLineParser(options);
+ parser.Parse();
+ if (parser.HasErrors)
+ {
+ Console.WriteLine(parser.UsageInfo.GetErrorsAsString(78));
+ return -1;
+ }
+ if (options.Help)
+ {
+ Console.WriteLine(parser.UsageInfo.GetOptionsAsString(78));
+ return 0;
+ }
+ bool singleProcess =
+ (!options.Setup && !options.Control && !options.Publish && !options.Subscribe);
+ if (singleProcess)
+ {
+ options.Setup = options.Control = options.Publish = true;
+ options.Subscribe = true;
+ }
+
+
+ string exchange = "amq.direct";
+ switch (options.Mode)
+ {
+ case "shared":
+ options.SubQuota = (options.Pubs*options.Count)/options.Subs;
+ break;
+ case "fanout":
+ options.SubQuota = (options.Pubs*options.Count);
+ exchange = "amq.fanout";
+ break;
+ case "topic":
+ options.SubQuota = (options.Pubs*options.Count);
+ exchange = "amq.topic";
+ break;
+ }
+
+ if (options.Setup)
+ {
+ SetupTest setup = new SetupTest(options);
+ setup.Start(); // Set up queues
+ }
+
+ Thread contT = null;
+ if ( options.Control)
+ {
+ Controller c = new Controller(options);
+ contT = new Thread(c.Start);
+ contT.Start();
+ }
+
+ Thread[] publishers = null;
+ Thread[] subscribers = null;
+
+ // Start pubs/subs for each queue/topic.
+ for (int i = 0; i < options.Queues; ++i)
+ {
+ string key = "perftest" + i; // Queue or topic name.
+ if (options.Publish)
+ {
+ int n = singleProcess ? options.Pubs : 1;
+ publishers = new Thread[n];
+ for (int j = 0; j < n; ++j)
+ {
+ PublishThread pt = new PublishThread(options, key, exchange);
+ publishers[i] = new Thread(pt.Start);
+ publishers[i].Start();
+ }
+ }
+ if ( options.Subscribe)
+ {
+ int n = singleProcess ? options.Subs : 1;
+ subscribers = new Thread[n];
+ for (int j = 0; j < n; ++j)
+ {
+ SubscribeThread st;
+ if (options.Mode.Equals("shared"))
+ st = new SubscribeThread(options, key);
+ else
+ st = new SubscribeThread(options, key, exchange);
+ subscribers[i] = new Thread(st.Start);
+ subscribers[i].Start();
+ }
+ }
+ }
+
+ if (options.Control)
+ {
+ contT.Join();
+ }
+
+
+ // Wait for started threads.
+ if (options.Publish)
+ {
+ foreach (Thread t in publishers)
+ {
+ t.Join();
+ }
+ }
+
+ if (options.Subscribe)
+ {
+ foreach (Thread t in subscribers)
+ {
+ t.Join();
+ }
+ }
+
+
+ return 0;
+ }
+ }
+}
diff --git a/dotnet/client-010/perftest/Properties/AssemblyInfo.cs b/dotnet/client-010/perftest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..415ad1f1ae
--- /dev/null
+++ b/dotnet/client-010/perftest/Properties/AssemblyInfo.cs
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("perftest")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("perftest")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("11b542db-0d57-4a67-8b92-24ac1d4ed4cf")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/perftest/README.txt b/dotnet/client-010/perftest/README.txt
new file mode 100644
index 0000000000..1c920a30b6
--- /dev/null
+++ b/dotnet/client-010/perftest/README.txt
@@ -0,0 +1,38 @@
+There are two ways to use perftest:
+- single process:
+If none of the -Setup, -Publish, -Subscribe or -Control options are given perftest will run a single-process test.
+- multi-process:
+For a multi-process test first run:
+Perftest.exe -Setup <other options>
+and wait for it to complete. The remaining process should run concurrently:
+Run -Pubs times: Perftest.exe -Publish <other options>
+Run -Subs times: Perftest.exe -Subscribe <other options>
+Run once: Perftest.exe -Control <other options>
+Note the <other options> must be identical for all processes.
+
+Options:
+ -Broker Specifies the broler name
+ -Confirm Publisher use confirm-mode.
+ -Control Run test, print report.
+ -Count Each publisher sends N messages.
+ -Durable Publish messages as durable.
+ -Help Displays this help text
+ -IntervalPub >=0 delay between msg publish.
+ -IntervalSub >=0 delay between msg consume
+ -Iterations Desired number of iterations of the test.
+ -Mode Test mode: [shared|fanout|topic]
+ -Port Specifies the port name
+ -Publish Publish messages.
+ -Pubs Create N publishers.
+ -QueueDurable Make queue durable (implied if durable set.
+ -QueueMaxCount Queue policy: count to trigger 'flow to disk'
+ -QueueMaxSize Queue policy: accumulated size to trigger 'flow to disk'
+ -Queues Create N queues.
+ -Setup Create shared queues.
+ -Size Size of messages in bytes.
+ -SubAck N>0: Subscriber acks batches of N. N==0: Subscriber uses unconfirmed mode
+ -Subs Create N subscribers.
+ -Subscribe Subscribe for messages.
+ -SyncPub Wait for confirmation of each message before sending the next one.
+ -Tx If non-zero, the transaction batch size.
+ -UniqueData Make data for each message unique. \ No newline at end of file
diff --git a/dotnet/client-010/perftest/default.build b/dotnet/client-010/perftest/default.build
new file mode 100644
index 0000000000..756f6c6493
--- /dev/null
+++ b/dotnet/client-010/perftest/default.build
@@ -0,0 +1,50 @@
+<?xml version="1.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.
+
+-->
+
+<project name="perftest" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="exe"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.exe">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ <include name="${build.dir}/C5.dll" />
+ <include name="${build.dir}/Plossum CommandLine.dll" />
+ </references>
+ </csc>
+ </target>
+
+</project>
+
diff --git a/dotnet/client-010/perftest/perftest.csproj b/dotnet/client-010/perftest/perftest.csproj
new file mode 100644
index 0000000000..90136f18bb
--- /dev/null
+++ b/dotnet/client-010/perftest/perftest.csproj
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7F7E8DE7-FDF2-4A52-A4CE-D3756B05273C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>perftest</RootNamespace>
+ <AssemblyName>perftest</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="C5, Version=1.0.2.0, Culture=neutral, PublicKeyToken=06a1b38866503b69, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\plossum\C5.dll</HintPath>
+ </Reference>
+ <Reference Include="Plossum CommandLine, Version=0.3.0.14, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\plossum\Plossum CommandLine.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="PerfTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/dotnet/client-010/test/Helpers/ConfigHelpers.cs b/dotnet/client-010/test/Helpers/ConfigHelpers.cs
new file mode 100644
index 0000000000..883e52c264
--- /dev/null
+++ b/dotnet/client-010/test/Helpers/ConfigHelpers.cs
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+using log4net.Config;
+
+namespace test.Helpers
+{
+ class ConfigHelpers
+ {
+ public static Dictionary<string, string> LoadConfig()
+ {
+ Dictionary<string, string> properties = new Dictionary<string, string>();
+
+ XmlConfigurator.Configure(new FileInfo("/log.xml"));
+ // populate default properties
+ properties.Add("Username", "guest");
+ properties.Add("Password", "guest");
+ properties.Add("Host", "localhost");
+ properties.Add("Port", "5672");
+ properties.Add("VirtualHost", "test");
+ //Read the test config file
+ XmlTextReader reader = new XmlTextReader(Environment.CurrentDirectory + "/Qpid Test.dll.config");
+ while (reader.Read())
+ {
+ // if node type is an element
+ if (reader.NodeType == XmlNodeType.Element && reader.Name.Equals("add"))
+ {
+ if (properties.ContainsKey(reader.GetAttribute("key")))
+ {
+ properties[reader.GetAttribute("key")] = reader.GetAttribute("value");
+ }
+ else
+ {
+ properties.Add(reader.GetAttribute("key"), reader.GetAttribute("value"));
+ }
+ }
+ }
+
+ return properties;
+ }
+ }
+}
diff --git a/dotnet/client-010/test/Properties/AssemblyInfo.cs b/dotnet/client-010/test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..871d450240
--- /dev/null
+++ b/dotnet/client-010/test/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid Test")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid Test")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3d62cb4f-4353-4eed-9669-3e1bc902081d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/test/Qpid Test.dll.config b/dotnet/client-010/test/Qpid Test.dll.config
new file mode 100644
index 0000000000..2a2fb72b61
--- /dev/null
+++ b/dotnet/client-010/test/Qpid Test.dll.config
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <appSettings>
+ <add key="UserMame" value="guest"/>
+ <add key="Password" value="guest"/>
+ <add key="Host" value="localhost"/>
+ <add key="Port" value="5672"/>
+ <add key="VirtualHost" value="test"/>
+ </appSettings>
+</configuration>
diff --git a/dotnet/client-010/test/Test.csproj b/dotnet/client-010/test/Test.csproj
new file mode 100644
index 0000000000..a9cd7c18af
--- /dev/null
+++ b/dotnet/client-010/test/Test.csproj
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95CB4C90-7C53-44A9-B11C-96235F158ACA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>test</RootNamespace>
+ <AssemblyName>Qpid Test</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\log4net\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="interop\ConnectionTests.cs" />
+ <Compile Include="Helpers\ConfigHelpers.cs" />
+ <Compile Include="interop\Admin.cs" />
+ <Compile Include="interop\ApplicationHeaders.cs" />
+ <Compile Include="interop\Message.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="interop\TestCase.cs" />
+ <Compile Include="transport\util\ByteEncoderTest.cs" />
+ <Compile Include="transport\util\CircularBufferTest.cs" />
+ <Compile Include="transport\util\ResultFutureTest.cs" />
+ <Compile Include="transport\util\SerialTest.cs" />
+ <Compile Include="transport\util\UUIDTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\client\Client.csproj">
+ <Project>{B911FFD7-754F-4735-A188-218D5065BE79}</Project>
+ <Name>Client</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\App.config">
+ <Link>App.config</Link>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/test/default.build b/dotnet/client-010/test/default.build
new file mode 100644
index 0000000000..f9dadb174b
--- /dev/null
+++ b/dotnet/client-010/test/default.build
@@ -0,0 +1,55 @@
+<?xml version="1.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.
+
+-->
+
+<project name="qpid.client.tests" default="build">
+ <!--
+ Properties that come from master build file
+ - build.dir: root directory for build
+ - build.debug: true if building debug release
+ - build.defines: variables to define during build
+ -->
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/log4net.dll" />
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/qpid.client.dll" />
+ </references>
+ </csc>
+ </target>
+
+ <target name="test" depends="build">
+ <nunit2>
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test assemblyname="${build.dir}/qpid.client.tests.dll" />
+ </nunit2>
+ </target>
+</project>
+
diff --git a/dotnet/client-010/test/interop/Admin.cs b/dotnet/client-010/test/interop/Admin.cs
new file mode 100644
index 0000000000..163e4cf49a
--- /dev/null
+++ b/dotnet/client-010/test/interop/Admin.cs
@@ -0,0 +1,90 @@
+/*
+*
+* 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.
+*
+*/
+
+using NUnit.Framework;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace test.interop
+{
+ public class Admin : TestCase
+ {
+ private static readonly Logger _log = Logger.Get(typeof(Admin));
+
+ [Test]
+ public void createSession()
+ {
+ _log.Debug("Running: CreateSession");
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.Close();
+ // This test fails if an exception is thrown
+ }
+
+ [Test]
+ public void queueLifecycle()
+ {
+ _log.Debug("Running: queueLifecycle");
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.Sync();
+ ssn.QueueDelete("queue1");
+ ssn.Sync();
+ try
+ {
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+ ssn.Sync();
+ }
+ catch (SessionException)
+ {
+ // as expected
+ }
+ // This test fails if an exception is thrown
+ }
+
+ [Test]
+ public void exchangeCheck()
+ {
+ _log.Debug("Running: exchangeCheck");
+ IClientSession ssn = Client.CreateSession(0);
+ ExchangeQueryResult query = (ExchangeQueryResult) ssn.ExchangeQuery("amq.direct").Result;
+ Assert.IsFalse(query.GetNotFound());
+ Assert.IsTrue(query.GetDurable());
+ query = (ExchangeQueryResult)ssn.ExchangeQuery("amq.topic").Result;
+ Assert.IsFalse(query.GetNotFound());
+ Assert.IsTrue(query.GetDurable());
+ query = (ExchangeQueryResult) ssn.ExchangeQuery("foo").Result;
+ Assert.IsTrue(query.GetNotFound());
+ }
+
+ [Test]
+ public void exchangeBind()
+ {
+ _log.Debug("Running: ExchangeBind");
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+ // This test fails if an exception is thrown
+ }
+
+
+ }
+}
diff --git a/dotnet/client-010/test/interop/ApplicationHeaders.cs b/dotnet/client-010/test/interop/ApplicationHeaders.cs
new file mode 100644
index 0000000000..d932057fd2
--- /dev/null
+++ b/dotnet/client-010/test/interop/ApplicationHeaders.cs
@@ -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.
+*
+*/
+using System;
+using common.org.apache.qpid.transport.util;
+using NUnit.Framework;
+using org.apache.qpid.client;
+using org.apache.qpid.transport.util;
+
+namespace test.interop
+{
+ public class ApplicationHeaders:TestCase
+ {
+ private static readonly Logger _log = Logger.Get(typeof(ApplicationHeaders));
+
+ [Test]
+ public void setHeaders()
+ {
+ _log.Debug("Running: setHeaders");
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.QueueDeclare("queue1");
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1");
+ ssn.Sync();
+ CircularBuffer<IMessage> buff = new CircularBuffer<IMessage>(10);
+ SyncListener listener = new SyncListener(ssn, buff);
+ ssn.AttachMessageListener(listener, "queue1");
+ ssn.MessageSubscribe("queue1");
+
+ IMessage message = new org.apache.qpid.client.Message();
+ message.DeliveryProperties.SetRoutingKey("queue1");
+ const long someLong = 14444444;
+ message.ApplicationHeaders.Add("someLong", someLong);
+ const int someInt = 14;
+ message.ApplicationHeaders.Add("soneInt", someInt);
+ const float someFloat = 14.001F;
+ message.ApplicationHeaders.Add("soneFloat", someFloat);
+ const double someDouble = 14.5555555;
+ message.ApplicationHeaders.Add("someDouble", someDouble);
+ const byte someByte = 2;
+ message.ApplicationHeaders.Add("someByte", someByte);
+ const string someString = "someString";
+ message.ApplicationHeaders.Add("someString", someString);
+ const char someChar = 'a';
+ message.ApplicationHeaders.Add("someChar", someChar);
+ const Boolean someBoolean = true;
+ message.ApplicationHeaders.Add("someBoolean", someBoolean);
+
+ // transfer the message
+ ssn.MessageTransfer("amq.direct", message);
+
+ // get the message and check the headers
+ IMessage messageBack = buff.Dequeue();
+ Assert.IsTrue(((string) messageBack.ApplicationHeaders["someString"]).Equals(someString));
+ Assert.IsTrue(((char)messageBack.ApplicationHeaders["someChar"]).Equals(someChar));
+ Assert.IsTrue((long)messageBack.ApplicationHeaders["someLong"] == someLong);
+ Assert.IsTrue((int)messageBack.ApplicationHeaders["soneInt"] == someInt);
+ Assert.IsTrue((double)messageBack.ApplicationHeaders["someDouble"] == someDouble);
+ Assert.IsTrue((byte) messageBack.ApplicationHeaders["someByte"] == someByte);
+ Assert.IsTrue((Boolean)messageBack.ApplicationHeaders["someBoolean"]);
+ // c# has an conversion precision issue with decimal
+ Assert.IsTrue((float) messageBack.ApplicationHeaders["soneFloat"] <= someFloat);
+ float b = (float) messageBack.ApplicationHeaders["soneFloat"];
+ Assert.IsTrue(Convert.ToInt32(b) == Convert.ToInt32(someFloat));
+ }
+ }
+}
diff --git a/dotnet/client-010/test/interop/ConnectionTests.cs b/dotnet/client-010/test/interop/ConnectionTests.cs
new file mode 100644
index 0000000000..37fd0e7933
--- /dev/null
+++ b/dotnet/client-010/test/interop/ConnectionTests.cs
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Net.Sockets;
+using NUnit.Framework;
+using org.apache.qpid.client;
+using test.Helpers;
+
+namespace test
+{
+ [TestFixture]
+ public class ConnectionTests
+ {
+ [SetUp]
+ public void Setup()
+ {
+
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void should_raise_exception_in_calling_thread_on_authentification_failure()
+ {
+ var properties = ConfigHelpers.LoadConfig();
+
+ var client = new Client();
+ client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"],
+ properties["Username"], "some silly password to make sure the authentification fail");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void should_raise_exception_in_calling_thread_on_authentification_failure_with_clodedListener()
+ {
+ var properties = ConfigHelpers.LoadConfig();
+
+ var client = new Client();
+ client.ClosedListener = new FakeListener();
+ client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"],
+ properties["Username"], "some silly password to make sure the authentification fail");
+ }
+
+ [Test]
+ public void should_not_block_on_close()
+ {
+ var properties = ConfigHelpers.LoadConfig();
+
+ var client = new Client();
+ client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"],
+ properties["Username"], properties["Password"]);
+ client.Close();
+ }
+ }
+
+ public class FakeListener : IClosedListener
+ {
+ public void OnClosed(ErrorCode errorCode, string reason, Exception t)
+ {
+ }
+ }
+}
diff --git a/dotnet/client-010/test/interop/Message.cs b/dotnet/client-010/test/interop/Message.cs
new file mode 100644
index 0000000000..107e69c287
--- /dev/null
+++ b/dotnet/client-010/test/interop/Message.cs
@@ -0,0 +1,180 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using System.Text;
+using System.Threading;
+using NUnit.Framework;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace test.interop
+{
+ public class Message : TestCase
+ {
+ private static readonly Logger _log = Logger.Get(typeof (Message));
+
+ [Test]
+ public void sendAndPurge()
+ {
+ _log.Debug("Running: ExchangeBind");
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.QueueDelete("queue1");
+ QueueQueryResult result = (QueueQueryResult) ssn.QueueQuery("queue1").Result;
+ Assert.IsNull(result.GetQueue());
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+
+ for (int i = 0; i < 10; i++)
+ {
+ ssn.MessageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().SetRoutingKey("queue1"),
+ new MessageProperties().SetMessageId(UUID.RandomUuid())),
+ Encoding.UTF8.GetBytes("test: " + i));
+ }
+ ssn.Sync();
+ result = (QueueQueryResult) ssn.QueueQuery("queue1").Result;
+ Assert.IsTrue(result.GetMessageCount() == 10);
+ ssn.QueuePurge("queue1");
+ ssn.Sync();
+ result = (QueueQueryResult) ssn.QueueQuery("queue1").Result;
+ Assert.IsTrue(result.GetMessageCount() == 0);
+ }
+
+ [Test]
+ public void sendAndReceiveSmallMessages()
+ {
+ _log.Debug("Running: sendAndReceiveSmallMessages");
+ byte[] smallMessage = Encoding.UTF8.GetBytes("test");
+ sendAndReceive(smallMessage, 100);
+ }
+
+ [Test]
+ public void sendAndReceiveLargeMessages()
+ {
+ _log.Debug("Running: sendAndReceiveSmallMessages");
+ byte[] largeMessage = new byte[100 * 1024];
+ Random random = new Random();
+ random.NextBytes(largeMessage);
+ sendAndReceive(largeMessage, 10);
+ }
+
+ [Test]
+ public void sendAndReceiveVeryLargeMessages()
+ {
+ _log.Debug("Running: sendAndReceiveSmallMessages");
+ byte[] verylargeMessage = new byte[1000 * 1024];
+ Random random = new Random();
+ random.NextBytes(verylargeMessage);
+ sendAndReceive(verylargeMessage, 2);
+ }
+
+ private void sendAndReceive(byte[] messageBody, int count)
+ {
+ IClientSession ssn = Client.CreateSession(0);
+ ssn.Sync();
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.QueueDelete("queue1");
+ QueueQueryResult result = (QueueQueryResult) ssn.QueueQuery("queue1").Result;
+ Assert.IsNull(result.GetQueue());
+ ssn.QueueDeclare("queue1", null, null);
+ ssn.ExchangeBind("queue1", "amq.direct", "queue1", null);
+ Object myLock = new Object();
+ MyListener myListener = new MyListener(myLock, count);
+ ssn.AttachMessageListener(myListener, "myDest");
+
+ ssn.MessageSubscribe("queue1", "myDest", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED, null,
+ 0, null);
+
+
+ // issue credits
+ ssn.MessageSetFlowMode("myDest", MessageFlowMode.WINDOW);
+ ssn.MessageFlow("myDest", MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ ssn.MessageFlow("myDest", MessageCreditUnit.MESSAGE, 10000);
+ ssn.Sync();
+
+ for (int i = 0; i < count; i++)
+ {
+ ssn.MessageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().SetRoutingKey("queue1"),
+ new MessageProperties().SetMessageId(UUID.RandomUuid())),
+ messageBody);
+ }
+ ssn.Sync();
+
+ lock (myLock)
+ {
+ if (myListener.Count != 0)
+ {
+ Monitor.Wait(myLock, 10000000);
+ }
+ }
+ Assert.IsTrue(myListener.Count == 0);
+ ssn.MessageAccept(myListener.UnAck);
+ ssn.Sync();
+ // the queue should be empty
+ result = (QueueQueryResult)ssn.QueueQuery("queue1").Result;
+ Assert.IsTrue(result.GetMessageCount() == 0);
+ ssn.Close();
+ }
+
+
+
+ private class MyListener : IMessageListener
+ {
+ private static readonly Logger _log = Logger.Get(typeof (MyListener));
+ private readonly Object _wl;
+ private int _count;
+ private RangeSet _rs = new RangeSet();
+
+ public MyListener(Object wl, int count)
+ {
+ _wl = wl;
+ _count = count;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ byte[] body = new byte[m.Body.Length - m.Body.Position];
+ _log.Debug("Got a message of size: " + body.Length + " count = " + _count);
+ _rs.Add(m.Id);
+ lock (_wl)
+ {
+ _count--;
+ if (_count == 0)
+ {
+ Monitor.PulseAll(_wl);
+ }
+ }
+ }
+
+ public int Count
+ {
+ get { return _count; }
+ }
+
+ public RangeSet UnAck
+ {
+ get { return _rs; }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/test/interop/TestCase.cs b/dotnet/client-010/test/interop/TestCase.cs
new file mode 100644
index 0000000000..867f082000
--- /dev/null
+++ b/dotnet/client-010/test/interop/TestCase.cs
@@ -0,0 +1,96 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Xml;
+using common.org.apache.qpid.transport.util;
+using log4net.Config;
+using NUnit.Framework;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+using test.Helpers;
+
+namespace test.interop
+{
+ [TestFixture]
+
+ public class TestCase
+ {
+ private readonly Dictionary<string,string> _properties = new Dictionary<string, string>();
+ private Client _client;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ var properties = ConfigHelpers.LoadConfig();
+ // create a client and connect to the broker
+ _client = new Client();
+ _client.Connect(properties["Host"], Convert.ToInt16(properties["Port"]), properties["VirtualHost"],
+ properties["Username"], properties["Password"]);
+
+ }
+
+ [TestFixtureTearDown]
+ public void Cleanup()
+ {
+ // Note : breaks the Resharper nunit test runner. It blocks on the Monitor.WaitAll()
+ // Certainly a problem with the threading context..
+ //_client.Close();
+ }
+
+ public Client Client
+ {
+ get{ return _client;}
+ }
+
+ public Dictionary<string,string> Properties
+ {
+ get { return _properties; }
+ }
+
+
+ public class SyncListener : IMessageListener
+ {
+ private static readonly Logger _log = Logger.Get(typeof(SyncListener));
+ private readonly CircularBuffer<IMessage> _buffer;
+ private readonly RangeSet _range = new RangeSet();
+ private readonly IClientSession _session;
+
+ public SyncListener(IClientSession session, CircularBuffer<IMessage> buffer)
+ {
+ _buffer = buffer;
+ _session = session;
+ }
+
+ public void MessageTransfer(IMessage m)
+ {
+ _range.Clear();
+ _range.Add(m.Id);
+ _session.MessageAccept(_range);
+ _buffer.Enqueue(m);
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/test/transport/util/ByteEncoderTest.cs b/dotnet/client-010/test/transport/util/ByteEncoderTest.cs
new file mode 100644
index 0000000000..f3a05f1c3c
--- /dev/null
+++ b/dotnet/client-010/test/transport/util/ByteEncoderTest.cs
@@ -0,0 +1,106 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using NUnit.Framework;
+using org.apache.qpid.transport.util;
+
+
+namespace test.transport.util
+{
+ [TestFixture]
+
+ public class ByteEncoderTest
+ {
+ private static readonly Logger _log = Logger.Get(typeof(ByteEncoderTest));
+
+ [Test]
+ public void GetBigEndianInt32()
+ {
+ _log.Debug("Running: GetBigEndianInt32");
+ const int anInt = -12345;
+ Int32 aNewInt = ByteEncoder.GetBigEndian(anInt);
+ Assert.IsTrue( anInt == ByteEncoder.GetBigEndian(aNewInt) );
+ }
+
+ [Test]
+ public void GetBigEndianUInt16()
+ {
+ _log.Debug("Running: GetBigEndianUInt16");
+ const UInt16 anInt = 123;
+ UInt16 aNewInt = ByteEncoder.GetBigEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetBigEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetBigEndianUInt32()
+ {
+ _log.Debug("Running: GetBigEndianUInt32");
+ const UInt32 anInt = 12345;
+ UInt32 aNewInt = ByteEncoder.GetBigEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetBigEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetBigEndianlong()
+ {
+ _log.Debug("Running: GetBigEndianlong");
+ const long anInt = 123456660700770;
+ long aNewInt = ByteEncoder.GetBigEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetBigEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetLittleEndianInt32()
+ {
+ _log.Debug("Running: GetBigEndianInt32");
+ const int anInt = -12345;
+ Int32 aNewInt = ByteEncoder.GetLittleEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetLittleEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetLittleEndianUInt16()
+ {
+ _log.Debug("Running: GetLittleEndianUInt16");
+ const UInt16 anInt = 123;
+ UInt16 aNewInt = ByteEncoder.GetLittleEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetLittleEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetLittleEndianUInt32()
+ {
+ _log.Debug("Running: GetLittleEndianUInt32");
+ const UInt32 anInt = 12345;
+ UInt32 aNewInt = ByteEncoder.GetLittleEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetLittleEndian(aNewInt));
+ }
+
+ [Test]
+ public void GetLittleEndianlong()
+ {
+ _log.Debug("Running: GetLittleEndianlong");
+ const long anInt = 123456660700770;
+ long aNewInt = ByteEncoder.GetLittleEndian(anInt);
+ Assert.IsTrue(anInt == ByteEncoder.GetLittleEndian(aNewInt));
+ }
+ }
+}
diff --git a/dotnet/client-010/test/transport/util/CircularBufferTest.cs b/dotnet/client-010/test/transport/util/CircularBufferTest.cs
new file mode 100644
index 0000000000..5e39569cf8
--- /dev/null
+++ b/dotnet/client-010/test/transport/util/CircularBufferTest.cs
@@ -0,0 +1,89 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Threading;
+using common.org.apache.qpid.transport.util;
+using NUnit.Framework;
+using org.apache.qpid.transport.util;
+
+namespace test.transport.util
+{
+ [TestFixture]
+
+ public class CircularBufferTest
+ {
+ private CircularBuffer<Object> _buf;
+ private static readonly Logger _log = Logger.Get(typeof(CircularBufferTest));
+
+ [Test]
+ public void BlockingEnqueue()
+ {
+ _log.Debug("Running: BlockingEnqueue");
+ const int size = 10;
+ _buf = new CircularBuffer<Object>(size);
+ // add size element anc check that the size +1 add blocks
+ for (int i = 1; i < size; i++ )
+ {
+ _buf.Enqueue(new object());
+ }
+ // check tha the buffer is now full
+ Thread t = new Thread(Go);
+ t.Start();
+ Thread.Sleep(100);
+ // the trhead t should block until an element is dequeued
+ Assert.IsTrue(t.ThreadState == ThreadState.WaitSleepJoin);
+ _buf.Dequeue();
+ // t should now be stopped
+ Thread.Sleep(100);
+ Assert.IsTrue(t.ThreadState == ThreadState.Stopped);
+ }
+
+ [Test]
+ public void Close()
+ {
+ _log.Debug("Running: BlockingEnqueue");
+ const int size = 10;
+ _buf = new CircularBuffer<Object>(size);
+ // add size element anc check that the size +1 add blocks
+ for (int i = 1; i < size; i++)
+ {
+ _buf.Enqueue(new object());
+ }
+ // check tha the buffer is now full
+ Thread t = new Thread(Go);
+ t.Start();
+ Thread.Sleep(1000);
+ // the trhead t should block until the buffer is closed
+ Assert.IsTrue(t.ThreadState == ThreadState.WaitSleepJoin);
+ _buf.Close();
+ Thread.Sleep(100);
+ // t should now be stopped
+ Assert.IsTrue(t.ThreadState == ThreadState.Stopped);
+ }
+
+ void Go()
+ {
+ _buf.Enqueue(new object());
+ }
+
+ }
+}
diff --git a/dotnet/client-010/test/transport/util/ResultFutureTest.cs b/dotnet/client-010/test/transport/util/ResultFutureTest.cs
new file mode 100644
index 0000000000..e8e011a1e9
--- /dev/null
+++ b/dotnet/client-010/test/transport/util/ResultFutureTest.cs
@@ -0,0 +1,103 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using common.org.apache.qpid.transport.util;
+using NUnit.Framework;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.codec;
+using org.apache.qpid.transport.util;
+
+
+namespace test.transport.util
+{
+ [TestFixture]
+ public class ResultFutureTest
+ {
+ private static readonly Logger _log = Logger.Get(typeof (ByteEncoderTest));
+ private static ResultFuture _future;
+
+ [Test]
+ public void getFutureTimeout()
+ {
+ _log.Debug("Running: getFutureTimeout");
+ _future = new ResultFuture();
+ _future.Session = new Session(new byte[1]);
+ DateTime start = DateTime.Now;
+ Struct result = _future.Get(1000);
+ Assert.IsTrue(DateTime.Now.Subtract(start).TotalMilliseconds >= 1000);
+ Assert.IsNull(result);
+ }
+
+ [Test]
+ public void getFuture()
+ {
+ _log.Debug("Running: getFuture");
+ _future = new ResultFuture();
+ _future.Session = new Session(new byte[1]);
+ Thread t = new Thread(Go);
+ t.Start();
+ Struct result = _future.Get(2000);
+ Assert.IsNotNull(result);
+ }
+
+
+ void Go()
+ {
+ Thread.Sleep(500);
+ _future.Result = new myStruct();
+ }
+ }
+
+ public class myStruct:Struct
+ {
+ public override int GetStructType()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override int GetSizeWidth()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override int GetPackWidth()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override void Read(IDecoder dec)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override void Write(IEncoder enc)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public override Dictionary<string, object> Fields
+ {
+ get { throw new System.NotImplementedException(); }
+ }
+ }
+}
diff --git a/dotnet/client-010/test/transport/util/SerialTest.cs b/dotnet/client-010/test/transport/util/SerialTest.cs
new file mode 100644
index 0000000000..772327c3b0
--- /dev/null
+++ b/dotnet/client-010/test/transport/util/SerialTest.cs
@@ -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.
+*
+*/
+using NUnit.Framework;
+using org.apache.qpid.transport.util;
+
+namespace test.transport.util
+{
+ [TestFixture]
+ public class SerialTest
+ {
+ private static readonly Logger _log = Logger.Get(typeof (SerialTest));
+
+ [Test]
+ ///
+ /// Test the key boundaries where wraparound occurs.
+ ///
+ public void testBoundaries()
+ {
+ Assert.IsTrue(Serial.Gt(1, 0));
+ Assert.IsTrue(Serial.Lt(0, 1));
+
+ Assert.IsTrue(Serial.Gt(int.MaxValue, int.MaxValue - 1));
+ Assert.IsTrue(Serial.Lt(int.MaxValue - 1, int.MaxValue));
+ }
+
+ ///
+ /// Test the first Corollary of RFC 1982
+ /// For any sequence number s and any integer n such that addition of n
+ /// to s is well defined, (s + n) >= s. Further (s + n) == s only when
+ /// n == 0, in all other defined cases, (s + n) > s.
+ ///
+ public void testCorollary1()
+ {
+ int wrapcount = 0;
+
+ int s = 0;
+
+ for (int i = 0; i < 67108664; i++)
+ {
+ for (int n = 1; n < 4096; n += 512)
+ {
+ Assert.IsTrue(Serial.Gt(s + n, s));
+ Assert.IsTrue(Serial.Lt(s, s + n));
+ }
+
+ s += 1024;
+
+ if (s == 0)
+ {
+ wrapcount += 1;
+ }
+ }
+
+ Assert.IsTrue(wrapcount > 0);
+ }
+ }
+}
diff --git a/dotnet/client-010/test/transport/util/UUIDTest.cs b/dotnet/client-010/test/transport/util/UUIDTest.cs
new file mode 100644
index 0000000000..41104f8873
--- /dev/null
+++ b/dotnet/client-010/test/transport/util/UUIDTest.cs
@@ -0,0 +1,64 @@
+/*
+*
+* 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.
+*
+*/
+using System;
+using NUnit.Framework;
+using org.apache.qpid.transport.util;
+
+namespace test.transport.util
+{
+ [TestFixture]
+
+ public class UUIDTest
+ {
+
+
+ [Test]
+ public void createUUID()
+ {
+ UUID uuid = UUID.RandomUuid();
+ String uuidStr = uuid.ToString();
+ Assert.IsNotNull(uuid);
+ UUID uuid2 = UUID.RandomUuid();
+ Assert.AreNotSame(uuid, uuid2);
+ }
+
+ [Test]
+ public void ToString_should_override_and_not_hide_base()
+ {
+ UUID uuid = UUID.RandomUuid();
+
+ string uuidStr = uuid.ToString();
+ string uuidConcat = "Test." + uuid;
+
+ Assert.AreEqual("Test." + uuidStr, uuidConcat);
+ }
+
+ [Test]
+ public void two_uuid_with_same_value_should_have_same_hash_code()
+ {
+ UUID uuid = UUID.RandomUuid();
+ UUID uuid2 = new UUID(uuid.MostSignificantBits, uuid.LeastSignificantBits);
+
+ Assert.AreEqual(uuid, uuid2);
+ Assert.AreEqual(uuid.GetHashCode(), uuid2.GetHashCode());
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..66f2bb1268
--- /dev/null
+++ b/dotnet/client-010/wcf/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid WCF")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid WCF")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a39d56ec-7d81-48e1-9602-347a3ce6f638")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/ConfigDemo.suo b/dotnet/client-010/wcf/demo/ConfigDemo.suo
new file mode 100644
index 0000000000..baa935693b
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/ConfigDemo.suo
Binary files differ
diff --git a/dotnet/client-010/wcf/demo/Demo.suo b/dotnet/client-010/wcf/demo/Demo.suo
new file mode 100644
index 0000000000..ee4cb5d21e
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/Demo.suo
Binary files differ
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.Designer.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.Designer.cs
new file mode 100644
index 0000000000..9ec3a08359
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.Designer.cs
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+namespace WindowsFormsBooking
+{
+ partial class Form1
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.comboBox1 = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+ this.label2 = new System.Windows.Forms.Label();
+ this.button1 = new System.Windows.Forms.Button();
+ this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+ this.button2 = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // comboBox1
+ //
+ this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboBox1.FormattingEnabled = true;
+ this.comboBox1.Items.AddRange(new object[] {
+ "Hotel",
+ "Taxi",
+ "Train",
+ "Cinema",
+ "Theater",
+ "Restaurant"});
+ this.comboBox1.Location = new System.Drawing.Point(60, 20);
+ this.comboBox1.Name = "comboBox1";
+ this.comboBox1.Size = new System.Drawing.Size(76, 21);
+ this.comboBox1.TabIndex = 0;
+ this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(23, 20);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(31, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Type";
+ //
+ // numericUpDown1
+ //
+ this.numericUpDown1.Increment = new decimal(new int[] {
+ 10,
+ 0,
+ 0,
+ 0});
+ this.numericUpDown1.Location = new System.Drawing.Point(60, 49);
+ this.numericUpDown1.Maximum = new decimal(new int[] {
+ 200,
+ 0,
+ 0,
+ 0});
+ this.numericUpDown1.Minimum = new decimal(new int[] {
+ 30,
+ 0,
+ 0,
+ 0});
+ this.numericUpDown1.Name = "numericUpDown1";
+ this.numericUpDown1.Size = new System.Drawing.Size(76, 20);
+ this.numericUpDown1.TabIndex = 2;
+ this.numericUpDown1.Value = new decimal(new int[] {
+ 30,
+ 0,
+ 0,
+ 0});
+ this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(23, 56);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(31, 13);
+ this.label2.TabIndex = 3;
+ this.label2.Text = "Price";
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(142, 20);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(40, 49);
+ this.button1.TabIndex = 4;
+ this.button1.Text = "Add";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // richTextBox1
+ //
+ this.richTextBox1.ForeColor = System.Drawing.SystemColors.ControlText;
+ this.richTextBox1.Location = new System.Drawing.Point(27, 113);
+ this.richTextBox1.Name = "richTextBox1";
+ this.richTextBox1.Size = new System.Drawing.Size(155, 83);
+ this.richTextBox1.TabIndex = 5;
+ this.richTextBox1.Text = "";
+ //
+ // button2
+ //
+ this.button2.Location = new System.Drawing.Point(27, 81);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(155, 29);
+ this.button2.TabIndex = 6;
+ this.button2.Text = "Receipt";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(211, 211);
+ this.Controls.Add(this.button2);
+ this.Controls.Add(this.richTextBox1);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.numericUpDown1);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.comboBox1);
+ this.Name = "Form1";
+ this.Text = "Booking Client";
+ ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ComboBox comboBox1;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.NumericUpDown numericUpDown1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.RichTextBox richTextBox1;
+ private System.Windows.Forms.Button button2;
+ }
+}
+
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.cs
new file mode 100644
index 0000000000..89205bd6bd
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.cs
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.ServiceModel;
+using System.Windows.Forms;
+using org.apache.qpid.wcf.demo;
+using org.apache.qpid.wcf.model;
+using org.apache.qpid.wcf.demo.bookingServer;
+
+namespace WindowsFormsBooking
+{
+ public partial class Form1 : Form
+ {
+ private ChannelFactory<IBooking> _fac;
+ private readonly Order _order = new Order();
+ private IBooking _calc;
+
+ public Form1()
+ {
+ InitializeComponent();
+ _calc = StartClient(new QpidBinding("192.168.1.14", 5673));
+ _order.Type = "Default";
+ _order.Price = 0;
+ }
+
+ public IBooking StartClient(System.ServiceModel.Channels.Binding binding)
+ {
+ IBooking res = null;
+ try
+ {
+ Console.WriteLine(" Starting Client...");
+ _fac = new ChannelFactory<IBooking>(binding, "soap.amqp:///Booking");
+ _fac.Open();
+ res = _fac.CreateChannel();
+ Console.WriteLine("[DONE]");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ return res;
+ }
+
+ public void StopClient(IBooking client)
+ {
+ Console.WriteLine(" Stopping Client...");
+ ((System.ServiceModel.Channels.IChannel)client).Close();
+ _fac.Close();
+ Console.WriteLine("[DONE]");
+ }
+
+ private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ _order.Type = ((ComboBox) sender).SelectedItem.ToString();
+ }
+
+ private void numericUpDown1_ValueChanged(object sender, EventArgs e)
+ {
+ _order.Price = (double) ((NumericUpDown) sender).Value;
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ _calc.Add(_order);
+ }
+
+ private void button2_Click(object sender, EventArgs e)
+ {
+ Receipt r = _calc.Checkout();
+ richTextBox1.Text = r.Summary + "\n" + "Total Price = " + r.Price;
+ // reset
+ _calc = StartClient(new QpidBinding("192.168.1.14", 5673));
+ }
+
+
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.resx b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.resx
new file mode 100644
index 0000000000..7c6a1b6a50
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Form1.resx
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <metadata name="richTextBox1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <value>True</value>
+ </metadata>
+</root> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Program.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Program.cs
new file mode 100644
index 0000000000..59189bf600
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Program.cs
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace WindowsFormsBooking
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..be301395d3
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Booking Client")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Booking Client")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fc8b1e0e-1ca9-46fe-9aae-b1ed046716b8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.Designer.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000..42f9731a3d
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.Designer.cs
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WindowsFormsBooking.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsFormsBooking.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.resx b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.resx
new file mode 100644
index 0000000000..af03750170
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Resources.resx
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.Designer.cs b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.Designer.cs
new file mode 100644
index 0000000000..212fb91438
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.Designer.cs
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace WindowsFormsBooking.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.settings b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.settings
new file mode 100644
index 0000000000..64cfd9241c
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/Properties/Settings.settings
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
diff --git a/dotnet/client-010/wcf/demo/wcfBookingClient/wcBookingClient.csproj b/dotnet/client-010/wcf/demo/wcfBookingClient/wcBookingClient.csproj
new file mode 100644
index 0000000000..1449446ae2
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingClient/wcBookingClient.csproj
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4086B3FE-F745-4DCC-952A-682CAE01F4C9}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>WindowsFormsBooking</RootNamespace>
+ <AssemblyName>Booking Client</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Form1.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="Form1.Designer.cs">
+ <DependentUpon>Form1.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="Form1.resx">
+ <DependentUpon>Form1.cs</DependentUpon>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\wcf.csproj">
+ <Project>{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}</Project>
+ <Name>wcf</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\wcfBookingServer\wcfBookingServer.csproj">
+ <Project>{B34E21C4-A742-4886-8569-1A89490E093E}</Project>
+ <Name>wcfBookingServer</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/Booking.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/Booking.cs
new file mode 100644
index 0000000000..7c0fbb39b4
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/Booking.cs
@@ -0,0 +1,62 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ServiceModel;
+
+
+namespace org.apache.qpid.wcf.demo.bookingServer
+{
+ [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
+ public class Booking : IBooking
+ {
+ private Guid _id;
+ private List<Order> _orders;
+
+ public Booking()
+ {
+ _id = Guid.NewGuid();
+ _orders = new List<Order>();
+ }
+
+ public void Add(Order order)
+ {
+ _orders.Add(order);
+ }
+
+ public Receipt Checkout()
+ {
+ var r = new Receipt();
+ foreach (Order order in _orders)
+ {
+ r.Price += order.Price;
+ r.Summary = r.Summary + " \n " + order.Type + " Price: " + order.Price;
+ }
+ return r;
+ }
+
+ public Guid Id
+ {
+ get { return _id; }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/IBooking.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/IBooking.cs
new file mode 100644
index 0000000000..cead4d0471
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/IBooking.cs
@@ -0,0 +1,43 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.bookingServer
+{
+ [ServiceContract(SessionMode=SessionMode.Required)]
+ public interface IBooking
+ {
+ [OperationContract]
+ void Add(Order order);
+
+ [OperationContract]
+ Receipt Checkout();
+
+ Guid Id
+ {
+ [OperationContract]
+ get;
+ }
+ }
+
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/Order.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/Order.cs
new file mode 100644
index 0000000000..aa52908692
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/Order.cs
@@ -0,0 +1,45 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+using System.Runtime.Serialization;
+
+namespace org.apache.qpid.wcf.demo.bookingServer
+{
+ [DataContract]
+ public sealed class Order
+ {
+ private double _price;
+ private string _type;
+
+ [DataMember]
+ public double Price
+ {
+ get { return _price; }
+ set { _price = value; }
+ }
+
+ [DataMember]
+ public string Type
+ {
+ get { return _type; }
+ set { _type = value; }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/Program.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/Program.cs
new file mode 100644
index 0000000000..ebb75308cf
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/Program.cs
@@ -0,0 +1,98 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.Threading;
+using org.apache.qpid.wcf.model;
+
+
+namespace org.apache.qpid.wcf.demo.bookingServer
+{
+ internal class Program
+ {
+ private ServiceHost _service;
+ private ChannelFactory<IBooking> fac;
+
+ public void StartService(Binding binding)
+ {
+ try
+ {
+ Console.WriteLine(" Binding Service...");
+ _service = new ServiceHost(typeof(Booking), new Uri("soap.amqp:///"));
+ _service.AddServiceEndpoint(typeof(IBooking), binding, "Booking");
+ _service.Open();
+ Thread.Sleep(500);
+ Console.WriteLine("[DONE]");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ }
+
+ public void StopService()
+ {
+ Console.WriteLine(" Stopping Service...");
+ _service.Close();
+ Console.WriteLine("[DONE]");
+ }
+
+ public IBooking StartClient(Binding binding)
+ {
+ IBooking res = null;
+ try
+ {
+ Console.WriteLine(" Starting Client...");
+ fac = new ChannelFactory<IBooking>(binding, "soap.amqp:///Booking");
+ fac.Open();
+ res = fac.CreateChannel();
+ Console.WriteLine("[DONE]");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ return res;
+ }
+
+ public void StopClient(IBooking client)
+ {
+ Console.WriteLine(" Stopping Client...");
+ ((IChannel)client).Close();
+ fac.Close();
+ Console.WriteLine("[DONE]");
+ }
+
+ private static void Main(string[] args)
+ {
+ var p = new Program();
+
+ Binding binding = new QpidBinding("192.168.1.14", 5673);
+ p.StartService(binding);
+
+ Console.ReadLine();
+
+ p.StopService();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..cc0208c9ca
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Booking Server")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Booking Server")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("12ef158b-ac5f-43b3-99f6-e4a4c096d6f8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/Receipt.cs b/dotnet/client-010/wcf/demo/wcfBookingServer/Receipt.cs
new file mode 100644
index 0000000000..d5ab0f3eb3
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/Receipt.cs
@@ -0,0 +1,46 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System.Runtime.Serialization;
+
+namespace org.apache.qpid.wcf.demo.bookingServer
+{
+ [DataContract]
+ public sealed class Receipt
+ {
+ private double _price;
+ private string _summary;
+
+ [DataMember]
+ public double Price
+ {
+ get { return _price; }
+ set { _price = value; }
+ }
+
+ [DataMember]
+ public string Summary
+ {
+ get { return _summary; }
+ set { _summary = value; }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfBookingServer/wcfBookingServer.csproj b/dotnet/client-010/wcf/demo/wcfBookingServer/wcfBookingServer.csproj
new file mode 100644
index 0000000000..2f744f8b6b
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfBookingServer/wcfBookingServer.csproj
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{B34E21C4-A742-4886-8569-1A89490E093E}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>wcfSession</RootNamespace>
+ <AssemblyName>Booking Server</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Runtime.Serialization">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Booking.cs" />
+ <Compile Include="Receipt.cs" />
+ <Compile Include="IBooking.cs" />
+ <Compile Include="Order.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\wcf.csproj">
+ <Project>{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}</Project>
+ <Name>wcf</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/App.config b/dotnet/client-010/wcf/demo/wcfHelloClient/App.config
new file mode 100644
index 0000000000..1545d71d6f
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/App.config
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <system.serviceModel>
+
+ <client>
+ <endpoint address="soap.amqp:///Hello"
+ binding="customBinding"
+ bindingConfiguration="QpidBinding"
+ contract="org.apache.qpid.wcf.demo.helloClient.IHelloContract"
+ name="HelloService" />
+ </client>
+
+
+ <bindings>
+ <customBinding>
+ <binding name="QpidBinding">
+ <textMessageEncoding />
+ <QpidTransport
+ host="localhost"
+ port="5672" />
+ </binding>
+ </customBinding>
+ </bindings>
+
+ <extensions>
+ <bindingElementExtensions>
+ <add
+ name="QpidTransport"
+ type="org.apache.qpid.wcf.model.QpidTransportElement, qpidWCFModel"/>
+ </bindingElementExtensions>
+ </extensions>
+
+
+ </system.serviceModel>
+</configuration>
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/HelloClient.cs b/dotnet/client-010/wcf/demo/wcfHelloClient/HelloClient.cs
new file mode 100644
index 0000000000..31743c62cf
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/HelloClient.cs
@@ -0,0 +1,36 @@
+/*
+*
+* 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.
+*
+*/
+
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.helloClient
+{
+ public class HelloClient : ClientBase<IHelloContract>, IHelloContract
+ {
+ public HelloClient(string configurationName)
+ : base(configurationName) { }
+
+ public void Hello(string name)
+ {
+ Channel.Hello(name);
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/IHelloService.cs b/dotnet/client-010/wcf/demo/wcfHelloClient/IHelloService.cs
new file mode 100644
index 0000000000..d3b9a354ba
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/IHelloService.cs
@@ -0,0 +1,33 @@
+/*
+*
+* 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.
+*
+*/
+
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.helloClient
+{
+ [ServiceContract]
+ public interface IHelloContract
+ {
+ [OperationContract(IsOneWay=true)]
+ void Hello(string name);
+ }
+
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/Program.cs b/dotnet/client-010/wcf/demo/wcfHelloClient/Program.cs
new file mode 100644
index 0000000000..fc68d2556a
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/Program.cs
@@ -0,0 +1,48 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.wcf.demo.helloClient
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.Title = "Hello Service Client";
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("Hello Service Client");
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine();
+ // create a client using the configuration file App.config
+ var client = new HelloClient("HelloService");
+ Console.WriteLine("Client Saying Hello to Qpid");
+ client.Hello("Qpid");
+ Console.WriteLine("Client Saying Hello to AMQP");
+ client.Hello("AMQP");
+ // closing the client service
+ client.ChannelFactory.Close();
+ Console.WriteLine();
+ Console.Write("Press Enter to Exit...");
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/demo/wcfHelloClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..83dfbcd5f4
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid WCF Hello Client")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid WCF Hello Client")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f7628695-280a-4689-ac6f-1186177f9a25")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/wcfHelloClient/wcfHelloClient.csproj b/dotnet/client-010/wcf/demo/wcfHelloClient/wcfHelloClient.csproj
new file mode 100644
index 0000000000..2e518d0da0
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloClient/wcfHelloClient.csproj
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A24E27DB-A38D-40C9-9879-8390B68C2F06}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>wcfHelloClient</RootNamespace>
+ <AssemblyName>Qpid WCF Hello Client</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HelloClient.cs" />
+ <Compile Include="IHelloService.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\wcf.csproj">
+ <Project>{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}</Project>
+ <Name>wcf</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/App.config b/dotnet/client-010/wcf/demo/wcfHelloServer/App.config
new file mode 100644
index 0000000000..de71f890b5
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/App.config
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <system.serviceModel>
+
+
+ <services>
+ <service name="org.apache.qpid.wcf.demo.HelloService">
+ <host>
+ <baseAddresses>
+ <add baseAddress="soap.amqp:///" />
+ </baseAddresses>
+ </host>
+ <endpoint
+ address="Hello"
+ binding="customBinding"
+ bindingConfiguration="QpidBinding"
+ contract="org.apache.qpid.wcf.demo.IHelloContract"/>
+ </service>
+ </services>
+
+
+ <bindings>
+ <customBinding>
+ <binding name="QpidBinding">
+ <textMessageEncoding />
+ <QpidTransport
+ host="192.168.1.14"
+ port="5673" />
+ </binding>
+ </customBinding>
+ </bindings>
+
+ <extensions>
+ <bindingElementExtensions>
+ <add
+ name="QpidTransport"
+ type="org.apache.qpid.wcf.model.QpidTransportElement, qpidWCFModel"/>
+ </bindingElementExtensions>
+ </extensions>
+
+
+ </system.serviceModel>
+</configuration>
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/HelloService.cs b/dotnet/client-010/wcf/demo/wcfHelloServer/HelloService.cs
new file mode 100644
index 0000000000..3b7df01ece
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/HelloService.cs
@@ -0,0 +1,34 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+
+namespace org.apache.qpid.wcf.demo.helloServer
+{
+ public class HelloService : IHelloContract
+ {
+ public void Hello(string name)
+ {
+ Console.WriteLine("Hello {0}!", name);
+
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/IHelloService.cs b/dotnet/client-010/wcf/demo/wcfHelloServer/IHelloService.cs
new file mode 100644
index 0000000000..1609439b94
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/IHelloService.cs
@@ -0,0 +1,32 @@
+/*
+*
+* 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.
+*
+*/
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.helloServer
+{
+ [ServiceContract]
+ public interface IHelloContract
+ {
+ [OperationContract(IsOneWay=true)]
+ void Hello(string name);
+ }
+
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/Program.cs b/dotnet/client-010/wcf/demo/wcfHelloServer/Program.cs
new file mode 100644
index 0000000000..1b8b8947ee
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/Program.cs
@@ -0,0 +1,47 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.helloServer
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.Title = "Hello Service Server";
+ Console.ForegroundColor = ConsoleColor.White;
+ Console.WriteLine("Hello Service Server");
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.WriteLine();
+
+ var host = new ServiceHost(typeof(HelloService));
+ host.Open();
+
+ Console.WriteLine("Service Ready");
+ Console.WriteLine("Press Enter to Exit...");
+ Console.ReadLine();
+
+ host.Close();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/demo/wcfHelloServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..a32f32e864
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid WCF Hello Server")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid WCF Hello Server")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("afa87185-f224-4948-904c-b4f3cd19dadb")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/wcfHelloServer/wcfHelloServer.csproj b/dotnet/client-010/wcf/demo/wcfHelloServer/wcfHelloServer.csproj
new file mode 100644
index 0000000000..3a672a87f4
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfHelloServer/wcfHelloServer.csproj
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>wcfHelloServer</RootNamespace>
+ <AssemblyName>Qpid WCF Hello Server</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HelloService.cs" />
+ <Compile Include="IHelloService.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/IUpperCase.cs b/dotnet/client-010/wcf/demo/wcfRPC/IUpperCase.cs
new file mode 100644
index 0000000000..668450948d
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/IUpperCase.cs
@@ -0,0 +1,31 @@
+/*
+*
+* 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.
+*
+*/
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.rpc
+{
+ [ServiceContract]
+ public interface IUpperCase
+ {
+ [OperationContract]
+ string ToUpperCase(string message);
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/Program.cs b/dotnet/client-010/wcf/demo/wcfRPC/Program.cs
new file mode 100644
index 0000000000..e2b54a0f61
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/Program.cs
@@ -0,0 +1,113 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.Threading;
+using org.apache.qpid.wcf.model;
+
+
+namespace org.apache.qpid.wcf.demo.rpc
+{
+ internal class Program
+ {
+ private ServiceHost _service;
+ private ChannelFactory<IUpperCase> fac;
+
+ public void StartService(Binding binding)
+ {
+ try
+ {
+ Console.WriteLine(" Binding Service...");
+ _service = new ServiceHost(typeof (UpperCase), new Uri("soap.amqp:///"));
+ _service.AddServiceEndpoint(typeof(IUpperCase), binding, "UpperCase");
+ _service.Open();
+ Thread.Sleep(500);
+ Console.WriteLine("[DONE]");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ }
+
+ public void StopService()
+ {
+ Console.WriteLine(" Stopping Service...");
+ _service.Close();
+ Console.WriteLine("[DONE]");
+ }
+
+ public IUpperCase StartClient(Binding binding)
+ {
+ IUpperCase res = null;
+ try
+ {
+ Console.WriteLine(" Starting Client...");
+ fac = new ChannelFactory<IUpperCase>(binding, "soap.amqp:///UpperCase");
+ fac.Open();
+ res = fac.CreateChannel();
+ Console.WriteLine("[DONE]");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ return res;
+ }
+
+ public void StopClient(IUpperCase client)
+ {
+ Console.WriteLine(" Stopping Client...");
+ ((IChannel) client).Close();
+ fac.Close();
+ Console.WriteLine("[DONE]");
+ }
+
+ private static void Main(string[] args)
+ {
+ var p = new Program();
+
+ Binding binding = new QpidBinding("192.168.1.14", 5673);
+ p.StartService(binding);
+
+
+ IUpperCase calc = p.StartClient(new QpidBinding("192.168.1.14", 5673));
+
+ string[] messages = {"Twas brillig, and the slithy toves",
+ "Did gire and gymble in the wabe. ",
+ "All mimsy were the borogroves, ",
+ "And the mome raths outgrabe. "};
+ foreach (string m in messages)
+ {
+ Console.Write(m + " --UperCase--> " );
+ Console.Write(calc.ToUpperCase(m));
+ Console.WriteLine();
+ }
+
+ Console.ReadLine();
+
+ p.StopClient(calc);
+ p.StopService();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/Properties/AssemblyInfo.cs b/dotnet/client-010/wcf/demo/wcfRPC/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..703fb9fcea
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Qpid WCF UpperCase")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Qpid WCF UpperCase")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("14ba3707-3fcc-4033-8bbc-0db65c5424f3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/QpidBindingConfigurationElement.cs b/dotnet/client-010/wcf/demo/wcfRPC/QpidBindingConfigurationElement.cs
new file mode 100644
index 0000000000..1d12868497
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/QpidBindingConfigurationElement.cs
@@ -0,0 +1,205 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Reflection;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Configuration;
+using System.Configuration;
+
+namespace org.apache.qpid.wcf.model
+{
+
+ /// <remarks>
+ /// This configuration element should be imported into the client
+ /// and server configuration files to provide declarative configuration
+ /// of a AMQP bound service.
+ /// </remarks>
+ public sealed class QpidBindingConfigurationElement : StandardBindingElement
+ {
+ /// <summary>
+ /// Creates a new instance of the QpidBindingConfigurationElement
+ /// Class initialized with values from the specified configuration.
+ /// </summary>
+ /// <param name="configurationName"></param>
+ public QpidBindingConfigurationElement(string configurationName)
+ : base(configurationName)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new instance of the RabbitMQBindingConfigurationElement Class.
+ /// </summary>
+ public QpidBindingConfigurationElement()
+ : this(null)
+ {
+ }
+
+
+ protected override void InitializeFrom(Binding binding)
+ {
+ base.InitializeFrom(binding);
+ QpidBinding qpidbinding = binding as QpidBinding;
+ if (qpidbinding != null)
+ {
+ Host = qpidbinding.Host;
+ OneWayOnly = qpidbinding.OneWayOnly;
+ TransactionFlowEnabled = qpidbinding.TransactionFlow;
+ VirtualHost = qpidbinding.VirtualHost;
+ PortNumber = qpidbinding.PortNumber;
+ UserName = qpidbinding.UserName;
+ Password = qpidbinding.Password;
+ }
+ }
+
+ protected override void OnApplyConfiguration(Binding binding)
+ {
+ if (binding == null)
+ throw new ArgumentNullException("binding");
+
+ var qpidbinding = binding as QpidBinding;
+ if (qpidbinding == null)
+ {
+ throw new ArgumentException(
+ string.Format("Invalid type for binding. Expected {0}, Passed: {1}",
+ typeof(QpidBinding).AssemblyQualifiedName,
+ binding.GetType().AssemblyQualifiedName));
+ }
+
+ qpidbinding.Host = Host;
+ qpidbinding.OneWayOnly = OneWayOnly;
+ qpidbinding.TransactionFlow = TransactionFlowEnabled;
+ qpidbinding.Password = Password;
+ qpidbinding.UserName = UserName;
+ qpidbinding.VirtualHost = VirtualHost;
+ qpidbinding.PortNumber = PortNumber;
+ }
+
+
+ /// <summary>
+ /// Specifies the host that the binding should connect to.
+ /// </summary>
+ [ConfigurationProperty("host", DefaultValue = "localhost")]
+ public string Host
+ {
+ get { return ((string) base["host"]); }
+ set { base["host"] = value; }
+ }
+
+ /// <summary>
+ /// Specifies the broker port number that the binding should connect to.
+ /// </summary>
+ [ConfigurationProperty("port", DefaultValue = "5672")]
+ public int PortNumber
+ {
+ get { return (Convert.ToInt16(base["port"])); }
+ set { base["port"] = value; }
+ }
+
+
+ /// <summary>
+ /// Specifies whether or not the CompositeDuplex and ReliableSession
+ /// binding elements are added to the channel stack.
+ /// </summary>
+ [ConfigurationProperty("oneWay", DefaultValue = false)]
+ public bool OneWayOnly
+ {
+ get { return ((bool)base["oneWay"]); }
+ set { base["oneWay"] = value; }
+ }
+
+ /// <summary>
+ /// Password to use when authenticating with the broker
+ /// </summary>
+ [ConfigurationProperty("password", DefaultValue = "guest")]
+ public string Password
+ {
+ get { return ((string)base["password"]); }
+ set { base["password"] = value; }
+ }
+
+ /// <summary>
+ /// Specifies whether or not WS-AtomicTransactions are supported by the binding
+ /// </summary>
+ [ConfigurationProperty("transactionFlow", DefaultValue = false)]
+ public bool TransactionFlowEnabled
+ {
+ get { return ((bool)base["transactionFlow"]); }
+ set { base["transactionFlow"] = value; }
+ }
+
+ /// <summary>
+ /// The username to use when authenticating with the broker
+ /// </summary>
+ [ConfigurationProperty("username", DefaultValue = "guest")]
+ public string UserName
+ {
+ get { return ((string)base["username"]); }
+ set { base["username"] = value; }
+ }
+
+
+
+
+ /// <summary>
+ /// The virtual host to access.
+ /// </summary>
+ [ConfigurationProperty("virtualHost", DefaultValue = "test")]
+ public string VirtualHost
+ {
+ get { return ((string)base["virtualHost"]); }
+ set { base["virtualHost"] = value; }
+ }
+
+ ///<summary>The security realm to use when calling IModel.AccessRequest</summary>
+ [ConfigurationProperty("realm", DefaultValue = "plain")]
+ public string Realm
+ {
+ get { return ((string)base["realm"]); }
+ set { base["realm"] = value; }
+ }
+
+ protected override Type BindingElementType
+ {
+ get { return typeof(QpidBinding); }
+ }
+
+ protected override ConfigurationPropertyCollection Properties
+ {
+ get
+ {
+ ConfigurationPropertyCollection configProperties = base.Properties;
+ foreach (PropertyInfo prop in this.GetType().GetProperties(BindingFlags.DeclaredOnly
+ | BindingFlags.Public
+ | BindingFlags.Instance))
+ {
+ foreach (ConfigurationPropertyAttribute attr in prop.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), false))
+ {
+ configProperties.Add(
+ new ConfigurationProperty(attr.Name, prop.PropertyType, attr.DefaultValue));
+ }
+ }
+
+ return configProperties;
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/UpperCase.cs b/dotnet/client-010/wcf/demo/wcfRPC/UpperCase.cs
new file mode 100644
index 0000000000..3e10926be4
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/UpperCase.cs
@@ -0,0 +1,33 @@
+/*
+*
+* 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.
+*
+*/
+using System.ServiceModel;
+
+namespace org.apache.qpid.wcf.demo.rpc
+{
+ [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
+ public sealed class UpperCase : IUpperCase
+ {
+ public string ToUpperCase(string message)
+ {
+ return message.ToUpper();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/demo/wcfRPC/wcfRPC.csproj b/dotnet/client-010/wcf/demo/wcfRPC/wcfRPC.csproj
new file mode 100644
index 0000000000..e8f7fee8f5
--- /dev/null
+++ b/dotnet/client-010/wcf/demo/wcfRPC/wcfRPC.csproj
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C988F456-1025-486F-9BCD-49C0F83B91DB}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>wcfRPC</RootNamespace>
+ <AssemblyName>Qpid WCF UpperCase</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IUpperCase.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UpperCase.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\wcf.csproj">
+ <Project>{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}</Project>
+ <Name>wcf</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/model/CommunicationOperation.cs b/dotnet/client-010/wcf/model/CommunicationOperation.cs
new file mode 100644
index 0000000000..3506d6729c
--- /dev/null
+++ b/dotnet/client-010/wcf/model/CommunicationOperation.cs
@@ -0,0 +1,31 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel.Channels;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal delegate void CommunicationOperation(TimeSpan timeout);
+ internal delegate TResult CommunicationOperation<TResult>(TimeSpan timeout);
+ internal delegate TResult CommunicationOperation<TResult, TArg>(TimeSpan timeout, out TArg arg0);
+ internal delegate void SendOperation(Message message, TimeSpan timeout);
+}
diff --git a/dotnet/client-010/wcf/model/QpidBinding.cs b/dotnet/client-010/wcf/model/QpidBinding.cs
new file mode 100644
index 0000000000..8f4684c1a1
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidBinding.cs
@@ -0,0 +1,185 @@
+/*
+*
+* 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.
+*
+*/
+
+using System.Configuration;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+
+namespace org.apache.qpid.wcf.model
+{
+ public sealed class QpidBinding : Binding
+ {
+ private string _host;
+ private int _port;
+ private string _username;
+ private string _password;
+ private string _virtuaHost;
+ private readonly CompositeDuplexBindingElement _compositeDuplex;
+ private readonly MessageEncodingBindingElement _encoding;
+ private bool _oneWayOnly;
+ private readonly ReliableSessionBindingElement _session;
+ private readonly TransactionFlowBindingElement _transactionFlow;
+ private bool _transactionsEnabled;
+ private readonly QpidTransportBindingElement _transport;
+
+
+
+ public QpidBinding() : this("localhost", 5672, "guest", "guest", "test")
+ {
+ }
+
+
+ public QpidBinding(string host, int port ) : this (host, port, "guest", "guest", "test")
+ {
+ }
+
+ public QpidBinding(string host, int port, string username, string password, string virtualhost)
+ {
+ Host = host;
+ PortNumber = port;
+ UserName = username;
+ Password = password;
+ VirtualHost = virtualhost;
+ _transport = new QpidTransportBindingElement();
+ _transport.Host = host;
+ _transport.PortNumber = port;
+ _transport.Password = password;
+ _transport.UserName = username;
+ _transport.VirtualHost = virtualhost;
+ _encoding = new TextMessageEncodingBindingElement();
+ _session = new ReliableSessionBindingElement();
+ _compositeDuplex = new CompositeDuplexBindingElement();
+ _transactionFlow = new TransactionFlowBindingElement();
+ }
+
+ public override BindingElementCollection CreateBindingElements()
+ {
+ var elements = new BindingElementCollection();
+
+ if (_transactionsEnabled)
+ {
+ elements.Add(_transactionFlow);
+ }
+ if (!OneWayOnly)
+ {
+ elements.Add(_session);
+ elements.Add(_compositeDuplex);
+ }
+ elements.Add(_encoding);
+ elements.Add(_transport);
+
+ return elements;
+ }
+
+
+
+ /// <summary>
+ /// Gets the scheme used by the binding, soap.amqp
+ /// </summary>
+ public override string Scheme
+ {
+ get { return "soap.amqp"; }
+ }
+
+ /// <summary>
+ /// Specifies the broker host
+ /// </summary>
+ [ConfigurationProperty("host")]
+ public string Host
+ {
+ get { return _host; }
+ set { _host = value; }
+ }
+
+ /// <summary>
+ /// Specifies the broker port
+ /// </summary>
+ public int PortNumber
+ {
+ get { return _port; }
+ set { _port = value; }
+ }
+
+ /// <summary>
+ /// Specifies the username
+ /// </summary>
+ public string UserName
+ {
+ get { return _username; }
+ set { _username = value; }
+ }
+
+ /// <summary>
+ /// Specifies the password
+ /// </summary>
+ public string Password
+ {
+ get { return _password; }
+ set { _password = value; }
+ }
+
+ /// <summary>
+ /// Specifies the virtualhost
+ /// </summary>
+ public string VirtualHost
+ {
+ get { return _virtuaHost; }
+ set { _virtuaHost = value; }
+ }
+
+
+ /// <summary>
+ /// Gets the AMQP _transport binding element
+ /// </summary>
+ public QpidTransportBindingElement Transport
+ {
+ get { return _transport; }
+ }
+
+ /// <summary>
+ /// Gets the reliable _session parameters for this binding instance
+ /// </summary>
+ public ReliableSession ReliableSession
+ {
+ get { return new ReliableSession(_session); }
+ }
+
+ /// <summary>
+ /// Determines whether or not the TransactionFlowBindingElement will
+ /// be added to the channel stack
+ /// </summary>
+ public bool TransactionFlow
+ {
+ get { return _transactionsEnabled; }
+ set { _transactionsEnabled = value; }
+ }
+
+ /// <summary>
+ /// Specifies whether or not the CompositeDuplex and ReliableSession
+ /// binding elements are added to the channel stack.
+ /// </summary>
+ public bool OneWayOnly
+ {
+ get { return _oneWayOnly; }
+ set { _oneWayOnly = value; }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/wcf/model/QpidChannelBase.cs b/dotnet/client-010/wcf/model/QpidChannelBase.cs
new file mode 100644
index 0000000000..174c28e108
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidChannelBase.cs
@@ -0,0 +1,167 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal abstract class QpidChannelBase : IChannel
+ {
+ private readonly CommunicationOperation _closeMethod;
+ private readonly BindingContext _context;
+ private readonly CommunicationOperation _openMethod;
+ private CommunicationState _state;
+
+ private QpidChannelBase()
+ {
+ _state = CommunicationState.Created;
+ _closeMethod = Close;
+ _openMethod = Open;
+ }
+
+ protected QpidChannelBase(BindingContext context)
+ : this()
+ {
+ _context = context;
+ }
+
+ public abstract void Close(TimeSpan timeout);
+
+ public abstract void Open(TimeSpan timeout);
+
+ public virtual void Abort()
+ {
+ Close();
+ }
+
+ public virtual void Close()
+ {
+ Close(_context.Binding.CloseTimeout);
+ }
+
+ public virtual T GetProperty<T>() where T : class
+ {
+ return default(T);
+ }
+
+ public virtual void Open()
+ {
+ Open(_context.Binding.OpenTimeout);
+ }
+
+ #region Async Methods
+
+ public virtual IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _closeMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ public virtual IAsyncResult BeginClose(AsyncCallback callback, object state)
+ {
+ return _closeMethod.BeginInvoke(_context.Binding.CloseTimeout, callback, state);
+ }
+
+ public virtual IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _openMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ public virtual IAsyncResult BeginOpen(AsyncCallback callback, object state)
+ {
+ return _openMethod.BeginInvoke(_context.Binding.OpenTimeout, callback, state);
+ }
+
+ public virtual void EndClose(IAsyncResult result)
+ {
+ _closeMethod.EndInvoke(result);
+ }
+
+ public virtual void EndOpen(IAsyncResult result)
+ {
+ _openMethod.EndInvoke(result);
+ }
+
+ #endregion
+
+ #region Event Raising Methods
+
+ protected void OnOpening()
+ {
+ _state = CommunicationState.Opening;
+ if (Opening != null)
+ Opening(this, null);
+ }
+
+ protected void OnOpened()
+ {
+ _state = CommunicationState.Opened;
+ if (Opened != null)
+ Opened(this, null);
+ }
+
+ protected void OnClosing()
+ {
+ _state = CommunicationState.Closing;
+ if (Closing != null)
+ Closing(this, null);
+ }
+
+ protected void OnClosed()
+ {
+ _state = CommunicationState.Closed;
+ if (Closed != null)
+ Closed(this, null);
+ }
+
+ protected void OnFaulted()
+ {
+ _state = CommunicationState.Faulted;
+ if (Faulted != null)
+ Faulted(this, null);
+ }
+
+ #endregion
+
+
+ public CommunicationState State
+ {
+ get { return _state; }
+ }
+
+ protected BindingContext Context
+ {
+ get { return _context; }
+ }
+
+
+ public event EventHandler Closed;
+
+ public event EventHandler Closing;
+
+ public event EventHandler Faulted;
+
+ public event EventHandler Opened;
+
+ public event EventHandler Opening;
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidChannelFactory.cs b/dotnet/client-010/wcf/model/QpidChannelFactory.cs
new file mode 100644
index 0000000000..84518cb1c3
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidChannelFactory.cs
@@ -0,0 +1,74 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.wcf.model
+{
+ public class QpidChannelFactory : ChannelFactoryBase<IOutputChannel>
+ {
+ private readonly BindingContext _context;
+ private readonly CommunicationOperation _openMethod;
+ private readonly QpidTransportBindingElement _bindingElement;
+ private ClientSession _session;
+
+ public QpidChannelFactory(BindingContext context)
+ {
+ _context = context;
+ _openMethod = Open;
+ _bindingElement = context.Binding.Elements.Find<QpidTransportBindingElement>();
+ }
+
+ protected override IOutputChannel OnCreateChannel(EndpointAddress address, Uri via)
+ {
+ return new QpidOutputChannel(_context, _session, address);
+ }
+
+ protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _openMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ protected override void OnEndOpen(IAsyncResult result)
+ {
+ _openMethod.EndInvoke(result);
+ }
+
+ protected override void OnOpen(TimeSpan timeout)
+ {
+ _session = _bindingElement.Open(timeout.Milliseconds);
+ }
+
+ protected override void OnClose(TimeSpan timeout)
+ {
+ _bindingElement.Close();
+ }
+
+ protected override void OnAbort()
+ {
+ base.OnAbort();
+ OnClose(_context.Binding.CloseTimeout);
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidChannelListener.cs b/dotnet/client-010/wcf/model/QpidChannelListener.cs
new file mode 100644
index 0000000000..f776fce9a5
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidChannelListener.cs
@@ -0,0 +1,79 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.wcf.model
+{
+ public sealed class QpidChannelListener : QpidChannelListenerBase<IInputChannel>
+ {
+
+ private IInputChannel _channel;
+ private ClientSession _session;
+
+ public QpidChannelListener(BindingContext context)
+ : base(context)
+ {
+ _channel = null;
+ _session = null;
+ }
+
+ protected override IInputChannel OnAcceptChannel(TimeSpan timeout)
+ {
+ // Since only one connection to a broker is required (even for communication
+ // with multiple exchanges
+ if (_channel != null)
+ return null;
+
+ _channel = new QpidInputChannel(Context, _session, new EndpointAddress(Uri.ToString()));
+ _channel.Closed += ListenChannelClosed;
+ return _channel;
+ }
+
+ protected override bool OnWaitForChannel(TimeSpan timeout)
+ {
+ return false;
+ }
+
+ protected override void OnOpen(TimeSpan timeout)
+ {
+ _session = _bindingElement.Open(timeout.Milliseconds);
+ }
+
+ protected override void OnClose(TimeSpan timeout)
+ {
+ if (_channel != null)
+ {
+ _channel.Close();
+ _channel = null;
+ }
+ _bindingElement.Close();
+ }
+
+ private void ListenChannelClosed(object sender, EventArgs args)
+ {
+ Close();
+ }
+}
+}
diff --git a/dotnet/client-010/wcf/model/QpidChannelListenerBase.cs b/dotnet/client-010/wcf/model/QpidChannelListenerBase.cs
new file mode 100644
index 0000000000..bdecb38c9d
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidChannelListenerBase.cs
@@ -0,0 +1,111 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+
+using System;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+
+namespace org.apache.qpid.wcf.model
+{
+ public abstract class QpidChannelListenerBase<TChannel> : ChannelListenerBase<TChannel> where TChannel: class, IChannel
+ {
+ private readonly Uri _listenUri;
+ private readonly BindingContext _context;
+ protected QpidTransportBindingElement _bindingElement;
+ private readonly CommunicationOperation _closeMethod;
+ private readonly CommunicationOperation _openMethod;
+ private readonly CommunicationOperation<TChannel> _acceptChannelMethod;
+ private readonly CommunicationOperation<bool> _waitForChannelMethod;
+
+ protected QpidChannelListenerBase(BindingContext context)
+ {
+ _context = context;
+ _bindingElement = context.Binding.Elements.Find<QpidTransportBindingElement>();
+ _closeMethod = OnClose;
+ _openMethod = OnOpen;
+ _waitForChannelMethod = OnWaitForChannel;
+ _acceptChannelMethod = OnAcceptChannel;
+ if (context.ListenUriMode == ListenUriMode.Explicit && context.ListenUriBaseAddress != null)
+ {
+ _listenUri = new Uri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
+ }
+ else
+ {
+ _listenUri = new Uri(new Uri("soap.amqp:///"), Guid.NewGuid().ToString());
+ }
+ }
+
+ protected override void OnAbort()
+ {
+ OnClose(_context.Binding.CloseTimeout);
+ }
+
+ protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _acceptChannelMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ protected override TChannel OnEndAcceptChannel(IAsyncResult result)
+ {
+ return _acceptChannelMethod.EndInvoke(result);
+ }
+
+ protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _waitForChannelMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ protected override bool OnEndWaitForChannel(IAsyncResult result)
+ {
+ return _waitForChannelMethod.EndInvoke(result);
+ }
+
+ protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _closeMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _openMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ protected override void OnEndClose(IAsyncResult result)
+ {
+ _closeMethod.EndInvoke(result);
+ }
+
+ protected override void OnEndOpen(IAsyncResult result)
+ {
+ _openMethod.EndInvoke(result);
+ }
+
+ public override Uri Uri
+ {
+ get { return _listenUri; }
+ }
+
+ protected BindingContext Context
+ {
+ get { return _context; }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidInputChannel.cs b/dotnet/client-010/wcf/model/QpidInputChannel.cs
new file mode 100644
index 0000000000..7a05153df9
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidInputChannel.cs
@@ -0,0 +1,218 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.Text;
+using System.Threading;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal sealed class QpidInputChannel : QpidInputChannelBase
+ {
+ private static readonly Logger _log = Logger.get(typeof (QpidInputChannel));
+
+ private readonly QpidTransportBindingElement _bindingElement;
+ private readonly MessageEncoder _encoder;
+ private readonly ClientSession _session;
+ private readonly string _queueName;
+ private BlockingQueue _queue;
+ private bool _closed = false;
+
+ public QpidInputChannel(BindingContext context, ClientSession session, EndpointAddress address)
+ : base(context, address)
+ {
+ _bindingElement = context.Binding.Elements.Find<QpidTransportBindingElement>();
+ var encoderElem = context.BindingParameters.Find<MessageEncodingBindingElement>();
+ if (encoderElem != null)
+ {
+ _encoder = encoderElem.CreateMessageEncoderFactory().Encoder;
+ }
+ _session = session;
+ _queueName = address.Uri.ToString();
+ _queue = new BlockingQueue();
+ }
+
+
+ public override System.ServiceModel.Channels.Message Receive(TimeSpan timeout)
+ {
+ _session.messageFlow("myDest", MessageCreditUnit.MESSAGE, 1);
+ _session.sync();
+ IMessage m = _queue.Dequeue();
+ System.ServiceModel.Channels.Message result = null;
+ if (m != null)
+ {
+ var reader = new BinaryReader(m.Body, Encoding.UTF8);
+ var body = new byte[m.Body.Length - m.Body.Position];
+ reader.Read(body, 0, body.Length);
+ try
+ {
+ result = _encoder.ReadMessage(new MemoryStream(body),
+ (int) _bindingElement.MaxReceivedMessageSize);
+ }
+ catch(Exception e)
+ {
+ Console.WriteLine(e.StackTrace);
+ }
+ result.Headers.To = LocalAddress.Uri;
+
+ var ack = new RangeSet();
+ // ack this message
+ ack.add(m.Id);
+ _session.messageAccept(ack);
+ _session.sync();
+ }
+ else
+ {
+ if(! _closed )
+ {
+ return Receive(timeout);
+ }
+ }
+ return result;
+ }
+
+ public override bool TryReceive(TimeSpan timeout, out System.ServiceModel.Channels.Message message)
+ {
+ message = Receive(timeout);
+ return message != null;
+ }
+
+ public override bool WaitForMessage(TimeSpan timeout)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Close(TimeSpan timeout)
+ {
+ _closed = true;
+ _queue = null;
+ }
+
+ public override void Open(TimeSpan timeout)
+ {
+ if (State != CommunicationState.Created && State != CommunicationState.Closed)
+ throw new InvalidOperationException(string.Format("Cannot open the channel from the {0} state.", State));
+
+ OnOpening();
+
+ var qr = (QueueQueryResult) _session.queueQuery(_queueName).Result;
+ if (qr.getQueue() == null)
+ {
+ // create the queue
+ _session.queueDeclare(_queueName, null, null);
+ }
+ // bind the queue
+ _session.exchangeBind(_queueName, "amq.direct", _queueName, null);
+ var myListener = new WCFListener(_queue);
+ _session.attachMessageListener(myListener, "myDest");
+ _session.messageSubscribe(_queueName, "myDest", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ null,
+ 0, null);
+ // issue credits
+ _session.messageSetFlowMode("myDest", MessageFlowMode.WINDOW);
+ _session.messageFlow("myDest", MessageCreditUnit.BYTE, ClientSession.MESSAGE_FLOW_MAX_BYTES);
+ _session.sync();
+
+ OnOpened();
+ }
+ }
+
+ internal class WCFListener : IMessageListener
+ {
+ private static readonly Logger _log = Logger.get(typeof (WCFListener));
+ private readonly BlockingQueue _q;
+
+ public WCFListener(BlockingQueue q)
+ {
+ _q = q;
+ }
+
+ public void messageTransfer(IMessage m)
+ {
+ _log.debug("message received by listener");
+ _q.Enqueue(m);
+ }
+ }
+
+ internal class BlockingQueue
+ {
+ private int _count;
+ private readonly Queue<IMessage> _queue = new Queue<IMessage>();
+
+ public IMessage Dequeue(TimeSpan timeout)
+ {
+ lock (_queue)
+ {
+ DateTime start = DateTime.Now;
+ long elapsed = 0;
+ while (_count <= 0 && elapsed < timeout.Milliseconds)
+ {
+ Monitor.Wait(_queue, new TimeSpan(timeout.Milliseconds - elapsed));
+ elapsed = DateTime.Now.Subtract(start).Milliseconds;
+ }
+ if (_count > 0)
+ {
+ _count--;
+ return _queue.Dequeue();
+ }
+ return null;
+ }
+ }
+
+ public IMessage Dequeue()
+ {
+ lock (_queue)
+ {
+ while (_count <= 0)
+ {
+ Monitor.Wait(_queue);
+ }
+ if (_count > 0)
+ {
+ _count--;
+ return _queue.Dequeue();
+ }
+ return null;
+ }
+ }
+
+ public void Enqueue(IMessage data)
+ {
+ if (data != null)
+ {
+ lock (_queue)
+ {
+ _queue.Enqueue(data);
+ _count++;
+ Monitor.Pulse(_queue);
+ }
+ }
+ }
+ }
+}
+
diff --git a/dotnet/client-010/wcf/model/QpidInputChannelBase.cs b/dotnet/client-010/wcf/model/QpidInputChannelBase.cs
new file mode 100644
index 0000000000..0bd9e85c0a
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidInputChannelBase.cs
@@ -0,0 +1,101 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal abstract class QpidInputChannelBase : QpidChannelBase, IInputChannel
+ {
+ private readonly EndpointAddress _localAddress;
+ private readonly CommunicationOperation<Message> _receiveMethod;
+ private readonly CommunicationOperation<bool, Message> _tryReceiveMethod;
+ private readonly CommunicationOperation<bool> _waitForMessage;
+
+
+ protected QpidInputChannelBase(BindingContext context, EndpointAddress localAddress)
+ :base(context)
+ {
+ _localAddress = localAddress;
+ _receiveMethod = Receive;
+ _tryReceiveMethod = TryReceive;
+ _waitForMessage = WaitForMessage;
+ }
+
+
+ #region Async Methods
+ public virtual IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _receiveMethod.BeginInvoke(timeout, callback, state);
+ }
+
+ public virtual IAsyncResult BeginReceive(AsyncCallback callback, object state)
+ {
+ return _receiveMethod.BeginInvoke(Context.Binding.ReceiveTimeout, callback, state);
+ }
+
+ public virtual IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ Message message;
+ return _tryReceiveMethod.BeginInvoke(timeout, out message, callback, state);
+ }
+
+ public virtual IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _waitForMessage.BeginInvoke(timeout, callback, state);
+ }
+
+ public virtual Message EndReceive(IAsyncResult result)
+ {
+ return _receiveMethod.EndInvoke(result);
+ }
+
+ public virtual bool EndTryReceive(IAsyncResult result, out Message message)
+ {
+ return _tryReceiveMethod.EndInvoke(out message, result);
+ }
+
+ public virtual bool EndWaitForMessage(IAsyncResult result)
+ {
+ return _waitForMessage.EndInvoke(result);
+ }
+ #endregion
+
+ public abstract Message Receive(TimeSpan timeout);
+
+ public abstract bool TryReceive(TimeSpan timeout, out Message message);
+
+ public abstract bool WaitForMessage(TimeSpan timeout);
+
+ public virtual Message Receive()
+ {
+ return Receive(Context.Binding.ReceiveTimeout);
+ }
+
+
+ public EndpointAddress LocalAddress
+ {
+ get { return _localAddress; }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidOutputChannel.cs b/dotnet/client-010/wcf/model/QpidOutputChannel.cs
new file mode 100644
index 0000000000..f53ed9b9b8
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidOutputChannel.cs
@@ -0,0 +1,89 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.IO;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using org.apache.qpid.client;
+using org.apache.qpid.transport;
+using org.apache.qpid.transport.util;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal sealed class QpidOutputChannel : QpidOutputChannelBase
+ {
+ private readonly MessageEncoder _encoder;
+ private readonly ClientSession _session;
+ private readonly string _queueName;
+
+ public QpidOutputChannel(BindingContext context, ClientSession session, EndpointAddress address)
+ : base(context, address)
+ {
+ var encoderElement = context.Binding.Elements.Find<MessageEncodingBindingElement>();
+ if (encoderElement != null)
+ {
+ _encoder = encoderElement.CreateMessageEncoderFactory().Encoder;
+ }
+ _queueName = address.Uri.ToString();
+ _session = session;
+ }
+
+ public override void Send(System.ServiceModel.Channels.Message message, TimeSpan timeout)
+ {
+ if (message.State != MessageState.Closed)
+ {
+ byte[] body;
+ using (var str = new MemoryStream())
+ {
+ _encoder.WriteMessage(message, str);
+ body = str.ToArray();
+ }
+ _session.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey(_queueName),
+ new transport.MessageProperties().setMessageId(UUID.randomUUID())),
+ body);
+ }
+ }
+
+ public override void Close(TimeSpan timeout)
+ {
+ if (State == CommunicationState.Closed || State == CommunicationState.Closing)
+ return; // Ignore the call, we're already closing.
+ OnClosing();
+ OnClosed();
+ }
+
+ public override void Open(TimeSpan timeout)
+ {
+ if (State != CommunicationState.Created && State != CommunicationState.Closed)
+ throw new InvalidOperationException(string.Format("Cannot open the channel from the {0} state.", State));
+ OnOpening();
+ var qr = (QueueQueryResult) _session.queueQuery(_queueName).Result;
+ if (qr.getQueue() == null)
+ {
+ // create the queue
+ _session.queueDeclare(_queueName, null, null);
+ }
+ OnOpened();
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidOutputChannelBase.cs b/dotnet/client-010/wcf/model/QpidOutputChannelBase.cs
new file mode 100644
index 0000000000..a3cd9020ff
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidOutputChannelBase.cs
@@ -0,0 +1,77 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+
+namespace org.apache.qpid.wcf.model
+{
+ internal abstract class QpidOutputChannelBase : QpidChannelBase, IOutputChannel
+ {
+
+ private readonly SendOperation _sendMethod;
+ private readonly EndpointAddress _address;
+
+ protected QpidOutputChannelBase(BindingContext context, EndpointAddress address)
+ : base(context)
+ {
+ _address = address;
+ _sendMethod = Send;
+ }
+
+ #region Async Methods
+
+ public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
+ {
+ return _sendMethod.BeginInvoke(message, timeout, callback, state);
+ }
+
+ public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
+ {
+ return _sendMethod.BeginInvoke(message, Context.Binding.SendTimeout, callback, state);
+ }
+
+ public void EndSend(IAsyncResult result)
+ {
+ _sendMethod.EndInvoke(result);
+ }
+
+ #endregion
+
+ public abstract void Send(Message message, TimeSpan timeout);
+
+ public virtual void Send(Message message)
+ {
+ Send(message, Context.Binding.SendTimeout);
+ }
+
+ public EndpointAddress RemoteAddress
+ {
+ get { return _address; }
+ }
+
+ public Uri Via
+ {
+ get { throw new NotImplementedException(); }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidTransportBindingElement.cs b/dotnet/client-010/wcf/model/QpidTransportBindingElement.cs
new file mode 100644
index 0000000000..50cc80422a
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidTransportBindingElement.cs
@@ -0,0 +1,186 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Configuration;
+using System.ServiceModel.Channels;
+using org.apache.qpid.client;
+
+namespace org.apache.qpid.wcf.model
+{
+ public sealed class QpidTransportBindingElement : TransportBindingElement
+ {
+ private Client _connection;
+ private string _host;
+ private int _port;
+ private string _username;
+ private string _password;
+ private string _virtuaHost;
+
+ /// <summary>
+ /// Creates a new instance of the QpidTransportBindingElement Class
+ /// </summary>
+ public QpidTransportBindingElement()
+ {
+ _host = "localhost";
+ _port = 5672;
+ _username = "guest";
+ _password = "guest";
+ _virtuaHost = "test";
+ }
+
+ private QpidTransportBindingElement(QpidTransportBindingElement other)
+ : this()
+ {
+ Connection = other.Connection;
+ Host = other.Host;
+ PortNumber = other.PortNumber;
+ UserName = other.UserName;
+ Password = other.Password;
+ }
+
+
+ public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
+ {
+ if (Host == null)
+ throw new InvalidOperationException("No broker was specified.");
+ return (IChannelFactory<TChannel>) new QpidChannelFactory(context);
+ }
+
+ public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
+ {
+ if (Host == null)
+ throw new InvalidOperationException("No broker was specified.");
+
+ return (IChannelListener<TChannel>) ((object) new QpidChannelListener(context));
+ }
+
+ public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
+ {
+ return typeof (TChannel) == typeof (IOutputChannel);
+ }
+
+ public override bool CanBuildChannelListener<TChannel>(BindingContext context)
+ {
+ return typeof (TChannel) == typeof (IInputChannel);
+ }
+
+ public override BindingElement Clone()
+ {
+ return new QpidTransportBindingElement(this);
+ }
+
+ public override T GetProperty<T>(BindingContext context)
+ {
+ return context.GetInnerProperty<T>();
+ }
+
+ /// <summary>
+ /// Gets the scheme used by the binding, this is 0.10 as default for now.
+ /// </summary>
+ public override string Scheme
+ {
+ get { return "soap.amqp"; }
+ }
+
+
+ /// <summary>
+ /// Specifies the broker host
+ /// </summary>
+ [ConfigurationProperty("host")]
+ public string Host
+ {
+ get { return _host; }
+ set { _host = value; }
+ }
+
+ /// <summary>
+ /// Specifies the broker port
+ /// </summary>
+ public int PortNumber
+ {
+ get { return _port; }
+ set { _port = value; }
+ }
+
+ /// <summary>
+ /// Specifies the username
+ /// </summary>
+ public string UserName
+ {
+ get { return _username; }
+ set { _username = value; }
+ }
+
+ /// <summary>
+ /// Specifies the password
+ /// </summary>
+ public string Password
+ {
+ get { return _password; }
+ set { _password = value; }
+ }
+
+ /// <summary>
+ /// Specifies the virtualhost
+ /// </summary>
+ public string VirtualHost
+ {
+ get { return _virtuaHost; }
+ set { _virtuaHost = value; }
+ }
+
+ /// <summary>
+ /// Specifies the connection
+ /// </summary>
+ public Client Connection
+ {
+ get { return _connection; }
+ set { _connection = value; }
+ }
+
+
+ internal ClientSession Open(long timeout)
+ {
+ if (Connection == null)
+ {
+ Connection = new Client();
+ }
+ Connection.connect(Host, PortNumber, VirtualHost, UserName, Password);
+ return Connection.createSession(timeout);
+ }
+
+ internal void Close()
+ {
+ if (Connection != null)
+ {
+ try
+ {
+ Connection.close();
+ }
+ catch (Exception e)
+ {
+ // todo log it
+ }
+ }
+ }
+ }
+}
diff --git a/dotnet/client-010/wcf/model/QpidTransportElement.cs b/dotnet/client-010/wcf/model/QpidTransportElement.cs
new file mode 100644
index 0000000000..f531186148
--- /dev/null
+++ b/dotnet/client-010/wcf/model/QpidTransportElement.cs
@@ -0,0 +1,183 @@
+/*
+*
+* 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.
+*
+*/
+
+using System;
+using System.Configuration;
+using System.Reflection;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Configuration;
+
+namespace org.apache.qpid.wcf.model
+{
+ public sealed class QpidTransportElement : TransportElement
+ {
+
+ public override void ApplyConfiguration(BindingElement bindingElement)
+ {
+ base.ApplyConfiguration(bindingElement);
+ if (bindingElement == null)
+ throw new ArgumentNullException("bindingElement");
+
+ var bindind = bindingElement as QpidTransportBindingElement;
+ if (bindind == null)
+ {
+ throw new ArgumentException(
+ string.Format("Invalid type for binding. Expected {0}, Passed: {1}",
+ typeof(QpidTransportBindingElement).AssemblyQualifiedName,
+ bindingElement.GetType().AssemblyQualifiedName));
+ }
+
+ bindind.Host = Host;
+ bindind.Password = Password;
+ bindind.UserName = UserName;
+ bindind.VirtualHost = VirtualHost;
+ bindind.PortNumber = PortNumber;
+ }
+
+ public override void CopyFrom(ServiceModelExtensionElement from)
+ {
+ base.CopyFrom(from);
+ var element = from as QpidTransportElement;
+ if (element != null)
+ {
+ Host = element.Host;
+ PortNumber = element.PortNumber;
+ Password = element.Password;
+ UserName = element.UserName;
+ VirtualHost = element.VirtualHost;
+ }
+ }
+
+ protected override BindingElement CreateBindingElement()
+ {
+ TransportBindingElement element = CreateDefaultBindingElement();
+ ApplyConfiguration(element);
+ return element;
+ }
+
+ protected override TransportBindingElement CreateDefaultBindingElement()
+ {
+ return new QpidTransportBindingElement();
+ }
+
+ protected override void InitializeFrom(BindingElement bindingElement)
+ {
+ base.InitializeFrom(bindingElement);
+
+ if (bindingElement == null)
+ throw new ArgumentNullException("bindingElement");
+
+ var binding = bindingElement as QpidTransportBindingElement;
+ if (binding == null)
+ {
+ throw new ArgumentException(
+ string.Format("Invalid type for binding. Expected {0}, Passed: {1}",
+ typeof(QpidTransportBindingElement).AssemblyQualifiedName,
+ bindingElement.GetType().AssemblyQualifiedName));
+ }
+
+ Host = binding.Host;
+ PortNumber = binding.PortNumber;
+ Password = binding.Password;
+ UserName = binding.UserName;
+ VirtualHost = binding.VirtualHost;
+ }
+
+ public override Type BindingElementType
+ {
+ get { return typeof(QpidTransportElement); }
+ }
+
+
+
+ /// <summary>
+ /// Specifies the broker host name that the binding should connect to.
+ /// </summary>
+ [ConfigurationProperty("host", DefaultValue = "localhost")]
+ public string Host
+ {
+ get { return ((string) base["host"]); }
+ set { base["host"] = value; }
+ }
+
+ /// <summary>
+ /// Specifies the broker port number that the binding should connect to.
+ /// </summary>
+ [ConfigurationProperty("port", DefaultValue = "5672")]
+ public int PortNumber
+ {
+ get { return (Convert.ToInt16(base["port"])); }
+ set { base["port"] = value; }
+ }
+
+ /// <summary>
+ /// Password to use when authenticating with the broker
+ /// </summary>
+ [ConfigurationProperty("password", DefaultValue = "guest")]
+ public string Password
+ {
+ get { return ((string)base["password"]); }
+ set { base["password"] = value; }
+ }
+
+ /// <summary>
+ /// The username to use when authenticating with the broker
+ /// </summary>
+ [ConfigurationProperty("username", DefaultValue = "guest")]
+ public string UserName
+ {
+ get { return ((string)base["username"]); }
+ set { base["username"] = value; }
+ }
+
+
+ /// <summary>
+ /// The virtual host to access.
+ /// </summary>
+ [ConfigurationProperty("virtualHost", DefaultValue = "test")]
+ public string VirtualHost
+ {
+ get { return ((string)base["virtualHost"]); }
+ set { base["virtualHost"] = value; }
+ }
+
+
+ protected override ConfigurationPropertyCollection Properties
+ {
+ get
+ {
+ ConfigurationPropertyCollection configProperties = base.Properties;
+ foreach (PropertyInfo prop in GetType().GetProperties(BindingFlags.DeclaredOnly
+ | BindingFlags.Public
+ | BindingFlags.Instance))
+ {
+ foreach (ConfigurationPropertyAttribute attr in prop.GetCustomAttributes(typeof(ConfigurationPropertyAttribute), false))
+ {
+ configProperties.Add(
+ new ConfigurationProperty(attr.Name, prop.PropertyType, attr.DefaultValue));
+ }
+ }
+
+ return configProperties;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/client-010/wcf/wcf.csproj b/dotnet/client-010/wcf/wcf.csproj
new file mode 100644
index 0000000000..f07c5ab1fd
--- /dev/null
+++ b/dotnet/client-010/wcf/wcf.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>WCF</RootNamespace>
+ <AssemblyName>qpidWCFModel</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Qpid Client, Version=0.10.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\client\bin\Debug\Qpid Client.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.configuration" />
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="model\*.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/dotnet/client-010/wcf/wcf.sln b/dotnet/client-010/wcf/wcf.sln
new file mode 100644
index 0000000000..8120f44576
--- /dev/null
+++ b/dotnet/client-010/wcf/wcf.sln
@@ -0,0 +1,70 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+
+#
+# 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.
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcfHelloClient", "demo\wcfHelloClient\wcfHelloClient.csproj", "{A24E27DB-A38D-40C9-9879-8390B68C2F06}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcfHelloServer", "demo\wcfHelloServer\wcfHelloServer.csproj", "{3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcfRPC", "demo\wcfRPC\wcfRPC.csproj", "{C988F456-1025-486F-9BCD-49C0F83B91DB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcBookingClient", "demo\wcfBookingClient\wcBookingClient.csproj", "{4086B3FE-F745-4DCC-952A-682CAE01F4C9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcfBookingServer", "demo\wcfBookingServer\wcfBookingServer.csproj", "{B34E21C4-A742-4886-8569-1A89490E093E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "wcf", "wcf.csproj", "{F1D80D9D-FE22-4213-A760-BFFDE7D131DD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A24E27DB-A38D-40C9-9879-8390B68C2F06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A24E27DB-A38D-40C9-9879-8390B68C2F06}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A24E27DB-A38D-40C9-9879-8390B68C2F06}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A24E27DB-A38D-40C9-9879-8390B68C2F06}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3EF848D7-5FAC-482C-922A-D4D45A4CCD2A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C988F456-1025-486F-9BCD-49C0F83B91DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C988F456-1025-486F-9BCD-49C0F83B91DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C988F456-1025-486F-9BCD-49C0F83B91DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C988F456-1025-486F-9BCD-49C0F83B91DB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4086B3FE-F745-4DCC-952A-682CAE01F4C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4086B3FE-F745-4DCC-952A-682CAE01F4C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4086B3FE-F745-4DCC-952A-682CAE01F4C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4086B3FE-F745-4DCC-952A-682CAE01F4C9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B34E21C4-A742-4886-8569-1A89490E093E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B34E21C4-A742-4886-8569-1A89490E093E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B34E21C4-A742-4886-8569-1A89490E093E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B34E21C4-A742-4886-8569-1A89490E093E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F1D80D9D-FE22-4213-A760-BFFDE7D131DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F1D80D9D-FE22-4213-A760-BFFDE7D131DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F1D80D9D-FE22-4213-A760-BFFDE7D131DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F1D80D9D-FE22-4213-A760-BFFDE7D131DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/dotnet/client-010/wcf/wcf.suo b/dotnet/client-010/wcf/wcf.suo
new file mode 100644
index 0000000000..60339d33e4
--- /dev/null
+++ b/dotnet/client-010/wcf/wcf.suo
Binary files differ
diff --git a/dotnet/default.build b/dotnet/default.build
new file mode 100644
index 0000000000..4cd38e90ff
--- /dev/null
+++ b/dotnet/default.build
@@ -0,0 +1,252 @@
+<?xml version="1.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.
+
+-->
+
+<project name="Qpid.NET" default="build">
+
+ <!-- Determines the formatter to use to format output of test results. -->
+ <property name="nant.formatter" value="Plain" />
+
+ <!-- Determines whether a 'debug' or 'release' build is to be done. Defaults to 'debug' -->
+ <property name="build.config" value="debug" />
+
+ <!-- Sets build properties consistently accross all assemblies in the project. -->
+ <property name="build.version.major" value="0"/>
+ <property name="build.version.minor" value="5"/>
+ <property name="build.version.build" value="0"/>
+ <property name="build.version.revision" value="0"/>
+ <property name="build.company" value="Apache Software Foundation"/>
+ <property name="build.copyright" value="Apache Software Foundation"/>
+ <property name="build.description" value="Built from svn revision number: "/>
+
+ <!-- Fileset with build files for each 'core' assembly. -->
+ <fileset id="src.builds">
+ <include name="Qpid.Buffer/default.build" />
+ <include name="Qpid.Sasl/default.build" />
+ <include name="Qpid.Messaging/default.build" />
+ <include name="Qpid.Codec/default.build" />
+ <include name="Qpid.Common/default.build" />
+ <include name="Qpid.Client/default.build" />
+ </fileset>
+
+ <!-- Fileset with build files for 'pure unit' test assemblies. -->
+ <fileset id="tests.pure.builds">
+ <include name="Qpid.Buffer.Tests/default.build" />
+ <include name="Qpid.Sasl.Tests/default.build" />
+ <include name="Qpid.Common.Tests/default.build" />
+ <include name="Qpid.Client.Tests/default.build" />
+ </fileset>
+
+ <!-- Fileset with build files for 'integration' test assemblies. -->
+ <fileset id="tests.integration.builds">
+ <include name="Qpid.Integration.Tests/default.build" />
+ </fileset>
+
+ <!-- Other test or utility assemblies. -->
+ <fileset id='other.builds'>
+ <include name="TopicListener/default.build" />
+ <include name="TopicPublisher/default.build" />
+ <include name="TestClient/default.build" />
+ </fileset>
+
+ <!-- Prepare environment for a debug build. -->
+ <target name="debug">
+ <property name="build.debug" value="true" />
+ <property name="build.defines" value="DEBUG;TRACE"/>
+ </target>
+
+ <!-- Prepare environment for a release build. -->
+ <target name="release">
+ <property name="build.debug" value="false" />
+ <property name="build.defines" value=""/>
+ </target>
+
+ <!-- Prepare environment for build. -->
+ <target name="init">
+ <property name="base.dir" value="${project::get-base-directory()}" />
+ <property name="build.dir" value="${base.dir}/bin/${framework::get-target-framework()}/${build.config}" />
+ <call target="${build.config}" />
+ </target>
+
+ <!-- Cleans up the build output directory. -->
+ <target name="clean" depends="init">
+ <delete dir="${build.dir}" failonerror="false" />
+ </target>
+
+ <!-- Runs 'svnversion' to get the repository revision into the build property 'build.svnversion'. -->
+ <target name="svnversion" description="Runs svnversion to get the current repository version into a build script property.">
+ <exec program="svnversion" output="svnversion_tmp.txt">
+ <arg value="-n"/>
+ </exec>
+
+ <loadfile file="svnversion_tmp.txt" property="build.svnversion"/>
+ <delete file="svnversion_tmp.txt"/>
+
+ <!-- For some competely retarted reason the '-n' parameter to svnversion doesn't really work under windows...
+ Here is some code to strip the unwanted newlines. -->
+ <script language="C#">
+ <code><![CDATA[
+ public static void ScriptMain(Project project)
+ {
+ project.Properties["build.svnversion"] = project.Properties["build.svnversion"].Trim("\n\r".ToCharArray());
+ }
+ ]]>
+ </code>
+ </script>
+
+ </target>
+
+ <!-- Performs a regex find-and-replace on assembly info files, substituting fields defined as build properties. -->
+ <target name="setversion" description="Stamp the version info onto assemblyinfo.cs files" depends="svnversion">
+
+ <echo>build.svnversion = ${build.svnversion}</echo>
+
+ <foreach item="File" property="filename">
+ <in>
+ <items basedir=".">
+ <include name="**\AssemblyInfo.cs"></include>
+ </items>
+ </in>
+ <do>
+ <script language="C#">
+ <code><![CDATA[
+ public static void ScriptMain(Project project)
+ {
+ // Read in the entire file to perform the substitution in.
+ StreamReader reader = new StreamReader(project.Properties["filename"]);
+ string contents = reader.ReadToEnd();
+ reader.Close();
+
+ // Substitute the version numbers.
+ string replacement = string.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]",
+ project.Properties["build.version.major"],
+ project.Properties["build.version.minor"],
+ project.Properties["build.version.build"],
+ project.Properties["build.version.revision"]);
+ contents = System.Text.RegularExpressions.Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
+
+ // Substitute the company name and copyright.
+ replacement = string.Format("[assembly: AssemblyCompany(\"{0}\")]",
+ project.Properties["build.company"]);
+ contents = System.Text.RegularExpressions.Regex.Replace(contents, @"\[assembly: AssemblyCompany\("".*""\)\]", replacement);
+
+ replacement = string.Format("[assembly: AssemblyCopyright(\"{0}\")]",
+ project.Properties["build.copyright"]);
+ contents = System.Text.RegularExpressions.Regex.Replace(contents, @"\[assembly: AssemblyCopyright\("".*""\)\]", replacement);
+
+ // Update the description.
+ //replacement = string.Format("[assembly: AssemblyDescription(\"{0} {1}\")]",
+ // project.Properties["build.description"],
+ // project.Properties["build.svnversion"]);
+ replacement = string.Format("[assembly: AssemblyDescription(\"{0}\")]",
+ project.Properties["build.description"]);
+ contents = System.Text.RegularExpressions.Regex.Replace(contents, @"\[assembly: AssemblyDescription\("".*""\)\]", replacement);
+
+ // Write out the file with the substituted version.
+ StreamWriter writer = new StreamWriter(project.Properties["filename"], false);
+ writer.Write(contents);
+ writer.Close();
+ }
+ ]]>
+ </code>
+ </script>
+ </do>
+ </foreach>
+ </target>
+
+ <!-- Do the build. -->
+ <target name="build" depends="init, setversion">
+ <echo message="Building all modules including tests."/>
+
+ <!-- Make sure output folder exists. -->
+ <mkdir dir="${build.dir}" />
+
+ <!-- copy reference assemblies over to the output dir -->
+ <copy todir="${build.dir}" file="Qpid.Common/lib/seclib-1.0.0/Org.Mentalis.Security.dll"/>
+ <copy todir="${build.dir}" file="Qpid.Common/lib/log4net/log4net.dll"/>
+ <copy todir="${build.dir}" file="Qpid.Client.Tests/lib/nunit/nunit.framework.dll"/>
+
+ <!-- Compile assemblies. -->
+ <nant target="build">
+ <buildfiles refid="src.builds" />
+ </nant>
+
+ <!-- Compile test assemblies. -->
+ <nant target="build">
+ <buildfiles refid="tests.pure.builds" />
+ </nant>
+ <nant target="build">
+ <buildfiles refid="tests.integration.builds" />
+ </nant>
+
+ <!-- Compile test assemblies. -->
+ <nant target="build">
+ <buildfiles refid="other.builds" />
+ </nant>
+ </target>
+
+ <!-- Runs all 'pure unit' tests. -->
+ <target name="test" depends="build">
+ <echo message="Running all pure unit tests."/>
+ <nant target="test">
+ <buildfiles refid="tests.pure.builds" />
+ </nant>
+ </target>
+
+ <!-- Runs all 'integration' tests. -->
+ <target name="integrationtest" depends="build">
+ <echo message="Running all integration tests."/>
+ <nant target="test">
+ <buildfiles refid="tests.integration.builds" />
+ </nant>
+ </target>
+
+ <!-- Creates a release package. -->
+ <target name="release-pkg">
+ <echo message="Building and packaging a release."/>
+
+ <call target="clean"/>
+ <call target="build"/>
+
+ <property name="build.date" value="${datetime::now()}"/>
+ <property name="build.timestamp" value="${framework::get-target-framework()}-${datetime::get-year(build.date)}${datetime::get-month(build.date)}${datetime::get-day(build.date)}"/>
+
+ <zip zipfile="${build.dir}/Qpid.NET-${build.timestamp}.zip">
+ <fileset basedir="${build.dir}" prefix="Qpid.NET-${build.timestamp}">
+ <include name="**/*.*"/>
+ <exclude name="**/*.Tests.*"/>
+ <exclude name="**/nunit.framework.dll"/>
+ <exclude name="**/*.exe"/>
+ </fileset>
+
+ <fileset basedir="${base.dir}" prefix="Qpid.NET-${build.timestamp}">
+ <include name="LICENSE.txt"/>
+ <include name="NOTICE.txt"/>
+ <include name="README.txt"/>
+ <include name="RELEASE_NOTES.txt"/>
+ <include name="DISCLAIMER"/>
+ </fileset>
+ </zip>
+ </target>
+
+</project>
+
+
diff --git a/extras/qmf/setup.py b/extras/qmf/setup.py
index ae35c42375..2e3ec7a38e 100755
--- a/extras/qmf/setup.py
+++ b/extras/qmf/setup.py
@@ -20,10 +20,10 @@
from distutils.core import setup
setup(name="qpid-qmf",
- version="0.13",
+ version="0.9",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
- packages=["qmf"],
+ packages=["qmf", "qmf2", "qmf2.tests"],
package_dir={"": "src/py"},
url="http://qpid.apache.org/",
license="Apache Software License",
diff --git a/extras/qmf/src/py/qmf/console.py b/extras/qmf/src/py/qmf/console.py
index a3d17b9af1..6f4c11ae15 100644
--- a/extras/qmf/src/py/qmf/console.py
+++ b/extras/qmf/src/py/qmf/console.py
@@ -107,8 +107,8 @@ class Console:
# BrokerURL
#===================================================================================================
class BrokerURL(URL):
- def __init__(self, *args, **kwargs):
- URL.__init__(self, *args, **kwargs)
+ def __init__(self, text):
+ URL.__init__(self, text)
if self.port is None:
if self.scheme == URL.AMQPS:
self.port = 5671
@@ -122,7 +122,7 @@ class BrokerURL(URL):
self.authPass = str(self.password)
def name(self):
- return str(self)
+ return self.host + ":" + str(self.port)
def match(self, host, port):
return socket.getaddrinfo(self.host, self.port)[0][4] == socket.getaddrinfo(host, port)[0][4]
@@ -359,8 +359,8 @@ class Object(object):
for arg in method.arguments:
if arg.dir.find("I") != -1:
count += 1
- if count != len(args) + len(kwargs):
- raise Exception("Incorrect number of arguments: expected %d, got %d" % (count, len(args) + len(kwargs)))
+ if count != len(args):
+ raise Exception("Incorrect number of arguments: expected %d, got %d" % (count, len(args)))
if self._agent.isV2:
#
@@ -372,10 +372,7 @@ class Object(object):
argMap = {}
for arg in method.arguments:
if arg.dir.find("I") != -1:
- if aIdx < len(args):
- argMap[arg.name] = args[aIdx]
- else:
- argMap[arg.name] = kwargs[arg.name]
+ argMap[arg.name] = args[aIdx]
aIdx += 1
call['_arguments'] = argMap
@@ -442,10 +439,6 @@ class Object(object):
else:
sync = True
- # Remove special "meta" kwargs before handing to _sendMethodRequest() to process
- if "_timeout" in kwargs: del kwargs["_timeout"]
- if "_async" in kwargs: del kwargs["_async"]
-
seq = self._sendMethodRequest(name, args, kwargs, sync, timeout)
if seq:
if not sync:
@@ -645,10 +638,7 @@ class Session:
Will raise an exception if the session is not managing the connection and
the connection setup to the broker fails.
"""
- if isinstance(target, BrokerURL):
- url = target
- else:
- url = BrokerURL(target)
+ url = BrokerURL(target)
broker = Broker(self, url.host, url.port, mechanisms, url.authName, url.authPass,
ssl = url.scheme == URL.AMQPS, connTimeout=timeout)
@@ -1221,22 +1211,11 @@ class Session:
try:
agentName = ah["qmf.agent"]
values = content["_values"]
-
- if '_timestamp' in values:
- timestamp = values["_timestamp"]
- else:
- timestamp = values['timestamp']
-
- if '_heartbeat_interval' in values:
- interval = values['_heartbeat_interval']
- else:
- interval = values['heartbeat_interval']
-
+ timestamp = values["_timestamp"]
+ interval = values["_heartbeat_interval"]
epoch = 0
if '_epoch' in values:
epoch = values['_epoch']
- elif 'epoch' in values:
- epoch = values['epoch']
except Exception,e:
return
@@ -2349,19 +2328,18 @@ class Broker(Thread):
def getUrl(self):
""" """
- return BrokerURL(host=self.host, port=self.port)
+ return "%s:%d" % (self.host, self.port)
def getFullUrl(self, noAuthIfGuestDefault=True):
""" """
+ ssl = ""
if self.ssl:
- scheme = "amqps"
- else:
- scheme = "amqp"
+ ssl = "s"
+ auth = "%s/%s@" % (self.authUser, self.authPass)
if self.authUser == "" or \
(noAuthIfGuestDefault and self.authUser == "guest" and self.authPass == "guest"):
- return BrokerURL(scheme=scheme, host=self.host, port=(self.port or 5672))
- else:
- return BrokerURL(scheme=scheme, user=self.authUser, password=self.authPass, host=self.host, port=(self.port or 5672))
+ auth = ""
+ return "amqp%s://%s%s:%d" % (ssl, auth, self.host, self.port or 5672)
def __repr__(self):
if self.connected:
@@ -2438,7 +2416,7 @@ class Broker(Thread):
if uid.__class__ == tuple and len(uid) == 2:
self.saslUser = uid[1]
else:
- self.saslUser = self.authUser
+ self.saslUser = None
# prevent topic queues from filling up (and causing the agents to
# disconnect) by discarding the oldest queued messages when full.
diff --git a/extras/qmf/src/py/qmf2-prototype/__init__.py b/extras/qmf/src/py/qmf2/__init__.py
index 31d5a2ef58..31d5a2ef58 100644
--- a/extras/qmf/src/py/qmf2-prototype/__init__.py
+++ b/extras/qmf/src/py/qmf2/__init__.py
diff --git a/extras/qmf/src/py/qmf2-prototype/agent.py b/extras/qmf/src/py/qmf2/agent.py
index 4ec00bd288..4ec00bd288 100644
--- a/extras/qmf/src/py/qmf2-prototype/agent.py
+++ b/extras/qmf/src/py/qmf2/agent.py
diff --git a/extras/qmf/src/py/qmf2-prototype/common.py b/extras/qmf/src/py/qmf2/common.py
index 2e5367f54f..2e5367f54f 100644
--- a/extras/qmf/src/py/qmf2-prototype/common.py
+++ b/extras/qmf/src/py/qmf2/common.py
diff --git a/extras/qmf/src/py/qmf2-prototype/console.py b/extras/qmf/src/py/qmf2/console.py
index 9227835b3f..9227835b3f 100644
--- a/extras/qmf/src/py/qmf2-prototype/console.py
+++ b/extras/qmf/src/py/qmf2/console.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/__init__.py b/extras/qmf/src/py/qmf2/tests/__init__.py
index eff9357e1f..eff9357e1f 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/__init__.py
+++ b/extras/qmf/src/py/qmf2/tests/__init__.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/agent_discovery.py b/extras/qmf/src/py/qmf2/tests/agent_discovery.py
index 2c20794aaa..2c20794aaa 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/agent_discovery.py
+++ b/extras/qmf/src/py/qmf2/tests/agent_discovery.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/agent_test.py b/extras/qmf/src/py/qmf2/tests/agent_test.py
index 14d8ada197..14d8ada197 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/agent_test.py
+++ b/extras/qmf/src/py/qmf2/tests/agent_test.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/async_method.py b/extras/qmf/src/py/qmf2/tests/async_method.py
index 2339fc71a9..2339fc71a9 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/async_method.py
+++ b/extras/qmf/src/py/qmf2/tests/async_method.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/async_query.py b/extras/qmf/src/py/qmf2/tests/async_query.py
index b1c01611f7..b1c01611f7 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/async_query.py
+++ b/extras/qmf/src/py/qmf2/tests/async_query.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/basic_method.py b/extras/qmf/src/py/qmf2/tests/basic_method.py
index 8d038bc4c8..8d038bc4c8 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/basic_method.py
+++ b/extras/qmf/src/py/qmf2/tests/basic_method.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/basic_query.py b/extras/qmf/src/py/qmf2/tests/basic_query.py
index 9f5dda6d54..9f5dda6d54 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/basic_query.py
+++ b/extras/qmf/src/py/qmf2/tests/basic_query.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/console_test.py b/extras/qmf/src/py/qmf2/tests/console_test.py
index ac0e064f20..ac0e064f20 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/console_test.py
+++ b/extras/qmf/src/py/qmf2/tests/console_test.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/events.py b/extras/qmf/src/py/qmf2/tests/events.py
index 624c9b3823..624c9b3823 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/events.py
+++ b/extras/qmf/src/py/qmf2/tests/events.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/multi_response.py b/extras/qmf/src/py/qmf2/tests/multi_response.py
index 991fa0114e..991fa0114e 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/multi_response.py
+++ b/extras/qmf/src/py/qmf2/tests/multi_response.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/obj_gets.py b/extras/qmf/src/py/qmf2/tests/obj_gets.py
index 695b096973..695b096973 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/obj_gets.py
+++ b/extras/qmf/src/py/qmf2/tests/obj_gets.py
diff --git a/extras/qmf/src/py/qmf2-prototype/tests/subscriptions.py b/extras/qmf/src/py/qmf2/tests/subscriptions.py
index 5c39af4b32..5c39af4b32 100644
--- a/extras/qmf/src/py/qmf2-prototype/tests/subscriptions.py
+++ b/extras/qmf/src/py/qmf2/tests/subscriptions.py
diff --git a/extras/sasl/bootstrap b/extras/sasl/bootstrap
index 906e5a71e4..32085c325d 100755
--- a/extras/sasl/bootstrap
+++ b/extras/sasl/bootstrap
@@ -22,7 +22,7 @@ aclocal -I m4
autoheader
libtoolize --automake
-automake --add-missing
+automake
autoconf
if [ "$1" = "-build" -o "$1" = "--build" ] ; then
diff --git a/extras/sasl/configure.ac b/extras/sasl/configure.ac
index 206c2f497d..bc0fadbb31 100644
--- a/extras/sasl/configure.ac
+++ b/extras/sasl/configure.ac
@@ -23,6 +23,7 @@ AC_CONFIG_HEADERS([config.h])
AC_PROG_CC_STDC
AM_PROG_CC_C_O
AC_PROG_CXX
+AC_USE_SYSTEM_EXTENSIONS
AC_LANG([C++])
# Check for optional use of help2man
diff --git a/extras/sasl/python/Makefile.am b/extras/sasl/python/Makefile.am
index 7c61f37cee..43eef70923 100644
--- a/extras/sasl/python/Makefile.am
+++ b/extras/sasl/python/Makefile.am
@@ -29,7 +29,8 @@ BUILT_SOURCES = $(generated_file_list)
$(generated_file_list): python.i $(top_srcdir)/src/saslwrapper.i
$(SWIG) -c++ -python -Wall -I/usr/include $(INCLUDES) -o saslwrapper.cpp $(srcdir)/python.i
-pyexec_PYTHON = saslwrapper.py
+pylibdir = $(PYTHON_LIB)
+python_PYTHON = saslwrapper.py
pyexec_LTLIBRARIES = _saslwrapper.la
_saslwrapper_la_LDFLAGS = -avoid-version -module -shared
diff --git a/extras/sasl/ruby/Makefile.am b/extras/sasl/ruby/Makefile.am
index 85fde1085d..da64239323 100644
--- a/extras/sasl/ruby/Makefile.am
+++ b/extras/sasl/ruby/Makefile.am
@@ -35,7 +35,7 @@ rubylibarch_LTLIBRARIES = saslwrapper.la
saslwrapper_la_LDFLAGS = -avoid-version -module -shared ".$(RUBY_DLEXT)"
saslwrapper_la_LIBADD = $(RUBY_LIBS) $(top_builddir)/src/libsaslwrapper.la -lsasl2
-saslwrapper_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) -fno-strict-aliasing
+saslwrapper_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH)
nodist_saslwrapper_la_SOURCES = saslwrapper.cpp
CLEANFILES = $(generated_file_list)
diff --git a/extras/sasl/src/Makefile.am b/extras/sasl/src/Makefile.am
index c2aa8dd188..25529a3607 100644
--- a/extras/sasl/src/Makefile.am
+++ b/extras/sasl/src/Makefile.am
@@ -24,7 +24,6 @@ nobase_include_HEADERS = ../include/saslwrapper.h
lib_LTLIBRARIES = libsaslwrapper.la
libsaslwrapper_la_SOURCES = cyrus/saslwrapper.cpp
-libsaslwrapper_la_CXXFLAGS = -fno-strict-aliasing
# Library Version Information:
#
diff --git a/gentools/build.xml b/gentools/build.xml
index f6760a215e..5d0976f56d 100644
--- a/gentools/build.xml
+++ b/gentools/build.xml
@@ -25,7 +25,7 @@
<property name="java.target" value="1.5"/>
<target name="compile">
- <javac srcdir="${src}" source="${java.source}" target="${java.target}" fork="true" debug="on" includeantruntime="false">
+ <javac srcdir="${src}" source="${java.source}" target="${java.target}" fork="true" debug="on">
<classpath>
<fileset dir="${src}/../lib">
<include name="**/*.jar"/>
diff --git a/java/bdbstore/bin/backup.sh b/java/bdbstore/bin/backup.sh
deleted file mode 100755
index 0e2f0fda09..0000000000
--- a/java/bdbstore/bin/backup.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Parse arguments taking all - prefixed args as JAVA_OPTS
-for arg in "$@"; do
- if [[ $arg == -java:* ]]; then
- JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
- else
- ARGS="${ARGS}$arg "
- fi
-done
-
-WHEREAMI=`dirname $0`
-if [ -z "$QPID_HOME" ]; then
- export QPID_HOME=`cd $WHEREAMI/../ && pwd`
-fi
-VERSION=0.13
-
-LIBS=$QPID_HOME/lib/je-4.0.103.jar:$QPID_HOME/lib/qpid-bdbstore-$VERSION.jar:$QPID_HOME/lib/qpid-all.jar
-
-
-echo "Starting Hot Backup Script"
-java -Dlog4j.configuration=backup-log4j.xml ${JAVA_OPTS} -cp $LIBS org.apache.qpid.server.store.berkeleydb.BDBBackup ${ARGS}
diff --git a/java/bdbstore/bin/storeUpgrade.sh b/java/bdbstore/bin/storeUpgrade.sh
deleted file mode 100755
index 076b9d3f7e..0000000000
--- a/java/bdbstore/bin/storeUpgrade.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# Parse arguements taking all - prefixed args as JAVA_OPTS
-for arg in "$@"; do
- if [[ $arg == -java:* ]]; then
- JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
- else
- ARGS="${ARGS}$arg "
- fi
-done
-
-if [ -z "$QPID_HOME" ]; then
- export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
- export PATH=${PATH}:${QPID_HOME}/bin
-fi
-
-if [ -z "$BDB_HOME" ]; then
- export BDB_HOME=$(dirname $(dirname $(readlink -f $0)))
-fi
-
-VERSION=0.13
-
-LIBS=$BDB_HOME/lib/je-4.0.103.jar:$BDB_HOME/lib/qpid-bdbstore-$VERSION.jar:$QPID_HOME/lib/qpid-all.jar
-
-java -Xms256m -Dlog4j.configuration=BDBStoreUpgrade.log4j.xml -Xmx256m -Damqj.logging.level=warn ${JAVA_OPTS} -cp $LIBS org.apache.qpid.server.store.berkeleydb.BDBStoreUpgrade ${ARGS}
diff --git a/java/bdbstore/build.xml b/java/bdbstore/build.xml
deleted file mode 100644
index 9355358e6c..0000000000
--- a/java/bdbstore/build.xml
+++ /dev/null
@@ -1,84 +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.
- -->
-<project name="bdbstore" default="build">
- <property name="module.depends" value="common client management/common broker perftests systests" />
- <property name="module.test.depends" value="test common/test broker/test management/common perftests systests" />
-
- <import file="../module.xml" />
-
- <property name="bdb.lib.dir" value="${project.root}/lib/bdbstore" />
- <property name="bdb.version" value="4.0.103" />
- <property name="bdb.download.url" value="http://download.oracle.com/maven/com/sleepycat/je/${bdb.version}/je-${bdb.version}.jar" />
- <property name="bdb.jar.file" value="${bdb.lib.dir}/je-${bdb.version}.jar" />
-
- <!--check whether the BDB jar is present, possibly after download-->
- <target name="check-bdb-jar">
- <available file="${bdb.jar.file}" type="file" property="bdb.jar.available"/>
- </target>
-
- <!--echo that BDB is required if it isnt present, with associated licencing note-->
- <target name="bdb-jar-required" depends="bdb-licence-note-optional" unless="bdb.jar.available">
- <echo>The BDB JE library is required to use this optional module.
-
-The jar file may be downloaded by either:
-
- Seperately running the following command from the qpid/java/bdbstore dir: ant download-bdb
-
- OR
-
- Adding -Ddownload-bdb=true to your regular build command.</echo>
- <fail>The BDB JE library was not found</fail>
- </target>
-
- <!--issue BDB licencing note if BDB isnt already present-->
- <target name="bdb-licence-note-optional" depends="check-bdb-jar" unless="bdb.jar.available">
- <antcall target="bdb-licence-note"/>
- </target>
-
- <!--issue BDB licencing note-->
- <target name="bdb-licence-note">
- <echo>*NOTE* The BDB JE library required by this optional module is licensed under the Sleepycat Licence, which is not compatible with the Apache Licence v2.0.
-
-For a copy of the Sleepycat Licence, please see:
-http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-086837.html</echo>
- </target>
-
- <!--check if an inline BDB download was requested with the build-->
- <target name="check-request-props" if="download-bdb">
- <antcall target="download-bdb"/>
- </target>
-
- <!--download BDB, with licencing note-->
- <target name="download-bdb" depends="bdb-licence-note">
- <mkdir dir="${bdb.lib.dir}"/>
- <echo>Downloading BDB JE</echo>
- <get src="${bdb.download.url}" dest="${bdb.jar.file}" usetimestamp="true" />
- </target>
-
- <target name="build" depends="check-request-props, bdb-jar-required, module.build" />
-
- <target name="postbuild" depends="copy-store-to-upgrade" />
-
- <target name="copy-store-to-upgrade" description="copy the upgrade tool resource folder contents into the build tree">
- <copy todir="${qpid.home}" failonerror="true">
- <fileset dir="src/test/resources/upgrade"/>
- </copy>
- </target>
-
-</project>
diff --git a/java/bdbstore/etc/scripts/bdbbackuptest.sh b/java/bdbstore/etc/scripts/bdbbackuptest.sh
deleted file mode 100755
index 2a0b72e5ad..0000000000
--- a/java/bdbstore/etc/scripts/bdbbackuptest.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-if [ -z "$QPID_HOME" ]; then
- export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
- export PATH=${PATH}:${QPID_HOME}/bin
-fi
-
-# Parse arguements taking all - prefixed args as JAVA_OPTS
-for arg in "$@"; do
- if [[ $arg == -java:* ]]; then
- JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
- else
- ARGS="${ARGS}$arg "
- fi
-done
-
-VERSION=0.5
-
-# Set classpath to include Qpid jar with all required jars in manifest
-QPID_LIBS=$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/qpid-junit-toolkit-$VERSION.jar:$QPID_HOME/lib/junit-3.8.1.jar:$QPID_HOME/lib/log4j-1.2.12.jar:$QPID_HOME/lib/qpid-systests-$VERSION.jar:$QPID_HOME/lib/qpid-perftests-$VERSION.jar:$QPID_HOME/lib/slf4j-log4j12-1.4.0.jar:$QPID_HOME/lib/qpid-bdbstore-$VERSION.jar
-
-# Set other variables used by the qpid-run script before calling
-export JAVA=java JAVA_MEM=-Xmx256m QPID_CLASSPATH=$QPID_LIBS
-
-. qpid-run -Dlog4j.configuration=perftests.log4j -Dbadger.level=warn -Damqj.test.logging.level=warn -Damqj.logging.level=warn ${JAVA_OPTS} org.apache.qpid.server.store.berkeleydb.testclient.BackupTestClient -o $QPID_WORK/results numMessagesToAction=55 ${ARGS}
-
diff --git a/java/bdbstore/etc/scripts/bdbtest.sh b/java/bdbstore/etc/scripts/bdbtest.sh
deleted file mode 100755
index eafdae9710..0000000000
--- a/java/bdbstore/etc/scripts/bdbtest.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-if [ -z "$QPID_HOME" ]; then
- export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
- export PATH=${PATH}:${QPID_HOME}/bin
-fi
-
-# Parse arguements taking all - prefixed args as JAVA_OPTS
-for arg in "$@"; do
- if [[ $arg == -java:* ]]; then
- JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
- else
- ARGS="${ARGS}$arg "
- fi
-done
-
-VERSION=0.5
-
-# Set classpath to include Qpid jar with all required jars in manifest
-QPID_LIBS=$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/qpid-junit-toolkit-$VERSION.jar:$QPID_HOME/lib/junit-3.8.1.jar:$QPID_HOME/lib/log4j-1.2.12.jar:$QPID_HOME/lib/qpid-systests-$VERSION.jar:$QPID_HOME/lib/qpid-perftests-$VERSION.jar:$QPID_HOME/lib/slf4j-log4j12-1.4.0.jar
-
-# Set other variables used by the qpid-run script before calling
-export JAVA=java JAVA_MEM=-Xmx256m QPID_CLASSPATH=$QPID_LIBS
-
-. qpid-run -Dlog4j.configuration=perftests.log4j -Dbadger.level=warn -Damqj.test.logging.level=warn -Damqj.logging.level=warn ${JAVA_OPTS} org.apache.qpid.ping.PingDurableClient -o $QPID_WORK/results ${ARGS}
diff --git a/java/bdbstore/src/main/java/BDBStoreUpgrade.log4j.xml b/java/bdbstore/src/main/java/BDBStoreUpgrade.log4j.xml
deleted file mode 100644
index 4d71963ea7..0000000000
--- a/java/bdbstore/src/main/java/BDBStoreUpgrade.log4j.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.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.
- -
- -->
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
-
- <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
-
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%d %-5p - %m%n"/>
- </layout>
- </appender>
-
- <category name="org.apache.qpid.server.store.berkeleydb.BDBStoreUpgrade">
- <priority value="info"/>
- </category>
-
- <!-- Only show errors from the BDB Store -->
- <category name="org.apache.qpid.server.store.berkeleydb.berkeleydb.BDBMessageStore">
- <priority value="error"/>
- </category>
-
- <!-- Provide warnings to standard output -->
- <category name="org.apache.qpid">
- <priority value="error"/>
- </category>
-
- <!-- Log all info events to file -->
- <root>
- <priority value="info"/>
- <appender-ref ref="STDOUT"/>
- </root>
-
-</log4j:configuration>
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java
deleted file mode 100644
index 8b887b1876..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncoding.java
+++ /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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.framing.AMQShortString;
-
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-public class AMQShortStringEncoding
-{
- public static AMQShortString readShortString(TupleInput tupleInput)
- {
- int length = (int) tupleInput.readShort();
- if (length < 0)
- {
- return null;
- }
- else
- {
- byte[] stringBytes = new byte[length];
- tupleInput.readFast(stringBytes);
- return new AMQShortString(stringBytes);
- }
-
- }
-
- public static void writeShortString(AMQShortString shortString, TupleOutput tupleOutput)
- {
-
- if (shortString == null)
- {
- tupleOutput.writeShort(-1);
- }
- else
- {
- tupleOutput.writeShort(shortString.length());
- tupleOutput.writeFast(shortString.getBytes(), 0, shortString.length());
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringTB.java
deleted file mode 100644
index 81ae315fe2..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringTB.java
+++ /dev/null
@@ -1,48 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import org.apache.log4j.Logger;
-import org.apache.qpid.framing.AMQShortString;
-
-public class AMQShortStringTB extends TupleBinding
-{
- private static final Logger _log = Logger.getLogger(AMQShortStringTB.class);
-
-
- public AMQShortStringTB()
- {
- }
-
- public Object entryToObject(TupleInput tupleInput)
- {
- return AMQShortStringEncoding.readShortString(tupleInput);
- }
-
- public void objectToEntry(Object object, TupleOutput tupleOutput)
- {
- AMQShortStringEncoding.writeShortString((AMQShortString)object, tupleOutput);
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java
deleted file mode 100644
index c515ca5d8e..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackup.java
+++ /dev/null
@@ -1,344 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import com.sleepycat.je.DatabaseException;
-import com.sleepycat.je.Environment;
-import com.sleepycat.je.EnvironmentConfig;
-import com.sleepycat.je.util.DbBackup;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.util.CommandLineParser;
-import org.apache.qpid.util.FileUtils;
-
-import java.io.*;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
-
-/**
- * BDBBackup is a utility for taking hot backups of the current state of a BDB transaction log database.
- *
- * <p/>This utility makes the following assumptions/performs the following actions:
- *
- * <p/><ul> <li>The from and to directory locations will already exist. This scripts does not create them. <li>If this
- * script fails to complete in one minute it will terminate. <li>This script always exits with code 1 on error, code 0
- * on success (standard unix convention). <li>This script will log out at info level, when it starts and ends and a list
- * of all files backed up. <li>This script logs all errors at error level. <li>This script does not perform regular
- * backups, wrap its calling script in a cron job or similar to do this. </ul>
- *
- * <p/>This utility is build around the BDB provided backup helper utility class, DbBackup. This utility class provides
- * an ability to force BDB to stop writing to the current log file set, whilst the backup is taken, to ensure that a
- * consistent snapshot is acquired. Preventing BDB from writing to the current log file set, does not stop BDB from
- * continuing to run concurrently while the backup is running, it simply moves onto a new set of log files; this
- * provides a 'hot' backup facility.
- *
- * <p/>DbBackup can also help with incremental backups, by providing the number of the last log file backed up.
- * Subsequent backups can be taken, from later log files only. In a messaging application, messages are not expected to
- * be long-lived in most cases, so the log files will usually have been completely turned over between backups. This
- * utility does not support incremental backups for this reason.
- *
- * <p/>If the database is locked by BDB, as is required when using transactions, and therefore will always be the case
- * in Qpid, this utility cannot make use of the DbBackup utility in a seperate process. DbBackup, needs to ensure that
- * the BDB envinronment used to take the backup has exclusive write access to the log files. This utility can take a
- * backup as a standalone utility against log files, when a broker is not running, using the {@link #takeBackup(String,
- *String,com.sleepycat.je.Environment)} method.
- *
- * <p/>A seperate backup machanism is provided by the {@link #takeBackupNoLock(String,String)} method which can take a
- * hot backup against a running broker. This works by finding out the set of files to copy, and then opening them all to
- * read, and repeating this process until a consistent set of open files is obtained. This is done to avoid the
- * situation where the BDB cleanup thread deletes a file, between the directory listing and opening of the file to copy.
- * All consistently opened files are copied. This is the default mechanism the the {@link #main} method of this utility
- * uses.
- *
- * <p/><table id="crc><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Hot copy all
- * BDB log files from one directory to another. </table>
- */
-public class BDBBackup
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(BDBBackup.class);
-
- /** Used for communicating with the user. */
- private static final Logger console = Logger.getLogger("Console");
-
- /** Defines the suffix used to identify BDB log files. */
- private static final String LOG_FILE_SUFFIX = ".jdb";
-
- /** Defines the command line format for this utility. */
- public static final String[][] COMMAND_LINE_SPEC =
- new String[][]
- {
- { "fromdir", "The path to the directory to back the bdb log file from.", "dir", "true" },
- { "todir", "The path to the directory to save the backed up bdb log files to.", "dir", "true" }
- };
-
- /** Defines the timeout to terminate the backup operation on if it fails to complete. One minte. */
- public static final long TIMEOUT = 60000;
-
- /**
- * Runs a backup of the BDB log files in a specified directory, copying the backed up files to another specified
- * directory.
- *
- * <p/>The following arguments must be specified:
- *
- * <p/><table><caption>Command Line</caption> <tr><th> Option <th> Comment <tr><td> -fromdir <td> The path to the
- * directory to back the bdb log file from. <tr><td> -todir <td> The path to the directory to save the backed up
- * bdb log files to. </table>
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- // Process the command line using standard handling (errors and usage followed by System.exit when it is wrong).
- Properties options =
- CommandLineParser.processCommandLine(args, new CommandLineParser(COMMAND_LINE_SPEC), System.getProperties());
-
- // Extract the from and to directory locations and perform a backup between them.
- try
- {
- String fromDir = options.getProperty("fromdir");
- String toDir = options.getProperty("todir");
-
- log.info("BDBBackup Utility: Starting Hot Backup.");
-
- BDBBackup bdbBackup = new BDBBackup();
- String[] backedUpFiles = bdbBackup.takeBackupNoLock(fromDir, toDir);
-
- if (log.isInfoEnabled())
- {
- log.info("BDBBackup Utility: Hot Backup Completed. Files backed up: " + backedUpFiles);
- }
- }
- catch (Exception e)
- {
- console.info("Backup script encountered an error and has failed: " + e.getMessage());
- log.error("Backup script got exception: " + e.getMessage(), e);
- System.exit(1);
- }
- }
-
- /**
- * Creates a backup of the BDB log files in the source directory, copying them to the destination directory.
- *
- * @param fromdir The source directory path.
- * @param todir The destination directory path.
- * @param environment An open BDB environment to perform the back up.
- *
- * @throws DatabaseException Any underlying execeptions from BDB are allowed to fall through.
- */
- public void takeBackup(String fromdir, String todir, Environment environment) throws DatabaseException
- {
- DbBackup backupHelper = null;
-
- try
- {
- backupHelper = new DbBackup(environment);
-
- // Prevent BDB from writing to its log files while the backup it taken.
- backupHelper.startBackup();
-
- // Back up the BDB log files to the destination directory.
- String[] filesForBackup = backupHelper.getLogFilesInBackupSet();
-
- for (int i = 0; i < filesForBackup.length; i++)
- {
- File sourceFile = new File(fromdir + File.separator + filesForBackup[i]);
- File destFile = new File(todir + File.separator + filesForBackup[i]);
- FileUtils.copy(sourceFile, destFile);
- }
- }
- finally
- {
- // Remember to exit backup mode, or all log files won't be cleaned and disk usage will bloat.
- if (backupHelper != null)
- {
- backupHelper.endBackup();
- }
- }
- }
-
- /**
- * Takes a hot backup when another process has locked the BDB database.
- *
- * @param fromdir The source directory path.
- * @param todir The destination directory path.
- *
- * @return A list of all of the names of the files succesfully backed up.
- */
- public String[] takeBackupNoLock(String fromdir, String todir)
- {
- if (log.isDebugEnabled())
- {
- log.debug("public void takeBackupNoLock(String fromdir = " + fromdir + ", String todir = " + todir
- + "): called");
- }
-
- File fromDirFile = new File(fromdir);
-
- if (!fromDirFile.isDirectory())
- {
- throw new IllegalArgumentException("The specified fromdir(" + fromdir
- + ") must be the directory containing your bdbstore.");
- }
-
- File toDirFile = new File(todir);
-
- if (!toDirFile.exists())
- {
- // Create directory if it doesn't exist
- toDirFile.mkdirs();
-
- if (log.isDebugEnabled())
- {
- log.debug("Created backup directory:" + toDirFile);
- }
- }
-
- if (!toDirFile.isDirectory())
- {
- throw new IllegalArgumentException("The specified todir(" + todir + ") must be a directory.");
- }
-
- // Repeat until manage to open consistent set of files for reading.
- boolean consistentSet = false;
- FileInputStream[] fileInputStreams = new FileInputStream[0];
- File[] fileSet = new File[0];
- long start = System.currentTimeMillis();
-
- while (!consistentSet)
- {
- // List all .jdb files in the directory.
- fileSet = fromDirFile.listFiles(new FilenameFilter()
- {
- public boolean accept(File dir, String name)
- {
- return name.endsWith(LOG_FILE_SUFFIX);
- }
- });
-
- // Open them all for reading.
- fileInputStreams = new FileInputStream[fileSet.length];
-
- if (fileSet.length == 0)
- {
- throw new RuntimeException("There are no BDB log files to backup in the " + fromdir + " directory.");
- }
-
- for (int i = 0; i < fileSet.length; i++)
- {
- try
- {
- fileInputStreams[i] = new FileInputStream(fileSet[i]);
- }
- catch (FileNotFoundException e)
- {
- // Close any files opened for reading so far.
- for (int j = 0; j < i; j++)
- {
- if (fileInputStreams[j] != null)
- {
- try
- {
- fileInputStreams[j].close();
- }
- catch (IOException ioEx)
- {
- // Rethrow this as a runtime exception, as something strange has happened.
- throw new RuntimeException(ioEx);
- }
- }
- }
-
- // Could not open a consistent file set so try again.
- break;
- }
-
- // A consistent set has been opened if all files were sucesfully opened for reading.
- if (i == (fileSet.length - 1))
- {
- consistentSet = true;
- }
- }
-
- // Check that the script has not timed out, and raise an error if it has.
- long now = System.currentTimeMillis();
- if ((now - start) > TIMEOUT)
- {
- throw new RuntimeException("Hot backup script failed to complete in " + (TIMEOUT / 1000) + " seconds.");
- }
- }
-
- // Copy the consistent set of open files.
- List<String> backedUpFileNames = new LinkedList<String>();
-
- for (int j = 0; j < fileSet.length; j++)
- {
- File destFile = new File(todir + File.separator + fileSet[j].getName());
- try
- {
- FileUtils.copy(fileSet[j], destFile);
- }
- catch (RuntimeException re)
- {
- Throwable cause = re.getCause();
- if ((cause != null) && (cause instanceof IOException))
- {
- throw new RuntimeException(re.getMessage() + " fromDir:" + fromdir + " toDir:" + toDirFile, cause);
- }
- else
- {
- throw re;
- }
- }
-
- backedUpFileNames.add(destFile.getName());
-
- // Close all of the files.
- try
- {
- fileInputStreams[j].close();
- }
- catch (IOException e)
- {
- // Rethrow this as a runtime exception, as something strange has happened.
- throw new RuntimeException(e);
- }
- }
-
- return backedUpFileNames.toArray(new String[backedUpFileNames.size()]);
- }
-
- /*
- * Creates an environment for the bdb log files in the specified directory. This envrinonment can only be used
- * to backup these files, if they are not locked by another database instance.
- *
- * @param fromdir The path to the directory to create the environment for.
- *
- * @throws DatabaseException Any underlying exceptions from BDB are allowed to fall through.
- */
- private Environment createSourceDirEnvironment(String fromdir) throws DatabaseException
- {
- // Initialize the BDB backup utility on the source directory.
- return new Environment(new File(fromdir), new EnvironmentConfig());
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
deleted file mode 100644
index f900159808..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
+++ /dev/null
@@ -1,2124 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import java.io.File;
-import java.lang.ref.SoftReference;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
-import org.apache.qpid.server.logging.messages.MessageStoreMessages;
-import org.apache.qpid.server.logging.messages.TransactionLogMessages;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MessageStoreRecoveryHandler;
-import org.apache.qpid.server.store.StorableMessageMetaData;
-import org.apache.qpid.server.store.StoredMemoryMessage;
-import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
-import org.apache.qpid.server.store.TransactionLogResource;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler;
-import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler;
-import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
-import org.apache.qpid.server.store.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_5;
-import org.apache.qpid.server.store.berkeleydb.records.ExchangeRecord;
-import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
-import org.apache.qpid.server.store.berkeleydb.tuples.BindingTupleBindingFactory;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTB_5;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageMetaDataTupleBindingFactory;
-import org.apache.qpid.server.store.berkeleydb.tuples.QueueEntryTB;
-import org.apache.qpid.server.store.berkeleydb.tuples.QueueTupleBindingFactory;
-
-import com.sleepycat.bind.EntryBinding;
-import com.sleepycat.bind.tuple.ByteBinding;
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.je.CheckpointConfig;
-import com.sleepycat.je.Cursor;
-import com.sleepycat.je.Database;
-import com.sleepycat.je.DatabaseConfig;
-import com.sleepycat.je.DatabaseEntry;
-import com.sleepycat.je.DatabaseException;
-import com.sleepycat.je.Environment;
-import com.sleepycat.je.EnvironmentConfig;
-import com.sleepycat.je.LockMode;
-import com.sleepycat.je.OperationStatus;
-import com.sleepycat.je.TransactionConfig;
-
-/**
- * BDBMessageStore implements a persistent {@link MessageStore} using the BDB high performance log.
- *
- * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Accept
- * transaction boundary demarcations: Begin, Commit, Abort. <tr><td> Store and remove queues. <tr><td> Store and remove
- * exchanges. <tr><td> Store and remove messages. <tr><td> Bind and unbind queues to exchanges. <tr><td> Enqueue and
- * dequeue messages to queues. <tr><td> Generate message identifiers. </table>
- */
-@SuppressWarnings({"unchecked"})
-public class BDBMessageStore implements MessageStore
-{
- private static final Logger _log = Logger.getLogger(BDBMessageStore.class);
-
- static final int DATABASE_FORMAT_VERSION = 5;
- private static final String DATABASE_FORMAT_VERSION_PROPERTY = "version";
- public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path";
-
- private Environment _environment;
-
- private String MESSAGEMETADATADB_NAME = "messageMetaDataDb";
- private String MESSAGECONTENTDB_NAME = "messageContentDb";
- private String QUEUEBINDINGSDB_NAME = "queueBindingsDb";
- private String DELIVERYDB_NAME = "deliveryDb";
- private String EXCHANGEDB_NAME = "exchangeDb";
- private String QUEUEDB_NAME = "queueDb";
- private Database _messageMetaDataDb;
- private Database _messageContentDb;
- private Database _queueBindingsDb;
- private Database _deliveryDb;
- private Database _exchangeDb;
- private Database _queueDb;
-
- /* =======
- * Schema:
- * =======
- *
- * Queue:
- * name(AMQShortString) - name(AMQShortString), owner(AMQShortString),
- * arguments(FieldTable encoded as binary), exclusive (boolean)
- *
- * Exchange:
- * name(AMQShortString) - name(AMQShortString), typeName(AMQShortString), autodelete (boolean)
- *
- * Binding:
- * exchangeName(AMQShortString), queueName(AMQShortString), routingKey(AMQShortString),
- * arguments (FieldTable encoded as binary) - 0 (zero)
- *
- * QueueEntry:
- * queueName(AMQShortString), messageId (long) - 0 (zero)
- *
- * Message (MetaData):
- * messageId (long) - bodySize (integer), metaData (MessageMetaData encoded as binary)
- *
- * Message (Content):
- * messageId (long), byteOffset (integer) - dataLength(integer), data(binary);
- */
-
- private LogSubject _logSubject;
-
- private final AtomicLong _messageId = new AtomicLong(0);
-
- private final CommitThread _commitThread = new CommitThread("Commit-Thread");
-
- // Factory Classes to create the TupleBinding objects that reflect the version instance of this BDBStore
- private MessageMetaDataTupleBindingFactory _metaDataTupleBindingFactory;
- private QueueTupleBindingFactory _queueTupleBindingFactory;
- private BindingTupleBindingFactory _bindingTupleBindingFactory;
-
- /** The data version this store should run with */
- private int _version;
- private enum State
- {
- INITIAL,
- CONFIGURING,
- CONFIGURED,
- RECOVERING,
- STARTED,
- CLOSING,
- CLOSED
- }
-
- private State _state = State.INITIAL;
-
- private TransactionConfig _transactionConfig = new TransactionConfig();
-
- private boolean _readOnly = false;
-
- private boolean _configured;
-
-
- public BDBMessageStore()
- {
- this(DATABASE_FORMAT_VERSION);
- }
-
- public BDBMessageStore(int version)
- {
- _version = version;
- }
-
- private void setDatabaseNames(int version)
- {
- if (version > 1)
- {
- MESSAGEMETADATADB_NAME += "_v" + version;
-
- MESSAGECONTENTDB_NAME += "_v" + version;
-
- QUEUEDB_NAME += "_v" + version;
-
- DELIVERYDB_NAME += "_v" + version;
-
- EXCHANGEDB_NAME += "_v" + version;
-
- QUEUEBINDINGSDB_NAME += "_v" + version;
- }
- }
-
- public void configureConfigStore(String name,
- ConfigurationRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
- {
- _logSubject = logSubject;
- CurrentActor.get().message(_logSubject, ConfigStoreMessages.CREATED(this.getClass().getName()));
-
- if(_configured)
- {
- throw new Exception("ConfigStore already configured");
- }
-
- configure(name,storeConfiguration);
-
- _configured = true;
- stateTransition(State.CONFIGURING, State.CONFIGURED);
-
- recover(recoveryHandler);
- stateTransition(State.RECOVERING, State.STARTED);
- }
-
- public void configureMessageStore(String name,
- MessageStoreRecoveryHandler recoveryHandler,
- Configuration storeConfiguration,
- LogSubject logSubject) throws Exception
- {
- CurrentActor.get().message(_logSubject, MessageStoreMessages.CREATED(this.getClass().getName()));
-
- if(!_configured)
- {
- throw new Exception("ConfigStore not configured");
- }
-
- recoverMessages(recoveryHandler);
- }
-
- public void configureTransactionLog(String name, TransactionLogRecoveryHandler recoveryHandler,
- Configuration storeConfiguration, LogSubject logSubject) throws Exception
- {
- CurrentActor.get().message(_logSubject, TransactionLogMessages.CREATED(this.getClass().getName()));
-
- if(!_configured)
- {
- throw new Exception("ConfigStore not configured");
- }
-
- recoverQueueEntries(recoveryHandler);
-
-
- }
-
- public org.apache.qpid.server.store.TransactionLog.Transaction newTransaction()
- {
- return new BDBTransaction();
- }
-
-
- /**
- * Called after instantiation in order to configure the message store.
- *
- * @param name The name of the virtual host using this store
- * @return whether a new store environment was created or not (to indicate whether recovery is necessary)
- *
- * @throws Exception If any error occurs that means the store is unable to configure itself.
- */
- public boolean configure(String name, Configuration storeConfig) throws Exception
- {
- File environmentPath = new File(storeConfig.getString(ENVIRONMENT_PATH_PROPERTY,
- System.getProperty("QPID_WORK") + "/bdbstore/" + name));
- if (!environmentPath.exists())
- {
- if (!environmentPath.mkdirs())
- {
- throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. "
- + "Ensure the path is correct and that the permissions are correct.");
- }
- }
-
- CurrentActor.get().message(_logSubject, MessageStoreMessages.STORE_LOCATION(environmentPath.getAbsolutePath()));
-
- _version = storeConfig.getInt(DATABASE_FORMAT_VERSION_PROPERTY, DATABASE_FORMAT_VERSION);
-
- return configure(environmentPath, false);
- }
-
- /**
- * @param environmentPath location for the store to be created in/recovered from
- * @param readonly if true then don't allow modifications to an existing store, and don't create a new store if none exists
- * @return whether or not a new store environment was created
- * @throws AMQStoreException
- * @throws DatabaseException
- */
- protected boolean configure(File environmentPath, boolean readonly) throws AMQStoreException, DatabaseException
- {
- _readOnly = readonly;
- stateTransition(State.INITIAL, State.CONFIGURING);
-
- _log.info("Configuring BDB message store");
-
- createTupleBindingFactories(_version);
-
- setDatabaseNames(_version);
-
- return setupStore(environmentPath, readonly);
- }
-
- private void createTupleBindingFactories(int version)
- {
- _bindingTupleBindingFactory = new BindingTupleBindingFactory(version);
- _queueTupleBindingFactory = new QueueTupleBindingFactory(version);
- _metaDataTupleBindingFactory = new MessageMetaDataTupleBindingFactory(version);
- }
-
- /**
- * Move the store state from CONFIGURING to STARTED.
- *
- * This is required if you do not want to perform recovery of the store data
- *
- * @throws AMQStoreException if the store is not in the correct state
- */
- public void start() throws AMQStoreException
- {
- stateTransition(State.CONFIGURING, State.STARTED);
- }
-
- private boolean setupStore(File storePath, boolean readonly) throws DatabaseException, AMQStoreException
- {
- checkState(State.CONFIGURING);
-
- boolean newEnvironment = createEnvironment(storePath, readonly);
-
- verifyVersionByTables();
-
- openDatabases(readonly);
-
- if (!readonly)
- {
- _commitThread.start();
- }
-
- return newEnvironment;
- }
-
- private void verifyVersionByTables() throws DatabaseException
- {
- for (String s : _environment.getDatabaseNames())
- {
- int versionIndex = s.indexOf("_v");
-
- // lack of _v index suggests DB is v1
- // so if _version is not v1 then error
- if (versionIndex == -1)
- {
- if (_version != 1)
- {
- closeEnvironment();
- throw new IllegalArgumentException("Error: Unable to load BDBStore as version " + _version
- + ". Store on disk contains version 1 data.");
- }
- else // DB is v1 and _version is v1
- {
- continue;
- }
- }
-
- // Otherwise Check Versions
- int version = Integer.parseInt(s.substring(versionIndex + 2));
-
- if (version != _version)
- {
- closeEnvironment();
- throw new IllegalArgumentException("Error: Unable to load BDBStore as version " + _version
- + ". Store on disk contains version " + version + " data.");
- }
- }
- }
-
- private synchronized void stateTransition(State requiredState, State newState) throws AMQStoreException
- {
- if (_state != requiredState)
- {
- throw new AMQStoreException("Cannot transition to the state: " + newState + "; need to be in state: " + requiredState
- + "; currently in state: " + _state);
- }
-
- _state = newState;
- }
-
- private void checkState(State requiredState) throws AMQStoreException
- {
- if (_state != requiredState)
- {
- throw new AMQStoreException("Unexpected state: " + _state + "; required state: " + requiredState);
- }
- }
-
- private boolean createEnvironment(File environmentPath, boolean readonly) throws DatabaseException
- {
- _log.info("BDB message store using environment path " + environmentPath.getAbsolutePath());
- EnvironmentConfig envConfig = new EnvironmentConfig();
- // This is what allows the creation of the store if it does not already exist.
- envConfig.setAllowCreate(true);
- envConfig.setTransactional(true);
- envConfig.setConfigParam("je.lock.nLockTables", "7");
-
- // Restore 500,000 default timeout.
- //envConfig.setLockTimeout(15000);
-
- // Added to help diagnosis of Deadlock issue
- // http://www.oracle.com/technology/products/berkeley-db/faq/je_faq.html#23
- if (Boolean.getBoolean("qpid.bdb.lock.debug"))
- {
- envConfig.setConfigParam("je.txn.deadlockStackTrace", "true");
- envConfig.setConfigParam("je.txn.dumpLocks", "true");
- }
-
- // Set transaction mode
- _transactionConfig.setReadCommitted(true);
-
- //This prevents background threads running which will potentially update the store.
- envConfig.setReadOnly(readonly);
- try
- {
- _environment = new Environment(environmentPath, envConfig);
- return false;
- }
- catch (DatabaseException de)
- {
- if (de.getMessage().contains("Environment.setAllowCreate is false"))
- {
- //Allow the creation this time
- envConfig.setAllowCreate(true);
- if (_environment != null )
- {
- _environment.cleanLog();
- _environment.close();
- }
- _environment = new Environment(environmentPath, envConfig);
-
- return true;
- }
- else
- {
- throw de;
- }
- }
- }
-
- private void openDatabases(boolean readonly) throws DatabaseException
- {
- DatabaseConfig dbConfig = new DatabaseConfig();
- dbConfig.setTransactional(true);
- dbConfig.setAllowCreate(true);
-
- //This is required if we are wanting read only access.
- dbConfig.setReadOnly(readonly);
-
- _messageMetaDataDb = _environment.openDatabase(null, MESSAGEMETADATADB_NAME, dbConfig);
- _queueDb = _environment.openDatabase(null, QUEUEDB_NAME, dbConfig);
- _exchangeDb = _environment.openDatabase(null, EXCHANGEDB_NAME, dbConfig);
- _queueBindingsDb = _environment.openDatabase(null, QUEUEBINDINGSDB_NAME, dbConfig);
- _messageContentDb = _environment.openDatabase(null, MESSAGECONTENTDB_NAME, dbConfig);
- _deliveryDb = _environment.openDatabase(null, DELIVERYDB_NAME, dbConfig);
-
- }
-
- /**
- * Called to close and cleanup any resources used by the message store.
- *
- * @throws Exception If the close fails.
- */
- public void close() throws Exception
- {
- if (_state != State.STARTED)
- {
- return;
- }
-
- _state = State.CLOSING;
-
- _commitThread.close();
- _commitThread.join();
-
- if (_messageMetaDataDb != null)
- {
- _log.info("Closing message metadata database");
- _messageMetaDataDb.close();
- }
-
- if (_messageContentDb != null)
- {
- _log.info("Closing message content database");
- _messageContentDb.close();
- }
-
- if (_exchangeDb != null)
- {
- _log.info("Closing exchange database");
- _exchangeDb.close();
- }
-
- if (_queueBindingsDb != null)
- {
- _log.info("Closing bindings database");
- _queueBindingsDb.close();
- }
-
- if (_queueDb != null)
- {
- _log.info("Closing queue database");
- _queueDb.close();
- }
-
- if (_deliveryDb != null)
- {
- _log.info("Close delivery database");
- _deliveryDb.close();
- }
-
- closeEnvironment();
-
- _state = State.CLOSED;
-
- CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED());
- }
-
- private void closeEnvironment() throws DatabaseException
- {
- if (_environment != null)
- {
- if(!_readOnly)
- {
- // Clean the log before closing. This makes sure it doesn't contain
- // redundant data. Closing without doing this means the cleaner may not
- // get a chance to finish.
- _environment.cleanLog();
- }
- _environment.close();
- }
- }
-
-
- public void recover(ConfigurationRecoveryHandler recoveryHandler) throws AMQStoreException
- {
- stateTransition(State.CONFIGURED, State.RECOVERING);
-
- CurrentActor.get().message(_logSubject,MessageStoreMessages.RECOVERY_START());
-
- try
- {
- QueueRecoveryHandler qrh = recoveryHandler.begin(this);
- loadQueues(qrh);
-
- ExchangeRecoveryHandler erh = qrh.completeQueueRecovery();
- loadExchanges(erh);
-
- BindingRecoveryHandler brh = erh.completeExchangeRecovery();
- recoverBindings(brh);
-
- brh.completeBindingRecovery();
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error recovering persistent state: " + e.getMessage(), e);
- }
-
- }
-
- private void loadQueues(QueueRecoveryHandler qrh) throws DatabaseException
- {
- Cursor cursor = null;
-
- try
- {
- cursor = _queueDb.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding binding = _queueTupleBindingFactory.getInstance();
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- QueueRecord queueRecord = (QueueRecord) binding.entryToObject(value);
-
- String queueName = queueRecord.getNameShortString() == null ? null :
- queueRecord.getNameShortString().asString();
- String owner = queueRecord.getOwner() == null ? null :
- queueRecord.getOwner().asString();
- boolean exclusive = queueRecord.isExclusive();
-
- FieldTable arguments = queueRecord.getArguments();
-
- qrh.queue(queueName, owner, exclusive, arguments);
- }
-
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
- }
-
-
- private void loadExchanges(ExchangeRecoveryHandler erh) throws DatabaseException
- {
- Cursor cursor = null;
-
- try
- {
- cursor = _exchangeDb.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding binding = new ExchangeTB();
-
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- ExchangeRecord exchangeRec = (ExchangeRecord) binding.entryToObject(value);
-
- String exchangeName = exchangeRec.getNameShortString() == null ? null :
- exchangeRec.getNameShortString().asString();
- String type = exchangeRec.getType() == null ? null :
- exchangeRec.getType().asString();
- boolean autoDelete = exchangeRec.isAutoDelete();
-
- erh.exchange(exchangeName, type, autoDelete);
- }
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
-
- }
-
- private void recoverBindings(BindingRecoveryHandler brh) throws DatabaseException
- {
- Cursor cursor = null;
- try
- {
- cursor = _queueBindingsDb.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding binding = _bindingTupleBindingFactory.getInstance();
-
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- //yes, this is retrieving all the useful information from the key only.
- //For table compatibility it shall currently be left as is
- BindingKey bindingRecord = (BindingKey) binding.entryToObject(key);
-
- String exchangeName = bindingRecord.getExchangeName() == null ? null :
- bindingRecord.getExchangeName().asString();
- String queueName = bindingRecord.getQueueName() == null ? null :
- bindingRecord.getQueueName().asString();
- String routingKey = bindingRecord.getRoutingKey() == null ? null :
- bindingRecord.getRoutingKey().asString();
- ByteBuffer argumentsBB = (bindingRecord.getArguments() == null ? null :
- java.nio.ByteBuffer.wrap(bindingRecord.getArguments().getDataAsBytes()));
-
- brh.binding(exchangeName, queueName, routingKey, argumentsBB);
- }
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
-
- }
-
- private void recoverMessages(MessageStoreRecoveryHandler msrh) throws DatabaseException
- {
- StoredMessageRecoveryHandler mrh = msrh.begin();
-
- Cursor cursor = null;
- try
- {
- cursor = _messageMetaDataDb.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class);;
-
- DatabaseEntry value = new DatabaseEntry();
- EntryBinding valueBinding = _metaDataTupleBindingFactory.getInstance();
-
- long maxId = 0;
-
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- long messageId = (Long) keyBinding.entryToObject(key);
- StorableMessageMetaData metaData = (StorableMessageMetaData) valueBinding.entryToObject(value);
-
- StoredBDBMessage message = new StoredBDBMessage(messageId, metaData, false);
- mrh.message(message);
-
- maxId = Math.max(maxId, messageId);
- }
-
- _messageId.set(maxId);
- }
- catch (DatabaseException e)
- {
- _log.error("Database Error: " + e.getMessage(), e);
- throw e;
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
- }
-
- private void recoverQueueEntries(TransactionLogRecoveryHandler recoveryHandler)
- throws DatabaseException
- {
- QueueEntryRecoveryHandler qerh = recoveryHandler.begin(this);
-
- ArrayList<QueueEntryKey> entries = new ArrayList<QueueEntryKey>();
-
- Cursor cursor = null;
- try
- {
- cursor = _deliveryDb.openCursor(null, null);
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new QueueEntryTB();
-
- DatabaseEntry value = new DatabaseEntry();
-
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- QueueEntryKey qek = (QueueEntryKey) keyBinding.entryToObject(key);
-
- entries.add(qek);
- }
-
- try
- {
- cursor.close();
- }
- finally
- {
- cursor = null;
- }
-
- for(QueueEntryKey entry : entries)
- {
- AMQShortString queueName = entry.getQueueName();
- long messageId = entry.getMessageId();
-
- qerh.queueEntry(queueName.asString(),messageId);
- }
- }
- catch (DatabaseException e)
- {
- _log.error("Database Error: " + e.getMessage(), e);
- throw e;
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
-
- qerh.completeQueueEntryRecovery();
- }
-
- /**
- * Removes the specified message from the store.
- *
- * @param messageId Identifies the message to remove.
- *
- * @throws AMQInternalException If the operation fails for any reason.
- */
- public void removeMessage(Long messageId) throws AMQStoreException
- {
- // _log.debug("public void removeMessage(Long messageId = " + messageId): called");
-
- com.sleepycat.je.Transaction tx = null;
-
- Cursor cursor = null;
- try
- {
- tx = _environment.beginTransaction(null, null);
-
- //remove the message meta data from the store
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding metaKeyBindingTuple = TupleBinding.getPrimitiveBinding(Long.class);
- metaKeyBindingTuple.objectToEntry(messageId, key);
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Removing message id " + messageId);
- }
-
-
- OperationStatus status = _messageMetaDataDb.delete(tx, key);
- if (status == OperationStatus.NOTFOUND)
- {
- tx.abort();
-
- throw new AMQStoreException("Message metadata not found for message id " + messageId);
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Deleted metadata for message " + messageId);
- }
-
- //now remove the content data from the store if there is any.
-
- DatabaseEntry contentKeyEntry = new DatabaseEntry();
- MessageContentKey_5 mck = new MessageContentKey_5(messageId,0);
-
- TupleBinding<MessageContentKey> contentKeyTupleBinding = new MessageContentKeyTB_5();
- contentKeyTupleBinding.objectToEntry(mck, contentKeyEntry);
-
- //Use a partial record for the value to prevent retrieving the
- //data itself as we only need the key to identify what to remove.
- DatabaseEntry value = new DatabaseEntry();
- value.setPartial(0, 0, true);
-
- cursor = _messageContentDb.openCursor(tx, null);
-
- status = cursor.getSearchKeyRange(contentKeyEntry, value, LockMode.RMW);
- while (status == OperationStatus.SUCCESS)
- {
- mck = (MessageContentKey_5) contentKeyTupleBinding.entryToObject(contentKeyEntry);
-
- if(mck.getMessageId() != messageId)
- {
- //we have exhausted all chunks for this message id, break
- break;
- }
- else
- {
- status = cursor.delete();
-
- if(status == OperationStatus.NOTFOUND)
- {
- cursor.close();
- cursor = null;
-
- tx.abort();
- throw new AMQStoreException("Content chunk offset" + mck.getOffset() + " not found for message " + messageId);
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Deleted content chunk offset " + mck.getOffset() + " for message " + messageId);
- }
- }
-
- status = cursor.getNext(contentKeyEntry, value, LockMode.RMW);
- }
-
- cursor.close();
- cursor = null;
-
- commit(tx, true);
- }
- catch (DatabaseException e)
- {
- e.printStackTrace();
-
- if (tx != null)
- {
- try
- {
- if(cursor != null)
- {
- cursor.close();
- cursor = null;
- }
-
- tx.abort();
- }
- catch (DatabaseException e1)
- {
- throw new AMQStoreException("Error aborting transaction " + e1, e1);
- }
- }
-
- throw new AMQStoreException("Error removing message with id " + messageId + " from database: " + e.getMessage(), e);
- }
- finally
- {
- if(cursor != null)
- {
- try
- {
- cursor.close();
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error closing database connection: " + e.getMessage(), e);
- }
- }
- }
- }
-
- /**
- * @see DurableConfigurationStore#createExchange(Exchange)
- */
- public void createExchange(Exchange exchange) throws AMQStoreException
- {
- if (_state != State.RECOVERING)
- {
- ExchangeRecord exchangeRec = new ExchangeRecord(exchange.getNameShortString(),
- exchange.getTypeShortString(), exchange.isAutoDelete());
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new AMQShortStringTB();
- keyBinding.objectToEntry(exchange.getNameShortString(), key);
-
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding exchangeBinding = new ExchangeTB();
- exchangeBinding.objectToEntry(exchangeRec, value);
-
- try
- {
- _exchangeDb.put(null, key, value);
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing Exchange with name " + exchange.getName() + " to database: " + e.getMessage(), e);
- }
- }
- }
-
- /**
- * @see DurableConfigurationStore#removeExchange(Exchange)
- */
- public void removeExchange(Exchange exchange) throws AMQStoreException
- {
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new AMQShortStringTB();
- keyBinding.objectToEntry(exchange.getNameShortString(), key);
- try
- {
- OperationStatus status = _exchangeDb.delete(null, key);
- if (status == OperationStatus.NOTFOUND)
- {
- throw new AMQStoreException("Exchange " + exchange.getName() + " not found");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing deleting with name " + exchange.getName() + " from database: " + e.getMessage(), e);
- }
- }
-
-
-
-
- /**
- * @see DurableConfigurationStore#bindQueue(Exchange, AMQShortString, AMQQueue, FieldTable)
- */
- public void bindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQStoreException
- {
- // _log.debug("public void bindQueue(Exchange exchange = " + exchange + ", AMQShortString routingKey = " + routingKey
- // + ", AMQQueue queue = " + queue + ", FieldTable args = " + args + "): called");
-
- if (_state != State.RECOVERING)
- {
- BindingKey bindingRecord = new BindingKey(exchange.getNameShortString(),
- queue.getNameShortString(), routingKey, args);
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = _bindingTupleBindingFactory.getInstance();
-
- keyBinding.objectToEntry(bindingRecord, key);
-
- //yes, this is writing out 0 as a value and putting all the
- //useful info into the key, don't ask me why. For table
- //compatibility it shall currently be left as is
- DatabaseEntry value = new DatabaseEntry();
- ByteBinding.byteToEntry((byte) 0, value);
-
- try
- {
- _queueBindingsDb.put(null, key, value);
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing binding for AMQQueue with name " + queue.getName() + " to exchange "
- + exchange.getName() + " to database: " + e.getMessage(), e);
- }
- }
- }
-
- /**
- * @see DurableConfigurationStore#unbindQueue(Exchange, AMQShortString, AMQQueue, FieldTable)
- */
- public void unbindQueue(Exchange exchange, AMQShortString routingKey, AMQQueue queue, FieldTable args)
- throws AMQStoreException
- {
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = _bindingTupleBindingFactory.getInstance();
- keyBinding.objectToEntry(new BindingKey(exchange.getNameShortString(), queue.getNameShortString(), routingKey, args), key);
-
- try
- {
- OperationStatus status = _queueBindingsDb.delete(null, key);
- if (status == OperationStatus.NOTFOUND)
- {
- throw new AMQStoreException("Queue binding for queue with name " + queue.getName() + " to exchange "
- + exchange.getName() + " not found");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error deleting queue binding for queue with name " + queue.getName() + " to exchange "
- + exchange.getName() + " from database: " + e.getMessage(), e);
- }
- }
-
- /**
- * @see DurableConfigurationStore#createQueue(AMQQueue)
- */
- public void createQueue(AMQQueue queue) throws AMQStoreException
- {
- createQueue(queue, null);
- }
-
- /**
- * @see DurableConfigurationStore#createQueue(AMQQueue, FieldTable)
- */
- public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQStoreException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("public void createQueue(AMQQueue queue(" + queue.getName() + ") = " + queue + "): called");
- }
-
- QueueRecord queueRecord= new QueueRecord(queue.getNameShortString(),
- queue.getOwner(), queue.isExclusive(), arguments);
-
- createQueue(queueRecord);
- }
-
- /**
- * Makes the specified queue persistent.
- *
- * Only intended for direct use during store upgrades.
- *
- * @param queueRecord Details of the queue to store.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- protected void createQueue(QueueRecord queueRecord) throws AMQStoreException
- {
- if (_state != State.RECOVERING)
- {
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new AMQShortStringTB();
- keyBinding.objectToEntry(queueRecord.getNameShortString(), key);
-
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding queueBinding = _queueTupleBindingFactory.getInstance();
-
- queueBinding.objectToEntry(queueRecord, value);
- try
- {
- _queueDb.put(null, key, value);
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing AMQQueue with name " + queueRecord.getNameShortString().asString()
- + " to database: " + e.getMessage(), e);
- }
- }
- }
-
- /**
- * Updates the specified queue in the persistent store, IF it is already present. If the queue
- * is not present in the store, it will not be added.
- *
- * NOTE: Currently only updates the exclusivity.
- *
- * @param queue The queue to update the entry for.
- * @throws AMQStoreException If the operation fails for any reason.
- */
- public void updateQueue(final AMQQueue queue) throws AMQStoreException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Updating queue: " + queue.getName());
- }
-
- try
- {
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new AMQShortStringTB();
- keyBinding.objectToEntry(queue.getNameShortString(), key);
-
- DatabaseEntry value = new DatabaseEntry();
- DatabaseEntry newValue = new DatabaseEntry();
- TupleBinding queueBinding = _queueTupleBindingFactory.getInstance();
-
- OperationStatus status = _queueDb.get(null, key, value, LockMode.DEFAULT);
- if(status == OperationStatus.SUCCESS)
- {
- //read the existing record and apply the new exclusivity setting
- QueueRecord queueRecord = (QueueRecord) queueBinding.entryToObject(value);
- queueRecord.setExclusive(queue.isExclusive());
-
- //write the updated entry to the store
- queueBinding.objectToEntry(queueRecord, newValue);
-
- _queueDb.put(null, key, newValue);
- }
- else if(status != OperationStatus.NOTFOUND)
- {
- throw new AMQStoreException("Error updating queue details within the store: " + status);
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error updating queue details within the store: " + e,e);
- }
- }
-
- /**
- * Removes the specified queue from the persistent store.
- *
- * @param queue The queue to remove.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- public void removeQueue(final AMQQueue queue) throws AMQStoreException
- {
- AMQShortString name = queue.getNameShortString();
-
- if (_log.isDebugEnabled())
- {
- _log.debug("public void removeQueue(AMQShortString name = " + name + "): called");
- }
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new AMQShortStringTB();
- keyBinding.objectToEntry(name, key);
- try
- {
- OperationStatus status = _queueDb.delete(null, key);
- if (status == OperationStatus.NOTFOUND)
- {
- throw new AMQStoreException("Queue " + name + " not found");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing deleting with name " + name + " from database: " + e.getMessage(), e);
- }
- }
-
- /**
- * Places a message onto a specified queue, in a given transaction.
- *
- * @param tx The transaction for the operation.
- * @param queue The the queue to place the message on.
- * @param messageId The message to enqueue.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- public void enqueueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
- // _log.debug("public void enqueueMessage(Transaction tx = " + tx + ", AMQShortString name = " + name + ", Long messageId): called");
-
- AMQShortString name = new AMQShortString(queue.getResourceName());
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new QueueEntryTB();
- QueueEntryKey dd = new QueueEntryKey(name, messageId);
- keyBinding.objectToEntry(dd, key);
- DatabaseEntry value = new DatabaseEntry();
- ByteBinding.byteToEntry((byte) 0, value);
-
- try
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Enqueuing message " + messageId + " on queue " + name + " [Transaction" + tx + "]");
- }
- _deliveryDb.put(tx, key, value);
- }
- catch (DatabaseException e)
- {
- _log.error("Failed to enqueue: " + e.getMessage(), e);
- throw new AMQStoreException("Error writing enqueued message with id " + messageId + " for queue " + name
- + " to database", e);
- }
- }
-
- /**
- * Extracts a message from a specified queue, in a given transaction.
- *
- * @param tx The transaction for the operation.
- * @param queue The name queue to take the message from.
- * @param messageId The message to dequeue.
- *
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- public void dequeueMessage(final com.sleepycat.je.Transaction tx, final TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
- AMQShortString name = new AMQShortString(queue.getResourceName());
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = new QueueEntryTB();
- QueueEntryKey dd = new QueueEntryKey(name, messageId);
-
- keyBinding.objectToEntry(dd, key);
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Dequeue message id " + messageId);
- }
-
- try
- {
-
- OperationStatus status = _deliveryDb.delete(tx, key);
- if (status == OperationStatus.NOTFOUND)
- {
- throw new AMQStoreException("Unable to find message with id " + messageId + " on queue " + name);
- }
- else if (status != OperationStatus.SUCCESS)
- {
- throw new AMQStoreException("Unable to remove message with id " + messageId + " on queue " + name);
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Removed message " + messageId + ", " + name + " from delivery db");
-
- }
- }
- catch (DatabaseException e)
- {
-
- _log.error("Failed to dequeue message " + messageId + ": " + e.getMessage(), e);
- _log.error(tx);
-
- throw new AMQStoreException("Error accessing database while dequeuing message: " + e.getMessage(), e);
- }
- }
-
- /**
- * Commits all operations performed within a given transaction.
- *
- * @param tx The transaction to commit all operations for.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- private StoreFuture commitTranImpl(final com.sleepycat.je.Transaction tx, boolean syncCommit) throws AMQStoreException
- {
- //if (_log.isDebugEnabled())
- //{
- // _log.debug("public void commitTranImpl() called with (Transaction=" + tx + ", syncCommit= "+ syncCommit + ")");
- //}
-
- if (tx == null)
- {
- throw new AMQStoreException("Fatal internal error: transactional is null at commitTran");
- }
-
- StoreFuture result;
- try
- {
- result = commit(tx, syncCommit);
-
- if (_log.isDebugEnabled())
- {
- _log.debug("commitTranImpl completed for [Transaction:" + tx + "]");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error commit tx: " + e.getMessage(), e);
- }
-
- return result;
- }
-
- /**
- * Abandons all operations performed within a given transaction.
- *
- * @param tx The transaction to abandon.
- *
- * @throws AMQStoreException If the operation fails for any reason.
- */
- public void abortTran(final com.sleepycat.je.Transaction tx) throws AMQStoreException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("abortTran called for [Transaction:" + tx + "]");
- }
-
- try
- {
- tx.abort();
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error aborting transaction: " + e.getMessage(), e);
- }
- }
-
- /**
- * Primarily for testing purposes.
- *
- * @param queueName
- *
- * @return a list of message ids for messages enqueued for a particular queue
- */
- List<Long> getEnqueuedMessages(AMQShortString queueName) throws AMQStoreException
- {
- Cursor cursor = null;
- try
- {
- cursor = _deliveryDb.openCursor(null, null);
-
- DatabaseEntry key = new DatabaseEntry();
-
- QueueEntryKey dd = new QueueEntryKey(queueName, 0);
-
- EntryBinding keyBinding = new QueueEntryTB();
- keyBinding.objectToEntry(dd, key);
-
- DatabaseEntry value = new DatabaseEntry();
-
- LinkedList<Long> messageIds = new LinkedList<Long>();
-
- OperationStatus status = cursor.getSearchKeyRange(key, value, LockMode.DEFAULT);
- dd = (QueueEntryKey) keyBinding.entryToObject(key);
-
- while ((status == OperationStatus.SUCCESS) && dd.getQueueName().equals(queueName))
- {
-
- messageIds.add(dd.getMessageId());
- status = cursor.getNext(key, value, LockMode.DEFAULT);
- if (status == OperationStatus.SUCCESS)
- {
- dd = (QueueEntryKey) keyBinding.entryToObject(key);
- }
- }
-
- return messageIds;
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Database error: " + e.getMessage(), e);
- }
- finally
- {
- if (cursor != null)
- {
- try
- {
- cursor.close();
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error closing cursor: " + e.getMessage(), e);
- }
- }
- }
- }
-
- /**
- * Return a valid, currently unused message id.
- *
- * @return A fresh message id.
- */
- public Long getNewMessageId()
- {
- return _messageId.incrementAndGet();
- }
-
- /**
- * Stores a chunk of message data.
- *
- * @param tx The transaction for the operation.
- * @param messageId The message to store the data for.
- * @param offset The offset of the data chunk in the message.
- * @param contentBody The content of the data chunk.
- *
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- protected void addContent(final com.sleepycat.je.Transaction tx, Long messageId, int offset,
- ByteBuffer contentBody) throws AMQStoreException
- {
- DatabaseEntry key = new DatabaseEntry();
- TupleBinding<MessageContentKey> keyBinding = new MessageContentKeyTB_5();
- keyBinding.objectToEntry(new MessageContentKey_5(messageId, offset), key);
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding<ByteBuffer> messageBinding = new ContentTB();
- messageBinding.objectToEntry(contentBody, value);
- try
- {
- OperationStatus status = _messageContentDb.put(tx, key, value);
- if (status != OperationStatus.SUCCESS)
- {
- throw new AMQStoreException("Error adding content chunk offset" + offset + " for message id " + messageId + ": "
- + status);
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Storing content chunk offset" + offset + " for message " + messageId + "[Transaction" + tx + "]");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing AMQMessage with id " + messageId + " to database: " + e.getMessage(), e);
- }
- }
-
- /**
- * Stores message meta-data.
- *
- * @param tx The transaction for the operation.
- * @param messageId The message to store the data for.
- * @param messageMetaData The message meta data to store.
- *
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- private void storeMetaData(final com.sleepycat.je.Transaction tx, Long messageId, StorableMessageMetaData messageMetaData)
- throws AMQStoreException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("public void storeMetaData(Txn tx = " + tx + ", Long messageId = "
- + messageId + ", MessageMetaData messageMetaData = " + messageMetaData + "): called");
- }
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class);
- keyBinding.objectToEntry(messageId, key);
- DatabaseEntry value = new DatabaseEntry();
-
- TupleBinding messageBinding = _metaDataTupleBindingFactory.getInstance();
- messageBinding.objectToEntry(messageMetaData, value);
- try
- {
- _messageMetaDataDb.put(tx, key, value);
- if (_log.isDebugEnabled())
- {
- _log.debug("Storing message metadata for message id " + messageId + "[Transaction" + tx + "]");
- }
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing message metadata with id " + messageId + " to database: " + e.getMessage(), e);
- }
- }
-
- /**
- * Retrieves message meta-data.
- *
- * @param messageId The message to get the meta-data for.
- *
- * @return The message meta data.
- *
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- public StorableMessageMetaData getMessageMetaData(Long messageId) throws AMQStoreException
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("public MessageMetaData getMessageMetaData(Long messageId = "
- + messageId + "): called");
- }
-
- DatabaseEntry key = new DatabaseEntry();
- EntryBinding keyBinding = TupleBinding.getPrimitiveBinding(Long.class);
- keyBinding.objectToEntry(messageId, key);
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding messageBinding = _metaDataTupleBindingFactory.getInstance();
-
- try
- {
- OperationStatus status = _messageMetaDataDb.get(null, key, value, LockMode.READ_UNCOMMITTED);
- if (status != OperationStatus.SUCCESS)
- {
- throw new AMQStoreException("Metadata not found for message with id " + messageId);
- }
-
- StorableMessageMetaData mdd = (StorableMessageMetaData) messageBinding.entryToObject(value);
-
- return mdd;
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error reading message metadata for message with id " + messageId + ": " + e.getMessage(), e);
- }
- }
-
- /**
- * Fills the provided ByteBuffer with as much content for the specified message as possible, starting
- * from the specified offset in the message.
- *
- * @param messageId The message to get the data for.
- * @param offset The offset of the data within the message.
- * @param dst The destination of the content read back
- *
- * @return The number of bytes inserted into the destination
- *
- * @throws AMQStoreException If the operation fails for any reason, or if the specified message does not exist.
- */
- public int getContent(Long messageId, int offset, ByteBuffer dst) throws AMQStoreException
- {
- DatabaseEntry contentKeyEntry = new DatabaseEntry();
-
- //Start from 0 offset and search for the starting chunk.
- MessageContentKey_5 mck = new MessageContentKey_5(messageId, 0);
- TupleBinding<MessageContentKey> contentKeyTupleBinding = new MessageContentKeyTB_5();
- contentKeyTupleBinding.objectToEntry(mck, contentKeyEntry);
- DatabaseEntry value = new DatabaseEntry();
- TupleBinding<ByteBuffer> contentTupleBinding = new ContentTB();
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Message Id: " + messageId + " Getting content body from offset: " + offset);
- }
-
- int written = 0;
- int seenSoFar = 0;
-
- Cursor cursor = null;
- try
- {
- cursor = _messageContentDb.openCursor(null, null);
-
- OperationStatus status = cursor.getSearchKeyRange(contentKeyEntry, value, LockMode.READ_UNCOMMITTED);
-
- while (status == OperationStatus.SUCCESS)
- {
- mck = (MessageContentKey_5) contentKeyTupleBinding.entryToObject(contentKeyEntry);
- long id = mck.getMessageId();
-
- if(id != messageId)
- {
- //we have exhausted all chunks for this message id, break
- break;
- }
-
- int offsetInMessage = mck.getOffset();
- ByteBuffer buf = (ByteBuffer) contentTupleBinding.entryToObject(value);
-
- final int size = (int) buf.limit();
-
- seenSoFar += size;
-
- if(seenSoFar >= offset)
- {
- byte[] dataAsBytes = buf.array();
-
- int posInArray = offset + written - offsetInMessage;
- int count = size - posInArray;
- if(count > dst.remaining())
- {
- count = dst.remaining();
- }
- dst.put(dataAsBytes,posInArray,count);
- written+=count;
-
- if(dst.remaining() == 0)
- {
- break;
- }
- }
-
- status = cursor.getNext(contentKeyEntry, value, LockMode.RMW);
- }
-
- return written;
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing AMQMessage with id " + messageId + " to database: " + e.getMessage(), e);
- }
- finally
- {
- if(cursor != null)
- {
- try
- {
- cursor.close();
- }
- catch (DatabaseException e)
- {
- throw new AMQStoreException("Error writing AMQMessage with id " + messageId + " to database: " + e.getMessage(), e);
- }
- }
- }
- }
-
- public boolean isPersistent()
- {
- return true;
- }
-
- public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData)
- {
- if(metaData.isPersistent())
- {
- return new StoredBDBMessage(getNewMessageId(), metaData);
- }
- else
- {
- return new StoredMemoryMessage(getNewMessageId(), metaData);
- }
- }
-
-
- //protected getters for the TupleBindingFactories
-
- protected QueueTupleBindingFactory getQueueTupleBindingFactory()
- {
- return _queueTupleBindingFactory;
- }
-
- protected BindingTupleBindingFactory getBindingTupleBindingFactory()
- {
- return _bindingTupleBindingFactory;
- }
-
- protected MessageMetaDataTupleBindingFactory getMetaDataTupleBindingFactory()
- {
- return _metaDataTupleBindingFactory;
- }
-
- //Package getters for the various databases used by the Store
-
- Database getMetaDataDb()
- {
- return _messageMetaDataDb;
- }
-
- Database getContentDb()
- {
- return _messageContentDb;
- }
-
- Database getQueuesDb()
- {
- return _queueDb;
- }
-
- Database getDeliveryDb()
- {
- return _deliveryDb;
- }
-
- Database getExchangesDb()
- {
- return _exchangeDb;
- }
-
- Database getBindingsDb()
- {
- return _queueBindingsDb;
- }
-
- void visitMetaDataDb(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_messageMetaDataDb, visitor);
- }
-
- void visitContentDb(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_messageContentDb, visitor);
- }
-
- void visitQueues(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_queueDb, visitor);
- }
-
- void visitDelivery(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_deliveryDb, visitor);
- }
-
- void visitExchanges(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_exchangeDb, visitor);
- }
-
- void visitBindings(DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- visitDatabase(_queueBindingsDb, visitor);
- }
-
- /**
- * Generic visitDatabase allows iteration through the specified database.
- *
- * @param database The database to visit
- * @param visitor The visitor to give each entry to.
- *
- * @throws DatabaseException If there is a problem with the Database structure
- * @throws AMQStoreException If there is a problem with the Database contents
- */
- void visitDatabase(Database database, DatabaseVisitor visitor) throws DatabaseException, AMQStoreException
- {
- Cursor cursor = database.openCursor(null, null);
-
- try
- {
- DatabaseEntry key = new DatabaseEntry();
- DatabaseEntry value = new DatabaseEntry();
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
- {
- visitor.visit(key, value);
- }
- }
- finally
- {
- if (cursor != null)
- {
- cursor.close();
- }
- }
- }
-
- private StoreFuture commit(com.sleepycat.je.Transaction tx, boolean syncCommit) throws DatabaseException
- {
- // _log.debug("void commit(Transaction tx = " + tx + ", sync = " + syncCommit + "): called");
-
- tx.commitNoSync();
-
- BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit);
- commitFuture.commit();
-
- return commitFuture;
- }
-
- public void startCommitThread()
- {
- _commitThread.start();
- }
-
- private static final class BDBCommitFuture implements StoreFuture
- {
- // private static final Logger _log = Logger.getLogger(BDBCommitFuture.class);
-
- private final CommitThread _commitThread;
- private final com.sleepycat.je.Transaction _tx;
- private DatabaseException _databaseException;
- private boolean _complete;
- private boolean _syncCommit;
-
- public BDBCommitFuture(CommitThread commitThread, com.sleepycat.je.Transaction tx, boolean syncCommit)
- {
- // _log.debug("public Commit(CommitThread commitThread = " + commitThread + ", Transaction tx = " + tx
- // + "): called");
-
- _commitThread = commitThread;
- _tx = tx;
- _syncCommit = syncCommit;
- }
-
- public synchronized void complete()
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("public synchronized void complete(): called (Transaction = " + _tx + ")");
- }
-
- _complete = true;
-
- notifyAll();
- }
-
- public synchronized void abort(DatabaseException databaseException)
- {
- // _log.debug("public synchronized void abort(DatabaseException databaseException = " + databaseException
- // + "): called");
-
- _complete = true;
- _databaseException = databaseException;
-
- notifyAll();
- }
-
- public void commit() throws DatabaseException
- {
- //_log.debug("public void commit(): called");
-
- _commitThread.addJob(this);
-
- if(!_syncCommit)
- {
- _log.debug("CommitAsync was requested, returning immediately.");
- return;
- }
-
- synchronized (BDBCommitFuture.this)
- {
- while (!_complete)
- {
- try
- {
- wait(250);
- }
- catch (InterruptedException e)
- {
- // _log.error("Unexpected thread interruption: " + e, e);
- throw new RuntimeException(e);
- }
- }
-
- // _log.debug("Commit completed, _databaseException = " + _databaseException);
-
- if (_databaseException != null)
- {
- throw _databaseException;
- }
- }
- }
-
- public synchronized boolean isComplete()
- {
- return _complete;
- }
-
- public void waitForCompletion()
- {
- while (!isComplete())
- {
- try
- {
- wait(250);
- }
- catch (InterruptedException e)
- {
- //TODO Should we ignore, or throw a 'StoreException'?
- throw new RuntimeException(e);
- }
- }
- }
- }
-
- /**
- * Implements a thread which batches and commits a queue of {@link BDBCommitFuture} operations. The commit operations
- * themselves are responsible for adding themselves to the queue and waiting for the commit to happen before
- * continuing, but it is the responsibility of this thread to tell the commit operations when they have been
- * completed by calling back on their {@link BDBCommitFuture#complete()} and {@link BDBCommitFuture#abort} methods.
- *
- * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collarations </table>
- */
- private class CommitThread extends Thread
- {
- // private final Logger _log = Logger.getLogger(CommitThread.class);
-
- private final AtomicBoolean _stopped = new AtomicBoolean(false);
- private final AtomicReference<Queue<BDBCommitFuture>> _jobQueue = new AtomicReference<Queue<BDBCommitFuture>>(new ConcurrentLinkedQueue<BDBCommitFuture>());
- private final CheckpointConfig _config = new CheckpointConfig();
- private final Object _lock = new Object();
-
- public CommitThread(String name)
- {
- super(name);
- _config.setForce(true);
-
- }
-
- public void run()
- {
- while (!_stopped.get())
- {
- synchronized (_lock)
- {
- while (!_stopped.get() && !hasJobs())
- {
- try
- {
- // RHM-7 Periodically wake up and check, just in case we
- // missed a notification. Don't want to lock the broker hard.
- _lock.wait(250);
- }
- catch (InterruptedException e)
- {
- // _log.info(getName() + " interrupted. ");
- }
- }
- }
- processJobs();
- }
- }
-
- private void processJobs()
- {
- // _log.debug("private void processJobs(): called");
-
- // we replace the old queue atomically with a new one and this avoids any need to
- // copy elements out of the queue
- Queue<BDBCommitFuture> jobs = _jobQueue.getAndSet(new ConcurrentLinkedQueue<BDBCommitFuture>());
-
- try
- {
- // _environment.checkpoint(_config);
- _environment.sync();
-
- for (BDBCommitFuture commit : jobs)
- {
- commit.complete();
- }
- }
- catch (DatabaseException e)
- {
- for (BDBCommitFuture commit : jobs)
- {
- commit.abort(e);
- }
- }
-
- }
-
- private boolean hasJobs()
- {
- return !_jobQueue.get().isEmpty();
- }
-
- public void addJob(BDBCommitFuture commit)
- {
- synchronized (_lock)
- {
- _jobQueue.get().add(commit);
- _lock.notifyAll();
- }
- }
-
- public void close()
- {
- synchronized (_lock)
- {
- _stopped.set(true);
- _lock.notifyAll();
- }
- }
- }
-
-
- private class StoredBDBMessage implements StoredMessage
- {
-
- private final long _messageId;
- private volatile SoftReference<StorableMessageMetaData> _metaDataRef;
- private com.sleepycat.je.Transaction _txn;
-
- StoredBDBMessage(long messageId, StorableMessageMetaData metaData)
- {
- this(messageId, metaData, true);
- }
-
-
- StoredBDBMessage(long messageId,
- StorableMessageMetaData metaData, boolean persist)
- {
- try
- {
- _messageId = messageId;
-
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
- if(persist)
- {
- _txn = _environment.beginTransaction(null, null);
- storeMetaData(_txn, messageId, metaData);
- }
- }
- catch (DatabaseException e)
- {
- throw new RuntimeException(e);
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
-
- }
-
- public StorableMessageMetaData getMetaData()
- {
- StorableMessageMetaData metaData = _metaDataRef.get();
- if(metaData == null)
- {
- try
- {
- metaData = BDBMessageStore.this.getMessageMetaData(_messageId);
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
- _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData);
- }
-
- return metaData;
- }
-
- public long getMessageNumber()
- {
- return _messageId;
- }
-
- public void addContent(int offsetInMessage, java.nio.ByteBuffer src)
- {
- try
- {
- BDBMessageStore.this.addContent(_txn, _messageId, offsetInMessage, src);
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public int getContent(int offsetInMessage, java.nio.ByteBuffer dst)
- {
- try
- {
- return BDBMessageStore.this.getContent(_messageId, offsetInMessage, dst);
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public StoreFuture flushToStore()
- {
- try
- {
- if(_txn != null)
- {
- //if(_log.isDebugEnabled())
- //{
- // _log.debug("Flushing message " + _messageId + " to store");
- //}
- BDBMessageStore.this.commitTranImpl(_txn, true);
- }
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
- finally
- {
- _txn = null;
- }
- return IMMEDIATE_FUTURE;
- }
-
- public void remove()
- {
- flushToStore();
- try
- {
- BDBMessageStore.this.removeMessage(_messageId);
- }
- catch (AMQStoreException e)
- {
- throw new RuntimeException(e);
- }
- }
- }
-
- private class BDBTransaction implements Transaction
- {
- private com.sleepycat.je.Transaction _txn;
-
- private BDBTransaction()
- {
- try
- {
- _txn = _environment.beginTransaction(null, null);
- }
- catch (DatabaseException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
- BDBMessageStore.this.enqueueMessage(_txn, queue, messageId);
- }
-
- public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException
- {
- BDBMessageStore.this.dequeueMessage(_txn, queue, messageId);
-
- }
-
- public void commitTran() throws AMQStoreException
- {
- BDBMessageStore.this.commitTranImpl(_txn, true);
- }
-
- public StoreFuture commitTranAsync() throws AMQStoreException
- {
- return BDBMessageStore.this.commitTranImpl(_txn, false);
- }
-
- public void abortTran() throws AMQStoreException
- {
- BDBMessageStore.this.abortTran(_txn);
- }
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgrade.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgrade.java
deleted file mode 100644
index 211c025dcd..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgrade.java
+++ /dev/null
@@ -1,1125 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.store.berkeleydb.BDBMessageStore;
-import org.apache.qpid.server.store.berkeleydb.BindingKey;
-import org.apache.qpid.server.store.berkeleydb.ContentTB;
-import org.apache.qpid.server.store.berkeleydb.DatabaseVisitor;
-import org.apache.qpid.server.store.berkeleydb.ExchangeTB;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_4;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_5;
-import org.apache.qpid.server.store.berkeleydb.records.ExchangeRecord;
-import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTB_4;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTB_5;
-import org.apache.qpid.server.store.berkeleydb.tuples.QueueEntryTB;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.NullRootMessageLogger;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.util.FileUtils;
-import org.apache.commons.cli.PosixParser;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-
-import java.io.File;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.nio.ByteBuffer;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map.Entry;
-
-import com.sleepycat.je.DatabaseEntry;
-import com.sleepycat.je.DatabaseException;
-import com.sleepycat.je.Database;
-import com.sleepycat.je.Environment;
-import com.sleepycat.je.EnvironmentConfig;
-import com.sleepycat.bind.tuple.TupleBinding;
-
-/**
- * This is a simple BerkeleyDB Store upgrade tool that will upgrade a V4 Store to a V5 Store.
- *
- * Currently upgrade is fixed from v4 -> v5
- *
- * Improvments:
- * - Add List BDBMessageStore.getDatabases(); This can the be iterated to guard against new DBs being added.
- * - A version in the store would allow automated upgrade or later with more available versions interactive upgrade.
- * - Add process logging and disable all Store and Qpid logging.
- */
-public class BDBStoreUpgrade
-{
- private static final Logger _logger = LoggerFactory.getLogger(BDBStoreUpgrade.class);
- /** The Store Directory that needs upgrading */
- File _fromDir;
- /** The Directory that will be made to contain the upgraded store */
- File _toDir;
- /** The Directory that will be made to backup the original store if required */
- File _backupDir;
-
- /** The Old Store */
- BDBMessageStore _oldMessageStore;
- /** The New Store */
- BDBMessageStore _newMessageStore;
- /** The file ending that is used by BDB Store Files */
- private static final String BDB_FILE_ENDING = ".jdb";
-
- static final Options _options = new Options();
- static CommandLine _commandLine;
- private boolean _interactive;
- private boolean _force;
-
- private static final String VERSION = "3.0";
- private static final String USER_ABORTED_PROCESS = "User aborted process";
- private static final int LOWEST_SUPPORTED_STORE_VERSION = 4;
- private static final String PREVIOUS_STORE_VERSION_UNSUPPORTED = "Store upgrade from version {0} is not supported."
- + " You must first run the previous store upgrade tool.";
- private static final String FOLLOWING_STORE_VERSION_UNSUPPORTED = "Store version {0} is newer than this tool supports. "
- + "You must use a newer version of the store upgrade tool";
- private static final String STORE_ALREADY_UPGRADED = "Store has already been upgraded to version {0}.";
-
- private static final String OPTION_INPUT_SHORT = "i";
- private static final String OPTION_INPUT = "input";
- private static final String OPTION_OUTPUT_SHORT = "o";
- private static final String OPTION_OUTPUT = "output";
- private static final String OPTION_BACKUP_SHORT = "b";
- private static final String OPTION_BACKUP = "backup";
- private static final String OPTION_QUIET_SHORT = "q";
- private static final String OPTION_QUIET = "quiet";
- private static final String OPTION_FORCE_SHORT = "f";
- private static final String OPTION_FORCE = "force";
- private boolean _inplace = false;
-
- public BDBStoreUpgrade(String fromDir, String toDir, String backupDir, boolean interactive, boolean force)
- {
- _interactive = interactive;
- _force = force;
-
- _fromDir = new File(fromDir);
- if (!_fromDir.exists())
- {
- throw new IllegalArgumentException("BDBStore path '" + fromDir + "' could not be read. "
- + "Ensure the path is correct and that the permissions are correct.");
- }
-
- if (!isDirectoryAStoreDir(_fromDir))
- {
- throw new IllegalArgumentException("Specified directory '" + fromDir + "' does not contain a valid BDBMessageStore.");
- }
-
- if (toDir == null)
- {
- _inplace = true;
- _toDir = new File(fromDir+"-Inplace");
- }
- else
- {
- _toDir = new File(toDir);
- }
-
- if (_toDir.exists())
- {
- if (_interactive)
- {
- if (toDir == null)
- {
- System.out.println("Upgrading in place:" + fromDir);
- }
- else
- {
- System.out.println("Upgrade destination: '" + toDir + "'");
- }
-
- if (userInteract("Upgrade destination exists do you wish to replace it?"))
- {
- if (!FileUtils.delete(_toDir, true))
- {
- throw new IllegalArgumentException("Unable to remove upgrade destination '" + _toDir + "'");
- }
- }
- else
- {
- throw new IllegalArgumentException("Upgrade destination '" + _toDir + "' already exists. ");
- }
- }
- else
- {
- if (_force)
- {
- if (!FileUtils.delete(_toDir, true))
- {
- throw new IllegalArgumentException("Unable to remove upgrade destination '" + _toDir + "'");
- }
- }
- else
- {
- throw new IllegalArgumentException("Upgrade destination '" + _toDir + "' already exists. ");
- }
- }
- }
-
- if (!_toDir.mkdirs())
- {
- throw new IllegalArgumentException("Upgrade destination '" + _toDir + "' could not be created. "
- + "Ensure the path is correct and that the permissions are correct.");
- }
-
- if (backupDir != null)
- {
- if (backupDir.equals(""))
- {
- _backupDir = new File(_fromDir.getAbsolutePath().toString() + "-Backup");
- }
- else
- {
- _backupDir = new File(backupDir);
- }
- }
- else
- {
- _backupDir = null;
- }
- }
-
- private static String ANSWER_OPTIONS = " Yes/No/Abort? ";
- private static String ANSWER_NO = "no";
- private static String ANSWER_N = "n";
- private static String ANSWER_YES = "yes";
- private static String ANSWER_Y = "y";
- private static String ANSWER_ABORT = "abort";
- private static String ANSWER_A = "a";
-
- /**
- * Interact with the user via System.in and System.out. If the user wishes to Abort then a RuntimeException is thrown.
- * Otherwise the method will return based on their response true=yes false=no.
- *
- * @param message Message to print out
- *
- * @return boolean response from user if they wish to proceed
- */
- private boolean userInteract(String message)
- {
- System.out.print(message + ANSWER_OPTIONS);
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
-
- String input = "";
- try
- {
- input = br.readLine();
- }
- catch (IOException e)
- {
- input = "";
- }
-
- if (input.equalsIgnoreCase(ANSWER_Y) || input.equalsIgnoreCase(ANSWER_YES))
- {
- return true;
- }
- else
- {
- if (input.equalsIgnoreCase(ANSWER_N) || input.equalsIgnoreCase(ANSWER_NO))
- {
- return false;
- }
- else
- {
- if (input.equalsIgnoreCase(ANSWER_A) || input.equalsIgnoreCase(ANSWER_ABORT))
- {
- throw new RuntimeException(USER_ABORTED_PROCESS);
- }
- }
- }
-
- return userInteract(message);
- }
-
- /**
- * Upgrade a Store of a specified version to the latest version.
- *
- * @param version the version of the current store
- *
- * @throws Exception
- */
- public void upgradeFromVersion(int version) throws Exception
- {
- upgradeFromVersion(version, _fromDir, _toDir, _backupDir, _force,
- _inplace);
- }
-
- /**
- * Upgrade a Store of a specified version to the latest version.
- *
- * @param version the version of the current store
- * @param fromDir the directory with the old Store
- * @param toDir the directrory to hold the newly Upgraded Store
- * @param backupDir the directrory to backup to if required
- * @param force suppress all questions
- * @param inplace replace the from dir with the upgraded result in toDir
- *
- * @throws Exception due to Virtualhost/MessageStore.close() being
- * rather poor at exception handling
- * @throws DatabaseException if there is a problem with the store formats
- * @throws AMQException if there is an issue creating Qpid data structures
- */
- public void upgradeFromVersion(int version, File fromDir, File toDir,
- File backupDir, boolean force,
- boolean inplace) throws Exception
- {
- _logger.info("Located store to upgrade at '" + fromDir + "'");
-
- // Verify user has created a backup, giving option to perform backup
- if (_interactive)
- {
- if (!userInteract("Have you performed a DB backup of this store."))
- {
- File backup;
- if (backupDir == null)
- {
- backup = new File(fromDir.getAbsolutePath().toString() + "-Backup");
- }
- else
- {
- backup = backupDir;
- }
-
- if (userInteract("Do you wish to perform a DB backup now? " +
- "(Store will be backed up to '" + backup.getName() + "')"))
- {
- performDBBackup(fromDir, backup, force);
- }
- else
- {
- if (!userInteract("Are you sure wish to proceed with DB migration without backup? " +
- "(For more details of the consequences check the Qpid/BDB Message Store Wiki)."))
- {
- throw new IllegalArgumentException("Upgrade stopped at user request as no DB Backup performed.");
- }
- }
- }
- else
- {
- if (!inplace)
- {
- _logger.info("Upgrade will create a new store at '" + toDir + "'");
- }
-
- _logger.info("Using the contents in the Message Store '" + fromDir + "'");
-
- if (!userInteract("Do you wish to proceed?"))
- {
- throw new IllegalArgumentException("Upgrade stopped as did not wish to proceed");
- }
- }
- }
- else
- {
- if (backupDir != null)
- {
- performDBBackup(fromDir, backupDir, force);
- }
- }
-
- CurrentActor.set(new BrokerActor(new NullRootMessageLogger()));
-
- //Create a new messageStore
- _newMessageStore = new BDBMessageStore();
- _newMessageStore.configure(toDir, false);
- _newMessageStore.start();
-
- try
- {
- //Load the old MessageStore
- switch (version)
- {
- default:
- case 4:
- _oldMessageStore = new BDBMessageStore(4);
- _oldMessageStore.configure(fromDir, true);
- _oldMessageStore.start();
- upgradeFromVersion_4();
- break;
- case 3:
- case 2:
- case 1:
- throw new IllegalArgumentException(MessageFormat.format(PREVIOUS_STORE_VERSION_UNSUPPORTED,
- new Object[] { Integer.toString(version) }));
- }
- }
- finally
- {
- _newMessageStore.close();
- if (_oldMessageStore != null)
- {
- _oldMessageStore.close();
- }
- // if we are running inplace then swap fromDir and toDir
- if (inplace)
- {
- // Remove original copy
- if (FileUtils.delete(fromDir, true))
- {
- // Rename upgraded store
- toDir.renameTo(fromDir);
- }
- else
- {
- throw new RuntimeException("Unable to upgrade inplace as " +
- "unable to delete source '"
- +fromDir+"', Store upgrade " +
- "successfully performed to :"
- +toDir);
- }
- }
- }
- }
-
- private void upgradeFromVersion_4() throws AMQException, DatabaseException
- {
- _logger.info("Starting store upgrade from version 4");
-
- //Migrate _exchangeDb;
- _logger.info("Exchanges");
-
- moveContents(_oldMessageStore.getExchangesDb(), _newMessageStore.getExchangesDb(), "Exchange");
-
- final List<AMQShortString> topicExchanges = new ArrayList<AMQShortString>();
- final TupleBinding exchangeTB = new ExchangeTB();
-
- DatabaseVisitor exchangeListVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- ExchangeRecord exchangeRec = (ExchangeRecord) exchangeTB.entryToObject(value);
- AMQShortString type = exchangeRec.getType();
-
- if (ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(type))
- {
- topicExchanges.add(exchangeRec.getNameShortString());
- }
- }
- };
- _oldMessageStore.visitExchanges(exchangeListVisitor);
-
-
- //Migrate _queueBindingsDb;
- _logger.info("Queue Bindings");
- moveContents(_oldMessageStore.getBindingsDb(), _newMessageStore.getBindingsDb(), "Queue Binding");
-
- //Inspect the bindings to gather a list of queues which are probably durable subscriptions, i.e. those
- //which have a colon in their name and are bound to the Topic exchanges above
- final List<AMQShortString> durableSubQueues = new ArrayList<AMQShortString>();
- final TupleBinding<BindingKey> bindingTB = _oldMessageStore.getBindingTupleBindingFactory().getInstance();
-
- DatabaseVisitor durSubQueueListVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- BindingKey bindingRec = (BindingKey) bindingTB.entryToObject(key);
- AMQShortString queueName = bindingRec.getQueueName();
- AMQShortString exchangeName = bindingRec.getExchangeName();
-
- if (topicExchanges.contains(exchangeName) && queueName.asString().contains(":"))
- {
- durableSubQueues.add(queueName);
- }
- }
- };
- _oldMessageStore.visitBindings(durSubQueueListVisitor);
-
-
- //Migrate _queueDb;
- _logger.info("Queues");
-
- // hold the list of existing queue names
- final List<AMQShortString> existingQueues = new ArrayList<AMQShortString>();
-
- final TupleBinding<QueueRecord> queueTupleBinding = _oldMessageStore.getQueueTupleBindingFactory().getInstance();
-
- DatabaseVisitor queueVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws AMQStoreException
- {
- QueueRecord queueRec = (QueueRecord) queueTupleBinding.entryToObject(value);
- AMQShortString queueName = queueRec.getNameShortString();
-
- //if the queue name is in the gathered list then set its exclusivity true
- if (durableSubQueues.contains(queueName))
- {
- _logger.info("Marking as possible DurableSubscription backing queue: " + queueName);
- queueRec.setExclusive(true);
- }
-
- //The simple call to createQueue with the QueueRecord object is sufficient for a v2->v3 upgrade as
- //the extra 'exclusive' property in v3 will be defaulted to false in the record creation.
- _newMessageStore.createQueue(queueRec);
-
- _count++;
- existingQueues.add(queueName);
- }
- };
- _oldMessageStore.visitQueues(queueVisitor);
-
- logCount(queueVisitor.getVisitedCount(), "Queue");
-
-
- // Look for persistent messages stored for non-durable queues
- _logger.info("Checking for messages previously sent to non-durable queues");
-
- // track all message delivery to existing queues
- final HashSet<Long> queueMessages = new HashSet<Long>();
-
- // hold all non existing queues and their messages IDs
- final HashMap<String, HashSet<Long>> phantomMessageQueues = new HashMap<String, HashSet<Long>>();
-
- // delivery DB visitor to check message delivery and identify non existing queues
- final QueueEntryTB queueEntryTB = new QueueEntryTB();
- DatabaseVisitor messageDeliveryCheckVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- QueueEntryKey entryKey = (QueueEntryKey) queueEntryTB.entryToObject(key);
- Long messageId = entryKey.getMessageId();
- AMQShortString queueName = entryKey.getQueueName();
- if (!existingQueues.contains(queueName))
- {
- String name = queueName.asString();
- HashSet<Long> messages = phantomMessageQueues.get(name);
- if (messages == null)
- {
- messages = new HashSet<Long>();
- phantomMessageQueues.put(name, messages);
- }
- messages.add(messageId);
- _count++;
- }
- else
- {
- queueMessages.add(messageId);
- }
- }
- };
- _oldMessageStore.visitDelivery(messageDeliveryCheckVisitor);
-
- if (phantomMessageQueues.isEmpty())
- {
- _logger.info("No such messages were found");
- }
- else
- {
- _logger.info("Found " + messageDeliveryCheckVisitor.getVisitedCount()+ " such messages in total");
-
- for (Entry<String, HashSet<Long>> phantomQueue : phantomMessageQueues.entrySet())
- {
- String queueName = phantomQueue.getKey();
- HashSet<Long> messages = phantomQueue.getValue();
-
- _logger.info(MessageFormat.format("There are {0} messages which were previously delivered to non-durable queue ''{1}''",messages.size(), queueName));
-
- boolean createQueue;
- if(!_interactive)
- {
- createQueue = true;
- _logger.info("Running in batch-mode, marking queue as durable to ensure retention of the messages.");
- }
- else
- {
- createQueue = userInteract("Do you want to make this queue durable?\n"
- + "NOTE: Answering No will result in these messages being discarded!");
- }
-
- if (createQueue)
- {
- for (Long messageId : messages)
- {
- queueMessages.add(messageId);
- }
- AMQShortString name = new AMQShortString(queueName);
- existingQueues.add(name);
- QueueRecord record = new QueueRecord(name, null, false, null);
- _newMessageStore.createQueue(record);
- }
- }
- }
-
-
- //Migrate _messageMetaDataDb;
- _logger.info("Message MetaData");
-
- final Database newMetaDataDB = _newMessageStore.getMetaDataDb();
- final TupleBinding<Object> oldMetaDataTupleBinding = _oldMessageStore.getMetaDataTupleBindingFactory().getInstance();
- final TupleBinding<Object> newMetaDataTupleBinding = _newMessageStore.getMetaDataTupleBindingFactory().getInstance();
-
- DatabaseVisitor metaDataVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- _count++;
- MessageMetaData metaData = (MessageMetaData) oldMetaDataTupleBinding.entryToObject(value);
-
- // get message id
- Long messageId = TupleBinding.getPrimitiveBinding(Long.class).entryToObject(key);
-
- // ONLY copy data if message is delivered to existing queue
- if (!queueMessages.contains(messageId))
- {
- return;
- }
- DatabaseEntry newValue = new DatabaseEntry();
- newMetaDataTupleBinding.objectToEntry(metaData, newValue);
-
- newMetaDataDB.put(null, key, newValue);
- }
- };
- _oldMessageStore.visitMetaDataDb(metaDataVisitor);
-
- logCount(metaDataVisitor.getVisitedCount(), "Message MetaData");
-
-
- //Migrate _messageContentDb;
- _logger.info("Message Contents");
- final Database newContentDB = _newMessageStore.getContentDb();
-
- final TupleBinding<MessageContentKey> oldContentKeyTupleBinding = new MessageContentKeyTB_4();
- final TupleBinding<MessageContentKey> newContentKeyTupleBinding = new MessageContentKeyTB_5();
- final TupleBinding contentTB = new ContentTB();
-
- DatabaseVisitor contentVisitor = new DatabaseVisitor()
- {
- long _prevMsgId = -1; //Initialise to invalid value
- int _bytesSeenSoFar = 0;
-
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- _count++;
-
- //determine the msgId of the current entry
- MessageContentKey_4 contentKey = (MessageContentKey_4) oldContentKeyTupleBinding.entryToObject(key);
- long msgId = contentKey.getMessageId();
-
- // ONLY copy data if message is delivered to existing queue
- if (!queueMessages.contains(msgId))
- {
- return;
- }
- //if this is a new message, restart the byte offset count.
- if(_prevMsgId != msgId)
- {
- _bytesSeenSoFar = 0;
- }
-
- //determine the content size
- ByteBuffer content = (ByteBuffer) contentTB.entryToObject(value);
- int contentSize = content.limit();
-
- //create the new key: id + previously seen data count
- MessageContentKey_5 newKey = new MessageContentKey_5(msgId, _bytesSeenSoFar);
- DatabaseEntry newKeyEntry = new DatabaseEntry();
- newContentKeyTupleBinding.objectToEntry(newKey, newKeyEntry);
-
- DatabaseEntry newValueEntry = new DatabaseEntry();
- contentTB.objectToEntry(content, newValueEntry);
-
- newContentDB.put(null, newKeyEntry, newValueEntry);
-
- _prevMsgId = msgId;
- _bytesSeenSoFar += contentSize;
- }
- };
- _oldMessageStore.visitContentDb(contentVisitor);
-
- logCount(contentVisitor.getVisitedCount(), "Message Content");
-
-
- //Migrate _deliveryDb;
- _logger.info("Delivery Records");
- final Database deliveryDb =_newMessageStore.getDeliveryDb();
- DatabaseVisitor deliveryDbVisitor = new DatabaseVisitor()
- {
-
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- _count++;
-
- // get message id from entry key
- QueueEntryKey entryKey = (QueueEntryKey) queueEntryTB.entryToObject(key);
- AMQShortString queueName = entryKey.getQueueName();
-
- // ONLY copy data if message queue exists
- if (existingQueues.contains(queueName))
- {
- deliveryDb.put(null, key, value);
- }
- }
- };
- _oldMessageStore.visitDelivery(deliveryDbVisitor);
- logCount(contentVisitor.getVisitedCount(), "Delivery Record");
- }
-
- /**
- * Log the specified count for item in a user friendly way.
- *
- * @param count of items to log
- * @param item description of what is being logged.
- */
- private void logCount(int count, String item)
- {
- _logger.info(" " + count + " " + item + " " + (count == 1 ? "entry" : "entries"));
- }
-
- /**
- * @param oldDatabase The old MessageStoreDB to perform the visit on
- * @param newDatabase The new MessageStoreDB to copy the data to.
- * @param contentName The string name of the content for display purposes.
- *
- * @throws AMQException Due to createQueue thorwing AMQException
- * @throws DatabaseException If there is a problem with the loading of the data
- */
- private void moveContents(Database oldDatabase, final Database newDatabase, String contentName) throws AMQException, DatabaseException
- {
-
- DatabaseVisitor moveVisitor = new DatabaseVisitor()
- {
- public void visit(DatabaseEntry key, DatabaseEntry value) throws DatabaseException
- {
- _count++;
- newDatabase.put(null, key, value);
- }
- };
-
- _oldMessageStore.visitDatabase(oldDatabase, moveVisitor);
-
- logCount(moveVisitor.getVisitedCount(), contentName);
- }
-
- private static void usage()
- {
- System.out.println("usage: BDBStoreUpgrade:\n [-h|--help] [-q|--quiet] [-f|--force] [-b|--backup <Path to backup-db>] " +
- "-i|--input <Path to input-db> [-o|--output <Path to upgraded-db>]");
- }
-
- private static void help()
- {
- System.out.println("usage: BDBStoreUpgrade:");
- System.out.println("Required:");
- for (Object obj : _options.getOptions())
- {
- Option option = (Option) obj;
- if (option.isRequired())
- {
- System.out.println("-" + option.getOpt() + "|--" + option.getLongOpt() + "\t\t-\t" + option.getDescription());
- }
- }
-
- System.out.println("\nOptions:");
- for (Object obj : _options.getOptions())
- {
- Option option = (Option) obj;
- if (!option.isRequired())
- {
- System.out.println("--" + option.getLongOpt() + "|-" + option.getOpt() + "\t\t-\t" + option.getDescription());
- }
- }
- }
-
- static boolean isDirectoryAStoreDir(File directory)
- {
- if (directory.isFile())
- {
- return false;
- }
-
- for (File file : directory.listFiles())
- {
- if (file.isFile())
- {
- if (file.getName().endsWith(BDB_FILE_ENDING))
- {
- return true;
- }
- }
- }
- return false;
- }
-
- static File[] discoverDBStores(File fromDir)
- {
- if (!fromDir.exists())
- {
- throw new IllegalArgumentException("'" + fromDir + "' does not exist unable to upgrade.");
- }
-
- // Ensure we are given a directory
- if (fromDir.isFile())
- {
- throw new IllegalArgumentException("'" + fromDir + "' is not a directory unable to upgrade.");
- }
-
- // Check to see if we have been given a single directory
- if (isDirectoryAStoreDir(fromDir))
- {
- return new File[]{fromDir};
- }
-
- // Check to see if we have been give a directory containing stores.
- List<File> stores = new LinkedList<File>();
-
- for (File directory : fromDir.listFiles())
- {
- if (directory.isDirectory())
- {
- if (isDirectoryAStoreDir(directory))
- {
- stores.add(directory);
- }
- }
- }
-
- return stores.toArray(new File[stores.size()]);
- }
-
- private static void performDBBackup(File source, File backup, boolean force) throws Exception
- {
- if (backup.exists())
- {
- if (force)
- {
- _logger.info("Backup location exists. Forced to remove.");
- FileUtils.delete(backup, true);
- }
- else
- {
- throw new IllegalArgumentException("Unable to perform backup a backup already exists.");
- }
- }
-
- try
- {
- _logger.info("Backing up '" + source + "' to '" + backup + "'");
- FileUtils.copyRecursive(source, backup);
- }
- catch (FileNotFoundException e)
- {
- //Throwing IAE here as this will be reported as a Backup not started
- throw new IllegalArgumentException("Unable to perform backup:" + e.getMessage());
- }
- catch (FileUtils.UnableToCopyException e)
- {
- //Throwing exception here as this will be reported as a Failed Backup
- throw new Exception("Unable to perform backup due to:" + e.getMessage());
- }
- }
-
- public static void main(String[] args) throws ParseException
- {
- setOptions(_options);
-
- final Options helpOptions = new Options();
- setHelpOptions(helpOptions);
-
- //Display help
- boolean displayHelp = false;
- try
- {
- if (new PosixParser().parse(helpOptions, args).hasOption("h"))
- {
- showHelp();
- }
- }
- catch (ParseException pe)
- {
- displayHelp = true;
- }
-
- //Parse commandline for required arguments
- try
- {
- _commandLine = new PosixParser().parse(_options, args);
- }
- catch (ParseException mae)
- {
- if (displayHelp)
- {
- showHelp();
- }
- else
- {
- fatalError(mae.getMessage());
- }
- }
-
- String fromDir = _commandLine.getOptionValue(OPTION_INPUT_SHORT);
- String toDir = _commandLine.getOptionValue(OPTION_OUTPUT_SHORT);
- String backupDir = _commandLine.getOptionValue(OPTION_BACKUP_SHORT);
-
- if (backupDir == null && _commandLine.hasOption(OPTION_BACKUP_SHORT))
- {
- backupDir = "";
- }
-
- //Attempt to locate possible Store to upgrade on input path
- File[] stores = new File[0];
- try
- {
- stores = discoverDBStores(new File(fromDir));
- }
- catch (IllegalArgumentException iae)
- {
- fatalError(iae.getMessage());
- }
-
- boolean interactive = !_commandLine.hasOption(OPTION_QUIET_SHORT);
- boolean force = _commandLine.hasOption(OPTION_FORCE_SHORT);
-
- try{
- for (File store : stores)
- {
-
- // if toDir is null then we are upgrading inplace so we don't need
- // to provide an upgraded toDir when upgrading multiple stores.
- if (toDir == null ||
- // Check to see if we are upgrading a store specified in
- // fromDir or if the directories are nested.
- (stores.length > 0
- && stores[0].toString().length() == fromDir.length()))
- {
- upgrade(store, toDir, backupDir, interactive, force);
- }
- else
- {
- // Add the extra part of path from store to the toDir
- upgrade(store, toDir + File.separator + store.toString().substring(fromDir.length()), backupDir, interactive, force);
- }
- }
- }
- catch (RuntimeException re)
- {
- if (!(USER_ABORTED_PROCESS).equals(re.getMessage()))
- {
- re.printStackTrace();
- _logger.error("Upgrade Failed: " + re.getMessage());
- }
- else
- {
- _logger.error("Upgrade stopped : User aborted");
- }
- }
-
- }
-
- @SuppressWarnings("static-access")
- private static void setOptions(Options options)
- {
- Option input =
- OptionBuilder.isRequired().hasArg().withDescription("Location (Path) of store to upgrade.").withLongOpt(OPTION_INPUT)
- .create(OPTION_INPUT_SHORT);
-
- Option output =
- OptionBuilder.hasArg().withDescription("Location (Path) for the upgraded-db to be written.").withLongOpt(OPTION_OUTPUT)
- .create(OPTION_OUTPUT_SHORT);
-
- Option quiet = new Option(OPTION_QUIET_SHORT, OPTION_QUIET, false, "Disable interactive options.");
-
- Option force = new Option(OPTION_FORCE_SHORT, OPTION_FORCE, false, "Force upgrade removing any existing upgrade target.");
- Option backup =
- OptionBuilder.hasOptionalArg().withDescription("Location (Path) for the backup-db to be written.").withLongOpt(OPTION_BACKUP)
- .create(OPTION_BACKUP_SHORT);
-
- options.addOption(input);
- options.addOption(output);
- options.addOption(quiet);
- options.addOption(force);
- options.addOption(backup);
- setHelpOptions(options);
- }
-
- private static void setHelpOptions(Options options)
- {
- options.addOption(new Option("h", "help", false, "Show this help."));
- }
-
- static void upgrade(File fromDir, String toDir, String backupDir, boolean interactive, boolean force)
- {
-
- _logger.info("Running BDB Message Store upgrade tool: v" + VERSION);
- int version = getStoreVersion(fromDir);
- if (!isVersionUpgradable(version))
- {
- return;
- }
- try
- {
- new BDBStoreUpgrade(fromDir.toString(), toDir, backupDir, interactive, force).upgradeFromVersion(version);
-
- _logger.info("Upgrade complete.");
- }
- catch (IllegalArgumentException iae)
- {
- _logger.error("Upgrade not started due to: " + iae.getMessage());
- }
- catch (DatabaseException de)
- {
- de.printStackTrace();
- _logger.error("Upgrade Failed: " + de.getMessage());
- }
- catch (RuntimeException re)
- {
- if (!(USER_ABORTED_PROCESS).equals(re.getMessage()))
- {
- re.printStackTrace();
- _logger.error("Upgrade Failed: " + re.getMessage());
- }
- else
- {
- throw re;
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- _logger.error("Upgrade Failed: " + e.getMessage());
- }
- }
-
- /**
- * Utility method to verify if store of given version can be upgraded.
- *
- * @param version
- * store version to verify
- * @return true if store can be upgraded, false otherwise
- */
- protected static boolean isVersionUpgradable(int version)
- {
- boolean storeUpgradable = false;
- if (version == 0)
- {
- _logger.error("Existing store version is undefined!");
- }
- else if (version < LOWEST_SUPPORTED_STORE_VERSION)
- {
- _logger.error(MessageFormat.format(PREVIOUS_STORE_VERSION_UNSUPPORTED,
- new Object[] { Integer.toString(version) }));
- }
- else if (version == BDBMessageStore.DATABASE_FORMAT_VERSION)
- {
- _logger.error(MessageFormat.format(STORE_ALREADY_UPGRADED, new Object[] { Integer.toString(version) }));
- }
- else if (version > BDBMessageStore.DATABASE_FORMAT_VERSION)
- {
- _logger.error(MessageFormat.format(FOLLOWING_STORE_VERSION_UNSUPPORTED,
- new Object[] { Integer.toString(version) }));
- }
- else
- {
- _logger.info("Existing store version is " + version);
- storeUpgradable = true;
- }
- return storeUpgradable;
- }
-
- /**
- * Detects existing store version by checking list of database in store
- * environment
- *
- * @param fromDir
- * store folder
- * @return version
- */
- public static int getStoreVersion(File fromDir)
- {
- int version = 0;
- EnvironmentConfig envConfig = new EnvironmentConfig();
- envConfig.setAllowCreate(false);
- envConfig.setTransactional(false);
- envConfig.setReadOnly(true);
- Environment environment = null;
- try
- {
-
- environment = new Environment(fromDir, envConfig);
- List<String> databases = environment.getDatabaseNames();
- for (String name : databases)
- {
- if (name.startsWith("exchangeDb"))
- {
- if (name.startsWith("exchangeDb_v"))
- {
- version = Integer.parseInt(name.substring(12));
- }
- else
- {
- version = 1;
- }
- break;
- }
- }
- }
- catch (Exception e)
- {
- _logger.error("Failure to open existing database: " + e.getMessage());
- }
- finally
- {
- if (environment != null)
- {
- try
- {
- environment.close();
- }
- catch (Exception e)
- {
- // ignoring. It should never happen.
- }
- }
- }
- return version;
- }
-
- private static void fatalError(String message)
- {
- System.out.println(message);
- usage();
- System.exit(1);
- }
-
- private static void showHelp()
- {
- help();
- System.exit(0);
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BindingKey.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BindingKey.java
deleted file mode 100644
index 396f0ed817..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BindingKey.java
+++ /dev/null
@@ -1,62 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-public class BindingKey extends Object
-{
- private final AMQShortString _exchangeName;
- private final AMQShortString _queueName;
- private final AMQShortString _routingKey;
- private final FieldTable _arguments;
-
- public BindingKey(AMQShortString exchangeName, AMQShortString queueName, AMQShortString routingKey, FieldTable arguments)
- {
- _exchangeName = exchangeName;
- _queueName = queueName;
- _routingKey = routingKey;
- _arguments = arguments;
- }
-
-
- public AMQShortString getExchangeName()
- {
- return _exchangeName;
- }
-
- public AMQShortString getQueueName()
- {
- return _queueName;
- }
-
- public AMQShortString getRoutingKey()
- {
- return _routingKey;
- }
-
- public FieldTable getArguments()
- {
- return _arguments;
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ContentTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ContentTB.java
deleted file mode 100644
index 5ea3e9c2e8..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ContentTB.java
+++ /dev/null
@@ -1,52 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import java.nio.ByteBuffer;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-public class ContentTB extends TupleBinding
-{
- public Object entryToObject(TupleInput tupleInput)
- {
-
- final int size = tupleInput.readInt();
- byte[] underlying = new byte[size];
- tupleInput.readFast(underlying);
- return ByteBuffer.wrap(underlying);
- }
-
- public void objectToEntry(Object object, TupleOutput tupleOutput)
- {
- ByteBuffer src = (ByteBuffer) object;
-
- src = src.slice();
-
- byte[] chunkData = new byte[src.limit()];
- src.duplicate().get(chunkData);
-
- tupleOutput.writeInt(chunkData.length);
- tupleOutput.writeFast(chunkData);
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/DatabaseVisitor.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/DatabaseVisitor.java
deleted file mode 100644
index 9bd879025f..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/DatabaseVisitor.java
+++ /dev/null
@@ -1,44 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.AMQStoreException;
-
-import com.sleepycat.je.DatabaseEntry;
-import com.sleepycat.je.DatabaseException;
-
-/** Visitor Interface so that each DatabaseEntry for a database can easily be processed. */
-public abstract class DatabaseVisitor
-{
- protected int _count;
-
- abstract public void visit(DatabaseEntry entry, DatabaseEntry value) throws AMQStoreException, DatabaseException;
-
- public int getVisitedCount()
- {
- return _count;
- }
-
- public void resetVisitCount()
- {
- _count = 0;
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ExchangeTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ExchangeTB.java
deleted file mode 100644
index f9c7828bef..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/ExchangeTB.java
+++ /dev/null
@@ -1,58 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import org.apache.log4j.Logger;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.store.berkeleydb.records.ExchangeRecord;
-
-public class ExchangeTB extends TupleBinding
-{
- private static final Logger _log = Logger.getLogger(ExchangeTB.class);
-
- public ExchangeTB()
- {
- }
-
- public Object entryToObject(TupleInput tupleInput)
- {
-
- AMQShortString name = AMQShortStringEncoding.readShortString(tupleInput);
- AMQShortString typeName = AMQShortStringEncoding.readShortString(tupleInput);
-
- boolean autoDelete = tupleInput.readBoolean();
-
- return new ExchangeRecord(name, typeName, autoDelete);
- }
-
- public void objectToEntry(Object object, TupleOutput tupleOutput)
- {
- ExchangeRecord exchange = (ExchangeRecord) object;
-
- AMQShortStringEncoding.writeShortString(exchange.getNameShortString(), tupleOutput);
- AMQShortStringEncoding.writeShortString(exchange.getType(), tupleOutput);
-
- tupleOutput.writeBoolean(exchange.isAutoDelete());
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java
deleted file mode 100644
index c09498cce3..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/FieldTableEncoding.java
+++ /dev/null
@@ -1,74 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.framing.FieldTable;
-
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import com.sleepycat.je.DatabaseException;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-
-public class FieldTableEncoding
-{
- public static FieldTable readFieldTable(TupleInput tupleInput) throws DatabaseException
- {
- long length = tupleInput.readLong();
- if (length <= 0)
- {
- return null;
- }
- else
- {
-
- byte[] data = new byte[(int)length];
- tupleInput.readFast(data);
-
- try
- {
- return new FieldTable(new DataInputStream(new ByteArrayInputStream(data)),length);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
-
- }
-
- }
-
- public static void writeFieldTable(FieldTable fieldTable, TupleOutput tupleOutput)
- {
-
- if (fieldTable == null)
- {
- tupleOutput.writeLong(0);
- }
- else
- {
- tupleOutput.writeLong(fieldTable.getEncodedSize());
- tupleOutput.writeFast(fieldTable.getDataAsBytes());
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/MessageContentKey.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/MessageContentKey.java
deleted file mode 100644
index 005e8d4604..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/MessageContentKey.java
+++ /dev/null
@@ -1,42 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-public class MessageContentKey
-{
- private long _messageId;
-
- public MessageContentKey(long messageId)
- {
- _messageId = messageId;
- }
-
-
- public long getMessageId()
- {
- return _messageId;
- }
-
- public void setMessageId(long messageId)
- {
- this._messageId = messageId;
- }
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/QueueEntryKey.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/QueueEntryKey.java
deleted file mode 100644
index c274fdec8c..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/QueueEntryKey.java
+++ /dev/null
@@ -1,49 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.framing.AMQShortString;
-
-public class QueueEntryKey
-{
- private AMQShortString _queueName;
- private long _messageId;
-
-
- public QueueEntryKey(AMQShortString queueName, long messageId)
- {
- _queueName = queueName;
- _messageId = messageId;
- }
-
-
- public AMQShortString getQueueName()
- {
- return _queueName;
- }
-
-
- public long getMessageId()
- {
- return _messageId;
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_4.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_4.java
deleted file mode 100644
index 30357c97d4..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_4.java
+++ /dev/null
@@ -1,44 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.keys;
-
-import org.apache.qpid.server.store.berkeleydb.MessageContentKey;
-
-public class MessageContentKey_4 extends MessageContentKey
-{
- private int _chunkNum;
-
- public MessageContentKey_4(long messageId, int chunkNo)
- {
- super(messageId);
- _chunkNum = chunkNo;
- }
-
- public int getChunk()
- {
- return _chunkNum;
- }
-
- public void setChunk(int chunk)
- {
- this._chunkNum = chunk;
- }
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_5.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_5.java
deleted file mode 100644
index a1a7fe80b5..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/keys/MessageContentKey_5.java
+++ /dev/null
@@ -1,44 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.keys;
-
-import org.apache.qpid.server.store.berkeleydb.MessageContentKey;
-
-public class MessageContentKey_5 extends MessageContentKey
-{
- private int _offset;
-
- public MessageContentKey_5(long messageId, int chunkNo)
- {
- super(messageId);
- _offset = chunkNo;
- }
-
- public int getOffset()
- {
- return _offset;
- }
-
- public void setOffset(int chunk)
- {
- this._offset = chunk;
- }
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/ExchangeRecord.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/ExchangeRecord.java
deleted file mode 100644
index f20367e33b..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/ExchangeRecord.java
+++ /dev/null
@@ -1,53 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.records;
-
-import org.apache.qpid.framing.AMQShortString;
-
-public class ExchangeRecord extends Object
-{
- private final AMQShortString _exchangeName;
- private final AMQShortString _exchangeType;
- private final boolean _autoDelete;
-
- public ExchangeRecord(AMQShortString exchangeName, AMQShortString exchangeType, boolean autoDelete)
- {
- _exchangeName = exchangeName;
- _exchangeType = exchangeType;
- _autoDelete = autoDelete;
- }
-
- public AMQShortString getNameShortString()
- {
- return _exchangeName;
- }
-
- public AMQShortString getType()
- {
- return _exchangeType;
- }
-
- public boolean isAutoDelete()
- {
- return _autoDelete;
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/QueueRecord.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/QueueRecord.java
deleted file mode 100644
index fbe10433ca..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/records/QueueRecord.java
+++ /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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.records;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-public class QueueRecord extends Object
-{
- private final AMQShortString _queueName;
- private final AMQShortString _owner;
- private final FieldTable _arguments;
- private boolean _exclusive;
-
- public QueueRecord(AMQShortString queueName, AMQShortString owner, boolean exclusive, FieldTable arguments)
- {
- _queueName = queueName;
- _owner = owner;
- _exclusive = exclusive;
- _arguments = arguments;
- }
-
- public AMQShortString getNameShortString()
- {
- return _queueName;
- }
-
- public AMQShortString getOwner()
- {
- return _owner;
- }
-
- public boolean isExclusive()
- {
- return _exclusive;
- }
-
- public void setExclusive(boolean exclusive)
- {
- _exclusive = exclusive;
- }
-
- public FieldTable getArguments()
- {
- return _arguments;
- }
-
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/testclient/BackupTestClient.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/testclient/BackupTestClient.java
deleted file mode 100644
index f6344b3d7d..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/testclient/BackupTestClient.java
+++ /dev/null
@@ -1,120 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.testclient;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.ping.PingDurableClient;
-import org.apache.qpid.server.store.berkeleydb.BDBBackup;
-import org.apache.qpid.util.CommandLineParser;
-
-import java.util.Properties;
-
-/**
- * BackupTestClient extends {@link PingDurableClient} with an action that takes a BDB backup when a configurable
- * message count is reached. This enables a test user to restore this beackup, knowing how many committed but undelivered
- * messages were in the backup, in order to check that all are re-delivered when the backup is retored.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Perform BDB Backup on configurable message count.
- * </table>
- */
-public class BackupTestClient extends PingDurableClient
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(BackupTestClient.class);
-
- /** Holds the from directory to take backups from. */
- private String fromDir;
-
- /** Holds the to directory to store backups in. */
- private String toDir;
-
- /**
- * Default constructor, passes all property overrides to the parent.
- *
- * @param overrides Any property overrides to apply to the defaults.
- *
- * @throws Exception Any underlying exception is allowed to fall through.
- */
- BackupTestClient(Properties overrides) throws Exception
- {
- super(overrides);
- }
-
- /**
- * Starts the ping/wait/receive process. From and to directory locations for the BDB backups must be specified
- * on the command line:
- *
- * <p/><table><caption>Command Line</caption>
- * <tr><th> Option <th> Comment
- * <tr><td> -fromdir <td> The path to the directory to back the bdb log file from.
- * <tr><td> -todir <td> The path to the directory to save the backed up bdb log files to.
- * </table>
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- try
- {
- // Use the same command line format as BDBBackup utility, (compulsory from and to directories).
- Properties options =
- CommandLineParser.processCommandLine(args, new CommandLineParser(BDBBackup.COMMAND_LINE_SPEC),
- System.getProperties());
- BackupTestClient pingProducer = new BackupTestClient(options);
-
- // Keep the from and to directories for backups.
- pingProducer.fromDir = options.getProperty("fromdir");
- pingProducer.toDir = options.getProperty("todir");
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
-
- // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
- // pingProducer.getConnection().setExceptionListener(pingProducer);
-
- // Run the test procedure.
- int sent = pingProducer.send();
- pingProducer.waitForUser("Press return to begin receiving the pings.");
- pingProducer.receive(sent);
-
- System.exit(0);
- }
- catch (Exception e)
- {
- System.err.println(e.getMessage());
- log.error("Top level handler caught execption.", e);
- System.exit(1);
- }
- }
-
- /**
- * Supplies a triggered action extension, based on message count. This action takes a BDB log file backup.
- */
- public void takeAction()
- {
- BDBBackup backupUtil = new BDBBackup();
- backupUtil.takeBackupNoLock(fromDir, toDir);
- System.out.println("Took backup of BDB log files from directory: " + fromDir);
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple.java
deleted file mode 100644
index 301ee417c5..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple.java
+++ /dev/null
@@ -1,25 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-public interface BindingTuple
-{
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTupleBindingFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTupleBindingFactory.java
deleted file mode 100644
index 8e17f074d7..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTupleBindingFactory.java
+++ /dev/null
@@ -1,45 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.server.store.berkeleydb.BindingKey;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-
-public class BindingTupleBindingFactory extends TupleBindingFactory<BindingKey>
-{
- public BindingTupleBindingFactory(int version)
- {
- super(version);
- }
-
- public TupleBinding<BindingKey> getInstance()
- {
- switch (_version)
- {
- default:
- case 5:
- //no change from v4
- case 4:
- return new BindingTuple_4();
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple_4.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple_4.java
deleted file mode 100644
index 52b131a7f2..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/BindingTuple_4.java
+++ /dev/null
@@ -1,76 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
-import org.apache.qpid.server.store.berkeleydb.BindingKey;
-import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import com.sleepycat.je.DatabaseException;
-
-public class BindingTuple_4 extends TupleBinding<BindingKey> implements BindingTuple
-{
- protected static final Logger _log = Logger.getLogger(BindingTuple.class);
-
- public BindingTuple_4()
- {
- super();
- }
-
- public BindingKey entryToObject(TupleInput tupleInput)
- {
- AMQShortString exchangeName = AMQShortStringEncoding.readShortString(tupleInput);
- AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput);
- AMQShortString routingKey = AMQShortStringEncoding.readShortString(tupleInput);
-
- FieldTable arguments;
-
- // Addition for Version 2 of this table
- try
- {
- arguments = FieldTableEncoding.readFieldTable(tupleInput);
- }
- catch (DatabaseException e)
- {
- _log.error("Unable to create binding: " + e, e);
- return null;
- }
-
- return new BindingKey(exchangeName, queueName, routingKey, arguments);
- }
-
- public void objectToEntry(BindingKey binding, TupleOutput tupleOutput)
- {
- AMQShortStringEncoding.writeShortString(binding.getExchangeName(), tupleOutput);
- AMQShortStringEncoding.writeShortString(binding.getQueueName(), tupleOutput);
- AMQShortStringEncoding.writeShortString(binding.getRoutingKey(), tupleOutput);
-
- // Addition for Version 2 of this table
- FieldTableEncoding.writeFieldTable(binding.getArguments(), tupleOutput);
- }
-
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_4.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_4.java
deleted file mode 100644
index f5ba6bbce3..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_4.java
+++ /dev/null
@@ -1,47 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.server.store.berkeleydb.MessageContentKey;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_4;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-public class MessageContentKeyTB_4 extends TupleBinding<MessageContentKey>
-{
-
- public MessageContentKey entryToObject(TupleInput tupleInput)
- {
- long messageId = tupleInput.readLong();
- int chunk = tupleInput.readInt();
- return new MessageContentKey_4(messageId, chunk);
- }
-
- public void objectToEntry(MessageContentKey object, TupleOutput tupleOutput)
- {
- final MessageContentKey_4 mk = (MessageContentKey_4) object;
- tupleOutput.writeLong(mk.getMessageId());
- tupleOutput.writeInt(mk.getChunk());
- }
-
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_5.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_5.java
deleted file mode 100644
index e6a2fd23a8..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTB_5.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.server.store.berkeleydb.MessageContentKey;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_5;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-public class MessageContentKeyTB_5 extends TupleBinding<MessageContentKey>
-{
- public MessageContentKey entryToObject(TupleInput tupleInput)
- {
- long messageId = tupleInput.readLong();
- int offset = tupleInput.readInt();
- return new MessageContentKey_5(messageId, offset);
- }
-
- public void objectToEntry(MessageContentKey object, TupleOutput tupleOutput)
- {
- final MessageContentKey_5 mk = (MessageContentKey_5) object;
- tupleOutput.writeLong(mk.getMessageId());
- tupleOutput.writeInt(mk.getOffset());
- }
-
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTupleBindingFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTupleBindingFactory.java
deleted file mode 100644
index 76ee4f66e4..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageContentKeyTupleBindingFactory.java
+++ /dev/null
@@ -1,45 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.server.store.berkeleydb.MessageContentKey;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-
-public class MessageContentKeyTupleBindingFactory extends TupleBindingFactory<MessageContentKey>
-{
- public MessageContentKeyTupleBindingFactory(int version)
- {
- super(version);
- }
-
- public TupleBinding<MessageContentKey> getInstance()
- {
- switch (_version)
- {
- default:
- case 5:
- return new MessageContentKeyTB_5();
- case 4:
- return new MessageContentKeyTB_4();
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_4.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_4.java
deleted file mode 100644
index e26b544e38..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_4.java
+++ /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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
-
-import java.io.*;
-
-/**
- * Handles the mapping to and from 0-8/0-9 message meta data
- */
-public class MessageMetaDataTB_4 extends TupleBinding<Object>
-{
- private static final Logger _log = Logger.getLogger(MessageMetaDataTB_4.class);
-
- public MessageMetaDataTB_4()
- {
- }
-
- public Object entryToObject(TupleInput tupleInput)
- {
- try
- {
- final MessagePublishInfo publishBody = readMessagePublishInfo(tupleInput);
- final ContentHeaderBody contentHeaderBody = readContentHeaderBody(tupleInput);
- final int contentChunkCount = tupleInput.readInt();
-
- return new MessageMetaData(publishBody, contentHeaderBody, contentChunkCount);
- }
- catch (Exception e)
- {
- _log.error("Error converting entry to object: " + e, e);
- // annoyingly just have to return null since we cannot throw
- return null;
- }
- }
-
- public void objectToEntry(Object object, TupleOutput tupleOutput)
- {
- MessageMetaData message = (MessageMetaData) object;
- try
- {
- writeMessagePublishInfo(message.getMessagePublishInfo(), tupleOutput);
- }
- catch (AMQException e)
- {
- // can't do anything else since the BDB interface precludes throwing any exceptions
- // in practice we should never get an exception
- throw new RuntimeException("Error converting object to entry: " + e, e);
- }
- writeContentHeader(message.getContentHeaderBody(), tupleOutput);
- tupleOutput.writeInt(message.getContentChunkCount());
- }
-
- private MessagePublishInfo readMessagePublishInfo(TupleInput tupleInput)
- {
-
- final AMQShortString exchange = AMQShortStringEncoding.readShortString(tupleInput);
- final AMQShortString routingKey = AMQShortStringEncoding.readShortString(tupleInput);
- final boolean mandatory = tupleInput.readBoolean();
- final boolean immediate = tupleInput.readBoolean();
-
- return new MessagePublishInfo()
- {
-
- public AMQShortString getExchange()
- {
- return exchange;
- }
-
- public void setExchange(AMQShortString exchange)
- {
-
- }
-
- public boolean isImmediate()
- {
- return immediate;
- }
-
- public boolean isMandatory()
- {
- return mandatory;
- }
-
- public AMQShortString getRoutingKey()
- {
- return routingKey;
- }
- } ;
-
- }
-
- private ContentHeaderBody readContentHeaderBody(TupleInput tupleInput) throws AMQFrameDecodingException, AMQProtocolVersionException
- {
- int bodySize = tupleInput.readInt();
- byte[] underlying = new byte[bodySize];
- tupleInput.readFast(underlying);
-
- try
- {
- return ContentHeaderBody.createFromBuffer(new DataInputStream(new ByteArrayInputStream(underlying)), bodySize);
- }
- catch (IOException e)
- {
- throw new AMQFrameDecodingException(null, e.getMessage(), e);
- }
- }
-
- private void writeMessagePublishInfo(MessagePublishInfo publishBody, TupleOutput tupleOutput) throws AMQException
- {
-
- AMQShortStringEncoding.writeShortString(publishBody.getExchange(), tupleOutput);
- AMQShortStringEncoding.writeShortString(publishBody.getRoutingKey(), tupleOutput);
- tupleOutput.writeBoolean(publishBody.isMandatory());
- tupleOutput.writeBoolean(publishBody.isImmediate());
- }
-
- private void writeContentHeader(ContentHeaderBody headerBody, TupleOutput tupleOutput)
- {
- // write out the content header body
- final int bodySize = headerBody.getSize();
- ByteArrayOutputStream baos = new ByteArrayOutputStream(bodySize);
- try
- {
- headerBody.writePayload(new DataOutputStream(baos));
- tupleOutput.writeInt(bodySize);
- tupleOutput.writeFast(baos.toByteArray());
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
-
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_5.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_5.java
deleted file mode 100644
index 6dc041cb23..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTB_5.java
+++ /dev/null
@@ -1,77 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.store.MessageMetaDataType;
-import org.apache.qpid.server.store.StorableMessageMetaData;
-
-/**
- * Handles the mapping to and from message meta data
- */
-public class MessageMetaDataTB_5 extends MessageMetaDataTB_4
-{
- private static final Logger _log = Logger.getLogger(MessageMetaDataTB_5.class);
-
- @Override
- public Object entryToObject(TupleInput tupleInput)
- {
- try
- {
- final int bodySize = tupleInput.readInt();
- byte[] dataAsBytes = new byte[bodySize];
- tupleInput.readFast(dataAsBytes);
-
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(dataAsBytes);
- buf.position(1);
- buf = buf.slice();
- MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]];
- StorableMessageMetaData metaData = type.getFactory().createMetaData(buf);
-
- return metaData;
- }
- catch (Exception e)
- {
- _log.error("Error converting entry to object: " + e, e);
- // annoyingly just have to return null since we cannot throw
- return null;
- }
- }
-
- @Override
- public void objectToEntry(Object object, TupleOutput tupleOutput)
- {
- StorableMessageMetaData metaData = (StorableMessageMetaData) object;
-
- final int bodySize = 1 + metaData.getStorableSize();
- byte[] underlying = new byte[bodySize];
- underlying[0] = (byte) metaData.getType().ordinal();
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(underlying);
- buf.position(1);
- buf = buf.slice();
-
- metaData.writeToBuffer(0, buf);
- tupleOutput.writeInt(bodySize);
- tupleOutput.writeFast(underlying);
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTupleBindingFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTupleBindingFactory.java
deleted file mode 100644
index 40153c13ea..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/MessageMetaDataTupleBindingFactory.java
+++ /dev/null
@@ -1,43 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-
-public class MessageMetaDataTupleBindingFactory extends TupleBindingFactory<Object>
-{
- public MessageMetaDataTupleBindingFactory(int version)
- {
- super(version);
- }
-
- public TupleBinding<Object> getInstance()
- {
- switch (_version)
- {
- default:
- case 5:
- return new MessageMetaDataTB_5();
- case 4:
- return new MessageMetaDataTB_4();
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java
deleted file mode 100644
index 975e558874..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueEntryTB.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
-import org.apache.qpid.server.store.berkeleydb.QueueEntryKey;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-public class QueueEntryTB extends TupleBinding<QueueEntryKey>
-{
- public QueueEntryKey entryToObject(TupleInput tupleInput)
- {
- AMQShortString queueName = AMQShortStringEncoding.readShortString(tupleInput);
- Long messageId = tupleInput.readLong();
-
- return new QueueEntryKey(queueName, messageId);
- }
-
- public void objectToEntry(QueueEntryKey mk, TupleOutput tupleOutput)
- {
- AMQShortStringEncoding.writeShortString(mk.getQueueName(),tupleOutput);
- tupleOutput.writeLong(mk.getMessageId());
- }
-} \ No newline at end of file
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple.java
deleted file mode 100644
index affa9a271d..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple.java
+++ /dev/null
@@ -1,25 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-public interface QueueTuple
-{
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTupleBindingFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTupleBindingFactory.java
deleted file mode 100644
index 512e319f96..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTupleBindingFactory.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-
-public class QueueTupleBindingFactory extends TupleBindingFactory<QueueRecord>
-{
-
- public QueueTupleBindingFactory(int version)
- {
- super(version);
- }
-
- public TupleBinding<QueueRecord> getInstance()
- {
- switch (_version)
- {
- default:
- case 5:
- return new QueueTuple_5();
- case 4:
- return new QueueTuple_4();
- }
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_4.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_4.java
deleted file mode 100644
index 347eecf08e..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_4.java
+++ /dev/null
@@ -1,72 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import com.sleepycat.je.DatabaseException;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
-import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding;
-import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-public class QueueTuple_4 extends TupleBinding<QueueRecord> implements QueueTuple
-{
- protected static final Logger _logger = Logger.getLogger(QueueTuple_4.class);
-
- protected FieldTable _arguments;
-
- public QueueTuple_4()
- {
- super();
- }
-
- public QueueRecord entryToObject(TupleInput tupleInput)
- {
- try
- {
- AMQShortString name = AMQShortStringEncoding.readShortString(tupleInput);
- AMQShortString owner = AMQShortStringEncoding.readShortString(tupleInput);
- // Addition for Version 2 of this table, read the queue arguments
- FieldTable arguments = FieldTableEncoding.readFieldTable(tupleInput);
-
- return new QueueRecord(name, owner, false, arguments);
- }
- catch (DatabaseException e)
- {
- _logger.error("Unable to create binding: " + e, e);
- return null;
- }
-
- }
-
- public void objectToEntry(QueueRecord queue, TupleOutput tupleOutput)
- {
- AMQShortStringEncoding.writeShortString(queue.getNameShortString(), tupleOutput);
- AMQShortStringEncoding.writeShortString(queue.getOwner(), tupleOutput);
- // Addition for Version 2 of this table, store the queue arguments
- FieldTableEncoding.writeFieldTable(queue.getArguments(), tupleOutput);
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_5.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_5.java
deleted file mode 100644
index 0f293b79b7..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/QueueTuple_5.java
+++ /dev/null
@@ -1,75 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-import com.sleepycat.je.DatabaseException;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding;
-import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding;
-import org.apache.qpid.server.store.berkeleydb.records.QueueRecord;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-public class QueueTuple_5 extends QueueTuple_4
-{
- protected static final Logger _logger = Logger.getLogger(QueueTuple_5.class);
-
- protected FieldTable _arguments;
-
- public QueueTuple_5()
- {
- super();
- }
-
- public QueueRecord entryToObject(TupleInput tupleInput)
- {
- try
- {
- AMQShortString name = AMQShortStringEncoding.readShortString(tupleInput);
- AMQShortString owner = AMQShortStringEncoding.readShortString(tupleInput);
- // Addition for Version 2 of this table, read the queue arguments
- FieldTable arguments = FieldTableEncoding.readFieldTable(tupleInput);
- // Addition for Version 3 of this table, read the queue exclusivity
- boolean exclusive = tupleInput.readBoolean();
-
- return new QueueRecord(name, owner, exclusive, arguments);
- }
- catch (DatabaseException e)
- {
- _logger.error("Unable to create binding: " + e, e);
- return null;
- }
-
- }
-
- public void objectToEntry(QueueRecord queue, TupleOutput tupleOutput)
- {
- AMQShortStringEncoding.writeShortString(queue.getNameShortString(), tupleOutput);
- AMQShortStringEncoding.writeShortString(queue.getOwner(), tupleOutput);
- // Addition for Version 2 of this table, store the queue arguments
- FieldTableEncoding.writeFieldTable(queue.getArguments(), tupleOutput);
- // Addition for Version 3 of this table, store the queue exclusivity
- tupleOutput.writeBoolean(queue.isExclusive());
- }
-}
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/TupleBindingFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/TupleBindingFactory.java
deleted file mode 100644
index 2adac1f9a3..0000000000
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuples/TupleBindingFactory.java
+++ /dev/null
@@ -1,35 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb.tuples;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-
-public abstract class TupleBindingFactory<E>
-{
- protected int _version;
-
- public TupleBindingFactory(int version)
- {
- _version = version;
- }
-
- public abstract TupleBinding<E> getInstance();
-}
diff --git a/java/bdbstore/src/resources/backup-log4j.xml b/java/bdbstore/src/resources/backup-log4j.xml
deleted file mode 100644
index 6b0619f0b6..0000000000
--- a/java/bdbstore/src/resources/backup-log4j.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- -
- - Licensed to the Apache Software Foundation (ASF) under one
- - or more contributor license agreements. See the NOTICE file
- - distributed with this work for additional information
- - regarding copyright ownership. The ASF licenses this file
- - to you under the Apache License, Version 2.0 (the
- - "License"); you may not use this file except in compliance
- - with the License. You may obtain a copy of the License at
- -
- - http://www.apache.org/licenses/LICENSE-2.0
- -
- - Unless required by applicable law or agreed to in writing,
- - software distributed under the License is distributed on an
- - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- - KIND, either express or implied. See the License for the
- - specific language governing permissions and limitations
- - under the License.
- -
- -->
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<!-- =============================================================================== -->
-<!-- This is a Log4j configuration specially created for the BDB Backup utility, -->
-<!-- it outputs logging to the console for specifically designated console loggers -->
-<!-- at info level or above only. This avoids spamming the user with any internals -->
-<!-- of the Qpid code. -->
-<!-- Use a different logging set up to capture debugging output to diagnose errors. -->
-<!-- =============================================================================== -->
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
-
- <!-- ====================================================== -->
- <!-- Append messages to the console at info level or above. -->
- <!-- ====================================================== -->
-
- <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
- <param name="Target" value="System.out"/>
- <param name="Threshold" value="info"/>
-
- <layout class="org.apache.log4j.PatternLayout">
- <!-- The default pattern: Date Priority [Category] Message\n -->
- <param name="ConversionPattern" value="%m%n"/>
- </layout>
-
- </appender>
-
- <!-- ================ -->
- <!-- Limit categories -->
- <!-- ================ -->
-
- <category name="org.apache.qpid.server.store.berkeleydb.BDBBackup">
- <priority value="info"/>
- </category>
-
- <!-- ======================= -->
- <!-- Setup the Root category -->
- <!-- ======================= -->
-
- <root>
- <appender-ref ref="CONSOLE"/>
- </root>
-
-</log4j:configuration>
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java
deleted file mode 100644
index d076babc61..0000000000
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/AMQShortStringEncodingTest.java
+++ /dev/null
@@ -1,88 +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.
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.framing.AMQShortString;
-
-import com.sleepycat.bind.tuple.TupleInput;
-import com.sleepycat.bind.tuple.TupleOutput;
-
-import junit.framework.TestCase;
-
-/**
- * Tests for {@code AMQShortStringEncoding} including corner cases when string
- * is null or over 127 characters in length
- */
-public class AMQShortStringEncodingTest extends TestCase
-{
-
- public void testWriteReadNullValues()
- {
- // write into tuple output
- TupleOutput tupleOutput = new TupleOutput();
- AMQShortStringEncoding.writeShortString(null, tupleOutput);
- byte[] data = tupleOutput.getBufferBytes();
-
- // read from tuple input
- TupleInput tupleInput = new TupleInput(data);
- AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput);
- assertNull("Expected null but got " + result, result);
- }
-
- public void testWriteReadShortStringWithLengthOver127()
- {
- AMQShortString value = createString('a', 128);
-
- // write into tuple output
- TupleOutput tupleOutput = new TupleOutput();
- AMQShortStringEncoding.writeShortString(value, tupleOutput);
- byte[] data = tupleOutput.getBufferBytes();
-
- // read from tuple input
- TupleInput tupleInput = new TupleInput(data);
- AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput);
- assertEquals("Expected " + value + " but got " + result, value, result);
- }
-
- public void testWriteReadShortStringWithLengthLess127()
- {
- AMQShortString value = new AMQShortString("test");
-
- // write into tuple output
- TupleOutput tupleOutput = new TupleOutput();
- AMQShortStringEncoding.writeShortString(value, tupleOutput);
- byte[] data = tupleOutput.getBufferBytes();
-
- // read from tuple input
- TupleInput tupleInput = new TupleInput(data);
- AMQShortString result = AMQShortStringEncoding.readShortString(tupleInput);
- assertEquals("Expected " + value + " but got " + result, value, result);
- }
-
- private AMQShortString createString(char ch, int length)
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++)
- {
- sb.append(ch);
- }
- return new AMQShortString(sb.toString());
- }
-
-}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
deleted file mode 100644
index ef31b78cfe..0000000000
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
+++ /dev/null
@@ -1,470 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.qpid.AMQStoreException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.message.MessageMetaData_0_10;
-import org.apache.qpid.server.store.MessageMetaDataType;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StorableMessageMetaData;
-import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.store.TransactionLog;
-import org.apache.qpid.server.store.TransactionLogResource;
-import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.qpid.transport.Header;
-import org.apache.qpid.transport.MessageAcceptMode;
-import org.apache.qpid.transport.MessageAcquireMode;
-import org.apache.qpid.transport.MessageDeliveryMode;
-import org.apache.qpid.transport.MessageDeliveryPriority;
-import org.apache.qpid.transport.MessageProperties;
-import org.apache.qpid.transport.MessageTransfer;
-
-/**
- * Subclass of MessageStoreTest which runs the standard tests from the superclass against
- * the BDB Store as well as additional tests specific to the DBB store-implementation.
- */
-public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageStoreTest
-{
- /**
- * Tests that message metadata and content are successfully read back from a
- * store after it has been reloaded. Both 0-8 and 0-10 metadata is used to
- * verify their ability to co-exist within the store and be successful retrieved.
- */
- public void testBDBMessagePersistence() throws Exception
- {
- MessageStore store = getVirtualHost().getMessageStore();
-
- BDBMessageStore bdbStore = assertBDBStore(store);
-
- // Create content ByteBuffers.
- // Split the content into 2 chunks for the 0-8 message, as per broker behaviour.
- // Use a single chunk for the 0-10 message as per broker behaviour.
- String bodyText = "jfhdjsflsdhfjdshfjdslhfjdslhfsjlhfsjkhfdsjkhfdsjkfhdslkjf";
-
- ByteBuffer firstContentBytes_0_8 = ByteBuffer.wrap(bodyText.substring(0, 10).getBytes());
- ByteBuffer secondContentBytes_0_8 = ByteBuffer.wrap(bodyText.substring(10).getBytes());
-
- ByteBuffer completeContentBody_0_10 = ByteBuffer.wrap(bodyText.getBytes());
- int bodySize = completeContentBody_0_10.limit();
-
- /*
- * Create and insert a 0-8 message (metadata and multi-chunk content)
- */
- MessagePublishInfo pubInfoBody_0_8 = createPublishInfoBody_0_8();
- BasicContentHeaderProperties props_0_8 = createContentHeaderProperties_0_8();
-
- ContentHeaderBody chb_0_8 = createContentHeaderBody_0_8(props_0_8, bodySize);
-
- MessageMetaData messageMetaData_0_8 = new MessageMetaData(pubInfoBody_0_8, chb_0_8, 0);
- StoredMessage<MessageMetaData> storedMessage_0_8 = bdbStore.addMessage(messageMetaData_0_8);
-
- long origArrivalTime_0_8 = messageMetaData_0_8.getArrivalTime();
- long messageid_0_8 = storedMessage_0_8.getMessageNumber();
-
- storedMessage_0_8.addContent(0, firstContentBytes_0_8);
- storedMessage_0_8.addContent(firstContentBytes_0_8.limit(), secondContentBytes_0_8);
- storedMessage_0_8.flushToStore();
-
- /*
- * Create and insert a 0-10 message (metadata and content)
- */
- MessageProperties msgProps_0_10 = createMessageProperties_0_10(bodySize);
- DeliveryProperties delProps_0_10 = createDeliveryProperties_0_10();
- Header header_0_10 = new Header(msgProps_0_10, delProps_0_10);
-
- MessageTransfer xfr_0_10 = new MessageTransfer("destination", MessageAcceptMode.EXPLICIT,
- MessageAcquireMode.PRE_ACQUIRED, header_0_10, completeContentBody_0_10);
-
- MessageMetaData_0_10 messageMetaData_0_10 = new MessageMetaData_0_10(xfr_0_10);
- StoredMessage<MessageMetaData_0_10> storedMessage_0_10 = bdbStore.addMessage(messageMetaData_0_10);
-
- long origArrivalTime_0_10 = messageMetaData_0_10.getArrivalTime();
- long messageid_0_10 = storedMessage_0_10.getMessageNumber();
-
- storedMessage_0_10.addContent(0, completeContentBody_0_10);
- storedMessage_0_10.flushToStore();
-
- /*
- * reload the store only (read-only)
- */
- bdbStore = reloadStoreReadOnly(bdbStore);
-
- /*
- * Read back and validate the 0-8 message metadata and content
- */
- StorableMessageMetaData storeableMMD_0_8 = bdbStore.getMessageMetaData(messageid_0_8);
-
- assertEquals("Unexpected message type",MessageMetaDataType.META_DATA_0_8, storeableMMD_0_8.getType());
- assertTrue("Unexpected instance type", storeableMMD_0_8 instanceof MessageMetaData);
- MessageMetaData returnedMMD_0_8 = (MessageMetaData) storeableMMD_0_8;
-
- assertEquals("Message arrival time has changed", origArrivalTime_0_8, returnedMMD_0_8.getArrivalTime());
-
- MessagePublishInfo returnedPubBody_0_8 = returnedMMD_0_8.getMessagePublishInfo();
- assertEquals("Message exchange has changed", pubInfoBody_0_8.getExchange(), returnedPubBody_0_8.getExchange());
- assertEquals("Immediate flag has changed", pubInfoBody_0_8.isImmediate(), returnedPubBody_0_8.isImmediate());
- assertEquals("Mandatory flag has changed", pubInfoBody_0_8.isMandatory(), returnedPubBody_0_8.isMandatory());
- assertEquals("Routing key has changed", pubInfoBody_0_8.getRoutingKey(), returnedPubBody_0_8.getRoutingKey());
-
- ContentHeaderBody returnedHeaderBody_0_8 = returnedMMD_0_8.getContentHeaderBody();
- assertEquals("ContentHeader ClassID has changed", chb_0_8.classId, returnedHeaderBody_0_8.classId);
- assertEquals("ContentHeader weight has changed", chb_0_8.weight, returnedHeaderBody_0_8.weight);
- assertEquals("ContentHeader bodySize has changed", chb_0_8.bodySize, returnedHeaderBody_0_8.bodySize);
-
- BasicContentHeaderProperties returnedProperties_0_8 = (BasicContentHeaderProperties) returnedHeaderBody_0_8.getProperties();
- assertEquals("Property ContentType has changed", props_0_8.getContentTypeAsString(), returnedProperties_0_8.getContentTypeAsString());
- assertEquals("Property MessageID has changed", props_0_8.getMessageIdAsString(), returnedProperties_0_8.getMessageIdAsString());
-
- ByteBuffer recoveredContent_0_8 = ByteBuffer.allocate((int) chb_0_8.bodySize) ;
- long recoveredCount_0_8 = bdbStore.getContent(messageid_0_8, 0, recoveredContent_0_8);
- assertEquals("Incorrect amount of payload data recovered", chb_0_8.bodySize, recoveredCount_0_8);
- String returnedPayloadString_0_8 = new String(recoveredContent_0_8.array());
- assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_8);
-
- /*
- * Read back and validate the 0-10 message metadata and content
- */
- StorableMessageMetaData storeableMMD_0_10 = bdbStore.getMessageMetaData(messageid_0_10);
-
- assertEquals("Unexpected message type",MessageMetaDataType.META_DATA_0_10, storeableMMD_0_10.getType());
- assertTrue("Unexpected instance type", storeableMMD_0_10 instanceof MessageMetaData_0_10);
- MessageMetaData_0_10 returnedMMD_0_10 = (MessageMetaData_0_10) storeableMMD_0_10;
-
- assertEquals("Message arrival time has changed", origArrivalTime_0_10, returnedMMD_0_10.getArrivalTime());
-
- DeliveryProperties returnedDelProps_0_10 = returnedMMD_0_10.getHeader().get(DeliveryProperties.class);
- assertNotNull("DeliveryProperties were not returned", returnedDelProps_0_10);
- assertEquals("Immediate flag has changed", delProps_0_10.getImmediate(), returnedDelProps_0_10.getImmediate());
- assertEquals("Routing key has changed", delProps_0_10.getRoutingKey(), returnedDelProps_0_10.getRoutingKey());
- assertEquals("Message exchange has changed", delProps_0_10.getExchange(), returnedDelProps_0_10.getExchange());
- assertEquals("Message expiration has changed", delProps_0_10.getExpiration(), returnedDelProps_0_10.getExpiration());
- assertEquals("Message delivery priority has changed", delProps_0_10.getPriority(), returnedDelProps_0_10.getPriority());
-
- MessageProperties returnedMsgProps = returnedMMD_0_10.getHeader().get(MessageProperties.class);
- assertNotNull("MessageProperties were not returned", returnedMsgProps);
- assertTrue("Message correlationID has changed", Arrays.equals(msgProps_0_10.getCorrelationId(), returnedMsgProps.getCorrelationId()));
- assertEquals("Message content length has changed", msgProps_0_10.getContentLength(), returnedMsgProps.getContentLength());
- assertEquals("Message content type has changed", msgProps_0_10.getContentType(), returnedMsgProps.getContentType());
-
- ByteBuffer recoveredContent = ByteBuffer.allocate((int) msgProps_0_10.getContentLength()) ;
- long recoveredCount = bdbStore.getContent(messageid_0_10, 0, recoveredContent);
- assertEquals("Incorrect amount of payload data recovered", msgProps_0_10.getContentLength(), recoveredCount);
-
- String returnedPayloadString_0_10 = new String(recoveredContent.array());
- assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_10);
- }
-
- private DeliveryProperties createDeliveryProperties_0_10()
- {
- DeliveryProperties delProps_0_10 = new DeliveryProperties();
-
- delProps_0_10.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
- delProps_0_10.setImmediate(true);
- delProps_0_10.setExchange("exchange12345");
- delProps_0_10.setRoutingKey("routingKey12345");
- delProps_0_10.setExpiration(5);
- delProps_0_10.setPriority(MessageDeliveryPriority.ABOVE_AVERAGE);
-
- return delProps_0_10;
- }
-
- private MessageProperties createMessageProperties_0_10(int bodySize)
- {
- MessageProperties msgProps_0_10 = new MessageProperties();
- msgProps_0_10.setContentLength(bodySize);
- msgProps_0_10.setCorrelationId("qwerty".getBytes());
- msgProps_0_10.setContentType("text/html");
-
- return msgProps_0_10;
- }
-
- /**
- * Close the provided store and create a new (read-only) store to read back the data.
- *
- * Use this method instead of reloading the virtual host like other tests in order
- * to avoid the recovery handler deleting the message for not being on a queue.
- */
- private BDBMessageStore reloadStoreReadOnly(BDBMessageStore messageStore) throws Exception
- {
- messageStore.close();
- File storePath = new File(String.valueOf(_config.getProperty("store.environment-path")));
-
- BDBMessageStore newStore = new BDBMessageStore();
- newStore.configure(storePath, false);
- newStore.start();
-
- return newStore;
- }
-
- private MessagePublishInfo createPublishInfoBody_0_8()
- {
- return new MessagePublishInfo()
- {
- public AMQShortString getExchange()
- {
- return new AMQShortString("exchange12345");
- }
-
- public void setExchange(AMQShortString exchange)
- {
- }
-
- public boolean isImmediate()
- {
- return false;
- }
-
- public boolean isMandatory()
- {
- return true;
- }
-
- public AMQShortString getRoutingKey()
- {
- return new AMQShortString("routingKey12345");
- }
- };
-
- }
-
- private ContentHeaderBody createContentHeaderBody_0_8(BasicContentHeaderProperties props, int length)
- {
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- int classForBasic = methodRegistry.createBasicQosOkBody().getClazz();
- return new ContentHeaderBody(classForBasic, 1, props, length);
- }
-
- private BasicContentHeaderProperties createContentHeaderProperties_0_8()
- {
- BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue());
- props.setContentType("text/html");
- props.getHeaders().setString("Test", "MST");
- return props;
- }
-
- /**
- * Tests that messages which are added to the store and then removed using the
- * public MessageStore interfaces are actually removed from the store by then
- * interrogating the store with its own implementation methods and verifying
- * expected exceptions are thrown to indicate the message is not present.
- */
- public void testMessageCreationAndRemoval() throws Exception
- {
- MessageStore store = getVirtualHost().getMessageStore();
- BDBMessageStore bdbStore = assertBDBStore(store);
-
- StoredMessage<MessageMetaData> storedMessage_0_8 = createAndStoreMultiChunkMessage_0_8(store);
- long messageid_0_8 = storedMessage_0_8.getMessageNumber();
-
- //remove the message in the fashion the broker normally would
- storedMessage_0_8.remove();
-
- //verify the removal using the BDB store implementation methods directly
- try
- {
- // the next line should throw since the message id should not be found
- bdbStore.getMessageMetaData(messageid_0_8);
- fail("No exception thrown when message id not found getting metadata");
- }
- catch (AMQStoreException e)
- {
- // pass since exception expected
- }
-
- //expecting no content, allocate a 1 byte
- ByteBuffer dst = ByteBuffer.allocate(1);
-
- assertEquals("Retrieved content when none was expected",
- 0, bdbStore.getContent(messageid_0_8, 0, dst));
- }
-
- private BDBMessageStore assertBDBStore(Object store)
- {
- if(!(store instanceof BDBMessageStore))
- {
- fail("Test requires an instance of BDBMessageStore to proceed");
- }
-
- return (BDBMessageStore) store;
- }
-
- private StoredMessage<MessageMetaData> createAndStoreMultiChunkMessage_0_8(MessageStore store)
- {
- byte[] body10Bytes = "0123456789".getBytes();
- byte[] body5Bytes = "01234".getBytes();
-
- ByteBuffer chunk1 = ByteBuffer.wrap(body10Bytes);
- ByteBuffer chunk2 = ByteBuffer.wrap(body5Bytes);
-
- int bodySize = body10Bytes.length + body5Bytes.length;
-
- //create and store the message using the MessageStore interface
- MessagePublishInfo pubInfoBody_0_8 = createPublishInfoBody_0_8();
- BasicContentHeaderProperties props_0_8 = createContentHeaderProperties_0_8();
-
- ContentHeaderBody chb_0_8 = createContentHeaderBody_0_8(props_0_8, bodySize);
-
- MessageMetaData messageMetaData_0_8 = new MessageMetaData(pubInfoBody_0_8, chb_0_8, 0);
- StoredMessage<MessageMetaData> storedMessage_0_8 = store.addMessage(messageMetaData_0_8);
-
- storedMessage_0_8.addContent(0, chunk1);
- storedMessage_0_8.addContent(chunk1.limit(), chunk2);
- storedMessage_0_8.flushToStore();
-
- return storedMessage_0_8;
- }
-
- /**
- * Tests transaction commit by utilising the enqueue and dequeue methods available
- * in the TransactionLog interface implemented by the store, and verifying the
- * behaviour using BDB implementation methods.
- */
- public void testTranCommit() throws Exception
- {
- TransactionLog log = getVirtualHost().getTransactionLog();
-
- BDBMessageStore bdbStore = assertBDBStore(log);
-
- final AMQShortString mockQueueName = new AMQShortString("queueName");
-
- TransactionLogResource mockQueue = new TransactionLogResource()
- {
- public String getResourceName()
- {
- return mockQueueName.asString();
- }
- };
-
- TransactionLog.Transaction txn = log.newTransaction();
-
- txn.enqueueMessage(mockQueue, 1L);
- txn.enqueueMessage(mockQueue, 5L);
- txn.commitTran();
-
- List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName);
-
- assertEquals("Number of enqueued messages is incorrect", 2, enqueuedIds.size());
- Long val = enqueuedIds.get(0);
- assertEquals("First Message is incorrect", 1L, val.longValue());
- val = enqueuedIds.get(1);
- assertEquals("Second Message is incorrect", 5L, val.longValue());
- }
-
-
- /**
- * Tests transaction rollback before a commit has occurred by utilising the
- * enqueue and dequeue methods available in the TransactionLog interface
- * implemented by the store, and verifying the behaviour using BDB
- * implementation methods.
- */
- public void testTranRollbackBeforeCommit() throws Exception
- {
- TransactionLog log = getVirtualHost().getTransactionLog();
-
- BDBMessageStore bdbStore = assertBDBStore(log);
-
- final AMQShortString mockQueueName = new AMQShortString("queueName");
-
- TransactionLogResource mockQueue = new TransactionLogResource()
- {
- public String getResourceName()
- {
- return mockQueueName.asString();
- }
- };
-
- TransactionLog.Transaction txn = log.newTransaction();
-
- txn.enqueueMessage(mockQueue, 21L);
- txn.abortTran();
-
- txn = log.newTransaction();
- txn.enqueueMessage(mockQueue, 22L);
- txn.enqueueMessage(mockQueue, 23L);
- txn.commitTran();
-
- List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName);
-
- assertEquals("Number of enqueued messages is incorrect", 2, enqueuedIds.size());
- Long val = enqueuedIds.get(0);
- assertEquals("First Message is incorrect", 22L, val.longValue());
- val = enqueuedIds.get(1);
- assertEquals("Second Message is incorrect", 23L, val.longValue());
- }
-
- /**
- * Tests transaction rollback after a commit has occurred by utilising the
- * enqueue and dequeue methods available in the TransactionLog interface
- * implemented by the store, and verifying the behaviour using BDB
- * implementation methods.
- */
- public void testTranRollbackAfterCommit() throws Exception
- {
- TransactionLog log = getVirtualHost().getTransactionLog();
-
- BDBMessageStore bdbStore = assertBDBStore(log);
-
- final AMQShortString mockQueueName = new AMQShortString("queueName");
-
- TransactionLogResource mockQueue = new TransactionLogResource()
- {
- public String getResourceName()
- {
- return mockQueueName.asString();
- }
- };
-
- TransactionLog.Transaction txn = log.newTransaction();
-
- txn.enqueueMessage(mockQueue, 30L);
- txn.commitTran();
-
- txn = log.newTransaction();
- txn.enqueueMessage(mockQueue, 31L);
- txn.abortTran();
-
- txn = log.newTransaction();
- txn.enqueueMessage(mockQueue, 32L);
- txn.commitTran();
-
- List<Long> enqueuedIds = bdbStore.getEnqueuedMessages(mockQueueName);
-
- assertEquals("Number of enqueued messages is incorrect", 2, enqueuedIds.size());
- Long val = enqueuedIds.get(0);
- assertEquals("First Message is incorrect", 30L, val.longValue());
- val = enqueuedIds.get(1);
- assertEquals("Second Message is incorrect", 32L, val.longValue());
- }
-
-}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java
deleted file mode 100644
index cc19bcf5d8..0000000000
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java
+++ /dev/null
@@ -1,232 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.Topic;
-import javax.jms.TopicConnection;
-import javax.jms.TopicPublisher;
-import javax.jms.TopicSession;
-import javax.jms.TopicSubscriber;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.url.URLSyntaxException;
-
-/**
- * Prepares an older version brokers BDB store with the required
- * contents for use in the BDBStoreUpgradeTest.
- *
- * The store will then be used to verify that the upgraded is
- * completed properly and that once upgraded it functions as
- * expected with the new broker.
- */
-public class BDBStoreUpgradeTestPreparer extends TestCase
-{
- public static final String TOPIC_NAME="myUpgradeTopic";
- public static final String SUB_NAME="myDurSubName";
- public static final String QUEUE_NAME="myUpgradeQueue";
-
- private static AMQConnectionFactory _connFac;
- private static final String CONN_URL =
- "amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'";
-
- /**
- * Create a BDBStoreUpgradeTestPreparer instance
- */
- public BDBStoreUpgradeTestPreparer () throws URLSyntaxException
- {
- _connFac = new AMQConnectionFactory(CONN_URL);
- }
-
- /**
- * Utility test method to allow running the preparation tool
- * using the test framework
- */
- public void testPrepareBroker() throws Exception
- {
- prepareBroker();
- }
-
- private void prepareBroker() throws Exception
- {
- prepareQueues();
- prepareDurableSubscription();
- }
-
- /**
- * Prepare a queue for use in testing message and binding recovery
- * after the upgrade is performed.
- *
- * - Create a transacted session on the connection.
- * - Use a consumer to create the (durable by default) queue.
- * - Send 5 large messages to test (multi-frame) content recovery.
- * - Send 1 small message to test (single-frame) content recovery.
- * - Commit the session.
- * - Send 5 small messages to test that uncommitted messages are not recovered.
- * following the upgrade.
- * - Close the session.
- */
- private void prepareQueues() throws Exception
- {
- // Create a connection
- Connection connection = _connFac.createConnection();
- connection.start();
- connection.setExceptionListener(new ExceptionListener()
- {
- public void onException(JMSException e)
- {
- e.printStackTrace();
- }
- });
- // Create a session on the connection, transacted to confirm delivery
- Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
- Queue queue = session.createQueue(QUEUE_NAME);
- // Create a consumer to ensure the queue gets created
- // (and enter it into the store, as queues are made durable by default)
- MessageConsumer messageConsumer = session.createConsumer(queue);
- messageConsumer.close();
-
- // Create a Message producer
- MessageProducer messageProducer = session.createProducer(queue);
-
- // Publish 5 persistent messages, 256k chars to ensure they are multi-frame
- sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 256*1024, 5);
- // Publish 5 persistent messages, 1k chars to ensure they are single-frame
- sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 1*1024, 5);
-
- session.commit();
-
- // Publish 5 persistent messages which will NOT be committed and so should be 'lost'
- sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 1*1024, 5);
-
- session.close();
- connection.close();
- }
-
- /**
- * Prepare a DurableSubscription backing queue for use in testing selector
- * recovery and queue exclusivity marking during the upgrade process.
- *
- * - Create a transacted session on the connection.
- * - Open and close a DurableSubscription with selector to create the backing queue.
- * - Send a message which matches the selector.
- * - Send a message which does not match the selector.
- * - Send a message which matches the selector but will remain uncommitted.
- * - Close the session.
- */
- private void prepareDurableSubscription() throws Exception
- {
-
- // Create a connection
- TopicConnection connection = _connFac.createTopicConnection();
- connection.start();
- connection.setExceptionListener(new ExceptionListener()
- {
- public void onException(JMSException e)
- {
- e.printStackTrace();
- }
- });
- // Create a session on the connection, transacted to confirm delivery
- Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
- Topic topic = session.createTopic(TOPIC_NAME);
-
- // Create and register a durable subscriber with selector and then close it
- TopicSubscriber durSub1 = session.createDurableSubscriber(topic, SUB_NAME,"testprop='true'", false);
- durSub1.close();
-
- // Create a publisher and send a persistent message which matches the selector
- // followed by one that does not match, and another which matches but is not
- // committed and so should be 'lost'
- TopicSession pubSession = connection.createTopicSession(true, Session.SESSION_TRANSACTED);
- TopicPublisher publisher = pubSession.createPublisher(topic);
-
- publishMessages(session, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "true");
- publishMessages(session, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "false");
- pubSession.commit();
- publishMessages(session, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "true");
-
- publisher.close();
- pubSession.close();
-
- }
-
- public static void sendMessages(Session session, MessageProducer messageProducer,
- Destination dest, int deliveryMode, int length, int numMesages) throws JMSException
- {
- for (int i = 1; i <= numMesages; i++)
- {
- Message message = session.createTextMessage(generateString(length));
- message.setIntProperty("ID", i);
- messageProducer.send(message, deliveryMode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
- }
- }
-
- public static void publishMessages(Session session, TopicPublisher publisher,
- Destination dest, int deliveryMode, int length, int numMesages, String selectorProperty) throws JMSException
- {
- for (int i = 1; i <= numMesages; i++)
- {
- Message message = session.createTextMessage(generateString(length));
- message.setIntProperty("ID", i);
- message.setStringProperty("testprop", selectorProperty);
- publisher.publish(message, deliveryMode, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
- }
- }
-
- /**
- * Generates a string of a given length consisting of the sequence 0,1,2,..,9,0,1,2.
- *
- * @param length number of characters in the string
- * @return string sequence of the given length
- */
- public static String generateString(int length)
- {
- char[] base_chars = new char[]{'0','1','2','3','4','5','6','7','8','9'};
- char[] chars = new char[length];
- for (int i = 0; i < (length); i++)
- {
- chars[i] = base_chars[i % 10];
- }
- return new String(chars);
- }
-
- /**
- * Run the preparation tool.
- * @param args Command line arguments.
- */
- public static void main(String[] args) throws Exception
- {
- BDBStoreUpgradeTestPreparer producer = new BDBStoreUpgradeTestPreparer();
- producer.prepareBroker();
- }
-} \ No newline at end of file
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java
deleted file mode 100644
index 4861e007af..0000000000
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java
+++ /dev/null
@@ -1,540 +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.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME;
-import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SUB_NAME;
-import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.TOPIC_NAME;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.jms.Topic;
-import javax.jms.TopicConnection;
-import javax.jms.TopicPublisher;
-import javax.jms.TopicSession;
-import javax.jms.TopicSubscriber;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl;
-import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.store.TransactionLog;
-import org.apache.qpid.server.store.TransactionLogResource;
-import org.apache.qpid.server.store.berkeleydb.keys.MessageContentKey_4;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageContentKeyTupleBindingFactory;
-import org.apache.qpid.server.store.berkeleydb.tuples.MessageMetaDataTupleBindingFactory;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.util.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.sleepycat.bind.tuple.TupleBinding;
-import com.sleepycat.je.DatabaseEntry;
-
-/**
- * Tests upgrading a BDB store and using it with the new broker
- * after the required contents are entered into the store using
- * an old broker with the BDBStoreUpgradeTestPreparer. The store
- * will then be used to verify that the upgraded is completed
- * properly and that once upgraded it functions as expected with
- * the new broker.
- */
-public class BDBUpgradeTest extends QpidBrokerTestCase
-{
- protected static final Logger _logger = LoggerFactory.getLogger(BDBUpgradeTest.class);
-
- private static final String STRING_1024 = BDBStoreUpgradeTestPreparer.generateString(1024);
- private static final String STRING_1024_256 = BDBStoreUpgradeTestPreparer.generateString(1024*256);
- private static final String QPID_WORK_ORIG = System.getProperty("QPID_WORK");
- private static final String QPID_HOME = System.getProperty("QPID_HOME");
- private static final int VERSION_4 = 4;
-
- private String _fromDir;
- private String _toDir;
- private String _toDirTwice;
-
- @Override
- public void setUp() throws Exception
- {
- assertNotNull("QPID_WORK must be set", QPID_WORK_ORIG);
- assertNotNull("QPID_HOME must be set", QPID_HOME);
-
- if(! isExternalBroker())
- {
- //override QPID_WORK to add the InVM port used so the store
- //output from the upgrade tool can be found by the broker
- setSystemProperty("QPID_WORK", QPID_WORK_ORIG + "/" + getPort());
- }
-
- _fromDir = QPID_HOME + "/bdbstore-to-upgrade/test-store";
- _toDir = getWorkDirBaseDir() + "/bdbstore/test-store";
- _toDirTwice = getWorkDirBaseDir() + "/bdbstore-upgraded-twice";
-
- //Clear the two target directories if they exist.
- File directory = new File(_toDir);
- if (directory.exists() && directory.isDirectory())
- {
- FileUtils.delete(directory, true);
- }
- directory = new File(_toDirTwice);
- if (directory.exists() && directory.isDirectory())
- {
- FileUtils.delete(directory, true);
- }
-
- //Upgrade the test store.
- upgradeBrokerStore(_fromDir, _toDir);
-
- //override the broker config used and then start the broker with the updated store
- _configFile = new File("build/etc/config-systests-bdb.xml");
- setConfigurationProperty("management.enabled", "true");
-
- super.setUp();
- }
-
- private String getWorkDirBaseDir()
- {
- return QPID_WORK_ORIG + (isInternalBroker() ? "" : "/" + getPort());
- }
-
- /**
- * Tests that the core upgrade method of the store upgrade tool passes through the exception
- * from the BDBMessageStore indicating that the data on disk can't be loaded as the previous
- * version because it has already been upgraded.
- * @throws Exception
- */
- public void testMultipleUpgrades() throws Exception
- {
- //stop the broker started by setUp() in order to allow the second upgrade attempt to proceed
- stopBroker();
-
- try
- {
- new BDBStoreUpgrade(_toDir, _toDirTwice, null, false, true).upgradeFromVersion(VERSION_4);
- fail("Second Upgrade Succeeded");
- }
- catch (Exception e)
- {
- System.err.println("Showing stack trace, we are expecting an 'Unable to load BDBStore' error");
- e.printStackTrace();
- assertTrue("Incorrect Exception Thrown:" + e.getMessage(),
- e.getMessage().contains("Unable to load BDBStore as version 4. Store on disk contains version 5 data"));
- }
- }
-
- /**
- * Test that the selector applied to the DurableSubscription was successfully
- * transfered to the new store, and functions as expected with continued use
- * by monitoring message count while sending new messages to the topic.
- */
- public void testSelectorDurability() throws Exception
- {
- JMXTestUtils jmxUtils = null;
- try
- {
- jmxUtils = new JMXTestUtils(this, "guest", "guest");
- jmxUtils.open();
- }
- catch (Exception e)
- {
- fail("Unable to establish JMX connection, test cannot proceed");
- }
-
- try
- {
- ManagedQueue dursubQueue = jmxUtils.getManagedQueue("clientid" + ":" + SUB_NAME);
- assertEquals("DurableSubscription backing queue should have 1 message on it initially",
- new Integer(1), dursubQueue.getMessageCount());
-
- // Create a connection and start it
- TopicConnection connection = (TopicConnection) getConnection();
- connection.start();
-
- // Send messages which don't match and do match the selector, checking message count
- TopicSession pubSession = connection.createTopicSession(true, org.apache.qpid.jms.Session.SESSION_TRANSACTED);
- Topic topic = pubSession.createTopic(TOPIC_NAME);
- TopicPublisher publisher = pubSession.createPublisher(topic);
-
- BDBStoreUpgradeTestPreparer.publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "false");
- pubSession.commit();
- assertEquals("DurableSubscription backing queue should still have 1 message on it",
- new Integer(1), dursubQueue.getMessageCount());
-
- BDBStoreUpgradeTestPreparer.publishMessages(pubSession, publisher, topic, DeliveryMode.PERSISTENT, 1*1024, 1, "true");
- pubSession.commit();
- assertEquals("DurableSubscription backing queue should now have 2 messages on it",
- new Integer(2), dursubQueue.getMessageCount());
-
- dursubQueue.clearQueue();
- pubSession.close();
- }
- finally
- {
- jmxUtils.close();
- }
- }
-
- /**
- * Test that the backing queue for the durable subscription created was successfully
- * detected and set as being exclusive during the upgrade process, and that the
- * regular queue was not.
- */
- public void testQueueExclusivity() throws Exception
- {
- JMXTestUtils jmxUtils = null;
- try
- {
- jmxUtils = new JMXTestUtils(this, "guest", "guest");
- jmxUtils.open();
- }
- catch (Exception e)
- {
- fail("Unable to establish JMX connection, test cannot proceed");
- }
-
- try
- {
- ManagedQueue queue = jmxUtils.getManagedQueue(QUEUE_NAME);
- assertFalse("Queue should not have been marked as Exclusive during upgrade", queue.isExclusive());
-
- ManagedQueue dursubQueue = jmxUtils.getManagedQueue("clientid" + ":" + SUB_NAME);
- assertTrue("DurableSubscription backing queue should have been marked as Exclusive during upgrade", dursubQueue.isExclusive());
- }
- finally
- {
- jmxUtils.close();
- }
- }
-
- /**
- * Test that the upgraded queue continues to function properly when used
- * for persistent messaging and restarting the broker.
- *
- * Sends the new messages to the queue BEFORE consuming those which were
- * sent before the upgrade. In doing so, this also serves to test that
- * the queue bindings were successfully transitioned during the upgrade.
- */
- public void testBindingAndMessageDurabability() throws Exception
- {
- // Create a connection and start it
- TopicConnection connection = (TopicConnection) getConnection();
- connection.start();
-
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- Queue queue = session.createQueue(QUEUE_NAME);
- MessageProducer messageProducer = session.createProducer(queue);
-
- // Send a new message
- BDBStoreUpgradeTestPreparer.sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 256*1024, 1);
-
- session.close();
-
- // Restart the broker
- restartBroker();
-
- // Drain the queue of all messages
- connection = (TopicConnection) getConnection();
- connection.start();
- consumeQueueMessages(connection, true);
- }
-
- /**
- * Test that all of the committed persistent messages previously sent to
- * the broker are properly received following update of the MetaData and
- * Content entries during the store upgrade process.
- */
- public void testConsumptionOfUpgradedMessages() throws Exception
- {
- // Create a connection and start it
- Connection connection = getConnection();
- connection.start();
-
- consumeDurableSubscriptionMessages(connection);
- consumeQueueMessages(connection, false);
- }
-
- /**
- * Tests store migration containing messages for non-existing queue.
- *
- * @throws Exception
- */
- public void testMigrationOfMessagesForNonExistingQueues() throws Exception
- {
- stopBroker();
-
- // copy store data into a new location for adding of phantom message
- File storeLocation = new File(_fromDir);
- File target = new File(_toDirTwice);
- if (!target.exists())
- {
- target.mkdirs();
- }
- FileUtils.copyRecursive(storeLocation, target);
-
- // delete migrated data
- File directory = new File(_toDir);
- if (directory.exists() && directory.isDirectory())
- {
- FileUtils.delete(directory, true);
- }
-
- // test data
- String nonExistingQueueName = getTestQueueName();
- String messageText = "Test Phantom Message";
-
- // add message
- addMessageForNonExistingQueue(target, VERSION_4, nonExistingQueueName, messageText);
-
- String[] inputs = { "Yes", "Yes", "Yes" };
- upgradeBrokerStoreInInterractiveMode(_toDirTwice, _toDir, inputs);
-
- // start broker
- startBroker();
-
- // Create a connection and start it
- Connection connection = getConnection();
- connection.start();
-
- // consume a message for non-existing store
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- Queue queue = session.createQueue(nonExistingQueueName);
- MessageConsumer messageConsumer = session.createConsumer(queue);
- Message message = messageConsumer.receive(1000);
-
- // assert consumed message
- assertNotNull("Message was not migrated!", message);
- assertTrue("Unexpected message received!", message instanceof TextMessage);
- String text = ((TextMessage) message).getText();
- assertEquals("Message migration failed!", messageText, text);
- }
-
- /**
- * An utility method to upgrade broker with simulation user interactions
- *
- * @param fromDir
- * location of the store to migrate
- * @param toDir
- * location of where migrated data will be stored
- * @param inputs
- * user answers on upgrade tool questions
- * @throws Exception
- */
- private void upgradeBrokerStoreInInterractiveMode(String fromDir, String toDir, final String[] inputs)
- throws Exception
- {
- // save to restore system.in after data migration
- InputStream stdin = System.in;
-
- // set fake system in to simulate user interactions
- // FIXME: it is a quite dirty simulator of system input but it does the job
- System.setIn(new InputStream()
- {
-
- int counter = 0;
-
- public synchronized int read(byte b[], int off, int len)
- {
- byte[] src = (inputs[counter] + "\n").getBytes();
- System.arraycopy(src, 0, b, off, src.length);
- counter++;
- return src.length;
- }
-
- @Override
- public int read() throws IOException
- {
- return -1;
- }
- });
-
- try
- {
- // Upgrade the test store.
- new BDBStoreUpgrade(fromDir, toDir, null, true, true).upgradeFromVersion(VERSION_4);
- }
- finally
- {
- // restore system in
- System.setIn(stdin);
- }
- }
-
- @SuppressWarnings("unchecked")
- private void addMessageForNonExistingQueue(File storeLocation, int storeVersion, String nonExistingQueueName,
- String messageText) throws Exception
- {
- final AMQShortString queueName = new AMQShortString(nonExistingQueueName);
- BDBMessageStore store = new BDBMessageStore(storeVersion);
- store.configure(storeLocation, false);
- try
- {
- store.start();
-
- // store message objects
- ByteBuffer completeContentBody = ByteBuffer.wrap(messageText.getBytes("UTF-8"));
- long bodySize = completeContentBody.limit();
- MessagePublishInfo pubInfoBody = new MessagePublishInfoImpl(new AMQShortString("amq.direct"), false,
- false, queueName);
- BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue());
- props.setContentType("text/plain");
- props.setType("text/plain");
- props.setMessageId("whatever");
- props.setEncoding("UTF-8");
- props.getHeaders().setString("Test", "MST");
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- int classForBasic = methodRegistry.createBasicQosOkBody().getClazz();
- ContentHeaderBody contentHeaderBody = new ContentHeaderBody(classForBasic, 1, props, bodySize);
-
- // add content entry to database
- long messageId = store.getNewMessageId();
- TupleBinding<MessageContentKey> contentKeyTB = new MessageContentKeyTupleBindingFactory(storeVersion).getInstance();
- MessageContentKey contentKey = null;
- if (storeVersion == VERSION_4)
- {
- contentKey = new MessageContentKey_4(messageId, 0);
- }
- else
- {
- throw new Exception(storeVersion + " is not supported");
- }
- DatabaseEntry key = new DatabaseEntry();
- contentKeyTB.objectToEntry(contentKey, key);
- DatabaseEntry data = new DatabaseEntry();
- ContentTB contentTB = new ContentTB();
- contentTB.objectToEntry(completeContentBody, data);
- store.getContentDb().put(null, key, data);
-
- // add meta data entry to database
- TupleBinding<Long> longTB = TupleBinding.getPrimitiveBinding(Long.class);
- TupleBinding<Object> metaDataTB = new MessageMetaDataTupleBindingFactory(storeVersion).getInstance();
- key = new DatabaseEntry();
- data = new DatabaseEntry();
- longTB.objectToEntry(new Long(messageId), key);
- MessageMetaData metaData = new MessageMetaData(pubInfoBody, contentHeaderBody, 1);
- metaDataTB.objectToEntry(metaData, data);
- store.getMetaDataDb().put(null, key, data);
-
- // add delivery entry to database
- TransactionLogResource mockQueue = new TransactionLogResource()
- {
- public String getResourceName()
- {
- return queueName.asString();
- }
- };
- TransactionLog log = (TransactionLog) store;
- TransactionLog.Transaction txn = log.newTransaction();
- txn.enqueueMessage(mockQueue, messageId);
- txn.commitTran();
- }
- finally
- {
- // close store
- store.close();
- }
- }
-
- private void consumeDurableSubscriptionMessages(Connection connection) throws Exception
- {
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- Topic topic = session.createTopic(TOPIC_NAME);
-
- TopicSubscriber durSub = session.createDurableSubscriber(topic, SUB_NAME,"testprop='true'", false);
-
- // Retrieve the matching message
- Message m = durSub.receive(2000);
- assertNotNull("Failed to receive an expected message", m);
- assertEquals("Selector property did not match", "true", m.getStringProperty("testprop"));
- assertEquals("ID property did not match", 1, m.getIntProperty("ID"));
- assertEquals("Message content was not as expected",BDBStoreUpgradeTestPreparer.generateString(1024) , ((TextMessage)m).getText());
-
- // Verify that neither the non-matching or uncommitted message are received
- m = durSub.receive(1000);
- assertNull("No more messages should have been recieved", m);
-
- durSub.close();
- session.close();
- }
-
- private void consumeQueueMessages(Connection connection, boolean extraMessage) throws Exception
- {
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- Queue queue = session.createQueue(QUEUE_NAME);
-
- MessageConsumer consumer = session.createConsumer(queue);
- Message m;
-
- // Retrieve the initial pre-upgrade messages
- for (int i=1; i <= 5 ; i++)
- {
- m = consumer.receive(2000);
- assertNotNull("Failed to receive an expected message", m);
- assertEquals("ID property did not match", i, m.getIntProperty("ID"));
- assertEquals("Message content was not as expected", STRING_1024_256, ((TextMessage)m).getText());
- }
- for (int i=1; i <= 5 ; i++)
- {
- m = consumer.receive(2000);
- assertNotNull("Failed to receive an expected message", m);
- assertEquals("ID property did not match", i, m.getIntProperty("ID"));
- assertEquals("Message content was not as expected", STRING_1024, ((TextMessage)m).getText());
- }
-
- if(extraMessage)
- {
- //verify that the extra message is received
- m = consumer.receive(2000);
- assertNotNull("Failed to receive an expected message", m);
- assertEquals("ID property did not match", 1, m.getIntProperty("ID"));
- assertEquals("Message content was not as expected", STRING_1024_256, ((TextMessage)m).getText());
- }
-
- // Verify that no more messages are received
- m = consumer.receive(1000);
- assertNull("No more messages should have been recieved", m);
-
- consumer.close();
- session.close();
- }
-
- private void upgradeBrokerStore(String fromDir, String toDir) throws Exception
- {
- new BDBStoreUpgrade(_fromDir, _toDir, null, false, true).upgradeFromVersion(VERSION_4);
- }
-}
diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-to-upgrade/test-store/00000000.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-to-upgrade/test-store/00000000.jdb
deleted file mode 100644
index c4e4e6c306..0000000000
--- a/java/bdbstore/src/test/resources/upgrade/bdbstore-to-upgrade/test-store/00000000.jdb
+++ /dev/null
Binary files differ
diff --git a/java/broker-plugins/access-control/MANIFEST.MF b/java/broker-plugins/access-control/MANIFEST.MF
index 78072850e4..1cd285ba20 100644
--- a/java/broker-plugins/access-control/MANIFEST.MF
+++ b/java/broker-plugins/access-control/MANIFEST.MF
@@ -35,7 +35,6 @@ Import-Package: org.apache.qpid,
org.apache.log4j;version=1.0.0,
javax.management;version=1.0.0,
javax.management.openmbean;version=1.0.0,
- javax.security.auth;version=1.0.0,
org.osgi.util.tracker;version=1.0.0,
org.osgi.framework;version=1.3
Private-Package: org.apache.qpid.server.security.access.config,
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
index 78355a7501..ebc73440ed 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
@@ -18,24 +18,20 @@
*/
package org.apache.qpid.server.security.access.config;
-import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.WeakHashMap;
-import javax.security.auth.Subject;
-
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.security.Result;
@@ -49,132 +45,147 @@ import org.apache.qpid.server.security.access.logging.AccessControlMessages;
* Models the rule configuration for the access control plugin.
*
* The access control rule definitions are loaded from an external configuration file, passed in as the
- * target to the {@link load(ConfigurationFile)} method. The file specified
+ * target to the {@link load(ConfigurationFile)} method. The file specified
*/
public class RuleSet
{
+ private static final Logger _logger = Logger.getLogger(RuleSet.class);
+
private static final String AT = "@";
- private static final String SLASH = "/";
+ private static final String SLASH = "/";
- public static final String DEFAULT_ALLOW = "defaultallow";
- public static final String DEFAULT_DENY = "defaultdeny";
- public static final String TRANSITIVE = "transitive";
- public static final String EXPAND = "expand";
+ public static final String DEFAULT_ALLOW = "defaultallow";
+ public static final String DEFAULT_DENY = "defaultdeny";
+ public static final String TRANSITIVE = "transitive";
+ public static final String EXPAND = "expand";
public static final String AUTONUMBER = "autonumber";
public static final String CONTROLLED = "controlled";
public static final String VALIDATE = "validate";
-
+
public static final List<String> CONFIG_PROPERTIES = Arrays.asList(
DEFAULT_ALLOW, DEFAULT_DENY, TRANSITIVE, EXPAND, AUTONUMBER, CONTROLLED
);
-
+
private static final Integer _increment = 10;
-
- private final Map<String, List<String>> _aclGroups = new HashMap<String, List<String>>();
+
+ private final Map<String, List<String>> _groups = new HashMap<String, List<String>>();
private final SortedMap<Integer, Rule> _rules = new TreeMap<Integer, Rule>();
- private final Map<Subject, Map<Operation, Map<ObjectType, List<Rule>>>> _cache =
- new WeakHashMap<Subject, Map<Operation, Map<ObjectType, List<Rule>>>>();
+ private final Map<String, Map<Operation, Map<ObjectType, List<Rule>>>> _cache =
+ new WeakHashMap<String, Map<Operation, Map<ObjectType, List<Rule>>>>();
private final Map<String, Boolean> _config = new HashMap<String, Boolean>();
-
+
public RuleSet()
{
// set some default configuration properties
configure(DEFAULT_DENY, Boolean.TRUE);
configure(TRANSITIVE, Boolean.TRUE);
}
-
+
/**
- * Clear the contents, including acl groups, rules and configuration.
+ * Clear the contents, invluding groups, rules and configuration.
*/
public void clear()
{
_rules.clear();
_cache.clear();
_config.clear();
- _aclGroups.clear();
+ _groups.clear();
}
-
+
public int getRuleCount()
{
return _rules.size();
}
-
- /**
- * Filtered rules list based on a subject and operation.
- *
- * Allows only enabled rules with identity equal to all, the same, or a group with identity as a member,
- * and operation is either all or the same operation.
- */
- public List<Rule> getRules(final Subject subject, final Operation operation, final ObjectType objectType)
- {
- final Map<ObjectType, List<Rule>> objects = getObjectToRuleCache(subject, operation);
+
+ /**
+ * Filtered rules list based on an identity and operation.
+ *
+ * Allows only enabled rules with identity equal to all, the same, or a group with identity as a member,
+ * and operation is either all or the same operation.
+ */
+ public List<Rule> getRules(String identity, Operation operation, ObjectType objectType)
+ {
+ // Lookup identity in cache and create empty operation map if required
+ Map<Operation, Map<ObjectType, List<Rule>>> operations = _cache.get(identity);
+ if (operations == null)
+ {
+ operations = new EnumMap<Operation, Map<ObjectType, List<Rule>>>(Operation.class);
+ _cache.put(identity, operations);
+ }
+
+ // Lookup operation and create empty object type map if required
+ Map<ObjectType, List<Rule>> objects = operations.get(operation);
+ if (objects == null)
+ {
+ objects = new EnumMap<ObjectType, List<Rule>>(ObjectType.class);
+ operations.put(operation, objects);
+ }
// Lookup object type rules for the operation
if (!objects.containsKey(objectType))
{
- final Set<Principal> principals = subject.getPrincipals();
boolean controlled = false;
List<Rule> filtered = new LinkedList<Rule>();
for (Rule rule : _rules.values())
{
- final Action ruleAction = rule.getAction();
if (rule.isEnabled()
- && (ruleAction.getOperation() == Operation.ALL || ruleAction.getOperation() == operation)
- && (ruleAction.getObjectType() == ObjectType.ALL || ruleAction.getObjectType() == objectType))
+ && (rule.getAction().getOperation() == Operation.ALL || rule.getAction().getOperation() == operation)
+ && (rule.getAction().getObjectType() == ObjectType.ALL || rule.getAction().getObjectType() == objectType))
{
controlled = true;
- if (isRelevant(principals,rule))
+ if (rule.getIdentity().equalsIgnoreCase(Rule.ALL)
+ || rule.getIdentity().equalsIgnoreCase(identity)
+ || (_groups.containsKey(rule.getIdentity()) && _groups.get(rule.getIdentity()).contains(identity)))
{
filtered.add(rule);
}
}
}
-
+
// Return null if there are no rules at all for this operation and object type
if (filtered.isEmpty() && controlled == false)
{
filtered = null;
}
-
+
// Save the rules we selected
objects.put(objectType, filtered);
}
-
+
// Return the cached rules
- return objects.get(objectType);
- }
-
-
+ return objects.get(objectType);
+ }
+
public boolean isValidNumber(Integer number)
{
return !_rules.containsKey(number);
}
-
+
public void grant(Integer number, String identity, Permission permission, Operation operation)
{
Action action = new Action(operation);
addRule(number, identity, permission, action);
}
-
+
public void grant(Integer number, String identity, Permission permission, Operation operation, ObjectType object, ObjectProperties properties)
{
Action action = new Action(operation, object, properties);
addRule(number, identity, permission, action);
}
-
+
public boolean ruleExists(String identity, Action action)
{
- for (Rule rule : _rules.values())
- {
- if (rule.getIdentity().equals(identity) && rule.getAction().equals(action))
- {
- return true;
- }
- }
- return false;
+ for (Rule rule : _rules.values())
+ {
+ if (rule.getIdentity().equals(identity) && rule.getAction().equals(action))
+ {
+ return true;
+ }
+ }
+ return false;
}
-
+
private Permission noLog(Permission permission)
{
switch (permission)
@@ -192,17 +203,15 @@ public class RuleSet
// TODO make this work when group membership is not known at file parse time
public void addRule(Integer number, String identity, Permission permission, Action action)
{
- _cache.clear();
-
- if (!action.isAllowed())
- {
- throw new IllegalArgumentException("Action is not allowd: " + action);
- }
+ if (!action.isAllowed())
+ {
+ throw new IllegalArgumentException("Action is not allowd: " + action);
+ }
if (ruleExists(identity, action))
{
return;
}
-
+
// expand actions - possibly multiply number by
if (isSet(EXPAND))
{
@@ -225,8 +234,8 @@ public class RuleSet
return;
}
}
-
- // transitive action dependencies
+
+ // transitive action dependencies
if (isSet(TRANSITIVE))
{
if (action.getOperation() == Operation.CREATE && action.getObjectType() == ObjectType.QUEUE)
@@ -235,10 +244,10 @@ public class RuleSet
exchProperties.setName(ExchangeDefaults.DEFAULT_EXCHANGE_NAME);
exchProperties.put(ObjectProperties.Property.ROUTING_KEY, action.getProperties().get(ObjectProperties.Property.NAME));
addRule(null, identity, noLog(permission), new Action(Operation.BIND, ObjectType.EXCHANGE, exchProperties));
- if (action.getProperties().isSet(ObjectProperties.Property.AUTO_DELETE))
- {
- addRule(null, identity, noLog(permission), new Action(Operation.DELETE, ObjectType.QUEUE, action.getProperties()));
- }
+ if (action.getProperties().isSet(ObjectProperties.Property.AUTO_DELETE))
+ {
+ addRule(null, identity, noLog(permission), new Action(Operation.DELETE, ObjectType.QUEUE, action.getProperties()));
+ }
}
else if (action.getOperation() == Operation.DELETE && action.getObjectType() == ObjectType.QUEUE)
{
@@ -252,9 +261,9 @@ public class RuleSet
addRule(null, identity, noLog(permission), new Action(Operation.ACCESS, ObjectType.VIRTUALHOST));
}
}
-
+
// set rule number if needed
- Rule rule = new Rule(number, identity, action, permission);
+ Rule rule = new Rule(number, identity, action, permission);
if (rule.getNumber() == null)
{
if (_rules.isEmpty())
@@ -266,36 +275,34 @@ public class RuleSet
rule.setNumber(_rules.lastKey() + _increment);
}
}
-
+
// save rule
_cache.remove(identity);
_rules.put(rule.getNumber(), rule);
- }
-
+ }
+
public void enableRule(int ruleNumber)
{
_rules.get(Integer.valueOf(ruleNumber)).enable();
}
-
+
public void disableRule(int ruleNumber)
{
_rules.get(Integer.valueOf(ruleNumber)).disable();
}
-
+
public boolean addGroup(String group, List<String> constituents)
{
- _cache.clear();
-
- if (_aclGroups.containsKey(group))
+ if (_groups.containsKey(group))
{
// cannot redefine
return false;
}
else
{
- _aclGroups.put(group, new ArrayList<String>());
+ _groups.put(group, new ArrayList<String>());
}
-
+
for (String name : constituents)
{
if (name.equalsIgnoreCase(group))
@@ -303,17 +310,17 @@ public class RuleSet
// recursive definition
return false;
}
-
+
if (!checkName(name))
{
// invalid name
return false;
}
-
- if (_aclGroups.containsKey(name))
+
+ if (_groups.containsKey(name))
{
// is a group
- _aclGroups.get(group).addAll(_aclGroups.get(name));
+ _groups.get(group).addAll(_groups.get(name));
}
else
{
@@ -323,12 +330,12 @@ public class RuleSet
// invalid username
return false;
}
- _aclGroups.get(group).add(name);
+ _groups.get(group).add(name);
}
}
return true;
}
-
+
/** Return true if the name is well-formed (contains legal characters). */
protected boolean checkName(String name)
{
@@ -342,79 +349,79 @@ public class RuleSet
}
return true;
}
-
+
/** Returns true if a username has the name[@domain][/realm] format */
protected boolean isvalidUserName(String name)
- {
- // check for '@' and '/' in namne
- int atPos = name.indexOf(AT);
- int slashPos = name.indexOf(SLASH);
- boolean atFound = atPos != StringUtils.INDEX_NOT_FOUND && atPos == name.lastIndexOf(AT);
- boolean slashFound = slashPos != StringUtils.INDEX_NOT_FOUND && slashPos == name.lastIndexOf(SLASH);
-
- // must be at least one character after '@' or '/'
- if (atFound && atPos > name.length() - 2)
- {
- return false;
- }
- if (slashFound && slashPos > name.length() - 2)
- {
- return false;
- }
-
- // must be at least one character between '@' and '/'
- if (atFound && slashFound)
- {
- return (atPos < (slashPos - 1));
- }
-
- // otherwise all good
- return true;
+ {
+ // check for '@' and '/' in namne
+ int atPos = name.indexOf(AT);
+ int slashPos = name.indexOf(SLASH);
+ boolean atFound = atPos != StringUtils.INDEX_NOT_FOUND && atPos == name.lastIndexOf(AT);
+ boolean slashFound = slashPos != StringUtils.INDEX_NOT_FOUND && slashPos == name.lastIndexOf(SLASH);
+
+ // must be at least one character after '@' or '/'
+ if (atFound && atPos > name.length() - 2)
+ {
+ return false;
+ }
+ if (slashFound && slashPos > name.length() - 2)
+ {
+ return false;
+ }
+
+ // must be at least one character between '@' and '/'
+ if (atFound && slashFound)
+ {
+ return (atPos < (slashPos - 1));
+ }
+
+ // otherwise all good
+ return true;
}
- // C++ broker authorise function prototype
+ // C++ broker authorise function prototype
// virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType,
- // const std::string& name, std::map<Property, std::string>* params=0);
-
- // Possibly add a String name paramater?
+ // const std::string& name, std::map<Property, std::string>* params=0);
+
+ // Possibly add a String name paramater?
/**
* Check the authorisation granted to a particular identity for an operation on an object type with
* specific properties.
*
- * Looks up the entire ruleset, which may be cached, for the user and operation and goes through the rules
+ * Looks up the entire ruleset, whcih may be cached, for the user and operation and goes through the rules
* in order to find the first one that matches. Either defers if there are no rules, returns the result of
* the first match found, or denies access if there are no matching rules. Normally, it would be expected
* to have a default deny or allow rule at the end of an access configuration however.
*/
- public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
+ public Result check(String identity, Operation operation, ObjectType objectType, ObjectProperties properties)
{
// Create the action to check
Action action = new Action(operation, objectType, properties);
- // get the list of rules relevant for this request
- List<Rule> rules = getRules(subject, operation, objectType);
- if (rules == null)
- {
- if (isSet(CONTROLLED))
- {
- // Abstain if there are no rules for this operation
+ // get the list of rules relevant for this request
+ List<Rule> rules = getRules(identity, operation, objectType);
+ if (rules == null)
+ {
+ if (isSet(CONTROLLED))
+ {
+ // Abstain if there are no rules for this operation
return Result.ABSTAIN;
- }
- else
- {
- return getDefault();
- }
- }
-
- // Iterate through a filtered set of rules dealing with this identity and operation
+ }
+ else
+ {
+ return getDefault();
+ }
+ }
+
+ // Iterate through a filtered set of rules dealing with this identity and operation
for (Rule current : rules)
- {
- // Check if action matches
+ {
+ // Check if action matches
if (action.matches(current.getAction()))
{
Permission permission = current.getPermission();
-
+
switch (permission)
{
case ALLOW_LOG:
@@ -432,15 +439,15 @@ public class RuleSet
return Result.DENIED;
}
}
-
+
// Defer to the next plugin of this type, if it exists
- return Result.DEFER;
+ return Result.DEFER;
}
-
- /** Default deny. */
- public Result getDefault()
- {
- if (isSet(DEFAULT_ALLOW))
+
+ /** Default deny. */
+ public Result getDefault()
+ {
+ if (isSet(DEFAULT_ALLOW))
{
return Result.ALLOWED;
}
@@ -449,19 +456,19 @@ public class RuleSet
return Result.DENIED;
}
return Result.ABSTAIN;
- }
-
- /**
- * Check if a configuration property is set.
- */
- protected boolean isSet(String key)
- {
- return BooleanUtils.isTrue(_config.get(key));
- }
+ }
+
+ /**
+ * Check if a configuration property is set.
+ */
+ protected boolean isSet(String key)
+ {
+ return BooleanUtils.isTrue(_config.get(key));
+ }
/**
* Configure properties for the plugin instance.
- *
+ *
* @param properties
*/
public void configure(Map<String, Boolean> properties)
@@ -471,7 +478,7 @@ public class RuleSet
/**
* Configure a single property for the plugin instance.
- *
+ *
* @param key
* @param value
*/
@@ -479,48 +486,4 @@ public class RuleSet
{
_config.put(key, value);
}
-
- private boolean isRelevant(final Set<Principal> principals, final Rule rule)
- {
- if (rule.getIdentity().equalsIgnoreCase(Rule.ALL))
- {
- return true;
- }
- else
- {
- for (Iterator<Principal> iterator = principals.iterator(); iterator.hasNext();)
- {
- final Principal principal = iterator.next();
-
- if (rule.getIdentity().equalsIgnoreCase(principal.getName())
- || (_aclGroups.containsKey(rule.getIdentity()) && _aclGroups.get(rule.getIdentity()).contains(principal.getName())))
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- private Map<ObjectType, List<Rule>> getObjectToRuleCache(final Subject subject, final Operation operation)
- {
- // Lookup identity in cache and create empty operation map if required
- Map<Operation, Map<ObjectType, List<Rule>>> operations = _cache.get(subject);
- if (operations == null)
- {
- operations = new EnumMap<Operation, Map<ObjectType, List<Rule>>>(Operation.class);
- _cache.put(subject, operations);
- }
-
- // Lookup operation and create empty object type map if required
- Map<ObjectType, List<Rule>> objects = operations.get(operation);
- if (objects == null)
- {
- objects = new EnumMap<ObjectType, List<Rule>>(ObjectType.class);
- operations.put(operation, objects);
- }
- return objects;
- }
-
}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
index a7b3059262..69cfa173bd 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.server.security.access.plugins;
-import javax.security.auth.Subject;
+import java.security.Principal;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -89,19 +89,20 @@ public class AccessControl extends AbstractPlugin
/**
* Check if an operation is authorised by asking the configuration object about the access
- * control rules granted to the current thread's {@link Subject}. If there is no current
+ * control rules granted to the current thread's {@link Principal}. If there is no current
* user the plugin will abstain.
*/
public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
{
- final Subject subject = SecurityManager.getThreadSubject();
- // Abstain if there is no subject/principal associated with this thread
- if (subject == null || subject.getPrincipals().size() == 0)
+ Principal principal = SecurityManager.getThreadPrincipal();
+
+ // Abstain if there is no user associated with this thread
+ if (principal == null)
{
return Result.ABSTAIN;
}
-
- return _ruleSet.check(subject, operation, objectType, properties);
+
+ return _ruleSet.check(principal.getName(), operation, objectType, properties);
}
public void configure(ConfigurationPlugin config)
diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
index 09d26e5451..309a3aeb2c 100644
--- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
+++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
@@ -1,172 +1,195 @@
/*
+ * 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
*
- * 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.
+ * 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 org.apache.qpid.server.security.access.plugins;
-import java.util.Arrays;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.PrintWriter;
import junit.framework.TestCase;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.logging.UnitTestMessageLogger;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.TestLogActor;
-import org.apache.qpid.server.security.Result;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.access.ObjectProperties;
-import org.apache.qpid.server.security.access.ObjectType;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.access.Permission;
-import org.apache.qpid.server.security.access.config.Rule;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.security.access.config.ConfigurationFile;
+import org.apache.qpid.server.security.access.config.PlainConfiguration;
import org.apache.qpid.server.security.access.config.RuleSet;
-import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils;
/**
- * Unit test for ACL V2 plugin.
- *
- * This unit test tests the AccessControl class and it collaboration with {@link RuleSet},
- * {@link SecurityManager} and {@link CurrentActor}. The ruleset is configured programmatically,
- * rather than from an external file.
+ * These tests check that the ACL file parsing works correctly.
*
- * @see RuleSetTest
+ * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this
+ * particular message.
*/
public class AccessControlTest extends TestCase
{
- private AccessControl _plugin = null; // Class under test
- private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger();
-
- protected void setUp() throws Exception
+ public void writeACLConfig(String...aclData) throws Exception
{
- super.setUp();
-
- final RuleSet rs = new RuleSet();
- rs.addGroup("aclGroup1", Arrays.asList(new String[] {"member1", "member2"}));
-
- // Rule expressed with username
- rs.grant(0, "user1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- // Rule expressed with a acl group
- rs.grant(1, "aclGroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- // Rule expressed with an external group
- rs.grant(2, "extGroup1", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- // Catch all rule
- rs.grant(3, Rule.ALL, Permission.DENY_LOG, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
-
- _plugin = (AccessControl) AccessControl.FACTORY.newInstance(createConfiguration(rs));
-
- SecurityManager.setThreadSubject(null);
+ File acl = File.createTempFile(getClass().getName() + getName(), "acl");
+ acl.deleteOnExit();
- CurrentActor.set(new TestLogActor(messageLogger));
+ // Write ACL file
+ PrintWriter aclWriter = new PrintWriter(new FileWriter(acl));
+ for (String line : aclData)
+ {
+ aclWriter.println(line);
+ }
+ aclWriter.close();
+
+ // Load ruleset
+ ConfigurationFile configFile = new PlainConfiguration(acl);
+ RuleSet ruleSet = configFile.load();
}
- protected void tearDown() throws Exception
+ public void testMissingACLConfig() throws Exception
{
- super.tearDown();
- SecurityManager.setThreadSubject(null);
+ try
+ {
+ // Load ruleset
+ ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist"));
+ RuleSet ruleSet = configFile.load();
+
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage());
+ assertTrue(ce.getCause() instanceof FileNotFoundException);
+ assertEquals("doesnotexist (No such file or directory)", ce.getCause().getMessage());
+ }
}
- /**
- * ACL plugin must always abstain if there is no subject attached to the thread.
- */
- public void testNoSubjectAlwaysAbstains()
+ public void testACLFileSyntaxContinuation() throws Exception
{
- SecurityManager.setThreadSubject(null);
-
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.ABSTAIN, result);
+ try
+ {
+ writeACLConfig("ACL ALLOW ALL \\ ALL");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage());
+ }
}
- /**
- * Tests that an allow rule expressed with a username allows an operation performed by a thread running
- * with the same username.
- */
- public void testUsernameAllowsOperation()
+ public void testACLFileSyntaxTokens() throws Exception
{
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user1"));
-
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.ALLOWED, result);
+ try
+ {
+ writeACLConfig("ACL unparsed ALL ALL");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage());
+ assertTrue(ce.getCause() instanceof IllegalArgumentException);
+ assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage());
+ }
}
- /**
- * Tests that an allow rule expressed with an <b>ACL groupname</b> allows an operation performed by a thread running
- * by a user who belongs to the same group..
- */
- public void testAclGroupMembershipAllowsOperation()
+ public void testACLFileSyntaxNotEnoughGroup() throws Exception
{
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("member1"));
+ try
+ {
+ writeACLConfig("GROUP blah");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_GROUP_MSG, 1), ce.getMessage());
+ }
+ }
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.ALLOWED, result);
+ public void testACLFileSyntaxNotEnoughACL() throws Exception
+ {
+ try
+ {
+ writeACLConfig("ACL ALLOW");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage());
+ }
}
- /**
- * Tests that a deny rule expressed with an <b>External groupname</b> denies an operation performed by a thread running
- * by a user who belongs to the same group.
- */
- public void testExternalGroupMembershipDeniesOperation()
+ public void testACLFileSyntaxNotEnoughConfig() throws Exception
{
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user3", "extGroup1"));
-
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.DENIED, result);
+ try
+ {
+ writeACLConfig("CONFIG");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage());
+ }
}
- /**
- * Tests that the catch all deny denies the operation and logs with the logging actor.
- */
- public void testCatchAllRuleDeniesUnrecognisedUsername()
+ public void testACLFileSyntaxNotEnough() throws Exception
{
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2"));
-
- assertEquals("Expecting zero messages before test", 0, messageLogger.getLogMessages().size());
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.DENIED, result);
-
- assertEquals("Expecting one message before test", 1, messageLogger.getLogMessages().size());
- assertTrue("Logged message does not contain expected string", messageLogger.messageContains(0, "ACL-1002"));
+ try
+ {
+ writeACLConfig("INVALID");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage());
+ }
}
-
- /**
- * Creates a configuration plugin for the {@link AccessControl} plugin.
- */
- private ConfigurationPlugin createConfiguration(final RuleSet rs)
+
+ public void testACLFileSyntaxPropertyKeyOnly() throws Exception
{
- final ConfigurationPlugin cp = new ConfigurationPlugin()
- {
- public AccessControlConfiguration getConfiguration(final String plugin)
- {
- return new AccessControlConfiguration()
- {
- public RuleSet getRuleSet()
- {
- return rs;
- }
- };
- }
+ try
+ {
+ writeACLConfig("ACL ALLOW adk CREATE QUEUE name");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage());
+ }
+ }
- public String[] getElementsProcessed()
- {
- throw new UnsupportedOperationException();
- }
- };
+ public void testACLFileSyntaxPropertyNoEquals() throws Exception
+ {
+ try
+ {
+ writeACLConfig("ACL ALLOW adk CREATE QUEUE name test");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage());
+ }
+ }
- return cp;
+ public void testACLFileSyntaxPropertyNoValue() throws Exception
+ {
+ try
+ {
+ writeACLConfig("ACL ALLOW adk CREATE QUEUE name =");
+ fail("fail");
+ }
+ catch (ConfigurationException ce)
+ {
+ assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage());
+ }
}
}
diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java
deleted file mode 100644
index e16f9943ba..0000000000
--- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java
+++ /dev/null
@@ -1,194 +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.
- */
-package org.apache.qpid.server.security.access.plugins;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.PrintWriter;
-
-import junit.framework.TestCase;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.security.access.config.ConfigurationFile;
-import org.apache.qpid.server.security.access.config.PlainConfiguration;
-
-/**
- * These tests check that the ACL file parsing works correctly.
- *
- * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this
- * particular message.
- */
-public class PlainConfigurationTest extends TestCase
-{
- public void writeACLConfig(String...aclData) throws Exception
- {
- File acl = File.createTempFile(getClass().getName() + getName(), "acl");
- acl.deleteOnExit();
-
- // Write ACL file
- PrintWriter aclWriter = new PrintWriter(new FileWriter(acl));
- for (String line : aclData)
- {
- aclWriter.println(line);
- }
- aclWriter.close();
-
- // Load ruleset
- ConfigurationFile configFile = new PlainConfiguration(acl);
- configFile.load();
- }
-
- public void testMissingACLConfig() throws Exception
- {
- try
- {
- // Load ruleset
- ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist"));
- configFile.load();
-
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage());
- assertTrue(ce.getCause() instanceof FileNotFoundException);
- assertEquals("doesnotexist (No such file or directory)", ce.getCause().getMessage());
- }
- }
-
- public void testACLFileSyntaxContinuation() throws Exception
- {
- try
- {
- writeACLConfig("ACL ALLOW ALL \\ ALL");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxTokens() throws Exception
- {
- try
- {
- writeACLConfig("ACL unparsed ALL ALL");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage());
- assertTrue(ce.getCause() instanceof IllegalArgumentException);
- assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage());
- }
- }
-
- public void testACLFileSyntaxNotEnoughGroup() throws Exception
- {
- try
- {
- writeACLConfig("GROUP blah");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_GROUP_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxNotEnoughACL() throws Exception
- {
- try
- {
- writeACLConfig("ACL ALLOW");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxNotEnoughConfig() throws Exception
- {
- try
- {
- writeACLConfig("CONFIG");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxNotEnough() throws Exception
- {
- try
- {
- writeACLConfig("INVALID");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxPropertyKeyOnly() throws Exception
- {
- try
- {
- writeACLConfig("ACL ALLOW adk CREATE QUEUE name");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxPropertyNoEquals() throws Exception
- {
- try
- {
- writeACLConfig("ACL ALLOW adk CREATE QUEUE name test");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage());
- }
- }
-
- public void testACLFileSyntaxPropertyNoValue() throws Exception
- {
- try
- {
- writeACLConfig("ACL ALLOW adk CREATE QUEUE name =");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage());
- }
- }
-}
diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
index bd9deac153..aad7290557 100644
--- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
+++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
@@ -21,21 +21,13 @@
package org.apache.qpid.server.security.access.plugins;
-import java.security.Principal;
-import java.util.Arrays;
-
-import javax.security.auth.Subject;
-
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.security.Result;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
-import org.apache.qpid.server.security.access.config.Rule;
import org.apache.qpid.server.security.access.config.RuleSet;
-import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.test.utils.QpidTestCase;
/**
@@ -44,24 +36,16 @@ import org.apache.qpid.test.utils.QpidTestCase;
* The ruleset is configured directly rather than using an external file by adding rules individually, calling the
* {@link RuleSet#grant(Integer, String, Permission, Operation, ObjectType, ObjectProperties)} method. Then, the
* access control mechanism is validated by checking whether operations would be authorised by calling the
- * {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method.
- *
- * It ensure that permissions can be granted correctly on users directly, ACL groups (that is those
- * groups declared directly in the ACL itself), and External groups (that is a group from an External
- * Authentication Provider, such as an LDAP).
-
+ * {@link RuleSet#check(String, Operation, ObjectType, ObjectProperties)} method.
*/
public class RuleSetTest extends QpidTestCase
{
- private RuleSet _ruleSet; // Object under test
-
- private static final String TEST_USER = "user";
+ private RuleSet _ruleSet;
// Common things that are passed to frame constructors
private AMQShortString _queueName = new AMQShortString(this.getClass().getName() + "queue");
private AMQShortString _exchangeName = new AMQShortString("amq.direct");
private AMQShortString _exchangeType = new AMQShortString("direct");
- private Subject _testSubject = TestPrincipalUtils.createTestSubject(TEST_USER);
@Override
public void setUp() throws Exception
@@ -79,36 +63,34 @@ public class RuleSetTest extends QpidTestCase
super.tearDown();
}
- public void assertDenyGrantAllow(Subject subject, Operation operation, ObjectType objectType)
+ public void assertDenyGrantAllow(String identity, Operation operation, ObjectType objectType)
{
- assertDenyGrantAllow(subject, operation, objectType, ObjectProperties.EMPTY);
+ assertDenyGrantAllow(identity, operation, objectType, ObjectProperties.EMPTY);
}
- public void assertDenyGrantAllow(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
+ public void assertDenyGrantAllow(String identity, Operation operation, ObjectType objectType, ObjectProperties properties)
{
- final Principal identity = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
-
- assertEquals(Result.DENIED, _ruleSet.check(subject, operation, objectType, properties));
- _ruleSet.grant(0, identity.getName(), Permission.ALLOW, operation, objectType, properties);
+ assertEquals(Result.DENIED, _ruleSet.check(identity, operation, objectType, properties));
+ _ruleSet.grant(0, identity, Permission.ALLOW, operation, objectType, properties);
assertEquals(1, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(subject, operation, objectType, properties));
+ assertEquals(Result.ALLOWED, _ruleSet.check(identity, operation, objectType, properties));
}
public void testEmptyRuleSet()
{
assertNotNull(_ruleSet);
assertEquals(_ruleSet.getRuleCount(), 0);
- assertEquals(_ruleSet.getDefault(), _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(_ruleSet.getDefault(), _ruleSet.check("user", Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
public void testVirtualHostAccess() throws Exception
{
- assertDenyGrantAllow(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST);
+ assertDenyGrantAllow("user", Operation.ACCESS, ObjectType.VIRTUALHOST);
}
public void testQueueCreateNamed() throws Exception
{
- assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queueName));
+ assertDenyGrantAllow("user", Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queueName));
}
public void testQueueCreatenamedNullRoutingKey()
@@ -116,7 +98,7 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties properties = new ObjectProperties(_queueName);
properties.put(ObjectProperties.Property.ROUTING_KEY, (String) null);
- assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.QUEUE, properties);
+ assertDenyGrantAllow("user", Operation.CREATE, ObjectType.QUEUE, properties);
}
public void testExchangeCreate()
@@ -124,17 +106,17 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties properties = new ObjectProperties(_exchangeName);
properties.put(ObjectProperties.Property.TYPE, _exchangeType.asString());
- assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, properties);
+ assertDenyGrantAllow("user", Operation.CREATE, ObjectType.EXCHANGE, properties);
}
public void testConsume()
{
- assertDenyGrantAllow(_testSubject, Operation.CONSUME, ObjectType.QUEUE);
+ assertDenyGrantAllow("user", Operation.CONSUME, ObjectType.QUEUE);
}
public void testPublish()
{
- assertDenyGrantAllow(_testSubject, Operation.PUBLISH, ObjectType.EXCHANGE);
+ assertDenyGrantAllow("user", Operation.PUBLISH, ObjectType.EXCHANGE);
}
/**
@@ -149,13 +131,13 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties normal = new ObjectProperties();
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
- _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
+ _ruleSet.grant(0, "user", Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
assertEquals(1, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
// defer to global if exists, otherwise default answer - this is handled by the security manager
- assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
+ assertEquals(Result.DEFER, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, normal));
}
/**
@@ -169,15 +151,15 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
// should not matter if the temporary permission is processed first or last
- _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
- _ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
+ _ruleSet.grant(1, "user", Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
+ _ruleSet.grant(2, "user", Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, normal));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
}
/**
@@ -191,15 +173,15 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties normal = new ObjectProperties(_queueName);
normal.put(ObjectProperties.Property.AUTO_DELETE, Boolean.FALSE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
// should not matter if the temporary permission is processed first or last
- _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
- _ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
+ _ruleSet.grant(1, "user", Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, temporary);
+ _ruleSet.grant(2, "user", Permission.ALLOW, Operation.CONSUME, ObjectType.QUEUE, normal);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, normal));
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CONSUME, ObjectType.QUEUE, temporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, normal));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CONSUME, ObjectType.QUEUE, temporary));
}
/*
@@ -215,15 +197,15 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
- _ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
+ _ruleSet.grant(1, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
+ _ruleSet.grant(2, "user", Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
/**
@@ -235,15 +217,15 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- _ruleSet.grant(1, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
- _ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
+ _ruleSet.grant(1, "user", Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
+ _ruleSet.grant(2, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
/**
@@ -257,18 +239,18 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties namedDurable = new ObjectProperties(_queueName);
namedDurable.put(ObjectProperties.Property.DURABLE, Boolean.TRUE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedDurable));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedDurable));
- _ruleSet.grant(1, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
- _ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedDurable);
- _ruleSet.grant(3, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
+ _ruleSet.grant(1, "user", Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
+ _ruleSet.grant(2, "user", Permission.DENY, Operation.CREATE, ObjectType.QUEUE, namedDurable);
+ _ruleSet.grant(3, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(3, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedDurable));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedDurable));
}
public void testNamedTemporaryQueueAllowed()
@@ -277,15 +259,15 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
- _ruleSet.grant(2, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
+ _ruleSet.grant(1, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
+ _ruleSet.grant(2, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
public void testNamedTemporaryQueueDeniedAllowed()
@@ -294,101 +276,14 @@ public class RuleSetTest extends QpidTestCase
ObjectProperties namedTemporary = new ObjectProperties(_queueName);
namedTemporary.put(ObjectProperties.Property.AUTO_DELETE, Boolean.TRUE);
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
- _ruleSet.grant(2, TEST_USER, Permission.DENY, Operation.CREATE, ObjectType.QUEUE, named);
+ _ruleSet.grant(1, "user", Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, namedTemporary);
+ _ruleSet.grant(2, "user", Permission.DENY, Operation.CREATE, ObjectType.QUEUE, named);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, named));
- assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, namedTemporary));
- }
-
- /**
- * Tests support for the {@link Rule#ALL} keyword.
- */
- public void testAllowToAll()
- {
- _ruleSet.grant(1, Rule.ALL, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(1, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Tests support for ACL groups (i.e. inline groups declared in the ACL file itself).
- */
- public void testAclGroupsSupported()
- {
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"})));
-
- _ruleSet.grant(1, "aclgroup", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(1, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("userc"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Tests support for nested ACL groups.
- */
- public void testNestedAclGroupsSupported()
- {
- assertTrue(_ruleSet.addGroup("aclgroup1", Arrays.asList(new String[] {"userb"})));
- assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"})));
-
- _ruleSet.grant(1, "aclgroup2", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(1, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Tests support for nested External groups (i.e. those groups coming from an external source such as an LDAP).
- */
- public void testExternalGroupsSupported()
- {
- _ruleSet.grant(1, "extgroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "extgroup2", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(2, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", "extgroup1"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", "extgroup2"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Rule order in the ACL determines the outcome of the check. This test ensures that a user who is
- * granted explicit permission on an object, is granted that access even although late a group
- * to which the user belongs is later denied the permission.
- */
- public void testAllowDeterminedByRuleOrder()
- {
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
-
- _ruleSet.grant(1, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(2, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Rule order in the ACL determines the outcome of the check. This tests ensures that a user who is denied
- * access by group, is denied access, despite there being a later rule granting permission to that user.
- */
- public void testDenyDeterminedByRuleOrder()
- {
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
-
- _ruleSet.grant(1, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
-
- assertEquals(2, _ruleSet.getRuleCount());
-
- assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.DENIED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, named));
+ assertEquals(Result.ALLOWED, _ruleSet.check("user", Operation.CREATE, ObjectType.QUEUE, namedTemporary));
}
}
diff --git a/java/broker-plugins/experimental/info/build.xml b/java/broker-plugins/experimental/info/build.xml
index 8f91adc5ff..c5881aa839 100644
--- a/java/broker-plugins/experimental/info/build.xml
+++ b/java/broker-plugins/experimental/info/build.xml
@@ -20,14 +20,7 @@ nn - or more contributor license agreements. See the NOTICE file
-->
<project name="AMQ Broker Info Plugin" default="build">
- <condition property="info-plugin.optional.depends" value="bdbstore" else="">
- <and>
- <contains string="${modules.opt}" substring="bdbstore"/>
- <contains string="${profile}" substring="bdb"/>
- </and>
- </condition>
-
- <property name="module.depends" value="common broker broker-plugins ${info-plugin.optional.depends}"/>
+ <property name="module.depends" value="common broker broker-plugins"/>
<property name="module.test.depends" value="test broker/test management/common client systests common/test"/>
<property name="module.manifest" value="MANIFEST.MF"/>
<property name="module.plugin" value="true"/>
diff --git a/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java b/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java
index 21e7be26c1..c7d3fd38ff 100644
--- a/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java
+++ b/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java
@@ -59,14 +59,7 @@ public class Activator implements BundleActivator
_ctx = ctx;
_service = new InfoServiceImpl();
ctx.registerService(InfoService.class.getName(), _service, null);
-
- new Thread(new Runnable()
- {
- public void run()
- {
- sendInfo("STARTUP");
- }
- }).start();
+ sendInfo("STARTUP");
}
}
diff --git a/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java b/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
index c8e9805cd9..a5d267282b 100644
--- a/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
+++ b/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java
@@ -70,13 +70,15 @@ public class AppInfo
sc = ApplicationRegistry.getInstance().getConfiguration();
if (null != sc)
{
- appInfoMap.put("jmxport", sc.getJMXPortRegistryServer() + "");
+ appInfoMap.put("jmxport", sc.getJMXManagementPort() + "");
appInfoMap.put("port", sc.getPorts().toString());
appInfoMap.put("version", QpidProperties.getReleaseVersion());
appInfoMap.put("vhosts", "standalone");
- appInfoMap.put("KeystorePath", sc.getConnectorKeyStorePath());
+ appInfoMap.put("JMXPrincipalDatabase", sc
+ .getJMXPrincipalDatabase());
+ appInfoMap.put("KeystorePath", sc.getKeystorePath());
appInfoMap.put("PluginDirectory", sc.getPluginDirectory());
- appInfoMap.put("CertType", sc.getConnectorCertType());
+ appInfoMap.put("CertType", sc.getCertType());
appInfoMap.put("QpidWork", sc.getQpidWork());
appInfoMap.put("Bind", sc.getBind());
}
diff --git a/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java b/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java
index 348e860d5f..156c9eb138 100644
--- a/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java
+++ b/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java
@@ -210,13 +210,12 @@ public class InfoPluginTest extends QpidBrokerTestCase
}
br.close();
System.out.println("*** Received buffer: " + buf);
+ System.out.println("*** Latch countdown");
+ _latch.countDown();
synchronized (_recv)
{
_recv.add(buf);
}
-
- System.out.println("*** Latch countdown");
- _latch.countDown();
}
catch (Exception ex)
{
diff --git a/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd b/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
index f6ae79536d..6e005f5bdb 100755
--- a/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
+++ b/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.13.0
+ver: 0.9.0
Bundle-SymbolicName: qpid-shutdown-plugin
Bundle-Version: ${ver}
diff --git a/java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java b/java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java
index db3ebfd4e1..57b6e19b5d 100644
--- a/java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java
+++ b/java/broker-plugins/extras/src/test/java/org/apache/qpid/server/plugins/ExtrasTest.java
@@ -67,7 +67,7 @@ public class ExtrasTest extends TestCase
public void testNoExchanges() throws Exception
{
- PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp", null);
+ PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp");
Map<String, ExchangeType<?>> exchanges = manager.getExchanges();
assertTrue("Exchanges found", exchanges.isEmpty());
}
diff --git a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
index e078675efc..ab8957e7ef 100644
--- a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
+++ b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java
@@ -28,19 +28,12 @@ import java.net.InetSocketAddress;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
-public class FirewallConfigurationTest extends QpidTestCase
+public class FirewallConfigurationTest extends InternalBrokerBaseCase
{
- @Override
- protected void tearDown() throws Exception
- {
- super.tearDown();
- ApplicationRegistry.remove();
- }
-
public void testFirewallConfiguration() throws Exception
{
// Write out config
@@ -50,11 +43,18 @@ public class FirewallConfigurationTest extends QpidTestCase
// Load config
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ try
+ {
+ ApplicationRegistry.initialise(reg, 1);
- // Test config
- assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
- assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.1.2.3", 65535)));
+ // Test config
+ assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.1.2.3", 65535)));
+ }
+ finally
+ {
+ ApplicationRegistry.remove(1);
+ }
}
public void testCombinedConfigurationFirewall() throws Exception
@@ -80,8 +80,9 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t<cache-directory>${QPID_WORK}/cache</cache-directory>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -90,7 +91,11 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<xml fileName=\"" + fileB.getAbsolutePath() + "\"/>");
out.write("\t\t</firewall>\n");
@@ -111,10 +116,17 @@ public class FirewallConfigurationTest extends QpidTestCase
// Load config
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ try
+ {
+ ApplicationRegistry.initialise(reg, 1);
- // Test config
- assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ // Test config
+ assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ }
+ finally
+ {
+ ApplicationRegistry.remove(1);
+ }
}
public void testConfigurationFirewallReload() throws Exception
@@ -127,17 +139,24 @@ public class FirewallConfigurationTest extends QpidTestCase
// Load config
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ try
+ {
+ ApplicationRegistry.initialise(reg, 1);
- // Test config
- assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ // Test config
+ assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
- // Switch to deny the connection
- writeConfigFile(mainFile, true);
+ // Switch to deny the connection
+ writeConfigFile(mainFile, true);
- reg.getConfiguration().reparseConfigFileSecuritySections();
+ reg.getConfiguration().reparseConfigFileSecuritySections();
- assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ }
+ finally
+ {
+ ApplicationRegistry.remove(1);
+ }
}
public void testCombinedConfigurationFirewallReload() throws Exception
@@ -162,8 +181,9 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t<plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -172,7 +192,11 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<xml fileName=\"" + fileB.getAbsolutePath() + "\"/>");
out.write("\t\t</firewall>\n");
@@ -193,40 +217,47 @@ public class FirewallConfigurationTest extends QpidTestCase
// Load config
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ try
+ {
+ ApplicationRegistry.initialise(reg, 1);
- // Test config
- assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ // Test config
+ assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
- RandomAccessFile fileBRandom = new RandomAccessFile(fileB, "rw");
- fileBRandom.setLength(0);
- fileBRandom.seek(0);
- fileBRandom.close();
+ RandomAccessFile fileBRandom = new RandomAccessFile(fileB, "rw");
+ fileBRandom.setLength(0);
+ fileBRandom.seek(0);
+ fileBRandom.close();
- out = new FileWriter(fileB);
- out.write("<firewall>\n");
- out.write("\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
- out.write("</firewall>\n");
- out.close();
+ out = new FileWriter(fileB);
+ out.write("<firewall>\n");
+ out.write("\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
+ out.write("</firewall>\n");
+ out.close();
- reg.getConfiguration().reparseConfigFileSecuritySections();
+ reg.getConfiguration().reparseConfigFileSecuritySections();
- assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
- fileBRandom = new RandomAccessFile(fileB, "rw");
- fileBRandom.setLength(0);
- fileBRandom.seek(0);
- fileBRandom.close();
+ fileBRandom = new RandomAccessFile(fileB, "rw");
+ fileBRandom.setLength(0);
+ fileBRandom.seek(0);
+ fileBRandom.close();
- out = new FileWriter(fileB);
- out.write("<firewall>\n");
- out.write("\t<rule access=\"deny\" network=\"127.0.0.1\"/>");
- out.write("</firewall>\n");
- out.close();
+ out = new FileWriter(fileB);
+ out.write("<firewall>\n");
+ out.write("\t<rule access=\"deny\" network=\"127.0.0.1\"/>");
+ out.write("</firewall>\n");
+ out.close();
- reg.getConfiguration().reparseConfigFileSecuritySections();
+ reg.getConfiguration().reparseConfigFileSecuritySections();
- assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535)));
+ }
+ finally
+ {
+ ApplicationRegistry.remove(1);
+ }
}
private void writeFirewallVhostsFile(File vhostsFile, boolean allow) throws IOException
@@ -260,8 +291,9 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t<plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -270,7 +302,11 @@ public class FirewallConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<rule access=\""+ ((allow) ? "allow" : "deny") +"\" network=\"127.0.0.1\"/>");
out.write("\t\t</firewall>\n");
@@ -310,8 +346,8 @@ public class FirewallConfigurationTest extends QpidTestCase
// Load config
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
-
+ ApplicationRegistry.initialise(reg, 1);
+
// Test config
VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry();
VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test");
diff --git a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java
index 00077d9d9c..2b04962c89 100644
--- a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java
+++ b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java
@@ -27,15 +27,12 @@ import java.net.SocketAddress;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.Result;
import org.apache.qpid.server.security.access.plugins.Firewall;
import org.apache.qpid.server.security.access.plugins.FirewallConfiguration;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
-public class FirewallPluginTest extends QpidTestCase
+public class FirewallPluginTest extends InternalBrokerBaseCase
{
public class RuleInfo
{
@@ -76,23 +73,15 @@ public class FirewallPluginTest extends QpidTestCase
// IP address
private SocketAddress _address;
- private ServerConfiguration _serverConfig;
@Override
- protected void setUp() throws Exception
+ public void setUp() throws Exception
{
super.setUp();
- _serverConfig = new ServerConfiguration(new XMLConfiguration());
- ApplicationRegistry.initialise(new TestApplicationRegistry(_serverConfig));
+
_address = new InetSocketAddress("127.0.0.1", 65535);
}
- @Override
- protected void tearDown() throws Exception
- {
- super.tearDown();
- ApplicationRegistry.remove();
- }
private Firewall initialisePlugin(String defaultAction, RuleInfo[] rules) throws IOException, ConfigurationException
{
// Create sample config file
@@ -119,7 +108,7 @@ public class FirewallPluginTest extends QpidTestCase
}
buf.write("</firewall>");
buf.close();
-
+
// Configure plugin
FirewallConfiguration config = new FirewallConfiguration();
config.setConfiguration("", new XMLConfiguration(confFile));
diff --git a/java/broker-plugins/simple-xml/MANIFEST.MF b/java/broker-plugins/simple-xml/MANIFEST.MF
new file mode 100644
index 0000000000..04fe7518df
--- /dev/null
+++ b/java/broker-plugins/simple-xml/MANIFEST.MF
@@ -0,0 +1,36 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Broker-Plugins Simple XML
+Bundle-SymbolicName: broker-plugins-simple-xml
+Bundle-Description: Simple XML ACL plugin for Qpid.
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-DocURL: http://www.apache.org/
+Bundle-Version: 1.0.0
+Bundle-Activator: org.apache.qpid.server.security.access.plugins.SimpleXMLActivator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.5
+Bundle-ClassPath: .
+Bundle-ActivationPolicy: lazy
+Import-Package: org.apache.qpid,
+ org.apache.qpid.framing,
+ org.apache.qpid.junit.extensions.util,
+ org.apache.qpid.protocol,
+ org.apache.qpid.server.configuration,
+ org.apache.qpid.server.configuration.plugins,
+ org.apache.qpid.server.exchange,
+ org.apache.qpid.server.management,
+ org.apache.qpid.server.plugins,
+ org.apache.qpid.server.queue,
+ org.apache.qpid.server.security,
+ org.apache.qpid.server.security.access,
+ org.apache.qpid.server.virtualhost,
+ org.apache.qpid.util,
+ org.apache.commons.configuration;version=1.0.0,
+ org.apache.commons.lang;version=1.0.0,
+ org.apache.commons.lang.builder;version=1.0.0,
+ org.apache.log4j;version=1.0.0,
+ javax.management;version=1.0.0,
+ javax.management.openmbean;version=1.0.0,
+ org.osgi.util.tracker;version=1.0.0,
+ org.osgi.framework;version=1.3
+Private-Package: org.apache.qpid.server.security.access.config
+Export-Package: org.apache.qpid.server.security.access.plugins
diff --git a/java/broker-plugins/simple-xml/build.xml b/java/broker-plugins/simple-xml/build.xml
new file mode 100644
index 0000000000..d3cd451648
--- /dev/null
+++ b/java/broker-plugins/simple-xml/build.xml
@@ -0,0 +1,29 @@
+<!--
+ - 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.
+ -->
+<project name="Qpid Broker-Plugins Simple XML" default="build">
+ <property name="module.depends" value="common broker broker-plugins" />
+ <property name="module.test.depends" value="test broker/test common/test management/common systests" />
+
+ <property name="module.manifest" value="MANIFEST.MF" />
+ <property name="module.plugin" value="true" />
+
+ <import file="../../module.xml" />
+
+ <target name="bundle" depends="bundle-tasks" />
+</project>
diff --git a/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java
new file mode 100755
index 0000000000..d9fc292f03
--- /dev/null
+++ b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/config/PrincipalPermissions.java
@@ -0,0 +1,687 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security.access.config;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.security.Result;
+
+@SuppressWarnings("unchecked")
+public class PrincipalPermissions
+{
+ public enum Permission
+ {
+ CONSUME,
+ PUBLISH,
+ CREATEQUEUE,
+ CREATEEXCHANGE,
+ ACCESS,
+ BIND,
+ UNBIND,
+ DELETE,
+ PURGE
+ }
+
+ private static final Logger _logger = Logger.getLogger(PrincipalPermissions.class);
+
+ private static final Object CONSUME_QUEUES_KEY = new Object();
+ private static final Object CONSUME_TEMPORARY_KEY = new Object();
+ private static final Object CONSUME_OWN_QUEUES_ONLY_KEY = new Object();
+
+ private static final Object CREATE_QUEUES_KEY = new Object();
+ private static final Object CREATE_EXCHANGES_KEY = new Object();
+
+
+ private static final Object CREATE_QUEUE_TEMPORARY_KEY = new Object();
+ private static final Object CREATE_QUEUE_QUEUES_KEY = new Object();
+ private static final Object CREATE_QUEUE_EXCHANGES_KEY = new Object();
+
+ private static final Object CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY = new Object();
+
+ private static final int PUBLISH_EXCHANGES_KEY = 0;
+
+ private Map _permissions;
+ private boolean _fullVHostAccess = false;
+
+ private String _user;
+
+
+ public PrincipalPermissions(String user)
+ {
+ _user = user;
+ _permissions = new ConcurrentHashMap();
+ }
+
+ /**
+ *
+ * @param permission the type of permission to check
+ *
+ * @param parameters vararg depending on what permission was passed in
+ * ACCESS: none
+ * BIND: none
+ * CONSUME: AMQShortString queueName, Boolean temporary, Boolean ownQueueOnly
+ * CREATEQUEUE: Boolean temporary, AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey
+ * CREATEEXCHANGE: AMQShortString exchangeName, AMQShortString Class
+ * DELETE: none
+ * PUBLISH: Exchange exchange, AMQShortString routingKey
+ * PURGE: none
+ * UNBIND: none
+ */
+ public void grant(Permission permission, Object... parameters)
+ {
+ switch (permission)
+ {
+ case ACCESS:// Parameters : None
+ grantAccess(permission);
+ break;
+ case CONSUME: // Parameters : AMQShortString queueName, Boolean Temporary, Boolean ownQueueOnly
+ grantConsume(permission, parameters);
+ break;
+ case CREATEQUEUE: // Parameters : Boolean temporary, AMQShortString queueName
+ // , AMQShortString exchangeName , AMQShortString routingKey
+ grantCreateQueue(permission, parameters);
+ break;
+ case CREATEEXCHANGE:
+ // Parameters AMQShortString exchangeName , AMQShortString Class
+ grantCreateExchange(permission, parameters);
+ break;
+ case PUBLISH: // Parameters : Exchange exchange, AMQShortString routingKey
+ grantPublish(permission, parameters);
+ break;
+ /* The other cases just fall through to no-op */
+ case DELETE:
+ case BIND: // All the details are currently included in the create setup.
+ case PURGE:
+ case UNBIND:
+ break;
+ }
+
+ }
+
+ private void grantAccess(Permission permission)
+ {
+ _fullVHostAccess = true;
+ }
+
+ private void grantPublish(Permission permission, Object... parameters) {
+ Map publishRights = (Map) _permissions.get(permission);
+
+ if (publishRights == null)
+ {
+ publishRights = new ConcurrentHashMap();
+ _permissions.put(permission, publishRights);
+ }
+
+ if (parameters == null || parameters.length == 0)
+ {
+ //If we have no parameters then allow publish to all destinations
+ // this is signified by having a null value for publish_exchanges
+ }
+ else
+ {
+ Map publish_exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY);
+
+ if (publish_exchanges == null)
+ {
+ publish_exchanges = new ConcurrentHashMap();
+ publishRights.put(PUBLISH_EXCHANGES_KEY, publish_exchanges);
+ }
+
+
+ HashSet routingKeys = (HashSet) publish_exchanges.get(parameters[0]);
+
+ // Check to see if we have a routing key
+ if (parameters.length == 2)
+ {
+ if (routingKeys == null)
+ {
+ routingKeys = new HashSet<AMQShortString>();
+ }
+ //Add routing key to permitted publish destinations
+ routingKeys.add(parameters[1]);
+ }
+
+ // Add the updated routingkey list or null if all values allowed
+ publish_exchanges.put(parameters[0], routingKeys);
+ }
+ }
+
+ private void grantCreateExchange(Permission permission, Object... parameters) {
+ Map rights = (Map) _permissions.get(permission);
+ if (rights == null)
+ {
+ rights = new ConcurrentHashMap();
+ _permissions.put(permission, rights);
+ }
+
+ Map create_exchanges = (Map) rights.get(CREATE_EXCHANGES_KEY);
+ if (create_exchanges == null)
+ {
+ create_exchanges = new ConcurrentHashMap();
+ rights.put(CREATE_EXCHANGES_KEY, create_exchanges);
+ }
+
+ //Should perhaps error if parameters[0] is null;
+ AMQShortString name = parameters.length > 0 ? (AMQShortString) parameters[0] : null;
+ AMQShortString className = parameters.length > 1 ? (AMQShortString) parameters[1] : new AMQShortString("direct");
+
+ //Store the exchangeName / class mapping if the mapping is null
+ rights.put(name, className);
+ }
+
+ private void grantCreateQueue(Permission permission, Object... parameters)
+ {
+ Map createRights = (Map) _permissions.get(permission);
+
+ if (createRights == null)
+ {
+ createRights = new ConcurrentHashMap();
+ _permissions.put(permission, createRights);
+ }
+
+ //The existence of the empty map mean permission to all.
+ if (parameters.length == 0)
+ {
+ return;
+ }
+
+ // Get the queues map
+ Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY);
+
+ //Initialiase the queue permissions if not already done
+ if (create_queues == null)
+ {
+ create_queues = new ConcurrentHashMap();
+ //initialise temp queue permission to false and overwrite below if true
+ create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, false);
+ createRights.put(CREATE_QUEUES_KEY, create_queues);
+ }
+
+ //Create empty list of queues
+ Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY);
+
+ if (create_queues_queues == null)
+ {
+ create_queues_queues = new ConcurrentHashMap();
+ create_queues.put(CREATE_QUEUE_QUEUES_KEY, create_queues_queues);
+ }
+
+ // If we are initialising and granting CREATE rights to all temporary queues, then that's all we do
+ Boolean temporary = false;
+ if (parameters.length == 1)
+ {
+ temporary = (Boolean) parameters[0];
+ create_queues.put(CREATE_QUEUE_TEMPORARY_KEY, temporary);
+ return;
+ }
+
+ //From here we can be permissioning a variety of things, with varying parameters
+ AMQShortString queueName = parameters.length > 1 ? (AMQShortString) parameters[1] : null;
+ AMQShortString exchangeName = parameters.length > 2 ? (AMQShortString) parameters[2] : null;
+ //Set the routingkey to the specified value or the queueName if present
+ AMQShortString routingKey = (parameters.length > 3 && null != parameters[3]) ? (AMQShortString) parameters[3] : queueName;
+ // if we have a queueName then we need to store any associated exchange / rk bindings
+ if (queueName != null)
+ {
+ Map queue = (Map) create_queues_queues.get(queueName);
+ if (queue == null)
+ {
+ queue = new ConcurrentHashMap();
+ create_queues_queues.put(queueName, queue);
+ }
+
+ if (exchangeName != null)
+ {
+ queue.put(exchangeName, routingKey);
+ }
+
+ //If no exchange is specified then the presence of the queueName in the map says any exchange is ok
+ }
+
+ // Store the exchange that we are being granted rights to. This will be used as part of binding
+
+ //Lookup the list of exchanges
+ Map create_queues_exchanges = (Map) create_queues.get(CREATE_QUEUE_EXCHANGES_KEY);
+
+ if (create_queues_exchanges == null)
+ {
+ create_queues_exchanges = new ConcurrentHashMap();
+ create_queues.put(CREATE_QUEUE_EXCHANGES_KEY, create_queues_exchanges);
+ }
+
+ //if we have an exchange
+ if (exchangeName != null)
+ {
+ //Retrieve the list of permitted exchanges.
+ Map exchanges = (Map) create_queues_exchanges.get(exchangeName);
+
+ if (exchanges == null)
+ {
+ exchanges = new ConcurrentHashMap();
+ create_queues_exchanges.put(exchangeName, exchanges);
+ }
+
+ //Store the binding details of queue/rk for this exchange.
+ if (queueName != null)
+ {
+ //Retrieve the list of permitted routingKeys.
+ Map rKeys = (Map) exchanges.get(exchangeName);
+
+ if (rKeys == null)
+ {
+ rKeys = new ConcurrentHashMap();
+ exchanges.put(CREATE_QUEUE_EXCHANGES_ROUTINGKEYS_KEY, rKeys);
+ }
+
+ rKeys.put(queueName, routingKey);
+ }
+ }
+ }
+
+ /**
+ * Grant consume permissions
+ */
+ private void grantConsume(Permission permission, Object... parameters)
+ {
+ Map consumeRights = (Map) _permissions.get(permission);
+
+ if (consumeRights == null)
+ {
+ consumeRights = new ConcurrentHashMap();
+ _permissions.put(permission, consumeRights);
+
+ //initialise own and temporary rights to false to be overwritten below if set
+ consumeRights.put(CONSUME_TEMPORARY_KEY, false);
+ consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, false);
+ }
+
+
+ //if we only have one param then we're permissioning temporary queues and topics
+ if (parameters.length == 1)
+ {
+ Boolean temporary = (Boolean) parameters[0];
+
+ if (temporary)
+ {
+ consumeRights.put(CONSUME_TEMPORARY_KEY, true);
+ }
+ }
+
+ //if we have 2 parameters - should be a contract for this, but for now we'll handle it as is
+ if (parameters.length == 2)
+ {
+ AMQShortString queueName = (AMQShortString) parameters[0];
+ Boolean ownQueueOnly = (Boolean) parameters[1];
+
+ if (ownQueueOnly)
+ {
+ consumeRights.put(CONSUME_OWN_QUEUES_ONLY_KEY, true);
+ }
+
+ LinkedList queues = (LinkedList) consumeRights.get(CONSUME_QUEUES_KEY);
+ if (queues == null)
+ {
+ queues = new LinkedList();
+ consumeRights.put(CONSUME_QUEUES_KEY, queues);
+ }
+
+ if (queueName != null)
+ {
+ queues.add(queueName);
+ }
+ }
+ }
+
+ /**
+ *
+ * @param permission the type of permission to check
+ *
+ * @param parameters vararg depending on what permission was passed in
+ * ACCESS: none
+ * BIND: QueueBindBody bindmethod, Exchange exchange, AMQQueue queue, AMQShortString routingKey
+ * CONSUME: AMQQueue queue
+ * CREATEQUEUE: Boolean autodelete, AMQShortString name
+ * CREATEEXCHANGE: AMQShortString exchangeName
+ * DELETE: none
+ * PUBLISH: Exchange exchange, AMQShortString routingKey
+ * PURGE: none
+ * UNBIND: none
+ */
+ public Result authorise(Permission permission, String... parameters)
+ {
+
+ switch (permission)
+ {
+ case ACCESS://No Parameters
+ return Result.ALLOWED; // The existence of this user-specific PP infers some level of access is authorised
+ case BIND: // Parameters : QueueBindMethod , exhangeName , queueName, routingKey
+ return authoriseBind(parameters);
+ case CREATEQUEUE:// Parameters : autoDelete, queueName
+ return authoriseCreateQueue(permission, parameters);
+ case CREATEEXCHANGE: //Parameters: exchangeName
+ return authoriseCreateExchange(permission, parameters);
+ case CONSUME: // Parameters : queueName, autoDelete, owner
+ return authoriseConsume(permission, parameters);
+ case PUBLISH: // Parameters : exchangeName, routingKey
+ return authorisePublish(permission, parameters);
+ /* Fall through */
+ case DELETE:
+ case PURGE:
+ case UNBIND:
+ default:
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+ else
+ {
+ //SimpleXML ACL does not implement these permissions and should abstain
+ return Result.ABSTAIN;
+ }
+ }
+
+ }
+
+ private Result authoriseConsume(Permission permission, String... parameters)
+ {
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+
+ if (parameters.length == 3)
+ {
+ AMQShortString queueName = new AMQShortString(parameters[0]);
+ Boolean autoDelete = Boolean.valueOf(parameters[1]);
+ AMQShortString owner = new AMQShortString(parameters[2]);
+ Map queuePermissions = (Map) _permissions.get(permission);
+
+ _logger.error("auth consume on " + StringUtils.join(parameters, ", "));
+
+ if (queuePermissions == null)
+ {
+ //we have a problem - we've never granted this type of permission .....
+ return Result.DENIED;
+ }
+
+ List queues = (List) queuePermissions.get(CONSUME_QUEUES_KEY);
+
+ Boolean temporaryQueues = (Boolean) queuePermissions.get(CONSUME_TEMPORARY_KEY);
+ Boolean ownQueuesOnly = (Boolean) queuePermissions.get(CONSUME_OWN_QUEUES_ONLY_KEY);
+
+
+ // If user is allowed to consume from temporary queues and this is a temp queue then allow it.
+ if (temporaryQueues && autoDelete)
+ {
+ // This will allow consumption from any temporary queue including ones not owned by this user.
+ // Of course the exclusivity will not be broken.
+ {
+
+ // if not limited to ownQueuesOnly then ok else check queue Owner.
+ return (!ownQueuesOnly || owner.equals(_user)) ? Result.ALLOWED : Result.DENIED;
+ }
+ }
+ //if this is a temporary queue and the user does not have permissions for temporary queues then deny
+ else if (!temporaryQueues && autoDelete)
+ {
+ return Result.DENIED;
+ }
+
+ // if queues are white listed then ensure it is ok
+ if (queues != null)
+ {
+ // if no queues are listed then ALL are ok othereise it must be specified.
+ if (ownQueuesOnly)
+ {
+ if (owner.equals(_user))
+ {
+ return (queues.size() == 0 || queues.contains(queueName)) ? Result.ALLOWED : Result.DENIED;
+ }
+ else
+ {
+ return Result.DENIED;
+ }
+ }
+
+ // If we are
+ return (queues.size() == 0 || queues.contains(queueName)) ? Result.ALLOWED : Result.DENIED;
+ }
+ }
+
+ // Can't authenticate without the right parameters
+ return Result.DENIED;
+ }
+
+ private Result authorisePublish(Permission permission, String... parameters)
+ {
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+
+ Map publishRights = (Map) _permissions.get(permission);
+
+ if (publishRights == null)
+ {
+ return Result.DENIED;
+ }
+
+ Map exchanges = (Map) publishRights.get(PUBLISH_EXCHANGES_KEY);
+
+ // Having no exchanges listed gives full publish rights to all exchanges
+ if (exchanges == null)
+ {
+ return Result.ALLOWED;
+ }
+ // Otherwise exchange must be listed in the white list
+
+ // If the map doesn't have the exchange then it isn't allowed
+ AMQShortString exchangeName = new AMQShortString(parameters[0]);
+ if (!exchanges.containsKey(exchangeName))
+ {
+ return Result.DENIED;
+ }
+ else
+ {
+ // Get valid routing keys
+ HashSet routingKeys = (HashSet) exchanges.get(exchangeName);
+
+ // Having no routingKeys in the map then all are allowed.
+ if (routingKeys == null)
+ {
+ return Result.ALLOWED;
+ }
+ else
+ {
+ // We have routingKeys so a match must be found to allowed binding
+ Iterator keys = routingKeys.iterator();
+
+ AMQShortString publishRKey = new AMQShortString(parameters[1]);
+
+ boolean matched = false;
+ while (keys.hasNext() && !matched)
+ {
+ AMQShortString rkey = (AMQShortString) keys.next();
+
+ if (rkey.endsWith("*"))
+ {
+ matched = publishRKey.startsWith(rkey.subSequence(0, rkey.length() - 1));
+ }
+ else
+ {
+ matched = publishRKey.equals(rkey);
+ }
+ }
+ return (matched) ? Result.ALLOWED : Result.DENIED;
+ }
+ }
+ }
+
+ private Result authoriseCreateExchange(Permission permission, String... parameters)
+ {
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+
+ Map rights = (Map) _permissions.get(permission);
+
+ AMQShortString exchangeName = new AMQShortString(parameters[0]);
+
+ // If the exchange list is doesn't exist then all is allowed else
+ // check the valid exchanges
+ if (rights == null || rights.containsKey(exchangeName))
+ {
+ return Result.ALLOWED;
+ }
+ else
+ {
+ return Result.DENIED;
+ }
+ }
+
+ private Result authoriseCreateQueue(Permission permission, String... parameters)
+ {
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+
+ Map createRights = (Map) _permissions.get(permission);
+
+ // If there are no create rights then deny request
+ if (createRights == null)
+ {
+ return Result.DENIED;
+ }
+
+ //Look up the Queue Creation Rights
+ Map create_queues = (Map) createRights.get(CREATE_QUEUES_KEY);
+
+ //Lookup the list of queues allowed to be created
+ Map create_queues_queues = (Map) create_queues.get(CREATE_QUEUE_QUEUES_KEY);
+
+
+ Boolean autoDelete = Boolean.valueOf(parameters[0]);
+ AMQShortString queueName = new AMQShortString(parameters[1]);
+
+ if (autoDelete)// we have a temporary queue
+ {
+ return ((Boolean) create_queues.get(CREATE_QUEUE_TEMPORARY_KEY)) ? Result.ALLOWED : Result.DENIED;
+ }
+ else
+ {
+ // If there is a white list then check
+ if (create_queues_queues == null || create_queues_queues.containsKey(queueName))
+ {
+ return Result.ALLOWED;
+ }
+ else
+ {
+ return Result.DENIED;
+ }
+
+ }
+ }
+
+ private Result authoriseBind(String... parameters)
+ {
+ if(_fullVHostAccess)
+ {
+ //user has been granted full access to the vhost
+ return Result.ALLOWED;
+ }
+
+ AMQShortString exchangeName = new AMQShortString(parameters[1]);
+ AMQShortString bind_queueName = new AMQShortString(parameters[2]);
+ AMQShortString routingKey = new AMQShortString(parameters[3]);
+
+ //Get all Create Rights for this user
+ Map bindCreateRights = (Map) _permissions.get(Permission.CREATEQUEUE);
+
+ //Lookup the list of queues
+ Map bind_create_queues_queues = (Map) bindCreateRights.get(CREATE_QUEUE_QUEUES_KEY);
+
+ // Check and see if we have a queue white list to check
+ if (bind_create_queues_queues != null)
+ {
+ //There a white list for queues
+ Map exchangeDetails = (Map) bind_create_queues_queues.get(bind_queueName);
+
+ if (exchangeDetails == null) //Then all queue can be bound to all exchanges.
+ {
+ return Result.ALLOWED;
+ }
+
+ // Check to see if we have a white list of routingkeys to check
+ Map rkeys = (Map) exchangeDetails.get(exchangeName);
+
+ // if keys is null then any rkey is allowed on this exchange
+ if (rkeys == null)
+ {
+ // There is no routingkey white list
+ return Result.ALLOWED;
+ }
+ else
+ {
+ // We have routingKeys so a match must be found to allowed binding
+ Iterator keys = rkeys.keySet().iterator();
+
+ boolean matched = false;
+ while (keys.hasNext() && !matched)
+ {
+ AMQShortString rkey = (AMQShortString) keys.next();
+ if (rkey.endsWith("*"))
+ {
+ matched = routingKey.startsWith(rkey.subSequence(0, rkey.length() - 1).toString());
+ }
+ else
+ {
+ matched = routingKey.equals(rkey);
+ }
+ }
+
+
+ return (matched) ? Result.ALLOWED : Result.DENIED;
+ }
+
+
+ }
+ else
+ {
+ //no white list so all allowed.
+ return Result.ALLOWED;
+ }
+ }
+}
diff --git a/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java
new file mode 100644
index 0000000000..ab43653122
--- /dev/null
+++ b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXML.java
@@ -0,0 +1,427 @@
+/*
+ * 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 org.apache.qpid.server.security.access.plugins;
+
+import static org.apache.qpid.server.security.access.ObjectProperties.Property.*;
+
+import java.security.Principal;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.security.AbstractPlugin;
+import org.apache.qpid.server.security.Result;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.SecurityPluginFactory;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.config.PrincipalPermissions;
+import org.apache.qpid.server.security.access.config.PrincipalPermissions.Permission;
+
+/**
+ * This uses the default
+ */
+public class SimpleXML extends AbstractPlugin
+{
+ public static final Logger _logger = Logger.getLogger(SimpleXML.class);
+
+ private Map<String, PrincipalPermissions> _users;
+
+ public static final SecurityPluginFactory<SimpleXML> FACTORY = new SecurityPluginFactory<SimpleXML>()
+ {
+ public SimpleXML newInstance(ConfigurationPlugin config) throws ConfigurationException
+ {
+ SimpleXMLConfiguration configuration = config.getConfiguration(SimpleXMLConfiguration.class.getName());
+
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ return null;
+ }
+
+ SimpleXML plugin = new SimpleXML();
+ plugin.configure(configuration);
+ return plugin;
+ }
+
+ public String getPluginName()
+ {
+ return SimpleXML.class.getName();
+ }
+
+ public Class<SimpleXML> getPluginClass()
+ {
+ return SimpleXML.class;
+ }
+ };
+
+ public void configure(ConfigurationPlugin config)
+ {
+ super.configure(config);
+
+ SimpleXMLConfiguration configuration = (SimpleXMLConfiguration) _config;
+
+ _users = new ConcurrentHashMap<String, PrincipalPermissions>();
+
+ processConfig(configuration.getConfiguration());
+ }
+
+ private void processConfig(Configuration config)
+ {
+ processPublish(config);
+ processConsume(config);
+ processCreate(config);
+ processAccess(config);
+ }
+
+ /**
+ * @param config XML Configuration
+ */
+ private void processAccess(Configuration config)
+ {
+ Configuration accessConfig = config.subset("access");
+
+ if (accessConfig.isEmpty())
+ {
+ //there is no access configuration to process
+ return;
+ }
+
+ // Process users that have full access permission
+ String[] users = accessConfig.getStringArray("users.user");
+
+ for (String user : users)
+ {
+ grant(Permission.ACCESS, user);
+ }
+ }
+
+ /**
+ * Publish format takes Exchange + Routing Key Pairs
+ *
+ * @param config XML Configuration
+ */
+ private void processPublish(Configuration config)
+ {
+ Configuration publishConfig = config.subset("publish");
+
+ // Process users that have full publish permission
+ String[] users = publishConfig.getStringArray("users.user");
+
+ for (String user : users)
+ {
+ grant(Permission.PUBLISH, user);
+ }
+
+ // Process exchange limited users
+ int exchangeCount = 0;
+ Configuration exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+
+ while (!exchangeConfig.isEmpty())
+ {
+ // Get Exchange Name
+ AMQShortString exchangeName = new AMQShortString(exchangeConfig.getString("name"));
+
+ // Get Routing Keys
+ int keyCount = 0;
+ Configuration routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")");
+
+ while (!routingkeyConfig.isEmpty())
+ {
+ // Get RoutingKey Value
+ AMQShortString routingKeyValue = new AMQShortString(routingkeyConfig.getString("value"));
+
+ // Apply Exchange + RoutingKey permissions to Users
+ users = routingkeyConfig.getStringArray("users.user");
+ for (String user : users)
+ {
+ grant(Permission.PUBLISH, user, exchangeName, routingKeyValue);
+ }
+
+ // Apply permissions to Groups
+
+ // Check for more configs
+ keyCount++;
+ routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")");
+ }
+
+ // Apply Exchange wide permissions to Users
+ users = exchangeConfig.getStringArray("exchange(" + exchangeCount + ").users.user");
+
+ for (String user : users)
+ {
+ grant(Permission.PUBLISH, user, exchangeName);
+ }
+
+ // Apply permissions to Groups
+ exchangeCount++;
+ exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+ }
+ }
+
+ private void grant(Permission permission, String user, Object... parameters)
+ {
+ PrincipalPermissions permissions = _users.get(user);
+
+ if (permissions == null)
+ {
+ permissions = new PrincipalPermissions(user);
+ }
+
+ _users.put(user, permissions);
+ permissions.grant(permission, parameters);
+ }
+
+ /**
+ * @param config XML Configuration
+ */
+ private void processConsume(Configuration config)
+ {
+ boolean temporary = false;
+ Configuration tempConfig = null;
+ Configuration consumeConfig = config.subset("consume");
+
+ tempConfig = consumeConfig.subset("queues.temporary(0)");
+ if (tempConfig != null)
+ {
+ temporary = true;
+ }
+
+ //Permission all users who have rights to temp queues and topics
+ if (tempConfig != null && !tempConfig.isEmpty())
+ {
+ String[] tempUsers = tempConfig.getStringArray("users.user");
+ for (String user : tempUsers)
+ {
+ grant(Permission.CONSUME, user, temporary);
+ }
+ }
+
+ // Process queue limited users
+ int queueCount = 0;
+ Configuration queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")");
+
+ while (!queueConfig.isEmpty())
+ {
+ // Get queue Name
+ AMQShortString queueName = new AMQShortString(queueConfig.getString("name"));
+ // if there is no name then there may be a temporary element
+
+ boolean ownQueues = queueConfig.containsKey("own_queues");
+
+ // Process permissions for this queue
+ String[] users = queueConfig.getStringArray("users.user");
+ for (String user : users)
+ {
+ grant(Permission.CONSUME, user, queueName, ownQueues);
+ }
+
+ // See if we have another config
+ queueCount++;
+ queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")");
+ }
+
+ // Process users that have full consume permission
+ String[] users = consumeConfig.getStringArray("users.user");
+
+ for (String user : users)
+ {
+ //NOTE: this call does not appear to do anything inside the grant section for consume
+ grant(Permission.CONSUME, user);
+ }
+ }
+
+ /**
+ * @param config XML Configuration
+ */
+ private void processCreate(Configuration config)
+ {
+ boolean temporary = false;
+ Configuration tempConfig = null;
+
+ Configuration createConfig = config.subset("create");
+
+ tempConfig = createConfig.subset("queues.temporary(0)");
+ if (tempConfig != null)
+ {
+ temporary = true;
+ }
+
+ //Permission all users who have rights to temp queues and topics
+ if (tempConfig != null && !tempConfig.isEmpty())
+ {
+ String[] tempUsers = tempConfig.getStringArray("users.user");
+ for (String user : tempUsers)
+ {
+ grant(Permission.CREATEQUEUE, user, temporary);
+ }
+ }
+ // Process create permissions for queue creation
+ int queueCount = 0;
+ Configuration queueConfig = createConfig.subset("queues.queue(" + queueCount + ")");
+
+ while (!queueConfig.isEmpty())
+ {
+ // Get queue Name
+ AMQShortString queueName = new AMQShortString(queueConfig.getString("name"));
+
+ int exchangeCount = 0;
+ Configuration exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+
+ while (!exchangeConfig.isEmpty())
+ {
+
+ AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name"));
+ AMQShortString routingKey = new AMQShortString(exchangeConfig.getString("routing_key"));
+
+ // Process permissions for this queue
+ String[] users = exchangeConfig.getStringArray("users.user");
+ for (String user : users)
+ {
+ //This is broken as the user name is not stored
+ grant(Permission.CREATEEXCHANGE, user, exchange);
+
+ //This call could be cleaned up as temporary is now being set earlier (above)
+ grant(Permission.CREATEQUEUE, user, temporary, (queueName.equals("") ? null : queueName), (exchange
+ .equals("") ? null : exchange), (routingKey.equals("") ? null : routingKey));
+ }
+
+ // See if we have another config
+ exchangeCount++;
+ exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+ }
+
+ // Process users that are not bound to an exchange
+ String[] users = queueConfig.getStringArray("users.user");
+
+ for (String user : users)
+ {
+ grant(Permission.CREATEQUEUE, user, temporary, queueName);
+ }
+
+ // See if we have another config
+ queueCount++;
+ queueConfig = createConfig.subset("queues.queue(" + queueCount + ")");
+ }
+
+ // Process create permissions for exchange creation
+ int exchangeCount = 0;
+ Configuration exchangeConfig = createConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+
+ while (!exchangeConfig.isEmpty())
+ {
+ AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name"));
+ AMQShortString clazz = new AMQShortString(exchangeConfig.getString("class"));
+
+ // Process permissions for this queue
+ String[] users = exchangeConfig.getStringArray("users.user");
+ for (String user : users)
+ {
+ //And this is broken too
+ grant(Permission.CREATEEXCHANGE, user, exchange, clazz);
+ }
+
+ // See if we have another config
+ exchangeCount++;
+ exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
+ }
+
+ // Process users that have full create permission
+ String[] users = createConfig.getStringArray("users.user");
+
+ for (String user : users)
+ {
+ grant(Permission.CREATEEXCHANGE, user);
+ grant(Permission.CREATEQUEUE, user);
+ }
+ }
+
+ public Result access(ObjectType objectType, Object instance)
+ {
+ Principal principal = SecurityManager.getThreadPrincipal();
+ if (principal == null)
+ {
+ return getDefault(); // Default if there is no user associated with the thread
+ }
+ PrincipalPermissions principalPermissions = _users.get(principal.getName());
+ if (principalPermissions == null)
+ {
+ return Result.DENIED;
+ }
+
+ // Authorise object access
+ if (objectType == ObjectType.VIRTUALHOST)
+ {
+ return principalPermissions.authorise(Permission.ACCESS);
+ }
+
+ // Default
+ return getDefault();
+ }
+
+ public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
+ {
+ Principal principal = SecurityManager.getThreadPrincipal();
+ if (principal == null)
+ {
+ return getDefault(); // Default if there is no user associated with the thread
+ }
+ PrincipalPermissions principalPermissions = _users.get(principal.getName());
+ if (principalPermissions == null)
+ {
+ return Result.DENIED;
+ }
+
+ // Authorise operation
+ switch (operation)
+ {
+ case CONSUME:
+ return principalPermissions.authorise(Permission.CONSUME, properties.get(NAME), properties.get(AUTO_DELETE), properties.get(OWNER));
+ case PUBLISH:
+ return principalPermissions.authorise(Permission.PUBLISH, properties.get(NAME), properties.get(ROUTING_KEY));
+ case CREATE:
+ if (objectType == ObjectType.EXCHANGE)
+ {
+ return principalPermissions.authorise(Permission.CREATEEXCHANGE, properties.get(NAME));
+ }
+ else if (objectType == ObjectType.QUEUE)
+ {
+ return principalPermissions.authorise(Permission.CREATEQUEUE, properties.get(AUTO_DELETE), properties.get(NAME));
+ }
+ case ACCESS:
+ return principalPermissions.authorise(Permission.ACCESS);
+ case BIND:
+ return principalPermissions.authorise(Permission.BIND, null, properties.get(NAME), properties.get(QUEUE_NAME), properties.get(ROUTING_KEY));
+ case UNBIND:
+ return principalPermissions.authorise(Permission.UNBIND);
+ case DELETE:
+ return principalPermissions.authorise(Permission.DELETE);
+ case PURGE:
+ return principalPermissions.authorise(Permission.PURGE);
+ }
+
+ // Default
+ return getDefault();
+ }
+}
diff --git a/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java
new file mode 100644
index 0000000000..c09a9da0d8
--- /dev/null
+++ b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLActivator.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security.access.plugins;
+
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.security.SecurityPluginActivator;
+import org.apache.qpid.server.security.SecurityPluginFactory;
+import org.osgi.framework.BundleActivator;
+
+/**
+ * The OSGi {@link BundleActivator} for {@link SimpleXML}.
+ */
+public class SimpleXMLActivator extends SecurityPluginActivator
+{
+ public SecurityPluginFactory getFactory()
+ {
+ return SimpleXML.FACTORY;
+ }
+
+ public ConfigurationPluginFactory getConfigurationFactory()
+ {
+ return SimpleXMLConfiguration.FACTORY;
+ }
+}
diff --git a/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java
new file mode 100644
index 0000000000..e95c21b590
--- /dev/null
+++ b/java/broker-plugins/simple-xml/src/main/java/org/apache/qpid/server/security/access/plugins/SimpleXMLConfiguration.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security.access.plugins;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+
+public class SimpleXMLConfiguration extends ConfigurationPlugin
+{
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ {
+ public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
+ {
+ ConfigurationPlugin instance = new SimpleXMLConfiguration();
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security.access_control_list", "virtualhosts.virtualhost.security.access_control_list");
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[] { "" };
+ }
+
+ public Configuration getConfiguration()
+ {
+ return _configuration;
+ }
+}
diff --git a/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java b/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java
new file mode 100644
index 0000000000..65ab12a095
--- /dev/null
+++ b/java/broker-plugins/simple-xml/src/test/java/org/apache/qpid/server/security/access/PrincipalPermissionsTest.java
@@ -0,0 +1,209 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security.access;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.security.Result;
+import org.apache.qpid.server.security.access.config.PrincipalPermissions;
+import org.apache.qpid.server.security.access.config.PrincipalPermissions.Permission;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class PrincipalPermissionsTest extends QpidTestCase
+{
+ private String _user = "user";
+ private PrincipalPermissions _perms;
+
+ // Common things that are passed to frame constructors
+ private AMQShortString _queueName = new AMQShortString(this.getClass().getName() + "queue");
+ private AMQShortString _tempQueueName = new AMQShortString(this.getClass().getName() + "tempqueue");
+ private AMQShortString _exchangeName = new AMQShortString("amq.direct");
+ private AMQShortString _routingKey = new AMQShortString(this.getClass().getName() + "route");
+ private boolean _autoDelete = false;
+ private AMQShortString _exchangeType = new AMQShortString("direct");
+ private Boolean _temporary = false;
+ private Boolean _ownQueue = false;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ _perms = new PrincipalPermissions(_user);
+ }
+
+
+ public void testPrincipalPermissions()
+ {
+ assertNotNull(_perms);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.ACCESS, (String[]) null));
+ }
+
+ // FIXME: test has been disabled since the permissions assume that the user has tried to create
+ // the queue first. QPID-1597
+ public void disableTestBind() throws Exception
+ {
+ String[] args = new String[]{null, _exchangeName.asString(), _queueName.asString(), _routingKey.asString()};
+
+ assertEquals(Result.DENIED, _perms.authorise(Permission.BIND, args));
+ _perms.grant(Permission.BIND, (Object[]) null);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.BIND, args));
+ }
+
+ public void testQueueCreate()
+ {
+ Object[] grantArgs = new Object[]{_temporary , _queueName, _exchangeName, _routingKey};
+ String[] authArgs = new String[]{Boolean.toString(_autoDelete), _queueName.asString()};
+
+ assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgs));
+ _perms.grant(Permission.CREATEQUEUE, grantArgs);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs));
+ }
+
+ public void testQueueCreateWithNullRoutingKey()
+ {
+ Object[] grantArgs = new Object[]{_temporary , _queueName, _exchangeName, null};
+ String[] authArgs = new String[]{Boolean.toString(_autoDelete), _queueName.asString()};
+
+ assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgs));
+ _perms.grant(Permission.CREATEQUEUE, grantArgs);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgs));
+ }
+
+ // FIXME disabled, this fails due to grant putting the grant into the wrong map QPID-1598
+ public void disableTestExchangeCreate()
+ {
+ String[] authArgs = new String[]{_exchangeName.asString()};
+ Object[] grantArgs = new Object[]{_exchangeName, _exchangeType};
+
+ assertEquals(Result.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs));
+ _perms.grant(Permission.CREATEEXCHANGE, grantArgs);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgs));
+ }
+
+ public void testConsume()
+ {
+ String[] authArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user};
+ Object[] grantArgs = new Object[]{_queueName, _ownQueue};
+
+ // FIXME: This throws a null pointer exception QPID-1599
+ // assertFalse(_perms.authorise(Permission.CONSUME, authArgs));
+ _perms.grant(Permission.CONSUME, grantArgs);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authArgs));
+ }
+
+ public void testPublish() throws AMQException
+ {
+ String[] authArgs = new String[]{_exchangeName.asString(), _routingKey.asString()};
+ Object[] grantArgs = new Object[]{_exchangeName, _routingKey};
+
+ assertEquals(Result.DENIED, _perms.authorise(Permission.PUBLISH, authArgs));
+ _perms.grant(Permission.PUBLISH, grantArgs);
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgs));
+ }
+
+ public void testVhostAccess()
+ {
+ //Tests that granting a user Virtualhost level access allows all authorisation requests
+ //where previously they would be denied
+
+ //QPID-2133 createExchange rights currently allow all exchange creation unless rights for creating some
+ //specific exchanges are granted. Grant a specific exchange creation to cause all others to be denied.
+ Object[] createArgsCreateExchange = new Object[]{new AMQShortString("madeup"), _exchangeType};
+ String[] authArgsCreateExchange = new String[]{_exchangeName.asString()};
+ assertEquals("Exchange creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange));
+ _perms.grant(Permission.CREATEEXCHANGE, createArgsCreateExchange);
+
+ String[] authArgsPublish = new String[]{_exchangeName.asString(), _routingKey.asString()};
+ String[] authArgsConsume = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user};
+ String[] authArgsCreateQueue = new String[]{Boolean.toString(_autoDelete), _queueName.asString()};
+// QueueBindBodyImpl bind = new QueueBindBodyImpl(_ticket, _queueName, _exchangeName, _routingKey, _nowait, _arguments);
+ String[] authArgsBind = new String[]{ null, _exchangeName.asString(), _queueName.asString(), _routingKey.asString()};
+
+ assertEquals("Exchange creation was not denied", Result.DENIED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange));
+ assertEquals("Publish was not denied", Result.DENIED, _perms.authorise(Permission.PUBLISH, authArgsPublish));
+ assertEquals("Consume creation was not denied", Result.DENIED, _perms.authorise(Permission.CONSUME, authArgsConsume));
+ assertEquals("Queue creation was not denied", Result.DENIED, _perms.authorise(Permission.CREATEQUEUE, authArgsCreateQueue));
+ //BIND pre-grant authorise check disabled due to QPID-1597
+ //assertEquals("Binding creation was not denied", Result.DENIED, _perms.authorise(Permission.BIND, authArgsBind));
+
+ _perms.grant(Permission.ACCESS);
+
+ assertEquals("Exchange creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEEXCHANGE, authArgsCreateExchange));
+ assertEquals("Publish was not allowed", Result.ALLOWED, _perms.authorise(Permission.PUBLISH, authArgsPublish));
+ assertEquals("Consume creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CONSUME, authArgsConsume));
+ assertEquals("Queue creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.CREATEQUEUE, authArgsCreateQueue));
+ assertEquals("Binding creation was not allowed", Result.ALLOWED, _perms.authorise(Permission.BIND, authArgsBind));
+ }
+
+ /**
+ * If the consume permission for temporary queues is for an unnamed queue then is should
+ * be global for any temporary queue but not for any non-temporary queue
+ */
+ public void testTemporaryUnnamedQueueConsume()
+ {
+ String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user};
+ String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user};
+ Object[] grantArgs = new Object[]{true};
+
+ _perms.grant(Permission.CONSUME, grantArgs);
+
+ //Next line shows up bug - non temp queue should be denied
+ assertEquals(Result.DENIED, _perms.authorise(Permission.CONSUME, authNonTempQArgs));
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs));
+ }
+
+ /**
+ * Test that temporary queue permissions before queue perms in the ACL config work correctly
+ */
+ public void testTemporaryQueueFirstConsume()
+ {
+ String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user};
+ String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user};
+ Object[] grantArgs = new Object[]{true};
+ Object[] grantNonTempQArgs = new Object[]{_queueName, _ownQueue};
+
+ //should not matter if the temporary permission is processed first or last
+ _perms.grant(Permission.CONSUME, grantNonTempQArgs);
+ _perms.grant(Permission.CONSUME, grantArgs);
+
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authNonTempQArgs));
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs));
+ }
+
+ /**
+ * Test that temporary queue permissions after queue perms in the ACL config work correctly
+ */
+ public void testTemporaryQueueLastConsume()
+ {
+ String[] authNonTempQArgs = new String[]{_queueName.asString(), Boolean.toString(_autoDelete), _user};
+ String[] authTempQArgs = new String[]{_tempQueueName.asString(), Boolean.TRUE.toString(), _user};
+ Object[] grantArgs = new Object[]{true};
+ Object[] grantNonTempQArgs = new Object[]{_queueName, _ownQueue};
+
+ //should not matter if the temporary permission is processed first or last
+ _perms.grant(Permission.CONSUME, grantArgs);
+ _perms.grant(Permission.CONSUME, grantNonTempQArgs);
+
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authNonTempQArgs));
+ assertEquals(Result.ALLOWED, _perms.authorise(Permission.CONSUME, authTempQArgs));
+ }
+}
diff --git a/java/broker/bin/qpid-server b/java/broker/bin/qpid-server
index 382004c9f5..90b11da202 100755
--- a/java/broker/bin/qpid-server
+++ b/java/broker/bin/qpid-server
@@ -33,8 +33,8 @@ if [ -z "$QPID_PNAME" ]; then
export QPID_PNAME=" -DPNAME=QPBRKR"
fi
-# Set classpath to include the qpid-all manifest jar, and any jars supplied in lib/opt
-QPID_LIBS="$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/opt/*"
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-all.jar
# Set other variables used by the qpid-run script before calling
export JAVA=java \
@@ -51,6 +51,6 @@ QPID_OPTS="$QPID_OPTS -Damqj.read_write_pool_size=32 -DQPID_LOG_APPEND=$QPID_LOG
if [ -z "$QPID_PID_FILENAME" ]; then
export QPID_PID_FILENAME="qpid-server.pid"
fi
-echo $$ > "${QPID_WORK}/${QPID_PID_FILENAME}"
+echo $$ > ${QPID_WORK}/${QPID_PID_FILENAME}
-. "${QPID_HOME}/bin/qpid-run" org.apache.qpid.server.Main "$@"
+. ${QPID_HOME}/bin/qpid-run org.apache.qpid.server.Main "$@"
diff --git a/java/broker/bin/qpid-server.bat b/java/broker/bin/qpid-server.bat
index af543decb3..c81f5fc3e7 100644
--- a/java/broker/bin/qpid-server.bat
+++ b/java/broker/bin/qpid-server.bat
@@ -108,13 +108,13 @@ goto beforeRunShift
:runJdpa
REM USAGE: adds debugging options to the java command, use
-REM USAGE: JPDA_TRANSPORT and JPDA_ADDRESS to customize the debugging
+REM USAGE: JDPA_TRANSPORT and JPDA_ADDRESS to customize the debugging
REM USAGE: behavior and use JPDA_OPTS to override it entirely
-if not "%JPDA_OPTS%" == "" goto beforeRunShift
-if "%JPDA_TRANSPORT%" == "" set JPDA_TRANSPORT=dt_socket
+if "%JPDA_OPTS%" == "" goto beforeRunShift
+if "%JPDA_TRANSPORT%" == "" set JPDA_TRANSPORT=-dt_socket
if "%JPDA_ADDRESS%" == "" set JPDA_ADDRESS=8000
-set JPDA_OPTS=-Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n
-REM set QPID_OPTS="%QPID_OPTS% %JPDA_OPTS%"
+set JPDA_OPTS="-Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n"
+set QPID_OPTS="%QPID_OPTS% %JPDA_OPTS%"
goto beforeRunShift
:runExternalClasspath
@@ -192,7 +192,7 @@ rem QPID_OPTS intended to hold any -D props for use
rem user must enclose any value for QPID_OPTS in double quotes
:runCommand
set MODULE_JARS=%QPID_MODULE_JARS%
-set COMMAND="%JAVA_HOME%\bin\java" %JAVA_VM% %JAVA_MEM% %JAVA_GC% %QPID_OPTS% %JPDA_OPTS% %SYSTEM_PROPS% -cp "%CLASSPATH%;%MODULE_JARS%" org.apache.qpid.server.Main %QPID_ARGS%
+set COMMAND="%JAVA_HOME%\bin\java" %JAVA_VM% %JAVA_MEM% %JAVA_GC% %QPID_OPTS% %SYSTEM_PROPS% -cp "%CLASSPATH%;%MODULE_JARS%" org.apache.qpid.server.Main %QPID_ARGS%
if "%debug%" == "true" echo %CLASSPATH%;%LAUNCH_JAR%;%MODULE_JARS%
if "%debug%" == "true" echo %COMMAND%
diff --git a/java/broker/build.xml b/java/broker/build.xml
index e733474ef0..edd71effaa 100644
--- a/java/broker/build.xml
+++ b/java/broker/build.xml
@@ -76,10 +76,6 @@
<copy todir="${module.release}/lib/plugins" failonerror="true">
<fileset dir="${build.lib}/plugins"/>
</copy>
- <!--copy optional bdbstore module if it exists -->
- <copy todir="${module.release}/lib/" failonerror="false">
- <fileset file="${build.lib}/${project.name}-bdbstore-${project.version}.jar"/>
- </copy>
</target>
<target name="release-bin" depends="release-bin-tasks"/>
diff --git a/java/broker/etc/access b/java/broker/etc/access
new file mode 100644
index 0000000000..58b7443fa9
--- /dev/null
+++ b/java/broker/etc/access
@@ -0,0 +1,19 @@
+#
+# 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.
+
+guest:localhost(rw),test(rw) \ No newline at end of file
diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml
index d18e1392e6..14b9456067 100644
--- a/java/broker/etc/config.xml
+++ b/java/broker/etc/config.xml
@@ -30,27 +30,28 @@
<connector>
<!-- To enable SSL edit the keystorePath and keystorePassword
and set enabled to true.
- To disable Non-SSL port set sslOnly to true -->
+ To disasble Non-SSL port set sslOnly to true -->
<ssl>
<enabled>false</enabled>
- <port>5671</port>
<sslOnly>false</sslOnly>
- <keyStorePath>/path/to/keystore.ks</keyStorePath>
- <keyStorePassword>keystorepass</keyStorePassword>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
</ssl>
+ <qpidnio>false</qpidnio>
+ <protectio>
+ <enabled>false</enabled>
+ <readBufferLimitSize>262144</readBufferLimitSize>
+ <writeBufferLimitSize>262144</writeBufferLimitSize>
+ </protectio>
+ <transport>nio</transport>
<port>5672</port>
- <socketReceiveBuffer>262144</socketReceiveBuffer>
- <socketSendBuffer>262144</socketSendBuffer>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
</connector>
<management>
<enabled>true</enabled>
- <jmxport>
- <registryServer>8999</registryServer>
- <!--
- If unspecified, connectorServer defaults to 100 + registryServer port.
- <connectorServer>9099</connectionServer>
- -->
- </jmxport>
+ <jmxport>8999</jmxport>
<ssl>
<enabled>false</enabled>
<!-- Update below path to your keystore location, or run the bin/create-example-ssl-stores(.sh|.bat)
@@ -68,8 +69,10 @@
</advanced>
<security>
- <pd-auth-manager>
+ <principal-databases>
+ <!-- Example use of Base64 encoded MD5 hashes for authentication via CRAM-MD5-Hashed -->
<principal-database>
+ <name>passwordfile</name>
<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
<attributes>
<attribute>
@@ -78,11 +81,16 @@
</attribute>
</attributes>
</principal-database>
- </pd-auth-manager>
+ </principal-databases>
<allow-all />
<msg-auth>false</msg-auth>
+
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
</security>
<virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
diff --git a/java/broker/etc/jmxremote.access b/java/broker/etc/jmxremote.access
new file mode 100644
index 0000000000..1a51a6991b
--- /dev/null
+++ b/java/broker/etc/jmxremote.access
@@ -0,0 +1,23 @@
+#
+# 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.
+
+#Generated by JMX Console : Last edited by user:admin
+#Tue Jun 12 16:46:39 BST 2007
+admin=admin
+guest=readonly
+user=readwrite
diff --git a/java/broker/etc/passwdVhost b/java/broker/etc/passwdVhost
new file mode 100644
index 0000000000..48ce8299b6
--- /dev/null
+++ b/java/broker/etc/passwdVhost
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+guest:guest:localhost,test
diff --git a/java/broker/etc/qpid-server.conf.jpp b/java/broker/etc/qpid-server.conf.jpp
index 0378c82fd9..3ed2431ef3 100644
--- a/java/broker/etc/qpid-server.conf.jpp
+++ b/java/broker/etc/qpid-server.conf.jpp
@@ -17,7 +17,8 @@
# under the License.
#
-QPID_LIBS=$(build-classpath commons-beanutils \
+QPID_LIBS=$(build-classpath backport-util-concurrent \
+ commons-beanutils \
commons-beanutils-core \
commons-cli \
commons-codec \
diff --git a/java/broker/etc/virtualhosts.xml b/java/broker/etc/virtualhosts.xml
index 33a48a1349..5860bfe2cb 100644
--- a/java/broker/etc/virtualhosts.xml
+++ b/java/broker/etc/virtualhosts.xml
@@ -31,7 +31,7 @@
<housekeeping>
<threadCount>2</threadCount>
- <checkPeriod>20000</checkPeriod>
+ <expiredMessageCheckPeriod>20000</expiredMessageCheckPeriod>
</housekeeping>
<exchanges>
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
index 6abef6fd6b..c0afae0773 100644
--- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
+++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java
@@ -694,8 +694,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
public BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommand queueMoveMessages(final BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommandFactory factory,
final String srcQueue,
final String destQueue,
- final Long qty,
- final Map filter) // TODO: move based on group identifier
+ final Long qty)
{
// TODO
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
@@ -713,46 +712,6 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
}
- public BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommand getTimestampConfig(final BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommandFactory factory)
- {
- // TODO: timestamp support
- return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
- }
-
- public BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommand setTimestampConfig(final BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommandFactory factory,
- final java.lang.Boolean receive)
- {
- // TODO: timestamp support
- return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
- }
-
- public BrokerSchema.BrokerClass.CreateMethodResponseCommand create(final BrokerSchema.BrokerClass.CreateMethodResponseCommandFactory factory,
- final String type,
- final String name,
- final Map properties,
- final java.lang.Boolean lenient)
- {
- //TODO:
- return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
- }
-
- public BrokerSchema.BrokerClass.DeleteMethodResponseCommand delete(final BrokerSchema.BrokerClass.DeleteMethodResponseCommandFactory factory,
- final String type,
- final String name,
- final Map options)
- {
- //TODO:
- return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
- }
-
- public BrokerSchema.BrokerClass.QueryMethodResponseCommand query(final BrokerSchema.BrokerClass.QueryMethodResponseCommandFactory factory,
- final String type,
- final String name)
- {
- //TODO:
- return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
- }
-
public UUID getId()
{
return _obj.getId();
@@ -1113,19 +1072,8 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return 0l;
}
- public Boolean getFlowStopped()
- {
- return Boolean.FALSE;
- }
-
- public Long getFlowStoppedCount()
- {
- return 0L;
- }
-
public BrokerSchema.QueueClass.PurgeMethodResponseCommand purge(final BrokerSchema.QueueClass.PurgeMethodResponseCommandFactory factory,
- final Long request,
- final Map filter) // TODO: support for purge-by-group-identifier
+ final Long request)
{
try
{
@@ -1141,8 +1089,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
public BrokerSchema.QueueClass.RerouteMethodResponseCommand reroute(final BrokerSchema.QueueClass.RerouteMethodResponseCommandFactory factory,
final Long request,
final Boolean useAltExchange,
- final String exchange,
- final Map filter) // TODO: support for re-route-by-group-identifier
+ final String exchange)
{
//TODO
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
@@ -1335,23 +1282,6 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
{
return _obj.isShadow();
}
-
- public Boolean getUserProxyAuth()
- {
- // TODO
- return false;
- }
-
- public String getSaslMechanism()
- {
- // TODO
- return null;
- }
- public Integer getSaslSsf()
- {
- // TODO
- return 0;
- }
}
private class SessionDelegate implements BrokerSchema.SessionDelegate
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
index d1ea5dba69..a612f280d6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -327,74 +327,4 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
return getObjectNameForSingleInstanceMBean();
}
-
- public void resetStatistics() throws Exception
- {
- getVirtualHost().resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return getVirtualHost().getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return getVirtualHost().getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return getVirtualHost().getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return getVirtualHost().getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return getVirtualHost().getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return getVirtualHost().getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return getVirtualHost().getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return getVirtualHost().getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return getVirtualHost().getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return getVirtualHost().getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return getVirtualHost().isStatisticsEnabled();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index 34bc57a826..4f86c82578 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -22,7 +22,6 @@ package org.apache.qpid.server;
import org.apache.log4j.Logger;
-import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQMethodBody;
@@ -50,7 +49,6 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.AMQPChannelActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ChannelMessages;
-import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
@@ -76,7 +74,6 @@ import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.TransportException;
import java.util.ArrayList;
import java.util.Collection;
@@ -139,12 +136,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
private final AtomicBoolean _suspended = new AtomicBoolean(false);
private ServerTransaction _transaction;
-
+
private final AtomicLong _txnStarts = new AtomicLong(0);
private final AtomicLong _txnCommits = new AtomicLong(0);
private final AtomicLong _txnRejects = new AtomicLong(0);
private final AtomicLong _txnCount = new AtomicLong(0);
- private final AtomicLong _txnUpdateTime = new AtomicLong(0);
private final AMQProtocolSession _session;
private AtomicBoolean _closing = new AtomicBoolean(false);
@@ -203,12 +199,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
// theory
return !(_transaction instanceof AutoCommitTransaction);
}
-
- public boolean inTransaction()
- {
- return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0;
- }
-
+
private void incrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -218,7 +209,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_txnCount.compareAndSet(0,1);
}
}
-
+
private void decrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -304,6 +295,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
});
deliverCurrentMessageIfComplete();
+
}
}
@@ -316,6 +308,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
try
{
_currentMessage.getStoredMessage().flushToStore();
+
final ArrayList<? extends BaseQueue> destinationQueues = _currentMessage.getDestinationQueues();
if(!checkMessageUserId(_currentMessage.getContentHeader()))
@@ -324,7 +317,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
else
{
- if(destinationQueues == null || destinationQueues.isEmpty())
+ if(destinationQueues == null || _currentMessage.getDestinationQueues().isEmpty())
{
if (_currentMessage.isMandatory() || _currentMessage.isImmediate())
{
@@ -332,7 +325,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
else
{
- _actor.message(ExchangeMessages.DISCARDMSG(_currentMessage.getExchange().asString(), _currentMessage.getRoutingKey()));
+ _logger.warn("MESSAGE DISCARDED: No routes for message - " + createAMQMessage(_currentMessage));
}
}
@@ -340,15 +333,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
_transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues, isTransactional()));
incrementOutstandingTxnsIfNecessary();
- updateTransactionalActivity();
}
}
}
finally
{
- long bodySize = _currentMessage.getSize();
- long timestamp = ((BasicContentHeaderProperties) _currentMessage.getContentHeader().getProperties()).getTimestamp();
- _session.registerMessageReceived(bodySize, timestamp);
_currentMessage = null;
}
}
@@ -386,13 +375,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_currentMessage = null;
throw e;
}
- catch (RuntimeException e)
- {
- // we want to make sure we don't keep a reference to the message in the
- // event of an error
- _currentMessage = null;
- throw e;
- }
}
protected void routeCurrentMessage() throws AMQException
@@ -443,7 +425,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
throw new AMQException("Consumer already exists with same tag: " + tag);
}
-
+
Subscription subscription =
SubscriptionFactoryImpl.INSTANCE.createSubscription(_channelId, _session, tag, acks, filters, noLocal, _creditManager);
@@ -464,11 +446,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_tag2SubscriptionMap.remove(tag);
throw e;
}
- catch (RuntimeException e)
- {
- _tag2SubscriptionMap.remove(tag);
- throw e;
- }
return tag;
}
@@ -526,11 +503,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
catch (AMQException e)
{
- _logger.error("Caught AMQException whilst attempting to requeue:" + e);
- }
- catch (TransportException e)
- {
- _logger.error("Caught TransportException whilst attempting to requeue:" + e);
+ _logger.error("Caught AMQException whilst attempting to reque:" + e);
}
getConfigStore().removeConfiguredObject(this);
@@ -821,7 +794,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
Collection<QueueEntry> ackedMessages = getAckedMessages(deliveryTag, multiple);
_transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages));
- updateTransactionalActivity();
}
private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple)
@@ -961,7 +933,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
finally
{
_rollingBack = false;
-
+
_txnRejects.incrementAndGet();
_txnStarts.incrementAndGet();
decrementOutstandingTxnsIfNecessary();
@@ -996,17 +968,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
- /**
- * Update last transaction activity timestamp
- */
- private void updateTransactionalActivity()
- {
- if (isTransactional())
- {
- _txnUpdateTime.set(System.currentTimeMillis());
- }
- }
-
public String toString()
{
return "["+_session.toString()+":"+_channelId+"]";
@@ -1055,7 +1016,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag)
throws AMQException
{
- _session.registerMessageDelivered(entry.getMessage().getSize());
getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(),
deliveryTag, sub.getConsumerTag());
}
@@ -1096,11 +1056,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
private boolean checkMessageUserId(ContentHeaderBody header)
{
AMQShortString userID =
- header.getProperties() instanceof BasicContentHeaderProperties
- ? ((BasicContentHeaderProperties) header.getProperties()).getUserId()
+ header.properties instanceof BasicContentHeaderProperties
+ ? ((BasicContentHeaderProperties) header.properties).getUserId()
: null;
- return (!MSG_AUTH || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString()));
+ return (!MSG_AUTH || _session.getPrincipal().getName().equals(userID == null? "" : userID.toString()));
}
@@ -1442,41 +1402,9 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
return _createTime;
}
-
+
public void mgmtClose() throws AMQException
{
_session.mgmtCloseChannel(_channelId);
}
-
- public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException
- {
- if (inTransaction())
- {
- long currentTime = System.currentTimeMillis();
- long openTime = currentTime - _transaction.getTransactionStartTime();
- long idleTime = currentTime - _txnUpdateTime.get();
-
- // Log a warning on idle or open transactions
- if (idleWarn > 0L && idleTime > idleWarn)
- {
- CurrentActor.get().message(_logSubject, ChannelMessages.IDLE_TXN(idleTime));
- _logger.warn("IDLE TRANSACTION ALERT " + _logSubject.toString() + " " + idleTime + " ms");
- }
- else if (openWarn > 0L && openTime > openWarn)
- {
- CurrentActor.get().message(_logSubject, ChannelMessages.OPEN_TXN(openTime));
- _logger.warn("OPEN TRANSACTION ALERT " + _logSubject.toString() + " " + openTime + " ms");
- }
-
- // Close connection for idle or open transactions that have timed out
- if (idleClose > 0L && idleTime > idleClose)
- {
- getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out");
- }
- else if (openClose > 0L && openTime > openClose)
- {
- getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out");
- }
- }
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
deleted file mode 100644
index 1632effaf0..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java
+++ /dev/null
@@ -1,441 +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.
- *
- */
-package org.apache.qpid.server;
-
-import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.xml.QpidLog4JConfigurator;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration;
-import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
-import org.apache.qpid.server.information.management.ServerInformationMBean;
-import org.apache.qpid.server.logging.SystemOutMessageLogger;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.server.logging.management.LoggingManagementMBean;
-import org.apache.qpid.server.logging.messages.BrokerMessages;
-import org.apache.qpid.server.protocol.AmqpProtocolVersion;
-import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
-import org.apache.qpid.server.transport.QpidAcceptor;
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.network.IncomingNetworkTransport;
-import org.apache.qpid.transport.network.Transport;
-
-public class Broker
-{
- private static final int IPV4_ADDRESS_LENGTH = 4;
- private static final char IPV4_LITERAL_SEPARATOR = '.';
-
- protected static class InitException extends RuntimeException
- {
- private static final long serialVersionUID = 1L;
-
- InitException(String msg, Throwable cause)
- {
- super(msg, cause);
- }
- }
-
- public void shutdown()
- {
- ApplicationRegistry.remove();
- }
-
- public void startup() throws Exception
- {
- startup(new BrokerOptions());
- }
-
- public void startup(final BrokerOptions options) throws Exception
- {
- try
- {
- CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
- startupImpl(options);
- }
- finally
- {
- CurrentActor.remove();
- }
- }
-
- private void startupImpl(final BrokerOptions options) throws Exception
- {
- final String qpidHome = options.getQpidHome();
- final File configFile = getConfigFile(options.getConfigFile(),
- BrokerOptions.DEFAULT_CONFIG_FILE, qpidHome, true);
-
- CurrentActor.get().message(BrokerMessages.CONFIG(configFile.getAbsolutePath()));
-
- File logConfigFile = getConfigFile(options.getLogConfigFile(),
- BrokerOptions.DEFAULT_LOG_CONFIG_FILE, qpidHome, false);
-
- configureLogging(logConfigFile, options.getLogWatchFrequency());
-
- ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext());
- ServerConfiguration serverConfig = config.getConfiguration();
- updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer());
-
- ApplicationRegistry.initialise(config);
-
- // We have already loaded the BrokerMessages class by this point so we
- // need to refresh the locale setting incase we had a different value in
- // the configuration.
- BrokerMessages.reload();
-
- // AR.initialise() sets and removes its own actor so we now need to set the actor
- // for the remainder of the startup, and the default actor if the stack is empty
- CurrentActor.set(new BrokerActor(config.getCompositeStartupMessageLogger()));
- CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger()));
- GenericActor.setDefaultMessageLogger(config.getRootMessageLogger());
-
- try
- {
- configureLoggingManagementMBean(logConfigFile, options.getLogWatchFrequency());
-
- ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean();
- configMBean.register();
-
- ServerInformationMBean sysInfoMBean = new ServerInformationMBean(config);
- sysInfoMBean.register();
-
- Set<Integer> ports = new HashSet<Integer>(options.getPorts());
- if(ports.isEmpty())
- {
- parsePortList(ports, serverConfig.getPorts());
- }
-
- Set<Integer> sslPorts = new HashSet<Integer>(options.getSSLPorts());
- if(sslPorts.isEmpty())
- {
- parsePortList(sslPorts, serverConfig.getSSLPorts());
- }
-
- Set<Integer> exclude_0_10 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_10));
- if(exclude_0_10.isEmpty())
- {
- parsePortList(exclude_0_10, serverConfig.getPortExclude010());
- }
-
- Set<Integer> exclude_0_9_1 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_9_1));
- if(exclude_0_9_1.isEmpty())
- {
- parsePortList(exclude_0_9_1, serverConfig.getPortExclude091());
- }
-
- Set<Integer> exclude_0_9 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_9));
- if(exclude_0_9.isEmpty())
- {
- parsePortList(exclude_0_9, serverConfig.getPortExclude09());
- }
-
- Set<Integer> exclude_0_8 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_8));
- if(exclude_0_8.isEmpty())
- {
- parsePortList(exclude_0_8, serverConfig.getPortExclude08());
- }
-
- String bindAddr = options.getBind();
- if (bindAddr == null)
- {
- bindAddr = serverConfig.getBind();
- }
-
- InetAddress bindAddress = null;
- if (bindAddr.equals(WILDCARD_ADDRESS))
- {
- bindAddress = new InetSocketAddress(0).getAddress();
- }
- else
- {
- bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
- }
- String hostName = bindAddress.getCanonicalHostName();
-
- if (!serverConfig.getSSLOnly())
- {
- for(int port : ports)
- {
- final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(port, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8);
- final NetworkTransportConfiguration settings =
- new ServerNetworkTransportConfiguration(serverConfig, port, bindAddress.getHostName(), Transport.TCP);
-
- final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
- final MultiVersionProtocolEngineFactory protocolEngineFactory =
- new MultiVersionProtocolEngineFactory(hostName, supported);
-
- transport.accept(settings, protocolEngineFactory, null);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
- new QpidAcceptor(transport,"TCP"));
- CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
- }
- }
-
- if (serverConfig.getEnableSSL())
- {
- final String keystorePath = serverConfig.getConnectorKeyStorePath();
- final String keystorePassword = serverConfig.getConnectorKeyStorePassword();
- final String certType = serverConfig.getConnectorCertType();
- final SSLContext sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, certType);
-
- for(int sslPort : sslPorts)
- {
- final Set<AmqpProtocolVersion> supported =
- getSupportedVersions(sslPort, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8);
- final NetworkTransportConfiguration settings =
- new ServerNetworkTransportConfiguration(serverConfig, sslPort, bindAddress.getHostName(), Transport.TCP);
-
- final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
- final MultiVersionProtocolEngineFactory protocolEngineFactory =
- new MultiVersionProtocolEngineFactory(hostName, supported);
-
- transport.accept(settings, protocolEngineFactory, sslContext);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, sslPort),
- new QpidAcceptor(transport,"TCP"));
- CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort));
- }
- }
-
- CurrentActor.get().message(BrokerMessages.READY());
- }
- finally
- {
- // Startup is complete so remove the AR initialised Startup actor
- CurrentActor.remove();
- }
- }
-
- private static Set<AmqpProtocolVersion> getSupportedVersions(final int port, final Set<Integer> exclude_0_10,
- final Set<Integer> exclude_0_9_1, final Set<Integer> exclude_0_9,
- final Set<Integer> exclude_0_8)
- {
- final EnumSet<AmqpProtocolVersion> supported = EnumSet.allOf(AmqpProtocolVersion.class);
-
- if(exclude_0_10.contains(port))
- {
- supported.remove(AmqpProtocolVersion.v0_10);
- }
- if(exclude_0_9_1.contains(port))
- {
- supported.remove(AmqpProtocolVersion.v0_9_1);
- }
- if(exclude_0_9.contains(port))
- {
- supported.remove(AmqpProtocolVersion.v0_9);
- }
- if(exclude_0_8.contains(port))
- {
- supported.remove(AmqpProtocolVersion.v0_8);
- }
-
- return supported;
- }
-
- private File getConfigFile(final String fileName,
- final String defaultFileName,
- final String qpidHome, boolean throwOnFileNotFound) throws InitException
- {
- File configFile = null;
- if (fileName != null)
- {
- configFile = new File(fileName);
- }
- else
- {
- configFile = new File(qpidHome, defaultFileName);
- }
-
- if (!configFile.exists() && throwOnFileNotFound)
- {
- String error = "File " + fileName + " could not be found. Check the file exists and is readable.";
-
- if (qpidHome == null)
- {
- error = error + "\nNote: " + BrokerOptions.QPID_HOME + " is not set.";
- }
-
- throw new InitException(error, null);
- }
-
- return configFile;
- }
-
- public static void parsePortList(Set<Integer> output, List<?> ports) throws InitException
- {
- if(ports != null)
- {
- for(Object o : ports)
- {
- try
- {
- output.add(Integer.parseInt(String.valueOf(o)));
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid port: " + o, e);
- }
- }
- }
- }
-
- /**
- * Update the configuration data with the management port.
- * @param configuration
- * @param registryServerPort The string from the command line
- */
- private void updateManagementPorts(ServerConfiguration configuration, Integer registryServerPort, Integer connectorServerPort)
- {
- if (registryServerPort != null)
- {
- try
- {
- configuration.setJMXPortRegistryServer(registryServerPort);
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid management (registry server) port: " + registryServerPort, null);
- }
- }
- if (connectorServerPort != null)
- {
- try
- {
- configuration.setJMXPortConnectorServer(connectorServerPort);
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid management (connector server) port: " + connectorServerPort, null);
- }
- }
- }
-
- private byte[] parseIP(String address) throws Exception
- {
- char[] literalBuffer = address.toCharArray();
- int byteCount = 0;
- int currByte = 0;
- byte[] ip = new byte[IPV4_ADDRESS_LENGTH];
- for (int i = 0; i < literalBuffer.length; i++)
- {
- char currChar = literalBuffer[i];
- if ((currChar >= '0') && (currChar <= '9'))
- {
- currByte = (currByte * 10) + (Character.digit(currChar, 10) & 0xFF);
- }
-
- if (currChar == IPV4_LITERAL_SEPARATOR || (i + 1 == literalBuffer.length))
- {
- ip[byteCount++] = (byte) currByte;
- currByte = 0;
- }
- }
-
- if (byteCount != 4)
- {
- throw new Exception("Invalid IP address: " + address);
- }
- return ip;
- }
-
- private void configureLogging(File logConfigFile, long logWatchTime) throws InitException, IOException
- {
- if (logConfigFile.exists() && logConfigFile.canRead())
- {
- CurrentActor.get().message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
-
- if (logWatchTime > 0)
- {
- System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every "
- + logWatchTime + " seconds");
- // log4j expects the watch interval in milliseconds
- try
- {
- QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
- }
- catch (Exception e)
- {
- throw new InitException(e.getMessage(),e);
- }
- }
- else
- {
- try
- {
- QpidLog4JConfigurator.configure(logConfigFile.getPath());
- }
- catch (Exception e)
- {
- throw new InitException(e.getMessage(),e);
- }
- }
- }
- else
- {
- System.err.println("Logging configuration error: unable to read file " + logConfigFile.getAbsolutePath());
- System.err.println("Using the fallback internal log4j.properties configuration");
-
- InputStream propsFile = this.getClass().getResourceAsStream("/log4j.properties");
- if(propsFile == null)
- {
- throw new IOException("Unable to load the fallback internal log4j.properties configuration file");
- }
- else
- {
- try
- {
- Properties fallbackProps = new Properties();
- fallbackProps.load(propsFile);
- PropertyConfigurator.configure(fallbackProps);
- }
- finally
- {
- propsFile.close();
- }
- }
- }
- }
-
- private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
- {
- LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
-
- blm.register();
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
deleted file mode 100644
index 3defd8260c..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ /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.
- *
- */
-package org.apache.qpid.server;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.framework.BundleContext;
-
-public class BrokerOptions
-{
- /** serialVersionUID */
- private static final long serialVersionUID = 8051825964945442234L;
-
- public static final String DEFAULT_CONFIG_FILE = "etc/config.xml";
- public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml";
- public static final String QPID_HOME = "QPID_HOME";
-
- private final Set<Integer> _ports = new HashSet<Integer>();
- private final Set<Integer> _sslPorts = new HashSet<Integer>();
- private final Map<ProtocolExclusion,Set<Integer>> _exclusionMap = new HashMap<ProtocolExclusion, Set<Integer>>();
-
- private String _configFile;
- private String _logConfigFile;
- private String _bind;
- private Integer _jmxPortRegistryServer;
- private Integer _jmxPortConnectorServer;
- private BundleContext _bundleContext;
-
- private Integer _logWatchFrequency = 0;
-
-
- public void addPort(final int port)
- {
- _ports.add(port);
- }
-
- public void addSSLPort(final int sslPort)
- {
- _sslPorts.add(sslPort);
- }
-
- public Set<Integer> getPorts()
- {
- return Collections.unmodifiableSet(_ports);
- }
-
- public Set<Integer> getSSLPorts()
- {
- return Collections.unmodifiableSet(_sslPorts);
- }
-
- public String getConfigFile()
- {
- return _configFile;
- }
-
- public void setConfigFile(final String configFile)
- {
- _configFile = configFile;
- }
-
- public String getLogConfigFile()
- {
- return _logConfigFile;
- }
-
- public void setLogConfigFile(final String logConfigFile)
- {
- _logConfigFile = logConfigFile;
- }
-
- public Integer getJmxPortRegistryServer()
- {
- return _jmxPortRegistryServer;
- }
-
- public void setJmxPortRegistryServer(final int jmxPortRegistryServer)
- {
- _jmxPortRegistryServer = jmxPortRegistryServer;
- }
-
- public Integer getJmxPortConnectorServer()
- {
- return _jmxPortConnectorServer;
- }
-
- public void setJmxPortConnectorServer(final int jmxPortConnectorServer)
- {
- _jmxPortConnectorServer = jmxPortConnectorServer;
- }
-
- public String getQpidHome()
- {
- return System.getProperty(QPID_HOME);
- }
-
- public Set<Integer> getExcludedPorts(final ProtocolExclusion excludeProtocol)
- {
- final Set<Integer> excludedPorts = _exclusionMap.get(excludeProtocol);
- return excludedPorts == null ? Collections.<Integer>emptySet() : excludedPorts;
- }
-
- public void addExcludedPort(final ProtocolExclusion excludeProtocol, final int port)
- {
- if (!_exclusionMap.containsKey(excludeProtocol))
- {
- _exclusionMap.put(excludeProtocol, new HashSet<Integer>());
- }
-
- Set<Integer> ports = _exclusionMap.get(excludeProtocol);
- ports.add(port);
- }
-
- public String getBind()
- {
- return _bind;
- }
-
- public void setBind(final String bind)
- {
- _bind = bind;
- }
-
- public int getLogWatchFrequency()
- {
- return _logWatchFrequency;
- }
-
- /**
- * Set the frequency with which the log config file will be checked for updates.
- * @param logWatchFrequency frequency in seconds
- */
- public void setLogWatchFrequency(final int logWatchFrequency)
- {
- _logWatchFrequency = logWatchFrequency;
- }
-
- public BundleContext getBundleContext()
- {
- return _bundleContext ;
- }
-
- public void setBundleContext(final BundleContext bundleContext)
- {
- _bundleContext = bundleContext;
- }
-
-} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java
index 0c038c7800..71cf17ed60 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -20,6 +20,17 @@
*/
package org.apache.qpid.server;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
@@ -27,9 +38,29 @@ import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
-import org.apache.qpid.server.Broker.InitException;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.QpidLog4JConfigurator;
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
+import org.apache.qpid.server.information.management.ServerInformationMBean;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
+import org.apache.qpid.server.logging.actors.BrokerActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.GenericActor;
+import org.apache.qpid.server.logging.management.LoggingManagementMBean;
+import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.protocol.AMQProtocolEngineFactory;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
import org.apache.qpid.server.registry.ApplicationRegistry;
-
+import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
+import org.apache.qpid.server.transport.QpidAcceptor;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.network.mina.MINANetworkDriver;
/**
* Main entry point for AMQPD.
@@ -37,129 +68,41 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
*/
public class Main
{
+ private static Logger _logger;
- private static final Option OPTION_HELP = new Option("h", "help", false, "print this message");
-
- private static final Option OPTION_VERSION = new Option("v", "version", false, "print the version information and exit");
-
- private static final Option OPTION_CONFIG_FILE =
- OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config")
- .create("c");
-
- private static final Option OPTION_PORT =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("listen on the specified port. Overrides any value in the config file")
- .withLongOpt("port").create("p");
-
- private static final Option OPTION_SSLPORT =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("SSL port. Overrides any value in the config file")
- .withLongOpt("sslport").create("s");
-
- private static final Option OPTION_EXCLUDE_0_10 =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-10").create();
-
- private static final Option OPTION_EXCLUDE_0_9_1 =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-9-1 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-9-1").create();
-
- private static final Option OPTION_EXCLUDE_0_9 =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-9").create();
-
- private static final Option OPTION_EXCLUDE_0_8 =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-8 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-8").create();
-
- private static final Option OPTION_JMX_PORT_REGISTRY_SERVER =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("listen on the specified management (registry server) port. Overrides any value in the config file")
- .withLongOpt("jmxregistryport").create("m");
-
- private static final Option OPTION_JMX_PORT_CONNECTOR_SERVER =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("listen on the specified management (connector server) port. Overrides any value in the config file")
- .withLongOpt("jmxconnectorport").create();
-
- private static final Option OPTION_BIND =
- OptionBuilder.withArgName("address").hasArg()
- .withDescription("bind to the specified address. Overrides any value in the config file")
- .withLongOpt("bind").create("b");
-
- private static final Option OPTION_LOG_CONFIG_FILE =
- OptionBuilder.withArgName("file").hasArg()
- .withDescription("use the specified log4j xml configuration file. By "
- + "default looks for a file named " + BrokerOptions.DEFAULT_LOG_CONFIG_FILE
- + " in the same directory as the configuration file").withLongOpt("logconfig").create("l");
-
- private static final Option OPTION_LOG_WATCH =
- OptionBuilder.withArgName("period").hasArg()
- .withDescription("monitor the log file configuration file for changes. Units are seconds. "
- + "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
-
- private static final Options OPTIONS = new Options();
-
- static
- {
- OPTIONS.addOption(OPTION_HELP);
- OPTIONS.addOption(OPTION_VERSION);
- OPTIONS.addOption(OPTION_CONFIG_FILE);
- OPTIONS.addOption(OPTION_LOG_CONFIG_FILE);
- OPTIONS.addOption(OPTION_LOG_WATCH);
- OPTIONS.addOption(OPTION_PORT);
- OPTIONS.addOption(OPTION_SSLPORT);
- OPTIONS.addOption(OPTION_EXCLUDE_0_10);
- OPTIONS.addOption(OPTION_EXCLUDE_0_9_1);
- OPTIONS.addOption(OPTION_EXCLUDE_0_9);
- OPTIONS.addOption(OPTION_EXCLUDE_0_8);
- OPTIONS.addOption(OPTION_BIND);
-
- OPTIONS.addOption(OPTION_JMX_PORT_REGISTRY_SERVER);
- OPTIONS.addOption(OPTION_JMX_PORT_CONNECTOR_SERVER);
- }
+ private static final String DEFAULT_CONFIG_FILE = "etc/config.xml";
- private CommandLine commandLine;
+ public static final String DEFAULT_LOG_CONFIG_FILENAME = "log4j.xml";
+ public static final String QPID_HOME = "QPID_HOME";
+ private static final int IPV4_ADDRESS_LENGTH = 4;
- public static void main(String[] args)
+ private static final char IPV4_LITERAL_SEPARATOR = '.';
+
+ protected static class InitException extends Exception
{
- //if the -Dlog4j.configuration property has not been set, enable the init override
- //to stop Log4J wondering off and picking up the first log4j.xml/properties file it
- //finds from the classpath when we get the first Loggers
- if(System.getProperty("log4j.configuration") == null)
+ InitException(String msg, Throwable cause)
{
- System.setProperty("log4j.defaultInitOverride", "true");
+ super(msg, cause);
}
-
- new Main(args);
}
- public Main(final String[] args)
+ protected final Options options = new Options();
+ protected CommandLine commandLine;
+
+ protected Main(String[] args)
{
+ setOptions(options);
if (parseCommandline(args))
{
- try
- {
- execute();
- }
- catch(Throwable e)
- {
- System.err.println("Exception during startup: " + e);
- e.printStackTrace();
- shutdown(1);
- }
+ execute();
}
}
- protected boolean parseCommandline(final String[] args)
+ protected boolean parseCommandline(String[] args)
{
try
{
- commandLine = new PosixParser().parse(OPTIONS, args);
+ commandLine = new PosixParser().parse(options, args);
return true;
}
@@ -167,129 +110,509 @@ public class Main
{
System.err.println("Error: " + e.getMessage());
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("Qpid", OPTIONS, true);
+ formatter.printHelp("Qpid", options, true);
return false;
}
}
- protected void execute() throws Exception
+ @SuppressWarnings("static-access")
+ protected void setOptions(Options options)
+ {
+ Option help = new Option("h", "help", false, "print this message");
+ Option version = new Option("v", "version", false, "print the version information and exit");
+ Option configFile =
+ OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config")
+ .create("c");
+ Option port =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("listen on the specified port. Overrides any value in the config file")
+ .withLongOpt("port").create("p");
+
+ Option exclude0_10 =
+ OptionBuilder.withArgName("exclude-0-10").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-10").create();
+
+ Option exclude0_9_1 =
+ OptionBuilder.withArgName("exclude-0-9-1").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-9-1 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-9-1").create();
+
+
+ Option exclude0_9 =
+ OptionBuilder.withArgName("exclude-0-9").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-9").create();
+
+
+ Option exclude0_8 =
+ OptionBuilder.withArgName("exclude-0-8").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-8 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-8").create();
+
+
+ Option mport =
+ OptionBuilder.withArgName("mport").hasArg()
+ .withDescription("listen on the specified management port. Overrides any value in the config file")
+ .withLongOpt("mport").create("m");
+
+
+ Option bind =
+ OptionBuilder.withArgName("bind").hasArg()
+ .withDescription("bind to the specified address. Overrides any value in the config file")
+ .withLongOpt("bind").create("b");
+ Option logconfig =
+ OptionBuilder.withArgName("logconfig").hasArg()
+ .withDescription("use the specified log4j xml configuration file. By "
+ + "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME
+ + " in the same directory as the configuration file").withLongOpt("logconfig").create("l");
+ Option logwatchconfig =
+ OptionBuilder.withArgName("logwatch").hasArg()
+ .withDescription("monitor the log file configuration file for changes. Units are seconds. "
+ + "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
+
+ options.addOption(help);
+ options.addOption(version);
+ options.addOption(configFile);
+ options.addOption(logconfig);
+ options.addOption(logwatchconfig);
+ options.addOption(port);
+ options.addOption(exclude0_10);
+ options.addOption(exclude0_9_1);
+ options.addOption(exclude0_9);
+ options.addOption(exclude0_8);
+ options.addOption(mport);
+ options.addOption(bind);
+ }
+
+ protected void execute()
{
- BrokerOptions options = new BrokerOptions();
- String configFile = commandLine.getOptionValue(OPTION_CONFIG_FILE.getOpt());
- if(configFile != null)
+ // note this understands either --help or -h. If an option only has a long name you can use that but if
+ // an option has a short name and a long name you must use the short name here.
+ if (commandLine.hasOption("h"))
{
- options.setConfigFile(configFile);
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("Qpid", options, true);
}
+ else if (commandLine.hasOption("v"))
+ {
+ String ver = QpidProperties.getVersionString();
- String logWatchConfig = commandLine.getOptionValue(OPTION_LOG_WATCH.getOpt());
- if(logWatchConfig != null)
+ StringBuilder protocol = new StringBuilder("AMQP version(s) [major.minor]: ");
+
+ boolean first = true;
+ for (ProtocolVersion pv : ProtocolVersion.getSupportedProtocolVersions())
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ protocol.append(", ");
+ }
+
+ protocol.append(pv.getMajorVersion()).append('-').append(pv.getMinorVersion());
+
+ }
+
+ System.out.println(ver + " (" + protocol + ")");
+ }
+ else
{
- options.setLogWatchFrequency(Integer.parseInt(logWatchConfig));
+ try
+ {
+ CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
+ startup();
+ CurrentActor.remove();
+ }
+ catch (InitException e)
+ {
+ System.out.println("Initialisation Error : " + e.getMessage());
+ shutdown(1);
+ }
+ catch (Throwable e)
+ {
+ System.out.println("Error initialising message broker: " + e);
+ e.printStackTrace();
+ shutdown(1);
+ }
}
+ }
+
+ protected void shutdown(int status)
+ {
+ ApplicationRegistry.removeAll();
+ System.exit(status);
+ }
- String logConfig = commandLine.getOptionValue(OPTION_LOG_CONFIG_FILE.getOpt());
- if(logConfig != null)
+ protected void startup() throws Exception
+ {
+ final String QpidHome = System.getProperty(QPID_HOME);
+ final File defaultConfigFile = new File(QpidHome, DEFAULT_CONFIG_FILE);
+ final File configFile = new File(commandLine.getOptionValue("c", defaultConfigFile.getPath()));
+ if (!configFile.exists())
+ {
+ String error = "File " + configFile + " could not be found. Check the file exists and is readable.";
+
+ if (QpidHome == null)
+ {
+ error = error + "\nNote: " + QPID_HOME + " is not set.";
+ }
+
+ throw new InitException(error, null);
+ }
+ else
{
- options.setLogConfigFile(logConfig);
+ CurrentActor.get().message(BrokerMessages.CONFIG(configFile.getAbsolutePath()));
}
- String jmxPortRegistryServer = commandLine.getOptionValue(OPTION_JMX_PORT_REGISTRY_SERVER.getOpt());
- if(jmxPortRegistryServer != null)
+ String logConfig = commandLine.getOptionValue("l");
+ String logWatchConfig = commandLine.getOptionValue("w", "0");
+
+ int logWatchTime = 0;
+ try
+ {
+ logWatchTime = Integer.parseInt(logWatchConfig);
+ }
+ catch (NumberFormatException e)
{
- options.setJmxPortRegistryServer(Integer.parseInt(jmxPortRegistryServer));
+ System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be "
+ + "a non-negative integer. Using default of zero (no watching configured");
}
- String jmxPortConnectorServer = commandLine.getOptionValue(OPTION_JMX_PORT_CONNECTOR_SERVER.getLongOpt());
- if(jmxPortConnectorServer != null)
+ File logConfigFile;
+ if (logConfig != null)
+ {
+ logConfigFile = new File(logConfig);
+ configureLogging(logConfigFile, logWatchTime);
+ }
+ else
{
- options.setJmxPortConnectorServer(Integer.parseInt(jmxPortConnectorServer));
+ File configFileDirectory = configFile.getParentFile();
+ logConfigFile = new File(configFileDirectory, DEFAULT_LOG_CONFIG_FILENAME);
+ configureLogging(logConfigFile, logWatchTime);
}
- String bindAddr = commandLine.getOptionValue(OPTION_BIND.getOpt());
- if (bindAddr != null)
+ ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile);
+ ServerConfiguration serverConfig = config.getConfiguration();
+ updateManagementPort(serverConfig, commandLine.getOptionValue("m"));
+
+ ApplicationRegistry.initialise(config);
+
+ // We have already loaded the BrokerMessages class by this point so we
+ // need to refresh the locale setting incase we had a different value in
+ // the configuration.
+ BrokerMessages.reload();
+
+ // AR.initialise() sets and removes its own actor so we now need to set the actor
+ // for the remainder of the startup, and the default actor if the stack is empty
+ CurrentActor.set(new BrokerActor(config.getCompositeStartupMessageLogger()));
+ CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger()));
+ GenericActor.setDefaultMessageLogger(config.getRootMessageLogger());
+
+
+ try
{
- options.setBind(bindAddr);
+ configureLoggingManagementMBean(logConfigFile, logWatchTime);
+
+ ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean();
+ configMBean.register();
+
+ ServerInformationMBean sysInfoMBean =
+ new ServerInformationMBean(QpidProperties.getBuildVersion(), QpidProperties.getReleaseVersion());
+ sysInfoMBean.register();
+
+
+ String[] portStr = commandLine.getOptionValues("p");
+
+ Set<Integer> ports = new HashSet<Integer>();
+ Set<Integer> exclude_0_10 = new HashSet<Integer>();
+ Set<Integer> exclude_0_9_1 = new HashSet<Integer>();
+ Set<Integer> exclude_0_9 = new HashSet<Integer>();
+ Set<Integer> exclude_0_8 = new HashSet<Integer>();
+
+ if(portStr == null || portStr.length == 0)
+ {
+
+ parsePortList(ports, serverConfig.getPorts());
+ parsePortList(exclude_0_10, serverConfig.getPortExclude010());
+ parsePortList(exclude_0_9_1, serverConfig.getPortExclude091());
+ parsePortList(exclude_0_9, serverConfig.getPortExclude09());
+ parsePortList(exclude_0_8, serverConfig.getPortExclude08());
+
+ }
+ else
+ {
+ parsePortArray(ports, portStr);
+ parsePortArray(exclude_0_10, commandLine.getOptionValues("exclude-0-10"));
+ parsePortArray(exclude_0_9_1, commandLine.getOptionValues("exclude-0-9-1"));
+ parsePortArray(exclude_0_9, commandLine.getOptionValues("exclude-0-9"));
+ parsePortArray(exclude_0_8, commandLine.getOptionValues("exclude-0-8"));
+
+ }
+
+
+
+
+ String bindAddr = commandLine.getOptionValue("b");
+ if (bindAddr == null)
+ {
+ bindAddr = serverConfig.getBind();
+ }
+ InetAddress bindAddress = null;
+
+
+
+ if (bindAddr.equals("wildcard"))
+ {
+ bindAddress = new InetSocketAddress(0).getAddress();
+ }
+ else
+ {
+ bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
+ }
+
+ String hostName = bindAddress.getCanonicalHostName();
+
+
+ String keystorePath = serverConfig.getKeystorePath();
+ String keystorePassword = serverConfig.getKeystorePassword();
+ String certType = serverConfig.getCertType();
+ SSLContextFactory sslFactory = null;
+
+ if (!serverConfig.getSSLOnly())
+ {
+
+ for(int port : ports)
+ {
+
+ NetworkDriver driver = new MINANetworkDriver();
+
+ Set<VERSION> supported = EnumSet.allOf(VERSION.class);
+
+ if(exclude_0_10.contains(port))
+ {
+ supported.remove(VERSION.v0_10);
+ }
+
+ if(exclude_0_9_1.contains(port))
+ {
+ supported.remove(VERSION.v0_9_1);
+ }
+ if(exclude_0_9.contains(port))
+ {
+ supported.remove(VERSION.v0_9);
+ }
+ if(exclude_0_8.contains(port))
+ {
+ supported.remove(VERSION.v0_8);
+ }
+
+ MultiVersionProtocolEngineFactory protocolEngineFactory =
+ new MultiVersionProtocolEngineFactory(hostName, supported);
+
+
+
+ driver.bind(port, new InetAddress[]{bindAddress}, protocolEngineFactory,
+ serverConfig.getNetworkConfiguration(), null);
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
+ new QpidAcceptor(driver,"TCP"));
+ CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
+
+ }
+
+ }
+
+ if (serverConfig.getEnableSSL())
+ {
+ sslFactory = new SSLContextFactory(keystorePath, keystorePassword, certType);
+ NetworkDriver driver = new MINANetworkDriver();
+ driver.bind(serverConfig.getSSLPort(), new InetAddress[]{bindAddress},
+ new AMQProtocolEngineFactory(), serverConfig.getNetworkConfiguration(), sslFactory);
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, serverConfig.getSSLPort()),
+ new QpidAcceptor(driver,"TCP"));
+ CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", serverConfig.getSSLPort()));
+ }
+
+ CurrentActor.get().message(BrokerMessages.READY());
+
+ }
+ finally
+ {
+ // Startup is complete so remove the AR initialised Startup actor
+ CurrentActor.remove();
}
- String[] portStr = commandLine.getOptionValues(OPTION_PORT.getOpt());
+
+
+ }
+
+ private void parsePortArray(Set<Integer> ports, String[] portStr)
+ throws InitException
+ {
if(portStr != null)
{
- parsePortArray(options, portStr, false);
- for(ProtocolExclusion pe : ProtocolExclusion.values())
+ for(int i = 0; i < portStr.length; i++)
{
- parsePortArray(options, commandLine.getOptionValues(pe.getExcludeName()), pe);
+ try
+ {
+ ports.add(Integer.parseInt(portStr[i]));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port: " + portStr[i], e);
+ }
}
}
+ }
- String[] sslPortStr = commandLine.getOptionValues(OPTION_SSLPORT.getOpt());
- if(sslPortStr != null)
+ private void parsePortList(Set<Integer> output, List input)
+ throws InitException
+ {
+ if(input != null)
{
- parsePortArray(options, sslPortStr, true);
- for(ProtocolExclusion pe : ProtocolExclusion.values())
+ for(Object port : input)
{
- parsePortArray(options, commandLine.getOptionValues(pe.getExcludeName()), pe);
+ try
+ {
+ output.add(Integer.parseInt(String.valueOf(port)));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port: " + port, e);
+ }
}
}
-
- startBroker(options);
}
- protected void startBroker(final BrokerOptions options) throws Exception
+ /**
+ * Update the configuration data with the management port.
+ * @param configuration
+ * @param managementPort The string from the command line
+ */
+ private void updateManagementPort(ServerConfiguration configuration, String managementPort)
{
- Broker broker = new Broker();
- broker.startup(options);
+ if (managementPort != null)
+ {
+ try
+ {
+ configuration.setJMXManagementPort(Integer.parseInt(managementPort));
+ }
+ catch (NumberFormatException e)
+ {
+ _logger.warn("Invalid management port: " + managementPort + " will use:" + configuration.getJMXManagementPort(), e);
+ }
+ }
}
- protected void shutdown(final int status)
+ public static void main(String[] args)
{
- ApplicationRegistry.remove();
- System.exit(status);
+ //if the -Dlog4j.configuration property has not been set, enable the init override
+ //to stop Log4J wondering off and picking up the first log4j.xml/properties file it
+ //finds from the classpath when we get the first Loggers
+ if(System.getProperty("log4j.configuration") == null)
+ {
+ System.setProperty("log4j.defaultInitOverride", "true");
+ }
+
+ //now that the override status is know, we can instantiate the Loggers
+ _logger = Logger.getLogger(Main.class);
+
+ new Main(args);
}
- private static void parsePortArray(final BrokerOptions options,final Object[] ports,
- final boolean ssl) throws InitException
+ private byte[] parseIP(String address) throws Exception
{
- if(ports != null)
+ char[] literalBuffer = address.toCharArray();
+ int byteCount = 0;
+ int currByte = 0;
+ byte[] ip = new byte[IPV4_ADDRESS_LENGTH];
+ for (int i = 0; i < literalBuffer.length; i++)
{
- for(int i = 0; i < ports.length; i++)
+ char currChar = literalBuffer[i];
+ if ((currChar >= '0') && (currChar <= '9'))
+ {
+ currByte = (currByte * 10) + (Character.digit(currChar, 10) & 0xFF);
+ }
+
+ if (currChar == IPV4_LITERAL_SEPARATOR || (i + 1 == literalBuffer.length))
{
+ ip[byteCount++] = (byte) currByte;
+ currByte = 0;
+ }
+ }
+
+ if (byteCount != 4)
+ {
+ throw new Exception("Invalid IP address: " + address);
+ }
+ return ip;
+ }
+
+ private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException
+ {
+ if (logConfigFile.exists() && logConfigFile.canRead())
+ {
+ CurrentActor.get().message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
+
+ if (logWatchTime > 0)
+ {
+ System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every "
+ + logWatchTime + " seconds");
+ // log4j expects the watch interval in milliseconds
try
{
- if(ssl)
- {
- options.addSSLPort(Integer.parseInt(String.valueOf(ports[i])));
- }
- else
- {
- options.addPort(Integer.parseInt(String.valueOf(ports[i])));
- }
+ QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
}
- catch (NumberFormatException e)
+ catch (Exception e)
{
- throw new InitException("Invalid port: " + ports[i], e);
+ throw new InitException(e.getMessage(),e);
+ }
+ }
+ else
+ {
+ try
+ {
+ QpidLog4JConfigurator.configure(logConfigFile.getPath());
+ }
+ catch (Exception e)
+ {
+ throw new InitException(e.getMessage(),e);
}
}
}
- }
-
- private static void parsePortArray(final BrokerOptions options, final Object[] ports,
- final ProtocolExclusion excludedProtocol) throws InitException
- {
- if(ports != null)
+ else
{
- for(int i = 0; i < ports.length; i++)
+ System.err.println("Logging configuration error: unable to read file " + logConfigFile.getAbsolutePath());
+ System.err.println("Using the fallback internal log4j.properties configuration");
+
+ InputStream propsFile = this.getClass().getResourceAsStream("/log4j.properties");
+ if(propsFile == null)
+ {
+ throw new IOException("Unable to load the fallback internal log4j.properties configuration file");
+ }
+ else
{
try
{
- options.addExcludedPort(excludedProtocol,
- Integer.parseInt(String.valueOf(ports[i])));
+ Properties fallbackProps = new Properties();
+ fallbackProps.load(propsFile);
+ PropertyConfigurator.configure(fallbackProps);
}
- catch (NumberFormatException e)
+ finally
{
- throw new InitException("Invalid port for exclusion: " + ports[i], e);
+ propsFile.close();
}
}
}
}
+
+ private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
+ {
+ LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
+
+ blm.register();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
deleted file mode 100644
index 22d97d36dd..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
+++ /dev/null
@@ -1,73 +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.
- *
- */
-package org.apache.qpid.server;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public enum ProtocolExclusion
-{
- v0_8("exclude-0-8","--exclude-0-8"),
- v0_9("exclude-0-9", "--exclude-0-9"),
- v0_9_1("exclude-0-9-1", "--exclude-0-9-1"),
- v0_10("exclude-0-10", "--exclude-0-10");
-
- private static final Map<String, ProtocolExclusion> MAP = new HashMap<String,ProtocolExclusion>();
-
- static
- {
- for(ProtocolExclusion pe : ProtocolExclusion.values())
- {
- MAP.put(pe.getArg(), pe);
- }
- }
-
- private String _arg;
- private String _excludeName;
-
- private ProtocolExclusion(final String excludeName, final String arg)
- {
- _excludeName = excludeName;
- _arg = arg;
- }
-
- public String getArg()
- {
- return _arg;
- }
-
- public String getExcludeName()
- {
- return _excludeName;
- }
-
- public static ProtocolExclusion lookup(final String arg)
- {
- ProtocolExclusion ex = MAP.get(arg);
-
- if(ex == null)
- {
- throw new IllegalArgumentException(arg + " is not a valid protocol exclusion");
- }
-
- return ex;
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
index 70fa39c71d..7197ec8cdc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java
@@ -20,8 +20,6 @@
package org.apache.qpid.server.configuration;
-import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
@@ -39,28 +37,33 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.signal.SignalHandlerTask;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.transport.NetworkDriverConfiguration;
+
+import sun.misc.Signal;
+import sun.misc.SignalHandler;
-public class ServerConfiguration extends ConfigurationPlugin
+public class ServerConfiguration extends ConfigurationPlugin implements SignalHandler
{
protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class);
// Default Configuration values
- public static final int DEFAULT_BUFFER_SIZE = 262144;
+ public static final int DEFAULT_BUFFER_READ_LIMIT_SIZE = 262144;
+ public static final int DEFAULT_BUFFER_WRITE_LIMIT_SIZE = 262144;
+ public static final boolean DEFAULT_BROKER_CONNECTOR_PROTECTIO_ENABLED = false;
public static final String DEFAULT_STATUS_UPDATES = "on";
public static final String SECURITY_CONFIG_RELOADED = "SECURITY CONFIGURATION RELOADED";
public static final int DEFAULT_FRAME_SIZE = 65536;
public static final int DEFAULT_PORT = 5672;
- public static final int DEFAULT_SSL_PORT = 5671;
+ public static final int DEFAULT_SSL_PORT = 8672;
public static final long DEFAULT_HOUSEKEEPING_PERIOD = 30000L;
- public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999;
- public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100;
-
+ public static final int DEFAULT_JMXPORT = 8999;
+
public static final String QPID_HOME = "QPID_HOME";
public static final String QPID_WORK = "QPID_WORK";
public static final String LIB_DIR = "lib";
@@ -72,14 +75,19 @@ public class ServerConfiguration extends ConfigurationPlugin
private File _configFile;
private File _vhostsFile;
+ private Logger _log = Logger.getLogger(this.getClass());
+
+ private ConfigurationManagementMBean _mbean;
+
// Map of environment variables to config items
private static final Map<String, String> envVarMap = new HashMap<String, String>();
// Configuration values to be read from the configuration file
//todo Move all properties to static values to ensure system testing can be performed.
+ public static final String CONNECTOR_PROTECTIO_ENABLED = "connector.protectio.enabled";
+ public static final String CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE = "connector.protectio.readBufferLimitSize";
+ public static final String CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE = "connector.protectio.writeBufferLimitSize";
public static final String MGMT_CUSTOM_REGISTRY_SOCKET = "management.custom-registry-socket";
- public static final String MGMT_JMXPORT_REGISTRYSERVER = "management.jmxport.registryServer";
- public static final String MGMT_JMXPORT_CONNECTORSERVER = "management.jmxport.connectorServer";
public static final String STATUS_UPDATES = "status-updates";
public static final String ADVANCED_LOCALE = "advanced.locale";
@@ -87,9 +95,9 @@ public class ServerConfiguration extends ConfigurationPlugin
envVarMap.put("QPID_PORT", "connector.port");
envVarMap.put("QPID_ENABLEDIRECTBUFFERS", "advanced.enableDirectBuffers");
envVarMap.put("QPID_SSLPORT", "connector.ssl.port");
+ envVarMap.put("QPID_NIO", "connector.qpidnio");
envVarMap.put("QPID_WRITEBIASED", "advanced.useWriteBiasedPool");
- envVarMap.put("QPID_JMXPORT_REGISTRYSERVER", MGMT_JMXPORT_REGISTRYSERVER);
- envVarMap.put("QPID_JMXPORT_CONNECTORSERVER", MGMT_JMXPORT_CONNECTORSERVER);
+ envVarMap.put("QPID_JMXPORT", "management.jmxport");
envVarMap.put("QPID_FRAMESIZE", "advanced.framesize");
envVarMap.put("QPID_MSGAUTH", "security.msg-auth");
envVarMap.put("QPID_AUTOREGISTER", "auto_register");
@@ -123,7 +131,7 @@ public class ServerConfiguration extends ConfigurationPlugin
* Configuration Manager to be initialised in the Application Registry.
* <p>
* If using this ServerConfiguration via an ApplicationRegistry there is no
- * need to explicitly call {@link #initialise()} as this is done via the
+ * need to explictly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
* @param configurationURL
@@ -133,26 +141,15 @@ public class ServerConfiguration extends ConfigurationPlugin
{
this(parseConfig(configurationURL));
_configFile = configurationURL;
-
- SignalHandlerTask hupReparseTask = new SignalHandlerTask()
+ try
{
- public void handle()
- {
- try
- {
- reparseConfigFileSecuritySections();
- }
- catch (ConfigurationException e)
- {
- _logger.error("Could not reload configuration file security sections", e);
- }
- }
- };
-
- if(!hupReparseTask.register("HUP"))
+ Signal sig = new sun.misc.Signal("HUP");
+ sun.misc.Signal.handle(sig, this);
+ }
+ catch (Exception e)
{
- _logger.info("Unable to register Signal HUP handler to reload security configuration.");
- _logger.info("Signal HUP not supported for this OS / JVM combination - " + SignalHandlerTask.getPlatformDescription());
+ _logger.error("Signal HUP not supported for OS: " + System.getProperty("os.name"));
+ // We're on something that doesn't handle SIGHUP, how sad, Windows.
}
}
@@ -169,7 +166,7 @@ public class ServerConfiguration extends ConfigurationPlugin
* Configuration Manager to be initialised in the Application Registry.
* <p>
* If using this ServerConfiguration via an ApplicationRegistry there is no
- * need to explicitly call {@link #initialise()} as this is done via the
+ * need to explictly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
* @param conf
@@ -208,53 +205,7 @@ public class ServerConfiguration extends ConfigurationPlugin
@Override
public void validateConfiguration() throws ConfigurationException
{
- // Support for security.jmx.access was removed when JMX access rights were incorporated into the main ACL.
- // This ensure that users remove the element from their configuration file.
-
- if (getListValue("security.jmx.access").size() > 0)
- {
- String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml."
- + (_configFile == null ? "" : " Configuration file : " + _configFile);
- throw new ConfigurationException(message);
- }
-
- if (getListValue("security.jmx.principal-database").size() > 0)
- {
- String message = "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml."
- + (_configFile == null ? "" : " Configuration file : " + _configFile);
- throw new ConfigurationException(message);
- }
-
- if (getListValue("security.principal-databases.principal-database(0).class").size() > 0)
- {
- String message = "Validation error : security/principal-databases is no longer supported within the configuration xml."
- + (_configFile == null ? "" : " Configuration file : " + _configFile);
- throw new ConfigurationException(message);
- }
-
- // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency
- if (contains("housekeeping.expiredMessageCheckPeriod"))
- {
- String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod."
- + (_configFile == null ? "" : " Configuration file : " + _configFile);
- throw new ConfigurationException(message);
- }
-
- // QPID-3517: Inconsistency in capitalisation in the SSL configuration keys used within the connector and management configuration
- // sections. For the moment, continue to understand both but generate a deprecated warning if the less preferred keystore is used.
- for (String key : new String[] {"management.ssl.keystorePath",
- "management.ssl.keystorePassword," +
- "connector.ssl.keystorePath",
- "connector.ssl.keystorePassword"})
- {
- if (contains(key))
- {
- final String deprecatedXpath = key.replaceAll("\\.", "/");
- final String preferredXpath = deprecatedXpath.replaceAll("keystore", "keyStore");
- _logger.warn("Validation warning: " + deprecatedXpath + " is deprecated and must be replaced by " + preferredXpath
- + (_configFile == null ? "" : " Configuration file : " + _configFile));
- }
- }
+ //Currently doesn't do validation
}
/*
@@ -420,7 +371,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public final static Configuration flatConfig(File file) throws ConfigurationException
{
// We have to override the interpolate methods so that
- // interpolation takes place across the entirety of the
+ // interpolation takes place accross the entirety of the
// composite configuration. Without doing this each
// configuration object only interpolates variables defined
// inside itself.
@@ -447,6 +398,18 @@ public class ServerConfiguration extends ConfigurationPlugin
return _configFile == null ? "" : _configFile.getAbsolutePath();
}
+ public void handle(Signal arg0)
+ {
+ try
+ {
+ reparseConfigFileSecuritySections();
+ }
+ catch (ConfigurationException e)
+ {
+ _logger.error("Could not reload configuration file security sections", e);
+ }
+ }
+
public void reparseConfigFileSecuritySections() throws ConfigurationException
{
if (_configFile != null)
@@ -490,24 +453,14 @@ public class ServerConfiguration extends ConfigurationPlugin
return System.getProperty(QPID_HOME);
}
- public void setJMXPortRegistryServer(int registryServerPort)
- {
- getConfig().setProperty(MGMT_JMXPORT_REGISTRYSERVER, registryServerPort);
- }
-
- public int getJMXPortRegistryServer()
+ public void setJMXManagementPort(int mport)
{
- return getIntValue(MGMT_JMXPORT_REGISTRYSERVER, DEFAULT_JMXPORT_REGISTRYSERVER);
+ getConfig().setProperty("management.jmxport", mport);
}
- public void setJMXPortConnectorServer(int connectorServerPort)
+ public int getJMXManagementPort()
{
- getConfig().setProperty(MGMT_JMXPORT_CONNECTORSERVER, connectorServerPort);
- }
-
- public int getJMXConnectorServerPort()
- {
- return getIntValue(MGMT_JMXPORT_CONNECTORSERVER, getJMXPortRegistryServer() + JMXPORT_CONNECTORSERVER_OFFSET);
+ return getIntValue("management.jmxport", DEFAULT_JMXPORT);
}
public boolean getUseCustomRMISocketFactory()
@@ -550,11 +503,58 @@ public class ServerConfiguration extends ConfigurationPlugin
_virtualHosts.put(config.getName(), config);
}
+ public List<String> getPrincipalDatabaseNames()
+ {
+ return getListValue("security.principal-databases.principal-database.name");
+ }
+
+ public List<String> getPrincipalDatabaseClass()
+ {
+ return getListValue("security.principal-databases.principal-database.class");
+ }
+
+ public List<String> getPrincipalDatabaseAttributeNames(int index)
+ {
+ String name = "security.principal-databases.principal-database(" + index + ")." + "attributes.attribute.name";
+ return getListValue(name);
+ }
+
+ public List<String> getPrincipalDatabaseAttributeValues(int index)
+ {
+ String name = "security.principal-databases.principal-database(" + index + ")." + "attributes.attribute.value";
+ return getListValue(name);
+ }
+
+ public List<String> getManagementPrincipalDBs()
+ {
+ return getListValue("security.jmx.principal-database");
+ }
+
+ public List<String> getManagementAccessList()
+ {
+ return getListValue("security.jmx.access");
+ }
+
public int getFrameSize()
{
return getIntValue("advanced.framesize", DEFAULT_FRAME_SIZE);
}
+ public boolean getProtectIOEnabled()
+ {
+ return getBooleanValue(CONNECTOR_PROTECTIO_ENABLED, DEFAULT_BROKER_CONNECTOR_PROTECTIO_ENABLED);
+ }
+
+ public int getBufferReadLimit()
+ {
+ return getIntValue(CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE, DEFAULT_BUFFER_READ_LIMIT_SIZE);
+ }
+
+ public int getBufferWriteLimit()
+ {
+ return getIntValue(CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE, DEFAULT_BUFFER_WRITE_LIMIT_SIZE);
+ }
+
public boolean getSynchedClocks()
{
return getBooleanValue("advanced.synced-clocks");
@@ -565,10 +565,14 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("security.msg-auth");
}
+ public String getJMXPrincipalDatabase()
+ {
+ return getStringValue("security.jmx.principal-database");
+ }
+
public String getManagementKeyStorePath()
{
- final String fallback = getStringValue("management.ssl.keystorePath");
- return getStringValue("management.ssl.keyStorePath", fallback);
+ return getStringValue("management.ssl.keyStorePath");
}
public boolean getManagementSSLEnabled()
@@ -578,8 +582,7 @@ public class ServerConfiguration extends ConfigurationPlugin
public String getManagementKeyStorePassword()
{
- final String fallback = getStringValue("management.ssl.keystorePassword");
- return getStringValue("management.ssl.keyStorePassword", fallback);
+ return getStringValue("management.ssl.keyStorePassword");
}
public boolean getQueueAutoRegister()
@@ -647,14 +650,14 @@ public class ServerConfiguration extends ConfigurationPlugin
return getLongValue("flowResumeCapacity", getCapacity());
}
- public int getConnectorProcessors()
+ public int getProcessors()
{
return getIntValue("connector.processors", 4);
}
public List getPorts()
{
- return getListValue("connector.port", Collections.<Integer>singletonList(DEFAULT_PORT));
+ return getListValue("connector.port", Collections.singletonList(DEFAULT_PORT));
}
public List getPortExclude010()
@@ -679,17 +682,17 @@ public class ServerConfiguration extends ConfigurationPlugin
public String getBind()
{
- return getStringValue("connector.bind", WILDCARD_ADDRESS);
+ return getStringValue("connector.bind", "wildcard");
}
public int getReceiveBufferSize()
{
- return getIntValue("connector.socketReceiveBuffer", DEFAULT_BUFFER_SIZE);
+ return getIntValue("connector.socketReceiveBuffer", 32767);
}
public int getWriteBufferSize()
{
- return getIntValue("connector.socketWriteBuffer", DEFAULT_BUFFER_SIZE);
+ return getIntValue("connector.socketWriteBuffer", 32767);
}
public boolean getTcpNoDelay()
@@ -712,28 +715,31 @@ public class ServerConfiguration extends ConfigurationPlugin
return getBooleanValue("connector.ssl.sslOnly");
}
- public List getSSLPorts()
+ public int getSSLPort()
{
- return getListValue("connector.ssl.port", Collections.<Integer>singletonList(DEFAULT_SSL_PORT));
+ return getIntValue("connector.ssl.port", DEFAULT_SSL_PORT);
}
- public String getConnectorKeyStorePath()
+ public String getKeystorePath()
{
- final String fallback = getStringValue("connector.ssl.keystorePath"); // pre-0.13 broker supported this name.
- return getStringValue("connector.ssl.keyStorePath", fallback);
+ return getStringValue("connector.ssl.keystorePath", "none");
}
- public String getConnectorKeyStorePassword()
+ public String getKeystorePassword()
{
- final String fallback = getStringValue("connector.ssl.keystorePassword"); // pre-0.13 brokers supported this name.
- return getStringValue("connector.ssl.keyStorePassword", fallback);
+ return getStringValue("connector.ssl.keystorePassword", "none");
}
- public String getConnectorCertType()
+ public String getCertType()
{
return getStringValue("connector.ssl.certType", "SunX509");
}
+ public boolean getQpidNIO()
+ {
+ return getBooleanValue("connector.qpidnio");
+ }
+
public boolean getUseBiasedWrites()
{
return getBooleanValue("advanced.useWriteBiasedPool");
@@ -749,44 +755,69 @@ public class ServerConfiguration extends ConfigurationPlugin
getConfig().setProperty("virtualhosts.default", vhost);
}
- public void setHousekeepingCheckPeriod(long value)
+ public void setHousekeepingExpiredMessageCheckPeriod(long value)
{
- getConfig().setProperty("housekeeping.checkPeriod", value);
+ getConfig().setProperty("housekeeping.expiredMessageCheckPeriod", value);
}
public long getHousekeepingCheckPeriod()
{
- return getLongValue("housekeeping.checkPeriod", DEFAULT_HOUSEKEEPING_PERIOD);
+ return getLongValue("housekeeping.checkPeriod",
+ getLongValue("housekeeping.expiredMessageCheckPeriod",
+ DEFAULT_HOUSEKEEPING_PERIOD));
}
- public long getStatisticsSamplePeriod()
+ public NetworkDriverConfiguration getNetworkConfiguration()
{
- return getConfig().getLong("statistics.sample.period", 5000L);
- }
+ return new NetworkDriverConfiguration()
+ {
- public boolean isStatisticsGenerationBrokerEnabled()
- {
- return getConfig().getBoolean("statistics.generation.broker", false);
- }
+ public Integer getTrafficClass()
+ {
+ return null;
+ }
- public boolean isStatisticsGenerationVirtualhostsEnabled()
- {
- return getConfig().getBoolean("statistics.generation.virtualhosts", false);
- }
+ public Boolean getTcpNoDelay()
+ {
+ // Can't call parent getTcpNoDelay since it just calls this one
+ return getBooleanValue("connector.tcpNoDelay", true);
+ }
- public boolean isStatisticsGenerationConnectionsEnabled()
- {
- return getConfig().getBoolean("statistics.generation.connections", false);
- }
+ public Integer getSoTimeout()
+ {
+ return null;
+ }
- public long getStatisticsReportingPeriod()
- {
- return getConfig().getLong("statistics.reporting.period", 0L);
- }
+ public Integer getSoLinger()
+ {
+ return null;
+ }
- public boolean isStatisticsReportResetEnabled()
- {
- return getConfig().getBoolean("statistics.reporting.reset", false);
+ public Integer getSendBufferSize()
+ {
+ return getBufferWriteLimit();
+ }
+
+ public Boolean getReuseAddress()
+ {
+ return null;
+ }
+
+ public Integer getReceiveBufferSize()
+ {
+ return getBufferReadLimit();
+ }
+
+ public Boolean getOOBInline()
+ {
+ return null;
+ }
+
+ public Boolean getKeepAlive()
+ {
+ return null;
+ }
+ };
}
public int getMaxChannelCount()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
deleted file mode 100644
index 81dfcb4465..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
+++ /dev/null
@@ -1,75 +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.
- *
- */
-package org.apache.qpid.server.configuration;
-
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-
-public class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration
-{
- private final ServerConfiguration _serverConfig;
- private final int _port;
- private final String _host;
- private final String _transport;
-
- public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
- final int port, final String host,
- final String transport)
- {
- _serverConfig = serverConfig;
- _port = port;
- _host = host;
- _transport = transport;
- }
-
- public Boolean getTcpNoDelay()
- {
- return _serverConfig.getTcpNoDelay();
- }
-
- public Integer getSendBufferSize()
- {
- return _serverConfig.getWriteBufferSize();
- }
-
- public Integer getReceiveBufferSize()
- {
- return _serverConfig.getReceiveBufferSize();
- }
-
- public Integer getPort()
- {
- return _port;
- }
-
- public String getHost()
- {
- return _host;
- }
-
- public String getTransport()
- {
- return _transport;
- }
-
- public Integer getConnectorProcessors()
- {
- return _serverConfig.getConnectorProcessors();
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
index 6729a5ce0f..d9d7083543 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
@@ -86,9 +86,9 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return _name;
}
- public long getHousekeepingCheckPeriod()
+ public long getHousekeepingExpiredMessageCheckPeriod()
{
- return getLongValue("housekeeping.checkPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
+ return getLongValue("housekeeping.expiredMessageCheckPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
}
public String getAuthenticationDatabase()
@@ -306,45 +306,11 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
@Override
public void validateConfiguration() throws ConfigurationException
{
- // QPID-3249. Support for specifying authentication name at vhost level is no longer supported.
- if (getListValue("security.authentication.name").size() > 0)
- {
- String message = "Validation error : security/authentication/name is no longer a supported element within the configuration xml."
- + " It appears in virtual host definition : " + _name;
- throw new ConfigurationException(message);
- }
-
- // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency
- if (contains("housekeeping.expiredMessageCheckPeriod"))
- {
- String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod."
- + " It appears in virtual host definition : " + _name;
- throw new ConfigurationException(message);
- }
+ //Currently doesn't do validation
}
public int getHouseKeepingThreadCount()
{
return getIntValue("housekeeping.poolSize", Runtime.getRuntime().availableProcessors());
}
-
- public long getTransactionTimeoutOpenWarn()
- {
- return getLongValue("transactionTimeout.openWarn", 0L);
- }
-
- public long getTransactionTimeoutOpenClose()
- {
- return getLongValue("transactionTimeout.openClose", 0L);
- }
-
- public long getTransactionTimeoutIdleWarn()
- {
- return getLongValue("transactionTimeout.idleWarn", 0L);
- }
-
- public long getTransactionTimeoutIdleClose()
- {
- return getLongValue("transactionTimeout.idleClose", 0L);
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
index b4f82649b0..82b576ea51 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
@@ -24,7 +24,6 @@ import org.apache.commons.configuration.ConversionException;
import org.apache.log4j.Logger;
import org.apache.qpid.server.configuration.ConfigurationManager;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
import java.util.Collections;
import java.util.HashMap;
@@ -139,28 +138,10 @@ public abstract class ConfigurationPlugin
}
}
- offerRemainingConfigurationToOtherPlugins(path, configuration, elements);
-
- validateConfiguration();
- }
-
- private void offerRemainingConfigurationToOtherPlugins(String path,
- Configuration configuration, Set<String> elements) throws ConfigurationException
- {
- final IApplicationRegistry appRegistry = safeGetApplicationRegistryInstance();
-
- if (appRegistry == null)
- {
- // We see this happen during shutdown due to asynchronous reconfig using IO threads.
- // Need to remove the responsibility for offering configuration to other class.
- _logger.info("Cannot offer remaining config to other plugins, can't find app registry");
- return;
- }
-
- final ConfigurationManager configurationManager = appRegistry.getConfigurationManager();
// Process the elements in the configuration
for (String element : elements)
{
+ ConfigurationManager configurationManager = ApplicationRegistry.getInstance().getConfigurationManager();
Configuration handled = element.length() == 0 ? configuration : configuration.subset(element);
String configurationElement = element;
@@ -181,18 +162,8 @@ public abstract class ConfigurationPlugin
_pluginConfiguration.put(plugin.getClass().getName(), plugin);
}
}
- }
- private IApplicationRegistry safeGetApplicationRegistryInstance()
- {
- try
- {
- return ApplicationRegistry.getInstance();
- }
- catch (IllegalStateException ise)
- {
- return null;
- }
+ validateConfiguration();
}
/** Helper method to print out list of keys in a {@link Configuration}. */
diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
index 1c01ce465d..bac751e0c8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
@@ -20,21 +20,19 @@
*/
package org.apache.qpid.server.connection;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.log4j.Logger;
+import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.protocol.AMQProtocolEngine;
-import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
public class ConnectionRegistry implements IConnectionRegistry, Closeable
{
- private List<AMQConnectionModel> _registry = new CopyOnWriteArrayList<AMQConnectionModel>();
+ private List<AMQProtocolSession> _registry = new CopyOnWriteArrayList<AMQProtocolSession>();
private Logger _logger = Logger.getLogger(ConnectionRegistry.class);
@@ -42,46 +40,44 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
{
// None required
}
-
- /** Close all of the currently open connections. */
- public void close()
+
+ public void expireClosedChannels()
{
- _logger.debug("Closing connection registry :" + _registry.size() + " connections.");
- while (!_registry.isEmpty())
+ for (AMQProtocolSession connection : _registry)
{
- AMQConnectionModel connection = _registry.get(0);
- closeConnection(connection, AMQConstant.CONNECTION_FORCED, "Broker is shutting down");
+ connection.closeIfLingeringClosedChannels();
}
}
- public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message)
+ /** Close all of the currently open connections. */
+ public void close()
{
- try
- {
- connection.close(cause, message);
- }
- catch (TransportException e)
- {
- _logger.warn("Error closing connection:" + e.getMessage());
- }
- catch (AMQException e)
+ while (!_registry.isEmpty())
{
- _logger.warn("Error closing connection:" + e.getMessage());
+ AMQProtocolSession connection = _registry.get(0);
+
+ try
+ {
+ connection.closeConnection(0, new AMQConnectionException(AMQConstant.INTERNAL_ERROR, "Broker is shutting down",
+ 0, 0,
+ connection.getProtocolOutputConverter().getProtocolMajorVersion(),
+ connection.getProtocolOutputConverter().getProtocolMinorVersion(),
+ (Throwable) null), true);
+ }
+ catch (AMQException e)
+ {
+ _logger.warn("Error closing connection:" + e.getMessage());
+ }
}
}
- public void registerConnection(AMQConnectionModel connnection)
+ public void registerConnection(AMQProtocolSession connnection)
{
_registry.add(connnection);
}
- public void deregisterConnection(AMQConnectionModel connnection)
+ public void deregisterConnection(AMQProtocolSession connnection)
{
_registry.remove(connnection);
}
-
- public List<AMQConnectionModel> getConnections()
- {
- return new ArrayList<AMQConnectionModel>(_registry);
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
index b4f5bffa57..002269bbaa 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
@@ -20,23 +20,18 @@
*/
package org.apache.qpid.server.connection;
-import java.util.List;
-
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
public interface IConnectionRegistry
{
+
public void initialise();
public void close() throws AMQException;
-
- public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message);
-
- public List<AMQConnectionModel> getConnections();
- public void registerConnection(AMQConnectionModel connnection);
+ public void registerConnection(AMQProtocolSession connnection);
+
+ public void deregisterConnection(AMQProtocolSession connnection);
- public void deregisterConnection(AMQConnectionModel connnection);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index d693c6962b..d0231e4d80 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -356,7 +356,7 @@ public abstract class AbstractExchange implements Exchange, Managable
_receivedMessageCount.incrementAndGet();
_receivedMessageSize.addAndGet(message.getSize());
final ArrayList<? extends BaseQueue> queues = doRoute(message);
- if(!queues.isEmpty())
+ if(queues != null && !queues.isEmpty())
{
_routedMessageCount.incrementAndGet();
_routedMessageSize.addAndGet(message.getSize());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
index 0f1b709475..7aeff2561e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java
@@ -90,12 +90,12 @@ public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends
public String getObjectInstanceName()
{
- return ObjectName.quote(_exchange.getName());
+ return _exchange.getNameShortString().toString();
}
public String getName()
{
- return _exchange.getName();
+ return _exchange.getNameShortString().toString();
}
public String getExchangeType()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index 29a3611709..356a7f89b9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -30,12 +30,15 @@ import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.message.InboundMessage;
+import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.ExchangeConfig;
import javax.management.JMException;
import java.util.ArrayList;
+import java.util.List;
import java.util.Collection;
+import java.util.concurrent.CopyOnWriteArrayList;
public interface Exchange extends ExchangeReferrer, ExchangeConfig
{
@@ -64,12 +67,7 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
void close() throws AMQException;
- /**
- * Returns a list of queues to which to route this message. If there are
- * no queues the empty list must be returned.
- *
- * @return list of queues to which to route the message.
- */
+
ArrayList<? extends BaseQueue> route(InboundMessage message);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
index d76b163fa1..0e3a3894fe 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
@@ -274,6 +274,132 @@ public class HeadersParser
}
+ public static void main(String[] args) throws AMQFrameDecodingException
+ {
+
+ FieldTable bindingTable = new FieldTable();
+
+ bindingTable.setString(new AMQShortString("x-match"),"all");
+ bindingTable.setInteger("a",1);
+ bindingTable.setVoid(new AMQShortString("b"));
+ bindingTable.setString("c","");
+ bindingTable.setInteger("d",4);
+ bindingTable.setInteger("e",1);
+
+
+
+ FieldTable bindingTable2 = new FieldTable();
+ bindingTable2.setString(new AMQShortString("x-match"),"all");
+ bindingTable2.setInteger("a",1);
+ bindingTable2.setVoid(new AMQShortString("b"));
+ bindingTable2.setString("c","");
+ bindingTable2.setInteger("d",4);
+ bindingTable2.setInteger("e",1);
+ bindingTable2.setInteger("f",1);
+
+
+ FieldTable table = new FieldTable();
+ table.setInteger("a",1);
+ table.setInteger("b",2);
+ table.setString("c","");
+ table.setInteger("d",4);
+ table.setInteger("e",1);
+ table.setInteger("f",1);
+ table.setInteger("h",1);
+ table.setInteger("i",1);
+ table.setInteger("j",1);
+ table.setInteger("k",1);
+ table.setInteger("l",1);
+
+ org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.allocate( (int) table.getEncodedSize());
+ EncodingUtils.writeFieldTableBytes(buffer, table);
+ buffer.flip();
+
+ FieldTable table2 = EncodingUtils.readFieldTable(buffer);
+
+
+
+ FieldTable bindingTable3 = new FieldTable();
+ bindingTable3.setString(new AMQShortString("x-match"),"any");
+ bindingTable3.setInteger("a",1);
+ bindingTable3.setInteger("b",3);
+
+
+ FieldTable bindingTable4 = new FieldTable();
+ bindingTable4.setString(new AMQShortString("x-match"),"any");
+ bindingTable4.setVoid(new AMQShortString("a"));
+
+
+ FieldTable bindingTable5 = new FieldTable();
+ bindingTable5.setString(new AMQShortString("x-match"),"all");
+ bindingTable5.setString(new AMQShortString("h"),"hello");
+
+ for(int i = 0; i < 100; i++)
+ {
+ printMatches(new FieldTable[] {bindingTable5} , table2);
+ }
+
+
+
+ }
+
+
+
+ private static void printMatches(final FieldTable[] bindingKeys, final FieldTable routingKey)
+ {
+ HeadersMatcherDFAState sm = null;
+ Map<HeaderMatcherResult, String> resultMap = new HashMap<HeaderMatcherResult, String>();
+
+ HeadersParser parser = new HeadersParser();
+
+ for(int i = 0; i < bindingKeys.length; i++)
+ {
+ HeaderMatcherResult r = new HeaderMatcherResult();
+ resultMap.put(r, bindingKeys[i].toString());
+
+
+ if(i==0)
+ {
+ sm = parser.createStateMachine(bindingKeys[i], r);
+ }
+ else
+ {
+ sm = sm.mergeStateMachines(parser.createStateMachine(bindingKeys[i], r));
+ }
+ }
+
+ Collection<HeaderMatcherResult> results = null;
+ long beforeTime = System.currentTimeMillis();
+ for(int i = 0; i < 1000000; i++)
+ {
+ routingKey.size();
+
+ assert sm != null;
+ results = sm.match(routingKey);
+
+ }
+ long elapsed = System.currentTimeMillis() - beforeTime;
+ System.out.println("1000000 Iterations took: " + elapsed);
+ Collection<String> resultStrings = new ArrayList<String>();
+
+ assert results != null;
+ for(HeaderMatcherResult result : results)
+ {
+ resultStrings.add(resultMap.get(result));
+ }
+
+ final ArrayList<String> nonMatches = new ArrayList<String>();
+ for(FieldTable key : bindingKeys)
+ {
+ nonMatches.add(key.toString());
+ }
+ nonMatches.removeAll(resultStrings);
+ System.out.println("\""+routingKey+"\" matched with " + resultStrings + " DID NOT MATCH with " + nonMatches);
+
+
+ }
+
+
public final static class KeyValuePair
{
public final HeaderKey _key;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
index 2dff45c326..fbc5387daf 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java
@@ -38,7 +38,6 @@ import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.transport.ServerSession;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -697,7 +696,7 @@ public class Bridge implements BridgeConfig
//TODO Handle the passing of non-null Filters and Arguments here
- Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
+ Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
_destination,
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
@@ -769,7 +768,7 @@ public class Bridge implements BridgeConfig
//TODO Handle the passing of non-null Filters and Arguments here
- Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
+ Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
_destination,
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
index f21158cd0c..fa2fb9ead1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java
@@ -258,6 +258,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener
_remoteFederationTag = UUID.fromString(_transport+":"+_host+":"+_port).toString();
}
_qpidConnection.setSessionFactory(new SessionFactory());
+ _qpidConnection.setAuthorizationID(_username == null ? "" : _username);
updateState(State.ESTABLISHING, State.OPERATIONAL);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
index 9848f90ea9..11fdeae2b1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
@@ -37,8 +37,8 @@ import org.apache.qpid.server.queue.Filterable;
public class PropertyExpression implements Expression
{
// Constants - defined the same as JMS
- private static enum JMSDeliveryMode { NON_PERSISTENT, PERSISTENT }
-
+ private static final int NON_PERSISTENT = 1;
+ private static final int PERSISTENT = 2;
private static final int DEFAULT_PRIORITY = 4;
private static final Logger _logger = org.apache.log4j.Logger.getLogger(PropertyExpression.class);
@@ -172,14 +172,13 @@ public class PropertyExpression implements Expression
{
public Object evaluate(Filterable message)
{
- JMSDeliveryMode mode = message.isPersistent() ? JMSDeliveryMode.PERSISTENT :
- JMSDeliveryMode.NON_PERSISTENT;
+ int mode = message.isPersistent() ? PERSISTENT : NON_PERSISTENT;
if (_logger.isDebugEnabled())
{
_logger.debug("JMSDeliveryMode is :" + mode);
}
- return mode.toString();
+ return mode;
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
index 765dee2878..a5999711bc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
@@ -144,7 +144,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
_logger.debug("Closing connection due to invalid selector");
MethodRegistry methodRegistry = protocolConnection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),
+ AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.INVALID_ARGUMENT.getCode(),
new AMQShortString(ise.getMessage()),
body.getClazz(),
body.getMethod());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
index 14ce85530e..790027f293 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
@@ -162,7 +162,14 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
}
else
{
- sub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(channel, session, null, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod);
+ sub = new GetNoAckSubscription(channel,
+ session,
+ null,
+ null,
+ false,
+ singleMessageCredit,
+ getDeliveryMethod,
+ getRecordMethod);
}
queue.registerSubscription(sub,false);
@@ -173,5 +180,27 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
}
+ public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
+ {
+ public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ }
+ public boolean isTransient()
+ {
+ return true;
+ }
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return !getCreditManager().useCreditForMessage(msg.getMessage());
+ }
+
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
index f8e4eab0b6..dade5d5f54 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
@@ -68,7 +68,5 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co
ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();
session.writeFrame(responseBody.generateFrame(channelId));
- session.closeProtocolSession();
-
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
index 09f35da41d..d4b79134a2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
@@ -20,9 +20,9 @@
*/
package org.apache.qpid.server.handler;
-
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.ConnectionCloseBody;
@@ -68,7 +68,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
}
MethodRegistry methodRegistry = session.getMethodRegistry();
AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
- switch (authResult.getStatus())
+ switch (authResult.status)
{
case ERROR:
Exception cause = authResult.getCause();
@@ -88,10 +88,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
disposeSaslServer(session);
break;
case SUCCESS:
- if (_logger.isInfoEnabled())
- {
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
- }
+ _logger.info("Connected as: " + ss.getAuthorizationID());
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
ConnectionTuneBody tuneBody =
@@ -99,13 +96,13 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ConnectionStartOkMethodHandler.getConfiguredFrameSize(),
ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
session.writeFrame(tuneBody.generateFrame(0));
- session.setAuthorizedSubject(authResult.getSubject());
+ session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
disposeSaslServer(session);
break;
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
- ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+ ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
session.writeFrame(secureBody.generateFrame(0));
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
index 2dd9a63540..4442f969c4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
@@ -65,6 +65,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
_logger.info("Locale selected: " + body.getLocale());
AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
+
SaslServer ss = null;
try
{
@@ -77,7 +78,8 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
session.setSaslServer(ss);
- final AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
+ AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
+
//save clientProperties
if (session.getClientProperties() == null)
{
@@ -86,7 +88,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
MethodRegistry methodRegistry = session.getMethodRegistry();
- switch (authResult.getStatus())
+ switch (authResult.status)
{
case ERROR:
Exception cause = authResult.getCause();
@@ -106,11 +108,8 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
break;
case SUCCESS:
- if (_logger.isInfoEnabled())
- {
- _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
- }
- session.setAuthorizedSubject(authResult.getSubject());
+ _logger.info("Connected as: " + ss.getAuthorizationID());
+ session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
@@ -122,7 +121,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
- ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+ ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
session.writeFrame(secureBody.generateFrame(0));
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
index 0cfed77f2e..8939cfa334 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
@@ -106,7 +106,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
else
{
queue = createQueue(queueName, body, virtualHost, protocolConnection);
- queue.setAuthorizationHolder(protocolConnection);
+ queue.setPrincipalHolder(protocolConnection);
if (queue.isDurable() && !queue.isAutoDelete())
{
store.createQueue(queue, body.getArguments());
@@ -119,7 +119,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
if (body.getExclusive())
{
queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId));
- queue.setAuthorizationHolder(protocolConnection);
+ queue.setPrincipalHolder(protocolConnection);
if(!body.getDurable())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java b/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java
index 5e6a143d52..db2cc970b2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java
@@ -22,11 +22,9 @@ package org.apache.qpid.server.information.management;
import java.io.IOException;
-import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.management.common.mbeans.ServerInformation;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.registry.ApplicationRegistry;
import javax.management.JMException;
@@ -36,15 +34,12 @@ public class ServerInformationMBean extends AMQManagedObject implements ServerIn
{
private String buildVersion;
private String productVersion;
- private ApplicationRegistry registry;
- public ServerInformationMBean(ApplicationRegistry applicationRegistry) throws JMException
+ public ServerInformationMBean(String buildVersion, String productVersion) throws JMException
{
super(ServerInformation.class, ServerInformation.TYPE);
-
- registry = applicationRegistry;
- buildVersion = QpidProperties.getBuildVersion();
- productVersion = QpidProperties.getReleaseVersion();
+ this.buildVersion = buildVersion;
+ this.productVersion = productVersion;
}
public String getObjectInstanceName()
@@ -72,75 +67,5 @@ public class ServerInformationMBean extends AMQManagedObject implements ServerIn
return productVersion;
}
-
- public void resetStatistics() throws Exception
- {
- registry.resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return registry.getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return registry.getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return registry.getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return registry.getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return registry.getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return registry.getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return registry.getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return registry.getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return registry.getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return registry.getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return registry.getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return registry.getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return registry.isStatisticsEnabled();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
index 286fc78719..2825fa1b75 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
@@ -20,15 +20,11 @@
*/
package org.apache.qpid.server.logging.actors;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.RootMessageLogger;
-import java.security.AccessController;
-import java.security.Principal;
import java.text.MessageFormat;
-import java.util.Set;
-
-import javax.management.remote.JMXPrincipal;
-import javax.security.auth.Subject;
/**
* NOTE: This actor is not thread safe.
@@ -44,23 +40,16 @@ import javax.security.auth.Subject;
*/
public class ManagementActor extends AbstractActor
{
- /**
- * Holds the principal name to display when principal subject is not available.
- * <p>
- * This is useful for cases when users invoke JMX operation over JConsole
- * attached to the local JVM.
- */
- private static final String UNKNOWN_PRINCIPAL = "N/A";
-
String _lastThreadName = null;
/**
* LOG FORMAT for the ManagementActor,
- * Uses a MessageFormat call to insert the required values according to
- * these indices:
+ * Uses a MessageFormat call to insert the requried values according to
+ * these indicies:
*
- * 0 - User ID
- * 1 - IP
+ * 0 - Connection ID
+ * 1 - User ID
+ * 2 - IP
*/
public static final String MANAGEMENT_FORMAT = "mng:{0}({1})";
@@ -86,20 +75,19 @@ public class ManagementActor extends AbstractActor
_lastThreadName = currentName;
// Management Thread names have this format.
- // RMI TCP Connection(2)-169.24.29.116
+ //RMI TCP Connection(2)-169.24.29.116
// This is true for both LocalAPI and JMX Connections
// However to be defensive lets test.
String[] split = currentName.split("\\(");
if (split.length == 2)
{
+ String connectionID = split[1].split("\\)")[0];
String ip = currentName.split("-")[1];
- String principalName = getPrincipalName();
- if (principalName == null)
- {
- principalName = UNKNOWN_PRINCIPAL;
- }
- actor = MessageFormat.format(MANAGEMENT_FORMAT, principalName, ip);
+
+ actor = MessageFormat.format(MANAGEMENT_FORMAT,
+ connectionID,
+ ip);
}
else
{
@@ -117,30 +105,6 @@ public class ManagementActor extends AbstractActor
}
}
- /**
- * Returns current JMX principal name.
- *
- * @return principal name or null if principal can not be found
- */
- protected String getPrincipalName()
- {
- String identity = null;
-
- // retrieve Subject from current AccessControlContext
- final Subject subject = Subject.getSubject(AccessController.getContext());
- if (subject != null)
- {
- // retrieve JMXPrincipal from Subject
- final Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
- if (principals != null && !principals.isEmpty())
- {
- final Principal principal = principals.iterator().next();
- identity = principal.getName();
- }
- }
- return identity;
- }
-
public String getLogMessage()
{
updateLogString();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
index 5d1e85fe41..6b83a7e7a5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
@@ -32,7 +32,4 @@ STOPPED = BRK-1005 : Stopped
# 0 - path
CONFIG = BRK-1006 : Using configuration : {0}
# 0 - path
-LOG_CONFIG = BRK-1007 : Using logging configuration : {0}
-
-STATS_DATA = BRK-1008 : {0,choice,0#delivered|1#received} : {1,number,#.###} kB/s peak : {2,number,#} bytes total
-STATS_MSGS = BRK-1009 : {0,choice,0#delivered|1#received} : {1,number,#.###} msg/s peak : {2,number,#} msgs total \ No newline at end of file
+LOG_CONFIG = BRK-1007 : Using logging configuration : {0} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
index ed8c0d0ce9..53bcd712f2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
@@ -28,7 +28,3 @@ PREFETCH_SIZE = CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number}
# 0 - queue causing flow control
FLOW_ENFORCED = CHN-1005 : Flow Control Enforced (Queue {0})
FLOW_REMOVED = CHN-1006 : Flow Control Removed
-# Channel Transactions
-# 0 - time in milliseconds
-OPEN_TXN = CHN-1007 : Open Transaction : {0,number} ms
-IDLE_TXN = CHN-1008 : Idle Transaction : {0,number} ms
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
index b25a6a7301..b9890d9f27 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
@@ -21,5 +21,4 @@
# 0 - type
# 1 - name
CREATED = EXH-1001 : Create :[ Durable] Type: {0} Name: {1}
-DELETED = EXH-1002 : Deleted
-DISCARDMSG = EXH-1003 : Discarded Message : Name: {0} Routing Key: {1}
+DELETED = EXH-1002 : Deleted \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
index ac77f674f2..ab77476da2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
@@ -30,4 +30,4 @@ STOPPED = MNG-1005 : Stopped
# 0 - Path
SSL_KEYSTORE = MNG-1006 : Using SSL Keystore : {0}
OPEN = MNG-1007 : Open : User {0}
-CLOSE = MNG-1008 : Close : User {0} \ No newline at end of file
+CLOSE = MNG-1008 : Close \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties
index 3e640c7929..66bbefacb0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties
@@ -20,7 +20,4 @@
#
# 0 - name
CREATED = VHT-1001 : Created : {0}
-CLOSED = VHT-1002 : Closed
-
-STATS_DATA = VHT-1003 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} kB/s peak : {3,number,#} bytes total
-STATS_MSGS = VHT-1004 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} msg/s peak : {3,number,#} msgs total` \ No newline at end of file
+CLOSED = VHT-1002 : Closed \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
index 9b357403a8..f28873940b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
@@ -47,7 +47,7 @@ public class ChannelLogSubject extends AbstractLogSubject
*/
setLogStringWithFormat(CHANNEL_FORMAT,
session.getSessionID(),
- session.getAuthorizedPrincipal().getName(),
+ session.getPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName(),
channel.getChannelId());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
index c1c836f9b4..a697029d24 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
@@ -56,7 +56,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
{
if (!_upToDate)
{
- if (_session.getAuthorizedPrincipal() != null)
+ if (_session.getPrincipal() != null)
{
if (_session.getVirtualHost() != null)
{
@@ -72,7 +72,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
*/
_logString = "[" + MessageFormat.format(CONNECTION_FORMAT,
_session.getSessionID(),
- _session.getAuthorizedPrincipal().getName(),
+ _session.getPrincipal().getName(),
_session.getRemoteAddress(),
_session.getVirtualHost().getName())
+ "] ";
@@ -83,7 +83,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
{
_logString = "[" + MessageFormat.format(USER_FORMAT,
_session.getSessionID(),
- _session.getAuthorizedPrincipal().getName(),
+ _session.getPrincipal().getName(),
_session.getRemoteAddress())
+ "] ";
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
index e44b8c41cb..0a739af695 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java
@@ -26,9 +26,8 @@ import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;
-import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
/**
* Provides implementation of the boilerplate ManagedObject interface. Most managed objects should find it useful
@@ -37,14 +36,10 @@ import org.apache.qpid.server.registry.IApplicationRegistry;
*/
public abstract class DefaultManagedObject extends StandardMBean implements ManagedObject
{
- private static final Logger LOGGER = Logger.getLogger(ApplicationRegistry.class);
-
private Class<?> _managementInterface;
private String _typeName;
- private ManagedObjectRegistry _registry;
-
protected DefaultManagedObject(Class<?> managementInterface, String typeName)
throws NotCompliantMBeanException
{
@@ -70,26 +65,23 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
public void register() throws JMException
{
- _registry = ApplicationRegistry.getInstance().getManagedObjectRegistry();
- _registry.registerObject(this);
+ getManagedObjectRegistry().registerObject(this);
}
- public void unregister()
+ protected ManagedObjectRegistry getManagedObjectRegistry()
+ {
+ return ApplicationRegistry.getInstance().getManagedObjectRegistry();
+ }
+
+ public void unregister() throws AMQException
{
try
{
- if(_registry != null)
- {
- _registry.unregisterObject(this);
- }
+ getManagedObjectRegistry().unregisterObject(this);
}
catch (JMException e)
{
- LOGGER.error("Error unregistering managed object: " + this + ": " + e, e);
- }
- finally
- {
- _registry = null;
+ throw new AMQException("Error unregistering managed object: " + this + ": " + e, e);
}
}
@@ -161,4 +153,32 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
return "";
}
+ protected static StringBuffer jmxEncode(StringBuffer jmxName, int attrPos)
+ {
+ for (int i = attrPos; i < jmxName.length(); i++)
+ {
+ if (jmxName.charAt(i) == ',')
+ {
+ jmxName.setCharAt(i, ';');
+ }
+ else if (jmxName.charAt(i) == ':')
+ {
+ jmxName.setCharAt(i, '-');
+ }
+ else if (jmxName.charAt(i) == '?' ||
+ jmxName.charAt(i) == '*' ||
+ jmxName.charAt(i) == '\\')
+ {
+ jmxName.insert(i, '\\');
+ i++;
+ }
+ else if (jmxName.charAt(i) == '\n')
+ {
+ jmxName.insert(i, '\\');
+ i++;
+ jmxName.setCharAt(i, 'n');
+ }
+ }
+ return jmxName;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
index b44964f176..0334a856c1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
@@ -20,6 +20,32 @@
*/
package org.apache.qpid.server.management;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import javax.management.NotificationListener;
+import javax.management.NotificationFilterSupport;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServerImpl;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -38,31 +64,7 @@ import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
-
-import javax.management.JMException;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
-import javax.management.NotificationFilterSupport;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.rmi.RMIConnectorServer;
-import javax.management.remote.rmi.RMIJRMPServerImpl;
-import javax.management.remote.rmi.RMIServerImpl;
-import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.rmi.ssl.SslRMIServerSocketFactory;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
+import java.util.Map;
/**
* This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
@@ -72,14 +74,15 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
+ public static final String MANAGEMENT_PORT_CONFIG_PATH = "management.jmxport";
+ public static final int MANAGEMENT_PORT_DEFAULT = 8999;
+ public static final int PORT_EXPORT_OFFSET = 100;
+
private final MBeanServer _mbeanServer;
private JMXConnectorServer _cs;
private Registry _rmiRegistry;
private boolean _useCustomSocketFactory;
- private final int _jmxPortRegistryServer;
- private final int _jmxPortConnectorServer;
-
public JMXManagedObjectRegistry() throws AMQException
{
_log.info("Initialising managed object registry using platform MBean server");
@@ -92,12 +95,9 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_mbeanServer =
platformServer ? ManagementFactory.getPlatformMBeanServer()
: MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN);
-
- _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer();
- _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort();
-
}
+
public void start() throws IOException, ConfigurationException
{
@@ -111,7 +111,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+ int port = appRegistry.getConfiguration().getJMXManagementPort();
+ //retrieve the Principal Database assigned to JMX authentication duties
+ String jmxDatabaseName = appRegistry.getConfiguration().getJMXPrincipalDatabase();
+ Map<String, PrincipalDatabase> map = appRegistry.getDatabaseManager().getDatabases();
+ PrincipalDatabase db = map.get(jmxDatabaseName);
+
+ HashMap<String,Object> env = new HashMap<String,Object>();
//Socket factories for the RMIConnectorServer, either default or SLL depending on configuration
RMIClientSocketFactory csf;
@@ -193,8 +200,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
//add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator();
- rmipa.setAuthenticationManager(appRegistry.getAuthenticationManager());
- HashMap<String,Object> env = new HashMap<String,Object>();
+ rmipa.setPrincipalDatabase(db);
env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
/*
@@ -205,14 +211,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
System.setProperty("java.rmi.server.randomIDs", "true");
if(_useCustomSocketFactory)
{
- _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
+ _rmiRegistry = LocateRegistry.createRegistry(port, null, new CustomRMIServerSocketFactory());
}
else
{
- _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
+ _rmiRegistry = LocateRegistry.createRegistry(port, null, null);
}
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", port));
/*
* We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
@@ -223,7 +229,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer
* on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's.
*/
- final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env);
+ final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env);
String localHost;
try
{
@@ -235,9 +241,9 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
final String hostname = localHost;
final JMXServiceURL externalUrl = new JMXServiceURL(
- "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi");
+ "service:jmx:rmi://"+hostname+":"+(port+PORT_EXPORT_OFFSET)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi");
- final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
+ final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, port+PORT_EXPORT_OFFSET);
_cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
{
@Override
@@ -306,7 +312,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_cs.start();
String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer));
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, port + PORT_EXPORT_OFFSET));
CurrentActor.get().message(ManagementConsoleMessages.READY(false));
}
@@ -401,7 +407,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
if (_rmiRegistry != null)
{
// Stopping the RMI registry
- CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
+ CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _cs.getAddress().getPort() - PORT_EXPORT_OFFSET));
try
{
UnicastRemoteObject.unexportObject(_rmiRegistry, false);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
index 169195304c..964b5ed5a0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
@@ -26,6 +26,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
+import java.security.Principal;
+import java.util.Properties;
import java.util.Set;
import javax.management.Attribute;
@@ -42,6 +44,7 @@ import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -49,15 +52,20 @@ import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
/**
- * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates
- * JMX access decisions to the SecurityPlugin.
+ * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. This implements
+ * the logic for allowing the users to invoke MBean operations and implements the restrictions for readOnly, readWrite
+ * and admin users.
*/
public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener
{
private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class);
+ public final static String ADMIN = "admin";
+ public final static String READWRITE = "readwrite";
+ public final static String READONLY = "readonly";
private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
private MBeanServer _mbs;
+ private static Properties _userRoles = new Properties();
private static ManagementActor _logActor;
public static MBeanServerForwarder newProxyInstance()
@@ -129,13 +137,14 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
if (principals == null || principals.isEmpty())
{
- throw new SecurityException("Access denied: no JMX principal");
+ throw new SecurityException("Access denied: no principal");
}
-
- // Save the subject
- SecurityManager.setThreadSubject(subject);
-
- // Get the component, type and impact, which may be null
+
+ // Save the principal
+ Principal principal = principals.iterator().next();
+ SecurityManager.setThreadPrincipal(principal);
+
+ // Get the component, type and impact, which may be null
String type = getType(method, args);
String vhost = getVirtualHost(method, args);
int impact = getImpact(method, args);
@@ -204,20 +213,6 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
ObjectName object = (ObjectName) args[0];
String vhost = object.getKeyProperty("VirtualHost");
- if(vhost != null)
- {
- try
- {
- //if the name is quoted in the ObjectName, unquote it
- vhost = ObjectName.unquote(vhost);
- }
- catch(IllegalArgumentException e)
- {
- //ignore, this just means the name is not quoted
- //and can be left unchanged
- }
- }
-
return vhost;
}
return null;
@@ -277,7 +272,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
catch (JMException ex)
{
- _logger.error("Unable to determine mbean impact for method : " + mbeanMethod, ex);
+ ex.printStackTrace();
}
}
@@ -313,7 +308,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
else if (notification.getType().equals(JMXConnectionNotification.CLOSED) ||
notification.getType().equals(JMXConnectionNotification.FAILED))
{
- _logActor.message(ManagementConsoleMessages.CLOSE(user));
+ _logActor.message(ManagementConsoleMessages.CLOSE());
}
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
index 84a1642578..194835ac02 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java
@@ -37,7 +37,7 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
private BasicContentHeaderProperties getProperties()
{
- return (BasicContentHeaderProperties) _contentHeaderBody.getProperties();
+ return (BasicContentHeaderProperties) _contentHeaderBody.properties;
}
public String getCorrelationId()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
index 5992e42fb7..30bea7b6e6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java
@@ -29,10 +29,7 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.store.StorableMessageMetaData;
import org.apache.qpid.server.store.MessageMetaDataType;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.util.ByteBufferInputStream;
-import org.apache.qpid.server.util.ByteBufferOutputStream;
-import java.io.*;
import java.nio.ByteBuffer;
import java.util.Set;
@@ -123,38 +120,38 @@ public class MessageMetaData implements StorableMessageMetaData
return size;
}
-
public int writeToBuffer(int offset, ByteBuffer dest)
{
- int oldPosition = dest.position();
- try
+ ByteBuffer src = ByteBuffer.allocate((int)getStorableSize());
+
+ org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(src);
+ EncodingUtils.writeInteger(minaSrc, _contentHeaderBody.getSize());
+ _contentHeaderBody.writePayload(minaSrc);
+ EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getExchange());
+ EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getRoutingKey());
+ byte flags = 0;
+ if(_messagePublishInfo.isMandatory())
{
-
- DataOutputStream dataOutputStream = new DataOutputStream(new ByteBufferOutputStream(dest));
- EncodingUtils.writeInteger(dataOutputStream, _contentHeaderBody.getSize());
- _contentHeaderBody.writePayload(dataOutputStream);
- EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getExchange());
- EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getRoutingKey());
- byte flags = 0;
- if(_messagePublishInfo.isMandatory())
- {
- flags |= MANDATORY_FLAG;
- }
- if(_messagePublishInfo.isImmediate())
- {
- flags |= IMMEDIATE_FLAG;
- }
- dest.put(flags);
- dest.putLong(_arrivalTime);
-
+ flags |= MANDATORY_FLAG;
}
- catch (IOException e)
+ if(_messagePublishInfo.isImmediate())
{
- // This shouldn't happen as we are not actually using anything that can throw an IO Exception
- throw new RuntimeException(e);
+ flags |= IMMEDIATE_FLAG;
}
+ EncodingUtils.writeByte(minaSrc, flags);
+ EncodingUtils.writeLong(minaSrc,_arrivalTime);
+ src.position(minaSrc.position());
+ src.flip();
+ src.position(offset);
+ src = src.slice();
+ if(dest.remaining() < src.limit())
+ {
+ src.limit(dest.remaining());
+ }
+ dest.put(src);
+
- return dest.position()-oldPosition;
+ return src.limit();
}
public int getContentSize()
@@ -164,7 +161,7 @@ public class MessageMetaData implements StorableMessageMetaData
public boolean isPersistent()
{
- BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.getProperties());
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties);
return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT;
}
@@ -176,15 +173,14 @@ public class MessageMetaData implements StorableMessageMetaData
{
try
{
- ByteBufferInputStream bbis = new ByteBufferInputStream(buf);
- DataInputStream dais = new DataInputStream(bbis);
- int size = EncodingUtils.readInteger(dais);
- ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(dais, size);
- final AMQShortString exchange = EncodingUtils.readAMQShortString(dais);
- final AMQShortString routingKey = EncodingUtils.readAMQShortString(dais);
+ org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(buf);
+ int size = EncodingUtils.readInteger(minaSrc);
+ ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(minaSrc, size);
+ final AMQShortString exchange = EncodingUtils.readAMQShortString(minaSrc);
+ final AMQShortString routingKey = EncodingUtils.readAMQShortString(minaSrc);
- final byte flags = EncodingUtils.readByte(dais);
- long arrivalTime = EncodingUtils.readLong(dais);
+ final byte flags = EncodingUtils.readByte(minaSrc);
+ long arrivalTime = EncodingUtils.readLong(minaSrc);
MessagePublishInfo publishBody =
new MessagePublishInfo()
@@ -220,10 +216,6 @@ public class MessageMetaData implements StorableMessageMetaData
{
throw new RuntimeException(e);
}
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
}
};
@@ -237,7 +229,7 @@ public class MessageMetaData implements StorableMessageMetaData
{
private BasicContentHeaderProperties getProperties()
{
- return (BasicContentHeaderProperties) getContentHeaderBody().getProperties();
+ return (BasicContentHeaderProperties) getContentHeaderBody().properties;
}
public String getCorrelationId()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
index 2297e4200d..cf8ae2166c 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
@@ -34,7 +34,7 @@ import org.apache.qpid.transport.codec.BBDecoder;
import java.nio.ByteBuffer;
import java.lang.ref.SoftReference;
-public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMessage
+public class MessageMetaData_0_10 implements StorableMessageMetaData
{
private Header _header;
private DeliveryProperties _deliveryProps;
@@ -194,12 +194,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes
return _deliveryProps == null ? 0L : _deliveryProps.getExpiration();
}
- public boolean isRedelivered()
- {
- // The *Message* is never redelivered, only queue entries are...
- return false;
- }
-
public long getArrivalTime()
{
return _arrivalTime;
@@ -245,6 +239,4 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes
}
}
-
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
index 3970e5a2d4..2cebec373e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
@@ -26,7 +26,6 @@
*/
package org.apache.qpid.server.output.amqp0_8;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
@@ -35,18 +34,22 @@ import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.message.MessageContentSource;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import java.nio.ByteBuffer;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ private static final ProtocolVersionMethodConverter PROTOCOL_CONVERTER =
+ METHOD_REGISTRY.getProtocolVersionMethodConverter();
+
public static Factory getInstanceFactory()
{
return new Factory()
@@ -59,7 +62,6 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
};
}
-
private final AMQProtocolSession _protocolSession;
private ProtocolOutputConverterImpl(AMQProtocolSession session)
@@ -76,11 +78,10 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag);
- writeMessageDelivery(entry, channelId, deliverBody);
+ AMQDataBlock deliver = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
}
-
private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
throws AMQException
{
@@ -92,120 +93,65 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
- ContentHeaderBody chb = new ContentHeaderBody(props, org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl.CLASS_ID);
- chb.bodySize = message.getSize();
+ ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
return chb;
}
}
- private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody)
- throws AMQException
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
{
- writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody);
+ AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
}
- private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody)
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody chb, int channelId, AMQDataBlock deliver)
throws AMQException
{
- int bodySize = (int) message.getSize();
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, chb);
+
+ final int bodySize = (int) message.getSize();
if(bodySize == 0)
{
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
writeFrame(compositeBlock);
}
else
{
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ ByteBuffer buf = ByteBuffer.allocate(capacity);
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
-
- int writtenSize = capacity;
-
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
+ int writtenSize = 0;
- CompositeAMQBodyBlock
- compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
writeFrame(compositeBlock);
while(writtenSize < bodySize)
{
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
-
- writeFrame(new AMQFrame(channelId, body));
+ buf = java.nio.ByteBuffer.allocate(capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
}
- }
- }
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
}
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
}
- public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
- AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
- writeMessageDelivery(entry, channelId, deliver);
- }
-
-
- private AMQBody createEncodedDeliverBody(QueueEntry entry,
- final long deliveryTag,
- final AMQShortString consumerTag)
+ private AMQDataBlock createEncodedDeliverFrame(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
-
final AMQShortString exchangeName;
final AMQShortString routingKey;
@@ -226,58 +172,21 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
final boolean isRedelivered = entry.isRedelivered();
- final AMQBody returnBlock = new AMQBody()
- {
-
- public AMQBody _underlyingBody;
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- isRedelivered,
- exchangeName,
- routingKey);
+ BasicDeliverBody deliverBody =
+ METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ isRedelivered,
+ exchangeName,
+ routingKey);
+ AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
+ return deliverFrame;
}
- private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
+ private AMQDataBlock createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
throws AMQException
{
final AMQShortString exchangeName;
@@ -306,8 +215,9 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
exchangeName,
routingKey,
queueSize);
+ AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
- return getOkBody;
+ return getOkFrame;
}
public byte getProtocolMinorVersion()
@@ -320,28 +230,31 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return getProtocolSession().getProtocolMajorVersion();
}
- private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
- int replyCode,
- AMQShortString replyText) throws AMQException
+ private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
{
-
BasicReturnBody basicReturnBody =
METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- messagePublishInfo.getExchange(),
- messagePublishInfo.getRoutingKey());
+ replyText,
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
+ AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
-
- return basicReturnBody;
+ return returnFrame;
}
- public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo,
+ ContentHeaderBody header,
+ MessageContentSource content,
+ int channelId,
+ int replyCode,
+ AMQShortString replyText)
throws AMQException
{
- AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
+ AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
+
+ writeMessageDelivery(content, header, channelId, returnFrame);
- writeMessageDelivery(message, header, channelId, returnFrame);
}
@@ -353,68 +266,8 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
{
-
BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
writeFrame(basicCancelOkBody.generateFrame(channelId));
}
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
index aef3483282..319b5cc7bd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
@@ -20,6 +20,9 @@ package org.apache.qpid.server.output.amqp0_9;
*
*/
+
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -35,13 +38,11 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
+ private static final ProtocolVersionMethodConverter
+ PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
@@ -120,12 +121,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
- int writtenSize = capacity;
+ int writtenSize = 0;
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
CompositeAMQBodyBlock
compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
@@ -133,55 +137,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
while(writtenSize < bodySize)
{
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
+ buf = java.nio.ByteBuffer.allocate(capacity);
- writeFrame(new AMQFrame(channelId, body));
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
}
}
}
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
-
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
@@ -257,7 +221,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _underlyingBody.getSize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
if(_underlyingBody == null)
{
@@ -382,7 +346,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
}
@@ -410,7 +374,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
index 10748298bc..cffbe445ee 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
@@ -20,6 +20,9 @@ package org.apache.qpid.server.output.amqp0_9_1;
*
*/
+
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -30,16 +33,17 @@ import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_0_91.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91);
+ private static final ProtocolVersionMethodConverter
+ PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
+
public static Factory getInstanceFactory()
{
@@ -117,11 +121,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
- int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
- int writtenSize = capacity;
+ int writtenSize = 0;
- AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
+
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
CompositeAMQBodyBlock
compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
@@ -129,54 +137,15 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
while(writtenSize < bodySize)
{
- capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
- MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
- writtenSize += capacity;
+ buf = java.nio.ByteBuffer.allocate(capacity);
- writeFrame(new AMQFrame(channelId, body));
+ writtenSize += message.getContent(buf, writtenSize);
+ buf.flip();
+ writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
}
}
}
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private int _length;
- private MessageContentSource _message;
- private int _offset;
-
- public MessageContentSourceBody(MessageContentSource message, int offset, int length)
- {
- _message = message;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- public void writePayload(DataOutputStream buffer) throws IOException
- {
- byte[] data = new byte[_length];
-
- _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
-
- buffer.write(data);
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
- {
- throw new UnsupportedOperationException();
- }
- }
-
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
@@ -252,7 +221,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _underlyingBody.getSize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
if(_underlyingBody == null)
{
@@ -377,7 +346,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
}
@@ -405,7 +374,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java
deleted file mode 100644
index 644f714c8c..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java
+++ /dev/null
@@ -1,91 +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.
- */
-package org.apache.qpid.server.plugins;
-
-import java.util.Iterator;
-import java.util.Map;
-
-import org.osgi.framework.Version;
-
-/**
- * Utility class to convert a map of package name to version numbers into the string
- * with the format expected of a OSGi system package declaration:
- *
- * <code>
- * org.xyz; version=1.0.0, org.xyz.xyz; version=1.0.0,...
- * </code>
- *
- * Additionally, if the caller has provided a qpidPackageReleaseNumber and the package
- * begins org.apache.qpid, this release number will be used, in preference to the one
- * found in the Map.
- *
- * @see org.osgi.framework.Constants#FRAMEWORK_SYSTEMPACKAGES
- *
- */
-public class OsgiSystemPackageUtil
-{
- private static final String APACHE_QPID_PKG_PREFIX = "org.apache.qpid";
-
- private final Map<String, String> _packageNameVersionMap;
- private final Version _qpidPackageReleaseNumber;
-
- public OsgiSystemPackageUtil(final Version qpidPackageReleaseNumber, final Map<String, String> packageNameVersionMap)
- {
- _qpidPackageReleaseNumber = qpidPackageReleaseNumber;
- _packageNameVersionMap = packageNameVersionMap;
- }
-
- public String getFormattedSystemPackageString()
- {
- if (_packageNameVersionMap == null || _packageNameVersionMap.size() == 0)
- {
- return null;
- }
-
- final StringBuilder packages = new StringBuilder();
-
- for(Iterator<String> itr = _packageNameVersionMap.keySet().iterator(); itr.hasNext();)
- {
- final String packageName = itr.next();
- final String packageVersion;
-
- if (_qpidPackageReleaseNumber != null && packageName.startsWith(APACHE_QPID_PKG_PREFIX))
- {
- packageVersion = _qpidPackageReleaseNumber.toString();
- }
- else
- {
- packageVersion = _packageNameVersionMap.get(packageName);
- }
-
- packages.append(packageName);
- packages.append("; ");
- packages.append("version=");
- packages.append(packageVersion);
-
- if (itr.hasNext())
- {
- packages.append(", ");
- }
- }
-
- return packages.toString();
- }
-
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
deleted file mode 100644
index aaab4f76cc..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
+++ /dev/null
@@ -1,93 +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.
-#
-
-#
-# OSGi framework system package list
-#
-# PluginManager uses these properties to construct the FRAMEWORK_SYSTEMPACKAGES list
-#
-
-# Format is:
-# <package>=<version>
-# and PluginManager will convert this into:
-# <package>; version=<version>
-# e.g. org.osgi.framework; version=1.3.0
-
-javax.management.openmbean=1.0.0
-javax.management=1.0.0
-
-javax.security.auth=1.0.0
-javax.security.auth.callback=1.0.0
-javax.security.sasl=1.0.0
-javax.security=1.0.0
-
-org.xml.sax=1.0.0
-org.xml.sax.helpers=1.0.0
-
-org.osgi.framework=1.3.0
-org.osgi.service.packageadmin=1.2.0
-org.osgi.service.startlevel=1.0.0
-org.osgi.service.url=1.0.0
-org.osgi.util.tracker=1.0.0
-
-org.apache.commons.configuration=1.0.0
-
-org.apache.commons.lang=1.0.0
-org.apache.commons.lang.builder=1.0.0
-org.apache.commons.logging=1.0.0
-
-org.apache.log4j=1.2.12
-
-org.slf4j=1.6.1
-
-# For Qpid packages (org.apache.qpid), the version number is automatically overridden by QpidPropertis#getReleaseVersion()
-
-org.apache.qpid.junit.extensions.util=0.0.0
-org.apache.qpid=0.0.0
-org.apache.qpid.common=0.0.0
-org.apache.qpid.exchange=0.0.0
-org.apache.qpid.framing=0.0.0
-org.apache.qpid.management.common.mbeans.annotations=0.0.0
-org.apache.qpid.protocol=0.0.0
-org.apache.qpid.transport=0.0.0
-org.apache.qpid.transport.codec=0.0.0
-org.apache.qpid.server.binding=0.0.0
-org.apache.qpid.server.configuration=0.0.0
-org.apache.qpid.server.configuration.plugins=0.0.0
-org.apache.qpid.server.configuration.management=0.0.0
-org.apache.qpid.server.exchange=0.0.0
-org.apache.qpid.server.logging=0.0.0
-org.apache.qpid.server.logging.actors=0.0.0
-org.apache.qpid.server.logging.subjects=0.0.0
-org.apache.qpid.server.management=0.0.0
-org.apache.qpid.server.persistent=0.0.0
-org.apache.qpid.server.plugins=0.0.0
-org.apache.qpid.server.protocol=0.0.0
-org.apache.qpid.server.queue=0.0.0
-org.apache.qpid.server.registry=0.0.0
-org.apache.qpid.server.security=0.0.0
-org.apache.qpid.server.security.access=0.0.0
-org.apache.qpid.server.security.access.plugins=0.0.0
-org.apache.qpid.server.security.auth=0.0.0
-org.apache.qpid.server.security.auth.sasl=0.0.0
-org.apache.qpid.server.security.auth.manager=0.0.0
-org.apache.qpid.server.virtualhost=0.0.0
-org.apache.qpid.server.virtualhost.plugins=0.0.0
-org.apache.qpid.util=0.0.0
-
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
index 804a9d5027..e7f9983fff 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
@@ -27,5 +27,5 @@ public interface Plugin
/**
* Provide Configuration to this plugin
*/
- public void configure(ConfigurationPlugin config) throws ConfigurationException;
+ public void configure(ConfigurationPlugin config);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
index dab6c3b231..a6bab017a1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
@@ -18,56 +18,39 @@
*/
package org.apache.qpid.server.plugins;
-import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP;
-import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY;
-import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_DIR_PROPERY;
-import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_INSTALL_VALUE;
-import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_START_VALUE;
-import static org.apache.felix.main.AutoProcessor.process;
-import static org.osgi.framework.Constants.FRAMEWORK_STORAGE;
-import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN;
-import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
-import static org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES;
+import static org.apache.felix.framework.util.FelixConstants.*;
+import static org.apache.felix.main.AutoProcessor.*;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.felix.framework.Felix;
import org.apache.felix.framework.util.StringMap;
import org.apache.log4j.Logger;
import org.apache.qpid.common.Closeable;
-import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.server.configuration.TopicConfiguration;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionConfiguration.SlowConsumerDetectionConfigurationFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionPolicyConfiguration.SlowConsumerDetectionPolicyConfigurationFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration.SlowConsumerDetectionQueueConfigurationFactory;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
import org.apache.qpid.server.exchange.ExchangeType;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.SecurityPluginFactory;
import org.apache.qpid.server.security.access.plugins.AllowAll;
import org.apache.qpid.server.security.access.plugins.DenyAll;
import org.apache.qpid.server.security.access.plugins.LegacyAccess;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
-import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
-import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection;
import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
+import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection;
import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy;
import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory;
-import org.apache.qpid.util.FileUtils;
import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
import org.osgi.framework.launch.Framework;
import org.osgi.util.tracker.ServiceTracker;
@@ -80,6 +63,7 @@ public class PluginManager implements Closeable
private static final Logger _logger = Logger.getLogger(PluginManager.class);
private static final int FELIX_STOP_TIMEOUT = 30000;
+ private static final String QPID_VER_SUFFIX = "version=0.9,";
private Framework _felix;
@@ -88,61 +72,15 @@ public class PluginManager implements Closeable
private ServiceTracker _configTracker = null;
private ServiceTracker _virtualHostTracker = null;
private ServiceTracker _policyTracker = null;
- private ServiceTracker _authenticationManagerTracker = null;
private Activator _activator;
- private final List<ServiceTracker> _trackers = new ArrayList<ServiceTracker>();
private Map<String, SecurityPluginFactory> _securityPlugins = new HashMap<String, SecurityPluginFactory>();
private Map<List<String>, ConfigurationPluginFactory> _configPlugins = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();
private Map<String, VirtualHostPluginFactory> _vhostPlugins = new HashMap<String, VirtualHostPluginFactory>();
private Map<String, SlowConsumerPolicyPluginFactory> _policyPlugins = new HashMap<String, SlowConsumerPolicyPluginFactory>();
- private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> _authenticationManagerPlugins = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>();
- /** The default name of the OSGI system package list. */
- private static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/server/plugins/OsgiSystemPackages.properties";
-
- /** The name of the override system property that holds the name of the OSGI system package list. */
- private static final String FILE_PROPERTY = "qpid.osgisystempackages.properties";
-
- private static final String OSGI_SYSTEM_PACKAGES;
-
- static
- {
- final String filename = System.getProperty(FILE_PROPERTY);
- final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
- PluginManager.class.getClassLoader());
-
- try
- {
- Version qpidReleaseVersion;
- try
- {
- qpidReleaseVersion = Version.parseVersion(QpidProperties.getReleaseVersion());
- }
- catch (IllegalArgumentException iae)
- {
- qpidReleaseVersion = null;
- }
-
- final Properties p = new Properties();
- p.load(is);
-
- final OsgiSystemPackageUtil osgiSystemPackageUtil = new OsgiSystemPackageUtil(qpidReleaseVersion, (Map)p);
-
- OSGI_SYSTEM_PACKAGES = osgiSystemPackageUtil.getFormattedSystemPackageString();
-
- _logger.debug("List of OSGi system packages to be added: " + OSGI_SYSTEM_PACKAGES);
- }
- catch (IOException e)
- {
- _logger.error("Error reading OSGI system package list", e);
- throw new ExceptionInInitializerError(e);
- }
- }
-
-
- public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception
+ public PluginManager(String pluginPath, String cachePath) throws Exception
{
// Store all non-OSGi plugins
// A little gross that we have to add them here, but not all the plugins are OSGIfied
@@ -159,8 +97,7 @@ public class PluginManager implements Closeable
LegacyAccess.LegacyAccessConfiguration.FACTORY,
new SlowConsumerDetectionConfigurationFactory(),
new SlowConsumerDetectionPolicyConfigurationFactory(),
- new SlowConsumerDetectionQueueConfigurationFactory(),
- PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY))
+ new SlowConsumerDetectionQueueConfigurationFactory()))
{
_configPlugins.put(configFactory.getParentPaths(), configFactory);
}
@@ -175,109 +112,125 @@ public class PluginManager implements Closeable
_vhostPlugins.put(pluginFactory.getClass().getName(), pluginFactory);
}
- for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList(
- PrincipalDatabaseAuthenticationManager.FACTORY))
+ // Check the plugin directory path is set and exist
+ if (pluginPath == null)
{
- _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
+ return;
}
-
- if(bundleContext == null)
+ File pluginDir = new File(pluginPath);
+ if (!pluginDir.exists())
{
- // Check the plugin directory path is set and exist
- if (pluginPath == null)
- {
- _logger.info("No plugin path specified, no plugins will be loaded.");
- return;
- }
- File pluginDir = new File(pluginPath);
- if (!pluginDir.exists())
- {
- _logger.warn("Plugin dir : " + pluginDir + " does not exist.");
- return;
- }
-
- // Add the bundle provided service interface package and the core OSGi
- // packages to be exported from the class path via the system bundle.
-
- // Setup OSGi configuration property map
- final StringMap configMap = new StringMap(false);
- configMap.put(FRAMEWORK_SYSTEMPACKAGES, OSGI_SYSTEM_PACKAGES);
-
- // No automatic shutdown hook
- configMap.put("felix.shutdown.hook", "false");
-
- // Add system activator
- List<BundleActivator> activators = new ArrayList<BundleActivator>();
- _activator = new Activator();
- activators.add(_activator);
- configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators);
-
- if (cachePath != null)
- {
- File cacheDir = new File(cachePath);
- if (!cacheDir.exists() && cacheDir.canWrite())
- {
- _logger.info("Creating plugin cache directory: " + cachePath);
- cacheDir.mkdir();
- }
-
- // Set plugin cache directory and empty it
- _logger.info("Cache bundles in directory " + cachePath);
- configMap.put(FRAMEWORK_STORAGE, cachePath);
- }
- configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
-
- // Set directory with plugins to auto-deploy
- _logger.info("Auto deploying bundles from directory " + pluginPath);
- configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath);
- configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE);
+ return;
+ }
+
+ // Setup OSGi configuration propery map
+ StringMap configMap = new StringMap(false);
+
+ // Add the bundle provided service interface package and the core OSGi
+ // packages to be exported from the class path via the system bundle.
+ configMap.put(FRAMEWORK_SYSTEMPACKAGES,
+ "org.osgi.framework; version=1.3.0," +
+ "org.osgi.service.packageadmin; version=1.2.0," +
+ "org.osgi.service.startlevel; version=1.0.0," +
+ "org.osgi.service.url; version=1.0.0," +
+ "org.osgi.util.tracker; version=1.0.0," +
+ "org.apache.qpid.junit.extensions.util; " + QPID_VER_SUFFIX +
+ "org.apache.qpid; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.common; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.exchange; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.framing; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.management.common.mbeans.annotations; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.protocol; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.binding; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.configuration; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.configuration.plugins; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.configuration.management; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.exchange; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.logging; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.logging.actors; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.logging.subjects; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.management; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.persistent; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.plugins; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.protocol; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.queue; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.registry; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.security; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.security.access; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.security.access.plugins; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.virtualhost; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.server.virtualhost.plugins; " + QPID_VER_SUFFIX +
+ "org.apache.qpid.util; " + QPID_VER_SUFFIX +
+ "org.apache.commons.configuration; version=1.0.0," +
+ "org.apache.commons.lang; version=1.0.0," +
+ "org.apache.commons.lang.builder; version=1.0.0," +
+ "org.apache.commons.logging; version=1.0.0," +
+ "org.apache.log4j; version=1.2.12," +
+ "javax.management.openmbean; version=1.0.0," +
+ "javax.management; version=1.0.0"
+ );
+
+ // No automatic shutdown hook
+ configMap.put("felix.shutdown.hook", "false");
+
+ // Add system activator
+ List<BundleActivator> activators = new ArrayList<BundleActivator>();
+ _activator = new Activator();
+ activators.add(_activator);
+ configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators);
- // Start plugin manager
- _felix = new Felix(configMap);
- try
- {
- _logger.info("Starting plugin manager framework");
- _felix.init();
- process(configMap, _felix.getBundleContext());
- _felix.start();
- _logger.info("Started plugin manager framework");
- }
- catch (BundleException e)
+ if (cachePath != null)
+ {
+ File cacheDir = new File(cachePath);
+ if (!cacheDir.exists() && cacheDir.canWrite())
{
- throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e);
+ _logger.info("Creating plugin cache directory: " + cachePath);
+ cacheDir.mkdir();
}
-
- bundleContext = _activator.getContext();
+
+ // Set plugin cache directory and empty it
+ _logger.info("Cache bundles in directory " + cachePath);
+ configMap.put(FRAMEWORK_STORAGE, cachePath);
}
- else
+ configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+
+ // Set directory with plugins to auto-deploy
+ _logger.info("Auto deploying bundles from directory " + pluginPath);
+ configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath);
+ configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE);
+
+ // Start plugin manager and trackers
+ _felix = new Felix(configMap);
+ try
{
- _logger.info("Using the specified external BundleContext");
+ _logger.info("Starting plugin manager...");
+ _felix.init();
+ process(configMap, _felix.getBundleContext());
+ _felix.start();
+ _logger.info("Started plugin manager");
}
-
- _exchangeTracker = new ServiceTracker(bundleContext, ExchangeType.class.getName(), null);
+ catch (BundleException e)
+ {
+ throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e);
+ }
+
+ // TODO save trackers in a map, keyed by class name
+
+ _exchangeTracker = new ServiceTracker(_activator.getContext(), ExchangeType.class.getName(), null);
_exchangeTracker.open();
- _trackers.add(_exchangeTracker);
- _securityTracker = new ServiceTracker(bundleContext, SecurityPluginFactory.class.getName(), null);
+ _securityTracker = new ServiceTracker(_activator.getContext(), SecurityPluginFactory.class.getName(), null);
_securityTracker.open();
- _trackers.add(_securityTracker);
- _configTracker = new ServiceTracker(bundleContext, ConfigurationPluginFactory.class.getName(), null);
+ _configTracker = new ServiceTracker(_activator.getContext(), ConfigurationPluginFactory.class.getName(), null);
_configTracker.open();
- _trackers.add(_configTracker);
- _virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null);
+ _virtualHostTracker = new ServiceTracker(_activator.getContext(), VirtualHostPluginFactory.class.getName(), null);
_virtualHostTracker.open();
- _trackers.add(_virtualHostTracker);
- _policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null);
+ _policyTracker = new ServiceTracker(_activator.getContext(), SlowConsumerPolicyPluginFactory.class.getName(), null);
_policyTracker.open();
- _trackers.add(_policyTracker);
-
- _authenticationManagerTracker = new ServiceTracker(bundleContext, AuthenticationManagerPluginFactory.class.getName(), null);
- _authenticationManagerTracker.open();
- _trackers.add(_authenticationManagerTracker);
-
+
_logger.info("Opened service trackers");
}
@@ -348,26 +301,22 @@ public class PluginManager implements Closeable
return getServices(_securityTracker, _securityPlugins);
}
- public Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> getAuthenticationManagerPlugins()
- {
- return getServices(_authenticationManagerTracker, _authenticationManagerPlugins);
- }
-
public void close()
{
- try
+ if (_felix != null)
{
- // Close all bundle trackers
- for(ServiceTracker tracker : _trackers)
+ try
{
- tracker.close();
+ // Close all bundle trackers
+ _exchangeTracker.close();
+ _securityTracker.close();
+ _configTracker.close();
+ _virtualHostTracker.close();
+ _policyTracker.close();
}
- }
- finally
- {
- if (_felix != null)
+ finally
{
- _logger.info("Stopping plugin manager framework");
+ _logger.info("Stopping plugin manager");
try
{
// FIXME should be stopAndWait() but hangs VM, need upgrade in felix
@@ -386,12 +335,7 @@ public class PluginManager implements Closeable
{
// Ignore
}
- _logger.info("Stopped plugin manager framework");
- }
- else
- {
- _logger.info("Plugin manager was started with an external BundleContext, " +
- "skipping remaining shutdown tasks");
+ _logger.info("Stopped plugin manager");
}
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
index b51e6aff1a..bcda385f64 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
@@ -20,35 +20,14 @@
*/
package org.apache.qpid.server.protocol;
-import java.util.List;
-import java.util.UUID;
-
-import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.stats.StatisticsGatherer;
+import org.apache.qpid.AMQException;
-public interface AMQConnectionModel extends StatisticsGatherer
+public interface AMQConnectionModel
{
- /**
- * get a unique id for this connection.
- *
- * @return a {@link UUID} representing the connection
- */
- public UUID getId();
-
- /**
- * Close the underlying Connection
- *
- * @param cause
- * @param message
- * @throws org.apache.qpid.AMQException
- */
- public void close(AMQConstant cause, String message) throws AMQException;
/**
* Close the given requested Session
- *
* @param session
* @param cause
* @param message
@@ -57,20 +36,4 @@ public interface AMQConnectionModel extends StatisticsGatherer
public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException;
public long getConnectionId();
-
- /**
- * Get a list of all sessions using this connection.
- *
- * @return a list of {@link AMQSessionModel}s
- */
- public List<AMQSessionModel> getSessionModels();
-
- /**
- * Return a {@link LogSubject} for the connection.
- */
- public LogSubject getLogSubject();
-
- public String getUserName();
-
- public boolean isSessionNameUnique(String name);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
index bff0a79de1..a1ffe272fd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.server.protocol;
-import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
@@ -32,16 +30,18 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
import javax.management.JMException;
-import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
import org.apache.log4j.Logger;
+import org.apache.mina.transport.vmpipe.VmPipeAddress;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
@@ -66,10 +66,12 @@ import org.apache.qpid.framing.MethodDispatcher;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.ProtocolInitiation;
import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.pool.Job;
+import org.apache.qpid.pool.ReferenceCountingExecutorService;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.configuration.ConfiguredObject;
@@ -88,22 +90,21 @@ import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.TransportException;
-import org.apache.qpid.transport.network.NetworkConnection;
-public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
+public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
{
private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class);
private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString();
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+
// to save boxing the channelId and looking up in a map... cache in an array the low numbered
// channels. This value must be of the form 2^x - 1.
private static final int CHANNEL_CACHE_SIZE = 0xff;
@@ -133,7 +134,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private Object _lastSent;
protected volatile boolean _closed;
-
+
// maximum number of channels this session should have
private long _maxNoOfChannels = ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount();
@@ -145,46 +146,47 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private Map<Integer, Long> _closingChannelsList = new ConcurrentHashMap<Integer, Long>();
private ProtocolOutputConverter _protocolOutputConverter;
- private Subject _authorizedSubject;
+ private Principal _authorizedID;
private MethodDispatcher _dispatcher;
private ProtocolSessionIdentifier _sessionIdentifier;
- private final long _sessionID;
+ // Create a simple ID that increments for ever new Session
+ private final long _sessionID = idGenerator.getAndIncrement();
private AMQPConnectionActor _actor;
private LogSubject _logSubject;
+ private NetworkDriver _networkDriver;
+
private long _lastIoTime;
private long _writtenBytes;
private long _readBytes;
+ private Job _readJob;
+ private Job _writeJob;
+ private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance();
private long _maxFrameSize;
private final AtomicBoolean _closing = new AtomicBoolean(false);
private final UUID _id;
private final ConfigStore _configStore;
private long _createTime = System.currentTimeMillis();
- private ApplicationRegistry _registry;
- private boolean _statisticsEnabled = false;
- private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
-
- private NetworkConnection _network;
- private Sender<ByteBuffer> _sender;
-
public ManagedObject getManagedObject()
{
return _managedObject;
}
- public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId)
+ public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkDriver driver)
{
_stateManager = new AMQStateManager(virtualHostRegistry, this);
- _codecFactory = new AMQCodecFactory(true, this);
+ _networkDriver = driver;
- setNetworkConnection(network);
- _sessionID = connectionId;
+ _codecFactory = new AMQCodecFactory(true, this);
+ _poolReference.acquireExecutorService();
+ _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true);
+ _writeJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, false);
_actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger());
@@ -193,21 +195,9 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_configStore = virtualHostRegistry.getConfigStore();
_id = _configStore.createId();
- _actor.message(ConnectionMessages.OPEN(null, null, false, false));
- _registry = virtualHostRegistry.getApplicationRegistry();
- initialiseStatistics();
- }
-
- public void setNetworkConnection(NetworkConnection network)
- {
- setNetworkConnection(network, network.getSender());
- }
+ _actor.message(ConnectionMessages.OPEN(null, null, false, false));
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
- {
- _network = network;
- _sender = sender;
}
private AMQProtocolSessionMBean createMBean() throws JMException
@@ -246,18 +236,26 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
try
{
final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg);
- for (AMQDataBlock dataBlock : dataBlocks)
+ Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable()
{
- try
- {
- dataBlockReceived(dataBlock);
- }
- catch (Exception e)
+ public void run()
{
- _logger.error("Unexpected exception when processing datablock", e);
- closeProtocolSession();
+ // Decode buffer
+
+ for (AMQDataBlock dataBlock : dataBlocks)
+ {
+ try
+ {
+ dataBlockReceived(dataBlock);
+ }
+ catch (Exception e)
+ {
+ _logger.error("Unexpected exception when processing datablock", e);
+ closeProtocolSession();
+ }
+ }
}
- }
+ });
}
catch (Exception e)
{
@@ -335,11 +333,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
closeChannel(channelId);
throw e;
}
- catch (TransportException e)
- {
- closeChannel(channelId);
- throw e;
- }
}
finally
{
@@ -350,7 +343,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
private void protocolInitiationReceived(ProtocolInitiation pi)
{
// this ensures the codec never checks for a PI message again
- (_codecFactory.getDecoder()).setExpectProtocolInitiation(false);
+ ((AMQDecoder) _codecFactory.getDecoder()).setExpectProtocolInitiation(false);
try
{
// Log incomming protocol negotiation request
@@ -370,49 +363,15 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
null,
mechanisms.getBytes(),
locales.getBytes());
- _sender.send(asByteBuffer(responseBody.generateFrame(0)));
- _sender.flush();
+ _networkDriver.send(responseBody.generateFrame(0).toNioByteBuffer());
}
catch (AMQException e)
{
_logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion());
- _sender.send(asByteBuffer(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())));
- _sender.flush();
- }
- }
-
- private ByteBuffer asByteBuffer(AMQDataBlock block)
- {
- final ByteBuffer buf = ByteBuffer.allocate((int) block.getSize());
-
- try
- {
- block.writePayload(new DataOutputStream(new OutputStream()
- {
-
-
- @Override
- public void write(int b) throws IOException
- {
- buf.put((byte) b);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException
- {
- buf.put(b, off, len);
- }
- }));
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
+ _networkDriver.send(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()).toNioByteBuffer());
}
-
- buf.flip();
- return buf;
}
public void methodFrameReceived(int channelId, AMQMethodBody methodBody)
@@ -467,19 +426,19 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
AMQConstant.CHANNEL_ERROR.getName().toString());
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, ce);
+ closeConnection(channelId, ce, false);
}
}
catch (AMQConnectionException e)
{
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, e);
+ closeConnection(channelId, e, false);
}
catch (AMQSecurityException e)
{
AMQConnectionException ce = evt.getMethod().getConnectionException(AMQConstant.ACCESS_REFUSED, e.getMessage());
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, ce);
+ closeConnection(channelId, ce, false);
}
}
catch (Exception e)
@@ -522,14 +481,19 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
*
* @param frame the frame to write
*/
- public synchronized void writeFrame(AMQDataBlock frame)
+ public void writeFrame(AMQDataBlock frame)
{
_lastSent = frame;
- final ByteBuffer buf = asByteBuffer(frame);
+ final ByteBuffer buf = frame.toNioByteBuffer();
_lastIoTime = System.currentTimeMillis();
_writtenBytes += buf.remaining();
- _sender.send(buf);
- _sender.flush();
+ Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable()
+ {
+ public void run()
+ {
+ _networkDriver.send(buf);
+ }
+ });
}
public AMQShortString getContextKey()
@@ -719,8 +683,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
if (delay > 0)
{
- _network.setMaxWriteIdle(delay);
- _network.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay));
+ _networkDriver.setMaxWriteIdle(delay);
+ _networkDriver.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay));
}
}
@@ -761,7 +725,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
}
closeAllChannels();
-
+
getConfigStore().removeConfiguredObject(this);
if (_managedObject != null)
@@ -781,6 +745,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_closed = true;
notifyAll();
}
+ _poolReference.releaseExecutorService();
CurrentActor.get().message(_logSubject, ConnectionMessages.CLOSE());
}
}
@@ -803,32 +768,27 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
}
}
- public void closeConnection(int channelId, AMQConnectionException e) throws AMQException
+ public void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException
{
- try
+ if (_logger.isInfoEnabled())
{
- if (_logger.isInfoEnabled())
- {
- _logger.info("Closing connection due to: " + e);
- }
-
- markChannelAwaitingCloseOk(channelId);
- closeSession();
- _stateManager.changeState(AMQState.CONNECTION_CLOSING);
- writeFrame(e.getCloseFrame(channelId));
+ _logger.info("Closing connection due to: " + e);
}
- finally
+
+ markChannelAwaitingCloseOk(channelId);
+ closeSession();
+ _stateManager.changeState(AMQState.CONNECTION_CLOSING);
+ writeFrame(e.getCloseFrame(channelId));
+
+ if (closeProtocolSession)
{
closeProtocolSession();
}
-
-
}
public void closeProtocolSession()
{
- _network.close();
-
+ _networkDriver.close();
try
{
_stateManager.changeState(AMQState.CONNECTION_CLOSED);
@@ -837,15 +797,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
_logger.info(e.getMessage());
}
- catch (TransportException e)
- {
- _logger.info(e.getMessage());
- }
}
public String toString()
{
- return getRemoteAddress() + "(" + (getAuthorizedPrincipal() == null ? "?" : getAuthorizedPrincipal().getName() + ")");
+ return getRemoteAddress() + "(" + (getAuthorizedID() == null ? "?" : getAuthorizedID().getName() + ")");
}
public String dump()
@@ -867,11 +823,17 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
*/
public String getLocalFQDN()
{
- SocketAddress address = _network.getLocalAddress();
+ SocketAddress address = _networkDriver.getLocalAddress();
+ // we use the vmpipe address in some tests hence the need for this rather ugly test. The host
+ // information is used by SASL primary.
if (address instanceof InetSocketAddress)
{
return ((InetSocketAddress) address).getHostName();
}
+ else if (address instanceof VmPipeAddress)
+ {
+ return "vmpipe:" + ((VmPipeAddress) address).getPort();
+ }
else
{
throw new IllegalArgumentException("Unsupported socket address class: " + address);
@@ -950,7 +912,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public Object getClientIdentifier()
{
- return _network.getRemoteAddress();
+ return (_networkDriver != null) ? _networkDriver.getRemoteAddress() : null;
}
public VirtualHost getVirtualHost()
@@ -963,7 +925,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
_virtualHost = virtualHost;
_virtualHost.getConnectionRegistry().registerConnection(this);
-
+
_configStore.addConfiguredObject(this);
try
@@ -992,33 +954,29 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return _protocolOutputConverter;
}
- public void setAuthorizedSubject(final Subject authorizedSubject)
+ public void setAuthorizedID(Principal authorizedID)
{
- if (authorizedSubject == null)
- {
- throw new IllegalArgumentException("authorizedSubject cannot be null");
- }
- _authorizedSubject = authorizedSubject;
+ _authorizedID = authorizedID;
}
- public Subject getAuthorizedSubject()
+ public Principal getAuthorizedID()
{
- return _authorizedSubject;
+ return _authorizedID;
}
- public Principal getAuthorizedPrincipal()
+ public Principal getPrincipal()
{
- return _authorizedSubject == null ? null : UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ return _authorizedID;
}
public SocketAddress getRemoteAddress()
{
- return _network.getRemoteAddress();
+ return _networkDriver.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _network.getLocalAddress();
+ return _networkDriver.getLocalAddress();
}
public MethodRegistry getMethodRegistry()
@@ -1041,10 +999,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
_logger.error("Could not close protocol engine", e);
}
- catch (TransportException e)
- {
- _logger.error("Could not close protocol engine", e);
- }
}
public void readerIdle()
@@ -1052,9 +1006,14 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
// Nothing
}
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _networkDriver = driver;
+ }
+
public void writerIdle()
{
- _sender.send(asByteBuffer(HeartbeatBody.FRAME));
+ _networkDriver.send(HeartbeatBody.FRAME.toNioByteBuffer());
}
public void exception(Throwable throwable)
@@ -1062,7 +1021,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
if (throwable instanceof AMQProtocolHeaderException)
{
writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()));
- _sender.close();
+ _networkDriver.close();
_logger.error("Error in protocol initiation " + this + ":" + getRemoteAddress() + " :" + throwable.getMessage(), throwable);
}
@@ -1080,7 +1039,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
writeFrame(closeBody.generateFrame(0));
- _sender.close();
+ _networkDriver.close();
}
}
@@ -1119,6 +1078,19 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
return (_clientVersion == null) ? null : _clientVersion.toString();
}
+ public void closeIfLingeringClosedChannels()
+ {
+ for (Entry<Integer, Long>id : _closingChannelsList.entrySet())
+ {
+ if (id.getValue() + 30000 > System.currentTimeMillis())
+ {
+ // We have a channel that we closed 30 seconds ago. Client's dead, kill the connection
+ _logger.error("Closing connection as channel was closed more than 30 seconds ago and no ChannelCloseOk has been processed");
+ closeProtocolSession();
+ }
+ }
+ }
+
public Boolean isIncoming()
{
return true;
@@ -1136,7 +1108,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public String getAuthId()
{
- return getAuthorizedPrincipal().getName();
+ return getAuthorizedID().getName();
}
public Integer getRemotePID()
@@ -1198,7 +1170,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
{
return false;
}
-
+
public void mgmtClose()
{
MethodRegistry methodRegistry = getMethodRegistry();
@@ -1291,6 +1263,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException
{
+
closeChannel((Integer)session.getID());
MethodRegistry methodRegistry = getMethodRegistry();
@@ -1300,110 +1273,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr
new AMQShortString(message),
0,0);
- writeFrame(responseBody.generateFrame((Integer)session.getID()));
- }
-
- public void close(AMQConstant cause, String message) throws AMQException
- {
- closeConnection(0, new AMQConnectionException(cause, message, 0, 0,
- getProtocolOutputConverter().getProtocolMajorVersion(),
- getProtocolOutputConverter().getProtocolMinorVersion(),
- (Throwable) null));
- }
-
- public List<AMQSessionModel> getSessionModels()
- {
- List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
- for (AMQChannel channel : getChannels())
- {
- sessions.add((AMQSessionModel) channel);
- }
- return sessions;
- }
-
- public LogSubject getLogSubject()
- {
- return _logSubject;
- }
-
- public void registerMessageDelivered(long messageSize)
- {
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
- _virtualHost.registerMessageDelivered(messageSize);
- }
-
- public void registerMessageReceived(long messageSize, long timestamp)
- {
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
- _virtualHost.registerMessageReceived(messageSize, timestamp);
- }
-
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return _messagesReceived;
- }
-
- public StatisticsCounter getDataReceiptStatistics()
- {
- return _dataReceived;
- }
-
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return _messagesDelivered;
- }
-
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return _dataDelivered;
- }
-
- public void resetStatistics()
- {
- _messagesDelivered.reset();
- _dataDelivered.reset();
- _messagesReceived.reset();
- _dataReceived.reset();
- }
-
- public void initialiseStatistics()
- {
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _registry.getConfiguration().isStatisticsGenerationConnectionsEnabled());
-
- _messagesDelivered = new StatisticsCounter("messages-delivered-" + getSessionID());
- _dataDelivered = new StatisticsCounter("data-delivered-" + getSessionID());
- _messagesReceived = new StatisticsCounter("messages-received-" + getSessionID());
- _dataReceived = new StatisticsCounter("data-received-" + getSessionID());
- }
-
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
-
- @Override
- public boolean isSessionNameUnique(String name)
- {
- return true;
- }
-
- @Override
- public String getUserName()
- {
- return getAuthorizedPrincipal().getName();
- }
+ writeFrame(responseBody.generateFrame((Integer)session.getID()));
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java
new file mode 100644
index 0000000000..0e4444725e
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java
@@ -0,0 +1,50 @@
+package org.apache.qpid.server.protocol;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.transport.NetworkDriver;
+
+public class AMQProtocolEngineFactory implements ProtocolEngineFactory
+{
+ private VirtualHostRegistry _vhosts;
+
+ public AMQProtocolEngineFactory()
+ {
+ this(1);
+ }
+
+ public AMQProtocolEngineFactory(Integer port)
+ {
+ _vhosts = ApplicationRegistry.getInstance(port).getVirtualHostRegistry();
+ }
+
+
+ public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
+ {
+ return new AMQProtocolEngine(_vhosts, networkDriver);
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
index c1b5b02f8f..f48a214933 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.server.protocol;
-import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
import org.apache.qpid.AMQException;
@@ -29,15 +28,16 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.security.Principal;
import java.util.List;
-public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, AuthorizationHolder, AMQConnectionModel
+public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, PrincipalHolder, AMQConnectionModel
{
long getSessionID();
@@ -163,10 +163,8 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
/** This must be called when the session is _closed in order to free up any resources managed by the session. */
void closeSession() throws AMQException;
- void closeProtocolSession();
-
/** This must be called to close the session in order to free up any resources managed by the session. */
- void closeConnection(int channelId, AMQConnectionException e) throws AMQException;
+ void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException;
/** @return a key that uniquely identifies this session */
@@ -207,7 +205,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
public ProtocolOutputConverter getProtocolOutputConverter();
- void setAuthorizedSubject(Subject authorizedSubject);
+ void setAuthorizedID(Principal authorizedID);
public java.net.SocketAddress getRemoteAddress();
@@ -233,5 +231,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth
List<AMQChannel> getChannels();
+ void closeIfLingeringClosedChannels();
+
void mgmtCloseChannel(int channelId);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
index 16d99de492..f4f2cab2c2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
@@ -37,15 +37,25 @@
*/
package org.apache.qpid.server.protocol;
-import java.util.Date;
-import java.util.List;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ConnectionCloseBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
+import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.ManagementActor;
+import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.management.ManagedObject;
import javax.management.JMException;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
-import javax.management.ObjectName;
import javax.management.monitor.MonitorNotification;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
@@ -56,20 +66,8 @@ import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ConnectionCloseBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
+import java.util.Date;
+import java.util.List;
/**
* This MBean class implements the management interface. In order to make more attributes, operations and notifications
@@ -96,7 +94,8 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
super(ManagedConnection.class, ManagedConnection.TYPE);
_protocolSession = amqProtocolSession;
String remote = getRemoteAddress();
- _name = "anonymous".equals(remote) ? (remote + hashCode()) : remote;
+ remote = "anonymous".equals(remote) ? (remote + hashCode()) : remote;
+ _name = jmxEncode(new StringBuffer(remote), 0).toString();
init();
}
@@ -131,7 +130,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
public String getAuthorizedId()
{
- return (_protocolSession.getAuthorizedPrincipal() != null ) ? _protocolSession.getAuthorizedPrincipal().getName() : null;
+ return (_protocolSession.getPrincipal() != null ) ? _protocolSession.getPrincipal().getName() : null;
}
public String getVersion()
@@ -176,7 +175,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
public String getObjectInstanceName()
{
- return ObjectName.quote(_name);
+ return _name;
}
/**
@@ -340,78 +339,4 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
_broadcaster.sendNotification(n);
}
- public void resetStatistics() throws Exception
- {
- _protocolSession.resetStatistics();
- }
-
- public double getPeakMessageDeliveryRate()
- {
- return _protocolSession.getMessageDeliveryStatistics().getPeak();
- }
-
- public double getPeakDataDeliveryRate()
- {
- return _protocolSession.getDataDeliveryStatistics().getPeak();
- }
-
- public double getMessageDeliveryRate()
- {
- return _protocolSession.getMessageDeliveryStatistics().getRate();
- }
-
- public double getDataDeliveryRate()
- {
- return _protocolSession.getDataDeliveryStatistics().getRate();
- }
-
- public long getTotalMessagesDelivered()
- {
- return _protocolSession.getMessageDeliveryStatistics().getTotal();
- }
-
- public long getTotalDataDelivered()
- {
- return _protocolSession.getDataDeliveryStatistics().getTotal();
- }
-
- public double getPeakMessageReceiptRate()
- {
- return _protocolSession.getMessageReceiptStatistics().getPeak();
- }
-
- public double getPeakDataReceiptRate()
- {
- return _protocolSession.getDataReceiptStatistics().getPeak();
- }
-
- public double getMessageReceiptRate()
- {
- return _protocolSession.getMessageReceiptStatistics().getRate();
- }
-
- public double getDataReceiptRate()
- {
- return _protocolSession.getDataReceiptStatistics().getRate();
- }
-
- public long getTotalMessagesReceived()
- {
- return _protocolSession.getMessageReceiptStatistics().getTotal();
- }
-
- public long getTotalDataReceived()
- {
- return _protocolSession.getDataReceiptStatistics().getTotal();
- }
-
- public boolean isStatisticsEnabled()
- {
- return _protocolSession.isStatisticsEnabled();
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _protocolSession.setStatisticsEnabled(enabled);
- }
-}
+} // End of MBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
index bc63403a86..a9b2354d75 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
@@ -20,35 +20,15 @@
*/
package org.apache.qpid.server.protocol;
-import org.apache.qpid.AMQException;
import org.apache.qpid.server.logging.LogSubject;
public interface AMQSessionModel
{
- public Object getID();
+ Object getID();
- public AMQConnectionModel getConnectionModel();
+ AMQConnectionModel getConnectionModel();
- public String getClientID();
-
- public void close() throws AMQException;
+ String getClientID();
- public LogSubject getLogSubject();
-
- /**
- * This method is called from the housekeeping thread to check the status of
- * transactions on this session and react appropriately.
- *
- * If a transaction is open for too long or idle for too long then a warning
- * is logged or the connection is closed, depending on the configuration. An open
- * transaction is one that has recent activity. The transaction age is counted
- * from the time the transaction was started. An idle transaction is one that
- * has had no activity, such as publishing or acknowledgeing messages.
- *
- * @param openWarn time in milliseconds before alerting on open transaction
- * @param openClose time in milliseconds before closing connection with open transaction
- * @param idleWarn time in milliseconds before alerting on idle transaction
- * @param idleClose time in milliseconds before closing connection with idle transaction
- */
- public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException;
+ LogSubject getLogSubject();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
deleted file mode 100644
index e925d7a1ec..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
+++ /dev/null
@@ -1,23 +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.
- *
- */
-package org.apache.qpid.server.protocol;
-
-public enum AmqpProtocolVersion { v0_8, v0_9, v0_9_1, v0_10 } \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
index 7033bf755d..eb957ee33c 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
@@ -22,53 +22,44 @@ package org.apache.qpid.server.protocol;
import org.apache.log4j.Logger;
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.transport.ServerConnection;
import org.apache.qpid.transport.ConnectionDelegate;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
+import org.apache.qpid.transport.NetworkDriver;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.Set;
-public class MultiVersionProtocolEngine implements ServerProtocolEngine
+public class MultiVersionProtocolEngine implements ProtocolEngine
{
private static final Logger _logger = Logger.getLogger(MultiVersionProtocolEngine.class);
- private final long _id;
- private Set<AmqpProtocolVersion> _supported;
+
+ private NetworkDriver _networkDriver;
+ private Set<VERSION> _supported;
private String _fqdn;
private IApplicationRegistry _appRegistry;
- private NetworkConnection _network;
- private Sender<ByteBuffer> _sender;
-
- private volatile ServerProtocolEngine _delegate = new SelfDelegateProtocolEngine();
- public MultiVersionProtocolEngine(IApplicationRegistry appRegistry,
- String fqdn,
- Set<AmqpProtocolVersion> supported,
- NetworkConnection network,
- long id)
- {
- this(appRegistry,fqdn,supported,id);
- setNetworkConnection(network);
- }
+ private volatile ProtocolEngine _delegate = new SelfDelegateProtocolEngine();
public MultiVersionProtocolEngine(IApplicationRegistry appRegistry,
String fqdn,
- Set<AmqpProtocolVersion> supported,
- long id)
+ Set<VERSION> supported, NetworkDriver networkDriver)
{
- _id = id;
_appRegistry = appRegistry;
_fqdn = fqdn;
_supported = supported;
-
+ _networkDriver = networkDriver;
}
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _delegate.setNetworkDriver(driver);
+ }
public SocketAddress getRemoteAddress()
{
@@ -105,7 +96,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
_delegate.readerIdle();
}
-
public void received(ByteBuffer msg)
{
_delegate.received(msg);
@@ -116,11 +106,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
_delegate.exception(t);
}
- public long getConnectionId()
- {
- return _delegate.getConnectionId();
- }
-
private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8;
private static final byte[] AMQP_0_8_HEADER =
@@ -145,7 +130,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
(byte) 9
};
- private static final byte[] AMQP_0_9_1_HEADER =
+private static final byte[] AMQP_0_9_1_HEADER =
new byte[] { (byte) 'A',
(byte) 'M',
(byte) 'Q',
@@ -168,31 +153,19 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
(byte) 10
};
- public void setNetworkConnection(NetworkConnection networkConnection)
- {
- setNetworkConnection(networkConnection, networkConnection.getSender());
- }
-
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
- {
- _network = network;
- _sender = sender;
- }
-
-
private static interface DelegateCreator
{
- AmqpProtocolVersion getVersion();
+ VERSION getVersion();
byte[] getHeaderIdentifier();
- ServerProtocolEngine getProtocolEngine();
+ ProtocolEngine getProtocolEngine();
}
private DelegateCreator creator_0_8 = new DelegateCreator()
{
- public AmqpProtocolVersion getVersion()
+ public VERSION getVersion()
{
- return AmqpProtocolVersion.v0_8;
+ return VERSION.v0_8;
}
public byte[] getHeaderIdentifier()
@@ -200,18 +173,18 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
return AMQP_0_8_HEADER;
}
- public ServerProtocolEngine getProtocolEngine()
+ public ProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
}
};
private DelegateCreator creator_0_9 = new DelegateCreator()
{
- public AmqpProtocolVersion getVersion()
+ public VERSION getVersion()
{
- return AmqpProtocolVersion.v0_9;
+ return VERSION.v0_9;
}
@@ -220,18 +193,18 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
return AMQP_0_9_HEADER;
}
- public ServerProtocolEngine getProtocolEngine()
+ public ProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
}
};
private DelegateCreator creator_0_9_1 = new DelegateCreator()
{
- public AmqpProtocolVersion getVersion()
+ public VERSION getVersion()
{
- return AmqpProtocolVersion.v0_9_1;
+ return VERSION.v0_9_1;
}
@@ -240,9 +213,9 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
return AMQP_0_9_1_HEADER;
}
- public ServerProtocolEngine getProtocolEngine()
+ public ProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
}
};
@@ -250,9 +223,9 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
private DelegateCreator creator_0_10 = new DelegateCreator()
{
- public AmqpProtocolVersion getVersion()
+ public VERSION getVersion()
{
- return AmqpProtocolVersion.v0_10;
+ return VERSION.v0_10;
}
@@ -261,15 +234,15 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
return AMQP_0_10_HEADER;
}
- public ServerProtocolEngine getProtocolEngine()
+ public ProtocolEngine getProtocolEngine()
{
final ConnectionDelegate connDelegate =
new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn);
- ServerConnection conn = new ServerConnection(_id);
+ ServerConnection conn = new ServerConnection();
conn.setConnectionDelegate(connDelegate);
- return new ProtocolEngine_0_10( conn, _network, _appRegistry);
+ return new ProtocolEngine_0_10( conn, _networkDriver, _appRegistry);
}
};
@@ -277,16 +250,21 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10 };
- private class ClosedDelegateProtocolEngine implements ServerProtocolEngine
+ private class ClosedDelegateProtocolEngine implements ProtocolEngine
{
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _networkDriver = driver;
+ }
+
public SocketAddress getRemoteAddress()
{
- return _network.getRemoteAddress();
+ return _networkDriver.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _network.getLocalAddress();
+ return _networkDriver.getLocalAddress();
}
public long getWrittenBytes()
@@ -323,30 +301,26 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
{
}
+ }
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
- {
+ private class SelfDelegateProtocolEngine implements ProtocolEngine
+ {
- }
+ private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
- public long getConnectionId()
+ public void setNetworkDriver(NetworkDriver driver)
{
- return _id;
+ _networkDriver = driver;
}
- }
-
- private class SelfDelegateProtocolEngine implements ServerProtocolEngine
- {
- private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
public SocketAddress getRemoteAddress()
{
- return _network.getRemoteAddress();
+ return _networkDriver.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _network.getLocalAddress();
+ return _networkDriver.getLocalAddress();
}
public long getWrittenBytes()
@@ -381,7 +355,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
_header.get(headerBytes);
- ServerProtocolEngine newDelegate = null;
+ ProtocolEngine newDelegate = null;
byte[] newestSupported = null;
for(int i = 0; newDelegate == null && i < _creators.length; i++)
@@ -406,20 +380,17 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
// If no delegate is found then send back the most recent support protocol version id
if(newDelegate == null)
{
- _sender.send(ByteBuffer.wrap(newestSupported));
- _sender.flush();
+ _networkDriver.send(ByteBuffer.wrap(newestSupported));
_delegate = new ClosedDelegateProtocolEngine();
-
- _network.close();
-
}
else
{
+ newDelegate.setNetworkDriver(_networkDriver);
+
_delegate = newDelegate;
_header.flip();
- _delegate.setNetworkConnection(_network, _sender);
_delegate.received(_header);
if(msg.hasRemaining())
{
@@ -431,11 +402,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
}
- public long getConnectionId()
- {
- return _id;
- }
-
public void exception(Throwable t)
{
_logger.error("Error establishing session", t);
@@ -455,10 +421,5 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine
{
}
-
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
- {
-
- }
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
index 7e327b221f..75358c42d9 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
@@ -20,38 +20,56 @@
*/
package org.apache.qpid.server.protocol;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.transport.network.NetworkConnection;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.util.HashSet;
public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory
{
- private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
+ ;
+
+
+ public enum VERSION { v0_8, v0_9, v0_9_1, v0_10 };
+
+ private static final Set<VERSION> ALL_VERSIONS = new HashSet<VERSION>(Arrays.asList(VERSION.values()));
private final IApplicationRegistry _appRegistry;
private final String _fqdn;
- private final Set<AmqpProtocolVersion> _supported;
+ private final Set<VERSION> _supported;
+
- public MultiVersionProtocolEngineFactory(String fqdn, Set<AmqpProtocolVersion> supportedVersions)
+ public MultiVersionProtocolEngineFactory()
{
- _appRegistry = ApplicationRegistry.getInstance();
- _fqdn = fqdn;
- _supported = supportedVersions;
+ this(1, "localhost", ALL_VERSIONS);
}
- public ServerProtocolEngine newProtocolEngine(NetworkConnection network)
+ public MultiVersionProtocolEngineFactory(String fqdn, Set<VERSION> versions)
{
- return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, network, ID_GENERATOR.getAndIncrement());
+ this(1, fqdn, versions);
}
- public ServerProtocolEngine newProtocolEngine()
+
+ public MultiVersionProtocolEngineFactory(String fqdn)
{
- return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, ID_GENERATOR.getAndIncrement());
+ this(1, fqdn, ALL_VERSIONS);
}
+ public MultiVersionProtocolEngineFactory(int instance, String fqdn, Set<VERSION> supportedVersions)
+ {
+ _appRegistry = ApplicationRegistry.getInstance(instance);
+ _fqdn = fqdn;
+ _supported = supportedVersions;
+ }
+
+
+ public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
+ {
+ return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, networkDriver);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
index 48a8a1bf42..30d506a89b 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java
@@ -20,26 +20,25 @@
*/
package org.apache.qpid.server.protocol;
-import org.apache.qpid.protocol.ServerProtocolEngine;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.network.InputHandler;
import org.apache.qpid.transport.network.Assembler;
import org.apache.qpid.transport.network.Disassembler;
-import org.apache.qpid.transport.network.NetworkConnection;
import org.apache.qpid.server.configuration.*;
import org.apache.qpid.server.transport.ServerConnection;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
import org.apache.qpid.server.registry.IApplicationRegistry;
import java.net.SocketAddress;
-import java.nio.ByteBuffer;
import java.util.UUID;
-public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine, ConnectionConfig
+public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine, ConnectionConfig
{
public static final int MAX_FRAME_SIZE = 64 * 1024 - 1;
- private NetworkConnection _network;
+ private NetworkDriver _networkDriver;
private long _readBytes;
private long _writtenBytes;
private ServerConnection _connection;
@@ -48,22 +47,26 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
private long _createTime = System.currentTimeMillis();
public ProtocolEngine_0_10(ServerConnection conn,
- NetworkConnection network,
+ NetworkDriver networkDriver,
final IApplicationRegistry appRegistry)
{
super(new Assembler(conn));
_connection = conn;
_connection.setConnectionConfig(this);
-
+ _networkDriver = networkDriver;
_id = appRegistry.getConfigStore().createId();
_appRegistry = appRegistry;
- if(network != null)
- {
- setNetworkConnection(network);
- }
-
+ // FIXME Two log messages to maintain compatinbility with earlier protocol versions
+ _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, false, false));
+ _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", false, true));
+ }
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _networkDriver = driver;
+ Disassembler dis = new Disassembler(driver, MAX_FRAME_SIZE);
+ _connection.setSender(dis);
_connection.onOpen(new Runnable()
{
public void run()
@@ -74,30 +77,14 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
}
- public void setNetworkConnection(NetworkConnection network)
- {
- setNetworkConnection(network, network.getSender());
- }
-
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
- {
- _network = network;
-
- _connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE));
-
- // FIXME Two log messages to maintain compatibility with earlier protocol versions
- _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, false, false));
- _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", false, true));
- }
-
public SocketAddress getRemoteAddress()
{
- return _network.getRemoteAddress();
+ return _networkDriver.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _network.getLocalAddress();
+ return _networkDriver.getLocalAddress();
}
public long getReadBytes()
@@ -147,7 +134,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
public String getAuthId()
{
- return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName();
+ return _connection.getAuthorizationID();
}
public String getRemoteProcessName()
@@ -206,14 +193,9 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol
{
return false;
}
-
+
public void mgmtClose()
{
_connection.mgmtClose();
}
-
- public long getConnectionId()
- {
- return _connection.getConnectionId();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
index 371ae0de50..b6e97e08fb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
@@ -60,7 +60,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue
{
// check that all subscriptions are not in advance of the entry
SubscriptionList.SubscriptionNodeIterator subIter = _subscriptionList.iterator();
- while(subIter.advance() && entry.isAvailable())
+ while(subIter.advance() && !entry.isAcquired())
{
final Subscription subscription = subIter.getNode().getSubscription();
if(!subscription.isClosed())
@@ -70,7 +70,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue
{
QueueEntry subnode = context._lastSeenEntry;
QueueEntry released = context._releasedEntry;
- while(subnode != null && entry.compareTo(subnode) < 0 && entry.isAvailable() && (released == null || released.compareTo(entry) < 0))
+ while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired() && (released == null || released.compareTo(entry) < 0))
{
if(QueueContext._releasedUpdater.compareAndSet(context,released,entry))
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 9140a13625..de9dc42de8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -21,18 +21,21 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.QueueConfig;
+import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.management.Managable;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.txn.ServerTransaction;
@@ -69,8 +72,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
boolean isAutoDelete();
AMQShortString getOwner();
- AuthorizationHolder getAuthorizationHolder();
- void setAuthorizationHolder(AuthorizationHolder principalHolder);
+ PrincipalHolder getPrincipalHolder();
+ void setPrincipalHolder(PrincipalHolder principalHolder);
void setExclusiveOwningSession(AMQSessionModel owner);
AMQSessionModel getExclusiveOwningSession();
@@ -105,16 +108,23 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
boolean isDeleted();
+
int delete() throws AMQException;
+
void requeue(QueueEntry entry);
+ void requeue(QueueEntryImpl storeContext, Subscription subscription);
+
void dequeue(QueueEntry entry, Subscription sub);
void decrementUnackedMsgCount();
+
boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
+
+
void addQueueDeleteTask(final Task task);
void removeQueueDeleteTask(final Task task);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index c8eb118b11..b5294b6d2f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -43,7 +43,6 @@ import javax.management.JMException;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
-import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.monitor.MonitorNotification;
import javax.management.openmbean.ArrayType;
@@ -98,7 +97,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
super(ManagedQueue.class, ManagedQueue.TYPE);
_queue = queue;
- _queueName = queue.getName();
+ _queueName = jmxEncode(new StringBuffer(queue.getNameShortString()), 0).toString();
}
public ManagedObject getParentObject()
@@ -148,7 +147,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
public String getObjectInstanceName()
{
- return ObjectName.quote(_queueName);
+ return _queueName;
}
public String getName()
@@ -507,7 +506,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
private String[] getMessageHeaderProperties(ContentHeaderBody headerBody)
{
List<String> list = new ArrayList<String>();
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.getProperties();
+ BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.properties;
list.add("reply-to = " + headerProperties.getReplyToAsString());
list.add("propertyFlags = " + headerProperties.getPropertyFlags());
list.add("ApplicationID = " + headerProperties.getAppIdAsString());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
index a56f5685b8..2d2fb3a214 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
@@ -96,9 +96,9 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public void setExpiration()
{
long expiration =
- ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getExpiration();
+ ((BasicContentHeaderProperties) _contentHeaderBody.properties).getExpiration();
long timestamp =
- ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getTimestamp();
+ ((BasicContentHeaderProperties) _contentHeaderBody.properties).getTimestamp();
if (SYNCHED_CLOCKS)
{
@@ -139,7 +139,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public int addContentBodyFrame(final ContentChunk contentChunk)
throws AMQException
{
- _storedMessageHandle.addContent((int)_bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData()));
+ _storedMessageHandle.addContent((int)_bodyLengthReceived, contentChunk.getData().buf());
_bodyLengthReceived += contentChunk.getSize();
_contentChunks.add(contentChunk);
@@ -193,8 +193,8 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public boolean isPersistent()
{
- return getContentHeader().getProperties() instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) getContentHeader().getProperties()).getDeliveryMode() ==
+ return getContentHeader().properties instanceof BasicContentHeaderProperties &&
+ ((BasicContentHeaderProperties) getContentHeader().properties).getDeliveryMode() ==
BasicContentHeaderProperties.PERSISTENT;
}
@@ -263,7 +263,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
int written = 0;
for(ContentChunk cb : _contentChunks)
{
- ByteBuffer data = ByteBuffer.wrap(cb.getData());
+ ByteBuffer data = cb.getData().buf();
if(offset+written >= pos && offset < pos + data.limit())
{
ByteBuffer src = data.duplicate();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
index be29245901..edd1e0bdc3 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
@@ -52,17 +52,6 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
}
public abstract State getState();
-
- /**
- * Returns true if state is either DEQUEUED or DELETED.
- *
- * @return true if state is either DEQUEUED or DELETED.
- */
- public boolean isDispensed()
- {
- State currentState = getState();
- return currentState == State.DEQUEUED || currentState == State.DELETED;
- }
}
@@ -202,7 +191,11 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
void reject();
- boolean isRejectedBy(long subscriptionId);
+ void reject(Subscription subscription);
+
+ boolean isRejectedBy(Subscription subscription);
+
+ void requeue(Subscription subscription);
void dequeue();
@@ -216,18 +209,4 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
void addStateChangeListener(StateChangeListener listener);
boolean removeStateChangeListener(StateChangeListener listener);
-
- /**
- * Returns true if entry is in DEQUEUED state, otherwise returns false.
- *
- * @return true if entry is in DEQUEUED state, otherwise returns false
- */
- boolean isDequeued();
-
- /**
- * Returns true if entry is either DEQUED or DELETED state.
- *
- * @return true if entry is either DEQUED or DELETED state
- */
- boolean isDispensed();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index 5b57e40a82..1ba4f4d89b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -51,7 +51,7 @@ public class QueueEntryImpl implements QueueEntry
private MessageReference _message;
- private Set<Long> _rejectedBy = null;
+ private Set<Subscription> _rejectedBy = null;
private volatile EntryState _state = AVAILABLE_STATE;
@@ -325,16 +325,19 @@ public class QueueEntryImpl implements QueueEntry
public void reject()
{
- Subscription subscription = getDeliveredSubscription();
+ reject(getDeliveredSubscription());
+ }
+ public void reject(Subscription subscription)
+ {
if (subscription != null)
{
if (_rejectedBy == null)
{
- _rejectedBy = new HashSet<Long>();
+ _rejectedBy = new HashSet<Subscription>();
}
- _rejectedBy.add(subscription.getSubscriptionID());
+ _rejectedBy.add(subscription);
}
else
{
@@ -342,12 +345,12 @@ public class QueueEntryImpl implements QueueEntry
}
}
- public boolean isRejectedBy(long subscriptionId)
+ public boolean isRejectedBy(Subscription subscription)
{
if (_rejectedBy != null) // We have subscriptions that rejected this message
{
- return _rejectedBy.contains(subscriptionId);
+ return _rejectedBy.contains(subscription);
}
else // This messasge hasn't been rejected yet.
{
@@ -355,6 +358,15 @@ public class QueueEntryImpl implements QueueEntry
}
}
+ public void requeue(Subscription subscription)
+ {
+ getQueue().requeue(this, subscription);
+ if(_stateChangeListeners != null)
+ {
+ notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
+ }
+ }
+
public void dequeue()
{
EntryState state = _state;
@@ -496,7 +508,7 @@ public class QueueEntryImpl implements QueueEntry
{
QueueEntryImpl next = nextNode();
- while(next != null && next.isDispensed() )
+ while(next != null && next.isDeleted())
{
final QueueEntryImpl newNext = next.nextNode();
@@ -544,14 +556,4 @@ public class QueueEntryImpl implements QueueEntry
return _queueEntryList;
}
- public boolean isDequeued()
- {
- return _state == DEQUEUED_STATE;
- }
-
- public boolean isDispensed()
- {
- return _state.isDispensed();
- }
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
deleted file mode 100644
index 7e1d57e205..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
+++ /dev/null
@@ -1,84 +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.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.pool.ReadWriteRunnable;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.queue.QueueRunner;
-import org.apache.qpid.server.queue.SimpleAMQQueue;
-
-/**
- * QueueRunners are Runnables used to process a queue when requiring
- * asynchronous message delivery to subscriptions, which is necessary
- * when straight-through delivery of a message to a subscription isn't
- * possible during the enqueue operation.
- */
-public class QueueRunner implements ReadWriteRunnable
-{
- private static final Logger _logger = Logger.getLogger(QueueRunner.class);
-
- private final String _name;
- private final SimpleAMQQueue _queue;
-
- public QueueRunner(SimpleAMQQueue queue, long count)
- {
- _queue = queue;
- _name = "QueueRunner-" + count + "-" + queue.getLogActor();
- }
-
- public void run()
- {
- String originalName = Thread.currentThread().getName();
- try
- {
- Thread.currentThread().setName(_name);
- CurrentActor.set(_queue.getLogActor());
-
- _queue.processQueue(this);
- }
- catch (AMQException e)
- {
- _logger.error("Exception during asynchronous delivery by " + _name, e);
- }
- finally
- {
- CurrentActor.remove();
- Thread.currentThread().setName(originalName);
- }
- }
-
- public boolean isRead()
- {
- return false;
- }
-
- public boolean isWrite()
- {
- return true;
- }
-
- public String toString()
- {
- return _name;
- }
-} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
index a095ef47ea..b003152db6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -44,7 +44,7 @@ import org.apache.qpid.server.logging.subjects.QueueLogSubject;
import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -83,7 +83,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
/** null means shared */
private final AMQShortString _owner;
- private AuthorizationHolder _authorizationHolder;
+ private PrincipalHolder _prinicpalHolder;
private boolean _exclusive = false;
private AMQSessionModel _exclusiveOwner;
@@ -102,7 +102,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
protected final QueueEntryList _entries;
- protected final SubscriptionList _subscriptionList = new SubscriptionList();
+ protected final SubscriptionList _subscriptionList = new SubscriptionList(this);
+
+ private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead());
private volatile Subscription _exclusiveSubscriber;
@@ -371,14 +373,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
return _owner;
}
- public AuthorizationHolder getAuthorizationHolder()
+ public PrincipalHolder getPrincipalHolder()
{
- return _authorizationHolder;
+ return _prinicpalHolder;
}
- public void setAuthorizationHolder(final AuthorizationHolder authorizationHolder)
+ public void setPrincipalHolder(PrincipalHolder prinicpalHolder)
{
- _authorizationHolder = authorizationHolder;
+ _prinicpalHolder = prinicpalHolder;
}
@@ -600,25 +602,25 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
iterate over subscriptions and if any is at the end of the queue and can deliver this message, then deliver the message
*/
- SubscriptionList.SubscriptionNode node = _subscriptionList.getMarkedNode();
- SubscriptionList.SubscriptionNode nextNode = node.findNext();
+ SubscriptionList.SubscriptionNode node = _lastSubscriptionNode.get();
+ SubscriptionList.SubscriptionNode nextNode = node.getNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().findNext();
+ nextNode = _subscriptionList.getHead().getNext();
}
while (nextNode != null)
{
- if (_subscriptionList.updateMarkedNode(node, nextNode))
+ if (_lastSubscriptionNode.compareAndSet(node, nextNode))
{
break;
}
else
{
- node = _subscriptionList.getMarkedNode();
- nextNode = node.findNext();
+ node = _lastSubscriptionNode.get();
+ nextNode = node.getNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().findNext();
+ nextNode = _subscriptionList.getHead().getNext();
}
}
}
@@ -627,7 +629,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// this catches the case where we *just* miss an update
int loops = 2;
- while (entry.isAvailable() && loops != 0)
+ while (!(entry.isAcquired() || entry.isDeleted()) && loops != 0)
{
if (nextNode == null)
{
@@ -640,13 +642,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
Subscription sub = nextNode.getSubscription();
deliverToSubscription(sub, entry);
}
- nextNode = nextNode.findNext();
+ nextNode = nextNode.getNext();
}
}
- if (entry.isAvailable())
+ if (!(entry.isAcquired() || entry.isDeleted()))
{
checkSubscriptionsNotAheadOfDelivery(entry);
@@ -803,6 +805,24 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
+ public void requeue(QueueEntryImpl entry, Subscription subscription)
+ {
+ SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards
+ while (subscriberIter.advance())
+ {
+ Subscription sub = subscriberIter.getNode().getSubscription();
+
+ // we don't make browsers send the same stuff twice
+ if (sub.seesRequeues() && (!sub.acquires() && sub == subscription))
+ {
+ updateSubRequeueEntry(sub, entry);
+ }
+ }
+
+ deliverAsync();
+ }
+
public void dequeue(QueueEntry entry, Subscription sub)
{
decrementQueueCount();
@@ -940,7 +960,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (node != null && !node.isDispensed())
+ if (node != null && !node.isDeleted())
{
entryList.add(node);
}
@@ -1044,7 +1064,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance() && !filter.filterComplete())
{
QueueEntry node = queueListIterator.getNode();
- if (!node.isDispensed() && filter.accept(node))
+ if (!node.isDeleted() && filter.accept(node))
{
entryList.add(node);
}
@@ -1238,6 +1258,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
if ((messageId >= fromMessageId)
&& (messageId <= toMessageId)
+ && !node.isDeleted()
&& node.acquire())
{
dequeueEntry(node);
@@ -1267,7 +1288,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (noDeletes && queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (node.acquire())
+ if (!node.isDeleted() && node.acquire())
{
dequeueEntry(node);
noDeletes = false;
@@ -1297,7 +1318,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (node.acquire())
+ if (!node.isDeleted() && node.acquire())
{
dequeueEntry(node, txn);
if(++count == request)
@@ -1564,7 +1585,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public void deliverAsync()
{
- QueueRunner runner = new QueueRunner(this, _stateChangeCount.incrementAndGet());
+ Runner runner = new Runner(_stateChangeCount.incrementAndGet());
if (_asynchronousRunner.compareAndSet(null, runner))
{
@@ -1583,6 +1604,52 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_asyncDelivery.execute(flusher);
}
+
+ private class Runner implements ReadWriteRunnable
+ {
+ String _name;
+ public Runner(long count)
+ {
+ _name = "QueueRunner-" + count + "-" + _logActor;
+ }
+
+ public void run()
+ {
+ String originalName = Thread.currentThread().getName();
+ try
+ {
+ Thread.currentThread().setName(_name);
+ CurrentActor.set(_logActor);
+
+ processQueue(this);
+ }
+ catch (AMQException e)
+ {
+ _logger.error(e);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ Thread.currentThread().setName(originalName);
+ }
+ }
+
+ public boolean isRead()
+ {
+ return false;
+ }
+
+ public boolean isWrite()
+ {
+ return true;
+ }
+
+ public String toString()
+ {
+ return _name;
+ }
+ }
+
public void flushSubscription(Subscription sub) throws AMQException
{
// Access control
@@ -1651,7 +1718,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = getNextAvailableEntry(sub);
- if (node != null && node.isAvailable())
+ if (node != null && !(node.isAcquired() || node.isDeleted()))
{
if (sub.hasInterest(node))
{
@@ -1712,7 +1779,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen);
boolean expired = false;
- while (node != null && (!node.isAvailable() || (expired = node.expired()) || !sub.hasInterest(node)))
+ while (node != null && (node.isAcquired() || node.isDeleted() || (expired = node.expired()) || !sub.hasInterest(node)))
{
if (expired)
{
@@ -1741,40 +1808,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
- /**
- * Used by queue Runners to asynchronously deliver messages to consumers.
- *
- * A queue Runner is started whenever a state change occurs, e.g when a new
- * message arrives on the queue and cannot be immediately delivered to a
- * subscription (i.e. asynchronous delivery is required). Unless there are
- * SubFlushRunners operating (due to subscriptions unsuspending) which are
- * capable of accepting/delivering all messages then these messages would
- * otherwise remain on the queue.
- *
- * processQueue should be running while there are messages on the queue AND
- * there are subscriptions that can deliver them. If there are no
- * subscriptions capable of delivering the remaining messages on the queue
- * then processQueue should stop to prevent spinning.
- *
- * Since processQueue is runs in a fixed size Executor, it should not run
- * indefinitely to prevent starving other tasks of CPU (e.g jobs to process
- * incoming messages may not be able to be scheduled in the thread pool
- * because all threads are working on clearing down large queues). To solve
- * this problem, after an arbitrary number of message deliveries the
- * processQueue job stops iterating, resubmits itself to the executor, and
- * ends the current instance
- *
- * @param runner the Runner to schedule
- * @throws AMQException
- */
- public void processQueue(QueueRunner runner) throws AMQException
+ private void processQueue(Runnable runner) throws AMQException
{
long stateChangeCount;
long previousStateChangeCount = Long.MIN_VALUE;
boolean deliveryIncomplete = true;
- boolean lastLoop = false;
- int iterations = MAX_ASYNC_DELIVERIES;
+ int extraLoops = 1;
+ long iterations = MAX_ASYNC_DELIVERIES;
_asynchronousRunner.compareAndSet(runner, null);
@@ -1791,14 +1832,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
if (previousStateChangeCount != stateChangeCount)
{
- //further asynchronous delivery is required since the
- //previous loop. keep going if iteration slicing allows.
- lastLoop = false;
+ extraLoops = 1;
}
previousStateChangeCount = stateChangeCount;
- boolean allSubscriptionsDone = true;
- boolean subscriptionDone;
+ deliveryIncomplete = _subscriptionList.size() != 0;
+ boolean done;
SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
//iterate over the subscribers and try to advance their pointer
@@ -1808,25 +1847,30 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
sub.getSendLock();
try
{
- //attempt delivery. returns true if no further delivery currently possible to this sub
- subscriptionDone = attemptDelivery(sub);
- if (subscriptionDone)
+
+ done = attemptDelivery(sub);
+
+ if (done)
{
- //close autoClose subscriptions if we are not currently intent on continuing
- if (lastLoop && sub.isAutoClose())
+ if (extraLoops == 0)
{
- unregisterSubscription(sub);
+ deliveryIncomplete = false;
+ if (sub.isAutoClose())
+ {
+ unregisterSubscription(sub);
- sub.confirmAutoClose();
+ sub.confirmAutoClose();
+ }
+ }
+ else
+ {
+ extraLoops--;
}
}
else
{
- //this subscription can accept additional deliveries, so we must
- //keep going after this (if iteration slicing allows it)
- allSubscriptionsDone = false;
- lastLoop = false;
iterations--;
+ extraLoops = 1;
}
}
finally
@@ -1834,34 +1878,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
sub.releaseSendLock();
}
}
-
- if(allSubscriptionsDone && lastLoop)
- {
- //We have done an extra loop already and there are again
- //again no further delivery attempts possible, only
- //keep going if state change demands it.
- deliveryIncomplete = false;
- }
- else if(allSubscriptionsDone)
- {
- //All subscriptions reported being done, but we have to do
- //an extra loop if the iterations are not exhausted and
- //there is still any work to be done
- deliveryIncomplete = _subscriptionList.size() != 0;
- lastLoop = true;
- }
- else
- {
- //some subscriptions can still accept more messages,
- //keep going if iteration count allows.
- lastLoop = false;
- deliveryIncomplete = true;
- }
-
_asynchronousRunner.set(null);
}
- // If iterations == 0 then the limiting factor was the time-slicing rather than available messages or credit
+ // If deliveries == 0 then the limitting factor was the time-slicing rather than available messages or credit
// therefore we should schedule this runner again (unless someone beats us to it :-) ).
if (iterations == 0 && _asynchronousRunner.compareAndSet(null, runner))
{
@@ -1881,8 +1901,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- // Only process nodes that are not currently deleted and not dequeued
- if (!node.isDispensed())
+ // Only process nodes that are not currently deleted
+ if (!node.isDeleted())
{
// If the node has exired then aquire it
if (node.expired() && node.acquire())
@@ -2222,9 +2242,4 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
}
}
-
- public LogActor getLogActor()
- {
- return _logActor;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
index 46baab8c85..b97c2c55c5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -1,5 +1,6 @@
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.message.ServerMessage;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -155,7 +156,7 @@ public class SimpleQueueEntryList implements QueueEntryList
if(!atTail())
{
QueueEntryImpl nextNode = _lastNode.nextNode();
- while(nextNode.isDispensed() && nextNode.nextNode() != null)
+ while(nextNode.isDeleted() && nextNode.nextNode() != null)
{
nextNode = nextNode.nextNode();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index c07074f69c..78a642f22f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -21,14 +21,9 @@
package org.apache.qpid.server.registry;
import java.net.InetSocketAddress;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
import java.util.UUID;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -46,27 +41,23 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.logging.CompositeStartupMessageLogger;
import org.apache.qpid.server.logging.Log4jMessageLogger;
import org.apache.qpid.server.logging.RootMessageLogger;
+import org.apache.qpid.server.logging.AbstractRootMessageLogger;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
-import org.apache.qpid.server.logging.actors.AbstractActor;
import org.apache.qpid.server.logging.actors.BrokerActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.BrokerMessages;
-import org.apache.qpid.server.logging.messages.VirtualHostMessages;
import org.apache.qpid.server.management.ManagedObjectRegistry;
import org.apache.qpid.server.management.NoopManagedObjectRegistry;
-import org.apache.qpid.server.plugins.Plugin;
import org.apache.qpid.server.plugins.PluginManager;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration;
+import org.apache.qpid.server.security.auth.database.ConfigurationFilePrincipalDatabaseManager;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
-import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import org.apache.qpid.server.transport.QpidAcceptor;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.osgi.framework.BundleContext;
-
/**
* An abstract application registry that provides access to configuration information and handles the
@@ -78,10 +69,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
protected static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
- private static AtomicReference<IApplicationRegistry> _instance = new AtomicReference<IApplicationRegistry>(null);
+ private static Map<Integer, IApplicationRegistry> _instanceMap = new HashMap<Integer, IApplicationRegistry>();
protected final ServerConfiguration _configuration;
+ public static final int DEFAULT_INSTANCE = 1;
+
protected final Map<InetSocketAddress, QpidAcceptor> _acceptors = new HashMap<InetSocketAddress, QpidAcceptor>();
protected ManagedObjectRegistry _managedObjectRegistry;
@@ -92,6 +85,8 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
protected SecurityManager _securityManager;
+ protected PrincipalDatabaseManager _databaseManager;
+
protected PluginManager _pluginManager;
protected ConfigurationManager _configurationManager;
@@ -107,12 +102,8 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private BrokerConfig _broker;
private ConfigStore _configStore;
-
- private Timer _reportingTimer;
- private boolean _statisticsEnabled = false;
- private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
- private BundleContext _bundleContext;
+ protected String _registryName;
static
{
@@ -123,54 +114,53 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
public void run()
{
- remove();
+ removeAll();
}
}
public static void initialise(IApplicationRegistry instance) throws Exception
{
- if(instance == null)
- {
- throw new IllegalArgumentException("ApplicationRegistry instance must not be null");
- }
+ initialise(instance, DEFAULT_INSTANCE);
+ }
- if(!_instance.compareAndSet(null, instance))
+ @SuppressWarnings("finally")
+ public static void initialise(IApplicationRegistry instance, int instanceID) throws Exception
+ {
+ if (instance != null)
{
- throw new IllegalStateException("An ApplicationRegistry is already initialised");
- }
-
- _logger.info("Initialising Application Registry(" + instance + ")");
-
-
- final ConfigStore store = ConfigStore.newInstance();
- store.setRoot(new SystemConfigImpl(store));
- instance.setConfigStore(store);
+ _logger.info("Initialising Application Registry(" + instance + "):" + instanceID);
+ _instanceMap.put(instanceID, instance);
- BrokerConfig broker = new BrokerConfigAdapter(instance);
+ final ConfigStore store = ConfigStore.newInstance();
+ store.setRoot(new SystemConfigImpl(store));
+ instance.setConfigStore(store);
- SystemConfig system = (SystemConfig) store.getRoot();
- system.addBroker(broker);
- instance.setBroker(broker);
+ BrokerConfig broker = new BrokerConfigAdapter(instance);
- try
- {
- instance.initialise();
- }
- catch (Exception e)
- {
- _instance.set(null);
+ SystemConfig system = (SystemConfig) store.getRoot();
+ system.addBroker(broker);
+ instance.setBroker(broker);
- //remove the Broker instance, then re-throw
try
{
- system.removeBroker(broker);
+ instance.initialise(instanceID);
}
- catch(Throwable t)
+ catch (Exception e)
{
- //ignore
+ _instanceMap.remove(instanceID);
+ try
+ {
+ system.removeBroker(broker);
+ }
+ finally
+ {
+ throw e;
+ }
}
-
- throw e;
+ }
+ else
+ {
+ remove(instanceID);
}
}
@@ -186,19 +176,35 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public static boolean isConfigured()
{
- return _instance.get() != null;
+ return isConfigured(DEFAULT_INSTANCE);
+ }
+
+ public static boolean isConfigured(int instanceID)
+ {
+ return _instanceMap.containsKey(instanceID);
}
+ /** Method to cleanly shutdown the default registry running in this JVM */
public static void remove()
{
- IApplicationRegistry instance = _instance.getAndSet(null);
+ remove(DEFAULT_INSTANCE);
+ }
+
+ /**
+ * Method to cleanly shutdown specified registry running in this JVM
+ *
+ * @param instanceID the instance to shutdown
+ */
+ public static void remove(int instanceID)
+ {
try
{
+ IApplicationRegistry instance = _instanceMap.get(instanceID);
if (instance != null)
{
if (_logger.isInfoEnabled())
{
- _logger.info("Shutting down ApplicationRegistry(" + instance + ")");
+ _logger.info("Shutting down ApplicationRegistry(" + instanceID + "):" + instance);
}
instance.close();
instance.getBroker().getSystem().removeBroker(instance.getBroker());
@@ -206,19 +212,27 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
catch (Exception e)
{
- _logger.error("Error shutting down Application Registry(" + instance + "): " + e, e);
+ _logger.error("Error shutting down Application Registry(" + instanceID + "): " + e, e);
+ }
+ finally
+ {
+ _instanceMap.remove(instanceID);
}
}
- protected ApplicationRegistry(ServerConfiguration configuration)
+ /** Method to cleanly shutdown all registries currently running in this JVM */
+ public static void removeAll()
{
- this(configuration, null);
+ Object[] keys = _instanceMap.keySet().toArray();
+ for (Object k : keys)
+ {
+ remove((Integer) k);
+ }
}
- protected ApplicationRegistry(ServerConfiguration configuration, BundleContext bundleContext)
+ protected ApplicationRegistry(ServerConfiguration configuration)
{
_configuration = configuration;
- _bundleContext = bundleContext;
}
public void configure() throws ConfigurationException
@@ -227,7 +241,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
- _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory(), _bundleContext);
+ _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory());
}
catch (Exception e)
{
@@ -237,10 +251,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_configuration.initialise();
}
- public void initialise() throws Exception
+ public void initialise(int instanceID) throws Exception
{
//Create the RootLogger to be used during broker operation
_rootMessageLogger = new Log4jMessageLogger(_configuration);
+ _registryName = String.valueOf(instanceID);
//Create the composite (log4j+SystemOut MessageLogger to be used during startup
RootMessageLogger[] messageLoggers = {new SystemOutMessageLogger(), _rootMessageLogger};
@@ -262,7 +277,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_securityManager = new SecurityManager(_configuration, _pluginManager);
- _authenticationManager = createAuthenticationManager();
+ createDatabaseManager(_configuration);
+
+ _authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null);
+
+ _databaseManager.initialiseManagement(_configuration);
_managedObjectRegistry.start();
}
@@ -275,8 +294,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
initialiseVirtualHosts();
- initialiseStatistics();
- initialiseStatisticsReporting();
}
finally
{
@@ -285,51 +302,9 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
- /**
- * Iterates across all discovered authentication manager factories, offering the security configuration to each.
- * Expects <b>exactly</b> one authentication manager to configure and initialise itself.
- *
- * It is an error to configure more than one authentication manager, or to configure none.
- *
- * @return authentication manager
- * @throws ConfigurationException
- */
- protected AuthenticationManager createAuthenticationManager() throws ConfigurationException
+ protected void createDatabaseManager(ServerConfiguration configuration) throws Exception
{
- final SecurityConfiguration securityConfiguration = _configuration.getConfiguration(SecurityConfiguration.class.getName());
- final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories = _pluginManager.getAuthenticationManagerPlugins().values();
-
- if (factories.size() == 0)
- {
- throw new ConfigurationException("No authentication manager factory plugins found. Check the desired authentication" +
- "manager plugin has been placed in the plugins directory.");
- }
-
- AuthenticationManager authMgr = null;
-
- for (final Iterator<AuthenticationManagerPluginFactory<? extends Plugin>> iterator = factories.iterator(); iterator.hasNext();)
- {
- final AuthenticationManagerPluginFactory<? extends Plugin> factory = (AuthenticationManagerPluginFactory<? extends Plugin>) iterator.next();
- final AuthenticationManager tmp = factory.newInstance(securityConfiguration);
- if (tmp != null)
- {
- if (authMgr != null)
- {
- throw new ConfigurationException("Cannot configure more than one authentication manager."
- + " Both " + tmp.getClass() + " and " + authMgr.getClass() + " are configured."
- + " Remove configuration for one of the authentication manager, or remove the plugin JAR"
- + " from the classpath.");
- }
- authMgr = tmp;
- }
- }
-
- if (authMgr == null)
- {
- throw new ConfigurationException("No authentication managers configured within the configure file.");
- }
-
- return authMgr;
+ _databaseManager = new ConfigurationFilePrincipalDatabaseManager(_configuration);
}
protected void initialiseVirtualHosts() throws Exception
@@ -345,88 +320,26 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_managedObjectRegistry = new NoopManagedObjectRegistry();
}
-
- public void initialiseStatisticsReporting()
- {
- long report = _configuration.getStatisticsReportingPeriod() * 1000; // convert to ms
- final boolean broker = _configuration.isStatisticsGenerationBrokerEnabled();
- final boolean virtualhost = _configuration.isStatisticsGenerationVirtualhostsEnabled();
- final boolean reset = _configuration.isStatisticsReportResetEnabled();
-
- /* add a timer task to report statistics if generation is enabled for broker or virtualhosts */
- if (report > 0L && (broker || virtualhost))
- {
- _reportingTimer = new Timer("Statistics-Reporting", true);
-
- class StatisticsReportingTask extends TimerTask
- {
- private final int DELIVERED = 0;
- private final int RECEIVED = 1;
-
- public void run()
- {
- CurrentActor.set(new AbstractActor(ApplicationRegistry.getInstance().getRootMessageLogger()) {
- public String getLogMessage()
- {
- return "[" + Thread.currentThread().getName() + "] ";
- }
- });
-
- if (broker)
- {
- CurrentActor.get().message(BrokerMessages.STATS_DATA(DELIVERED, _dataDelivered.getPeak() / 1024.0, _dataDelivered.getTotal()));
- CurrentActor.get().message(BrokerMessages.STATS_MSGS(DELIVERED, _messagesDelivered.getPeak(), _messagesDelivered.getTotal()));
- CurrentActor.get().message(BrokerMessages.STATS_DATA(RECEIVED, _dataReceived.getPeak() / 1024.0, _dataReceived.getTotal()));
- CurrentActor.get().message(BrokerMessages.STATS_MSGS(RECEIVED, _messagesReceived.getPeak(), _messagesReceived.getTotal()));
- }
-
- if (virtualhost)
- {
- for (VirtualHost vhost : getVirtualHostRegistry().getVirtualHosts())
- {
- String name = vhost.getName();
- StatisticsCounter dataDelivered = vhost.getDataDeliveryStatistics();
- StatisticsCounter messagesDelivered = vhost.getMessageDeliveryStatistics();
- StatisticsCounter dataReceived = vhost.getDataReceiptStatistics();
- StatisticsCounter messagesReceived = vhost.getMessageReceiptStatistics();
-
- CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, DELIVERED, dataDelivered.getPeak() / 1024.0, dataDelivered.getTotal()));
- CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, DELIVERED, messagesDelivered.getPeak(), messagesDelivered.getTotal()));
- CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, RECEIVED, dataReceived.getPeak() / 1024.0, dataReceived.getTotal()));
- CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, RECEIVED, messagesReceived.getPeak(), messagesReceived.getTotal()));
- }
- }
-
- if (reset)
- {
- resetStatistics();
- }
-
- CurrentActor.remove();
- }
- }
- _reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(),
- report / 2,
- report);
- }
+ public static IApplicationRegistry getInstance()
+ {
+ return getInstance(DEFAULT_INSTANCE);
}
- /**
- * Get the ApplicationRegistry
- * @return the IApplicationRegistry instance
- * @throws IllegalStateException if no registry instance has been initialised.
- */
- public static IApplicationRegistry getInstance() throws IllegalStateException
+ public static IApplicationRegistry getInstance(int instanceID)
{
- IApplicationRegistry iApplicationRegistry = _instance.get();
- if (iApplicationRegistry == null)
- {
- throw new IllegalStateException("No ApplicationRegistry has been initialised");
- }
- else
+ synchronized (IApplicationRegistry.class)
{
- return iApplicationRegistry;
+ IApplicationRegistry instance = _instanceMap.get(instanceID);
+
+ if (instance == null)
+ {
+ throw new IllegalStateException("Application Registry (" + instanceID + ") not created");
+ }
+ else
+ {
+ return instance;
+ }
}
}
@@ -456,12 +369,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_logger.info("Shutting down ApplicationRegistry:" + this);
}
-
- //Stop Statistics Reporting
- if (_reportingTimer != null)
- {
- _reportingTimer.cancel();
- }
//Stop incoming connections
unbind();
@@ -469,6 +376,10 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
//Shutdown virtualhosts
close(_virtualHostRegistry);
+// close(_accessManager);
+//
+// close(_databaseManager);
+
close(_authenticationManager);
close(_managedObjectRegistry);
@@ -490,7 +401,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
- acceptor.getNetworkTransport().close();
+ acceptor.getNetworkDriver().close();
}
catch (Throwable e)
{
@@ -530,6 +441,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _managedObjectRegistry;
}
+ public PrincipalDatabaseManager getDatabaseManager()
+ {
+ return _databaseManager;
+ }
+
public AuthenticationManager getAuthenticationManager()
{
return _authenticationManager;
@@ -577,81 +493,9 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception
{
- VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig, null);
+ VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig);
_virtualHostRegistry.registerVirtualHost(virtualHost);
getBroker().addVirtualHost(virtualHost);
return virtualHost;
}
-
- public void registerMessageDelivered(long messageSize)
- {
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
- }
-
- public void registerMessageReceived(long messageSize, long timestamp)
- {
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
- }
-
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return _messagesReceived;
- }
-
- public StatisticsCounter getDataReceiptStatistics()
- {
- return _dataReceived;
- }
-
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return _messagesDelivered;
- }
-
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return _dataDelivered;
- }
-
- public void resetStatistics()
- {
- _messagesDelivered.reset();
- _dataDelivered.reset();
- _messagesReceived.reset();
- _dataReceived.reset();
-
- for (VirtualHost vhost : _virtualHostRegistry.getVirtualHosts())
- {
- vhost.resetStatistics();
- }
- }
-
- public void initialiseStatistics()
- {
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- getConfiguration().isStatisticsGenerationBrokerEnabled());
-
- _messagesDelivered = new StatisticsCounter("messages-delivered");
- _dataDelivered = new StatisticsCounter("bytes-delivered");
- _messagesReceived = new StatisticsCounter("messages-received");
- _dataReceived = new StatisticsCounter("bytes-received");
- }
-
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
index 108533ef96..4a4253153c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java
@@ -71,7 +71,7 @@ public class BrokerConfigAdapter implements BrokerConfig
public Integer getWorkerThreads()
{
- return _instance.getConfiguration().getConnectorProcessors();
+ return _instance.getConfiguration().getProcessors();
}
public Integer getMaxConnections()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index 9121f8f927..ff2a8c959b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -29,18 +29,12 @@ import org.apache.qpid.server.logging.actors.BrokerActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.management.JMXManagedObjectRegistry;
import org.apache.qpid.server.management.NoopManagedObjectRegistry;
-import org.osgi.framework.BundleContext;
public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
public ConfigurationFileApplicationRegistry(File configurationURL) throws ConfigurationException
{
- this(configurationURL, null);
- }
-
- public ConfigurationFileApplicationRegistry(File configurationURL, BundleContext bundleContext) throws ConfigurationException
- {
- super(new ServerConfiguration(configurationURL), bundleContext);
+ super(new ServerConfiguration(configurationURL));
}
@Override
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
index c27e0d19ec..228c3b9112 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
@@ -33,20 +33,21 @@ import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.management.ManagedObjectRegistry;
import org.apache.qpid.server.plugins.PluginManager;
import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.transport.QpidAcceptor;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-public interface IApplicationRegistry extends StatisticsGatherer
+public interface IApplicationRegistry
{
/**
* Initialise the application registry. All initialisation must be done in this method so that any components
* that need access to the application registry itself for initialisation are able to use it. Attempting to
* initialise in the constructor will lead to failures since the registry reference will not have been set.
+ * @param instanceID the instanceID that we can use to identify this AR.
*/
- void initialise() throws Exception;
+ void initialise(int instanceID) throws Exception;
/**
* Shutdown this Registry
@@ -62,6 +63,8 @@ public interface IApplicationRegistry extends StatisticsGatherer
ManagedObjectRegistry getManagedObjectRegistry();
+ PrincipalDatabaseManager getDatabaseManager();
+
AuthenticationManager getAuthenticationManager();
VirtualHostRegistry getVirtualHostRegistry();
@@ -94,6 +97,4 @@ public interface IApplicationRegistry extends StatisticsGatherer
ConfigStore getConfigStore();
void setConfigStore(ConfigStore store);
-
- void initialiseStatisticsReporting();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java b/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java
deleted file mode 100755
index 3d8c77a86f..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java
+++ /dev/null
@@ -1,53 +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.
- *
- */
-package org.apache.qpid.server.security;
-
-import java.security.Principal;
-
-import javax.security.auth.Subject;
-
-import org.apache.qpid.server.security.auth.sasl.GroupPrincipal;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-
-/**
- * Represents the authorization of the logged on user.
- *
- */
-public interface AuthorizationHolder
-{
- /**
- * Returns the {@link Subject} of the authorized user. This is guaranteed to
- * contain at least one {@link UsernamePrincipal}, representing the the identity
- * used when the user logged on to the application, and zero or more {@link GroupPrincipal}
- * representing the group(s) to which the user belongs.
- *
- * @return the Subject
- */
- Subject getAuthorizedSubject();
-
- /**
- * Returns the {@link Principal} representing the the identity
- * used when the user logged on to the application.
- *
- * @return a Principal
- */
- Principal getAuthorizedPrincipal();
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java b/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java
new file mode 100755
index 0000000000..7e93623cab
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security;
+
+import java.security.Principal;
+
+public interface PrincipalHolder
+{
+ /** @return a Principal that was used to authorized this session */
+ Principal getPrincipal();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index f582fed6a0..f18c327692 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -18,19 +18,8 @@
*/
package org.apache.qpid.server.security;
-import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
-import static org.apache.qpid.server.security.access.ObjectType.METHOD;
-import static org.apache.qpid.server.security.access.ObjectType.OBJECT;
-import static org.apache.qpid.server.security.access.ObjectType.QUEUE;
-import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST;
-import static org.apache.qpid.server.security.access.Operation.ACCESS;
-import static org.apache.qpid.server.security.access.Operation.BIND;
-import static org.apache.qpid.server.security.access.Operation.CONSUME;
-import static org.apache.qpid.server.security.access.Operation.CREATE;
-import static org.apache.qpid.server.security.access.Operation.DELETE;
-import static org.apache.qpid.server.security.access.Operation.PUBLISH;
-import static org.apache.qpid.server.security.access.Operation.PURGE;
-import static org.apache.qpid.server.security.access.Operation.UNBIND;
+import static org.apache.qpid.server.security.access.ObjectType.*;
+import static org.apache.qpid.server.security.access.Operation.*;
import java.net.SocketAddress;
import java.security.Principal;
@@ -40,8 +29,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import javax.security.auth.Subject;
-
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -50,9 +37,11 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
/**
* The security manager contains references to all loaded {@link SecurityPlugin}s and delegates security decisions to them based
@@ -66,7 +55,7 @@ public class SecurityManager
private static final Logger _logger = Logger.getLogger(SecurityManager.class);
/** Container for the {@link Principal} that is using to this thread. */
- private static final ThreadLocal<Subject> _subject = new ThreadLocal<Subject>();
+ private static final ThreadLocal<Principal> _principal = new ThreadLocal<Principal>();
private PluginManager _pluginManager;
private Map<String, SecurityPluginFactory> _pluginFactories = new HashMap<String, SecurityPluginFactory>();
@@ -137,14 +126,19 @@ public class SecurityManager
configureHostPlugins(configuration);
}
- public static Subject getThreadSubject()
+ public static Principal getThreadPrincipal()
+ {
+ return _principal.get();
+ }
+
+ public static void setThreadPrincipal(Principal principal)
{
- return _subject.get();
+ _principal.set(principal);
}
- public static void setThreadSubject(final Subject subject)
+ public static void setThreadPrincipal(String authId)
{
- _subject.set(subject);
+ setThreadPrincipal(new UsernamePrincipal(authId));
}
public void configureHostPlugins(ConfigurationPlugin hostConfig) throws ConfigurationException
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
index e4bf8df340..70a9ea5356 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
@@ -149,9 +149,9 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String>
{
put(Property.OWNER, queue.getOwner());
}
- else if (queue.getAuthorizationHolder() != null)
+ else if (queue.getPrincipalHolder() != null)
{
- put(Property.OWNER, queue.getAuthorizationHolder().getAuthorizedPrincipal().getName());
+ put(Property.OWNER, queue.getPrincipalHolder().getPrincipal().getName());
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
index 8c2d60a660..62967ef7eb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
@@ -20,93 +20,42 @@
*/
package org.apache.qpid.server.security.auth;
-import javax.security.auth.Subject;
-
-/**
- * Encapsulates the result of an attempt to authenticate.
- * <p>
- * The authentication status describes the overall outcome.
- * <p>
- * <ol>
- * <li>If authentication status is SUCCESS, the subject will be populated.
- * </li>
- * <li>If authentication status is CONTINUE, the authentication has failed because the user
- * supplied incorrect credentials (etc). If the authentication requires it, the next challenge
- * is made available.
- * </li>
- * <li>If authentication status is ERROR , the authentication decision could not be made due
- * to a failure (such as an external system), the {@link AuthenticationResult#getCause()}
- * will provide the underlying exception.
- * </li>
- * </ol>
- *
- */
public class AuthenticationResult
{
public enum AuthenticationStatus
{
- /** Authentication successful */
- SUCCESS,
- /** Authentication not successful due to credentials problem etc */
- CONTINUE,
- /** Problem prevented the authentication from being made e.g. failure of an external system */
- ERROR
+ SUCCESS, CONTINUE, ERROR
}
- public final AuthenticationStatus _status;
- public final byte[] _challenge;
- private final Exception _cause;
- private final Subject _subject;
+ public AuthenticationStatus status;
+ public byte[] challenge;
+
+ private Exception cause;
- public AuthenticationResult(final AuthenticationStatus status)
+ public AuthenticationResult(AuthenticationStatus status)
{
this(null, status, null);
}
- public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status)
+ public AuthenticationResult(byte[] challenge, AuthenticationStatus status)
{
this(challenge, status, null);
}
- public AuthenticationResult(final AuthenticationStatus error, final Exception cause)
+ public AuthenticationResult(AuthenticationStatus error, Exception cause)
{
this(null, error, cause);
}
- public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status, final Exception cause)
- {
- this._status = status;
- this._challenge = challenge;
- this._cause = cause;
- this._subject = null;
- }
-
- public AuthenticationResult(final Subject subject)
+ public AuthenticationResult(byte[] challenge, AuthenticationStatus status, Exception cause)
{
- this._status = AuthenticationStatus.SUCCESS;
- this._challenge = null;
- this._cause = null;
- this._subject = subject;
+ this.status = status;
+ this.challenge = challenge;
+ this.cause = cause;
}
public Exception getCause()
{
- return _cause;
- }
-
- public AuthenticationStatus getStatus()
- {
- return _status;
- }
-
- public byte[] getChallenge()
- {
- return _challenge;
+ return cause;
}
-
- public Subject getSubject()
- {
- return _subject;
- }
-
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
new file mode 100644
index 0000000000..5cebb7d2d8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
@@ -0,0 +1,221 @@
+/*
+ *
+ * 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 org.apache.qpid.server.security.auth.database;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.configuration.PropertyUtils;
+import org.apache.qpid.configuration.PropertyException;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
+import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
+import org.apache.qpid.AMQException;
+
+import javax.management.JMException;
+
+public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatabaseManager
+{
+ private static final Logger _logger = Logger.getLogger(ConfigurationFilePrincipalDatabaseManager.class);
+
+ Map<String, PrincipalDatabase> _databases;
+
+ public ConfigurationFilePrincipalDatabaseManager(ServerConfiguration _configuration) throws Exception
+ {
+ _logger.info("Initialising PrincipalDatabase authentication manager");
+ _databases = initialisePrincipalDatabases(_configuration);
+ }
+
+ private Map<String, PrincipalDatabase> initialisePrincipalDatabases(ServerConfiguration _configuration) throws Exception
+ {
+ List<String> databaseNames = _configuration.getPrincipalDatabaseNames();
+ List<String> databaseClasses = _configuration.getPrincipalDatabaseClass();
+ Map<String, PrincipalDatabase> databases = new HashMap<String, PrincipalDatabase>();
+
+ if (databaseNames.size() == 0)
+ {
+ _logger.warn("No Principal databases specified. Broker running with NO AUTHENTICATION");
+ }
+
+ for (int i = 0; i < databaseNames.size(); i++)
+ {
+ Object o;
+ try
+ {
+ o = Class.forName(databaseClasses.get(i)).newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Error initialising principal database: " + e, e);
+ }
+
+ if (!(o instanceof PrincipalDatabase))
+ {
+ throw new Exception("Principal databases must implement the PrincipalDatabase interface");
+ }
+
+ initialisePrincipalDatabase((PrincipalDatabase) o, _configuration, i);
+
+ String name = databaseNames.get(i);
+ if ((name == null) || (name.length() == 0))
+ {
+ throw new Exception("Principal database names must have length greater than or equal to one character");
+ }
+
+ PrincipalDatabase pd = databases.get(name);
+ if (pd != null)
+ {
+ throw new Exception("Duplicate principal database name not permitted");
+ }
+
+ _logger.info("Initialised principal database '" + name + "' successfully");
+ databases.put(name, (PrincipalDatabase) o);
+ }
+
+ return databases;
+ }
+
+ private void initialisePrincipalDatabase(PrincipalDatabase principalDatabase, ServerConfiguration _configuration, int index)
+ throws FileNotFoundException, ConfigurationException
+ {
+ List<String> argumentNames = _configuration.getPrincipalDatabaseAttributeNames(index);
+ List<String> argumentValues = _configuration.getPrincipalDatabaseAttributeValues(index);
+ for (int i = 0; i < argumentNames.size(); i++)
+ {
+ String argName = argumentNames.get(i);
+ if ((argName == null) || (argName.length() == 0))
+ {
+ throw new ConfigurationException("Argument names must have length >= 1 character");
+ }
+
+ if (Character.isLowerCase(argName.charAt(0)))
+ {
+ argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
+ }
+
+ String methodName = "set" + argName;
+ Method method = null;
+ try
+ {
+ method = principalDatabase.getClass().getMethod(methodName, String.class);
+ }
+ catch (Exception e)
+ {
+ // do nothing.. as on error method will be null
+ }
+
+ if (method == null)
+ {
+ throw new ConfigurationException("No method " + methodName + " found in class "
+ + principalDatabase.getClass()
+ + " hence unable to configure principal database. The method must be public and "
+ + "have a single String argument with a void return type");
+ }
+
+ try
+ {
+ method.invoke(principalDatabase, PropertyUtils.replaceProperties(argumentValues.get(i)));
+ }
+ catch (Exception ite)
+ {
+ if (ite instanceof ConfigurationException)
+ {
+ throw(ConfigurationException) ite;
+ }
+ else
+ {
+ throw new ConfigurationException(ite.getMessage(), ite);
+ }
+ }
+ }
+ }
+
+ public Map<String, PrincipalDatabase> getDatabases()
+ {
+ return _databases;
+ }
+
+ public void initialiseManagement(ServerConfiguration config) throws ConfigurationException
+ {
+ try
+ {
+ AMQUserManagementMBean _mbean = new AMQUserManagementMBean();
+
+ List<String> principalDBs = config.getManagementPrincipalDBs();
+ if (principalDBs.isEmpty())
+ {
+ throw new ConfigurationException("No principal-database specified for jmx security");
+ }
+
+ String databaseName = principalDBs.get(0);
+ PrincipalDatabase database = getDatabases().get(databaseName);
+ if (database == null)
+ {
+ throw new ConfigurationException("Principal-database '" + databaseName + "' not found");
+ }
+
+ _mbean.setPrincipalDatabase(database);
+
+ List<String> jmxaccesslist = config.getManagementAccessList();
+ if (jmxaccesslist.isEmpty())
+ {
+ throw new ConfigurationException("No access control files specified for jmx security");
+ }
+
+ String jmxaccesssFile = null;
+
+ try
+ {
+ jmxaccesssFile = PropertyUtils.replaceProperties(jmxaccesslist.get(0));
+ }
+ catch (PropertyException e)
+ {
+ throw new ConfigurationException("Unable to parse access control filename '" + jmxaccesssFile + "'");
+ }
+
+ try
+ {
+ _mbean.setAccessFile(jmxaccesssFile);
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Unable to load access file:" + jmxaccesssFile);
+ }
+
+ _mbean.register();
+ }
+ catch (JMException e)
+ {
+ _logger.warn("User management disabled as unable to create MBean:" + e);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
new file mode 100644
index 0000000000..f9882f8810
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.auth.database;
+
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+
+import java.util.Map;
+
+public interface PrincipalDatabaseManager
+{
+ public Map<String, PrincipalDatabase> getDatabases();
+
+ public void initialiseManagement(ServerConfiguration _configuration) throws ConfigurationException;
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
new file mode 100644
index 0000000000..8658101cd8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
@@ -0,0 +1,49 @@
+/*
+ * 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 org.apache.qpid.server.security.auth.database;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.HashMap;
+
+public class PropertiesPrincipalDatabaseManager implements PrincipalDatabaseManager
+{
+
+ Map<String, PrincipalDatabase> _databases = new HashMap<String, PrincipalDatabase>();
+
+ public PropertiesPrincipalDatabaseManager(String name, Properties users)
+ {
+ _databases.put(name, new PropertiesPrincipalDatabase(users));
+ }
+
+ public Map<String, PrincipalDatabase> getDatabases()
+ {
+ return _databases;
+ }
+
+ public void initialiseManagement(ServerConfiguration _configuration) throws ConfigurationException
+ {
+ //todo
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
index 208130379e..ee4336055b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
@@ -20,9 +20,19 @@
*/
package org.apache.qpid.server.security.auth.management;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
import java.security.Principal;
+import java.util.Enumeration;
import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
@@ -34,13 +44,17 @@ import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
import javax.security.auth.login.AccountNotFoundException;
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.management.common.mbeans.UserManagement;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.management.MBeanInvocationHandlerImpl;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
@@ -51,18 +65,22 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
private PrincipalDatabase _principalDatabase;
+ private Properties _accessRights;
+ private File _accessFile;
+
+ private ReentrantLock _accessRightsUpdate = new ReentrantLock();
// Setup for the TabularType
- private static final TabularType _userlistDataType; // Datatype for representing User Lists
- private static final CompositeType _userDataType; // Composite type for representing User
+ static TabularType _userlistDataType; // Datatype for representing User Lists
+ static CompositeType _userDataType; // Composite type for representing User
static
{
OpenType[] userItemTypes = new OpenType[4]; // User item types.
userItemTypes[0] = SimpleType.STRING; // For Username
- userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - No longer in use
- userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - No longer in use
- userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - No longer is use
+ userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read
+ userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write
+ userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin
try
{
@@ -74,11 +92,12 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
}
catch (OpenDataException e)
{
- _logger.error("Tabular data setup for viewing users incorrect.", e);
- throw new ExceptionInInitializerError("Tabular data setup for viewing users incorrect");
+ _logger.error("Tabular data setup for viewing users incorrect.");
+ _userlistDataType = null;
}
}
+
public AMQUserManagementMBean() throws JMException
{
super(UserManagement.class, UserManagement.TYPE);
@@ -91,23 +110,121 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
public boolean setPassword(String username, String password)
{
+ return setPassword(username, password.toCharArray());
+ }
+
+ public boolean setPassword(String username, char[] password)
+ {
try
{
//delegate password changes to the Principal Database
- return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray());
+ return _principalDatabase.updatePassword(new UsernamePrincipal(username), password);
}
catch (AccountNotFoundException e)
{
- _logger.warn("Attempt to set password of non-existent user'" + username + "'");
+ _logger.warn("Attempt to set password of non-existant user'" + username + "'");
return false;
}
}
- public boolean createUser(String username, String password)
+ public boolean setRights(String username, boolean read, boolean write, boolean admin)
{
- if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray()))
+
+ Object oldRights = null;
+ if ((oldRights =_accessRights.get(username)) == null)
{
- return true;
+ // If the user doesn't exist in the access rights file check that they at least have an account.
+ if (_principalDatabase.getUser(username) == null)
+ {
+ return false;
+ }
+ }
+
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ // Update the access rights
+ if (admin)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.ADMIN);
+ }
+ else
+ {
+ if (read | write)
+ {
+ if (read)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.READONLY);
+ }
+ if (write)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.READWRITE);
+ }
+ }
+ else
+ {
+ _accessRights.remove(username);
+ }
+ }
+
+ //save the rights file
+ try
+ {
+ saveAccessFile();
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
+
+ //the rights file was not successfully saved, restore user rights to previous value
+ _logger.warn("Reverting attempted rights update for user'" + username + "'");
+ if (oldRights != null)
+ {
+ _accessRights.put(username, oldRights);
+ }
+ else
+ {
+ _accessRights.remove(username);
+ }
+
+ return false;
+ }
+ }
+ finally
+ {
+ _accessRightsUpdate.unlock();
+ }
+
+ return true;
+ }
+
+ public boolean createUser(String username, String password, boolean read, boolean write, boolean admin)
+ {
+ return createUser(username, password.toCharArray(), read, write, admin);
+ }
+
+ public boolean createUser(String username, char[] password, boolean read, boolean write, boolean admin)
+ {
+ if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password))
+ {
+ if (!setRights(username, read, write, admin))
+ {
+ //unable to set rights for user, remove account
+ try
+ {
+ _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
+ }
+ catch (AccountNotFoundException e)
+ {
+ //ignore
+ }
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
return false;
@@ -117,7 +234,29 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
{
try
{
- _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
+ if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username)))
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ _accessRights.remove(username);
+
+ try
+ {
+ saveAccessFile();
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
+ return false;
+ }
+ }
+ finally
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
}
catch (AccountNotFoundException e)
{
@@ -130,23 +269,38 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
public boolean reloadData()
{
- try
- {
- _principalDatabase.reload();
- }
- catch (IOException e)
- {
- _logger.warn("Reload failed due to:", e);
- return false;
- }
- // Reload successful
- return true;
+ try
+ {
+ loadAccessFile();
+ _principalDatabase.reload();
+ }
+ catch (ConfigurationException e)
+ {
+ _logger.warn("Reload failed due to:" + e);
+ return false;
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Reload failed due to:" + e);
+ return false;
+ }
+ // Reload successful
+ return true;
}
- @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.")
+ @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.")
public TabularData viewUsers()
{
+ // Table of users
+ // Username(string), Access rights Read,Write,Admin(bool,bool,bool)
+
+ if (_userlistDataType == null)
+ {
+ _logger.warn("TabluarData not setup correctly");
+ return null;
+ }
+
List<Principal> users = _principalDatabase.getUsers();
TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
@@ -157,15 +311,29 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
for (Principal user : users)
{
// Create header attributes list
- // Read,Write,Admin items are depcreated and we return always false.
- Object[] itemData = {user.getName(), false, false, false};
+
+ String rights = (String) _accessRights.get(user.getName());
+
+ Boolean read = false;
+ Boolean write = false;
+ Boolean admin = false;
+
+ if (rights != null)
+ {
+ read = rights.equals(MBeanInvocationHandlerImpl.READONLY)
+ || rights.equals(MBeanInvocationHandlerImpl.READWRITE);
+ write = rights.equals(MBeanInvocationHandlerImpl.READWRITE);
+ admin = rights.equals(MBeanInvocationHandlerImpl.ADMIN);
+ }
+
+ Object[] itemData = {user.getName(), read, write, admin};
CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
userList.put(messageData);
}
}
catch (OpenDataException e)
{
- _logger.warn("Unable to create user list due to :", e);
+ _logger.warn("Unable to create user list due to :" + e);
return null;
}
@@ -183,4 +351,187 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
{
_principalDatabase = database;
}
+
+ /**
+ * setAccessFile
+ *
+ * @param accessFile the file to use for updating.
+ *
+ * @throws java.io.IOException If the file cannot be accessed
+ * @throws org.apache.commons.configuration.ConfigurationException
+ * if checks on the file fail.
+ */
+ public void setAccessFile(String accessFile) throws IOException, ConfigurationException
+ {
+ if (accessFile != null)
+ {
+ _accessFile = new File(accessFile);
+ if (!_accessFile.exists())
+ {
+ throw new ConfigurationException("'" + _accessFile + "' does not exist");
+ }
+
+ if (!_accessFile.canRead())
+ {
+ throw new ConfigurationException("Cannot read '" + _accessFile + "'.");
+ }
+
+ if (!_accessFile.canWrite())
+ {
+ _logger.warn("Unable to write to access rights file '" + _accessFile + "', changes will not be preserved.");
+ }
+
+ loadAccessFile();
+ }
+ else
+ {
+ _logger.warn("Access rights file specified is null. Access rights not changed.");
+ }
+ }
+
+ private void loadAccessFile() throws IOException, ConfigurationException
+ {
+ if(_accessFile == null)
+ {
+ _logger.error("No jmx access rights file has been specified.");
+ return;
+ }
+
+ if(_accessFile.exists())
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ Properties accessRights = new Properties();
+ FileInputStream inStream = new FileInputStream(_accessFile);
+ try
+ {
+ accessRights.load(inStream);
+ }
+ finally
+ {
+ inStream.close();
+ }
+
+ checkAccessRights(accessRights);
+ setAccessRights(accessRights);
+ }
+ finally
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
+ else
+ {
+ _logger.error("Specified jmxaccess rights file '" + _accessFile + "' does not exist.");
+ }
+ }
+
+ private void checkAccessRights(Properties accessRights)
+ {
+ Enumeration values = accessRights.propertyNames();
+
+ while (values.hasMoreElements())
+ {
+ String user = (String) values.nextElement();
+
+ if (_principalDatabase.getUser(user) == null)
+ {
+ _logger.warn("Access rights contains user '" + user + "' but there is no authentication data for that user");
+ }
+ }
+ }
+
+ private void saveAccessFile() throws IOException
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ // Create temporary file
+ Random r = new Random();
+ File tmp;
+ do
+ {
+ tmp = new File(_accessFile.getPath() + r.nextInt() + ".tmp");
+ }
+ while(tmp.exists());
+
+ tmp.deleteOnExit();
+
+ FileOutputStream output = new FileOutputStream(tmp);
+ _accessRights.store(output, "Generated by AMQUserManagementMBean Console : Last edited by user:" + getCurrentJMXUser());
+ output.close();
+
+ // Swap temp file to main rights file.
+ File old = new File(_accessFile.getAbsoluteFile() + ".old");
+ if (old.exists())
+ {
+ old.delete();
+ }
+
+ if(!_accessFile.renameTo(old))
+ {
+ //unable to rename the existing file to the backup name
+ _logger.error("Could not backup the existing management rights file");
+ throw new IOException("Could not backup the existing management rights file");
+ }
+
+ if(!tmp.renameTo(_accessFile))
+ {
+ //failed to rename the new file to the required filename
+
+ if(!old.renameTo(_accessFile))
+ {
+ //unable to return the backup to required filename
+ _logger.error("Could not rename the new management rights file into place, and unable to restore original file");
+ throw new IOException("Could not rename the new management rights file into place, and unable to restore original file");
+ }
+
+ _logger.error("Could not rename the new management rights file into place");
+ throw new IOException("Could not rename the new management rights file into place");
+ }
+ }
+ finally
+ {
+ _accessRightsUpdate.unlock();
+ }
+
+ }
+
+ private String getCurrentJMXUser()
+ {
+ AccessControlContext acc = AccessController.getContext();
+
+ Subject subject = Subject.getSubject(acc);
+ if (subject == null)
+ {
+ return "Unknown user, authentication Subject was null";
+ }
+
+ // Retrieve JMXPrincipal from Subject
+ Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+ if (principals == null || principals.isEmpty())
+ {
+ return "Unknown user principals were null";
+ }
+
+ Principal principal = principals.iterator().next();
+ return principal.getName();
+ }
+
+ /**
+ * user=read user=write user=readwrite user=admin
+ *
+ * @param accessRights The properties list of access rights to process
+ */
+ private void setAccessRights(Properties accessRights)
+ {
+ _logger.debug("Setting Access Rights:" + accessRights);
+ _accessRights = accessRights;
+
+ // TODO check where this is used
+ // MBeanInvocationHandlerImpl.setAccessRights(_accessRights);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
index 4c59c25d84..bc771162fd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
@@ -20,73 +20,17 @@
*/
package org.apache.qpid.server.security.auth.manager;
-import javax.security.auth.Subject;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import org.apache.qpid.common.Closeable;
-import org.apache.qpid.server.plugins.Plugin;
import org.apache.qpid.server.security.auth.AuthenticationResult;
-/**
- * Implementations of the AuthenticationManager are responsible for determining
- * the authenticity of a user's credentials.
- *
- * If the authentication is successful, the manager is responsible for producing a populated
- * {@link Subject} containing the user's identity and zero or more principals representing
- * groups to which the user belongs.
- * <p>
- * The {@link #initialise()} method is responsible for registering SASL mechanisms required by
- * the manager. The {@link #close()} method must reverse this registration.
- *
- */
-public interface AuthenticationManager extends Closeable, Plugin
+public interface AuthenticationManager extends Closeable
{
- /** The name for the required SASL Server mechanisms */
- public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
-
- /**
- * Initialise the authentication plugin.
- *
- */
- void initialise();
-
- /**
- * Gets the SASL mechanisms known to this manager.
- *
- * @return SASL mechanism names, space separated.
- */
String getMechanisms();
- /**
- * Creates a SASL server for the specified mechanism name for the given
- * fully qualified domain name.
- *
- * @param mechanism mechanism name
- * @param localFQDN domain name
- *
- * @return SASL server
- * @throws SaslException
- */
SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
- /**
- * Authenticates a user using SASL negotiation.
- *
- * @param server SASL server
- * @param response SASL response to process
- *
- * @return authentication result
- */
AuthenticationResult authenticate(SaslServer server, byte[] response);
-
- /**
- * Authenticates a user using their username and password.
- *
- * @param username username
- * @param password password
- *
- * @return authentication result
- */
- AuthenticationResult authenticate(String username, String password);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java
deleted file mode 100644
index a51f195761..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java
+++ /dev/null
@@ -1,32 +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.
- *
- */
-package org.apache.qpid.server.security.auth.manager;
-
-import org.apache.qpid.server.plugins.PluginFactory;
-
-/**
- * Factory producing authentication producing configured, initialised authentication
- * managers.
- */
-public interface AuthenticationManagerPluginFactory<S extends AuthenticationManager> extends PluginFactory<S>
-{
-
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index 1945c2e15f..2a967f02af 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -20,65 +20,27 @@
*/
package org.apache.qpid.server.security.auth.manager;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.Security;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.AccountNotFoundException;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-import javax.security.sasl.SaslServerFactory;
-
+import org.apache.log4j.Logger;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.qpid.configuration.PropertyException;
-import org.apache.qpid.configuration.PropertyUtils;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.configuration.VirtualHostConfiguration;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
-import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
import org.apache.qpid.server.security.auth.sasl.JCAProvider;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslServerFactory;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.Sasl;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.TreeMap;
+import java.security.Security;
-/**
- * Concrete implementation of the AuthenticationManager that determines if supplied
- * user credentials match those appearing in a PrincipalDatabase. The implementation
- * of the PrincipalDatabase is determined from the configuration.
- *
- * This implementation also registers the JMX UserManagemement MBean.
- *
- * This plugin expects configuration such as:
- *
- * <pre>
- * &lt;pd-auth-manager&gt;
- * &lt;principal-database&gt;
- * &lt;class&gt;org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase&lt;/class&gt;
- * &lt;attributes&gt;
- * &lt;attribute&gt;
- * &lt;name>passwordFile&lt;/name&gt;
- * &lt;value>${conf}/passwd&lt;/value&gt;
- * &lt;/attribute&gt;
- * &lt;/attributes&gt;
- * &lt;/principal-database&gt;
- * &lt;/pd-auth-manager&gt;
- * </pre>
- */
public class PrincipalDatabaseAuthenticationManager implements AuthenticationManager
{
private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAuthenticationManager.class);
@@ -87,109 +49,55 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private String _mechanisms;
/** Maps from the mechanism to the callback handler to use for handling those requests */
- private final Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
+ private Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
/**
* Maps from the mechanism to the properties used to initialise the server. See the method Sasl.createSaslServer for
* details of the use of these properties. This map is populated during initialisation of each provider.
*/
- private final Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
-
- protected PrincipalDatabase _principalDatabase = null;
+ private Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
- protected AMQUserManagementMBean _mbean = null;
+ private AuthenticationManager _default = null;
+ /** The name for the required SASL Server mechanisms */
+ public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
- public static final AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager>()
+ public PrincipalDatabaseAuthenticationManager(String name, VirtualHostConfiguration hostConfig) throws Exception
{
- public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
- {
- final PrincipalDatabaseAuthenticationManagerConfiguration configuration = config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName());
+ _logger.info("Initialising " + (name == null ? "Default" : "'" + name + "'")
+ + " PrincipalDatabase authentication manager.");
- // If there is no configuration for this plugin then don't load it.
- if (configuration == null)
- {
- _logger.info("No authentication-manager configuration found for PrincipalDatabaseAuthenticationManager");
- return null;
- }
+ // Fixme This should be done per Vhost but allowing global hack isn't right but ...
+ // required as authentication is done before Vhost selection
- final PrincipalDatabaseAuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager();
- pdam.configure(configuration);
- pdam.initialise();
- return pdam;
- }
+ Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
- public Class<PrincipalDatabaseAuthenticationManager> getPluginClass()
- {
- return PrincipalDatabaseAuthenticationManager.class;
- }
- public String getPluginName()
+ if (name == null || hostConfig == null)
{
- return PrincipalDatabaseAuthenticationManager.class.getName();
+ initialiseAuthenticationMechanisms(providerMap, ApplicationRegistry.getInstance().getDatabaseManager().getDatabases());
}
- };
-
- public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin {
-
- public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ else
{
- public List<String> getParentPaths()
- {
- return Arrays.asList("security.pd-auth-manager");
- }
+ String databaseName = hostConfig.getAuthenticationDatabase();
- public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
+ if (databaseName == null)
{
- final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration();
-
- instance.setConfiguration(path, config);
- return instance;
- }
- };
- public String[] getElementsProcessed()
- {
- return new String[] {"principal-database.class",
- "principal-database.attributes.attribute.name",
- "principal-database.attributes.attribute.value"};
- }
-
- public void validateConfiguration() throws ConfigurationException
- {
- }
-
- public String getPrincipalDatabaseClass()
- {
- return _configuration.getString("principal-database.class");
- }
-
- public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
- {
- final List<String> argumentNames = _configuration.getList("principal-database.attributes.attribute.name");
- final List<String> argumentValues = _configuration.getList("principal-database.attributes.attribute.value");
- final Map<String,String> attributes = new HashMap<String,String>(argumentNames.size());
-
- for (int i = 0; i < argumentNames.size(); i++)
+ _default = ApplicationRegistry.getInstance().getAuthenticationManager();
+ return;
+ }
+ else
{
- final String argName = argumentNames.get(i);
- final String argValue = argumentValues.get(i);
+ PrincipalDatabase database = ApplicationRegistry.getInstance().getDatabaseManager().getDatabases().get(databaseName);
- attributes.put(argName, argValue);
- }
+ if (database == null)
+ {
+ throw new ConfigurationException("Requested database:" + databaseName + " was not found");
+ }
- return Collections.unmodifiableMap(attributes);
+ initialiseAuthenticationMechanisms(providerMap, database);
+ }
}
- }
-
- protected PrincipalDatabaseAuthenticationManager()
- {
- }
-
- public void initialise()
- {
- final Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
-
- initialiseAuthenticationMechanisms(providerMap, _principalDatabase);
if (providerMap.size() > 0)
{
@@ -202,16 +110,33 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_logger.info("Additional SASL providers successfully registered.");
}
+
}
else
{
_logger.warn("No additional SASL providers registered.");
}
- registerManagement();
}
- private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database)
+
+ private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, Map<String, PrincipalDatabase> databases) throws Exception
+ {
+ if (databases.size() > 1)
+ {
+ _logger.warn("More than one principle database provided currently authentication mechanism will override each other.");
+ }
+
+ for (Map.Entry<String, PrincipalDatabase> entry : databases.entrySet())
+ {
+ // fixme As the database now provide the mechanisms they support, they will ...
+ // overwrite each other in the map. There should only be one database per vhost.
+ // But currently we must have authentication before vhost definition.
+ initialiseAuthenticationMechanisms(providerMap, entry.getValue());
+ }
+ }
+
+ private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) throws Exception
{
if (database == null || database.getMechanisms().size() == 0)
{
@@ -227,6 +152,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private void initialiseAuthenticationMechanism(String mechanism, AuthenticationProviderInitialiser initialiser,
Map<String, Class<? extends SaslServerFactory>> providerMap)
+ throws Exception
{
if (_mechanisms == null)
{
@@ -247,217 +173,65 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
_logger.info("Initialised " + mechanism + " SASL provider successfully");
}
- /**
- * @see org.apache.qpid.server.plugins.Plugin#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin)
- */
- public void configure(final ConfigurationPlugin config) throws ConfigurationException
- {
- final PrincipalDatabaseAuthenticationManagerConfiguration pdamConfig = (PrincipalDatabaseAuthenticationManagerConfiguration) config;
- final String pdClazz = pdamConfig.getPrincipalDatabaseClass();
-
- _logger.info("PrincipalDatabase concrete implementation : " + pdClazz);
-
- _principalDatabase = createPrincipalDatabaseImpl(pdClazz);
-
- configPrincipalDatabase(_principalDatabase, pdamConfig);
- }
-
public String getMechanisms()
{
- return _mechanisms;
- }
-
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
- {
- return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
- _callbackHandlerMap.get(mechanism));
- }
-
- /**
- * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(SaslServer, byte[])
- */
- public AuthenticationResult authenticate(SaslServer server, byte[] response)
- {
- try
+ if (_default != null)
{
- // Process response from the client
- byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
-
- if (server.isComplete())
- {
- final Subject subject = new Subject();
- subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
- return new AuthenticationResult(subject);
- }
- else
- {
- return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
- }
+ // Use the default AuthenticationManager if present
+ return _default.getMechanisms();
}
- catch (SaslException e)
+ else
{
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ return _mechanisms;
}
}
- /**
- * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
- */
- public AuthenticationResult authenticate(final String username, final String password)
+ public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
{
- try
+ if (_default != null)
{
- if (_principalDatabase.verifyPassword(username, password.toCharArray()))
- {
- final Subject subject = new Subject();
- subject.getPrincipals().add(new UsernamePrincipal(username));
- return new AuthenticationResult(subject);
- }
- else
- {
- return new AuthenticationResult(AuthenticationStatus.CONTINUE);
- }
+ // Use the default AuthenticationManager if present
+ return _default.createSaslServer(mechanism, localFQDN);
}
- catch (AccountNotFoundException e)
+ else
{
- return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+ return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
+ _callbackHandlerMap.get(mechanism));
}
- }
-
- public void close()
- {
- _mechanisms = null;
- Security.removeProvider(PROVIDER_NAME);
- unregisterManagement();
}
- private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException
+ public AuthenticationResult authenticate(SaslServer server, byte[] response)
{
- try
- {
- return (PrincipalDatabase) Class.forName(pdClazz).newInstance();
- }
- catch (InstantiationException ie)
- {
- throw new ConfigurationException("Cannot instantiate " + pdClazz, ie);
- }
- catch (IllegalAccessException iae)
+ // Use the default AuthenticationManager if present
+ if (_default != null)
{
- throw new ConfigurationException("Cannot access " + pdClazz, iae);
+ return _default.authenticate(server, response);
}
- catch (ClassNotFoundException cnfe)
- {
- throw new ConfigurationException("Cannot load " + pdClazz + " implementation", cnfe);
- }
- catch (ClassCastException cce)
- {
- throw new ConfigurationException("Expecting a " + PrincipalDatabase.class + " implementation", cce);
- }
- }
- private void configPrincipalDatabase(final PrincipalDatabase principalDatabase, final PrincipalDatabaseAuthenticationManagerConfiguration config)
- throws ConfigurationException
- {
- final Map<String,String> attributes = config.getPdClassAttributeMap();
-
- for (Iterator<Entry<String, String>> iterator = attributes.entrySet().iterator(); iterator.hasNext();)
+ try
{
- final Entry<String, String> nameValuePair = iterator.next();
- final String methodName = generateSetterName(nameValuePair.getKey());
- final Method method;
- try
- {
- method = principalDatabase.getClass().getMethod(methodName, String.class);
- }
- catch (Exception e)
- {
- throw new ConfigurationException("No method " + methodName + " found in class "
- + principalDatabase.getClass()
- + " hence unable to configure principal database. The method must be public and "
- + "have a single String argument with a void return type", e);
- }
- try
- {
- method.invoke(principalDatabase, PropertyUtils.replaceProperties(nameValuePair.getValue()));
- }
- catch (IllegalArgumentException e)
- {
- throw new ConfigurationException(e.getMessage(), e);
- }
- catch (PropertyException e)
- {
- throw new ConfigurationException(e.getMessage(), e);
- }
- catch (IllegalAccessException e)
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
{
- throw new ConfigurationException(e.getMessage(), e);
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.SUCCESS);
}
- catch (InvocationTargetException e)
+ else
{
- // QPID-1347.. InvocationTargetException wraps the checked exception thrown from the reflective
- // method call. Pull out the underlying message and cause to make these more apparent to the user.
- throw new ConfigurationException(e.getCause().getMessage(), e.getCause());
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
}
}
- }
-
- private String generateSetterName(String argName) throws ConfigurationException
- {
- if ((argName == null) || (argName.length() == 0))
- {
- throw new ConfigurationException("Argument names must have length >= 1 character");
- }
-
- if (Character.isLowerCase(argName.charAt(0)))
- {
- argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
- }
-
- final String methodName = "set" + argName;
- return methodName;
- }
-
- protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase)
- {
- _principalDatabase = principalDatabase;
- }
-
- protected void registerManagement()
- {
- try
- {
- _logger.info("Registering UserManagementMBean");
-
- _mbean = new AMQUserManagementMBean();
- _mbean.setPrincipalDatabase(_principalDatabase);
- _mbean.register();
- }
- catch (Exception e)
+ catch (SaslException e)
{
- _logger.warn("User management disabled as unable to create MBean:", e);
- _mbean = null;
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
}
}
- protected void unregisterManagement()
+ public void close()
{
- try
- {
- if (_mbean != null)
- {
- _logger.info("Unregistering UserManagementMBean");
- _mbean.unregister();
- }
- }
- catch (Exception e)
- {
- _logger.warn("Failed to unregister User management MBean:", e);
- }
- finally
- {
- _mbean = null;
- }
+ Security.removeProvider(PROVIDER_NAME);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
index b7985ad972..0cbbccb3b8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
@@ -20,13 +20,14 @@
*/
package org.apache.qpid.server.security.auth.rmi;
+import java.util.Collections;
+
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
+import javax.security.auth.login.AccountNotFoundException;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
public class RMIPasswordAuthenticator implements JMXAuthenticator
{
@@ -38,15 +39,15 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
static final String CREDENTIALS_REQUIRED = "User details are required. " +
"Please ensure you are using an up to date management console to connect.";
- private AuthenticationManager _authenticationManager = null;
+ private PrincipalDatabase _db = null;
public RMIPasswordAuthenticator()
{
}
-
- public void setAuthenticationManager(final AuthenticationManager authenticationManager)
+
+ public void setPrincipalDatabase(PrincipalDatabase pd)
{
- _authenticationManager = authenticationManager;
+ this._db = pd;
}
public Subject authenticate(Object credentials) throws SecurityException
@@ -64,39 +65,50 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
}
}
- // Verify that required number of credentials.
+ // Verify that required number of credential's.
final String[] userCredentials = (String[]) credentials;
if (userCredentials.length != 2)
{
throw new SecurityException(SHOULD_HAVE_2_ELEMENTS);
}
- final String username = (String) userCredentials[0];
- final String password = (String) userCredentials[1];
+ String username = (String) userCredentials[0];
+ String password = (String) userCredentials[1];
- // Verify that all required credentials are actually present.
+ // Verify that all required credential's are actually present.
if (username == null || password == null)
{
throw new SecurityException(SHOULD_BE_NON_NULL);
}
- // Verify that an AuthenticationManager has been set.
- if (_authenticationManager == null)
+ // Verify that a PD has been set.
+ if (_db == null)
{
throw new SecurityException(UNABLE_TO_LOOKUP);
}
- final AuthenticationResult result = _authenticationManager.authenticate(username, password);
+
+ boolean authenticated = false;
- if (AuthenticationStatus.ERROR.equals(result.getStatus()))
+ // Perform authentication
+ try
{
- throw new SecurityException("Authentication manager failed", result.getCause());
+ if (_db.verifyPassword(username, password.toCharArray()))
+ {
+ authenticated = true;
+ }
+ }
+ catch (AccountNotFoundException e)
+ {
+ throw new SecurityException(INVALID_CREDENTIALS); // XXX
}
- else if (AuthenticationStatus.SUCCESS.equals(result.getStatus()))
+
+ if (authenticated)
{
- final Subject subject = result.getSubject();
- subject.getPrincipals().add(new JMXPrincipal(username));
- subject.setReadOnly();
- return subject;
+ //credential's check out, return the appropriate JAAS Subject
+ return new Subject(true,
+ Collections.singleton(new JMXPrincipal(username)),
+ Collections.EMPTY_SET,
+ Collections.EMPTY_SET);
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
index bc5d8a4f2b..89e545d6f5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
@@ -25,6 +25,9 @@ import java.util.Map;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslServerFactory;
+import org.apache.commons.configuration.Configuration;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+
public interface AuthenticationProviderInitialiser
{
/**
@@ -34,6 +37,24 @@ public interface AuthenticationProviderInitialiser
String getMechanismName();
/**
+ * Initialise the authentication provider.
+ * @param baseConfigPath the path in the config file that points to any config options for this provider. Each
+ * provider can have its own set of configuration options
+ * @param configuration the Apache Commons Configuration instance used to configure this provider
+ * @param principalDatabases the set of principal databases that are available
+ * @throws Exception needs refined Exception is too broad.
+ */
+ void initialise(String baseConfigPath, Configuration configuration,
+ Map<String, PrincipalDatabase> principalDatabases) throws Exception;
+
+ /**
+ * Initialise the authentication provider.
+ * @param db The principal database to initialise with
+ */
+ void initialise(PrincipalDatabase db);
+
+
+ /**
* @return the callback handler that should be used to process authentication requests for this mechanism. This will
* be called after initialise and will be stored by the authentication manager. The callback handler <b>must</b> be
* fully threadsafe.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java
deleted file mode 100644
index 30a503c769..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java
+++ /dev/null
@@ -1,99 +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.
- *
- */
-package org.apache.qpid.server.security.auth.sasl;
-
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.Enumeration;
-
-/**
- * Immutable representation of a user group. In Qpid, groups do <b>not</b> know
- * about their membership, and therefore the {@link #addMember(Principal)}
- * methods etc throw {@link UnsupportedOperationException}.
- *
- */
-public class GroupPrincipal implements Group
-{
- /** Name of the group */
- private final String _groupName;
-
- public GroupPrincipal(final String groupName)
- {
- _groupName = groupName;
- }
-
- public String getName()
- {
- return _groupName;
- }
-
- public boolean addMember(Principal user)
- {
- throw new UnsupportedOperationException("Not supported");
- }
-
- public boolean removeMember(Principal user)
- {
- throw new UnsupportedOperationException("Not supported");
- }
-
- public boolean isMember(Principal member)
- {
- throw new UnsupportedOperationException("Not supported");
- }
-
- public Enumeration<? extends Principal> members()
- {
- throw new UnsupportedOperationException("Not supported");
- }
-
- /**
- * @see java.lang.Object#hashCode()
- */
- public int hashCode()
- {
- final int prime = 37;
- return prime * _groupName.hashCode();
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- else
- {
- if (obj instanceof GroupPrincipal)
- {
- GroupPrincipal other = (GroupPrincipal) obj;
- return _groupName.equals(other._groupName);
- }
- else
- {
- return false;
- }
- }
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
index d6f6c714e2..d6a09d8217 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
@@ -21,11 +21,12 @@
package org.apache.qpid.server.security.auth.sasl;
import java.security.Provider;
+import java.security.Security;
import java.util.Map;
import javax.security.sasl.SaslServerFactory;
-public class JCAProvider extends Provider
+public final class JCAProvider extends Provider
{
public JCAProvider(String name, Map<String, Class<? extends SaslServerFactory>> providerMap)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
index b4ee13fe6b..d7c8383690 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
@@ -21,21 +21,14 @@
package org.apache.qpid.server.security.auth.sasl;
import java.security.Principal;
-import java.util.Set;
-
-import javax.security.auth.Subject;
/** A principal that is just a wrapper for a simple username. */
public class UsernamePrincipal implements Principal
{
- private final String _name;
+ private String _name;
public UsernamePrincipal(String name)
{
- if (name == null)
- {
- throw new IllegalArgumentException("name cannot be null");
- }
_name = name;
}
@@ -48,53 +41,4 @@ public class UsernamePrincipal implements Principal
{
return _name;
}
-
- /**
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode()
- {
- final int prime = 31;
- return prime * _name.hashCode();
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj)
- {
- return true;
- }
- else
- {
- if (obj instanceof UsernamePrincipal)
- {
- UsernamePrincipal other = (UsernamePrincipal) obj;
- return _name.equals(other._name);
- }
- else
- {
- return false;
- }
- }
- }
-
- public static UsernamePrincipal getUsernamePrincipalFromSubject(final Subject authSubject)
- {
- if (authSubject == null)
- {
- throw new IllegalArgumentException("No authenticated subject.");
- }
-
- final Set<UsernamePrincipal> principals = authSubject.getPrincipals(UsernamePrincipal.class);
- if (principals.size() != 1)
- {
- throw new IllegalArgumentException("Can't find single UsernamePrincipal in authenticated subject");
- }
- return principals.iterator().next();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
index dee40e7069..9f56b8521a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.server.security.auth.sasl.amqplain;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
import java.io.IOException;
import javax.security.auth.callback.Callback;
@@ -33,6 +31,7 @@ import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.AMQFrameDecodingException;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
@@ -61,7 +60,7 @@ public class AmqPlainSaslServer implements SaslServer
{
try
{
- final FieldTable ft = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(response)), response.length);
+ final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
String username = (String) ft.getString("LOGIN");
// we do not care about the prompt but it throws if null
NameCallback nameCb = new NameCallback("prompt", username);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
index 17d123eb0d..67d20136bf 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
@@ -45,10 +45,9 @@ public class AmqPlainSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props != null &&
- (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE)))
+ if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
index 52d36023c2..b4cce15d88 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
@@ -20,9 +20,21 @@
*/
package org.apache.qpid.server.security.auth.sasl.anonymous;
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
public class AnonymousSaslServer implements SaslServer
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
index 8a5ff7df2d..6032255870 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
@@ -47,11 +47,10 @@ public class AnonymousSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props != null &&
- (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE) ||
- props.containsKey(Sasl.POLICY_NOANONYMOUS)))
+ if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE) ||
+ props.containsKey(Sasl.POLICY_NOANONYMOUS))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
index 139818735f..8020d97364 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
@@ -70,7 +70,7 @@ public class CRAMMD5HexInitialiser extends UsernamePasswordInitialiser
for (char c : password)
{
//toHexString does not prepend 0 so we have to
- if (((byte) c > -1) && (byte) c < 0x10 )
+ if (((byte) c > -1) && (byte) c < 10)
{
sb.append(0);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
index 3144bfbce6..f0dd9eeb6d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
@@ -45,10 +45,9 @@ public class PlainSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props != null &&
- (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE)))
+ if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java b/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java
deleted file mode 100644
index 4e3fae1dbd..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java
+++ /dev/null
@@ -1,89 +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.
- *
- */
-package org.apache.qpid.server.signal;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import org.apache.log4j.Logger;
-
-public abstract class SignalHandlerTask
-{
- private static final Logger LOGGER = Logger.getLogger(SignalHandlerTask.class);
-
- private static final String HANDLE_METHOD = "handle";
- private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal";
- private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler";
-
- public boolean register(final String signalName)
- {
- try
- {
- //try to load the signal handling classes
- Class<?> signalClazz = Class.forName(SUN_MISC_SIGNAL_CLASS);
- Class<?> handlerClazz = Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS);
-
- //create an InvocationHandler that just executes the SignalHandlerTask
- InvocationHandler invoker = new InvocationHandler()
- {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- {
- handle();
-
- return null;
- }
- };
-
- //create a dynamic proxy implementing SignalHandler
- Object handler = Proxy.newProxyInstance(handlerClazz.getClassLoader(), new Class[]{handlerClazz}, invoker);
-
- //create the Signal to handle
- Constructor<?> signalConstructor = signalClazz.getConstructor(String.class);
- Object signal = signalConstructor.newInstance(signalName);
-
- //invoke the Signal.handle(signal, handler) method
- Method handleMethod = signalClazz.getMethod(HANDLE_METHOD, signalClazz, handlerClazz);
- handleMethod.invoke(null, signal, handler);
- }
- catch (Exception e)
- {
- LOGGER.debug("Unable to register handler for Signal " + signalName + " due to exception: " + e, e);
- return false;
- }
-
- return true;
- }
-
- public abstract void handle();
-
- public static String getPlatformDescription()
- {
- String name = System.getProperty("os.name");
- String osVer = System.getProperty("os.version");
- String jvmVendor = System.getProperty("java.vm.vendor");
- String jvmName = System.getProperty("java.vm.name");
- String javaRuntimeVer = System.getProperty("java.runtime.version");
-
- return "OS: " + name + " " + osVer + ", JVM:" + jvmVendor + " " + jvmName + " " + javaRuntimeVer;
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
index 33aebffcfb..6cc5e7b019 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
@@ -259,7 +259,7 @@ public class AMQStateManager implements AMQMethodListener
public AMQProtocolSession getProtocolSession()
{
- SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject());
+ SecurityManager.setThreadPrincipal(_protocolSession.getPrincipal());
return _protocolSession;
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
deleted file mode 100644
index b732121180..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
+++ /dev/null
@@ -1,163 +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.
- */
-package org.apache.qpid.server.stats;
-
-import java.util.Date;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class collects statistics and counts the total, rate per second and
- * peak rate per second values for the events that are registered with it.
- */
-public class StatisticsCounter
-{
- private static final Logger _log = LoggerFactory.getLogger(StatisticsCounter.class);
-
- public static final long DEFAULT_SAMPLE_PERIOD = Long.getLong("qpid.statistics.samplePeriod", 2000L); // 2s
- public static final boolean DISABLE_STATISTICS = Boolean.getBoolean("qpid.statistics.disable");
-
- private static final String COUNTER = "counter";
- private static final AtomicLong _counterIds = new AtomicLong(0L);
-
- private long _peak = 0L;
- private long _total = 0L;
- private long _temp = 0L;
- private long _last = 0L;
- private long _rate = 0L;
-
- private long _start;
-
- private final long _period;
- private final String _name;
-
- public StatisticsCounter()
- {
- this(COUNTER);
- }
-
- public StatisticsCounter(String name)
- {
- this(name, DEFAULT_SAMPLE_PERIOD);
- }
-
- public StatisticsCounter(String name, long period)
- {
- _period = period;
- _name = name + "-" + + _counterIds.incrementAndGet();
- reset();
- }
-
- public void registerEvent()
- {
- registerEvent(1L);
- }
-
- public void registerEvent(long value)
- {
- registerEvent(value, System.currentTimeMillis());
- }
-
- public void registerEvent(long value, long timestamp)
- {
- if (DISABLE_STATISTICS)
- {
- return;
- }
-
- long thisSample = (timestamp / _period);
- synchronized (this)
- {
- if (thisSample > _last)
- {
- _last = thisSample;
- _rate = _temp;
- _temp = 0L;
- if (_rate > _peak)
- {
- _peak = _rate;
- }
- }
-
- _total += value;
- _temp += value;
- }
- }
-
- /**
- * Update the current rate and peak - may reset rate to zero if a new
- * sample period has started.
- */
- private void update()
- {
- registerEvent(0L, System.currentTimeMillis());
- }
-
- /**
- * Reset
- */
- public void reset()
- {
- _log.info("Resetting statistics for counter: " + _name);
- _peak = 0L;
- _rate = 0L;
- _total = 0L;
- _start = System.currentTimeMillis();
- _last = _start / _period;
- }
-
- public double getPeak()
- {
- update();
- return (double) _peak / ((double) _period / 1000.0d);
- }
-
- public double getRate()
- {
- update();
- return (double) _rate / ((double) _period / 1000.0d);
- }
-
- public long getTotal()
- {
- return _total;
- }
-
- public long getStart()
- {
- return _start;
- }
-
- public Date getStartTime()
- {
- return new Date(_start);
- }
-
- public String getName()
- {
- return _name;
- }
-
- public long getPeriod()
- {
- return _period;
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
deleted file mode 100644
index 36fec4025a..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
+++ /dev/null
@@ -1,118 +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.
- */
-package org.apache.qpid.server.stats;
-
-/**
- * This interface is to be implemented by any broker business object that
- * wishes to gather statistics about messages delivered through it.
- *
- * These statistics are exposed using a separate JMX Mbean interface, which
- * calls these methods to retrieve the underlying {@link StatisticsCounter}s
- * and return their attributes. This interface gives a standard way for
- * parts of the broker to set up and configure statistics generation.
- * <p>
- * When creating these objects, there should be a parent/child relationship
- * between them, such that the lowest level gatherer can record staticics if
- * enabled, and pass on the notification to the parent object to allow higher
- * level aggregation. When resetting statistics, this works in the opposite
- * direction, with higher level gatherers also resetting all of their children.
- */
-public interface StatisticsGatherer
-{
- /**
- * Initialise the statistics gathering for this object.
- *
- * This method is responsible for creating any {@link StatisticsCounter}
- * objects and for determining whether statistics generation should be
- * enabled, by checking broker and system configuration.
- *
- * @see StatisticsCounter#DISABLE_STATISTICS
- */
- void initialiseStatistics();
-
- /**
- * This method is responsible for registering the receipt of a message
- * with the counters, and also for passing this notification to any parent
- * {@link StatisticsGatherer}s. If statistics generation is not enabled,
- * then this method should simple delegate to the parent gatherer.
- *
- * @param messageSize the size in bytes of the delivered message
- * @param timestamp the time the message was delivered
- */
- void registerMessageReceived(long messageSize, long timestamp);
-
- /**
- * This method is responsible for registering the delivery of a message
- * with the counters. Message delivery is recorded by the counter using
- * the current system time, as opposed to the message timestamp.
- *
- * @param messageSize the size in bytes of the delivered message
- * @see #registerMessageReceived(long, long)
- */
- void registerMessageDelivered(long messageSize);
-
- /**
- * Gives access to the {@link StatisticsCounter} that is used to count
- * delivered message statistics.
- *
- * @return the {@link StatisticsCounter} that counts delivered messages
- */
- StatisticsCounter getMessageDeliveryStatistics();
-
- /**
- * Gives access to the {@link StatisticsCounter} that is used to count
- * received message statistics.
- *
- * @return the {@link StatisticsCounter} that counts received messages
- */
- StatisticsCounter getMessageReceiptStatistics();
-
- /**
- * Gives access to the {@link StatisticsCounter} that is used to count
- * delivered message size statistics.
- *
- * @return the {@link StatisticsCounter} that counts delivered bytes
- */
- StatisticsCounter getDataDeliveryStatistics();
-
- /**
- * Gives access to the {@link StatisticsCounter} that is used to count
- * received message size statistics.
- *
- * @return the {@link StatisticsCounter} that counts received bytes
- */
- StatisticsCounter getDataReceiptStatistics();
-
- /**
- * Reset the counters for this, and any child {@link StatisticsGatherer}s.
- */
- void resetStatistics();
-
- /**
- * Check if this object has statistics generation enabled.
- *
- * @return true if statistics generation is enabled
- */
- boolean isStatisticsEnabled();
-
- /**
- * Enable or disable statistics generation for this object.
- */
- void setStatisticsEnabled(boolean enabled);
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
index 8b099b62ce..2e694b24ea 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.store;
import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
@@ -480,15 +479,9 @@ public class DerbyMessageStore implements MessageStore
FieldTable arguments;
if(dataAsBytes.length > 0)
{
+ org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.wrap(dataAsBytes);
- try
- {
- arguments = new FieldTable(new DataInputStream(new ByteArrayInputStream(dataAsBytes)),dataAsBytes.length);
- }
- catch (IOException e)
- {
- throw new RuntimeException("IO Exception should not be thrown",e);
- }
+ arguments = new FieldTable(buffer,buffer.limit());
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
index 0fd7fdffe5..ce0362d73f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
@@ -20,21 +20,13 @@
*/
package org.apache.qpid.server.subscription;
-import java.util.Map;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.subscription.Subscription;
-import org.apache.qpid.server.transport.ServerSession;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.transport.MessageAcceptMode;
-import org.apache.qpid.transport.MessageAcquireMode;
-import org.apache.qpid.transport.MessageFlowMode;
/**
* Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory
@@ -64,23 +56,4 @@ public interface SubscriptionFactory
RecordDeliveryMethod recordMethod
)
throws AMQException;
-
-
- SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel,
- AMQProtocolSession session,
- AMQShortString consumerTag,
- FieldTable filters,
- boolean noLocal,
- FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod) throws AMQException;
-
- Subscription_0_10 createSubscription(final ServerSession session,
- final String destination,
- final MessageAcceptMode acceptMode,
- final MessageAcquireMode acquireMode,
- final MessageFlowMode flowMode,
- final FlowCreditManager_0_10 creditManager,
- final FilterManager filterManager,
- final Map<String,Object> arguments);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
index 1622d63648..1bba2529c6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
@@ -20,28 +20,17 @@
*/
package org.apache.qpid.server.subscription;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.transport.ServerSession;
-import org.apache.qpid.transport.MessageAcceptMode;
-import org.apache.qpid.transport.MessageAcquireMode;
-import org.apache.qpid.transport.MessageFlowMode;
public class SubscriptionFactoryImpl implements SubscriptionFactory
{
- private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0);
-
public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession,
AMQShortString consumerTag, boolean acks, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager) throws AMQException
@@ -89,47 +78,18 @@ public class SubscriptionFactoryImpl implements SubscriptionFactory
if(isBrowser)
{
- return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
+ return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
}
else if(acks)
{
- return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
+ return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
}
else
{
- return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
+ return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
}
}
- public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel,
- final AMQProtocolSession session,
- final AMQShortString consumerTag,
- final FieldTable filters,
- final boolean noLocal,
- final FlowCreditManager creditManager,
- final ClientDeliveryMethod deliveryMethod,
- final RecordDeliveryMethod recordMethod) throws AMQException
- {
- return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId());
- }
-
- public Subscription_0_10 createSubscription(final ServerSession session,
- final String destination,
- final MessageAcceptMode acceptMode,
- final MessageAcquireMode acquireMode,
- final MessageFlowMode flowMode,
- final FlowCreditManager_0_10 creditManager,
- final FilterManager filterManager,
- final Map<String,Object> arguments)
- {
- return new Subscription_0_10(session, destination, acceptMode, acquireMode,
- flowMode, creditManager, filterManager, arguments, getNextSubscriptionId());
- }
public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl();
-
- private static long getNextSubscriptionId()
- {
- return SUB_ID_GENERATOR.getAndIncrement();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
index d6a256e2e1..d8f44c9f7f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
@@ -88,7 +88,9 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final Lock _stateChangeLock;
- private final long _subscriptionID;
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+ // Create a simple ID that increments for ever new Subscription
+ private final long _subscriptionID = idGenerator.getAndIncrement();
private LogSubject _logSubject;
private LogActor _logActor;
private UUID _id;
@@ -102,11 +104,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod,
- long subscriptionID)
+ RecordDeliveryMethod recordMethod)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
}
@@ -150,11 +151,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod,
- long subscriptionID)
+ RecordDeliveryMethod recordMethod)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
}
@@ -211,45 +211,16 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
- /**
- * NoAck Subscription for use with BasicGet method.
- */
- public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
- {
- public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod,
- long subscriptionID)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
- }
-
- public boolean isTransient()
- {
- return true;
- }
-
- public boolean wouldSuspend(QueueEntry msg)
- {
- return !getCreditManager().useCreditForMessage(msg.getMessage());
- }
-
- }
-
static final class AckSubscription extends SubscriptionImpl
{
public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod,
- long subscriptionID)
+ RecordDeliveryMethod recordMethod)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
}
@@ -325,11 +296,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable arguments,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod,
- long subscriptionID)
+ RecordDeliveryMethod recordMethod)
throws AMQException
{
- _subscriptionID = subscriptionID;
+
_channel = channel;
_consumerTag = consumerTag;
@@ -475,7 +445,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
//check that the message hasn't been rejected
- if (entry.isRejectedBy(getSubscriptionID()))
+ if (entry.isRejectedBy(this))
{
if (_logger.isDebugEnabled())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
index 3e6299cb8a..9ea81660c6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
@@ -20,108 +20,121 @@
*/
package org.apache.qpid.server.subscription;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.subscription.Subscription;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.nio.ByteBuffer;
public class SubscriptionList
{
+
private final SubscriptionNode _head = new SubscriptionNode();
- private final AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
- private final AtomicReference<SubscriptionNode> _subNodeMarker = new AtomicReference<SubscriptionNode>(_head);
- private final AtomicInteger _size = new AtomicInteger();
+ private AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
+ private AtomicInteger _size = new AtomicInteger();
+
- public static final class SubscriptionNode
+ public final class SubscriptionNode
{
private final AtomicBoolean _deleted = new AtomicBoolean();
private final AtomicReference<SubscriptionNode> _next = new AtomicReference<SubscriptionNode>();
private final Subscription _sub;
+
public SubscriptionNode()
{
- //used for sentinel head and dummy node construction
+
_sub = null;
_deleted.set(true);
}
public SubscriptionNode(final Subscription sub)
{
- //used for regular node construction
_sub = sub;
}
- /**
- * Retrieves the first non-deleted node following the current node.
- * Any deleted non-tail nodes encountered during the search are unlinked.
- *
- * @return the next non-deleted node, or null if none was found.
- */
- public SubscriptionNode findNext()
+
+ public SubscriptionNode getNext()
{
+
SubscriptionNode next = nextNode();
while(next != null && next.isDeleted())
{
+
final SubscriptionNode newNext = next.nextNode();
if(newNext != null)
{
- //try to move our _next reference forward to the 'newNext'
- //node to unlink the deleted node
_next.compareAndSet(next, newNext);
next = nextNode();
}
else
{
- //'newNext' is null, meaning 'next' is the current tail. Can't unlink
- //the tail node for thread safety reasons, just use the null.
next = null;
}
- }
+ }
return next;
}
- /**
- * Gets the immediately next referenced node in the structure.
- *
- * @return the immediately next node in the structure, or null if at the tail.
- */
- protected SubscriptionNode nextNode()
+ private SubscriptionNode nextNode()
{
return _next.get();
}
- /**
- * Used to initialise the 'next' reference. Will only succeed if the reference was not previously set.
- *
- * @param node the SubscriptionNode to set as 'next'
- * @return whether the operation succeeded
- */
- private boolean setNext(final SubscriptionNode node)
- {
- return _next.compareAndSet(null, node);
- }
-
public boolean isDeleted()
{
return _deleted.get();
}
+
public boolean delete()
{
- return _deleted.compareAndSet(false,true);
+ if(_deleted.compareAndSet(false,true))
+ {
+ _size.decrementAndGet();
+ advanceHead();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
+
public Subscription getSubscription()
{
return _sub;
}
}
- private void insert(final SubscriptionNode node, final boolean count)
+
+ public SubscriptionList(AMQQueue queue)
+ {
+ }
+
+ private void advanceHead()
+ {
+ SubscriptionNode head = _head.nextNode();
+ while(head._next.get() != null && head.isDeleted())
+ {
+
+ final SubscriptionNode newhead = head.nextNode();
+ if(newhead != null)
+ {
+ _head._next.compareAndSet(head, newhead);
+ }
+ head = _head.nextNode();
+ }
+ }
+
+
+ public SubscriptionNode add(Subscription sub)
{
+ SubscriptionNode node = new SubscriptionNode(sub);
for (;;)
{
SubscriptionNode tail = _tail.get();
@@ -130,14 +143,11 @@ public class SubscriptionList
{
if (next == null)
{
- if (tail.setNext(node))
+ if (tail._next.compareAndSet(null, node))
{
_tail.compareAndSet(tail, node);
- if(count)
- {
- _size.incrementAndGet();
- }
- return;
+ _size.incrementAndGet();
+ return node;
}
}
else
@@ -146,101 +156,27 @@ public class SubscriptionList
}
}
}
- }
- public void add(final Subscription sub)
- {
- SubscriptionNode node = new SubscriptionNode(sub);
- insert(node, true);
}
- public boolean remove(final Subscription sub)
+ public boolean remove(Subscription sub)
{
- SubscriptionNode prevNode = _head;
- SubscriptionNode node = _head.nextNode();
-
+ SubscriptionNode node = _head.getNext();
while(node != null)
{
- if(sub.equals(node.getSubscription()) && node.delete())
+ if(sub.equals(node._sub) && node.delete())
{
- _size.decrementAndGet();
-
- SubscriptionNode tail = _tail.get();
- if(node == tail)
- {
- //we cant remove the last node from the structure for
- //correctness reasons, however we have just 'deleted'
- //the tail. Inserting an empty dummy node after it will
- //let us scavenge the node containing the Subscription.
- insert(new SubscriptionNode(), false);
- }
-
- //advance the next node reference in the 'prevNode' to scavange
- //the newly 'deleted' node for the Subscription.
- prevNode.findNext();
-
- nodeMarkerCleanup(node);
-
return true;
}
-
- prevNode = node;
- node = node.findNext();
+ node = node.getNext();
}
-
return false;
}
- private void nodeMarkerCleanup(final SubscriptionNode node)
- {
- SubscriptionNode markedNode = _subNodeMarker.get();
- if(node == markedNode)
- {
- //if the marked node is the one we are removing, then
- //replace it with a dummy pointing at the next node.
- //this is OK as the marked node is only used to index
- //into the list and find the next node to use.
- //Because we inserted a dummy if node was the
- //tail, markedNode.nextNode() can never be null.
- SubscriptionNode dummy = new SubscriptionNode();
- dummy.setNext(markedNode.nextNode());
-
- //if the CAS fails the marked node has changed, thus
- //we don't care about the dummy and just forget it
- _subNodeMarker.compareAndSet(markedNode, dummy);
- }
- else if(markedNode != null)
- {
- //if the marked node was already deleted then it could
- //hold subsequently removed nodes after it in the list
- //in memory. Scavenge it to ensure their actual removal.
- if(markedNode != _head && markedNode.isDeleted())
- {
- markedNode.findNext();
- }
- }
- }
-
- public boolean updateMarkedNode(final SubscriptionNode expected, final SubscriptionNode nextNode)
- {
- return _subNodeMarker.compareAndSet(expected, nextNode);
- }
-
- /**
- * Get the current marked SubscriptionNode. This should only be used only to index into the list and find the next node
- * after the mark, since if the previously marked node was subsequently deleted the item returned may be a dummy node
- * with reference to the next node.
- *
- * @return the previously marked node (or a dummy if it was subsequently deleted)
- */
- public SubscriptionNode getMarkedNode()
- {
- return _subNodeMarker.get();
- }
-
public static class SubscriptionNodeIterator
{
+
private SubscriptionNode _lastNode;
SubscriptionNodeIterator(SubscriptionNode startNode)
@@ -248,25 +184,49 @@ public class SubscriptionList
_lastNode = startNode;
}
+
+ public boolean atTail()
+ {
+ return _lastNode.nextNode() == null;
+ }
+
public SubscriptionNode getNode()
{
+
return _lastNode;
+
}
public boolean advance()
{
- SubscriptionNode nextNode = _lastNode.findNext();
- _lastNode = nextNode;
- return _lastNode != null;
+ if(!atTail())
+ {
+ SubscriptionNode nextNode = _lastNode.nextNode();
+ while(nextNode.isDeleted() && nextNode.nextNode() != null)
+ {
+ nextNode = nextNode.nextNode();
+ }
+ _lastNode = nextNode;
+ return true;
+
+ }
+ else
+ {
+ return false;
+ }
+
}
+
}
+
public SubscriptionNodeIterator iterator()
{
return new SubscriptionNodeIterator(_head);
}
+
public SubscriptionNode getHead()
{
return _head;
@@ -276,6 +236,9 @@ public class SubscriptionList
{
return _size.get();
}
+
+
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
index c5d6bc203c..b36ac84cdd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java
@@ -40,6 +40,7 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.SubscriptionMessages;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.logging.actors.SubscriptionActor;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.AMQMessage;
@@ -79,7 +80,10 @@ import java.nio.ByteBuffer;
public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, SubscriptionConfig, LogSubject
{
- private final long _subscriptionID;
+
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+ // Create a simple ID that increments for ever new Subscription
+ private final long _subscriptionID = idGenerator.getAndIncrement();
private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
@@ -93,6 +97,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private FlowCreditManager_0_10 _creditManager;
+
private StateListener _stateListener = new StateListener()
{
@@ -109,15 +114,16 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private final MessageAcquireMode _acquireMode;
private MessageFlowMode _flowMode;
private final ServerSession _session;
- private final AtomicBoolean _stopped = new AtomicBoolean(true);
+ private AtomicBoolean _stopped = new AtomicBoolean(true);
+ private ConcurrentHashMap<Integer, QueueEntry> _sentMap = new ConcurrentHashMap<Integer, QueueEntry>();
private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0];
private LogActor _logActor;
- private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
+ private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
private UUID _id;
private String _traceExclude;
private String _trace;
- private final long _createTime = System.currentTimeMillis();
+ private long _createTime = System.currentTimeMillis();
private final AtomicLong _deliveredCount = new AtomicLong(0);
private final Map<String, Object> _arguments;
@@ -126,9 +132,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
MessageAcquireMode acquireMode,
MessageFlowMode flowMode,
FlowCreditManager_0_10 creditManager,
- FilterManager filters,Map<String, Object> arguments, long subscriptionId)
+ FilterManager filters,Map<String, Object> arguments)
{
- _subscriptionID = subscriptionId;
_session = session;
_destination = destination;
_acceptMode = acceptMode;
@@ -194,7 +199,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public boolean isSuspended()
{
- return !isActive() || _deleted.get() || _session.isClosing(); // TODO check for Session suspension
+ return !isActive() || _deleted.get(); // TODO check for Session suspension
}
public boolean hasInterest(QueueEntry entry)
@@ -203,7 +208,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
//check that the message hasn't been rejected
- if (entry.isRejectedBy(getSubscriptionID()))
+ if (entry.isRejectedBy(this))
{
return false;
@@ -437,7 +442,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
Struct[] headers = new Struct[] { deliveryProps, messageProps };
BasicContentHeaderProperties properties =
- (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties();
+ (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().properties;
final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange();
if(exchange != null)
{
@@ -727,22 +732,13 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public void stop()
{
- try
- {
- getSendLock();
-
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
- {
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
- }
- _stopped.set(true);
- FlowCreditManager_0_10 creditManager = getCreditManager();
- creditManager.clearCredit();
- }
- finally
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
{
- releaseSendLock();
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
}
+ _stopped.set(true);
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+ creditManager.clearCredit();
}
public void addCredit(MessageCreditUnit unit, long value)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
index abbc5a3805..3ca22b60c8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java
@@ -20,21 +20,21 @@
*/
package org.apache.qpid.server.transport;
-import org.apache.qpid.transport.network.NetworkTransport;
+import org.apache.qpid.transport.NetworkDriver;
public class QpidAcceptor
{
- NetworkTransport _transport;
+ NetworkDriver _driver;
String _protocol;
- public QpidAcceptor(NetworkTransport transport, String protocol)
+ public QpidAcceptor(NetworkDriver driver, String protocol)
{
- _transport = transport;
+ _driver = driver;
_protocol = protocol;
}
- public NetworkTransport getNetworkTransport()
+ public NetworkDriver getNetworkDriver()
{
- return _transport;
+ return _driver;
}
public String toString()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
index d83013afba..d2addfde0c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java
@@ -20,19 +20,11 @@
*/
package org.apache.qpid.server.transport;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.*;
-import java.security.Principal;
import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
-import javax.security.auth.Subject;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.configuration.ConnectionConfig;
@@ -43,39 +35,23 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.security.AuthorizationHolder;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.ConnectionCloseCode;
import org.apache.qpid.transport.ExecutionErrorCode;
import org.apache.qpid.transport.ExecutionException;
import org.apache.qpid.transport.Method;
import org.apache.qpid.transport.ProtocolEvent;
-import org.apache.qpid.transport.Session;
-public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder
+public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject
{
private ConnectionConfig _config;
private Runnable _onOpenTask;
private AtomicBoolean _logClosed = new AtomicBoolean(false);
private LogActor _actor = GenericActor.getInstance(this);
- private Subject _authorizedSubject = null;
- private Principal _authorizedPrincipal = null;
- private boolean _statisticsEnabled = false;
- private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
- private final long _connectionId;
-
- public ServerConnection(final long connectionId)
+ public ServerConnection()
{
- _connectionId = connectionId;
- }
- public UUID getId()
- {
- return _config.getId();
}
@Override
@@ -96,18 +72,8 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
_onOpenTask.run();
}
_actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", true, true));
-
- getVirtualHost().getConnectionRegistry().registerConnection(this);
}
-
- if (state == State.CLOSE_RCVD || state == State.CLOSED || state == State.CLOSING)
- {
- if(_virtualHost != null)
- {
- _virtualHost.getConnectionRegistry().deregisterConnection(this);
- }
- }
-
+
if (state == State.CLOSED)
{
logClosed();
@@ -144,8 +110,6 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
public void setVirtualHost(VirtualHost virtualHost)
{
_virtualHost = virtualHost;
-
- initialiseStatistics();
}
public void setConnectionConfig(final ConnectionConfig config)
@@ -181,11 +145,6 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
((ServerSession)session).close();
}
-
- public LogSubject getLogSubject()
- {
- return (LogSubject) this;
- }
@Override
public void received(ProtocolEvent event)
@@ -220,9 +179,9 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
public String toLogString()
{
boolean hasVirtualHost = (null != this.getVirtualHost());
- boolean hasClientId = (null != getClientId());
+ boolean hasPrincipal = (null != getAuthorizationID());
- if (hasClientId && hasVirtualHost)
+ if (hasPrincipal && hasVirtualHost)
{
return "[" +
MessageFormat.format(CONNECTION_FORMAT,
@@ -232,7 +191,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
getVirtualHost().getName())
+ "] ";
}
- else if (hasClientId)
+ else if (hasPrincipal)
{
return "[" +
MessageFormat.format(USER_FORMAT,
@@ -256,147 +215,4 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
{
return _actor;
}
-
- public void close(AMQConstant cause, String message) throws AMQException
- {
- ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
- try
- {
- replyCode = ConnectionCloseCode.get(cause.getCode());
- }
- catch (IllegalArgumentException iae)
- {
- // Ignore
- }
- close(replyCode, message);
- }
-
- public List<AMQSessionModel> getSessionModels()
- {
- List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
- for (Session ssn : getChannels())
- {
- sessions.add((AMQSessionModel) ssn);
- }
- return sessions;
- }
-
- public void registerMessageDelivered(long messageSize)
- {
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
- _virtualHost.registerMessageDelivered(messageSize);
- }
-
- public void registerMessageReceived(long messageSize, long timestamp)
- {
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
- _virtualHost.registerMessageReceived(messageSize, timestamp);
- }
-
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return _messagesReceived;
- }
-
- public StatisticsCounter getDataReceiptStatistics()
- {
- return _dataReceived;
- }
-
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return _messagesDelivered;
- }
-
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return _dataDelivered;
- }
-
- public void resetStatistics()
- {
- _messagesDelivered.reset();
- _dataDelivered.reset();
- _messagesReceived.reset();
- _dataReceived.reset();
- }
-
- public void initialiseStatistics()
- {
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _virtualHost.getApplicationRegistry().getConfiguration().isStatisticsGenerationConnectionsEnabled());
-
- _messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId());
- _dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId());
- _messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId());
- _dataReceived = new StatisticsCounter("data-received-" + getConnectionId());
- }
-
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
-
- /**
- * @return authorizedSubject
- */
- public Subject getAuthorizedSubject()
- {
- return _authorizedSubject;
- }
-
- /**
- * Sets the authorized subject. It also extracts the UsernamePrincipal from the subject
- * and caches it for optimisation purposes.
- *
- * @param authorizedSubject
- */
- public void setAuthorizedSubject(final Subject authorizedSubject)
- {
- if (authorizedSubject == null)
- {
- _authorizedSubject = null;
- _authorizedPrincipal = null;
- }
- else
- {
- _authorizedSubject = authorizedSubject;
- _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
- }
- }
-
- public Principal getAuthorizedPrincipal()
- {
- return _authorizedPrincipal;
- }
-
- public long getConnectionId()
- {
- return _connectionId;
- }
-
- @Override
- public boolean isSessionNameUnique(String name)
- {
- return !super.hasSessionWithName(name);
- }
-
- @Override
- public String getUserName()
- {
- return _authorizedPrincipal.getName();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
index 2de8a0425e..2b9e92f685 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java
@@ -20,47 +20,26 @@
*/
package org.apache.qpid.server.transport;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
+import org.apache.qpid.transport.*;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.GenericActor;
+import org.apache.qpid.common.ClientProperties;
import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
-import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.ConnectionClose;
-import org.apache.qpid.transport.ConnectionCloseCode;
-import org.apache.qpid.transport.ConnectionOpen;
-import org.apache.qpid.transport.ConnectionOpenOk;
-import org.apache.qpid.transport.ConnectionTuneOk;
-import org.apache.qpid.transport.ServerDelegate;
-import org.apache.qpid.transport.Session;
-import org.apache.qpid.transport.SessionAttach;
-import org.apache.qpid.transport.SessionDelegate;
-import org.apache.qpid.transport.SessionDetach;
-import org.apache.qpid.transport.SessionDetachCode;
-import org.apache.qpid.transport.SessionDetached;
+
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+import java.util.*;
public class ServerConnectionDelegate extends ServerDelegate
{
private String _localFQDN;
private final IApplicationRegistry _appRegistry;
+
public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN)
{
this(new HashMap<String,Object>(Collections.singletonMap("qpid.federation_tag",appRegistry.getBroker().getFederationTag())), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN);
@@ -89,42 +68,24 @@ public class ServerConnectionDelegate extends ServerDelegate
return list;
}
+ @Override
public ServerSession getSession(Connection conn, SessionAttach atc)
{
- SessionDelegate serverSessionDelegate = new ServerSessionDelegate();
+ SessionDelegate serverSessionDelegate = new ServerSessionDelegate(_appRegistry);
ServerSession ssn = new ServerSession(conn, serverSessionDelegate, new Binary(atc.getName()), 0);
return ssn;
}
+ @Override
protected SaslServer createSaslServer(String mechanism) throws SaslException
{
return _appRegistry.getAuthenticationManager().createSaslServer(mechanism, _localFQDN);
}
- protected void secure(final SaslServer ss, final Connection conn, final byte[] response)
- {
- final AuthenticationResult authResult = _appRegistry.getAuthenticationManager().authenticate(ss, response);
- final ServerConnection sconn = (ServerConnection) conn;
-
-
- if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus()))
- {
- tuneAuthorizedConnection(sconn);
- sconn.setAuthorizedSubject(authResult.getSubject());
- }
- else if (AuthenticationStatus.CONTINUE.equals(authResult.getStatus()))
- {
- connectionAuthContinue(sconn, authResult.getChallenge());
- }
- else
- {
- connectionAuthFailed(sconn, authResult.getCause());
- }
- }
-
+ @Override
public void connectionClose(Connection conn, ConnectionClose close)
{
try
@@ -138,9 +99,10 @@ public class ServerConnectionDelegate extends ServerDelegate
}
+ @Override
public void connectionOpen(Connection conn, ConnectionOpen open)
{
- final ServerConnection sconn = (ServerConnection) conn;
+ ServerConnection sconn = (ServerConnection) conn;
VirtualHost vhost;
String vhostName;
@@ -154,7 +116,7 @@ public class ServerConnectionDelegate extends ServerDelegate
}
vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName);
- SecurityManager.setThreadSubject(sconn.getAuthorizedSubject());
+ SecurityManager.setThreadPrincipal(conn.getAuthorizationID());
if(vhost != null)
{
@@ -176,27 +138,6 @@ public class ServerConnectionDelegate extends ServerDelegate
sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'"));
sconn.setState(Connection.State.CLOSING);
}
-
- }
-
- @Override
- public void connectionTuneOk(final Connection conn, final ConnectionTuneOk ok)
- {
- ServerConnection sconn = (ServerConnection) conn;
- int okChannelMax = ok.getChannelMax();
-
- if (okChannelMax > getChannelMax())
- {
- _logger.error("Connection '" + sconn.getConnectionId() + "' being severed, " +
- "client connectionTuneOk returned a channelMax (" + okChannelMax +
- ") above the servers offered limit (" + getChannelMax() +")");
-
- //Due to the error we must forcefully close the connection without negotiation
- sconn.getSender().close();
- return;
- }
-
- setConnectionTuneOkChannelMax(sconn, okChannelMax);
}
@Override
@@ -211,59 +152,4 @@ public class ServerConnectionDelegate extends ServerDelegate
{
return ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount();
}
-
- @Override public void sessionDetach(Connection conn, SessionDetach dtc)
- {
- // To ensure a clean detach, we unregister any remaining subscriptions. Unregister ensures
- // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the unregister
- // completes.
- unregisterAllSubscriptions(conn, dtc);
- super.sessionDetach(conn, dtc);
- }
-
- private void unregisterAllSubscriptions(Connection conn, SessionDetach dtc)
- {
- final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel());
- final Collection<Subscription_0_10> subs = ssn.getSubscriptions();
- for (Subscription_0_10 subscription_0_10 : subs)
- {
- ssn.unregister(subscription_0_10);
- }
- }
-
- @Override
- public void sessionAttach(final Connection conn, final SessionAttach atc)
- {
- final String clientId = new String(atc.getName());
- final Session ssn = getSession(conn, atc);
-
- if(isSessionNameUnique(clientId,conn))
- {
- conn.registerSession(ssn);
- super.sessionAttach(conn, atc);
- }
- else
- {
- ssn.invoke(new SessionDetached(atc.getName(), SessionDetachCode.SESSION_BUSY));
- ssn.closed();
- }
- }
-
- private boolean isSessionNameUnique(final String name, final Connection conn)
- {
- final ServerConnection sconn = (ServerConnection) conn;
- final String userId = sconn.getUserName();
-
- final Iterator<AMQConnectionModel> connections =
- ((ServerConnection)conn).getVirtualHost().getConnectionRegistry().getConnections().iterator();
- while(connections.hasNext())
- {
- final AMQConnectionModel amqConnectionModel = (AMQConnectionModel) connections.next();
- if (userId.equals(amqConnectionModel.getUserName()) && !amqConnectionModel.isSessionNameUnique(name))
- {
- return false;
- }
- }
- return true;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
index 67ddd6ca77..540ad3fffd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
@@ -23,25 +23,9 @@ package org.apache.qpid.server.transport;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
import static org.apache.qpid.util.Serial.gt;
-import java.lang.ref.WeakReference;
-import java.security.Principal;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.security.auth.Subject;
+import com.sun.security.auth.UserPrincipal;
import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.configuration.ConfiguredObject;
@@ -54,18 +38,18 @@ import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.transport.Binary;
import org.apache.qpid.transport.Connection;
import org.apache.qpid.transport.MessageTransfer;
@@ -74,13 +58,24 @@ import org.apache.qpid.transport.Range;
import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.Session;
import org.apache.qpid.transport.SessionDelegate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-public class ServerSession extends Session implements AuthorizationHolder, SessionConfig, AMQSessionModel, LogSubject
+import java.lang.ref.WeakReference;
+import java.security.Principal;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ServerSession extends Session implements PrincipalHolder, SessionConfig, AMQSessionModel, LogSubject
{
- private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class);
-
private static final String NULL_DESTINTATION = UUID.randomUUID().toString();
private final UUID _id;
@@ -116,7 +111,8 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
private final AtomicLong _txnCommits = new AtomicLong(0);
private final AtomicLong _txnRejects = new AtomicLong(0);
private final AtomicLong _txnCount = new AtomicLong(0);
- private final AtomicLong _txnUpdateTime = new AtomicLong(0);
+
+ private Principal _principal;
private Map<String, Subscription_0_10> _subscriptions = new ConcurrentHashMap<String, Subscription_0_10>();
@@ -129,27 +125,27 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig());
}
- public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig)
- {
- super(connection, delegate, name, expiry);
- _connectionConfig = connConfig;
- _transaction = new AutoCommitTransaction(this.getMessageStore());
-
- _reference = new WeakReference<Session>(this);
- _id = getConfigStore().createId();
- getConfigStore().addConfiguredObject(this);
- }
-
protected void setState(State state)
{
super.setState(state);
if (state == State.OPEN)
{
- _actor.message(ChannelMessages.CREATE());
+ _actor.message(ChannelMessages.CREATE());
}
}
+ public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig)
+ {
+ super(connection, delegate, name, expiry);
+ _connectionConfig = connConfig;
+ _transaction = new AutoCommitTransaction(this.getMessageStore());
+ _principal = new UserPrincipal(connection.getAuthorizationID());
+ _reference = new WeakReference(this);
+ _id = getConfigStore().createId();
+ getConfigStore().addConfiguredObject(this);
+ }
+
private ConfigStore getConfigStore()
{
return getConnectionConfig().getConfigStore();
@@ -164,8 +160,8 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
public void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues)
{
- getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime());
- _transaction.enqueue(queues,message, new ServerTransaction.Action()
+
+ _transaction.enqueue(queues,message, new ServerTransaction.Action()
{
BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]);
@@ -193,14 +189,12 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
});
incrementOutstandingTxnsIfNecessary();
- updateTransactionalActivity();
}
public void sendMessage(MessageTransfer xfr,
Runnable postIdSettingAction)
{
- getConnectionModel().registerMessageDelivered(xfr.getBodySize());
invoke(xfr, postIdSettingAction);
}
@@ -383,7 +377,6 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
entry.release();
}
});
- updateTransactionalActivity();
}
public Collection<Subscription_0_10> getSubscriptions()
@@ -417,7 +410,7 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
catch (AMQException e)
{
// TODO
- _logger.error("Failed to unregister subscription", e);
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
finally
{
@@ -432,11 +425,6 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
// theory
return !(_transaction instanceof AutoCommitTransaction);
}
-
- public boolean inTransaction()
- {
- return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0;
- }
public void selectTx()
{
@@ -483,17 +471,6 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
}
}
- /**
- * Update last transaction activity timestamp
- */
- public void updateTransactionalActivity()
- {
- if (isTransactional())
- {
- _txnUpdateTime.set(System.currentTimeMillis());
- }
- }
-
public Long getTxnStarts()
{
return _txnStarts.get();
@@ -514,14 +491,9 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
return _txnCount.get();
}
- public Principal getAuthorizedPrincipal()
+ public Principal getPrincipal()
{
- return ((ServerConnection) getConnection()).getAuthorizedPrincipal();
- }
-
- public Subject getAuthorizedSubject()
- {
- return ((ServerConnection) getConnection()).getAuthorizedSubject();
+ return _principal;
}
public void addSessionCloseTask(Task task)
@@ -634,61 +606,18 @@ public class ServerSession extends Session implements AuthorizationHolder, Sessi
return (LogSubject) this;
}
- public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException
- {
- if (inTransaction())
- {
- long currentTime = System.currentTimeMillis();
- long openTime = currentTime - _transaction.getTransactionStartTime();
- long idleTime = currentTime - _txnUpdateTime.get();
-
- // Log a warning on idle or open transactions
- if (idleWarn > 0L && idleTime > idleWarn)
- {
- CurrentActor.get().message(getLogSubject(), ChannelMessages.IDLE_TXN(idleTime));
- _logger.warn("IDLE TRANSACTION ALERT " + getLogSubject().toString() + " " + idleTime + " ms");
- }
- else if (openWarn > 0L && openTime > openWarn)
- {
- CurrentActor.get().message(getLogSubject(), ChannelMessages.OPEN_TXN(openTime));
- _logger.warn("OPEN TRANSACTION ALERT " + getLogSubject().toString() + " " + openTime + " ms");
- }
-
- // Close connection for idle or open transactions that have timed out
- if (idleClose > 0L && idleTime > idleClose)
- {
- getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out");
- }
- else if (openClose > 0L && openTime > openClose)
- {
- getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out");
- }
- }
- }
-
+ @Override
public String toLogString()
{
return "[" +
MessageFormat.format(CHANNEL_FORMAT,
- ((ServerConnection) getConnection()).getConnectionId(),
+ getConnection().getConnectionId(),
getClientID(),
((ProtocolEngine) _connectionConfig).getRemoteAddress().toString(),
getVirtualHost().getName(),
getChannel())
+ "] ";
- }
- @Override
- public void close()
- {
- // unregister subscriptions in order to prevent sending of new messages
- // to subscriptions with closing session
- final Collection<Subscription_0_10> subscriptions = getSubscriptions();
- for (Subscription_0_10 subscription_0_10 : subscriptions)
- {
- unregister(subscription_0_10);
- }
-
- super.close();
}
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
index 17bd06538f..42a3975e24 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java
@@ -25,34 +25,31 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
-import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnknownExchangeType;
+import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.exchange.ExchangeFactory;
-import org.apache.qpid.server.exchange.ExchangeInUseException;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.exchange.ExchangeType;
-import org.apache.qpid.server.exchange.HeadersExchange;
+import org.apache.qpid.server.exchange.*;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.FilterManagerFactory;
import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.flow.WindowCreditManager;
-import org.apache.qpid.server.logging.messages.ExchangeMessages;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.message.MessageMetaData_0_10;
import org.apache.qpid.server.message.MessageTransferMessage;
+import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoredMessage;
-import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Acquired;
@@ -98,34 +95,26 @@ import org.apache.qpid.transport.TxSelect;
public class ServerSessionDelegate extends SessionDelegate
{
- private static final Logger LOGGER = Logger.getLogger(ServerSessionDelegate.class);
+ private final IApplicationRegistry _appRegistry;
- public ServerSessionDelegate()
+ public ServerSessionDelegate(IApplicationRegistry appRegistry)
{
-
+ _appRegistry = appRegistry;
}
@Override
public void command(Session session, Method method)
{
- try
- {
- setThreadSubject(session);
+ SecurityManager.setThreadPrincipal(session.getConnection().getAuthorizationID());
- if(!session.isClosing())
+ if(!session.isClosing())
+ {
+ super.command(session, method);
+ if (method.isSync())
{
- super.command(session, method);
- if (method.isSync())
- {
- session.flushProcessed();
- }
+ session.flushProcessed();
}
}
- catch(RuntimeException e)
- {
- LOGGER.error("Exception processing command", e);
- exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Exception processing command: " + e);
- }
}
@Override
@@ -134,6 +123,8 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).accept(method.getTransfers());
}
+
+
@Override
public void messageReject(Session session, MessageReject method)
{
@@ -168,6 +159,7 @@ public class ServerSessionDelegate extends SessionDelegate
@Override
public void messageSubscribe(Session session, MessageSubscribe method)
{
+
//TODO - work around broken Python tests
if(!method.hasAcceptMode())
{
@@ -211,33 +203,32 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found");
}
- else if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session)
+ else if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != session)
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
else
{
+
if(queue.isExclusive())
{
- ServerSession s = (ServerSession) session;
- queue.setExclusiveOwningSession(s);
- if(queue.getAuthorizationHolder() == null)
+ if(queue.getPrincipalHolder() == null)
{
- queue.setAuthorizationHolder(s);
- queue.setExclusiveOwningSession(s);
+ queue.setPrincipalHolder((ServerSession)session);
((ServerSession) session).addSessionCloseTask(new ServerSession.Task()
{
+
public void doTask(ServerSession session)
{
- if(queue.getAuthorizationHolder() == session)
+ if(queue.getPrincipalHolder() == session)
{
- queue.setAuthorizationHolder(null);
- queue.setExclusiveOwningSession(null);
+ queue.setPrincipalHolder(null);
}
}
});
}
+
}
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
@@ -253,7 +244,7 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
- Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
+ Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
destination,
method.getAcceptMode(),
method.getAcquireMode(),
@@ -284,10 +275,25 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
+
@Override
public void messageTransfer(Session ssn, MessageTransfer xfr)
{
- final Exchange exchange = getExchangeForMessage(ssn, xfr);
+ ExchangeRegistry exchangeRegistry = getExchangeRegistry(ssn);
+ Exchange exchange;
+ if(xfr.hasDestination())
+ {
+ exchange = exchangeRegistry.getExchange(xfr.getDestination());
+ if(exchange == null)
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+ }
+ else
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+
DeliveryProperties delvProps = null;
if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration())
@@ -295,7 +301,7 @@ public class ServerSessionDelegate extends SessionDelegate
delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl());
}
- final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
+ MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName()))
{
@@ -305,63 +311,65 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
-
- final Exchange exchangeInUse;
- ArrayList<? extends BaseQueue> queues = exchange.route(messageMetaData);
- if(queues.isEmpty() && exchange.getAlternateExchange() != null)
- {
- final Exchange alternateExchange = exchange.getAlternateExchange();
- queues = alternateExchange.route(messageMetaData);
- if (!queues.isEmpty())
- {
- exchangeInUse = alternateExchange;
- }
- else
- {
- exchangeInUse = exchange;
- }
- }
- else
+
+ final MessageStore store = getVirtualHost(ssn).getMessageStore();
+ StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData);
+ ByteBuffer body = xfr.getBody();
+ if(body != null)
{
- exchangeInUse = exchange;
+ storeMessage.addContent(0, body);
}
+ storeMessage.flushToStore();
+ MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference());
- if(!queues.isEmpty())
+ ArrayList<? extends BaseQueue> queues = exchange.route(message);
+
+
+
+ if(queues != null && queues.size() != 0)
{
- final MessageStore store = getVirtualHost(ssn).getMessageStore();
- final StoredMessage<MessageMetaData_0_10> storeMessage = createAndFlushStoreMessage(xfr, messageMetaData, store);
- MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference());
((ServerSession) ssn).enqueue(message, queues);
}
else
{
- if((delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+ if(delvProps == null || !delvProps.hasDiscardUnroutable() || !delvProps.getDiscardUnroutable())
{
- RangeSet rejects = new RangeSet();
- rejects.add(xfr.getId());
- MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
- ssn.invoke(reject);
- }
- else
- {
- ((ServerSession) ssn).getLogActor().message(ExchangeMessages.DISCARDMSG(exchangeInUse.getName(), messageMetaData.getRoutingKey()));
+ if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+ {
+ RangeSet rejects = new RangeSet();
+ rejects.add(xfr.getId());
+ MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
+ ssn.invoke(reject);
+ }
+ else
+ {
+ Exchange alternate = exchange.getAlternateExchange();
+ if(alternate != null)
+ {
+ queues = alternate.route(message);
+ if(queues != null && queues.size() != 0)
+ {
+ ((ServerSession) ssn).enqueue(message, queues);
+ }
+ else
+ {
+ //TODO - log the message discard
+ }
+ }
+ else
+ {
+ //TODO - log the message discard
+ }
+
+
+ }
}
+
+
}
ssn.processed(xfr);
- }
- private StoredMessage<MessageMetaData_0_10> createAndFlushStoreMessage(final MessageTransfer xfr,
- final MessageMetaData_0_10 messageMetaData, final MessageStore store)
- {
- final StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData);
- ByteBuffer body = xfr.getBody();
- if(body != null)
- {
- storeMessage.addContent(0, body);
- }
- storeMessage.flushToStore();
- return storeMessage;
}
@Override
@@ -381,7 +389,7 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).unregister(sub);
if(!queue.isDeleted() && queue.isExclusive() && queue.getConsumerCount() == 0)
{
- queue.setAuthorizationHolder(null);
+ queue.setPrincipalHolder(null);
}
}
}
@@ -440,19 +448,6 @@ public class ServerSessionDelegate extends SessionDelegate
VirtualHost virtualHost = getVirtualHost(session);
Exchange exchange = getExchange(session, exchangeName);
- //we must check for any unsupported arguments present and throw not-implemented
- if(method.hasArguments())
- {
- Map<String,Object> args = method.getArguments();
-
- //QPID-3392: currently we don't support any!
- if(!args.isEmpty())
- {
- exception(session, method, ExecutionErrorCode.NOT_IMPLEMENTED, "Unsupported exchange argument(s) found " + args.keySet().toString());
- return;
- }
- }
-
if(method.getPassive())
{
if(exchange == null)
@@ -462,6 +457,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
+ // TODO - check exchange has same properties
if(!exchange.getTypeShortString().toString().equals(method.getType()))
{
exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type");
@@ -566,25 +562,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
- private Exchange getExchangeForMessage(Session ssn, MessageTransfer xfr)
- {
- final ExchangeRegistry exchangeRegistry = getExchangeRegistry(ssn);
- Exchange exchange;
- if(xfr.hasDestination())
- {
- exchange = exchangeRegistry.getExchange(xfr.getDestination());
- if(exchange == null)
- {
- exchange = exchangeRegistry.getDefaultExchange();
- }
- }
- else
- {
- exchange = exchangeRegistry.getDefaultExchange();
- }
- return exchange;
- }
-
private VirtualHost getVirtualHost(Session session)
{
ServerConnection conn = getServerConnection(session);
@@ -606,12 +583,6 @@ public class ServerSessionDelegate extends SessionDelegate
try
{
- if (nameNullOrEmpty(method.getExchange()))
- {
- exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Delete not allowed for default exchange");
- return;
- }
-
Exchange exchange = getExchange(session, method.getExchange());
if(exchange == null)
@@ -647,16 +618,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
- private boolean nameNullOrEmpty(String name)
- {
- if(name == null || name.length() == 0)
- {
- return true;
- }
-
- return false;
- }
-
private boolean isStandardExchange(Exchange exchange, Collection<ExchangeType<? extends Exchange>> registeredTypes)
{
for(ExchangeType type : registeredTypes)
@@ -703,9 +664,9 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
}
- else if (nameNullOrEmpty(method.getExchange()))
+ else if (!method.hasExchange())
{
- exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Bind not allowed for default exchange");
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
}
/*
else if (!method.hasBindingKey())
@@ -774,9 +735,9 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
}
- else if (nameNullOrEmpty(method.getExchange()))
+ else if (!method.hasExchange())
{
- exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Unbind not allowed for default exchange");
+ exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
}
else if (!method.hasBindingKey())
{
@@ -806,6 +767,9 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
}
+
+
+ super.exchangeUnbind(session, method);
}
@Override
@@ -1005,10 +969,10 @@ public class ServerSessionDelegate extends SessionDelegate
}
- if (method.hasAutoDelete()
- && method.getAutoDelete()
- && method.hasExclusive()
- && method.getExclusive())
+ if(method.hasAutoDelete()
+ && method.getAutoDelete()
+ && method.hasExclusive()
+ && method.getExclusive())
{
final AMQQueue q = queue;
final ServerSession.Task deleteQueueTask = new ServerSession.Task()
@@ -1035,23 +999,23 @@ public class ServerSessionDelegate extends SessionDelegate
}
});
}
- if (method.hasExclusive()
- && method.getExclusive())
+ else if(method.getExclusive())
{
final AMQQueue q = queue;
final ServerSession.Task removeExclusive = new ServerSession.Task()
{
+
public void doTask(ServerSession session)
{
- q.setAuthorizationHolder(null);
+ q.setPrincipalHolder(null);
q.setExclusiveOwningSession(null);
}
};
final ServerSession s = (ServerSession) session;
- q.setExclusiveOwningSession(s);
s.addSessionCloseTask(removeExclusive);
queue.addQueueDeleteTask(new AMQQueue.Task()
{
+
public void doTask(AMQQueue queue) throws AMQException
{
s.removeSessionCloseTask(removeExclusive);
@@ -1065,7 +1029,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
}
- else if (method.getExclusive() && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session)))
+ else if (method.getExclusive() && (queue.getPrincipalHolder() != null && !queue.getPrincipalHolder().equals(session)))
{
String description = "Cannot declare queue('" + queueName + "'),"
+ " as exclusive queue with same name "
@@ -1113,7 +1077,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session)
+ if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != session)
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
@@ -1259,8 +1223,6 @@ public class ServerSessionDelegate extends SessionDelegate
@Override
public void closed(Session session)
{
- setThreadSubject(session);
-
for(Subscription_0_10 sub : getSubscriptions(session))
{
((ServerSession)session).unregister(sub);
@@ -1279,9 +1241,4 @@ public class ServerSessionDelegate extends SessionDelegate
return ((ServerSession)session).getSubscriptions();
}
- private void setThreadSubject(Session session)
- {
- final ServerConnection scon = (ServerConnection) session.getConnection();
- SecurityManager.setThreadSubject(scon.getAuthorizedSubject());
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
index 36e9d78440..db781ead96 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
@@ -50,11 +50,6 @@ public class AutoCommitTransaction implements ServerTransaction
_transactionLog = transactionLog;
}
- public long getTransactionStartTime()
- {
- return 0L;
- }
-
/**
* Since AutoCommitTransaction have no concept of a long lived transaction, any Actions registered
* by the caller are executed immediately.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
index 946dbd7c28..a04c743be1 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
@@ -20,23 +20,18 @@ package org.apache.qpid.server.txn;
*
*/
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.TransactionLog;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.BaseQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.TransactionLog;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* A concrete implementation of ServerTransaction where enqueue/dequeue
@@ -46,28 +41,17 @@ import org.slf4j.LoggerFactory;
*/
public class LocalTransaction implements ServerTransaction
{
- protected static final Logger _logger = LoggerFactory.getLogger(LocalTransaction.class);
+ protected static final Logger _logger = Logger.getLogger(LocalTransaction.class);
private final List<Action> _postTransactionActions = new ArrayList<Action>();
private volatile TransactionLog.Transaction _transaction;
private TransactionLog _transactionLog;
- private long _txnStartTime = 0L;
public LocalTransaction(TransactionLog transactionLog)
{
_transactionLog = transactionLog;
}
-
- public boolean inTransaction()
- {
- return _transaction != null;
- }
-
- public long getTransactionStartTime()
- {
- return _txnStartTime;
- }
public void addPostTransactionAction(Action postTransactionAction)
{
@@ -105,6 +89,7 @@ public class LocalTransaction implements ServerTransaction
try
{
+
for(QueueEntry entry : queueEntries)
{
ServerMessage message = entry.getMessage();
@@ -128,6 +113,7 @@ public class LocalTransaction implements ServerTransaction
_logger.error("Error during message dequeues", e);
tidyUpOnError(e);
}
+
}
private void tidyUpOnError(Exception e)
@@ -154,7 +140,8 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- resetDetails();
+ _transaction = null;
+ _postTransactionActions.clear();
}
}
@@ -206,11 +193,6 @@ public class LocalTransaction implements ServerTransaction
{
_postTransactionActions.add(postTransactionAction);
- if (_txnStartTime == 0L)
- {
- _txnStartTime = System.currentTimeMillis();
- }
-
if(message.isPersistent())
{
try
@@ -266,14 +248,17 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- resetDetails();
+ _transaction = null;
+ _postTransactionActions.clear();
}
+
}
public void rollback()
{
try
{
+
if(_transaction != null)
{
_transaction.abortTran();
@@ -295,15 +280,9 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- resetDetails();
+ _transaction = null;
+ _postTransactionActions.clear();
}
}
}
-
- private void resetDetails()
- {
- _transaction = null;
- _postTransactionActions.clear();
- _txnStartTime = 0L;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
index b3c6e1ac3a..b61b8a5c64 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
@@ -52,13 +52,6 @@ public interface ServerTransaction
public void onRollback();
}
- /**
- * Return the time the current transaction started.
- *
- * @return the time this transaction started or 0 if not in a transaction
- */
- long getTransactionStartTime();
-
/**
* Register an Action for execution after transaction commit or rollback. Actions
* will be executed in the order in which they are registered.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java
deleted file mode 100644
index 898a667736..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java
+++ /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.
- *
- */
-package org.apache.qpid.server.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-public class ByteBufferInputStream extends InputStream
-{
- private final ByteBuffer _buffer;
-
- public ByteBufferInputStream(ByteBuffer buffer)
- {
- _buffer = buffer;
- }
-
- @Override
- public int read() throws IOException
- {
- return _buffer.get() & 0xFF;
- }
-
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException
- {
- if(_buffer.remaining() < len)
- {
- len = _buffer.remaining();
- }
- _buffer.get(b, off, len);
-
- return len;
- }
-
- @Override
- public void mark(int readlimit)
- {
- _buffer.mark();
- }
-
- @Override
- public void reset() throws IOException
- {
- _buffer.reset();
- }
-
- @Override
- public boolean markSupported()
- {
- return true;
- }
-
- @Override
- public long skip(long n) throws IOException
- {
-
- _buffer.position(_buffer.position()+(int)n);
-
- return n;
- }
-
- @Override
- public int available() throws IOException
- {
- return _buffer.remaining();
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java
deleted file mode 100644
index ca9a41bc32..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.server.util;
-
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-public class ByteBufferOutputStream extends OutputStream
-{
- private final ByteBuffer _buffer;
-
- public ByteBufferOutputStream(ByteBuffer buffer)
- {
- _buffer = buffer;
- }
-
- @Override
- public void write(int b)
- {
- _buffer.put((byte)b);
- }
-
- @Override
- public void write(byte[] b, int off, int len)
- {
- _buffer.put(b, off, len);
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java
index ebace95f65..2db1944cd1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java
@@ -63,10 +63,6 @@ public abstract class HouseKeepingTask implements Runnable
{
_logger.warn(this.getClass().getSimpleName() + " throw exception: " + e, e);
}
- finally
- {
- CurrentActor.remove();
- }
}
public VirtualHost getVirtualHost()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index 04f19b79bb..4ed0507228 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -20,28 +20,30 @@
*/
package org.apache.qpid.server.virtualhost;
-import java.util.UUID;
-
import org.apache.qpid.common.Closeable;
-import org.apache.qpid.server.binding.BindingFactory;
-import org.apache.qpid.server.configuration.ConfigStore;
-import org.apache.qpid.server.configuration.VirtualHostConfig;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.connection.IConnectionRegistry;
-import org.apache.qpid.server.exchange.ExchangeFactory;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.configuration.VirtualHostConfiguration;
+import org.apache.qpid.server.configuration.VirtualHostConfig;
+import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.stats.StatisticsGatherer;
-import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.binding.BindingFactory;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.TimerTask;
+import java.util.concurrent.FutureTask;
-public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer
+public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable
{
IConnectionRegistry getConnectionRegistry();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
index 0fd31973b2..96a9ac729e 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java
@@ -43,10 +43,7 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.AMQException;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.util.ByteBufferInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
@@ -239,14 +236,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
FieldTable argumentsFT = null;
if(buf != null)
{
- try
- {
- argumentsFT = new FieldTable(new DataInputStream(new ByteBufferInputStream(buf)),buf.limit());
- }
- catch (IOException e)
- {
- throw new RuntimeException("IOException should not be thrown here", e);
- }
+ argumentsFT = new FieldTable(org.apache.mina.common.ByteBuffer.wrap(buf),buf.limit());
}
BindingFactory bf = _virtualHost.getBindingFactory();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
index 17c65003e9..6ec1c512e5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java
@@ -20,21 +20,23 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -61,8 +63,6 @@ import org.apache.qpid.server.logging.messages.VirtualHostMessages;
import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.DefaultQueueRegistry;
@@ -71,7 +71,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
@@ -99,7 +99,7 @@ public class VirtualHostImpl implements VirtualHost
private AMQBrokerManagerMBean _brokerMBean;
- private final AuthenticationManager _authenticationManager;
+ private AuthenticationManager _authenticationManager;
private SecurityManager _securityManager;
@@ -111,8 +111,6 @@ public class VirtualHostImpl implements VirtualHost
private BrokerConfig _broker;
private UUID _id;
- private boolean _statisticsEnabled = false;
- private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final long _createTime = System.currentTimeMillis();
private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
@@ -163,12 +161,12 @@ public class VirtualHostImpl implements VirtualHost
public String getObjectInstanceName()
{
- return ObjectName.quote(_name);
+ return _name.toString();
}
public String getName()
{
- return _name;
+ return _name.toString();
}
public VirtualHostImpl getVirtualHost()
@@ -177,11 +175,22 @@ public class VirtualHostImpl implements VirtualHost
}
}
- public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
+ public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception
+ {
+ this(appRegistry, hostConfig, null);
+ }
+
+
+ public VirtualHostImpl(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
+ {
+ this(ApplicationRegistry.getInstance(),hostConfig,store);
+ }
+
+ private VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
{
if (hostConfig == null)
{
- throw new IllegalArgumentException("HostConfig cannot be null");
+ throw new IllegalAccessException("HostConfig and MessageStore cannot be null");
}
_appRegistry = appRegistry;
@@ -235,28 +244,21 @@ public class VirtualHostImpl implements VirtualHost
initialiseMessageStore(hostConfig);
}
- _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager();
+ _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, _configuration);
_brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
_brokerMBean.register();
- initialiseHouseKeeping(hostConfig.getHousekeepingCheckPeriod());
-
- initialiseStatistics();
+ initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod());
}
- /**
- * Initialise a housekeeping task to iterate over queues cleaning expired messages with no consumers
- * and checking for idle or open transactions that have exceeded the permitted thresholds.
- *
- * @param period
- */
private void initialiseHouseKeeping(long period)
{
+ /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */
if (period != 0L)
{
- class VirtualHostHouseKeepingTask extends HouseKeepingTask
+ class ExpiredMessagesTask extends HouseKeepingTask
{
- public VirtualHostHouseKeepingTask(VirtualHost vhost)
+ public ExpiredMessagesTask(VirtualHost vhost)
{
super(vhost);
}
@@ -279,29 +281,18 @@ public class VirtualHostImpl implements VirtualHost
// house keeping task from running.
}
}
- for (AMQConnectionModel connection : getConnectionRegistry().getConnections())
- {
- _logger.debug("Checking for long running open transactions on connection " + connection);
- for (AMQSessionModel session : connection.getSessionModels())
- {
- _logger.debug("Checking for long running open transactions on session " + session);
- try
- {
- session.checkTransactionStatus(_configuration.getTransactionTimeoutOpenWarn(),
- _configuration.getTransactionTimeoutOpenClose(),
- _configuration.getTransactionTimeoutIdleWarn(),
- _configuration.getTransactionTimeoutIdleClose());
- }
- catch (Exception e)
- {
- _logger.error("Exception in housekeeping for connection: " + connection.toString(), e);
- }
- }
- }
}
}
- scheduleHouseKeepingTask(period, new VirtualHostHouseKeepingTask(this));
+ scheduleHouseKeepingTask(period, new ExpiredMessagesTask(this));
+
+ class ForceChannelClosuresTask extends TimerTask
+ {
+ public void run()
+ {
+ _connectionRegistry.expireClosedChannels();
+ }
+ }
Map<String, VirtualHostPluginFactory> plugins =
ApplicationRegistry.getInstance().getPluginManager().getVirtualHostPlugins();
@@ -455,57 +446,46 @@ public class VirtualHostImpl implements VirtualHost
private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException
{
AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
- String queueName = queue.getName();
if (queue.isDurable())
{
getDurableConfigurationStore().createQueue(queue);
}
- //get the exchange name (returns default exchange name if none was specified)
String exchangeName = queueConfiguration.getExchange();
- Exchange exchange = _exchangeRegistry.getExchange(exchangeName);
+ Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName));
+
+ if (exchange == null)
+ {
+ exchange = _exchangeRegistry.getDefaultExchange();
+ }
+
if (exchange == null)
{
- throw new ConfigurationException("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName);
+ throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName);
}
- Exchange defaultExchange = _exchangeRegistry.getDefaultExchange();
-
- //get routing keys in configuration (returns empty list if none are defined)
- List<?> routingKeys = queueConfiguration.getRoutingKeys();
+ List routingKeys = queueConfiguration.getRoutingKeys();
+ if (routingKeys == null || routingKeys.isEmpty())
+ {
+ routingKeys = Collections.singletonList(queue.getNameShortString());
+ }
for (Object routingKeyNameObj : routingKeys)
{
- String routingKey = String.valueOf(routingKeyNameObj);
-
- if (exchange.equals(defaultExchange) && !queueName.equals(routingKey))
+ AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj));
+ if (_logger.isInfoEnabled())
{
- throw new ConfigurationException("Illegal attempt to bind queue '" + queueName +
- "' to the default exchange with a key other than the queue name: " + routingKey);
+ _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this);
}
-
- configureBinding(queue, exchange, routingKey);
- }
-
- if (!exchange.equals(defaultExchange))
- {
- //bind the queue to the named exchange using its name
- configureBinding(queue, exchange, queueName);
+ _bindingFactory.addBinding(routingKey.toString(), queue, exchange, null);
}
- //ensure the queue is bound to the default exchange using its name
- configureBinding(queue, defaultExchange, queueName);
- }
-
- private void configureBinding(AMQQueue queue, Exchange exchange, String routingKey) throws AMQException
- {
- if (_logger.isInfoEnabled())
+ if (exchange != _exchangeRegistry.getDefaultExchange())
{
- _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + exchange.getName());
+ _bindingFactory.addBinding(queue.getNameShortString().toString(), queue, exchange, null);
}
- _bindingFactory.addBinding(routingKey, queue, exchange, null);
}
public String getName()
@@ -647,80 +627,6 @@ public class VirtualHostImpl implements VirtualHost
{
return _bindingFactory;
}
-
- public void registerMessageDelivered(long messageSize)
- {
- if (isStatisticsEnabled())
- {
- _messagesDelivered.registerEvent(1L);
- _dataDelivered.registerEvent(messageSize);
- }
- _appRegistry.registerMessageDelivered(messageSize);
- }
-
- public void registerMessageReceived(long messageSize, long timestamp)
- {
- if (isStatisticsEnabled())
- {
- _messagesReceived.registerEvent(1L, timestamp);
- _dataReceived.registerEvent(messageSize, timestamp);
- }
- _appRegistry.registerMessageReceived(messageSize, timestamp);
- }
-
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return _messagesReceived;
- }
-
- public StatisticsCounter getDataReceiptStatistics()
- {
- return _dataReceived;
- }
-
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return _messagesDelivered;
- }
-
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return _dataDelivered;
- }
-
- public void resetStatistics()
- {
- _messagesDelivered.reset();
- _dataDelivered.reset();
- _messagesReceived.reset();
- _dataReceived.reset();
-
- for (AMQConnectionModel connection : _connectionRegistry.getConnections())
- {
- connection.resetStatistics();
- }
- }
-
- public void initialiseStatistics()
- {
- setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS &&
- _appRegistry.getConfiguration().isStatisticsGenerationVirtualhostsEnabled());
-
- _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
- _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
- _messagesReceived = new StatisticsCounter("messages-received-" + getName());
- _dataReceived = new StatisticsCounter("bytes-received-" + getName());
- }
-
- public boolean isStatisticsEnabled()
- {
- return _statisticsEnabled;
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
- _statisticsEnabled = enabled;
- }
public void createBrokerConnection(final String transport,
final String host,
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
index 2c0ceed80b..dca165fa7e 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
@@ -192,7 +192,7 @@ public class MessageStoreTool
if (_initialised)
{
- ApplicationRegistry.remove();
+ ApplicationRegistry.remove(1);
}
_console.println("...exiting");
@@ -274,7 +274,7 @@ public class MessageStoreTool
{
ConfigurationFileApplicationRegistry registry = new ConfigurationFileApplicationRegistry(configFile);
- ApplicationRegistry.remove();
+ ApplicationRegistry.remove(1);
ApplicationRegistry.initialise(registry);
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
index 806e161bbc..4fd4999b19 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
@@ -364,7 +364,7 @@ public class Show extends AbstractCommand
{
if(msg instanceof AMQMessage)
{
- headers = ((BasicContentHeaderProperties) ((AMQMessage)msg).getContentHeaderBody().getProperties());
+ headers = ((BasicContentHeaderProperties) ((AMQMessage)msg).getContentHeaderBody().properties);
}
}
catch (AMQException e)
diff --git a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
deleted file mode 100644
index 131f316330..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java
+++ /dev/null
@@ -1,202 +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.
- *
- */
-package org.apache.qpid.server;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.qpid.test.utils.QpidTestCase;
-
-
-public class BrokerOptionsTest extends QpidTestCase
-{
- private BrokerOptions _options;
-
- private static final int TEST_PORT1 = 6789;
- private static final int TEST_PORT2 = 6790;
-
-
- protected void setUp()
- {
- _options = new BrokerOptions();
- }
-
- public void testDefaultPort()
- {
- assertEquals(Collections.<Integer>emptySet(), _options.getPorts());
- }
-
- public void testOverriddenPort()
- {
- _options.addPort(TEST_PORT1);
- assertEquals(Collections.singleton(TEST_PORT1), _options.getPorts());
- }
-
- public void testManyOverriddenPorts()
- {
- _options.addPort(TEST_PORT1);
- _options.addPort(TEST_PORT2);
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getPorts());
- }
-
- public void testDuplicateOverriddenPortsAreSilentlyIgnored()
- {
- _options.addPort(TEST_PORT1);
- _options.addPort(TEST_PORT2);
- _options.addPort(TEST_PORT1); // duplicate - should be silently ignored
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getPorts());
- }
-
- public void testDefaultSSLPort()
- {
- assertEquals(Collections.<Integer>emptySet(), _options.getSSLPorts());
- }
-
- public void testOverriddenSSLPort()
- {
- _options.addSSLPort(TEST_PORT1);
- assertEquals(Collections.singleton(TEST_PORT1), _options.getSSLPorts());
- }
-
- public void testManyOverriddenSSLPorts()
- {
- _options.addSSLPort(TEST_PORT1);
- _options.addSSLPort(TEST_PORT2);
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getSSLPorts());
- }
-
- public void testDuplicateOverriddenSSLPortsAreSilentlyIgnored()
- {
- _options.addSSLPort(TEST_PORT1);
- _options.addSSLPort(TEST_PORT2);
- _options.addSSLPort(TEST_PORT1); // duplicate - should be silently ignored
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getSSLPorts());
- }
-
- public void testDefaultConfigFile()
- {
- assertNull(_options.getConfigFile());
- }
-
- public void testOverriddenConfigFile()
- {
- final String testConfigFile = "etc/mytestconfig.xml";
- _options.setConfigFile(testConfigFile);
- assertEquals(testConfigFile, _options.getConfigFile());
- }
-
- public void testDefaultLogConfigFile()
- {
- assertNull(_options.getLogConfigFile());
- }
-
- public void testOverriddenLogConfigFile()
- {
- final String testLogConfigFile = "etc/mytestlog4j.xml";
- _options.setLogConfigFile(testLogConfigFile);
- assertEquals(testLogConfigFile, _options.getLogConfigFile());
- }
-
- public void testDefaultJmxPortRegistryServer()
- {
- assertNull(_options.getJmxPortRegistryServer());
- }
-
- public void testJmxPortRegistryServer()
- {
- _options.setJmxPortRegistryServer(TEST_PORT1);
- assertEquals(Integer.valueOf(TEST_PORT1), _options.getJmxPortRegistryServer());
- }
-
- public void testDefaultJmxPortConnectorServer()
- {
- assertNull(_options.getJmxPortConnectorServer());
- }
-
- public void testJmxPortConnectorServer()
- {
- _options.setJmxPortConnectorServer(TEST_PORT1);
- assertEquals(Integer.valueOf(TEST_PORT1), _options.getJmxPortConnectorServer());
- }
-
- public void testQpidHomeExposesSysProperty()
- {
- assertEquals(System.getProperty("QPID_HOME"), _options.getQpidHome());
- }
-
- public void testDefaultExcludesPortFor0_10()
- {
- assertEquals(Collections.EMPTY_SET, _options.getExcludedPorts(ProtocolExclusion.v0_10));
- }
-
- public void testOverriddenExcludesPortFor0_10()
- {
- _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1);
- assertEquals(Collections.singleton(TEST_PORT1), _options.getExcludedPorts(ProtocolExclusion.v0_10));
- }
-
- public void testManyOverriddenExcludedPortFor0_10()
- {
- _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1);
- _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT2);
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getExcludedPorts(ProtocolExclusion.v0_10));
- }
-
- public void testDuplicatedOverriddenExcludedPortFor0_10AreSilentlyIgnored()
- {
- _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1);
- _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT2);
- final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2}));
- assertEquals(expectedPorts, _options.getExcludedPorts(ProtocolExclusion.v0_10));
- }
-
- public void testDefaultBind()
- {
- assertNull(_options.getBind());
- }
-
- public void testOverriddenBind()
- {
- final String bind = "192.168.0.1";
- _options.setBind(bind);
- assertEquals(bind, _options.getBind());
- }
-
- public void testDefaultLogWatchFrequency()
- {
- assertEquals(0L, _options.getLogWatchFrequency());
- }
-
- public void testOverridenLogWatchFrequency()
- {
- final int myFreq = 10 * 1000;
-
- _options.setLogWatchFrequency(myFreq);
- assertEquals(myFreq, _options.getLogWatchFrequency());
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
deleted file mode 100644
index 9b0ae82b84..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.apache.qpid.server;
-
-import java.util.EnumSet;
-
-import org.apache.qpid.test.utils.QpidTestCase;
-
-/**
- * Test to verify the command line parsing within the Main class, by
- * providing it a series of command line arguments and verifying the
- * BrokerOptions emerging for use in starting the Broker instance.
- */
-public class MainTest extends QpidTestCase
-{
- public void testNoOptionsSpecified()
- {
- BrokerOptions options = startDummyMain("");
-
- assertTrue(options.getPorts().isEmpty());
- assertTrue(options.getSSLPorts().isEmpty());
- assertEquals(null, options.getJmxPortRegistryServer());
- assertEquals(null, options.getConfigFile());
- assertEquals(null, options.getLogConfigFile());
- assertEquals(null, options.getBind());
-
- for(ProtocolExclusion pe : EnumSet.allOf(ProtocolExclusion.class))
- {
- assertEquals(0, options.getExcludedPorts(pe).size());
- }
- }
-
- public void testPortOverriddenSingle()
- {
- BrokerOptions options = startDummyMain("-p 1234");
-
- assertTrue(options.getPorts().contains(1234));
- assertEquals(1, options.getPorts().size());
- assertTrue(options.getSSLPorts().isEmpty());
- }
-
- public void testPortOverriddenMultiple()
- {
- BrokerOptions options = startDummyMain("-p 1234 -p 4321");
-
- assertTrue(options.getPorts().contains(1234));
- assertTrue(options.getPorts().contains(4321));
- assertEquals(2, options.getPorts().size());
- assertTrue(options.getSSLPorts().isEmpty());
- }
-
- public void testSSLPortOverriddenSingle()
- {
- BrokerOptions options = startDummyMain("-s 5678");
-
- assertTrue(options.getSSLPorts().contains(5678));
- assertEquals(1, options.getSSLPorts().size());
- assertTrue(options.getPorts().isEmpty());
- }
-
- public void testSSLPortOverriddenMultiple()
- {
- BrokerOptions options = startDummyMain("-s 5678 -s 8765");
-
- assertTrue(options.getSSLPorts().contains(5678));
- assertTrue(options.getSSLPorts().contains(8765));
- assertEquals(2, options.getSSLPorts().size());
- assertTrue(options.getPorts().isEmpty());
- }
-
- public void testNonSSLandSSLPortsOverridden()
- {
- BrokerOptions options = startDummyMain("-p 5678 -s 8765");
-
- assertTrue(options.getPorts().contains(5678));
- assertTrue(options.getSSLPorts().contains(8765));
- assertEquals(1, options.getPorts().size());
- assertEquals(1, options.getSSLPorts().size());
- }
-
- public void testJmxPortRegistryServerOverridden()
- {
- BrokerOptions options = startDummyMain("--jmxregistryport 3456");
-
- assertEquals(Integer.valueOf(3456), options.getJmxPortRegistryServer());
-
- options = startDummyMain("-m 3457");
- assertEquals(Integer.valueOf(3457), options.getJmxPortRegistryServer());
- }
-
- public void testJmxPortConnectorServerOverridden()
- {
- BrokerOptions options = startDummyMain("--jmxconnectorport 3456");
-
- assertEquals(Integer.valueOf(3456), options.getJmxPortConnectorServer());
- }
-
- public void testExclude0_10()
- {
- BrokerOptions options = startDummyMain("-p 3456 --exclude-0-10 3456");
-
- assertTrue(options.getPorts().contains(3456));
- assertEquals(1, options.getPorts().size());
- assertTrue(options.getExcludedPorts(ProtocolExclusion.v0_10).contains(3456));
- assertEquals(1, options.getExcludedPorts(ProtocolExclusion.v0_10).size());
- assertEquals(0, options.getExcludedPorts(ProtocolExclusion.v0_9_1).size());
- }
-
- public void testConfig()
- {
- BrokerOptions options = startDummyMain("-c abcd/config.xml");
-
- assertEquals("abcd/config.xml", options.getConfigFile());
- }
-
- public void testLogConfig()
- {
- BrokerOptions options = startDummyMain("-l wxyz/log4j.xml");
-
- assertEquals("wxyz/log4j.xml", options.getLogConfigFile());
- }
-
- public void testLogWatch()
- {
- BrokerOptions options = startDummyMain("-w 9");
-
- assertEquals(9, options.getLogWatchFrequency());
- }
-
- private BrokerOptions startDummyMain(String commandLine)
- {
- return (new TestMain(commandLine.split("\\s"))).getOptions();
- }
-
- private class TestMain extends Main
- {
- private BrokerOptions _options;
-
- public TestMain(String[] args)
- {
- super(args);
- }
-
- @Override
- protected void startBroker(BrokerOptions options)
- {
- _options = options;
- }
-
- public BrokerOptions getOptions()
- {
- return _options;
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/RunBrokerWithCommand.java b/java/broker/src/test/java/org/apache/qpid/server/RunBrokerWithCommand.java
new file mode 100644
index 0000000000..59543874b4
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/RunBrokerWithCommand.java
@@ -0,0 +1,132 @@
+/*
+ * 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 org.apache.qpid.server;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+public class RunBrokerWithCommand
+{
+ public static void main(String[] args)
+ {
+ //Start the broker
+ try
+ {
+ String[] fudge = args.clone();
+
+ // Override the first value which is the command we are going to run later.
+ fudge[0] = "-v";
+ new Main(fudge).startup();
+ }
+ catch (Exception e)
+ {
+ System.err.println("Unable to start broker due to: " + e.getMessage());
+
+ e.printStackTrace();
+ exit(1);
+ }
+
+ Logger.getRootLogger().setLevel(Level.ERROR);
+
+ //run command
+ try
+ {
+ Process task = Runtime.getRuntime().exec(args[0]);
+ System.err.println("Started Proccess: " + args[0]);
+
+ InputStream inputStream = task.getInputStream();
+
+ InputStream errorStream = task.getErrorStream();
+
+ Thread out = new Thread(new Outputter("[OUT]", new BufferedReader(new InputStreamReader(inputStream))));
+ Thread err = new Thread(new Outputter("[ERR]", new BufferedReader(new InputStreamReader(errorStream))));
+
+ out.start();
+ err.start();
+
+ out.join();
+ err.join();
+
+ System.err.println("Waiting for process to exit: " + args[0]);
+ task.waitFor();
+ System.err.println("Done Proccess: " + args[0]);
+
+ }
+ catch (IOException e)
+ {
+ System.err.println("Proccess had problems: " + e.getMessage());
+ e.printStackTrace(System.err);
+ exit(1);
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println("Proccess had problems: " + e.getMessage());
+ e.printStackTrace(System.err);
+
+ exit(1);
+ }
+
+
+ exit(0);
+ }
+
+ private static void exit(int i)
+ {
+ Logger.getRootLogger().setLevel(Level.INFO);
+ System.exit(i);
+ }
+
+ static class Outputter implements Runnable
+ {
+
+ BufferedReader reader;
+ String prefix;
+
+ Outputter(String s, BufferedReader r)
+ {
+ prefix = s;
+ reader = r;
+ }
+
+ public void run()
+ {
+ String line;
+ try
+ {
+ while ((line = reader.readLine()) != null)
+ {
+ System.out.println(prefix + line);
+ }
+ }
+ catch (IOException e)
+ {
+ System.out.println("Error occured reading; " + e.getMessage());
+ }
+ }
+
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
index d22f1e6e94..718874cf69 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java
@@ -20,598 +20,742 @@
*/
package org.apache.qpid.server.configuration;
-import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.List;
import java.util.Locale;
+import junit.framework.TestCase;
+
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.protocol.AMQProtocolEngine;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
-import org.apache.qpid.server.util.TestApplicationRegistry;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.transport.TestNetworkDriver;
-public class ServerConfigurationTest extends QpidTestCase
+public class ServerConfigurationTest extends InternalBrokerBaseCase
{
private XMLConfiguration _config = new XMLConfiguration();
- private ServerConfiguration _serverConfig = null;
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
- _serverConfig = new ServerConfiguration(_config);
- ApplicationRegistry.initialise(new TestApplicationRegistry(_serverConfig));
- }
- @Override
- protected void tearDown() throws Exception
+ public void testSetJMXManagementPort() throws ConfigurationException
{
- super.tearDown();
- ApplicationRegistry.remove();
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ serverConfig.setJMXManagementPort(23);
+ assertEquals(23, serverConfig.getJMXManagementPort());
}
- public void testSetJMXPortRegistryServer() throws ConfigurationException
+ public void testGetJMXManagementPort() throws ConfigurationException
{
- _serverConfig.initialise();
- _serverConfig.setJMXPortRegistryServer(23);
- assertEquals(23, _serverConfig.getJMXPortRegistryServer());
+ _config.setProperty("management.jmxport", 42);
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(42, serverConfig.getJMXManagementPort());
}
- public void testGetJMXPortRegistryServer() throws ConfigurationException
+ public void testGetPlatformMbeanserver() throws ConfigurationException
{
- _config.setProperty(ServerConfiguration.MGMT_JMXPORT_REGISTRYSERVER, 42);
- _serverConfig.initialise();
- assertEquals(42, _serverConfig.getJMXPortRegistryServer());
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getPlatformMbeanserver());
+
+ // Check value we set
+ _config.setProperty("management.platform-mbeanserver", false);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getPlatformMbeanserver());
}
- public void testDefaultJMXPortRegistryServer() throws ConfigurationException
+ public void testGetPluginDirectory() throws ConfigurationException
{
- _serverConfig.initialise();
- assertEquals(8999, _serverConfig.getJMXPortRegistryServer());
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(null, serverConfig.getPluginDirectory());
+
+ // Check value we set
+ _config.setProperty("plugin-directory", "/path/to/plugins");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("/path/to/plugins", serverConfig.getPluginDirectory());
}
- public void testSetJMXPortConnectorServer() throws ConfigurationException
+ public void testGetCacheDirectory() throws ConfigurationException
{
+ // Check default
ServerConfiguration serverConfig = new ServerConfiguration(_config);
- serverConfig.setJMXPortConnectorServer(67);
- assertEquals(67, serverConfig.getJMXConnectorServerPort());
+ serverConfig.initialise();
+ assertEquals(null, serverConfig.getCacheDirectory());
+
+ // Check value we set
+ _config.setProperty("cache-directory", "/path/to/cache");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("/path/to/cache", serverConfig.getCacheDirectory());
}
- public void testGetJMXPortConnectorServer() throws ConfigurationException
+ public void testGetPrincipalDatabaseNames() throws ConfigurationException
{
- _config.setProperty(ServerConfiguration.MGMT_JMXPORT_CONNECTORSERVER, 67);
+ // Check default
ServerConfiguration serverConfig = new ServerConfiguration(_config);
- assertEquals(67, serverConfig.getJMXConnectorServerPort());
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getPrincipalDatabaseNames().size());
+
+ // Check value we set
+ _config.setProperty("security.principal-databases.principal-database(0).name", "a");
+ _config.setProperty("security.principal-databases.principal-database(1).name", "b");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ List<String> dbs = serverConfig.getPrincipalDatabaseNames();
+ assertEquals(2, dbs.size());
+ assertEquals("a", dbs.get(0));
+ assertEquals("b", dbs.get(1));
}
- public void testDefaultJMXPortConnectorServer() throws ConfigurationException
+ public void testGetPrincipalDatabaseClass() throws ConfigurationException
{
+ // Check default
ServerConfiguration serverConfig = new ServerConfiguration(_config);
- assertEquals(ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET,
- serverConfig.getJMXConnectorServerPort());
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getPrincipalDatabaseClass().size());
+
+ // Check value we set
+ _config.setProperty("security.principal-databases.principal-database(0).class", "a");
+ _config.setProperty("security.principal-databases.principal-database(1).class", "b");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ List<String> dbs = serverConfig.getPrincipalDatabaseClass();
+ assertEquals(2, dbs.size());
+ assertEquals("a", dbs.get(0));
+ assertEquals("b", dbs.get(1));
}
- public void testGetPlatformMbeanserver() throws ConfigurationException
+ public void testGetPrincipalDatabaseAttributeNames() throws ConfigurationException
{
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getPlatformMbeanserver());
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getPrincipalDatabaseAttributeNames(1).size());
// Check value we set
- _config.setProperty("management.platform-mbeanserver", false);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getPlatformMbeanserver());
+ _config.setProperty("security.principal-databases.principal-database(0).attributes(0).attribute.name", "a");
+ _config.setProperty("security.principal-databases.principal-database(0).attributes(1).attribute.name", "b");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ List<String> dbs = serverConfig.getPrincipalDatabaseAttributeNames(0);
+ assertEquals(2, dbs.size());
+ assertEquals("a", dbs.get(0));
+ assertEquals("b", dbs.get(1));
}
- public void testGetPluginDirectory() throws ConfigurationException
+ public void testGetPrincipalDatabaseAttributeValues() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(null, _serverConfig.getPluginDirectory());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getPrincipalDatabaseAttributeValues(1).size());
// Check value we set
- _config.setProperty("plugin-directory", "/path/to/plugins");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("/path/to/plugins", _serverConfig.getPluginDirectory());
+ _config.setProperty("security.principal-databases.principal-database(0).attributes(0).attribute.value", "a");
+ _config.setProperty("security.principal-databases.principal-database(0).attributes(1).attribute.value", "b");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ List<String> dbs = serverConfig.getPrincipalDatabaseAttributeValues(0);
+ assertEquals(2, dbs.size());
+ assertEquals("a", dbs.get(0));
+ assertEquals("b", dbs.get(1));
}
- public void testGetCacheDirectory() throws ConfigurationException
+ public void testGetManagementAccessList() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(null, _serverConfig.getCacheDirectory());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getManagementAccessList().size());
// Check value we set
- _config.setProperty("cache-directory", "/path/to/cache");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("/path/to/cache", _serverConfig.getCacheDirectory());
+ _config.setProperty("security.jmx.access(0)", "a");
+ _config.setProperty("security.jmx.access(1)", "b");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ List<String> dbs = serverConfig.getManagementAccessList();
+ assertEquals(2, dbs.size());
+ assertEquals("a", dbs.get(0));
+ assertEquals("b", dbs.get(1));
}
public void testGetFrameSize() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(65536, _serverConfig.getFrameSize());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(65536, serverConfig.getFrameSize());
// Check value we set
_config.setProperty("advanced.framesize", "23");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(23, _serverConfig.getFrameSize());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getFrameSize());
}
+ public void testGetProtectIOEnabled() throws ConfigurationException
+ {
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getProtectIOEnabled());
+
+ // Check value we set
+ _config.setProperty(ServerConfiguration.CONNECTOR_PROTECTIO_ENABLED, true);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getProtectIOEnabled());
+ }
+
+ public void testGetBufferReadLimit() throws ConfigurationException
+ {
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(262144, serverConfig.getBufferReadLimit());
+
+ // Check value we set
+ _config.setProperty(ServerConfiguration.CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE, 23);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getBufferReadLimit());
+ }
+
+ public void testGetBufferWriteLimit() throws ConfigurationException
+ {
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(262144, serverConfig.getBufferWriteLimit());
+
+ // Check value we set
+ _config.setProperty(ServerConfiguration.CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE, 23);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getBufferWriteLimit());
+ }
+
+
public void testGetStatusEnabled() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
assertEquals(ServerConfiguration.DEFAULT_STATUS_UPDATES.equalsIgnoreCase("on"),
- _serverConfig.getStatusUpdatesEnabled());
+ serverConfig.getStatusUpdatesEnabled());
// Check disabling we set
_config.setProperty(ServerConfiguration.STATUS_UPDATES, "off");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getStatusUpdatesEnabled());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getStatusUpdatesEnabled());
// Check invalid values don't cause error but result in disabled
_config.setProperty(ServerConfiguration.STATUS_UPDATES, "Yes Please");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getStatusUpdatesEnabled());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getStatusUpdatesEnabled());
}
public void testGetSynchedClocks() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getSynchedClocks());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getSynchedClocks());
// Check value we set
_config.setProperty("advanced.synced-clocks", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getSynchedClocks());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getSynchedClocks());
}
public void testGetLocale() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
// The Default is what ever the VMs default is
Locale defaultLocale = Locale.getDefault();
- assertEquals(defaultLocale, _serverConfig.getLocale());
+ assertEquals(defaultLocale, serverConfig.getLocale());
//Test Language only
Locale update = new Locale("es");
_config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(update, _serverConfig.getLocale());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(update, serverConfig.getLocale());
//Test Language and Country
update = new Locale("es","ES");
_config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es_ES");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(update, _serverConfig.getLocale());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(update, serverConfig.getLocale());
//Test Language and Country and Variant
update = new Locale("es","ES", "Traditional_WIN");
_config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es_ES_Traditional_WIN");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(update, _serverConfig.getLocale());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(update, serverConfig.getLocale());
}
public void testGetMsgAuth() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getMsgAuth());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getMsgAuth());
// Check value we set
_config.setProperty("security.msg-auth", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getMsgAuth());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getMsgAuth());
+ }
+
+ public void testGetJMXPrincipalDatabase() throws ConfigurationException
+ {
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(null, serverConfig.getJMXPrincipalDatabase());
+
+ // Check value we set
+ _config.setProperty("security.jmx.principal-database", "a");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getJMXPrincipalDatabase());
}
public void testGetManagementKeyStorePath() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(null, _serverConfig.getManagementKeyStorePath());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(null, serverConfig.getManagementKeyStorePath());
// Check value we set
_config.setProperty("management.ssl.keyStorePath", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getManagementKeyStorePath());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getManagementKeyStorePath());
}
public void testGetManagementSSLEnabled() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementSSLEnabled());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getManagementSSLEnabled());
// Check value we set
_config.setProperty("management.ssl.enabled", false);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getManagementSSLEnabled());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getManagementSSLEnabled());
}
- public void testGetManagementKeystorePassword() throws ConfigurationException
+ public void testGetManagementKeyStorePassword() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(null, _serverConfig.getManagementKeyStorePassword());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(null, serverConfig.getManagementKeyStorePassword());
// Check value we set
_config.setProperty("management.ssl.keyStorePassword", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getManagementKeyStorePassword());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getManagementKeyStorePassword());
}
public void testGetQueueAutoRegister() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getQueueAutoRegister());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getQueueAutoRegister());
// Check value we set
_config.setProperty("queue.auto_register", false);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getQueueAutoRegister());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getQueueAutoRegister());
}
public void testGetManagementEnabled() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getManagementEnabled());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getManagementEnabled());
// Check value we set
_config.setProperty("management.enabled", false);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getManagementEnabled());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getManagementEnabled());
}
public void testSetManagementEnabled() throws ConfigurationException
{
// Check value we set
- _serverConfig.initialise();
- _serverConfig.setManagementEnabled(false);
- assertEquals(false, _serverConfig.getManagementEnabled());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ serverConfig.setManagementEnabled(false);
+ assertEquals(false, serverConfig.getManagementEnabled());
}
public void testGetHeartBeatDelay() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(5, _serverConfig.getHeartBeatDelay());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(5, serverConfig.getHeartBeatDelay());
// Check value we set
_config.setProperty("heartbeat.delay", 23);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(23, _serverConfig.getHeartBeatDelay());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getHeartBeatDelay());
}
public void testGetHeartBeatTimeout() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(2.0, _serverConfig.getHeartBeatTimeout());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(2.0, serverConfig.getHeartBeatTimeout());
// Check value we set
_config.setProperty("heartbeat.timeoutFactor", 2.3);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(2.3, _serverConfig.getHeartBeatTimeout());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(2.3, serverConfig.getHeartBeatTimeout());
}
public void testGetMaximumMessageAge() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(0, _serverConfig.getMaximumMessageAge());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getMaximumMessageAge());
// Check value we set
_config.setProperty("maximumMessageAge", 10L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getMaximumMessageAge());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getMaximumMessageAge());
}
public void testGetMaximumMessageCount() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(0, _serverConfig.getMaximumMessageCount());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getMaximumMessageCount());
// Check value we set
_config.setProperty("maximumMessageCount", 10L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getMaximumMessageCount());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getMaximumMessageCount());
}
public void testGetMaximumQueueDepth() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(0, _serverConfig.getMaximumQueueDepth());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getMaximumQueueDepth());
// Check value we set
_config.setProperty("maximumQueueDepth", 10L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getMaximumQueueDepth());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getMaximumQueueDepth());
}
public void testGetMaximumMessageSize() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(0, _serverConfig.getMaximumMessageSize());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getMaximumMessageSize());
// Check value we set
_config.setProperty("maximumMessageSize", 10L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getMaximumMessageSize());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getMaximumMessageSize());
}
public void testGetMinimumAlertRepeatGap() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(0, _serverConfig.getMinimumAlertRepeatGap());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(0, serverConfig.getMinimumAlertRepeatGap());
// Check value we set
_config.setProperty("minimumAlertRepeatGap", 10L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getMinimumAlertRepeatGap());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getMinimumAlertRepeatGap());
}
public void testGetProcessors() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(4, _serverConfig.getConnectorProcessors());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(4, serverConfig.getProcessors());
// Check value we set
_config.setProperty("connector.processors", 10);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(10, _serverConfig.getConnectorProcessors());
- }
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(10, serverConfig.getProcessors());
+ }
- public void testGetPorts() throws ConfigurationException
+ public void testGetPort() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertNotNull(_serverConfig.getPorts());
- assertEquals(1, _serverConfig.getPorts().size());
- assertEquals(5672, _serverConfig.getPorts().get(0));
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertNotNull(serverConfig.getPorts());
+ assertEquals(1, serverConfig.getPorts().size());
+ assertEquals(5672, serverConfig.getPorts().get(0));
// Check value we set
_config.setProperty("connector.port", "10");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertNotNull(_serverConfig.getPorts());
- assertEquals(1, _serverConfig.getPorts().size());
- assertEquals("10", _serverConfig.getPorts().get(0));
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertNotNull(serverConfig.getPorts());
+ assertEquals(1, serverConfig.getPorts().size());
+ assertEquals("10", serverConfig.getPorts().get(0));
}
public void testGetBind() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(WILDCARD_ADDRESS, _serverConfig.getBind());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("wildcard", serverConfig.getBind());
// Check value we set
_config.setProperty("connector.bind", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getBind());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getBind());
}
public void testGetReceiveBufferSize() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(ServerConfiguration.DEFAULT_BUFFER_SIZE, _serverConfig.getReceiveBufferSize());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(32767, serverConfig.getReceiveBufferSize());
// Check value we set
_config.setProperty("connector.socketReceiveBuffer", "23");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(23, _serverConfig.getReceiveBufferSize());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getReceiveBufferSize());
}
public void testGetWriteBufferSize() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(ServerConfiguration.DEFAULT_BUFFER_SIZE, _serverConfig.getWriteBufferSize());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(32767, serverConfig.getWriteBufferSize());
// Check value we set
_config.setProperty("connector.socketWriteBuffer", "23");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(23, _serverConfig.getWriteBufferSize());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getWriteBufferSize());
}
public void testGetTcpNoDelay() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getTcpNoDelay());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getTcpNoDelay());
// Check value we set
_config.setProperty("connector.tcpNoDelay", false);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getTcpNoDelay());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getTcpNoDelay());
}
public void testGetEnableExecutorPool() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getEnableExecutorPool());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getEnableExecutorPool());
// Check value we set
_config.setProperty("advanced.filterchain[@enableExecutorPool]", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getEnableExecutorPool());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getEnableExecutorPool());
}
public void testGetEnableSSL() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getEnableSSL());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getEnableSSL());
// Check value we set
_config.setProperty("connector.ssl.enabled", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getEnableSSL());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getEnableSSL());
}
public void testGetSSLOnly() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getSSLOnly());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getSSLOnly());
// Check value we set
_config.setProperty("connector.ssl.sslOnly", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getSSLOnly());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getSSLOnly());
}
- public void testGetSSLPorts() throws ConfigurationException
+ public void testGetSSLPort() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertNotNull(_serverConfig.getSSLPorts());
- assertEquals(1, _serverConfig.getSSLPorts().size());
- assertEquals(ServerConfiguration.DEFAULT_SSL_PORT, _serverConfig.getSSLPorts().get(0));
-
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(8672, serverConfig.getSSLPort());
// Check value we set
- _config.setProperty("connector.ssl.port", "10");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertNotNull(_serverConfig.getSSLPorts());
- assertEquals(1, _serverConfig.getSSLPorts().size());
- assertEquals("10", _serverConfig.getSSLPorts().get(0));
+ _config.setProperty("connector.ssl.port", 23);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getSSLPort());
}
- public void testGetConnectorKeystorePath() throws ConfigurationException
+ public void testGetKeystorePath() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertNull(_serverConfig.getConnectorKeyStorePath());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("none", serverConfig.getKeystorePath());
// Check value we set
- _config.setProperty("connector.ssl.keyStorePath", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getConnectorKeyStorePath());
-
- // Ensure we continue to support the old name keystorePath
- _config.clearProperty("connector.ssl.keyStorePath");
- _config.setProperty("connector.ssl.keystorePath", "b");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("b", _serverConfig.getConnectorKeyStorePath());
+ _config.setProperty("connector.ssl.keystorePath", "a");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getKeystorePath());
}
- public void testGetConnectorKeystorePassword() throws ConfigurationException
+ public void testGetKeystorePassword() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertNull(_serverConfig.getConnectorKeyStorePassword());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("none", serverConfig.getKeystorePassword());
// Check value we set
- _config.setProperty("connector.ssl.keyStorePassword", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getConnectorKeyStorePassword());
-
- // Ensure we continue to support the old name keystorePassword
- _config.clearProperty("connector.ssl.keyStorePassword");
- _config.setProperty("connector.ssl.keystorePassword", "b");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("b", _serverConfig.getConnectorKeyStorePassword());
+ _config.setProperty("connector.ssl.keystorePassword", "a");
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getKeystorePassword());
}
- public void testGetConnectorCertType() throws ConfigurationException
+ public void testGetCertType() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals("SunX509", _serverConfig.getConnectorCertType());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("SunX509", serverConfig.getCertType());
// Check value we set
_config.setProperty("connector.ssl.certType", "a");
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals("a", _serverConfig.getConnectorCertType());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals("a", serverConfig.getCertType());
+ }
+
+ public void testGetQpidNIO() throws ConfigurationException
+ {
+ // Check default
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getQpidNIO());
+
+ // Check value we set
+ _config.setProperty("connector.qpidnio", true);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getQpidNIO());
}
public void testGetUseBiasedWrites() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(false, _serverConfig.getUseBiasedWrites());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(false, serverConfig.getUseBiasedWrites());
// Check value we set
_config.setProperty("advanced.useWriteBiasedPool", true);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- assertEquals(true, _serverConfig.getUseBiasedWrites());
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(true, serverConfig.getUseBiasedWrites());
}
- public void testGetHousekeepingCheckPeriod() throws ConfigurationException
+ public void testGetHousekeepingExpiredMessageCheckPeriod() throws ConfigurationException
{
// Check default
- _serverConfig.initialise();
- assertEquals(30000, _serverConfig.getHousekeepingCheckPeriod());
+ ServerConfiguration serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(30000, serverConfig.getHousekeepingCheckPeriod());
// Check value we set
- _config.setProperty("housekeeping.checkPeriod", 23L);
- _serverConfig = new ServerConfiguration(_config);
- _serverConfig.initialise();
- _serverConfig.setHousekeepingCheckPeriod(42L);
- assertEquals(42, _serverConfig.getHousekeepingCheckPeriod());
+ _config.setProperty("housekeeping.expiredMessageCheckPeriod", 23L);
+ serverConfig = new ServerConfiguration(_config);
+ serverConfig.initialise();
+ assertEquals(23, serverConfig.getHousekeepingCheckPeriod());
+ serverConfig.setHousekeepingExpiredMessageCheckPeriod(42L);
+ assertEquals(42, serverConfig.getHousekeepingCheckPeriod());
}
public void testSingleConfiguration() throws IOException, ConfigurationException
@@ -623,7 +767,7 @@ public class ServerConfigurationTest extends QpidTestCase
out.close();
ServerConfiguration conf = new ServerConfiguration(fileA);
conf.initialise();
- assertEquals("4235", conf.getSSLPorts().get(0));
+ assertEquals(4235, conf.getSSLPort());
}
public void testCombinedConfiguration() throws IOException, ConfigurationException
@@ -648,17 +792,19 @@ public class ServerConfigurationTest extends QpidTestCase
out.close();
out = new FileWriter(fileB);
- out.write("<broker><connector><ssl><port>2345</port></ssl></connector></broker>");
+ out.write("<broker><connector><ssl><port>2345</port></ssl><qpidnio>true</qpidnio></connector></broker>");
out.close();
ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile());
config.initialise();
- assertEquals("4235", config.getSSLPorts().get(0)); // From first file, not
+ assertEquals(4235, config.getSSLPort()); // From first file, not
// overriden by second
assertNotNull(config.getPorts());
assertEquals(1, config.getPorts().size());
assertEquals("2342", config.getPorts().get(0)); // From the first file, not
// present in the second
+ assertEquals(true, config.getQpidNIO()); // From the second file, not
+ // present in the first
}
public void testVariableInterpolation() throws Exception
@@ -689,8 +835,9 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("<broker>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -699,7 +846,11 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<rule access=\""+ ((allow) ? "allow" : "deny") +"\" network=\"127.0.0.1\"/>");
out.write("\t\t</firewall>\n");
@@ -735,8 +886,9 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("<broker>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -745,7 +897,11 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
out.write("\t\t</firewall>\n");
@@ -836,8 +992,9 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("<broker>\n");
out.write("\t<management><enabled>false</enabled></management>\n");
out.write("\t<security>\n");
- out.write("\t\t<pd-auth-manager>\n");
+ out.write("\t\t<principal-databases>\n");
out.write("\t\t\t<principal-database>\n");
+ out.write("\t\t\t\t<name>passwordfile</name>\n");
out.write("\t\t\t\t<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>\n");
out.write("\t\t\t\t<attributes>\n");
out.write("\t\t\t\t\t<attribute>\n");
@@ -846,7 +1003,11 @@ public class ServerConfigurationTest extends QpidTestCase
out.write("\t\t\t\t\t</attribute>\n");
out.write("\t\t\t\t</attributes>\n");
out.write("\t\t\t</principal-database>\n");
- out.write("\t\t</pd-auth-manager>\n");
+ out.write("\t\t</principal-databases>\n");
+ out.write("\t\t<jmx>\n");
+ out.write("\t\t\t<access>/dev/null</access>\n");
+ out.write("\t\t\t<principal-database>passwordfile</principal-database>\n");
+ out.write("\t\t</jmx>\n");
out.write("\t\t<firewall>\n");
out.write("\t\t\t<rule access=\"allow\" network=\"127.0.0.1\"/>");
out.write("\t\t</firewall>\n");
@@ -883,9 +1044,8 @@ public class ServerConfigurationTest extends QpidTestCase
writeConfigFile(mainFile, false, true, null, "test");
// Load config
- ApplicationRegistry.remove();
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ ApplicationRegistry.initialise(reg, 1);
// Test config
VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry();
@@ -916,9 +1076,8 @@ public class ServerConfigurationTest extends QpidTestCase
writeVirtualHostsFile(vhostsFile, "test");
// Load config
- ApplicationRegistry.remove();
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ ApplicationRegistry.initialise(reg, 1);
// Test config
VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry();
@@ -951,9 +1110,8 @@ public class ServerConfigurationTest extends QpidTestCase
writeConfigFile(mainFile, false, false, vhostsFile, null);
// Load config
- ApplicationRegistry.remove();
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ ApplicationRegistry.initialise(reg, 1);
// Test config
VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry();
@@ -995,10 +1153,9 @@ public class ServerConfigurationTest extends QpidTestCase
// Load config
try
- {
- ApplicationRegistry.remove();
+ {
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ ApplicationRegistry.initialise(reg, 1);
fail("Different virtualhost XML configurations not allowed");
}
catch (ConfigurationException ce)
@@ -1031,9 +1188,8 @@ public class ServerConfigurationTest extends QpidTestCase
// Load config
try
{
- ApplicationRegistry.remove();
ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile);
- ApplicationRegistry.initialise(reg);
+ ApplicationRegistry.initialise(reg, 1);
fail("Multiple virtualhost XML configurations not allowed");
}
catch (ConfigurationException ce)
@@ -1325,106 +1481,4 @@ public class ServerConfigurationTest extends QpidTestCase
fail("Should throw a ConfigurationException");
}
}
-
- /*
- * Tests that the old element security.jmx.access (that used to be used
- * to define JMX access rights) is rejected.
- */
- public void testManagementAccessRejected() throws ConfigurationException
- {
- // Check default
- _serverConfig.initialise();
-
- // Check value we set
- _config.setProperty("security.jmx.access(0)", "jmxremote.access");
- _serverConfig = new ServerConfiguration(_config);
-
- try
- {
- _serverConfig.initialise();
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : security/jmx/access is no longer a supported element within the configuration xml.",
- ce.getMessage());
- }
- }
-
- /*
- * Tests that the old element security.jmx.principal-database (that used to define the
- * principal database used for JMX authentication) is rejected.
- */
- public void testManagementPrincipalDatabaseRejected() throws ConfigurationException
- {
- // Check default
- _serverConfig.initialise();
-
- // Check value we set
- _config.setProperty("security.jmx.principal-database(0)", "mydb");
- _serverConfig = new ServerConfiguration(_config);
-
- try
- {
- _serverConfig.initialise();
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml.",
- ce.getMessage());
- }
- }
-
- /*
- * Tests that the old element security.principal-databases. ... (that used to define
- * principal databases) is rejected.
- */
- public void testPrincipalDatabasesRejected() throws ConfigurationException
- {
- _serverConfig.initialise();
-
- // Check value we set
- _config.setProperty("security.principal-databases.principal-database.class", "myclass");
- _serverConfig = new ServerConfiguration(_config);
-
- try
- {
- _serverConfig.initialise();
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : security/principal-databases is no longer supported within the configuration xml.",
- ce.getMessage());
- }
- }
-
- /*
- * Tests that the old element housekeeping.expiredMessageCheckPeriod. ... (that was
- * replaced by housekeeping.checkPeriod) is rejected.
- */
- public void testExpiredMessageCheckPeriodRejected() throws ConfigurationException
- {
- _serverConfig.initialise();
-
- // Check value we set
- _config.setProperty("housekeeping.expiredMessageCheckPeriod", 23L);
- _serverConfig = new ServerConfiguration(_config);
-
- try
- {
- _serverConfig.initialise();
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod.",
- ce.getMessage());
- }
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
index b133d53ac5..917755e8a5 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java
@@ -20,8 +20,6 @@
package org.apache.qpid.server.configuration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.queue.AMQPriorityQueue;
import org.apache.qpid.server.queue.AMQQueue;
@@ -205,50 +203,5 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase
}
- /**
- * Tests that the old element security.authentication.name is rejected. This element
- * was never supported properly as authentication is performed before the virtual host
- * is considered.
- */
- public void testSecurityAuthenticationNameRejected() throws Exception
- {
- getConfigXml().addProperty("virtualhosts.virtualhost.testSecurityAuthenticationNameRejected.security.authentication.name",
- "testdb");
-
- try
- {
- super.createBroker();
- fail("Exception not thrown");
- }
- catch(ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : security/authentication/name is no longer a supported element within the configuration xml." +
- " It appears in virtual host definition : " + getName(),
- ce.getMessage());
- }
- }
- /*
- * Tests that the old element housekeeping.expiredMessageCheckPeriod. ... (that was
- * replaced by housekeeping.checkPeriod) is rejected.
- */
- public void testExpiredMessageCheckPeriodRejected() throws Exception
- {
- getConfigXml().addProperty("virtualhosts.virtualhost.testExpiredMessageCheckPeriodRejected.housekeeping.expiredMessageCheckPeriod",
- 5);
-
- try
- {
- super.createBroker();
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- assertEquals("Incorrect error message",
- "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod." +
- " It appears in virtual host definition : " + getName(),
- ce.getMessage());
- }
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
index 3b7f5f3a51..7b58966a4c 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
@@ -52,7 +52,6 @@ import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -277,7 +276,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
static ContentHeaderBody getContentHeader(FieldTable headers)
{
ContentHeaderBody header = new ContentHeaderBody();
- header.setProperties(getProperties(headers));
+ header.properties = getProperties(headers);
return header;
}
@@ -429,11 +428,21 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
//To change body of implemented methods use File | Settings | File Templates.
}
- public boolean isRejectedBy(long subscriptionId)
+ public void reject(Subscription subscription)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isRejectedBy(Subscription subscription)
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
+ public void requeue(Subscription subscription)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void dequeue()
{
//To change body of implemented methods use File | Settings | File Templates.
@@ -473,16 +482,6 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
{
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
-
- public boolean isDequeued()
- {
- return false;
- }
-
- public boolean isDispensed()
- {
- return false;
- }
};
if(action != null)
@@ -566,8 +565,8 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase
int pos = 0;
for(ContentBody body : bodies)
{
- storedMessage.addContent(pos, ByteBuffer.wrap(body._payload));
- pos += body._payload.length;
+ storedMessage.addContent(pos, body.payload.duplicate().buf());
+ pos += body.payload.limit();
}
_incoming = new TestIncomingMessage(getMessageId(),publish, protocolsession);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
index 403a290a0f..f72961c03c 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java
@@ -396,7 +396,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase
IncomingMessage message = new IncomingMessage(info);
final ContentHeaderBody chb = new ContentHeaderBody();
BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- chb.setProperties(props);
+ chb.properties = props;
message.setContentHeaderBody(chb);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java b/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java
index e8defd0e58..3752dcb37e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java
@@ -28,7 +28,11 @@ import org.apache.qpid.server.logging.AbstractRootMessageLogger;
public class UnitTestMessageLogger extends AbstractRootMessageLogger
{
- private final List<Object> _log = new LinkedList<Object>();
+ List<Object> _log;
+
+ {
+ _log = new LinkedList<Object>();
+ }
public UnitTestMessageLogger()
{
@@ -65,14 +69,4 @@ public class UnitTestMessageLogger extends AbstractRootMessageLogger
{
_log.clear();
}
-
- public boolean messageContains(final int index, final String contains)
- {
- if (index + 1 > _log.size())
- {
- throw new IllegalArgumentException("Message with index " + index + " has not been logged");
- }
- final String message = _log.get(index).toString();
- return message.contains(contains);
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java
index d6b790db01..033ae3b4b3 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java
@@ -20,12 +20,12 @@
*/
package org.apache.qpid.server.logging.actors;
-import java.security.PrivilegedAction;
-import java.util.Collections;
-import java.util.List;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.logging.LogMessage;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.AMQException;
-import javax.management.remote.JMXPrincipal;
-import javax.security.auth.Subject;
+import java.util.List;
/**
* Test : AMQPManagementActorTest
@@ -96,40 +96,8 @@ public class ManagementActorTest extends BaseActorTestCase
// Verify that the message has the right values
assertTrue("Message contains the [mng: prefix",
- logs.get(0).toString().contains("[mng:N/A(" + IP + ")"));
- }
-
- /**
- * Tests appearance of principal name in log message
- */
- public void testSubjectPrincipalNameAppearance()
- {
- Subject subject = new Subject(true, Collections.singleton(new JMXPrincipal("guest")), Collections.EMPTY_SET,
- Collections.EMPTY_SET);
-
- final String message = Subject.doAs(subject, new PrivilegedAction<String>()
- {
- public String run()
- {
- return sendTestLogMessage(_amqpActor);
- }
- });
-
- // Verify that the log message was created
- assertNotNull("Test log message is not created!", message);
-
- List<Object> logs = _rawLogger.getLogMessages();
-
- // Verify that at least one log message was added to log
- assertEquals("Message log size not as expected.", 1, logs.size());
-
- String logMessage = logs.get(0).toString();
-
- // Verify that the logged message is present in the output
- assertTrue("Message was not found in log message", logMessage.contains(message));
+ logs.get(0).toString().contains("[mng:" + CONNECTION_ID + "(" + IP + ")"));
- // Verify that the message has the right principal value
- assertTrue("Message contains the [mng: prefix", logMessage.contains("[mng:guest(" + IP + ")"));
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java
index 4364376000..728a98e009 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java
@@ -66,6 +66,7 @@ public class ExchangeMessagesTest extends AbstractTestMessages
validateLogMessage(log, "EXH-1001", expected);
}
+
public void testExchangeDeleted()
{
_logMessage = ExchangeMessages.DELETED();
@@ -76,21 +77,4 @@ public class ExchangeMessagesTest extends AbstractTestMessages
validateLogMessage(log, "EXH-1002", expected);
}
- public void testExchangeDiscardedMessage()
- {
- // Get the Default Exchange on the Test Vhost for testing
- final Exchange exchange = ApplicationRegistry.getInstance().
- getVirtualHostRegistry().getVirtualHost("test").
- getExchangeRegistry().getDefaultExchange();
-
- final String name = exchange.getNameShortString().toString();
- final String routingKey = "routingKey";
-
- _logMessage = ExchangeMessages.DISCARDMSG(name, routingKey);
- List<Object> log = performLog();
-
- String[] expected = {"Discarded Message :","Name:", name, "Routing Key:", routingKey};
-
- validateLogMessage(log, "EXH-1003", expected);
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
index f3ee2707b0..a6c17e042e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java
@@ -21,26 +21,22 @@
package org.apache.qpid.server.management;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-
-import org.apache.commons.lang.NotImplementedException;
-import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
-/**
- *
- * Tests the AMQUserManagementMBean and its interaction with the PrincipalDatabase.
- *
+/* Note: The main purpose is to test the jmx access rights file manipulation
+ * within AMQUserManagementMBean. The Principal Databases are tested by their own tests,
+ * this test just exercises their usage in AMQUserManagementMBean.
*/
public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
{
@@ -48,6 +44,7 @@ public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
private AMQUserManagementMBean _amqumMBean;
private File _passwordFile;
+ private File _accessFile;
private static final String TEST_USERNAME = "testuser";
private static final String TEST_PASSWORD = "password";
@@ -60,6 +57,7 @@ public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
_database = new PlainPasswordFilePrincipalDatabase();
_amqumMBean = new AMQUserManagementMBean();
loadFreshTestPasswordFile();
+ loadFreshTestAccessFile();
}
@Override
@@ -67,67 +65,142 @@ public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
{
//clean up test password/access files
File _oldPasswordFile = new File(_passwordFile.getAbsolutePath() + ".old");
+ File _oldAccessFile = new File(_accessFile.getAbsolutePath() + ".old");
_oldPasswordFile.delete();
+ _oldAccessFile.delete();
_passwordFile.delete();
+ _accessFile.delete();
super.tearDown();
}
public void testDeleteUser()
{
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertTrue("Delete should return true to flag successful delete", _amqumMBean.deleteUser(TEST_USERNAME));
- assertEquals("Unexpected number of users after test", 0,_amqumMBean.viewUsers().size());
- }
-
- public void testDeleteUserWhereUserDoesNotExist()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertFalse("Delete should return false to flag unsuccessful delete", _amqumMBean.deleteUser("made.up.username"));
- assertEquals("Unexpected number of users after test", 1,_amqumMBean.viewUsers().size());
+ loadFreshTestPasswordFile();
+ loadFreshTestAccessFile();
+ //try deleting a non existant user
+ assertFalse(_amqumMBean.deleteUser("made.up.username"));
+
+ assertTrue(_amqumMBean.deleteUser(TEST_USERNAME));
}
- public void testCreateUser()
+ public void testDeleteUserIsSavedToAccessFile()
{
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertTrue("Create should return true to flag successful create", _amqumMBean.createUser("newuser", "mypass"));
- assertEquals("Unexpected number of users before test", 2,_amqumMBean.viewUsers().size());
- }
+ loadFreshTestPasswordFile();
+ loadFreshTestAccessFile();
- public void testCreateUserWhereUserAlreadyExists()
- {
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
- assertFalse("Create should return false to flag unsuccessful create", _amqumMBean.createUser(TEST_USERNAME, "mypass"));
- assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size());
+ assertTrue(_amqumMBean.deleteUser(TEST_USERNAME));
+
+ //check the access rights were actually deleted from the file
+ try{
+ BufferedReader reader = new BufferedReader(new FileReader(_accessFile));
+
+ //check the 'generated by' comment line is present
+ assertTrue("File has no content", reader.ready());
+ assertTrue("'Generated by' comment line was missing",reader.readLine().contains("Generated by " +
+ "AMQUserManagementMBean Console : Last edited by user:"));
+
+ //there should also be a modified date/time comment line
+ assertTrue("File has no modified date/time comment line", reader.ready());
+ assertTrue("Modification date/time comment line was missing",reader.readLine().startsWith("#"));
+
+ //the access file should not contain any further data now as we just deleted the only user
+ assertFalse("User access data was present when it should have been deleted", reader.ready());
+ }
+ catch (IOException e)
+ {
+ fail("Unable to valdate file contents due to:" + e.getMessage());
+ }
+
}
- public void testSetPassword()
+ public void testSetRights()
{
- assertTrue("Set password should return true to flag successful change", _amqumMBean.setPassword(TEST_USERNAME, "newpassword"));
+ loadFreshTestPasswordFile();
+ loadFreshTestAccessFile();
+
+ assertFalse(_amqumMBean.setRights("made.up.username", true, false, false));
+
+ assertTrue(_amqumMBean.setRights(TEST_USERNAME, true, false, false));
+ assertTrue(_amqumMBean.setRights(TEST_USERNAME, false, true, false));
+ assertTrue(_amqumMBean.setRights(TEST_USERNAME, false, false, true));
}
- public void testSetPasswordWhereUserDoesNotExist()
+ public void testSetRightsIsSavedToAccessFile()
{
- assertFalse("Set password should return false to flag successful change", _amqumMBean.setPassword("made.up.username", "newpassword"));
+ loadFreshTestPasswordFile();
+ loadFreshTestAccessFile();
+
+ assertTrue(_amqumMBean.setRights(TEST_USERNAME, false, false, true));
+
+ //check the access rights were actually updated in the file
+ try{
+ BufferedReader reader = new BufferedReader(new FileReader(_accessFile));
+
+ //check the 'generated by' comment line is present
+ assertTrue("File has no content", reader.ready());
+ assertTrue("'Generated by' comment line was missing",reader.readLine().contains("Generated by " +
+ "AMQUserManagementMBean Console : Last edited by user:"));
+
+ //there should also be a modified date/time comment line
+ assertTrue("File has no modified date/time comment line", reader.ready());
+ assertTrue("Modification date/time comment line was missing",reader.readLine().startsWith("#"));
+
+ //the access file should not contain any further data now as we just deleted the only user
+ assertTrue("User access data was not updated in the access file",
+ reader.readLine().equals(TEST_USERNAME + "=" + MBeanInvocationHandlerImpl.ADMIN));
+
+ //the access file should not contain any further data now as we just deleted the only user
+ assertFalse("Additional user access data was present when there should be no more", reader.ready());
+ }
+ catch (IOException e)
+ {
+ fail("Unable to valdate file contents due to:" + e.getMessage());
+ }
}
- public void testViewUsers()
+ public void testSetAccessFileWithMissingFile()
{
- TabularData userList = _amqumMBean.viewUsers();
+ try
+ {
+ _amqumMBean.setAccessFile("made.up.filename");
+ }
+ catch (IOException e)
+ {
+ fail("Should not have been an IOE." + e.getMessage());
+ }
+ catch (ConfigurationException e)
+ {
+ assertTrue(e.getMessage(), e.getMessage().endsWith("does not exist"));
+ }
+ }
- assertNotNull(userList);
- assertEquals("Unexpected number of users in user list", 1, userList.size());
- assertTrue(userList.containsKey(new Object[]{TEST_USERNAME}));
-
- // Check the deprecated read, write and admin items continue to exist but return false.
- CompositeData userRec = userList.get(new Object[]{TEST_USERNAME});
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_ONLY));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_ONLY));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_WRITE));
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_WRITE));
- assertTrue(userRec.containsKey(UserManagement.RIGHTS_ADMIN));
- assertEquals(false, userRec.get(UserManagement.RIGHTS_ADMIN));
+ public void testSetAccessFileWithReadOnlyFile()
+ {
+ File testFile = null;
+ try
+ {
+ testFile = File.createTempFile(this.getClass().getName(),".access.readonly");
+ BufferedWriter passwordWriter = new BufferedWriter(new FileWriter(testFile, false));
+ passwordWriter.write(TEST_USERNAME + ":" + TEST_PASSWORD);
+ passwordWriter.newLine();
+ passwordWriter.flush();
+ passwordWriter.close();
+
+ testFile.setReadOnly();
+ _amqumMBean.setAccessFile(testFile.getPath());
+ }
+ catch (IOException e)
+ {
+ fail("Access file was not created." + e.getMessage());
+ }
+ catch (ConfigurationException e)
+ {
+ fail("There should not have been a configuration exception." + e.getMessage());
+ }
+
+ testFile.delete();
}
// ============================ Utility methods =========================
@@ -154,4 +227,37 @@ public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase
fail("Unable to create test password file: " + e.getMessage());
}
}
+
+ private void loadFreshTestAccessFile()
+ {
+ try
+ {
+ if(_accessFile == null)
+ {
+ _accessFile = File.createTempFile(this.getClass().getName(),".access");
+ }
+
+ BufferedWriter accessWriter = new BufferedWriter(new FileWriter(_accessFile,false));
+ accessWriter.write("#Last Updated By comment");
+ accessWriter.newLine();
+ accessWriter.write("#Date/time comment");
+ accessWriter.newLine();
+ accessWriter.write(TEST_USERNAME + "=" + MBeanInvocationHandlerImpl.READONLY);
+ accessWriter.newLine();
+ accessWriter.flush();
+ accessWriter.close();
+ }
+ catch (IOException e)
+ {
+ fail("Unable to create test access file: " + e.getMessage());
+ }
+
+ try{
+ _amqumMBean.setAccessFile(_accessFile.toString());
+ }
+ catch (Exception e)
+ {
+ fail("Unable to set access file: " + e.getMessage());
+ }
+ }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/MockPluginManager.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/MockPluginManager.java
new file mode 100644
index 0000000000..a64ec5d3b1
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/plugins/MockPluginManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.qpid.server.plugins;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.exchange.ExchangeType;
+import org.apache.qpid.server.security.SecurityPluginFactory;
+
+public class MockPluginManager extends PluginManager
+{
+ private Map<String, SecurityPluginFactory> _securityPlugins = new HashMap<String, SecurityPluginFactory>();
+ private Map<List<String>, ConfigurationPluginFactory> _configPlugins = new HashMap<List<String>, ConfigurationPluginFactory>();
+
+ public MockPluginManager(String pluginPath, String cachePath) throws Exception
+ {
+ super(pluginPath, cachePath);
+ }
+
+ @Override
+ public Map<String, ExchangeType<?>> getExchanges()
+ {
+ return null;
+ }
+
+ @Override
+ public Map<String, SecurityPluginFactory> getSecurityPlugins()
+ {
+ return _securityPlugins;
+ }
+
+ @Override
+ public Map<List<String>, ConfigurationPluginFactory> getConfigurationPlugins()
+ {
+ return _configPlugins;
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java
deleted file mode 100644
index 4a03445357..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java
+++ /dev/null
@@ -1,93 +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.
- *
- */
-package org.apache.qpid.server.plugins;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.osgi.framework.Version;
-
-/**
- *
- */
-public class OsgiSystemPackageUtilTest extends QpidTestCase
-{
- private OsgiSystemPackageUtil _util = null; // Object under test
-
- private Map<String, String> _map = new TreeMap<String, String>(); // Use a TreeMap for unit test in order for determinstic results.
-
- public void testWithOnePackage() throws Exception
- {
- _map.put("org.xyz", "1.0.0");
-
- _util = new OsgiSystemPackageUtil(null, _map);
-
- final String systemPackageString = _util.getFormattedSystemPackageString();
-
- assertEquals("org.xyz; version=1.0.0", systemPackageString);
- }
-
- public void testWithTwoPackages() throws Exception
- {
- _map.put("org.xyz", "1.0.0");
- _map.put("org.abc", "1.2.3");
-
- _util = new OsgiSystemPackageUtil(null, _map);
-
- final String systemPackageString = _util.getFormattedSystemPackageString();
-
- assertEquals("org.abc; version=1.2.3, org.xyz; version=1.0.0", systemPackageString);
- }
-
- public void testWithNoPackages() throws Exception
- {
- _util = new OsgiSystemPackageUtil(null, _map);
-
- final String systemPackageString = _util.getFormattedSystemPackageString();
-
- assertNull(systemPackageString);
- }
-
- public void testWithQpidPackageWithQpidReleaseNumberSet() throws Exception
- {
- _map.put("org.apache.qpid.xyz", "1.0.0");
- _map.put("org.abc", "1.2.3");
-
- _util = new OsgiSystemPackageUtil(new Version("0.13"), _map);
-
- final String systemPackageString = _util.getFormattedSystemPackageString();
-
- assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.13.0", systemPackageString);
- }
-
- public void testWithQpidPackageWithoutQpidReleaseNumberSet() throws Exception
- {
- _map.put("org.apache.qpid.xyz", "1.0.0");
- _map.put("org.abc", "1.2.3");
-
- _util = new OsgiSystemPackageUtil(null, _map);
-
- final String systemPackageString = _util.getFormattedSystemPackageString();
-
- assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=1.0.0", systemPackageString);
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java
index 8c945aabfb..8c18ab85b0 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java
@@ -49,7 +49,7 @@ public class PluginTest extends InternalBrokerBaseCase
public void testNoExchanges() throws Exception
{
- PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp", null);
+ PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp");
Map<String, ExchangeType<?>> exchanges = manager.getExchanges();
assertTrue("Exchanges found", exchanges.isEmpty());
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
index 5a411c6807..3b6cd37ea9 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
@@ -20,16 +20,9 @@
*/
package org.apache.qpid.server.protocol;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.security.Principal;
+import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.security.auth.Subject;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
@@ -37,31 +30,35 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.message.MessageContentSource;
import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.transport.TestNetworkConnection;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.transport.TestNetworkDriver;
public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter
{
// ChannelID(LIST) -> LinkedList<Pair>
final Map<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>> _channelDelivers;
private AtomicInteger _deliveryCount = new AtomicInteger(0);
- private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
public InternalTestProtocolSession(VirtualHost virtualHost) throws AMQException
{
- super(ApplicationRegistry.getInstance().getVirtualHostRegistry(), new TestNetworkConnection(), ID_GENERATOR.getAndIncrement());
+ super(ApplicationRegistry.getInstance().getVirtualHostRegistry(), new TestNetworkDriver());
_channelDelivers = new HashMap<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>>();
// Need to authenticate session for it to be representative testing.
- setAuthorizedSubject(new Subject(true, Collections.singleton(new UsernamePrincipal("InternalTestProtocolSession")),
- Collections.EMPTY_SET, Collections.EMPTY_SET));
+ setAuthorizedID(new Principal()
+ {
+ public String getName()
+ {
+ return "InternalTestProtocolSession";
+ }
+ });
setVirtualHost(virtualHost);
}
@@ -196,7 +193,7 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr
return _closed;
}
- public void closeProtocolSession()
+ public void closeProtocolSession(boolean waitLast)
{
// Override as we don't have a real IOSession to close.
// The alternative is to fully implement the TestIOSession to return a CloseFuture from close();
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
deleted file mode 100644
index 9d76d5efca..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
+++ /dev/null
@@ -1,146 +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.
-*
-*/
-package org.apache.qpid.server.protocol;
-
-import java.nio.ByteBuffer;
-import java.util.EnumSet;
-import java.util.Set;
-
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.protocol.ServerProtocolEngine;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.transport.TestNetworkConnection;
-
-public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase
-{
- protected void setUp() throws Exception
- {
- super.setUp();
-
- //the factory needs a registry instance
- ApplicationRegistry.initialise(new TestApplicationRegistry(new ServerConfiguration(new XMLConfiguration())));
- }
-
- protected void tearDown()
- {
- //the factory opens a registry instance
- ApplicationRegistry.remove();
- }
-
- private static final byte[] AMQP_0_8_HEADER =
- new byte[] { (byte) 'A',
- (byte) 'M',
- (byte) 'Q',
- (byte) 'P',
- (byte) 1,
- (byte) 1,
- (byte) 8,
- (byte) 0
- };
-
- private static final byte[] AMQP_0_9_HEADER =
- new byte[] { (byte) 'A',
- (byte) 'M',
- (byte) 'Q',
- (byte) 'P',
- (byte) 1,
- (byte) 1,
- (byte) 0,
- (byte) 9
- };
-
- private static final byte[] AMQP_0_9_1_HEADER =
- new byte[] { (byte) 'A',
- (byte) 'M',
- (byte) 'Q',
- (byte) 'P',
- (byte) 0,
- (byte) 0,
- (byte) 9,
- (byte) 1
- };
-
-
- private static final byte[] AMQP_0_10_HEADER =
- new byte[] { (byte) 'A',
- (byte) 'M',
- (byte) 'Q',
- (byte) 'P',
- (byte) 1,
- (byte) 1,
- (byte) 0,
- (byte) 10
- };
-
- private byte[] getAmqpHeader(final AmqpProtocolVersion version)
- {
- switch(version)
- {
- case v0_8:
- return AMQP_0_8_HEADER;
- case v0_9:
- return AMQP_0_9_HEADER;
- case v0_9_1:
- return AMQP_0_9_1_HEADER;
- case v0_10:
- return AMQP_0_10_HEADER;
- default:
- fail("unknown AMQP version, appropriate header must be added for new protocol version");
- return null;
- }
- }
-
- /**
- * Test to verify that connections established using a MultiVersionProtocolEngine are assigned
- * IDs from a common sequence, independent of the protocol version under use.
- */
- public void testDifferentProtocolVersionsShareCommonIDNumberingSequence()
- {
- Set<AmqpProtocolVersion> versions = EnumSet.allOf(AmqpProtocolVersion.class);
-
- MultiVersionProtocolEngineFactory factory =
- new MultiVersionProtocolEngineFactory("localhost", versions);
-
- //create a dummy to retrieve the 'current' ID number
- long previousId = factory.newProtocolEngine(new TestNetworkConnection()).getConnectionId();
-
- //create a protocol engine and send the AMQP header for all supported AMQP verisons,
- //ensuring the ID assigned increases as expected
- for(AmqpProtocolVersion version : versions)
- {
- long expectedID = previousId + 1;
- byte[] header = getAmqpHeader(version);
- assertNotNull("protocol header should not be null", header);
-
- ServerProtocolEngine engine = factory.newProtocolEngine(new TestNetworkConnection());
- assertEquals("ID did not increment as expected", expectedID, engine.getConnectionId());
-
- //actually feed in the AMQP header for this protocol version, and ensure the ID remains consistent
- engine.received(ByteBuffer.wrap(header));
- assertEquals("ID was not as expected following receipt of the AMQP version header", expectedID, engine.getConnectionId());
-
- previousId = expectedID;
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
index 3961b3b355..d52f4c03f3 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java
@@ -96,7 +96,7 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest
AMQMessage msg = super.createMessage(id);
BasicContentHeaderProperties props = new BasicContentHeaderProperties();
props.setPriority(i);
- msg.getContentHeaderBody().setProperties(props);
+ msg.getContentHeaderBody().properties = props;
return msg;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
index 47b8b7eb18..0707cab3d5 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
@@ -276,7 +277,7 @@ public class AMQQueueAlertTest extends InternalBrokerBaseCase
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
BasicContentHeaderProperties props = new BasicContentHeaderProperties();
- contentHeaderBody.setProperties(props);
+ contentHeaderBody.properties = props;
contentHeaderBody.bodySize = size; // in bytes
IncomingMessage message = new IncomingMessage(publish);
message.setContentHeaderBody(contentHeaderBody);
@@ -288,7 +289,7 @@ public class AMQQueueAlertTest extends InternalBrokerBaseCase
protected void configure()
{
// Increase Alert Check period
- getConfiguration().setHousekeepingCheckPeriod(200);
+ getConfiguration().setHousekeepingExpiredMessageCheckPeriod(200);
}
private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException
@@ -311,14 +312,18 @@ public class AMQQueueAlertTest extends InternalBrokerBaseCase
{
messages[i].addContentBodyFrame(new ContentChunk(){
- byte[] _data = new byte[(int)size];
+ ByteBuffer _data = ByteBuffer.allocate((int)size);
+
+ {
+ _data.limit((int)size);
+ }
public int getSize()
{
return (int) size;
}
- public byte[] getData()
+ public ByteBuffer getData()
{
return _data;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
index 070d105805..5b72cfac40 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
@@ -37,6 +37,7 @@ import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.mina.common.ByteBuffer;
import javax.management.JMException;
@@ -274,14 +275,18 @@ public class AMQQueueMBeanTest extends InternalBrokerBaseCase
msg.addContentBodyFrame(new ContentChunk()
{
- byte[] _data = new byte[((int)MESSAGE_SIZE)];
+ ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE);
+
+ {
+ _data.limit((int)MESSAGE_SIZE);
+ }
public int getSize()
{
return (int) MESSAGE_SIZE;
}
- public byte[] getData()
+ public ByteBuffer getData()
{
return _data;
}
@@ -397,8 +402,8 @@ public class AMQQueueMBeanTest extends InternalBrokerBaseCase
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
contentHeaderBody.bodySize = MESSAGE_SIZE; // in bytes
- contentHeaderBody.setProperties(new BasicContentHeaderProperties());
- ((BasicContentHeaderProperties) contentHeaderBody.getProperties()).setDeliveryMode((byte) (persistent ? 2 : 1));
+ contentHeaderBody.properties = new BasicContentHeaderProperties();
+ ((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) (persistent ? 2 : 1));
IncomingMessage msg = new IncomingMessage(publish);
msg.setContentHeaderBody(contentHeaderBody);
return msg;
@@ -436,7 +441,8 @@ public class AMQQueueMBeanTest extends InternalBrokerBaseCase
getSession().getMethodRegistry()
.getProtocolVersionMethodConverter()
.convertToContentChunk(
- new ContentBody(new byte[(int) MESSAGE_SIZE])));
+ new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE),
+ MESSAGE_SIZE)));
AMQMessage m = new AMQMessage(currentMessage.getStoredMessage());
for(BaseQueue q : currentMessage.getDestinationQueues())
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
index 0f5374b3e5..04608275a3 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java
@@ -126,7 +126,7 @@ public class AckTest extends InternalBrokerBaseCase
//IncomingMessage msg2 = null;
BasicContentHeaderProperties b = new BasicContentHeaderProperties();
ContentHeaderBody cb = new ContentHeaderBody();
- cb.setProperties(b);
+ cb.properties = b;
if (persistent)
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
index 4c31092983..888a16053c 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java
@@ -29,7 +29,7 @@ import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.security.AuthorizationHolder;
+import org.apache.qpid.server.security.PrincipalHolder;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.binding.Binding;
@@ -48,7 +48,7 @@ public class MockAMQQueue implements AMQQueue
private AMQShortString _name;
private VirtualHost _virtualhost;
- private AuthorizationHolder _authorizationHolder;
+ private PrincipalHolder _principalHolder;
private AMQSessionModel _exclusiveOwner;
private AMQShortString _owner;
@@ -536,14 +536,14 @@ public class MockAMQQueue implements AMQQueue
return null; //To change body of implemented methods use File | Settings | File Templates.
}
- public AuthorizationHolder getAuthorizationHolder()
+ public PrincipalHolder getPrincipalHolder()
{
- return _authorizationHolder;
+ return _principalHolder;
}
- public void setAuthorizationHolder(final AuthorizationHolder authorizationHolder)
+ public void setPrincipalHolder(PrincipalHolder principalHolder)
{
- _authorizationHolder = authorizationHolder;
+ _principalHolder = principalHolder;
}
public AMQSessionModel getExclusiveOwningSession()
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
index ab8850c18c..5bdbe2c68e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java
@@ -139,7 +139,7 @@ public class MockQueueEntry implements QueueEntry
}
- public boolean isRejectedBy(long subscriptionId)
+ public boolean isRejectedBy(Subscription subscription)
{
return false;
@@ -153,6 +153,13 @@ public class MockQueueEntry implements QueueEntry
}
+ public void reject(Subscription subscription)
+ {
+
+
+ }
+
+
public void release()
{
@@ -224,14 +231,4 @@ public class MockQueueEntry implements QueueEntry
_message = msg;
}
- public boolean isDequeued()
- {
- return false;
- }
-
- public boolean isDispensed()
- {
- return false;
- }
-
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTest.java
deleted file mode 100644
index d8afd8d829..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTest.java
+++ /dev/null
@@ -1,247 +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.
- */
-package org.apache.qpid.server.queue;
-
-import java.lang.reflect.Field;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.message.AMQMessage;
-import org.apache.qpid.server.queue.QueueEntry.EntryState;
-import org.apache.qpid.server.subscription.MockSubscription;
-import org.apache.qpid.server.subscription.Subscription;
-
-/**
- * Tests for {@link QueueEntryImpl}
- *
- */
-public class QueueEntryImplTest extends TestCase
-{
- // tested entry
- private QueueEntryImpl _queueEntry;
-
- public void setUp() throws Exception
- {
- AMQMessage message = new MockAMQMessage(1);
- SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
- _queueEntry = new QueueEntryImpl(queueEntryList, message, 1);
- }
-
- public void testAquire()
- {
- assertTrue("Queue entry should be in AVAILABLE state before invoking of acquire method",
- _queueEntry.isAvailable());
- acquire();
- }
-
- public void testDequeue()
- {
- dequeue();
- }
-
- public void testDelete()
- {
- delete();
- }
-
- /**
- * Tests release method for entry in acquired state.
- * <p>
- * Entry in state ACQUIRED should be released and its status should be
- * changed to AVAILABLE.
- */
- public void testReleaseAquired()
- {
- acquire();
- _queueEntry.release();
- assertTrue("Queue entry should be in AVAILABLE state after invoking of release method",
- _queueEntry.isAvailable());
- }
-
- /**
- * Tests release method for entry in dequeued state.
- * <p>
- * Invoking release on dequeued entry should not have any effect on its
- * state.
- */
- public void testReleaseDequeued()
- {
- dequeue();
- _queueEntry.release();
- EntryState state = getState();
- assertEquals("Invoking of release on entry in DEQUEUED state should not have any effect",
- QueueEntry.DEQUEUED_STATE, state);
- }
-
- /**
- * Tests release method for entry in deleted state.
- * <p>
- * Invoking release on deleted entry should not have any effect on its
- * state.
- */
- public void testReleaseDeleted()
- {
- delete();
- _queueEntry.release();
- assertTrue("Invoking of release on entry in DELETED state should not have any effect",
- _queueEntry.isDeleted());
- }
-
- /**
- * Tests if entries in DEQUQUED or DELETED state are not returned by getNext method.
- */
- public void testGetNext()
- {
- int numberOfEntries = 5;
- QueueEntryImpl[] entries = new QueueEntryImpl[numberOfEntries];
- SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
-
- // create test entries
- for(int i = 0; i < numberOfEntries ; i++)
- {
- AMQMessage message = null;;
- try
- {
- message = new MockAMQMessage(i);
- }
- catch (AMQException e)
- {
- fail("Failure to create a mock message:" + e.getMessage());
- }
- QueueEntryImpl entry = (QueueEntryImpl)queueEntryList.add(message);
- entries[i] = entry;
- }
-
- // test getNext for not acquired entries
- for(int i = 0; i < numberOfEntries ; i++)
- {
- QueueEntryImpl queueEntry = entries[i];
- QueueEntryImpl next = queueEntry.getNext();
- if (i < numberOfEntries - 1)
- {
- assertEquals("Unexpected entry from QueueEntryImpl#getNext()", entries[i + 1], next);
- }
- else
- {
- assertNull("The next entry after the last should be null", next);
- }
- }
-
- // delete second
- entries[1].acquire();
- entries[1].delete();
-
- // dequeue third
- entries[2].acquire();
- entries[2].dequeue();
-
- QueueEntryImpl next = entries[0].getNext();
- assertEquals("expected forth entry",entries[3], next);
- next = next.getNext();
- assertEquals("expected fifth entry", entries[4], next);
- next = next.getNext();
- assertNull("The next entry after the last should be null", next);
- }
- /**
- * A helper method to put tested object into deleted state and assert the state
- */
- private void delete()
- {
- _queueEntry.delete();
- assertTrue("Queue entry should be in DELETED state after invoking of delete method",
- _queueEntry.isDeleted());
- }
-
- /**
- * A helper method to put tested entry into dequeue state and assert the sate
- */
- private void dequeue()
- {
- acquire();
- _queueEntry.dequeue();
- EntryState state = getState();
- assertEquals("Queue entry should be in DEQUEUED state after invoking of dequeue method",
- QueueEntry.DEQUEUED_STATE, state);
- }
-
- /**
- * A helper method to put tested entry into acquired state and assert the sate
- */
- private void acquire()
- {
- _queueEntry.acquire(new MockSubscription());
- assertTrue("Queue entry should be in ACQUIRED state after invoking of acquire method",
- _queueEntry.isAcquired());
- }
-
- /**
- * A helper method to get entry state
- *
- * @return entry state
- */
- private EntryState getState()
- {
- EntryState state = null;
- try
- {
- Field f = QueueEntryImpl.class.getDeclaredField("_state");
- f.setAccessible(true);
- state = (EntryState) f.get(_queueEntry);
- }
- catch (Exception e)
- {
- fail("Failure to get a state field: " + e.getMessage());
- }
- return state;
- }
-
- /**
- * Tests rejecting a queue entry records the Subscription ID
- * for later verification by isRejectedBy(subscriptionId).
- */
- public void testRejectAndRejectedBy()
- {
- Subscription sub = new MockSubscription();
- long subId = sub.getSubscriptionID();
-
- assertFalse("Queue entry should not yet have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
- assertFalse("Queue entry should not yet have been acquired by a subscription", _queueEntry.isAcquired());
-
- //acquire, reject, and release the message using the subscription
- assertTrue("Queue entry should have been able to be acquired", _queueEntry.acquire(sub));
- _queueEntry.reject();
- _queueEntry.release();
-
- //verify the rejection is recorded
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
-
- //repeat rejection using a second subscription
- Subscription sub2 = new MockSubscription();
- long sub2Id = sub2.getSubscriptionID();
-
- assertFalse("Queue entry should not yet have been rejected by the subscription", _queueEntry.isRejectedBy(sub2Id));
- assertTrue("Queue entry should have been able to be acquired", _queueEntry.acquire(sub2));
- _queueEntry.reject();
-
- //verify it still records being rejected by both subscriptions
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(subId));
- assertTrue("Queue entry should have been rejected by the subscription", _queueEntry.isRejectedBy(sub2Id));
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
index f4cdbbe02c..67d093d00a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -36,16 +36,13 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
-import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.BaseQueue.PostEnqueueAction;
-import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.subscription.MockSubscription;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.txn.AutoCommitTransaction;
-import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.util.InternalBrokerBaseCase;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -54,8 +51,6 @@ import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
public class SimpleAMQQueueTest extends InternalBrokerBaseCase
{
@@ -107,7 +102,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
ApplicationRegistry applicationRegistry = (ApplicationRegistry)ApplicationRegistry.getInstance();
PropertiesConfiguration env = new PropertiesConfiguration();
- _virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), new VirtualHostConfiguration(getClass().getName(), env), _store);
+ _virtualHost = new VirtualHostImpl(new VirtualHostConfiguration(getClass().getName(), env), _store);
applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost);
_queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, false, _virtualHost, _arguments);
@@ -232,10 +227,10 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
/**
- * Tests that a released queue entry is resent to the subscriber. Verifies also that the
+ * Tests that a re-queued message is resent to the subscriber. Verifies also that the
* QueueContext._releasedEntry is reset to null after the entry has been reset.
*/
- public void testReleasedMessageIsResentToSubscriber() throws Exception
+ public void testRequeuedMessageIsResentToSubscriber() throws Exception
{
_queue.registerSubscription(_subscription, false);
@@ -258,18 +253,19 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
_queue.enqueue(messageB, postEnqueueAction);
_queue.enqueue(messageC, postEnqueueAction);
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
assertEquals("Unexpected total number of messages sent to subscription", 3, _subscription.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(1).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(2).isRedelivered());
- /* Now release the first message only, causing it to be requeued */
+ /* Now requeue the first message only */
queueEntries.get(0).release();
+ _queue.requeue(queueEntries.get(0));
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
assertEquals("Unexpected total number of messages sent to subscription", 4, _subscription.getMessages().size());
assertTrue("Redelivery flag should now be set", queueEntries.get(0).isRedelivered());
@@ -279,11 +275,11 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
/**
- * Tests that a released message that becomes expired is not resent to the subscriber.
+ * Tests that a re-queued message that becomes expired is not resent to the subscriber.
* This tests ensures that SimpleAMQQueueEntry.getNextAvailableEntry avoids expired entries.
* Verifies also that the QueueContext._releasedEntry is reset to null after the entry has been reset.
*/
- public void testReleaseMessageThatBecomesExpiredIsNotRedelivered() throws Exception
+ public void testRequeuedMessageThatBecomesExpiredIsNotRedelivered() throws Exception
{
_queue.registerSubscription(_subscription, false);
@@ -305,16 +301,17 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
_queue.enqueue(messageA, postEnqueueAction);
int subFlushWaitTime = 150;
- Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner Thread
assertEquals("Unexpected total number of messages sent to subscription", 1, _subscription.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
- /* Wait a little more to be sure that message will have expired, then release the first message only, causing it to be requeued */
+ /* Wait a little more to be sure that message will have expired, then requeue it */
Thread.sleep(messageExpirationOffset - subFlushWaitTime + 10);
queueEntries.get(0).release();
+ _queue.requeue(queueEntries.get(0));
- Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(subFlushWaitTime); // Work done by SubFlushRunner Thread
assertTrue("Expecting the queue entry to be now expired", queueEntries.get(0).expired());
assertEquals("Total number of messages sent should not have changed", 1, _subscription.getMessages().size());
@@ -324,12 +321,12 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
/**
- * Tests that if a client releases entries 'out of order' (the order
+ * Tests that if a client requeues messages 'out of order' (the order
* used by QueueEntryImpl.compareTo) that messages are still resent
* successfully. Specifically this test ensures the {@see SimpleAMQQueue#requeue()}
* can correctly move the _releasedEntry to an earlier position in the QueueEntry list.
*/
- public void testReleasedOutOfComparableOrderAreRedelivered() throws Exception
+ public void testMessagesRequeuedOutOfComparableOrderAreDelivered() throws Exception
{
_queue.registerSubscription(_subscription, false);
@@ -352,19 +349,21 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
_queue.enqueue(messageB, postEnqueueAction);
_queue.enqueue(messageC, postEnqueueAction);
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
assertEquals("Unexpected total number of messages sent to subscription", 3, _subscription.getMessages().size());
assertFalse("Redelivery flag should not be set", queueEntries.get(0).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(1).isRedelivered());
assertFalse("Redelivery flag should not be set", queueEntries.get(2).isRedelivered());
- /* Now release the third and first message only, causing it to be requeued */
+ /* Now requeue the third and first message only */
queueEntries.get(2).release();
queueEntries.get(0).release();
+ _queue.requeue(queueEntries.get(2));
+ _queue.requeue(queueEntries.get(0));
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
assertEquals("Unexpected total number of messages sent to subscription", 5, _subscription.getMessages().size());
assertTrue("Redelivery flag should now be set", queueEntries.get(0).isRedelivered());
@@ -375,10 +374,10 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
/**
- * Tests that a release requeues an entry for a queue with multiple subscriptions. Verifies that a
+ * Tests a requeue for a queue with multiple subscriptions. Verifies that a
* requeue resends a message to a <i>single</i> subscriber.
*/
- public void testReleaseForQueueWithMultipleSubscriptions() throws Exception
+ public void testRequeueForQueueWithMultipleSubscriptions() throws Exception
{
MockSubscription subscription1 = new MockSubscription();
MockSubscription subscription2 = new MockSubscription();
@@ -403,16 +402,66 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
_queue.enqueue(messageA, postEnqueueAction);
_queue.enqueue(messageB, postEnqueueAction);
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
- assertEquals("Unexpected total number of messages sent to both after enqueue", 2, subscription1.getMessages().size() + subscription2.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to subscription1 after enqueue", 1, subscription1.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to subscription2 after enqueue", 1, subscription2.getMessages().size());
- /* Now release the first message only, causing it to be requeued */
- queueEntries.get(0).release();
+ /* Now requeue a message (for any subscription) */
- Thread.sleep(150); // Work done by SubFlushRunner/QueueRunner Threads
+ queueEntries.get(0).release();
+ _queue.requeue((QueueEntryImpl)queueEntries.get(0));
+
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
- assertEquals("Unexpected total number of messages sent to both subscriptions after release", 3, subscription1.getMessages().size() + subscription2.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to all subscriptions after requeue", 3, subscription1.getMessages().size() + subscription2.getMessages().size());
+ assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription1.getQueueContext())._releasedEntry);
+ assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription2.getQueueContext())._releasedEntry);
+ }
+
+ /**
+ * Tests a requeue for a queue with multiple subscriptions. Verifies that a
+ * subscriber specific requeue resends the message to <i>that</i> subscriber.
+ */
+ public void testSubscriptionSpecificRequeueForQueueWithMultipleSubscriptions() throws Exception
+ {
+ MockSubscription subscription1 = new MockSubscription();
+ MockSubscription subscription2 = new MockSubscription();
+
+ _queue.registerSubscription(subscription1, false);
+ _queue.registerSubscription(subscription2, false);
+
+ final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
+ PostEnqueueAction postEnqueueAction = new PostEnqueueAction()
+ {
+ public void onEnqueue(QueueEntry entry)
+ {
+ queueEntries.add(entry);
+ }
+ };
+
+ AMQMessage messageA = createMessage(new Long(24));
+ AMQMessage messageB = createMessage(new Long(25));
+
+ /* Enqueue two messages */
+
+ _queue.enqueue(messageA, postEnqueueAction);
+ _queue.enqueue(messageB, postEnqueueAction);
+
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
+
+ assertEquals("Unexpected total number of messages sent to subscription1 after enqueue", 1, subscription1.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to subscription2 after enqueue", 1, subscription2.getMessages().size());
+
+ /* Now requeue a message (for first subscription) */
+
+ queueEntries.get(0).release();
+ _queue.requeue((QueueEntryImpl)queueEntries.get(0), subscription1);
+
+ Thread.sleep(150); // Work done by SubFlushRunner Thread
+
+ assertEquals("Unexpected total number of messages sent to subscription1 after requeue", 2, subscription1.getMessages().size());
+ assertEquals("Unexpected total number of messages sent to subscription2 after requeue", 1, subscription2.getMessages().size());
assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription1.getQueueContext())._releasedEntry);
assertNull("releasedEntry should be cleared after requeue processed", ((QueueContext)subscription2.getQueueContext())._releasedEntry);
}
@@ -611,8 +660,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
// Create IncomingMessage and nondurable queue
final IncomingMessage msg = new IncomingMessage(info);
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
- contentHeaderBody.setProperties(new BasicContentHeaderProperties());
- ((BasicContentHeaderProperties) contentHeaderBody.getProperties()).setDeliveryMode((byte) 2);
+ contentHeaderBody.properties = new BasicContentHeaderProperties();
+ ((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) 2);
msg.setContentHeaderBody(contentHeaderBody);
final ArrayList<BaseQueue> qs = new ArrayList<BaseQueue>();
@@ -658,635 +707,6 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
}
- /**
- * processQueue() is used when asynchronously delivering messages to
- * subscriptions which could not be delivered immediately during the
- * enqueue() operation.
- *
- * A defect within the method would mean that delivery of these messages may
- * not occur should the Runner stop before all messages have been processed.
- * Such a defect was discovered when Selectors were used such that one and
- * only one subscription can/will accept any given messages, but multiple
- * subscriptions are present, and one of the earlier subscriptions receives
- * more messages than the others.
- *
- * This test is to validate that the processQueue() method is able to
- * correctly deliver all of the messages present for asynchronous delivery
- * to subscriptions in such a scenario.
- */
- public void testProcessQueueWithUniqueSelectors() throws Exception
- {
- TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory();
- SimpleAMQQueue testQueue = new SimpleAMQQueue("testQueue", false, "testOwner",false,
- false, _virtualHost, factory, null)
- {
- @Override
- public void deliverAsync(Subscription sub)
- {
- // do nothing, i.e prevent deliveries by the SubFlushRunner
- // when registering the new subscriptions
- }
- };
-
- // retrieve the QueueEntryList the queue creates and insert the test
- // messages, thus avoiding straight-through delivery attempts during
- //enqueue() process.
- QueueEntryList list = factory.getQueueEntryList();
- assertNotNull("QueueEntryList should have been created", list);
-
- QueueEntry msg1 = list.add(createMessage(1L));
- QueueEntry msg2 = list.add(createMessage(2L));
- QueueEntry msg3 = list.add(createMessage(3L));
- QueueEntry msg4 = list.add(createMessage(4L));
- QueueEntry msg5 = list.add(createMessage(5L));
-
- // Create lists of the entries each subscription should be interested
- // in.Bias over 50% of the messages to the first subscription so that
- // the later subscriptions reject them and report being done before
- // the first subscription as the processQueue method proceeds.
- List<QueueEntry> msgListSub1 = createEntriesList(msg1, msg2, msg3);
- List<QueueEntry> msgListSub2 = createEntriesList(msg4);
- List<QueueEntry> msgListSub3 = createEntriesList(msg5);
-
- MockSubscription sub1 = new MockSubscription(msgListSub1);
- MockSubscription sub2 = new MockSubscription(msgListSub2);
- MockSubscription sub3 = new MockSubscription(msgListSub3);
-
- // register the subscriptions
- testQueue.registerSubscription(sub1, false);
- testQueue.registerSubscription(sub2, false);
- testQueue.registerSubscription(sub3, false);
-
- //check that no messages have been delivered to the
- //subscriptions during registration
- assertEquals("No messages should have been delivered yet", 0, sub1.getMessages().size());
- assertEquals("No messages should have been delivered yet", 0, sub2.getMessages().size());
- assertEquals("No messages should have been delivered yet", 0, sub3.getMessages().size());
-
- // call processQueue to deliver the messages
- testQueue.processQueue(new QueueRunner(testQueue, 1)
- {
- @Override
- public void run()
- {
- // we dont actually want/need this runner to do any work
- // because we we are already doing it!
- }
- });
-
- // check expected messages delivered to correct consumers
- verifyRecievedMessages(msgListSub1, sub1.getMessages());
- verifyRecievedMessages(msgListSub2, sub2.getMessages());
- verifyRecievedMessages(msgListSub3, sub3.getMessages());
- }
-
- /**
- * Tests that dequeued message is not present in the list returned form
- * {@link SimpleAMQQueue#getMessagesOnTheQueue()}
- */
- public void testGetMessagesOnTheQueueWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // send test messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // get messages on the queue
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
-
- // assert queue entries
- assertEquals(messageNumber - 1, entries.size());
- int expectedId = 0;
- for (int i = 0; i < messageNumber - 1; i++)
- {
- Long id = ((AMQMessage) entries.get(i).getMessage()).getMessageId();
- if (i == dequeueMessageIndex)
- {
- assertFalse("Message with id " + dequeueMessageIndex
- + " was dequeued and should not be returned by method getMessagesOnTheQueue!",
- new Long(expectedId).equals(id));
- expectedId++;
- }
- assertEquals("Expected message with id " + expectedId + " but got message with id " + id,
- new Long(expectedId), id);
- expectedId++;
- }
- }
-
- /**
- * Tests that dequeued message is not present in the list returned form
- * {@link SimpleAMQQueue#getMessagesOnTheQueue(QueueEntryFilter)}
- */
- public void testGetMessagesOnTheQueueByQueueEntryFilterWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // send test messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // get messages on the queue with filter accepting all available messages
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue(new QueueEntryFilter()
- {
- public boolean accept(QueueEntry entry)
- {
- return true;
- }
-
- public boolean filterComplete()
- {
- return false;
- }
- });
-
- // assert entries on the queue
- assertEquals(messageNumber - 1, entries.size());
- int expectedId = 0;
- for (int i = 0; i < messageNumber - 1; i++)
- {
- Long id = ((AMQMessage) entries.get(i).getMessage()).getMessageId();
- if (i == dequeueMessageIndex)
- {
- assertFalse("Message with id " + dequeueMessageIndex
- + " was dequeued and should not be returned by method getMessagesOnTheQueue!",
- new Long(expectedId).equals(id));
- expectedId++;
- }
- assertEquals("Expected message with id " + expectedId + " but got message with id " + id,
- new Long(expectedId), id);
- expectedId++;
- }
- }
-
- /**
- * Tests that dequeued message is not copied as part of invocation of
- * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String, StoreContext)}
- */
- public void testCopyMessagesWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
- String anotherQueueName = "testQueue2";
-
- // put test messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // create another queue
- SimpleAMQQueue queue = createQueue(anotherQueueName);
-
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog());
-
- // copy messages into another queue
- _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
-
- // get messages on another queue
- List<QueueEntry> entries = queue.getMessagesOnTheQueue();
-
- // assert another queue entries
- assertEquals(messageNumber - 1, entries.size());
- int expectedId = 0;
- for (int i = 0; i < messageNumber - 1; i++)
- {
- Long id = ((AMQMessage)entries.get(i).getMessage()).getMessageId();
- if (i == dequeueMessageIndex)
- {
- assertFalse("Message with id " + dequeueMessageIndex
- + " was dequeued and should not been copied into another queue!",
- new Long(expectedId).equals(id));
- expectedId++;
- }
- assertEquals("Expected message with id " + expectedId + " but got message with id " + id,
- new Long(expectedId), id);
- expectedId++;
- }
- }
-
- /**
- * Tests that dequeued message is not moved as part of invocation of
- * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String, StoreContext)}
- */
- public void testMovedMessagesWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
- String anotherQueueName = "testQueue2";
-
- // put messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // create another queue
- SimpleAMQQueue queue = createQueue(anotherQueueName);
-
- // create transaction
- ServerTransaction txn = new LocalTransaction(_queue.getVirtualHost().getTransactionLog());
-
- // move messages into another queue
- _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName, txn);
-
- // commit transaction
- txn.commit();
-
- // get messages on another queue
- List<QueueEntry> entries = queue.getMessagesOnTheQueue();
-
- // assert another queue entries
- assertEquals(messageNumber - 1, entries.size());
- int expectedId = 0;
- for (int i = 0; i < messageNumber - 1; i++)
- {
- Long id = ((AMQMessage)entries.get(i).getMessage()).getMessageId();
- if (i == dequeueMessageIndex)
- {
- assertFalse("Message with id " + dequeueMessageIndex
- + " was dequeued and should not been copied into another queue!",
- new Long(expectedId).equals(id));
- expectedId++;
- }
- assertEquals("Expected message with id " + expectedId + " but got message with id " + id,
- new Long(expectedId), id);
- expectedId++;
- }
- }
-
- /**
- * Tests that messages in given range including dequeued one are deleted
- * from the queue on invocation of
- * {@link SimpleAMQQueue#removeMessagesFromQueue(long, long, StoreContext)}
- */
- public void testRemoveMessagesFromQueueWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // put messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // remove messages
- _queue.removeMessagesFromQueue(0, messageNumber);
-
- // get queue entries
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
-
- // assert queue entries
- assertNotNull("Null is returned from getMessagesOnTheQueue", entries);
- assertEquals("Queue should be empty", 0, entries.size());
- }
-
- /**
- * Tests that dequeued message on the top is not accounted and next message
- * is deleted from the queue on invocation of
- * {@link SimpleAMQQueue#deleteMessageFromTop(StoreContext)}
- */
- public void testDeleteMessageFromTopWithDequeuedEntryOnTop()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 0;
-
- // put messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message on top
- dequeueMessage(_queue, dequeueMessageIndex);
-
- //delete message from top
- _queue.deleteMessageFromTop();
-
- //get queue netries
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
-
- // assert queue entries
- assertNotNull("Null is returned from getMessagesOnTheQueue", entries);
- assertEquals("Expected " + (messageNumber - 2) + " number of messages but recieved " + entries.size(),
- messageNumber - 2, entries.size());
- assertEquals("Expected first entry with id 2", new Long(2),
- ((AMQMessage) entries.get(0).getMessage()).getMessageId());
- }
-
- /**
- * Tests that all messages including dequeued one are deleted from the queue
- * on invocation of {@link SimpleAMQQueue#clearQueue(StoreContext)}
- */
- public void testClearQueueWithDequeuedEntry()
- {
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // put messages into a test queue
- enqueueGivenNumberOfMessages(_queue, messageNumber);
-
- // dequeue message on a test queue
- dequeueMessage(_queue, dequeueMessageIndex);
-
- // clean queue
- try
- {
- _queue.clearQueue();
- }
- catch (AMQException e)
- {
- fail("Failure to clear queue:" + e.getMessage());
- }
-
- // get queue entries
- List<QueueEntry> entries = _queue.getMessagesOnTheQueue();
-
- // assert queue entries
- assertNotNull(entries);
- assertEquals(0, entries.size());
- }
-
- /**
- * Tests whether dequeued entry is sent to subscriber in result of
- * invocation of {@link SimpleAMQQueue#processQueue(QueueRunner)}
- */
- public void testProcessQueueWithDequeuedEntry()
- {
- // total number of messages to send
- int messageNumber = 4;
- int dequeueMessageIndex = 1;
-
- // create queue with overridden method deliverAsync
- SimpleAMQQueue testQueue = new SimpleAMQQueue(new AMQShortString("test"), false,
- new AMQShortString("testOwner"), false, false, _virtualHost, null)
- {
- @Override
- public void deliverAsync(Subscription sub)
- {
- // do nothing
- }
- };
-
- // put messages
- List<QueueEntry> entries = enqueueGivenNumberOfMessages(testQueue, messageNumber);
-
- // dequeue message
- dequeueMessage(testQueue, dequeueMessageIndex);
-
- // latch to wait for message receipt
- final CountDownLatch latch = new CountDownLatch(messageNumber -1);
-
- // create a subscription
- MockSubscription subscription = new MockSubscription()
- {
- /**
- * Send a message and decrement latch
- */
- public void send(QueueEntry msg) throws AMQException
- {
- super.send(msg);
- latch.countDown();
- }
- };
-
- try
- {
- // subscribe
- testQueue.registerSubscription(subscription, false);
-
- // process queue
- testQueue.processQueue(new QueueRunner(testQueue, 1)
- {
- public void run()
- {
- // do nothing
- }
- });
- }
- catch (AMQException e)
- {
- fail("Failure to process queue:" + e.getMessage());
- }
- // wait up to 1 minute for message receipt
- try
- {
- latch.await(1, TimeUnit.MINUTES);
- }
- catch (InterruptedException e1)
- {
- Thread.currentThread().interrupt();
- }
- List<QueueEntry> expected = createEntriesList(entries.get(0), entries.get(2), entries.get(3));
- verifyRecievedMessages(expected, subscription.getMessages());
- }
-
- /**
- * Tests that entry in dequeued state are not enqueued and not delivered to subscription
- */
- public void testEqueueDequeuedEntry()
- {
- // create a queue where each even entry is considered a dequeued
- SimpleAMQQueue queue = new SimpleAMQQueue(new AMQShortString("test"), false, new AMQShortString("testOwner"),
- false, false, _virtualHost, new QueueEntryListFactory()
- {
- public QueueEntryList createQueueEntryList(AMQQueue queue)
- {
- /**
- * Override SimpleQueueEntryList to create a dequeued
- * entries for messages with even id
- */
- return new SimpleQueueEntryList(queue)
- {
- /**
- * Entries with even message id are considered
- * dequeued!
- */
- protected QueueEntryImpl createQueueEntry(final ServerMessage message)
- {
- return new QueueEntryImpl(this, message)
- {
- public boolean isDequeued()
- {
- return (((AMQMessage) message).getMessageId().longValue() % 2 == 0);
- }
-
- public boolean isDispensed()
- {
- return (((AMQMessage) message).getMessageId().longValue() % 2 == 0);
- }
-
- public boolean isAvailable()
- {
- return !(((AMQMessage) message).getMessageId().longValue() % 2 == 0);
- }
- };
- }
- };
- }
- }, null);
- // create a subscription
- MockSubscription subscription = new MockSubscription();
-
- // register subscription
- try
- {
- queue.registerSubscription(subscription, false);
- }
- catch (AMQException e)
- {
- fail("Failure to register subscription:" + e.getMessage());
- }
-
- // put test messages into a queue
- putGivenNumberOfMessages(queue, 4);
-
- // assert received messages
- List<QueueEntry> messages = subscription.getMessages();
- assertEquals("Only 2 messages should be returned", 2, messages.size());
- assertEquals("ID of first message should be 1", new Long(1),
- ((AMQMessage) messages.get(0).getMessage()).getMessageId());
- assertEquals("ID of second message should be 3", new Long(3),
- ((AMQMessage) messages.get(1).getMessage()).getMessageId());
- }
-
- /**
- * A helper method to create a queue with given name
- *
- * @param name
- * queue name
- * @return queue
- */
- private SimpleAMQQueue createQueue(String name)
- {
- SimpleAMQQueue queue = null;
- try
- {
- AMQShortString queueName = new AMQShortString(name);
- AMQShortString ownerName = new AMQShortString(name + "Owner");
- queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(queueName, false, ownerName, false, false,
- _virtualHost, _arguments);
- }
- catch (AMQException e)
- {
- fail("Failure to create a queue:" + e.getMessage());
- }
- assertNotNull("Queue was not created", queue);
- return queue;
- }
-
- /**
- * A helper method to put given number of messages into queue
- * <p>
- * All messages are asserted that they are present on queue
- *
- * @param queue
- * queue to put messages into
- * @param messageNumber
- * number of messages to put into queue
- */
- private List<QueueEntry> enqueueGivenNumberOfMessages(AMQQueue queue, int messageNumber)
- {
- putGivenNumberOfMessages(queue, messageNumber);
-
- // make sure that all enqueued messages are on the queue
- List<QueueEntry> entries = queue.getMessagesOnTheQueue();
- assertEquals(messageNumber, entries.size());
- for (int i = 0; i < messageNumber; i++)
- {
- assertEquals(new Long(i), ((AMQMessage)entries.get(i).getMessage()).getMessageId());
- }
- return entries;
- }
-
- /**
- * A helper method to put given number of messages into queue
- * <p>
- * Queue is not checked if messages are added into queue
- *
- * @param queue
- * queue to put messages into
- * @param messageNumber
- * number of messages to put into queue
- * @param queue
- * @param messageNumber
- */
- private void putGivenNumberOfMessages(AMQQueue queue, int messageNumber)
- {
- for (int i = 0; i < messageNumber; i++)
- {
- // Create message
- Long messageId = new Long(i);
- AMQMessage message = null;
- try
- {
- message = createMessage(messageId);
- }
- catch (AMQException e)
- {
- fail("Failure to create a test message:" + e.getMessage());
- }
- // Put message on queue
- try
- {
- queue.enqueue(message);
- }
- catch (AMQException e)
- {
- fail("Failure to put message on queue:" + e.getMessage());
- }
- }
- }
-
- /**
- * A helper method to dequeue an entry on queue with given index
- *
- * @param queue
- * queue to dequeue message on
- * @param dequeueMessageIndex
- * entry index to dequeue.
- */
- private QueueEntry dequeueMessage(AMQQueue queue, int dequeueMessageIndex)
- {
- List<QueueEntry> entries = queue.getMessagesOnTheQueue();
- QueueEntry entry = entries.get(dequeueMessageIndex);
- entry.acquire();
- entry.dequeue();
- assertTrue(entry.isDequeued());
- return entry;
- }
-
- private List<QueueEntry> createEntriesList(QueueEntry... entries)
- {
- ArrayList<QueueEntry> entriesList = new ArrayList<QueueEntry>();
- for (QueueEntry entry : entries)
- {
- entriesList.add(entry);
- }
- return entriesList;
- }
-
- private void verifyRecievedMessages(List<QueueEntry> expected,
- List<QueueEntry> delivered)
- {
- assertEquals("Consumer did not receive the expected number of messages",
- expected.size(), delivered.size());
-
- for (QueueEntry msg : expected)
- {
- assertTrue("Consumer did not recieve msg: "
- + msg.getMessage().getMessageNumber(), delivered.contains(msg));
- }
- }
-
public class TestMessage extends AMQMessage
{
private final long _tag;
@@ -1327,20 +747,4 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase
AMQMessage messageA = new TestMessage(id, id, info);
return messageA;
}
-
- class TestSimpleQueueEntryListFactory implements QueueEntryListFactory
- {
- QueueEntryList _list;
-
- public QueueEntryList createQueueEntryList(AMQQueue queue)
- {
- _list = new SimpleQueueEntryList(queue);
- return _list;
- }
-
- public QueueEntryList getQueueEntryList()
- {
- return _list;
- }
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
index 7136f07ca5..320a75045a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java
@@ -23,7 +23,6 @@ package org.apache.qpid.server.queue;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.AMQMessage;
import junit.framework.TestCase;
@@ -156,55 +155,5 @@ public class SimpleQueueEntryListTest extends TestCase
assertEquals("Count should have been equal",count,remainingMessages.size());
}
-
- public void testDequedMessagedNotPresentInIterator()
- {
- int numberOfMessages = 10;
- SimpleQueueEntryList entryList = new SimpleQueueEntryList(new MockAMQQueue("test"));
- QueueEntry[] entries = new QueueEntry[numberOfMessages];
-
- for(int i = 0; i < numberOfMessages ; i++)
- {
- AMQMessage message = null;;
- try
- {
- message = new MockAMQMessage(i);
- }
- catch (AMQException e)
- {
- fail("Failure to create a mock message:" + e.getMessage());
- }
- QueueEntry entry = entryList.add(message);
- assertNotNull("QE should not be null", entry);
- entries[i]= entry;
- }
-
- // dequeue all even messages
- for (QueueEntry queueEntry : entries)
- {
- long i = ((AMQMessage)queueEntry.getMessage()).getMessageId().longValue();
- if (i%2 == 0)
- {
- queueEntry.acquire();
- queueEntry.dequeue();
- }
- }
-
- // iterate and check that dequeued messages are not returned by iterator
- QueueEntryIterator it = entryList.iterator();
- int counter = 0;
- int i = 1;
- while (it.advance())
- {
- QueueEntry entry = it.getNode();
- Long id = ((AMQMessage)entry.getMessage()).getMessageId();
- assertEquals("Expected message with id " + i + " but got message with id "
- + id, new Long(i), id);
- counter++;
- i += 2;
- }
- int expectedNumber = numberOfMessages / 2;
- assertEquals("Expected " + expectedNumber + " number of entries in iterator but got " + counter,
- expectedNumber, counter);
- }
+
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
deleted file mode 100644
index b10442d7db..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
+++ /dev/null
@@ -1,358 +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.
- *
- */
-package org.apache.qpid.server.security.auth.manager;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.security.Provider;
-import java.security.Security;
-
-import javax.security.auth.Subject;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
-import org.apache.commons.configuration.CompositeConfiguration;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
-import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-
-/**
- *
- * Tests the public methods of PrincipalDatabaseAuthenticationManager.
- *
- */
-public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBaseCase
-{
- private AuthenticationManager _manager = null; // Class under test
- private String TEST_USERNAME = "guest";
- private String TEST_PASSWORD = "guest";
-
- /**
- * @see org.apache.qpid.server.util.InternalBrokerBaseCase#tearDown()
- */
- @Override
- public void tearDown() throws Exception
- {
- super.tearDown();
- if (_manager != null)
- {
- _manager.close();
- }
- }
-
- /**
- * @see org.apache.qpid.server.util.InternalBrokerBaseCase#setUp()
- */
- @Override
- public void setUp() throws Exception
- {
- super.setUp();
-
- final String passwdFilename = createPasswordFile().getCanonicalPath();
- final ConfigurationPlugin config = getConfig(PlainPasswordFilePrincipalDatabase.class.getName(),
- "passwordFile", passwdFilename);
-
- _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(config);
- }
-
- /**
- * Tests where the case where the config specifies a PD implementation
- * that is not found.
- */
- public void testPrincipalDatabaseImplementationNotFound() throws Exception
- {
- try
- {
- _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig("not.Found", null, null));
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- // PASS
- }
- }
-
- /**
- * Tests where the case where the config specifies a PD implementation
- * of the wrong type.
- */
- public void testPrincipalDatabaseImplementationWrongType() throws Exception
- {
- try
- {
- _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(String.class.getName(), null, null)); // Not a PrincipalDatabase implementation
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- // PASS
- }
- }
-
- /**
- * Tests the case where a setter with the desired name cannot be found.
- */
- public void testPrincipalDatabaseSetterNotFound() throws Exception
- {
- try
- {
- _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "noMethod", "test"));
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- // PASS
- }
- }
-
- /**
- * QPID-1347. Make sure the exception message and stack trace is reasonable for an absent password file.
- */
- public void testPrincipalDatabaseThrowsSetterFileNotFound() throws Exception
- {
- try
- {
- _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "passwordFile", "/not/found"));
- fail("Exception not thrown");
- }
- catch (ConfigurationException ce)
- {
- // PASS
- assertNotNull("Expected an underlying cause", ce.getCause());
- assertEquals(FileNotFoundException.class, ce.getCause().getClass());
- }
- }
-
- /**
- * Tests that the PDAM registers SASL mechanisms correctly with the runtime.
- */
- public void testRegisteredMechanisms() throws Exception
- {
- assertNotNull(_manager.getMechanisms());
- // relies on those mechanisms attached to PropertiesPrincipalDatabaseManager
- assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms());
-
- Provider qpidProvider = Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME);
- assertNotNull(qpidProvider);
- }
-
- /**
- * Tests that the SASL factory method createSaslServer correctly
- * returns a non-null implementation.
- */
- public void testSaslMechanismCreation() throws Exception
- {
- SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost");
- assertNotNull(server);
- // Merely tests the creation of the mechanism. Mechanisms themselves are tested
- // by their own tests.
- }
-
- /**
- * Tests that the authenticate method correctly interprets an
- * authentication success.
- *
- */
- public void testSaslAuthenticationSuccess() throws Exception
- {
- SaslServer testServer = createTestSaslServer(true, false);
-
- AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
- final Subject subject = result.getSubject();
- assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest")));
- assertEquals(AuthenticationStatus.SUCCESS, result.getStatus());
- }
-
- /**
- *
- * Tests that the authenticate method correctly interprets an
- * authentication not complete.
- *
- */
- public void testSaslAuthenticationNotCompleted() throws Exception
- {
- SaslServer testServer = createTestSaslServer(false, false);
-
- AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
- assertNull(result.getSubject());
- assertEquals(AuthenticationStatus.CONTINUE, result.getStatus());
- }
-
- /**
- *
- * Tests that the authenticate method correctly interprets an
- * authentication error.
- *
- */
- public void testSaslAuthenticationError() throws Exception
- {
- SaslServer testServer = createTestSaslServer(false, true);
-
- AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes());
- assertNull(result.getSubject());
- assertEquals(AuthenticationStatus.ERROR, result.getStatus());
- }
-
- /**
- * Tests that the authenticate method correctly interprets an
- * authentication success.
- *
- */
- public void testNonSaslAuthenticationSuccess() throws Exception
- {
- AuthenticationResult result = _manager.authenticate("guest", "guest");
- final Subject subject = result.getSubject();
- assertFalse("Subject should not be set read-only", subject.isReadOnly());
- assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest")));
- assertEquals(AuthenticationStatus.SUCCESS, result.getStatus());
- }
-
- /**
- * Tests that the authenticate method correctly interprets an
- * authentication success.
- *
- */
- public void testNonSaslAuthenticationNotCompleted() throws Exception
- {
- AuthenticationResult result = _manager.authenticate("guest", "wrongpassword");
- assertNull(result.getSubject());
- assertEquals(AuthenticationStatus.CONTINUE, result.getStatus());
- }
-
- /**
- * Tests the ability to de-register the provider.
- */
- public void testClose() throws Exception
- {
- assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms());
- assertNotNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME));
-
- _manager.close();
-
- // Check provider has been removed.
- assertNull(_manager.getMechanisms());
- assertNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME));
- _manager = null;
- }
-
- /**
- * Test SASL implementation used to test the authenticate() method.
- */
- private SaslServer createTestSaslServer(final boolean complete, final boolean throwSaslException)
- {
- return new SaslServer()
- {
- public String getMechanismName()
- {
- return null;
- }
-
- public byte[] evaluateResponse(byte[] response) throws SaslException
- {
- if (throwSaslException)
- {
- throw new SaslException("Mocked exception");
- }
- return null;
- }
-
- public boolean isComplete()
- {
- return complete;
- }
-
- public String getAuthorizationID()
- {
- return complete ? "guest" : null;
- }
-
- public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
- {
- return null;
- }
-
- public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
- {
- return null;
- }
-
- public Object getNegotiatedProperty(String propName)
- {
- return null;
- }
-
- public void dispose() throws SaslException
- {
- }
- };
- }
-
- private ConfigurationPlugin getConfig(final String clazz, final String argName, final String argValue) throws Exception
- {
- final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration();
-
- XMLConfiguration xmlconfig = new XMLConfiguration();
- xmlconfig.addProperty("pd-auth-manager.principal-database.class", clazz);
-
- if (argName != null)
- {
- xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.name", argName);
- xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.value", argValue);
- }
-
- // Create a CompositeConfiguration as this is what the broker uses
- CompositeConfiguration composite = new CompositeConfiguration();
- composite.addConfiguration(xmlconfig);
- config.setConfiguration("security", xmlconfig);
- return config;
- }
-
- private File createPasswordFile() throws Exception
- {
- BufferedWriter writer = null;
- try
- {
- File testFile = File.createTempFile(this.getClass().getName(),"tmp");
- testFile.deleteOnExit();
-
- writer = new BufferedWriter(new FileWriter(testFile));
- writer.write(TEST_USERNAME + ":" + TEST_PASSWORD);
- writer.newLine();
-
- return testFile;
-
- }
- finally
- {
- if (writer != null)
- {
- writer.close();
- }
- }
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
index 6dc7b19d3d..e8c24da68d 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java
@@ -20,125 +20,188 @@
*/
package org.apache.qpid.server.security.auth.rmi;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.util.Collections;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-import junit.framework.TestCase;
+import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import junit.framework.TestCase;
-/**
- * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager.
- *
- */
public class RMIPasswordAuthenticatorTest extends TestCase
{
private final String USERNAME = "guest";
private final String PASSWORD = "guest";
+ private final String B64_MD5HASHED_PASSWORD = "CE4DQ6BIb/BVMN9scFyLtA==";
private RMIPasswordAuthenticator _rmipa;
- private String[] _credentials;
+
+ private Base64MD5PasswordFilePrincipalDatabase _md5Pd;
+ private File _md5PwdFile;
+
+ private PlainPasswordFilePrincipalDatabase _plainPd;
+ private File _plainPwdFile;
+
+ private Subject testSubject;
protected void setUp() throws Exception
{
_rmipa = new RMIPasswordAuthenticator();
- _credentials = new String[] {USERNAME, PASSWORD};
- }
-
- /**
- * Tests a successful authentication. Ensures that a populated read-only subject it returned.
- */
- public void testAuthenticationSuccess()
- {
- final Subject expectedSubject = new Subject(true,
+ _md5Pd = new Base64MD5PasswordFilePrincipalDatabase();
+ _md5PwdFile = createTempPasswordFile(this.getClass().getName()+"md5pwd", USERNAME, B64_MD5HASHED_PASSWORD);
+ _md5Pd.setPasswordFile(_md5PwdFile.getAbsolutePath());
+
+ _plainPd = new PlainPasswordFilePrincipalDatabase();
+ _plainPwdFile = createTempPasswordFile(this.getClass().getName()+"plainpwd", USERNAME, PASSWORD);
+ _plainPd.setPasswordFile(_plainPwdFile.getAbsolutePath());
+
+ testSubject = new Subject(true,
Collections.singleton(new JMXPrincipal(USERNAME)),
Collections.EMPTY_SET,
Collections.EMPTY_SET);
+ }
+
+ private File createTempPasswordFile(String filenamePrefix, String user, String password)
+ {
+ try
+ {
+ File testFile = File.createTempFile(filenamePrefix,"tmp");
+ testFile.deleteOnExit();
+
+ BufferedWriter writer = new BufferedWriter(new FileWriter(testFile));
- _rmipa.setAuthenticationManager(createTestAuthenticationManager(true, null));
+ writer.write(user + ":" + password);
+ writer.newLine();
+ writer.flush();
+ writer.close();
- Subject newSubject = _rmipa.authenticate(_credentials);
- assertTrue("Subject must be readonly", newSubject.isReadOnly());
- assertTrue("Returned subject does not equal expected value",
- newSubject.equals(expectedSubject));
+ return testFile;
+ }
+ catch (IOException e)
+ {
+ fail("Unable to create temporary test password file." + e.getMessage());
+ }
+ return null;
}
+
+
+ //********** Test Methods *********//
+
- /**
- * Tests a unsuccessful authentication.
- */
- public void testUsernameOrPasswordInvalid()
+ public void testAuthenticate()
{
- _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null));
-
+ String[] credentials;
+ Subject newSubject;
+
+ // Test when no PD has been set
try
{
- _rmipa.authenticate(_credentials);
- fail("Exception not thrown");
+ credentials = new String[]{USERNAME, PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
+ fail("SecurityException expected due to lack of principal database");
}
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
-
+ RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
}
- }
- /**
- * Tests case where authentication system itself fails.
- */
- public void testAuthenticationFailure()
- {
- final Exception mockAuthException = new Exception("Mock Auth system failure");
- _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, mockAuthException));
+ //The PrincipalDatabase's are tested primarily by their own tests, but
+ //minimal tests are done here to exercise their usage in this area.
+
+ // Test correct passwords are verified with an MD5 PD
+ try
+ {
+ _rmipa.setPrincipalDatabase(_md5Pd);
+ credentials = new String[]{USERNAME, PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
+ assertTrue("Returned subject does not equal expected value",
+ newSubject.equals(testSubject));
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected Exception:" + e.getMessage());
+ }
+ // Test incorrect passwords are not verified with an MD5 PD
try
{
- _rmipa.authenticate(_credentials);
- fail("Exception not thrown");
+ credentials = new String[]{USERNAME, PASSWORD+"incorrect"};
+ newSubject = _rmipa.authenticate(credentials);
+ fail("SecurityException expected due to incorrect password");
}
catch (SecurityException se)
{
- assertEquals("Initial cause not found", mockAuthException, se.getCause());
+ assertEquals("Unexpected exception message",
+ RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
+ }
+
+ // Test non-existent accounts are not verified with an MD5 PD
+ try
+ {
+ credentials = new String[]{USERNAME+"invalid", PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
+ fail("SecurityException expected due to non-existant account");
+ }
+ catch (SecurityException se)
+ {
+ assertEquals("Unexpected exception message",
+ RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
}
- }
+ // Test correct passwords are verified with a Plain PD
+ try
+ {
+ _rmipa.setPrincipalDatabase(_plainPd);
+ credentials = new String[]{USERNAME, PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
+ assertTrue("Returned subject does not equal expected value",
+ newSubject.equals(testSubject));
+ }
+ catch (Exception e)
+ {
+ fail("Unexpected Exception");
+ }
- /**
- * Tests case where authentication manager is not set.
- */
- public void testNullAuthenticationManager()
- {
+ // Test incorrect passwords are not verified with a Plain PD
try
{
- _rmipa.authenticate(_credentials);
- fail("SecurityException expected due to lack of authentication manager");
+ credentials = new String[]{USERNAME, PASSWORD+"incorrect"};
+ newSubject = _rmipa.authenticate(credentials);
+ fail("SecurityException expected due to incorrect password");
}
catch (SecurityException se)
{
assertEquals("Unexpected exception message",
- RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage());
+ RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
+ }
+
+ // Test non-existent accounts are not verified with an Plain PD
+ try
+ {
+ credentials = new String[]{USERNAME+"invalid", PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
+ fail("SecurityException expected due to non existant account");
+ }
+ catch (SecurityException se)
+ {
+ assertEquals("Unexpected exception message",
+ RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage());
}
- }
- /**
- * Tests case where arguments are non-Strings..
- */
- public void testWithNonStringArrayArgument()
- {
// Test handling of non-string credential's
- final Object[] objCredentials = new Object[]{USERNAME, PASSWORD};
try
{
- _rmipa.authenticate(objCredentials);
+ Object[] objCredentials = new Object[]{USERNAME, PASSWORD};
+ newSubject = _rmipa.authenticate(objCredentials);
fail("SecurityException expected due to non string[] credentials");
}
catch (SecurityException se)
@@ -146,18 +209,12 @@ public class RMIPasswordAuthenticatorTest extends TestCase
assertEquals("Unexpected exception message",
RMIPasswordAuthenticator.SHOULD_BE_STRING_ARRAY, se.getMessage());
}
- }
-
- /**
- * Tests case where there are too many, too few or null arguments.
- */
- public void testWithIllegalNumberOfArguments()
- {
- // Test handling of incorrect number of credentials
+
+ // Test handling of incorrect number of credential's
try
{
- _credentials = new String[]{USERNAME, PASSWORD, PASSWORD};
- _rmipa.authenticate(_credentials);
+ credentials = new String[]{USERNAME, PASSWORD, PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
fail("SecurityException expected due to supplying wrong number of credentials");
}
catch (SecurityException se)
@@ -166,12 +223,12 @@ public class RMIPasswordAuthenticatorTest extends TestCase
RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage());
}
- // Test handling of null credentials
+ // Test handling of null credential's
try
{
//send a null array
- _credentials = null;
- _rmipa.authenticate(_credentials);
+ credentials = null;
+ newSubject = _rmipa.authenticate(credentials);
fail("SecurityException expected due to not supplying an array of credentials");
}
catch (SecurityException se)
@@ -183,8 +240,8 @@ public class RMIPasswordAuthenticatorTest extends TestCase
try
{
//send a null password
- _credentials = new String[]{USERNAME, null};
- _rmipa.authenticate(_credentials);
+ credentials = new String[]{USERNAME, null};
+ newSubject = _rmipa.authenticate(credentials);
fail("SecurityException expected due to sending a null password");
}
catch (SecurityException se)
@@ -196,8 +253,8 @@ public class RMIPasswordAuthenticatorTest extends TestCase
try
{
//send a null username
- _credentials = new String[]{null, PASSWORD};
- _rmipa.authenticate(_credentials);
+ credentials = new String[]{null, PASSWORD};
+ newSubject = _rmipa.authenticate(credentials);
fail("SecurityException expected due to sending a null username");
}
catch (SecurityException se)
@@ -207,54 +264,4 @@ public class RMIPasswordAuthenticatorTest extends TestCase
}
}
- private AuthenticationManager createTestAuthenticationManager(final boolean successfulAuth, final Exception exception)
- {
- return new AuthenticationManager()
- {
- public void configure(ConfigurationPlugin config)
- {
- throw new UnsupportedOperationException();
- }
-
- public void initialise()
- {
- throw new UnsupportedOperationException();
- }
-
- public void close()
- {
- throw new UnsupportedOperationException();
- }
-
- public String getMechanisms()
- {
- throw new UnsupportedOperationException();
- }
-
- public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
- {
- throw new UnsupportedOperationException();
- }
-
- public AuthenticationResult authenticate(SaslServer server, byte[] response)
- {
- throw new UnsupportedOperationException();
- }
-
- public AuthenticationResult authenticate(String username, String password)
- {
- if (exception != null) {
- return new AuthenticationResult(AuthenticationStatus.ERROR, exception);
- }
- else if (successfulAuth)
- {
- return new AuthenticationResult(new Subject());
- }
- else
- {
- return new AuthenticationResult(AuthenticationStatus.CONTINUE);
- }
- }
- };
- }
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexServerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexServerTest.java
deleted file mode 100644
index 86e4e23750..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/CRAMMD5HexServerTest.java
+++ /dev/null
@@ -1,228 +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.
- *
- */
-
-package org.apache.qpid.server.security.auth.sasl;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.Principal;
-
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import javax.security.auth.login.AccountNotFoundException;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
-import junit.framework.TestCase;
-
-import org.apache.commons.codec.binary.Hex;
-import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexInitialiser;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexSaslServer;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HexServerFactory;
-
-/**
- * Test for the CRAM-MD5-HEX SASL mechanism.
- *
- * This test case focuses on testing {@link CRAMMD5HexSaslServer} but also exercises
- * collaborators {@link CRAMMD5HexInitialiser} and {@link Base64MD5PasswordFilePrincipalDatabase}
- */
-public class CRAMMD5HexServerTest extends TestCase
-{
-
- private SaslServer _saslServer; // Class under test
- private CRAMMD5HexServerFactory _saslFactory;
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
-
- CRAMMD5HexInitialiser _initializer = new CRAMMD5HexInitialiser();
-
- //Use properties to create a PrincipalDatabase
- Base64MD5PasswordFilePrincipalDatabase db = createTestPrincipalDatabase();
- assertEquals("Unexpected number of test users in the db", 2, db.getUsers().size());
-
- _initializer.initialise(db);
-
- _saslFactory = new CRAMMD5HexServerFactory();
-
- _saslServer = _saslFactory.createSaslServer(CRAMMD5HexSaslServer.MECHANISM,
- "AMQP",
- "localhost",
- _initializer.getProperties(),
- _initializer.getCallbackHandler());
- assertNotNull("Unable to create saslServer with mechanism type " + CRAMMD5HexSaslServer.MECHANISM, _saslServer);
-
- }
-
- public void testSuccessfulAuth() throws Exception
- {
-
- final byte[] serverChallenge = _saslServer.evaluateResponse(new byte[0]);
-
- // Generate client response
- final byte[] clientResponse = generateClientResponse("knownuser", "guest", serverChallenge);
-
-
- byte[] nextServerChallenge = _saslServer.evaluateResponse(clientResponse);
- assertTrue("Exchange must be flagged as complete after successful authentication", _saslServer.isComplete());
- assertNull("Next server challenge must be null after successful authentication", nextServerChallenge);
-
- }
-
- public void testKnownUserPresentsWrongPassword() throws Exception
- {
- byte[] serverChallenge = _saslServer.evaluateResponse(new byte[0]);
-
-
- final byte[] clientResponse = generateClientResponse("knownuser", "wrong!", serverChallenge);
- try
- {
- _saslServer.evaluateResponse(clientResponse);
- fail("Exception not thrown");
- }
- catch (SaslException se)
- {
- // PASS
- }
- assertFalse("Exchange must not be flagged as complete after unsuccessful authentication", _saslServer.isComplete());
- }
-
- public void testUnknownUser() throws Exception
- {
- final byte[] serverChallenge = _saslServer.evaluateResponse(new byte[0]);
-
-
- final byte[] clientResponse = generateClientResponse("unknownuser", "guest", serverChallenge);
-
- try
- {
- _saslServer.evaluateResponse(clientResponse);
- fail("Exception not thrown");
- }
- catch (SaslException se)
- {
- assertExceptionHasUnderlyingAsCause(AccountNotFoundException.class, se);
- // PASS
- }
- assertFalse("Exchange must not be flagged as complete after unsuccessful authentication", _saslServer.isComplete());
- }
-
- /**
- *
- * Demonstrates QPID-3158. A defect meant that users with some valid password were failing to
- * authenticate when using the .NET 0-8 client (uses this SASL mechanism).
- * It so happens that password "guest2" was one of the affected passwords.
- *
- * @throws Exception
- */
- public void testSuccessfulAuthReproducingQpid3158() throws Exception
- {
- byte[] serverChallenge = _saslServer.evaluateResponse(new byte[0]);
-
- // Generate client response
- byte[] resp = generateClientResponse("qpid3158user", "guest2", serverChallenge);
-
- byte[] nextServerChallenge = _saslServer.evaluateResponse(resp);
- assertTrue("Exchange must be flagged as complete after successful authentication", _saslServer.isComplete());
- assertNull("Next server challenge must be null after successful authentication", nextServerChallenge);
- }
-
- /**
- * Since we don't have a CRAM-MD5-HEX implementation client implementation in Java, this method
- * provides the implementation for first principals.
- *
- * @param userId user id
- * @param clearTextPassword clear text password
- * @param serverChallenge challenge from server
- *
- * @return challenge response
- */
- private byte[] generateClientResponse(final String userId, final String clearTextPassword, final byte[] serverChallenge) throws Exception
- {
- byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(clearTextPassword.getBytes());
- char[] hexEncodedDigestedPassword = Hex.encodeHex(digestedPasswordBytes);
- byte[] hexEncodedDigestedPasswordBytes = new String(hexEncodedDigestedPassword).getBytes();
-
-
- Mac hmacMd5 = Mac.getInstance("HmacMD5");
- hmacMd5.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, "HmacMD5"));
- final byte[] messageAuthenticationCode = hmacMd5.doFinal(serverChallenge);
-
- // Build client response
- String responseAsString = userId + " " + new String(Hex.encodeHex(messageAuthenticationCode));
- byte[] resp = responseAsString.getBytes();
- return resp;
- }
-
- /**
- * Creates a test principal database.
- *
- * @return
- * @throws IOException
- */
- private Base64MD5PasswordFilePrincipalDatabase createTestPrincipalDatabase() throws IOException
- {
- Base64MD5PasswordFilePrincipalDatabase db = new Base64MD5PasswordFilePrincipalDatabase();
- File file = File.createTempFile("passwd", "db");
- file.deleteOnExit();
- db.setPasswordFile(file.getCanonicalPath());
- db.createPrincipal( createTestPrincipal("knownuser"), "guest".toCharArray());
- db.createPrincipal( createTestPrincipal("qpid3158user"), "guest2".toCharArray());
- return db;
- }
-
- private Principal createTestPrincipal(final String name)
- {
- return new Principal()
- {
- public String getName()
- {
- return name;
- }
- };
- }
-
- private void assertExceptionHasUnderlyingAsCause(final Class<? extends Throwable> expectedUnderlying, Throwable e)
- {
- assertNotNull(e);
- int infiniteLoopGuard = 0; // Guard against loops in the cause chain
- boolean foundExpectedUnderlying = false;
- while (e.getCause() != null && infiniteLoopGuard++ < 10)
- {
- if (expectedUnderlying.equals(e.getCause().getClass()))
- {
- foundExpectedUnderlying = true;
- break;
- }
- e = e.getCause();
- }
-
- if (!foundExpectedUnderlying)
- {
- fail("Not found expected underlying exception " + expectedUnderlying + " as underlying cause of " + e.getClass());
- }
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java
deleted file mode 100644
index 076b7c9248..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java
+++ /dev/null
@@ -1,86 +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.
- *
- */
-package org.apache.qpid.server.security.auth.sasl;
-
-import junit.framework.TestCase;
-
-public class GroupPrincipalTest extends TestCase
-{
- public void testGetName()
- {
- final GroupPrincipal principal = new GroupPrincipal("group");
- assertEquals("group", principal.getName());
- }
-
- public void testAddRejected()
- {
- final GroupPrincipal principal = new GroupPrincipal("group");
- final UsernamePrincipal user = new UsernamePrincipal("name");
-
- try
- {
- principal.addMember(user);
- fail("Exception not thrown");
- }
- catch (UnsupportedOperationException uso)
- {
- // PASS
- }
- }
-
- public void testEqualitySameName()
- {
- final String string = "string";
- final GroupPrincipal principal1 = new GroupPrincipal(string);
- final GroupPrincipal principal2 = new GroupPrincipal(string);
- assertTrue(principal1.equals(principal2));
- }
-
- public void testEqualityEqualName()
- {
- final GroupPrincipal principal1 = new GroupPrincipal(new String("string"));
- final GroupPrincipal principal2 = new GroupPrincipal(new String("string"));
- assertTrue(principal1.equals(principal2));
- }
-
- public void testInequalityDifferentGroupPrincipals()
- {
- GroupPrincipal principal1 = new GroupPrincipal("string1");
- GroupPrincipal principal2 = new GroupPrincipal("string2");
- assertFalse(principal1.equals(principal2));
- }
-
- public void testInequalityNonGroupPrincipal()
- {
- GroupPrincipal principal = new GroupPrincipal("string");
- assertFalse(principal.equals(new UsernamePrincipal("string")));
- }
-
- public void testInequalityNull()
- {
- GroupPrincipal principal = new GroupPrincipal("string");
- assertFalse(principal.equals(null));
- }
-
-
-
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java
deleted file mode 100644
index 8b9b2df5a3..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java
+++ /dev/null
@@ -1,49 +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.
- *
- */
-package org.apache.qpid.server.security.auth.sasl;
-
-import java.security.Principal;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-
-public class TestPrincipalUtils
-{
-
- /**
- * Creates a test subject, with exactly one UsernamePrincipal and zero or more GroupPrincipals.
- */
- public static Subject createTestSubject(final String username, final String... groups)
- {
- final Set<Principal> principals = new HashSet<Principal>(1 + groups.length);
- principals.add(new UsernamePrincipal(username));
- for (String group : groups)
- {
- principals.add(new GroupPrincipal(group));
- }
-
- final Subject subject = new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET);
- return subject;
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
deleted file mode 100644
index 541f14d923..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java
+++ /dev/null
@@ -1,122 +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.
- *
- */
-package org.apache.qpid.server.security.auth.sasl;
-
-import java.security.Principal;
-import javax.security.auth.Subject;
-import junit.framework.TestCase;
-
-/**
- * Tests the UsernamePrincipal.
- *
- */
-public class UsernamePrincipalTest extends TestCase
-{
- public void testEqualitySameObject()
- {
- final UsernamePrincipal principal = new UsernamePrincipal("string");
- assertTrue(principal.equals(principal));
- }
-
- public void testEqualitySameName()
- {
- final String string = "string";
- final UsernamePrincipal principal1 = new UsernamePrincipal(string);
- final UsernamePrincipal principal2 = new UsernamePrincipal(string);
- assertTrue(principal1.equals(principal2));
- }
-
- public void testEqualityEqualName()
- {
- final UsernamePrincipal principal1 = new UsernamePrincipal(new String("string"));
- final UsernamePrincipal principal2 = new UsernamePrincipal(new String("string"));
- assertTrue(principal1.equals(principal2));
- }
-
- public void testInequalityDifferentUserPrincipals()
- {
- UsernamePrincipal principal1 = new UsernamePrincipal("string1");
- UsernamePrincipal principal2 = new UsernamePrincipal("string2");
- assertFalse(principal1.equals(principal2));
- }
-
- public void testInequalityNonUserPrincipal()
- {
- UsernamePrincipal principal = new UsernamePrincipal("string");
- assertFalse(principal.equals(new String("string")));
- }
-
- public void testInequalityNull()
- {
- UsernamePrincipal principal = new UsernamePrincipal("string");
- assertFalse(principal.equals(null));
- }
-
- public void testGetUsernamePrincipalFromSubject()
- {
- final UsernamePrincipal expected = new UsernamePrincipal("name");
- final Principal other = new Principal()
- {
- public String getName()
- {
- return "otherprincipal";
- }
- };
-
- final Subject subject = new Subject();
- subject.getPrincipals().add(expected);
- subject.getPrincipals().add(other);
-
- final UsernamePrincipal actual = UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
- assertSame(expected, actual);
- }
-
- public void testUsernamePrincipalNotInSubject()
- {
- try
- {
- UsernamePrincipal.getUsernamePrincipalFromSubject(new Subject());
- fail("Exception not thrown");
- }
- catch (IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
- public void testTooManyUsernamePrincipalInSubject()
- {
- final Subject subject = new Subject();
- subject.getPrincipals().add(new UsernamePrincipal("name1"));
- subject.getPrincipals().add(new UsernamePrincipal("name2"));
- try
- {
-
- UsernamePrincipal.getUsernamePrincipalFromSubject(subject);
- fail("Exception not thrown");
- }
- catch (IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java b/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java
deleted file mode 100644
index 886cb080aa..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java
+++ /dev/null
@@ -1,118 +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.
- *
- */
-package org.apache.qpid.server.signal;
-
-import java.lang.management.ManagementFactory;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class SignalHandlerTaskTest extends QpidTestCase
-{
- private static final Logger LOGGER = Logger.getLogger(SignalHandlerTaskTest.class);
- private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal";
- private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler";
-
- protected void setUp() throws Exception
- {
- super.setUp();
- }
-
- public void testSignalHandlerTask() throws Exception
- {
- final boolean expectedResult = classifyExpectedRegistrationResult();
- final int pid = getPID();
- final CountDownLatch latch = new CountDownLatch(1);
-
- SignalHandlerTask hupReparseTask = new SignalHandlerTask()
- {
- public void handle()
- {
- latch.countDown();
- LOGGER.info("Signal handled, latch decremented");
- }
- };
-
- assertEquals("Unexpected result trying to register Signal handler",
- expectedResult, hupReparseTask.register("HUP"));
- LOGGER.info("Signal handler was registered");
-
- assertEquals("unexpected count for the latch", 1, latch.getCount());
-
- if(expectedResult)
- {
- //registration succeeded as expected, so now
- //send SIGHUP and verify the handler was run
- String cmd = "/bin/kill -SIGHUP " + pid;
-
- LOGGER.info("Sending SIGHUP");
- Runtime.getRuntime().exec(cmd);
-
- assertTrue("HUP Signal was not handled in the allowed timeframe",
- latch.await(5, TimeUnit.SECONDS));
- }
- }
-
- public void testGetPlatformDescription() throws Exception
- {
- assertNotNull(SignalHandlerTask.getPlatformDescription());
- }
-
- private boolean classifyExpectedRegistrationResult()
- {
- String os = System.getProperty("os.name");
- if(String.valueOf(os).toLowerCase().contains("windows"))
- {
- //Windows does not support SIGHUP so registration will fail
- LOGGER.info("Running on windows, so we expect SIGHUP handler registration to fail");
- return false;
- }
-
- //otherwise, if the signal handler classes are present we would expect
- //registration to succeed
- boolean classesPresent = true;
- try
- {
- Class.forName(SUN_MISC_SIGNAL_CLASS);
- Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS);
- LOGGER.info("Signal handling classes were present so we expect SIGHUP handler registration to succeed");
- }
- catch (ClassNotFoundException cnfe)
- {
- classesPresent = false;
- }
-
- return classesPresent;
- }
-
- private int getPID()
- {
- String processName = ManagementFactory.getRuntimeMXBean().getName();
-
- int pid = Integer.parseInt(processName.substring(0,processName.indexOf('@')));
- LOGGER.info("PID was determined to be " + pid);
-
- return pid;
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/stats/StatisticsCounterTest.java b/java/broker/src/test/java/org/apache/qpid/server/stats/StatisticsCounterTest.java
deleted file mode 100644
index fbaa1342c9..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/stats/StatisticsCounterTest.java
+++ /dev/null
@@ -1,144 +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.
- *
- */
-package org.apache.qpid.server.stats;
-
-import junit.framework.TestCase;
-
-/**
- * Unit tests for the {@link StatisticsCounter} class.
- */
-public class StatisticsCounterTest extends TestCase
-{
- /**
- * Check that statistics counters are created correctly.
- */
- public void testCreate()
- {
- long before = System.currentTimeMillis();
- StatisticsCounter counter = new StatisticsCounter("name", 1234L);
- long after = System.currentTimeMillis();
-
- assertTrue(before <= counter.getStart());
- assertTrue(after >= counter.getStart());
- assertTrue(counter.getName().startsWith("name-"));
- assertEquals(1234L, counter.getPeriod());
- }
-
- /**
- * Check that totals add up correctly.
- */
- public void testTotal()
- {
- StatisticsCounter counter = new StatisticsCounter("test", 1000L);
- long start = counter.getStart();
- for (int i = 0; i < 100; i++)
- {
- counter.registerEvent(i, start + i);
- }
- assertEquals(99 * 50, counter.getTotal()); // cf. Gauss
- }
-
- /**
- * Test totals add up correctly even when messages are delivered
- * out-of-order.
- */
- public void testTotalOutOfOrder()
- {
- StatisticsCounter counter = new StatisticsCounter("test", 1000L);
- long start = counter.getStart();
- assertEquals(0, counter.getTotal());
- counter.registerEvent(10, start + 2500);
- assertEquals(10, counter.getTotal());
- counter.registerEvent(20, start + 1500);
- assertEquals(30, counter.getTotal());
- counter.registerEvent(10, start + 500);
- assertEquals(40, counter.getTotal());
- }
-
- /**
- * Test that the peak rate is reported correctly.
- */
- public void testPeak() throws Exception
- {
- StatisticsCounter counter = new StatisticsCounter("test", 1000L);
- long start = counter.getStart();
- assertEquals(0.0, counter.getPeak());
- Thread.sleep(500);
- counter.registerEvent(1000, start + 500);
- Thread.sleep(1000);
- assertEquals(1000.0, counter.getPeak());
- counter.registerEvent(2000, start + 1500);
- Thread.sleep(1000);
- assertEquals(2000.0, counter.getPeak());
- counter.registerEvent(1000, start + 2500);
- Thread.sleep(1000);
- assertEquals(2000.0, counter.getPeak());
- }
-
- /**
- * Test that peak rate is reported correctly for out-of-order messages,
- * and the total is also unaffected.
- */
- public void testPeakOutOfOrder() throws Exception
- {
- StatisticsCounter counter = new StatisticsCounter("test", 1000L);
- long start = counter.getStart();
- assertEquals(0.0, counter.getPeak());
- counter.registerEvent(1000, start + 2500);
- Thread.sleep(1500);
- assertEquals(0.0, counter.getPeak());
- counter.registerEvent(2000, start + 1500);
- Thread.sleep(1000L);
- assertEquals(0.0, counter.getPeak());
- counter.registerEvent(1000, start + 500);
- Thread.sleep(1500);
- assertEquals(4000.0, counter.getPeak());
- Thread.sleep(2000);
- assertEquals(4000.0, counter.getPeak());
- counter.registerEvent(1000, start + 500);
- assertEquals(4000.0, counter.getPeak());
- Thread.sleep(2000);
- counter.registerEvent(1000);
- assertEquals(4000.0, counter.getPeak());
- assertEquals(6000, counter.getTotal());
- }
-
- /**
- * Test the current rate is generated correctly.
- */
- public void testRate() throws Exception
- {
- StatisticsCounter counter = new StatisticsCounter("test", 1000L);
- assertEquals(0.0, counter.getRate());
- Thread.sleep(500);
- counter.registerEvent(1000);
- Thread.sleep(1000);
- assertEquals(1000.0, counter.getRate());
- counter.registerEvent(2000);
- Thread.sleep(1000);
- assertEquals(2000.0, counter.getRate());
- counter.registerEvent(1000);
- Thread.sleep(1000);
- assertEquals(1000.0, counter.getRate());
- Thread.sleep(1000);
- assertEquals(0.0, counter.getRate());
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
index 3acd064fd7..3ebe631f62 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -122,7 +122,6 @@ public class MessageStoreTest extends InternalBrokerBaseCase
}
catch (Exception e)
{
- e.printStackTrace();
fail(e.getMessage());
}
}
@@ -590,7 +589,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase
headerBody.classId = BasicConsumeBodyImpl.CLASS_ID;
headerBody.bodySize = 0;
- headerBody.setProperties(properties);
+ headerBody.properties = properties;
try
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
index 2d41eb9899..a75cbe8662 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java
@@ -102,7 +102,7 @@ public class ReferenceCountingTest extends QpidTestCase
ContentHeaderBody chb = new ContentHeaderBody();
BasicContentHeaderProperties bchp = new BasicContentHeaderProperties();
bchp.setDeliveryMode((byte)2);
- chb.setProperties(bchp);
+ chb.properties = bchp;
return chb;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
index 6fbc627d8c..1ec134e90e 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java
@@ -22,7 +22,6 @@ package org.apache.qpid.server.subscription;
*/
import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -46,7 +45,6 @@ public class MockSubscription implements Subscription
private State _state = State.ACTIVE;
private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>();
private final Lock _stateChangeLock = new ReentrantLock();
- private List<QueueEntry> _acceptEntries = null;
private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
@@ -56,15 +54,6 @@ public class MockSubscription implements Subscription
// Create a simple ID that increments for ever new Subscription
private final long _subscriptionID = idGenerator.getAndIncrement();
- public MockSubscription()
- {
- }
-
- public MockSubscription(List<QueueEntry> acceptEntries)
- {
- _acceptEntries = acceptEntries;
- }
-
public void close()
{
_closed = true;
@@ -130,15 +119,8 @@ public class MockSubscription implements Subscription
_stateChangeLock.lock();
}
- public boolean hasInterest(QueueEntry entry)
+ public boolean hasInterest(QueueEntry msg)
{
- if(_acceptEntries != null)
- {
- //simulate selector behaviour, only signal
- //interest in the dictated queue entries
- return _acceptEntries.contains(entry);
- }
-
return true;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java
deleted file mode 100644
index 29f45bf7f4..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java
+++ /dev/null
@@ -1,84 +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.
- *
- */
-package org.apache.qpid.server.subscription;
-
-import org.apache.qpid.common.AMQPFilterTypes;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.flow.WindowCreditManager;
-import org.apache.qpid.server.protocol.ProtocolEngine_0_10;
-import org.apache.qpid.server.transport.ServerConnection;
-import org.apache.qpid.server.transport.ServerSession;
-import org.apache.qpid.server.transport.ServerSessionDelegate;
-import org.apache.qpid.server.util.InternalBrokerBaseCase;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.MessageAcceptMode;
-import org.apache.qpid.transport.MessageAcquireMode;
-import org.apache.qpid.transport.MessageFlowMode;
-import org.apache.qpid.transport.TestNetworkConnection;
-
-public class SubscriptionFactoryImplTest extends InternalBrokerBaseCase
-{
- /**
- * Tests that while creating Subscriptions of various types, the
- * ID numbers assigned are allocated from a common sequence
- * (in increasing order).
- */
- public void testDifferingSubscriptionTypesShareCommonIdNumberingSequence() throws Exception
- {
- //create a No-Ack subscription, get the first Subscription ID
- long previousId = 0;
- Subscription noAckSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), false, null, false, getChannel().getCreditManager());
- previousId = noAckSub.getSubscriptionID();
-
- //create an ack subscription, verify the next Subscription ID is used
- Subscription ackSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), true, null, false, getChannel().getCreditManager());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, ackSub.getSubscriptionID());
- previousId = ackSub.getSubscriptionID();
-
- //create a browser subscription
- FieldTable filters = new FieldTable();
- filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true);
- Subscription browerSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), true, null, false, getChannel().getCreditManager());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, browerSub.getSubscriptionID());
- previousId = browerSub.getSubscriptionID();
-
- //create an BasicGet NoAck subscription
- Subscription getNoAckSub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(getChannel(), getSession(), new AMQShortString("1"), null, false,
- getChannel().getCreditManager(),getChannel().getClientDeliveryMethod(), getChannel().getRecordDeliveryMethod());
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, getNoAckSub.getSubscriptionID());
- previousId = getNoAckSub.getSubscriptionID();
-
- //create a 0-10 subscription
- ServerConnection conn = new ServerConnection(1);
- ProtocolEngine_0_10 engine = new ProtocolEngine_0_10(conn, new TestNetworkConnection(), getRegistry());
- conn.setVirtualHost(getVirtualHost());
- conn.setConnectionConfig(engine);
- ServerSessionDelegate sesDel = new ServerSessionDelegate();
- Binary name = new Binary(new byte[]{new Byte("1")});
- ServerSession session = new ServerSession(conn, sesDel, name, 0, engine);
-
- Subscription sub_0_10 = SubscriptionFactoryImpl.INSTANCE.createSubscription(session, "1", MessageAcceptMode.EXPLICIT,
- MessageAcquireMode.PRE_ACQUIRED, MessageFlowMode.WINDOW, new WindowCreditManager(), null, null);
- assertEquals("Unexpected Subscription ID allocated", previousId + 1, sub_0_10.getSubscriptionID());
- }
-
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java
deleted file mode 100644
index c4d1a1e614..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionListTest.java
+++ /dev/null
@@ -1,429 +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.
- *
- */
-package org.apache.qpid.server.subscription;
-
-import org.apache.qpid.server.subscription.SubscriptionList.SubscriptionNode;
-import org.apache.qpid.server.subscription.SubscriptionList.SubscriptionNodeIterator;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class SubscriptionListTest extends QpidTestCase
-{
- private SubscriptionList _subList;
- private MockSubscription _sub1;
- private MockSubscription _sub2;
- private MockSubscription _sub3;
- private SubscriptionNode _node;
-
- protected void setUp()
- {
- _subList = new SubscriptionList();
-
- _sub1 = new MockSubscription();
- _sub2 = new MockSubscription();
- _sub3 = new MockSubscription();
-
- _subList.add(_sub1);
- _subList.add(_sub2);
- _subList.add(_sub3);
-
- _node = _subList.getHead();
- }
-
- /**
- * Test that if the first (non-head) node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node, and the
- * subsequent viable node is returned instead.
- */
- public void testFindNextSkipsFirstDeletedNode()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 2nd subscription", _sub2, _node.getSubscription());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if a central node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node,
- * and the subsequent viable node is returned instead.
- */
- public void testFindNextSkipsCentralDeletedNode()
- {
- assertNotNull("Returned node should not be null", _node = _node.findNext());
-
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if the last node in the list is deleted (but is still present),
- * it is not returned when searching through the list for the next viable node,
- * and null is returned instead.
- */
- public void testFindNextSkipsLastDeletedNode()
- {
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 1st subscription", _sub1, _node.getSubscription());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 2nd subscription", _sub2, _node.getSubscription());
-
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub3).delete());
-
- assertNull("Returned node should be null", _node = _node.findNext());
- }
-
- /**
- * Test that if multiple nodes in the list are deleted (but still present), they
- * are not returned when searching through the list for the next viable node,
- * and the subsequent viable node is returned instead.
- */
- public void testFindNextSkipsMultipleDeletedNode()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
-
- assertNotNull("Returned node should not be null", _node = _node.findNext());
- assertEquals("Should have returned node for 3rd subscription", _sub3, _node.getSubscription());
- }
-
- /**
- * Test that if a node in the list is marked 'deleted' it is still present in the list
- * until actually removed. counter-test to verify above testing of getNext() method.
- */
- public void testDeletedNodeStillPresent()
- {
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
-
- assertNotNull("Node marked deleted should still be present", getNodeForSubscription(_subList, _sub1));
- assertEquals("All 3 nodes are still expected to be present", 3, countNodes(_subList));
- }
-
- /**
- * Traverses the list nodes in a non-mutating fashion, returning the first node which matches the given
- * Subscription, or null if none is found.
- */
- private SubscriptionNode getNodeForSubscription(final SubscriptionList list, final Subscription sub)
- {
- SubscriptionNode node = list.getHead();
- while (node != null && node.getSubscription() != sub)
- {
- node = node.nextNode();
- }
-
- return node;
- }
-
- /**
- * Counts the number of (non-head) nodes in the list.
- */
- private int countNodes(final SubscriptionList list)
- {
- SubscriptionNode node = list.getHead();
- int count;
- for(count = -1; node != null; count++)
- {
- node = node.nextNode();
- }
-
- return count;
- }
-
- /**
- * Tests that the head is returned as expected, and isn't the node for the first subscription.
- */
- public void testGetHead()
- {
- assertNotNull("List head should be non null", _node);
- assertNotSame("Head should not be node for first subscription",
- _node, getNodeForSubscription(_subList, _sub1));
- }
-
- /**
- * Tests that the size is returned correctly in the face of additions and removals.
- */
- public void testGetSize()
- {
- SubscriptionList subList = new SubscriptionList();
-
- assertEquals("Unexpected size result", 0, subList.size());
-
- Subscription sub1 = new MockSubscription();
- Subscription sub2 = new MockSubscription();
- Subscription sub3 = new MockSubscription();
-
- subList.add(sub1);
- assertEquals("Unexpected size result", 1, subList.size());
-
- subList.add(sub2);
- assertEquals("Unexpected size result", 2, subList.size());
-
- subList.add(sub3);
- assertEquals("Unexpected size result", 3, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub1));
- assertEquals("Unexpected size result", 2, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub2));
- assertEquals("Unexpected size result", 1, subList.size());
-
- assertTrue("Removing subscription from list should have succeeded", subList.remove(sub3));
- assertEquals("Unexpected size result", 0, subList.size());
- }
-
- /**
- * Test that if the first (non-head) node in the list is removed it is no longer
- * present in the node structure of the list at all.
- */
- public void testRemoveFirstNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub1));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- }
-
- /**
- * Test that if a central node in the list is removed it is no longer
- * present in the node structure of the list at all.
- */
- public void testRemoveCentralNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub2));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub2));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- }
-
- /**
- * Test that if the subscription contained in the last node of the list is removed
- * it is no longer present in the node structure of the list at all. However,
- * as the last node in the structure can't actually be removed a dummy will instead
- * be present.
- */
- public void testRemoveLastNode()
- {
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub3));
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
- assertNull("Should not have been a node present for the removed subscription", getNodeForSubscription(_subList, _sub3));
-
- //We actually expect 3 nodes to remain this time, because the last node cant be removed for thread safety reasons,
- //however a dummy final node can be used as substitute to allow removal of the subscription node.
- assertEquals("Unexpected number of nodes", 2 + 1, countNodes(_subList));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub1));
- assertNotNull("Should have been a node present for the subscription", getNodeForSubscription(_subList, _sub2));
- }
-
- /**
- * Test that if the subscription not contained in the list is requested to be removed
- * that the removal fails
- */
- public void testRemoveNonExistantNode()
- {
- Subscription sub4 = new MockSubscription();
- assertNull("Should not have been a node present for the subscription", getNodeForSubscription(_subList, sub4));
- assertFalse("Removing subscription node should not have succeeded", _subList.remove(sub4));
- assertEquals("Unexpected number of nodes", 3, countNodes(_subList));
- }
-
- /**
- * Test that if a subscription node which occurs later in the main list than the marked node is
- * removed from the list after the marked node is also removed, then the marker node doesn't
- * serve to retain the subsequent nodes in the list structure (and thus memory) despite their
- * removal.
- */
- public void testDeletedMarkedNodeDoesntLeakSubsequentlyDeletedNodes()
- {
- //get the nodes out the list for the 1st and 3rd subscriptions
- SubscriptionNode sub1Node = getNodeForSubscription(_subList, _sub1);
- assertNotNull("Should have been a node present for the subscription", sub1Node);
- SubscriptionNode sub3Node = getNodeForSubscription(_subList, _sub3);
- assertNotNull("Should have been a node present for the subscription", sub3Node);
-
- //mark the first subscription node
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), sub1Node));
-
- //remove the 1st subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
- //verify the 1st subscription is no longer the marker node (replaced by a dummy), or in the main list structure
- assertNotSame("Unexpected marker node", sub1Node, _subList.getMarkedNode());
- assertNull("Should not have been a node present in the list structure for the marked-but-removed sub1 node",
- getNodeForSubscription(_subList, _sub1));
-
- //remove the 2nd subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub2));
-
- //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
- //in its list structure is now the 3rd subscription (since the 2nd was removed too)
- assertEquals("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
-
- //remove the 3rd and final/tail subscription
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
-
- //verify the marker node isn't leaking subsequently removed nodes, by ensuring the very next node
- //in its list structure is now the dummy tail (since the 3rd subscription was removed, and a dummy
- //tail was inserted) and NOT the 3rd sub node.
- assertNotSame("Unexpected next node", sub3Node, _subList.getMarkedNode().nextNode());
- assertTrue("Unexpected next node", _subList.getMarkedNode().nextNode().isDeleted());
- assertNull("Next non-deleted node from the marker should now be the list end, i.e. null", _subList.getMarkedNode().findNext());
- }
-
- /**
- * Test that the marked node 'findNext' behaviour is as expected after a subscription is added
- * to the list following the tail subscription node being removed while it is the marked node.
- * That is, that the new subscriptions node is returned by getMarkedNode().findNext().
- */
- public void testMarkedNodeFindsNewSubscriptionAfterRemovingTailWhilstMarked()
- {
- //get the node out the list for the 3rd subscription
- SubscriptionNode sub3Node = getNodeForSubscription(_subList, _sub3);
- assertNotNull("Should have been a node present for the subscription", sub3Node);
-
- //mark the 3rd subscription node
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), sub3Node));
-
- //verify calling findNext on the marked node returns null, i.e. the end of the list has been reached
- assertEquals("Unexpected node after marked node", null, _subList.getMarkedNode().findNext());
-
- //remove the 3rd(marked) subscription from the list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub3));
-
- //add a new 4th subscription to the list
- Subscription sub4 = new MockSubscription();
- _subList.add(sub4);
-
- //get the node out the list for the 4th subscription
- SubscriptionNode sub4Node = getNodeForSubscription(_subList, sub4);
- assertNotNull("Should have been a node present for the subscription", sub4Node);
-
- //verify the marked node (which is now a dummy substitute for the 3rd subscription) returns
- //the 4th subscriptions node as the next non-deleted node.
- assertEquals("Unexpected next node", sub4Node, _subList.getMarkedNode().findNext());
- }
-
- /**
- * Test that setting the marked node to null doesn't cause problems during remove operations
- */
- public void testRemoveWithNullMarkedNode()
- {
- //set the marker to null
- assertTrue("should have succeeded in updating the marked node",
- _subList.updateMarkedNode(_subList.getMarkedNode(), null));
-
- //remove the 1st subscription from the main list
- assertTrue("Removing subscription node should have succeeded", _subList.remove(_sub1));
-
- //verify the 1st subscription is no longer in the main list structure
- assertNull("Should not have been a node present in the main list structure for sub1",
- getNodeForSubscription(_subList, _sub1));
- assertEquals("Unexpected number of nodes", 2, countNodes(_subList));
- }
-
- /**
- * Tests that after the first (non-head) node of the list is marked deleted but has not
- * yet been removed, the iterator still skips it.
- */
- public void testIteratorSkipsFirstDeletedNode()
- {
- //'delete' but dont remove the node for the 1st subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub1).delete());
- assertNotNull("Should still have been a node present for the deleted subscription",
- getNodeForSubscription(_subList, _sub1));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 2nd subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub2, iter.getNode().getSubscription());
-
- //verify the iterator returns the 3rd subscriptions node and not the 2nd.
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub3, iter.getNode().getSubscription());
- }
-
- /**
- * Tests that after a central node of the list is marked deleted but has not yet been removed,
- * the iterator still skips it.
- */
- public void testIteratorSkipsCentralDeletedNode()
- {
- //'delete' but dont remove the node for the 2nd subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub2).delete());
- assertNotNull("Should still have been a node present for the deleted subscription",
- getNodeForSubscription(_subList, _sub2));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 1st subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub1, iter.getNode().getSubscription());
-
- //verify the iterator returns the 3rd subscriptions node and not the 2nd.
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub3, iter.getNode().getSubscription());
- }
-
- /**
- * Tests that after the last node of the list is marked deleted but has not yet been removed,
- * the iterator still skips it.
- */
- public void testIteratorSkipsDeletedFinalNode()
- {
- //'delete' but dont remove the node for the 3rd subscription
- assertTrue("Deleting subscription node should have succeeded",
- getNodeForSubscription(_subList, _sub3).delete());
- assertNotNull("Should still have been a node present for the deleted 3rd subscription",
- getNodeForSubscription(_subList, _sub3));
-
- SubscriptionNodeIterator iter = _subList.iterator();
-
- //verify the iterator returns the 1st subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub1, iter.getNode().getSubscription());
-
- //verify the iterator returns the 2nd subscriptions node
- assertTrue("Iterator should have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", _sub2, iter.getNode().getSubscription());
-
- //verify the iterator can no longer advance and does not return a subscription node
- assertFalse("Iterator should not have been able to advance", iter.advance());
- assertEquals("Iterator returned unexpected SubscriptionNode", null, iter.getNode());
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockAction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockAction.java
index 15c135ea2c..975e3e91b9 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockAction.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockAction.java
@@ -32,11 +32,13 @@ class MockAction implements Action
private boolean _rollbackFired = false;
private boolean _postCommitFired = false;
+ @Override
public void postCommit()
{
_postCommitFired = true;
}
+ @Override
public void onRollback()
{
_rollbackFired = true;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java
index 422105e410..64c62fd029 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java
@@ -46,56 +46,67 @@ class MockServerMessage implements ServerMessage
this.persistent = persistent;
}
+ @Override
public boolean isPersistent()
{
return persistent;
}
+ @Override
public MessageReference newReference()
{
throw new NotImplementedException();
}
+ @Override
public boolean isImmediate()
{
throw new NotImplementedException();
}
+ @Override
public long getSize()
{
throw new NotImplementedException();
}
+ @Override
public SessionConfig getSessionConfig()
{
throw new NotImplementedException();
}
+ @Override
public String getRoutingKey()
{
throw new NotImplementedException();
}
+ @Override
public AMQMessageHeader getMessageHeader()
{
throw new NotImplementedException();
}
+ @Override
public long getExpiration()
{
throw new NotImplementedException();
}
+ @Override
public int getContent(ByteBuffer buf, int offset)
{
throw new NotImplementedException();
}
+ @Override
public long getArrivalTime()
{
throw new NotImplementedException();
}
+ @Override
public Long getMessageNumber()
{
return 0L;
diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
index ff372532ac..5700bba9f8 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
@@ -61,6 +61,7 @@ class MockStoreTransaction implements Transaction
return _state;
}
+ @Override
public void enqueueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException
{
if (_throwExceptionOnQueueOp)
@@ -82,6 +83,8 @@ class MockStoreTransaction implements Transaction
return _numberOfEnqueuedMessages;
}
+
+ @Override
public void dequeueMessage(TransactionLogResource queue, Long messageId) throws AMQStoreException
{
if (_throwExceptionOnQueueOp)
@@ -92,16 +95,19 @@ class MockStoreTransaction implements Transaction
_numberOfDequeuedMessages++;
}
+ @Override
public void commitTran() throws AMQStoreException
{
_state = TransactionState.COMMITTED;
}
+ @Override
public StoreFuture commitTranAsync() throws AMQStoreException
{
throw new NotImplementedException();
}
+ @Override
public void abortTran() throws AMQStoreException
{
_state = TransactionState.ABORTED;
@@ -111,11 +117,14 @@ class MockStoreTransaction implements Transaction
{
return new TransactionLog()
{
+
+ @Override
public void configureTransactionLog(String name, TransactionLogRecoveryHandler recoveryHandler,
Configuration storeConfiguration, LogSubject logSubject) throws Exception
{
}
-
+
+ @Override
public Transaction newTransaction()
{
storeTransaction.setState(TransactionState.STARTED);
diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
index a97134a58d..925b161118 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
@@ -44,13 +44,14 @@ import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.util.MockChannel;
public class InternalBrokerBaseCase extends QpidTestCase
{
private IApplicationRegistry _registry;
private MessageStore _messageStore;
- private AMQChannel _channel;
+ private MockChannel _channel;
private InternalTestProtocolSession _session;
private VirtualHost _virtualHost;
private AMQQueue _queue;
@@ -110,7 +111,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
_session = new InternalTestProtocolSession(_virtualHost);
CurrentActor.set(_session.getLogActor());
- _channel = new AMQChannel(_session, 1, _messageStore);
+ _channel = new MockChannel(_session, 1, _messageStore);
_session.addChannel(_channel);
}
@@ -242,7 +243,7 @@ public class InternalBrokerBaseCase extends QpidTestCase
//Make Message Persistent
properties.setDeliveryMode((byte) 2);
- _headerBody.setProperties(properties);
+ _headerBody.properties = properties;
channel.publishContentHeader(_headerBody);
}
@@ -282,12 +283,12 @@ public class InternalBrokerBaseCase extends QpidTestCase
_messageStore = messageStore;
}
- public AMQChannel getChannel()
+ public MockChannel getChannel()
{
return _channel;
}
- public void setChannel(AMQChannel channel)
+ public void setChannel(MockChannel channel)
{
_channel = channel;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
index 3c6857e8a9..af8997cf40 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
@@ -20,72 +20,27 @@
*/
package org.apache.qpid.server.util;
-import java.util.Properties;
-
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.logging.NullRootMessageLogger;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager;
+
+import java.util.Properties;
+
public class TestApplicationRegistry extends ApplicationRegistry
{
-
public TestApplicationRegistry(ServerConfiguration config) throws ConfigurationException
{
super(config);
}
- @Override
- public void initialise() throws Exception
- {
- CurrentActor.setDefault(new BrokerActor(new NullRootMessageLogger()));
- GenericActor.setDefaultMessageLogger(new NullRootMessageLogger());
- super.initialise();
- }
-
- /**
- * @see org.apache.qpid.server.registry.ApplicationRegistry#createAuthenticationManager()
- */
- @Override
- protected AuthenticationManager createAuthenticationManager() throws ConfigurationException
+ protected void createDatabaseManager(ServerConfiguration configuration) throws Exception
{
- final Properties users = new Properties();
+ Properties users = new Properties();
users.put("guest","guest");
users.put("admin","admin");
-
- final PropertiesPrincipalDatabase ppd = new PropertiesPrincipalDatabase(users);
-
- AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager()
- {
-
- /**
- * @see org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin)
- */
- @Override
- public void configure(ConfigurationPlugin config) throws ConfigurationException
- {
- // We don't pass configuration to this test instance.
- }
-
- @Override
- public void initialise()
- {
- setPrincipalDatabase(ppd);
-
- super.initialise();
- }
- };
-
- pdam.initialise();
-
- return pdam;
+ _databaseManager = new PropertiesPrincipalDatabaseManager("testPasswordFile", users);
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java
deleted file mode 100644
index 98bf381712..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java
+++ /dev/null
@@ -1,67 +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.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.util.concurrent.CountDownLatch;
-
-import org.apache.qpid.server.logging.LogActor;
-import org.apache.qpid.server.logging.NullRootMessageLogger;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.TestLogActor;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class HouseKeepingTaskTest extends QpidTestCase
-{
- /**
- * Tests that the abstract HouseKeepingTask properly cleans up any LogActor
- * it adds to the CurrentActor stack by verifying the CurrentActor set
- * before task execution is the CurrentActor after execution.
- */
- public void testCurrentActorStackBalance() throws Exception
- {
- //create and set a test actor
- LogActor testActor = new TestLogActor(new NullRootMessageLogger());
- CurrentActor.set(testActor);
-
- //verify it is returned correctly before executing a HouseKeepingTask
- assertEquals("Expected LogActor was not returned", testActor, CurrentActor.get());
-
- final CountDownLatch latch = new CountDownLatch(1);
- HouseKeepingTask testTask = new HouseKeepingTask(new MockVirtualHost("HouseKeepingTaskTestVhost"))
- {
- @Override
- public void execute()
- {
- latch.countDown();
- }
- };
-
- //run the test HouseKeepingTask using the current Thread to influence its CurrentActor stack
- testTask.run();
-
- assertEquals("The expected LogActor was not returned, the CurrentActor stack has become unbalanced",
- testActor, CurrentActor.get());
- assertEquals("HouseKeepingTask execute() method was not run", 0, latch.getCount());
-
- //clean up the test actor
- CurrentActor.remove();
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
deleted file mode 100644
index 7aa314bf22..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java
+++ /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.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.util.UUID;
-
-import org.apache.qpid.server.binding.BindingFactory;
-import org.apache.qpid.server.configuration.BrokerConfig;
-import org.apache.qpid.server.configuration.ConfigStore;
-import org.apache.qpid.server.configuration.ConfiguredObject;
-import org.apache.qpid.server.configuration.VirtualHostConfig;
-import org.apache.qpid.server.configuration.VirtualHostConfigType;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.connection.IConnectionRegistry;
-import org.apache.qpid.server.exchange.ExchangeFactory;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.federation.BrokerLink;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.stats.StatisticsCounter;
-import org.apache.qpid.server.store.DurableConfigurationStore;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TransactionLog;
-
-public class MockVirtualHost implements VirtualHost
-{
- private String _name;
-
- public MockVirtualHost(String name)
- {
- _name = name;
- }
-
- public void close()
- {
-
- }
-
- public void createBrokerConnection(String transport, String host, int port,
- String vhost, boolean durable, String authMechanism,
- String username, String password)
- {
-
- }
-
- public IApplicationRegistry getApplicationRegistry()
- {
- return null;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return null;
- }
-
- public BindingFactory getBindingFactory()
- {
- return null;
- }
-
- public UUID getBrokerId()
- {
- return null;
- }
-
- public ConfigStore getConfigStore()
- {
- return null;
- }
-
- public VirtualHostConfiguration getConfiguration()
- {
- return null;
- }
-
- public IConnectionRegistry getConnectionRegistry()
- {
- return null;
- }
-
- public DurableConfigurationStore getDurableConfigurationStore()
- {
- return null;
- }
-
- public ExchangeFactory getExchangeFactory()
- {
- return null;
- }
-
- public ExchangeRegistry getExchangeRegistry()
- {
- return null;
- }
-
- public int getHouseKeepingActiveCount()
- {
- return 0;
- }
-
- public long getHouseKeepingCompletedTaskCount()
- {
- return 0;
- }
-
- public int getHouseKeepingPoolSize()
- {
- return 0;
- }
-
- public long getHouseKeepingTaskCount()
- {
- return 0;
- }
-
- public ManagedObject getManagedObject()
- {
- return null;
- }
-
- public MessageStore getMessageStore()
- {
- return null;
- }
-
- public String getName()
- {
- return _name;
- }
-
- public QueueRegistry getQueueRegistry()
- {
- return null;
- }
-
- public SecurityManager getSecurityManager()
- {
- return null;
- }
-
- public TransactionLog getTransactionLog()
- {
- return null;
- }
-
- public void removeBrokerConnection(BrokerLink brokerLink)
- {
-
- }
-
- public void scheduleHouseKeepingTask(long period, HouseKeepingTask task)
- {
-
- }
-
- public void setHouseKeepingPoolSize(int newSize)
- {
-
- }
-
- public BrokerConfig getBroker()
- {
- return null;
- }
-
- public String getFederationTag()
- {
- return null;
- }
-
- public void setBroker(BrokerConfig brokerConfig)
- {
-
- }
-
- public VirtualHostConfigType getConfigType()
- {
- return null;
- }
-
- public long getCreateTime()
- {
- return 0;
- }
-
- public UUID getId()
- {
- return null;
- }
-
- public ConfiguredObject<VirtualHostConfigType, VirtualHostConfig> getParent()
- {
- return null;
- }
-
- public boolean isDurable()
- {
- return false;
- }
-
- public StatisticsCounter getDataDeliveryStatistics()
- {
- return null;
- }
-
- public StatisticsCounter getDataReceiptStatistics()
- {
- return null;
- }
-
- public StatisticsCounter getMessageDeliveryStatistics()
- {
- return null;
- }
-
- public StatisticsCounter getMessageReceiptStatistics()
- {
- return null;
- }
-
- public void initialiseStatistics()
- {
-
- }
-
- public boolean isStatisticsEnabled()
- {
- return false;
- }
-
- public void registerMessageDelivered(long messageSize)
- {
-
- }
-
- public void registerMessageReceived(long messageSize, long timestamp)
- {
-
- }
-
- public void resetStatistics()
- {
-
- }
-
- public void setStatisticsEnabled(boolean enabled)
- {
-
- }
-} \ No newline at end of file
diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
deleted file mode 100644
index c87e5a1648..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java
+++ /dev/null
@@ -1,214 +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.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
-import org.apache.qpid.server.util.TestApplicationRegistry;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class VirtualHostImplTest extends QpidTestCase
-{
- private ServerConfiguration _configuration;
- private ApplicationRegistry _registry;
-
- @Override
- public void tearDown() throws Exception
- {
- super.tearDown();
-
- ApplicationRegistry.remove();
- }
-
- /**
- * Tests that custom routing keys for the queue specified in the configuration
- * file are correctly bound to the exchange (in addition to the queue name)
- */
- public void testSpecifyingCustomBindings() throws Exception
- {
- customBindingTestImpl(new String[]{"custom1","custom2"});
- }
-
- /**
- * Tests that a queue specified in the configuration file to be bound to a
- * specified(non-default) direct exchange is a correctly bound to the exchange
- * and the default exchange using the queue name.
- */
- public void testQueueSpecifiedInConfigurationIsBoundToDefaultExchange() throws Exception
- {
- customBindingTestImpl(new String[0]);
- }
-
- private void customBindingTestImpl(final String[] routingKeys) throws Exception
- {
- String exchangeName = getName() +".direct";
- String vhostName = getName();
- String queueName = getName();
-
- File config = writeConfigFile(vhostName, queueName, exchangeName, false, routingKeys);
- VirtualHost vhost = createVirtualHost(vhostName, config);
- assertNotNull("virtualhost should exist", vhost);
-
- AMQQueue queue = vhost.getQueueRegistry().getQueue(queueName);
- assertNotNull("queue should exist", queue);
-
- Exchange defaultExch = vhost.getExchangeRegistry().getDefaultExchange();
- assertTrue("queue should have been bound to default exchange with its name", defaultExch.isBound(queueName, queue));
-
- Exchange exch = vhost.getExchangeRegistry().getExchange(exchangeName);
- assertTrue("queue should have been bound to " + exchangeName + " with its name", exch.isBound(queueName, queue));
-
- for(String key: routingKeys)
- {
- assertTrue("queue should have been bound to " + exchangeName + " with key " + key, exch.isBound(key, queue));
- }
- }
-
- /**
- * Tests that specifying custom routing keys for a queue in the configuration file results in failure
- * to create the vhost (since this is illegal, only queue names are used with the default exchange)
- */
- public void testSpecifyingCustomBindingForDefaultExchangeThrowsException() throws Exception
- {
- File config = writeConfigFile(getName(), getName(), null, false, new String[]{"custom-binding"});
-
- try
- {
- createVirtualHost(getName(), config);
- fail("virtualhost creation should have failed due to illegal configuration");
- }
- catch (ConfigurationException e)
- {
- //expected
- }
- }
-
- /**
- * Tests that specifying an unknown exchange to bind the queue to results in failure to create the vhost
- */
- public void testSpecifyingUnknownExchangeThrowsException() throws Exception
- {
- File config = writeConfigFile(getName(), getName(), "made-up-exchange", true, new String[0]);
-
- try
- {
- createVirtualHost(getName(), config);
- fail("virtualhost creation should have failed due to illegal configuration");
- }
- catch (ConfigurationException e)
- {
- //expected
- }
- }
-
- private VirtualHost createVirtualHost(String vhostName, File config) throws Exception
- {
- _configuration = new ServerConfiguration(new XMLConfiguration(config));
-
- _registry = new TestApplicationRegistry(_configuration);
- ApplicationRegistry.initialise(_registry);
-
- return _registry.getVirtualHostRegistry().getVirtualHost(vhostName);
- }
-
- /**
- * Create a configuration file for testing virtualhost creation
- *
- * @param vhostName name of the virtualhost
- * @param queueName name of the queue
- * @param exchangeName name of a direct exchange to declare (unless dontDeclare = true) and bind the queue to (null = none)
- * @param dontDeclare if true then dont declare the exchange, even if its name is non-null
- * @param routingKeys routingKeys to bind the queue with (empty array = none)
- * @return
- */
- private File writeConfigFile(String vhostName, String queueName, String exchangeName, boolean dontDeclare, String[] routingKeys)
- {
- File tmpFile = null;
- try
- {
- tmpFile = File.createTempFile(getName(), ".tmp");
- tmpFile.deleteOnExit();
-
- FileWriter fstream = new FileWriter(tmpFile);
- BufferedWriter writer = new BufferedWriter(fstream);
-
- //extra outer tag to please Commons Configuration
- writer.write("<configuration>");
-
- writer.write("<virtualhosts>");
- writer.write(" <default>" + vhostName + "</default>");
- writer.write(" <virtualhost>");
- writer.write(" <store>");
- writer.write(" <class>" + TestableMemoryMessageStore.class.getName() + "</class>");
- writer.write(" </store>");
- writer.write(" <name>" + vhostName + "</name>");
- writer.write(" <" + vhostName + ">");
- if(exchangeName != null && !dontDeclare)
- {
- writer.write(" <exchanges>");
- writer.write(" <exchange>");
- writer.write(" <type>direct</type>");
- writer.write(" <name>" + exchangeName + "</name>");
- writer.write(" </exchange>");
- writer.write(" </exchanges>");
- }
- writer.write(" <queues>");
- writer.write(" <queue>");
- writer.write(" <name>" + queueName + "</name>");
- writer.write(" <" + queueName + ">");
- if(exchangeName != null)
- {
- writer.write(" <exchange>" + exchangeName + "</exchange>");
- }
- for(String routingKey: routingKeys)
- {
- writer.write(" <routingKey>" + routingKey + "</routingKey>");
- }
- writer.write(" </" + queueName + ">");
- writer.write(" </queue>");
- writer.write(" </queues>");
- writer.write(" </" + vhostName + ">");
- writer.write(" </virtualhost>");
- writer.write("</virtualhosts>");
-
- writer.write("</configuration>");
-
- writer.flush();
- writer.close();
- }
- catch (IOException e)
- {
- fail("Unable to create virtualhost configuration");
- }
-
- return tmpFile;
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java b/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java
new file mode 100644
index 0000000000..9bd1e7c5e1
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/util/MockChannel.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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 org.apache.qpid.util;
+
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+
+public class MockChannel extends AMQChannel
+{
+ public MockChannel(AMQProtocolSession session, int channelId, MessageStore messageStore)
+ throws AMQException
+ {
+ super(session, channelId, messageStore);
+ }
+
+
+
+}
diff --git a/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java b/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
index a39799a6b6..902b86f80b 100644
--- a/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
+++ b/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java
@@ -481,7 +481,7 @@ public class GenerateLogMessages
// Only check the text inside the braces '{}'
int typeIndexEnd = parametersString[index].indexOf("}", typeIndex);
String typeString = parametersString[index].substring(typeIndex, typeIndexEnd);
- if (typeString.contains("number") || typeString.contains("choice"))
+ if (typeString.contains("number"))
{
type = "Number";
}
diff --git a/java/build.deps b/java/build.deps
index d0691275ff..aebd381bbc 100644
--- a/java/build.deps
+++ b/java/build.deps
@@ -17,6 +17,8 @@
# under the License.
#
+backport-util-concurrent=lib/backport-util-concurrent-2.2.jar
+
commons-beanutils-core=lib/commons-beanutils-core-1.8.0.jar
commons-cli=lib/commons-cli-1.0.jar
commons-codec=lib/commons-codec-1.3.jar
@@ -25,40 +27,88 @@ commons-configuration=lib/commons-configuration-1.6.jar
commons-digester=lib/commons-digester-1.8.1.jar
commons-lang=lib/commons-lang-2.2.jar
commons-logging=lib/commons-logging-1.0.4.jar
+commons-pool=lib/commons-pool-1.4.jar
derby-db=lib/derby-10.6.1.0.jar
geronimo-jms=lib/geronimo-jms_1.1_spec-1.0.jar
junit=lib/junit-3.8.1.jar
+junit4=lib/junit-4.4.jar
+
+jline=lib/jline-0.9.94.jar
log4j=lib/log4j-1.2.12.jar
+mina-core=lib/mina-core-1.0.1.jar
+mina-filter-ssl=lib/mina-filter-ssl-1.0.1.jar
+
slf4j-api=lib/slf4j-api-1.6.1.jar
slf4j-log4j=lib/slf4j-log4j12-1.6.1.jar
xalan=lib/xalan-2.7.0.jar
+muse-core=lib/muse-core-2.2.0.jar
+muse-platform-mini=lib/muse-platform-mini-2.2.0.jar
+muse-util=lib/muse-util-2.2.0.jar
+muse-util-qname=lib/muse-util-qname-2.2.0.jar
+muse-util-xml=lib/muse-util-xml-2.2.0.jar
+muse-wsa-soap=lib/muse-wsa-soap-2.2.0.jar
+muse-wsdm-muws-adv-api=lib/muse-wsdm-muws-adv-api-2.2.0.jar
+muse-wsdm-muws-adv-impl=lib/muse-wsdm-muws-adv-impl-2.2.0.jar
+muse-wsdm-muws-api=lib/muse-wsdm-muws-api-2.2.0.jar
+muse-wsdm-muws-impl=lib/muse-wsdm-muws-impl-2.2.0.jar
+muse-wsdm-wef-api=lib/muse-wsdm-wef-api-2.2.0.jar
+muse-wsdm-wef-impl=lib/muse-wsdm-wef-impl-2.2.0.jar
+muse-wsn-api=lib/muse-wsn-api-2.2.0.jar
+muse-wsn-impl=lib/muse-wsn-impl-2.2.0.jar
+muse-wsrf-api=lib/muse-wsrf-api-2.2.0.jar
+muse-wsrf-impl=lib/muse-wsrf-impl-2.2.0.jar
+muse-wsrf-rmd=lib/muse-wsrf-rmd-2.2.0.jar
+muse-wsx-api=lib/muse-wsx-api-2.2.0.jar
+muse-wsx-impl=lib/muse-wsx-impl-2.2.0.jar
+wsdl4j=lib/wsdl4j-1.6.1.jar
+xercesImpl=lib/xercesImpl-2.8.1.jar
+xml-apis=lib/xml-apis-1.3.03.jar
+javassist=lib/javassist.jar
jetty=lib/jetty-6.1.14.jar
jetty-util=lib/jetty-util-6.1.14.jar
jetty-servlet-tester=lib/jetty-servlet-tester-6.1.14.jar
+jetty-bootstrap=lib/start.jar
+jsp-api=lib/jsp-api-2.1.jar
+jsp-impl=lib/jsp-2.1.jar
+core-lib=lib/core-3.1.1.jar
servlet-api=lib/servlet-api.jar
+muse.libs = ${muse-core} ${muse-platform-mini} ${muse-util} ${muse-util-qname} \
+${muse-util-xml} ${muse-wsa-soap} ${muse-wsdm-muws-adv-api} ${muse-wsdm-muws-adv-impl} \
+${muse-wsdm-muws-api} ${muse-wsdm-muws-impl} ${muse-wsdm-wef-api} ${muse-wsdm-wef-impl} \
+${muse-wsn-api} ${muse-wsn-impl} ${muse-wsrf-api} ${muse-wsrf-impl} ${muse-wsrf-rmd} \
+${muse-wsx-api} ${muse-wsx-impl} ${wsdl4j} ${xercesImpl} ${xml-apis} ${jetty} ${jetty-util} ${jetty-bootstrap}
+
+jsp.libs = ${jsp-api} ${jsp-impl} ${core-lib}
+
osgi-core=lib/org.osgi.core-1.0.0.jar
felix-framework=lib/org.apache.felix.framework-2.0.5.jar
+geronimo-servlet=lib/geronimo-servlet_2.5_spec-1.2.jar
felix.libs=${osgi-core} ${felix-framework}
commons-configuration.libs = ${commons-beanutils-core} ${commons-digester} \
${commons-codec} ${commons-lang} ${commons-collections} ${commons-configuration}
-common.libs=${slf4j-api}
+common.libs=${slf4j-api} ${backport-util-concurrent} ${mina-core} ${mina-filter-ssl}
client.libs=${geronimo-jms}
tools.libs=${commons-configuration.libs} ${log4j}
broker.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \
${xalan} ${felix.libs} ${derby-db} ${commons-configuration.libs}
-broker-plugins.libs=${felix.libs} ${log4j} ${commons-configuration.libs}
+broker-plugins.libs=${felix.libs} ${log4j} ${commons-configuration.libs}
+management-client.libs=${jsp.libs} ${log4j} ${slf4j-log4j} ${slf4j-api} \
+ ${commons-pool} ${geronimo-servlet} ${muse.libs} ${javassist} ${xalan}
+
+management-agent.libs=${commons-logging}
+management-console.libs=${commons-logging}
junit-toolkit.libs=${log4j} ${junit} ${slf4j-api}
test.libs=${slf4j-log4j} ${junit-toolkit.libs}
@@ -100,28 +150,34 @@ ecl-equinox-launcher-solaris-gtk-sparc=lib/org.eclipse.equinox.launcher.gtk.sola
management-common.libs=
-management-eclipse-plugin.core-libs=${ibm-icu} ${ecl-core-jface} ${ecl-core-jface-databinding} \
- ${ecl-core-commands} ${ecl-core-contenttype} ${ecl-core-databinding} ${ecl-core-expressions} \
- ${ecl-core-jobs} ${ecl-core-runtime} ${ecl-equinox-app} ${ecl-equinox-common} ${ecl-equinox-launcher} \
- ${ecl-equinox-prefs} ${ecl-equinox-registry} ${ecl-help} ${ecl-osgi} ${ecl-swt} ${ecl-ui} ${ecl-ui-forms} \
- ${ecl-ui-workbench} ${apache-commons-codec}
-
-management-eclipse-plugin.swt-libs=${ecl-swt-win32-win32-x86} ${ecl-swt-linux-gtk-x86} ${ecl-swt-macosx-carbon} \
- ${ecl-swt-linux-gtk-x86_64} ${ecl-swt-solaris-gtk-sparc}
-
-management-eclipse-plugin.libs=${management-eclipse-plugin.core-libs} ${management-eclipse-plugin.swt-libs}
-
management-eclipse-plugin-win32-win32-x86.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-win32-win32-x86} ${ecl-equinox-launcher-win32-win32-x86} ${ecl-core-runtime-compat-registry}
+ ${ecl-swt-win32-win32-x86} ${ecl-equinox-launcher-win32-win32-x86}
management-eclipse-plugin-linux-gtk-x86.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-linux-gtk-x86} ${ecl-equinox-launcher-linux-gtk-x86} ${ecl-core-runtime-compat-registry}
+ ${ecl-swt-linux-gtk-x86} ${ecl-equinox-launcher-linux-gtk-x86}
management-eclipse-plugin-linux-gtk-x86_64.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-linux-gtk-x86_64} ${ecl-equinox-launcher-linux-gtk-x86_64} ${ecl-core-runtime-compat-registry}
+ ${ecl-swt-linux-gtk-x86_64} ${ecl-equinox-launcher-linux-gtk-x86_64}
management-eclipse-plugin-macosx.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-macosx-carbon} ${ecl-equinox-launcher-macosx-carbon} ${ecl-core-runtime-compat-registry}
+ ${ecl-swt-macosx-carbon} ${ecl-equinox-launcher-macosx-carbon}
management-eclipse-plugin-solaris-gtk-sparc.libs=${management-eclipse-plugin.core-libs} \
- ${ecl-swt-solaris-gtk-sparc} ${ecl-equinox-launcher-solaris-gtk-sparc} ${ecl-core-runtime-compat-registry}
+ ${ecl-swt-solaris-gtk-sparc} ${ecl-equinox-launcher-solaris-gtk-sparc}
+
+management-eclipse-plugin.core-libs=${ibm-icu} ${ecl-core-jface} ${ecl-core-jface-databinding} \
+ ${ecl-core-commands} ${ecl-core-contenttype} ${ecl-core-databinding} ${ecl-core-expressions} \
+ ${ecl-core-jobs} ${ecl-core-runtime} ${ecl-core-runtime-compat-registry} ${ecl-equinox-app} \
+ ${ecl-equinox-common} ${ecl-equinox-launcher} ${ecl-equinox-prefs} ${ecl-equinox-registry} \
+ ${ecl-help} ${ecl-osgi} ${ecl-swt} ${ecl-ui} ${ecl-ui-forms} ${ecl-ui-workbench} ${apache-commons-codec}
+management-eclipse-plugin.platform-libs=${ecl-equinox-launcher-win32-win32-x86} \
+ ${ecl-equinox-launcher-linux-gtk-x86} ${ecl-equinox-launcher-macosx-carbon} \
+ ${ecl-swt-win32-win32-x86} ${ecl-swt-linux-gtk-x86} ${ecl-swt-macosx-carbon} \
+ ${ecl-swt-linux-gtk-x86_64} ${ecl-equinox-launcher-linux-gtk-x86_64} \
+ ${ecl-swt-solaris-gtk-sparc} ${ecl-equinox-launcher-solaris-gtk-sparc}
+
+management-eclipse-plugin.libs=${management-eclipse-plugin.core-libs} ${management-eclipse-plugin.platform-libs}
+
+
+management-tools-qpid-cli.libs=${jline} ${commons-configuration.libs}
+
common.test.libs=${test.libs}
broker.test.libs=${test.libs}
client.test.libs=${test.libs}
@@ -133,10 +189,9 @@ systests.libs=${test.libs}
broker-plugins.test.libs=${test.libs}
broker-plugins-experimental-info.test.libs=${test.libs} ${servlet-api} ${jetty} ${jetty-util} ${jetty-servlet-tester}
-management-eclipse-plugin.test.libs=${test.libs}
+management-client.test.libs=${muse.libs} ${test.libs} ${log4j} ${javassist} ${geronimo-servlet} ${commons-pool}
+management-console.test.libs=${junit4} ${slf4j-log4j} ${log4j}
+management-agent.test.libs=${junit}
+management-eclipse-plugin.test.libs=${systests.libs}
+management-tools-qpid-cli.test.libs=${junit4} ${slf4j-log4j} ${log4j}
management-common.test.libs=${test.libs}
-
-# optional bdbstore module deps
-bdb-je=lib/bdbstore/je-4.0.103.jar
-bdbstore.libs=${bdb-je}
-bdbstore.test.libs=${test.libs}
diff --git a/java/build.overrides b/java/build.overrides
deleted file mode 100644
index dbe05b4ec0..0000000000
--- a/java/build.overrides
+++ /dev/null
@@ -1,24 +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.
-#
-
-# File to allow overriding default values of properties within the build system
-# without having to specify them on the command line on every build execution
-
-# Override the setting for the optional modules to be built
-#modules.opt=bdbstore
diff --git a/java/build.xml b/java/build.xml
index 1118822b14..9031166d76 100644
--- a/java/build.xml
+++ b/java/build.xml
@@ -22,20 +22,18 @@
<import file="common.xml"/>
- <property file="${project.root}/build.overrides"/>
<findSubProjects name="broker-plugins" dir="broker-plugins"/>
- <findSubProjects name="client-plugins" dir="client-plugins"/>
- <findSubProjects name="management" dir="management" excludes="common,example"/>
+ <findSubProjects name="management" dir="management" excludes="common,example,tools/qpid-cli"/>
<property name="modules.core" value="junit-toolkit common management/common broker client tools"/>
<property name="modules.examples" value="client/example management/example"/>
<property name="modules.tests" value="systests perftests integrationtests testkit"/>
<property name="modules.management" value="${management}"/>
- <property name="modules.plugin" value="${broker-plugins} ${client-plugins}"/>
- <property name="modules.opt" value=""/>
+ <property name="modules.plugin" value="${broker-plugins}"/>
+ <property name="modules.management.tools" value="management/tools/qpid-cli"/>
<property name="modules" value="${modules.core} ${modules.examples}
- ${modules.management} ${modules.tests} ${modules.plugin} ${modules.opt}"/>
+ ${modules.management} ${modules.management.tools} ${modules.tests} ${modules.plugin}"/>
<property name="qpid.jar" location="${build.lib}/qpid-all.jar"/>
<basename property="qpid.jar.name" file="${qpid.jar}"/>
@@ -80,7 +78,7 @@
<iterate target="compile-tests"/>
</target>
- <target name="test" description="execute tests" depends="manifest">
+ <target name="test" description="execute tests">
<delete file="${build.failed}"/>
@@ -95,10 +93,6 @@
<fail if="failed" message="TEST SUITE FAILED"/>
</target>
-
- <target name="report-module" description="generate junitreport for modules">
- <iterate target="report-module"/>
- </target>
<target name="jar" description="create module jars">
<iterate target="jar"/>
@@ -219,18 +213,7 @@
<include name="**/*.ser"/>
</fileset>
</cobertura-merge>
- <cobertura-report format="xml"
- destdir="${build.coveragereport}"
- datafile="${build.coveragereport}/cobertura.ser"
- >
- <fileset dir="${project.root}/common/src/main/java" includes="**/*.java" />
- <fileset dir="${project.root}/build/scratch/common/src" includes="**/*.java" />
- <fileset dir="${project.root}/broker/src/main/java" includes="**/*.java" />
- <fileset dir="${project.root}/build/scratch/broker/src" includes="**/*.java" />
- <fileset dir="${project.root}/client/src/main/java" includes="**/*.java" />
- <fileset dir="${project.root}/build/scratch/client/src" includes="**/*.java" />
- </cobertura-report>
- <cobertura-report format="html"
+ <cobertura-report format="html"
destdir="${build.coveragereport}"
datafile="${build.coveragereport}/cobertura.ser"
>
@@ -294,7 +277,4 @@
</findbugs>
</target>
- <target name="eclipse" description="build eclipse project and classpath files">
- <iterate target="eclipse"/>
- </target>
</project>
diff --git a/java/client-plugins/.gitignore b/java/client-plugins/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/java/client-plugins/.gitignore
+++ /dev/null
diff --git a/java/client-plugins/README.txt b/java/client-plugins/README.txt
deleted file mode 100644
index 64884f27a2..0000000000
--- a/java/client-plugins/README.txt
+++ /dev/null
@@ -1,21 +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.
-#
-
-Placeholder directory to allow for the building of client side optional modules such as transports or custom SASL modules etc. Analogous to
-broker-plugins.
diff --git a/java/client/README.txt b/java/client/README.txt
index b9cde71db3..57a98cc978 100644
--- a/java/client/README.txt
+++ b/java/client/README.txt
@@ -24,7 +24,7 @@ run more easily.
E.g, in order to run the Hello example, you would add the client+example library
files to the java classpath and launch the example like follows:
-java -cp "lib/qpid-all.jar:example/lib/qpid-client-example-<version>.jar" \
+java -cp "lib/qpid-all.jar:example/lib/qpid-client-examples-<version>.jar" \
org.apache.qpid.example.Hello
NOTE: The client uses the SL4FJ API for its logging. You must supply a logging
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/pubsub/ConnectionSetup.java b/java/client/example/src/main/java/org/apache/qpid/example/pubsub/ConnectionSetup.java
index 0734704e59..c4edd9034f 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/pubsub/ConnectionSetup.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/pubsub/ConnectionSetup.java
@@ -33,6 +33,7 @@ import java.util.Properties;
* It is equivalent to a PropertyFile of value:
*
* connectionfactory.local=amqp://guest:guest@clientid/test?brokerlist='localhost'
+ * connectionfactory.vm=amqp://guest:guest@clientid/test?brokerlist='vm://:1'
*
* queue.queue=example.MyQueue
* topic.topic=example.hierarical.topic
@@ -49,7 +50,7 @@ public class ConnectionSetup
final static String QUEUE_NAME = "example.MyQueue";
public static final String TOPIC_JNDI_NAME = "topic";
- final static String TOPIC_NAME = "usa.news";
+ final static String TOPIC_NAME = "example.hierarical.topic";
private Context _ctx;
@@ -60,6 +61,7 @@ public class ConnectionSetup
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
properties.put("connectionfactory." + CONNECTION_JNDI_NAME, CONNECTION_NAME);
+ properties.put("connectionfactory." + "vm", "amqp://guest:guest@clientid/test?brokerlist='vm://:1'");
properties.put("queue." + QUEUE_JNDI_NAME, QUEUE_NAME);
properties.put("topic." + TOPIC_JNDI_NAME, TOPIC_NAME);
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/pubsub/Publisher.java b/java/client/example/src/main/java/org/apache/qpid/example/pubsub/Publisher.java
index ac3829d49e..dd936e429f 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/pubsub/Publisher.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/pubsub/Publisher.java
@@ -71,7 +71,7 @@ public class Publisher extends Client
public static void main(String[] args)
{
- String destination = args.length > 2 ? args[1] : "usa.news";
+ String destination = args.length > 2 ? args[1] : null;
int msgCount = args.length > 2 ? Integer.parseInt(args[2]) : 100;
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/transport/ExistingSocketConnectorDemo.java b/java/client/example/src/main/java/org/apache/qpid/example/transport/ExistingSocketConnectorDemo.java
new file mode 100644
index 0000000000..d7eb138523
--- /dev/null
+++ b/java/client/example/src/main/java/org/apache/qpid/example/transport/ExistingSocketConnectorDemo.java
@@ -0,0 +1,171 @@
+/*
+ *
+ * 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 org.apache.qpid.example.transport;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.nio.channels.SocketChannel;
+import java.util.UUID;
+
+/**
+ * This is a simple application that demonstrates how you can use the Qpid AMQP interfaces to use existing sockets as
+ * the transport for the Client API.
+ *
+ * The Demo here runs twice:
+ * 1. Just to show a simple publish and receive.
+ * 2. To demonstrate how to use existing sockets and utilise the underlying client failover mechnaism.
+ */
+public class ExistingSocketConnectorDemo implements ConnectionListener
+{
+ private static boolean DEMO_FAILOVER = false;
+
+ public static void main(String[] args) throws IOException, URLSyntaxException, AMQException, JMSException
+ {
+ System.out.println("Testing socket connection to localhost:5672.");
+
+ new ExistingSocketConnectorDemo();
+
+ System.out.println("Testing socket connection failover between localhost:5672 and localhost:5673.");
+
+ DEMO_FAILOVER = true;
+
+ new ExistingSocketConnectorDemo();
+ }
+
+ Connection _connection;
+ MessageProducer _producer;
+ Session _session;
+
+ String Socket1_ID = UUID.randomUUID().toString();
+ String Socket2_ID = UUID.randomUUID().toString();
+
+
+
+ /** Here we can see the broker we are connecting to is set to be 'socket:///' signifying we will provide the socket. */
+ public final String CONNECTION = "amqp://guest:guest@id/test?brokerlist='socket://" + Socket1_ID + ";socket://" + Socket2_ID + "'";
+
+
+ public ExistingSocketConnectorDemo() throws IOException, URLSyntaxException, AMQException, JMSException
+ {
+
+ Socket socket = SocketChannel.open().socket();
+ socket.connect(new InetSocketAddress("localhost", 5672));
+
+ TransportConnection.registerOpenSocket(Socket1_ID, socket);
+
+
+ _connection = new AMQConnection(CONNECTION);
+
+ _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ MessageConsumer consumer = _session.createConsumer(_session.createQueue("Queue"));
+
+ _producer = _session.createProducer(_session.createQueue("Queue"));
+
+ _connection.start();
+
+ if (!DEMO_FAILOVER)
+ {
+ _producer.send(_session.createTextMessage("Simple Test"));
+ }
+ else
+ {
+ // Using the Qpid interfaces we can set a listener that allows us to demonstrate failover
+ ((AMQConnection) _connection).setConnectionListener(this);
+
+ System.out.println("Testing failover: Please ensure second broker running on localhost:5673 and shutdown broker on 5672.");
+ }
+
+ //We do a blocking receive here so that we can demonstrate failover.
+ Message message = consumer.receive();
+
+ System.out.println("Recevied :" + message);
+
+ _connection.close();
+ }
+
+ // ConnectionListener Interface
+
+ public void bytesSent(long count)
+ {
+ //not used in this example
+ }
+ public void bytesReceived(long count)
+ {
+ //not used in this example
+ }
+
+ public boolean preFailover(boolean redirect)
+ {
+ /**
+ * This method is called before the underlying client library starts to reconnect. This gives us the opportunity
+ * to set a new socket for the failover to occur on.
+ */
+ try
+ {
+ Socket socket = SocketChannel.open().socket();
+
+ socket.connect(new InetSocketAddress("localhost", 5673));
+
+ // This is the new method to pass in an open socket for the connection to use.
+ TransportConnection.registerOpenSocket(Socket2_ID, socket);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ public boolean preResubscribe()
+ {
+ //not used in this example - but must return true to allow the resubscription of existing clients.
+ return true;
+ }
+
+ public void failoverComplete()
+ {
+ // Now that failover has completed we can send a message that the receiving thread will pick up
+ try
+ {
+ _producer.send(_session.createTextMessage("Simple Failover Test"));
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/java/client/src/main/java/client.bnd b/java/client/src/main/java/client.bnd
index 98696dc7d8..0ddd163d4f 100755
--- a/java/client/src/main/java/client.bnd
+++ b/java/client/src/main/java/client.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.13.0
+ver: 0.9.0
Bundle-SymbolicName: qpid-client
Bundle-Version: ${ver}
diff --git a/java/client/src/main/java/org/apache/mina/transport/socket/nio/ExistingSocketConnector.java b/java/client/src/main/java/org/apache/mina/transport/socket/nio/ExistingSocketConnector.java
new file mode 100644
index 0000000000..98716c0c3c
--- /dev/null
+++ b/java/client/src/main/java/org/apache/mina/transport/socket/nio/ExistingSocketConnector.java
@@ -0,0 +1,478 @@
+/*
+ * 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 org.apache.mina.transport.socket.nio;
+
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoConnectorConfig;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.support.BaseIoConnector;
+import org.apache.mina.common.support.DefaultConnectFuture;
+import org.apache.mina.util.NamePreservingRunnable;
+import org.apache.mina.util.NewThreadExecutor;
+import org.apache.mina.util.Queue;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * {@link IoConnector} for socket transport (TCP/IP).
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 627427 $, $Date: 2008-02-13 14:39:10 +0000 (Wed, 13 Feb 2008) $
+ */
+public class ExistingSocketConnector extends BaseIoConnector
+{
+ /** @noinspection StaticNonFinalField */
+ private static volatile int nextId = 0;
+
+ private final Object lock = new Object();
+ private final int id = nextId++;
+ private final String threadName = "SocketConnector-" + id;
+ private SocketConnectorConfig defaultConfig = new SocketConnectorConfig();
+ private final Queue connectQueue = new Queue();
+ private final SocketIoProcessor[] ioProcessors;
+ private final int processorCount;
+ private final Executor executor;
+
+ /** @noinspection FieldAccessedSynchronizedAndUnsynchronized */
+ private Selector selector;
+ private Worker worker;
+ private int processorDistributor = 0;
+ private int workerTimeout = 60; // 1 min.
+ private Socket _openSocket = null;
+
+ /** Create a connector with a single processing thread using a NewThreadExecutor */
+ public ExistingSocketConnector()
+ {
+ this(1, new NewThreadExecutor());
+ }
+
+ /**
+ * Create a connector with the desired number of processing threads
+ *
+ * @param processorCount Number of processing threads
+ * @param executor Executor to use for launching threads
+ */
+ public ExistingSocketConnector(int processorCount, Executor executor)
+ {
+ if (processorCount < 1)
+ {
+ throw new IllegalArgumentException("Must have at least one processor");
+ }
+
+ this.executor = executor;
+ this.processorCount = processorCount;
+ ioProcessors = new SocketIoProcessor[processorCount];
+
+ for (int i = 0; i < processorCount; i++)
+ {
+ ioProcessors[i] = new SocketIoProcessor("SocketConnectorIoProcessor-" + id + "." + i, executor);
+ }
+ }
+
+ /**
+ * How many seconds to keep the connection thread alive between connection requests
+ *
+ * @return Number of seconds to keep connection thread alive
+ */
+ public int getWorkerTimeout()
+ {
+ return workerTimeout;
+ }
+
+ /**
+ * Set how many seconds the connection worker thread should remain alive once idle before terminating itself.
+ *
+ * @param workerTimeout Number of seconds to keep thread alive. Must be >=0
+ */
+ public void setWorkerTimeout(int workerTimeout)
+ {
+ if (workerTimeout < 0)
+ {
+ throw new IllegalArgumentException("Must be >= 0");
+ }
+ this.workerTimeout = workerTimeout;
+ }
+
+ public ConnectFuture connect(SocketAddress address, IoHandler handler, IoServiceConfig config)
+ {
+ return connect(address, null, handler, config);
+ }
+
+ public ConnectFuture connect(SocketAddress address, SocketAddress localAddress,
+ IoHandler handler, IoServiceConfig config)
+ {
+ /** Changes here from the Mina OpenSocketConnector.
+ * Ignoreing all address as they are not needed */
+
+ if (handler == null)
+ {
+ throw new NullPointerException("handler");
+ }
+
+
+ if (config == null)
+ {
+ config = getDefaultConfig();
+ }
+
+ if (_openSocket == null)
+ {
+ throw new IllegalArgumentException("Specifed Socket not active");
+ }
+
+ boolean success = false;
+
+ try
+ {
+ DefaultConnectFuture future = new DefaultConnectFuture();
+ newSession(_openSocket, handler, config, future);
+ success = true;
+ return future;
+ }
+ catch (IOException e)
+ {
+ return DefaultConnectFuture.newFailedFuture(e);
+ }
+ finally
+ {
+ if (!success && _openSocket != null)
+ {
+ try
+ {
+ _openSocket.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ }
+ }
+ }
+
+ public IoServiceConfig getDefaultConfig()
+ {
+ return defaultConfig;
+ }
+
+ /**
+ * Sets the config this connector will use by default.
+ *
+ * @param defaultConfig the default config.
+ *
+ * @throws NullPointerException if the specified value is <code>null</code>.
+ */
+ public void setDefaultConfig(SocketConnectorConfig defaultConfig)
+ {
+ if (defaultConfig == null)
+ {
+ throw new NullPointerException("defaultConfig");
+ }
+ this.defaultConfig = defaultConfig;
+ }
+
+ private synchronized void startupWorker() throws IOException
+ {
+ if (worker == null)
+ {
+ selector = Selector.open();
+ worker = new Worker();
+ executor.execute(new NamePreservingRunnable(worker));
+ }
+ }
+
+ private void registerNew()
+ {
+ if (connectQueue.isEmpty())
+ {
+ return;
+ }
+
+ for (; ;)
+ {
+ ConnectionRequest req;
+ synchronized (connectQueue)
+ {
+ req = (ConnectionRequest) connectQueue.pop();
+ }
+
+ if (req == null)
+ {
+ break;
+ }
+
+ SocketChannel ch = req.channel;
+ try
+ {
+ ch.register(selector, SelectionKey.OP_CONNECT, req);
+ }
+ catch (IOException e)
+ {
+ req.setException(e);
+ }
+ }
+ }
+
+ private void processSessions(Set keys)
+ {
+ Iterator it = keys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+
+ if (!key.isConnectable())
+ {
+ continue;
+ }
+
+ SocketChannel ch = (SocketChannel) key.channel();
+ ConnectionRequest entry = (ConnectionRequest) key.attachment();
+
+ boolean success = false;
+ try
+ {
+ ch.finishConnect();
+ newSession(ch, entry.handler, entry.config, entry);
+ success = true;
+ }
+ catch (Throwable e)
+ {
+ entry.setException(e);
+ }
+ finally
+ {
+ key.cancel();
+ if (!success)
+ {
+ try
+ {
+ ch.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ }
+ }
+ }
+
+ keys.clear();
+ }
+
+ private void processTimedOutSessions(Set keys)
+ {
+ long currentTime = System.currentTimeMillis();
+ Iterator it = keys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+
+ if (!key.isValid())
+ {
+ continue;
+ }
+
+ ConnectionRequest entry = (ConnectionRequest) key.attachment();
+
+ if (currentTime >= entry.deadline)
+ {
+ entry.setException(new ConnectException());
+ try
+ {
+ key.channel().close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ key.cancel();
+ }
+ }
+ }
+ }
+
+ private void newSession(Socket socket, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture)
+ throws IOException
+ {
+ SocketSessionImpl session = new SocketSessionImpl(this,
+ nextProcessor(),
+ getListeners(),
+ config,
+ socket.getChannel(),
+ handler,
+ socket.getRemoteSocketAddress());
+
+ newSession(session, config, connectFuture);
+ }
+
+ private void newSession(SocketChannel ch, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture)
+ throws IOException
+
+ {
+ SocketSessionImpl session = new SocketSessionImpl(this,
+ nextProcessor(),
+ getListeners(),
+ config,
+ ch,
+ handler,
+ ch.socket().getRemoteSocketAddress());
+
+ newSession(session, config, connectFuture);
+ }
+
+ private void newSession(SocketSessionImpl session, IoServiceConfig config, ConnectFuture connectFuture)
+ throws IOException
+ {
+ try
+ {
+ getFilterChainBuilder().buildFilterChain(session.getFilterChain());
+ config.getFilterChainBuilder().buildFilterChain(session.getFilterChain());
+ config.getThreadModel().buildFilterChain(session.getFilterChain());
+ }
+ catch (Throwable e)
+ {
+ throw (IOException) new IOException("Failed to create a session.").initCause(e);
+ }
+ session.getIoProcessor().addNew(session);
+ connectFuture.setSession(session);
+ }
+
+ private SocketIoProcessor nextProcessor()
+ {
+ return ioProcessors[processorDistributor++ % processorCount];
+ }
+
+ public void setOpenSocket(Socket openSocket)
+ {
+ _openSocket = openSocket;
+ }
+
+ private class Worker implements Runnable
+ {
+ private long lastActive = System.currentTimeMillis();
+
+ public void run()
+ {
+ Thread.currentThread().setName(ExistingSocketConnector.this.threadName);
+
+ for (; ;)
+ {
+ try
+ {
+ int nKeys = selector.select(1000);
+
+ registerNew();
+
+ if (nKeys > 0)
+ {
+ processSessions(selector.selectedKeys());
+ }
+
+ processTimedOutSessions(selector.keys());
+
+ if (selector.keys().isEmpty())
+ {
+ if (System.currentTimeMillis() - lastActive > workerTimeout * 1000L)
+ {
+ synchronized (lock)
+ {
+ if (selector.keys().isEmpty() &&
+ connectQueue.isEmpty())
+ {
+ worker = null;
+ try
+ {
+ selector.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ selector = null;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ lastActive = System.currentTimeMillis();
+ }
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e1)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e1);
+ }
+ }
+ }
+ }
+ }
+
+ private class ConnectionRequest extends DefaultConnectFuture
+ {
+ private final SocketChannel channel;
+ private final long deadline;
+ private final IoHandler handler;
+ private final IoServiceConfig config;
+
+ private ConnectionRequest(SocketChannel channel, IoHandler handler, IoServiceConfig config)
+ {
+ this.channel = channel;
+ long timeout;
+ if (config instanceof IoConnectorConfig)
+ {
+ timeout = ((IoConnectorConfig) config).getConnectTimeoutMillis();
+ }
+ else
+ {
+ timeout = ((IoConnectorConfig) getDefaultConfig()).getConnectTimeoutMillis();
+ }
+ this.deadline = System.currentTimeMillis() + timeout;
+ this.handler = handler;
+ this.config = config;
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQAnyDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQAnyDestination.java
index 999b22299c..a201f7d61e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQAnyDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQAnyDestination.java
@@ -72,17 +72,6 @@ public class AMQAnyDestination extends AMQDestination implements Queue, Topic
public String getTopicName() throws JMSException
{
- if (getRoutingKey() != null)
- {
- return getRoutingKey().asString();
- }
- else if (getSubject() != null)
- {
- return getSubject();
- }
- else
- {
- return null;
- }
+ return super.getRoutingKey().toString();
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java
index c0d4d8a893..ee52cd50af 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java
@@ -26,7 +26,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.qpid.jms.BrokerDetails;
-import org.apache.qpid.transport.ConnectionSettings;
+import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.url.URLHelper;
import org.apache.qpid.url.URLSyntaxException;
@@ -38,6 +38,8 @@ public class AMQBrokerDetails implements BrokerDetails
private Map<String, String> _options = new HashMap<String, String>();
+ private SSLConfiguration _sslConfiguration;
+
public AMQBrokerDetails(){}
public AMQBrokerDetails(String url) throws URLSyntaxException
@@ -54,7 +56,9 @@ public class AMQBrokerDetails implements BrokerDetails
if (transport != null)
{
//todo this list of valid transports should be enumerated somewhere
- if (!(transport.equalsIgnoreCase(BrokerDetails.TCP)))
+ if ((!(transport.equalsIgnoreCase(BrokerDetails.VM) ||
+ transport.equalsIgnoreCase(BrokerDetails.TCP) ||
+ transport.equalsIgnoreCase(BrokerDetails.SOCKET))))
{
if (transport.equalsIgnoreCase("localhost"))
{
@@ -101,21 +105,6 @@ public class AMQBrokerDetails implements BrokerDetails
if (host == null)
{
host = "";
-
- String auth = connection.getAuthority();
- if (auth != null)
- {
- // contains both host & port myhost:5672
- if (auth.contains(":"))
- {
- host = auth.substring(0,auth.indexOf(":"));
- }
- else
- {
- host = auth;
- }
- }
-
}
setHost(host);
@@ -178,7 +167,10 @@ public class AMQBrokerDetails implements BrokerDetails
}
else
{
- setPort(port);
+ if (!_transport.equalsIgnoreCase(SOCKET))
+ {
+ setPort(port);
+ }
}
String queryString = connection.getQuery();
@@ -198,10 +190,11 @@ public class AMQBrokerDetails implements BrokerDetails
}
}
- public AMQBrokerDetails(String host, int port)
+ public AMQBrokerDetails(String host, int port, SSLConfiguration sslConfiguration)
{
_host = host;
_port = port;
+ _sslConfiguration = sslConfiguration;
}
public String getHost()
@@ -277,15 +270,33 @@ public class AMQBrokerDetails implements BrokerDetails
setProperty(OPTIONS_CONNECT_TIMEOUT, Long.toString(timeout));
}
+ public SSLConfiguration getSSLConfiguration()
+ {
+ return _sslConfiguration;
+ }
+
+ public void setSSLConfiguration(SSLConfiguration sslConfig)
+ {
+ _sslConfiguration = sslConfig;
+ }
+
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append(_transport);
sb.append("://");
- sb.append(_host);
- sb.append(':');
- sb.append(_port);
+
+ if (!(_transport.equalsIgnoreCase(VM)))
+ {
+ sb.append(_host);
+ }
+
+ if (!(_transport.equalsIgnoreCase(SOCKET)))
+ {
+ sb.append(':');
+ sb.append(_port);
+ }
sb.append(printOptionsURL());
@@ -303,8 +314,9 @@ public class AMQBrokerDetails implements BrokerDetails
return _host.equalsIgnoreCase(bd.getHost()) &&
(_port == bd.getPort()) &&
- _transport.equalsIgnoreCase(bd.getTransport());
- //TODO do we need to compare all the options as well?
+ _transport.equalsIgnoreCase(bd.getTransport()) &&
+ compareSSLConfigurations(bd.getSSLConfiguration());
+ //todo do we need to compare all the options as well?
}
@Override
@@ -345,6 +357,24 @@ public class AMQBrokerDetails implements BrokerDetails
return optionsURL.toString();
}
+ // Do we need to do a more in-depth comparison?
+ private boolean compareSSLConfigurations(SSLConfiguration other)
+ {
+ boolean retval = false;
+ if (_sslConfiguration == null &&
+ other == null)
+ {
+ retval = true;
+ }
+ else if (_sslConfiguration != null &&
+ other != null)
+ {
+ retval = true;
+ }
+
+ return retval;
+ }
+
public static String checkTransport(String broker)
{
if ((!broker.contains("://")))
@@ -366,82 +396,4 @@ public class AMQBrokerDetails implements BrokerDetails
{
_options = props;
}
-
- public ConnectionSettings buildConnectionSettings()
- {
- ConnectionSettings conSettings = new ConnectionSettings();
-
- conSettings.setHost(getHost());
- conSettings.setPort(getPort());
-
- // ------------ sasl options ---------------
- if (getProperty(BrokerDetails.OPTIONS_SASL_MECHS) != null)
- {
- conSettings.setSaslMechs(
- getProperty(BrokerDetails.OPTIONS_SASL_MECHS));
- }
-
- // Sun SASL Kerberos client uses the
- // protocol + servername as the service key.
-
- if (getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME) != null)
- {
- conSettings.setSaslProtocol(
- getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME));
- }
-
-
- if (getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME) != null)
- {
- conSettings.setSaslServerName(
- getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME));
- }
-
- conSettings.setUseSASLEncryption(
- getBooleanProperty(BrokerDetails.OPTIONS_SASL_ENCRYPTION));
-
- // ------------- ssl options ---------------------
- conSettings.setUseSSL(getBooleanProperty(BrokerDetails.OPTIONS_SSL));
-
- if (getProperty(BrokerDetails.OPTIONS_TRUST_STORE) != null)
- {
- conSettings.setTrustStorePath(
- getProperty(BrokerDetails.OPTIONS_TRUST_STORE));
- }
-
- if (getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD) != null)
- {
- conSettings.setTrustStorePassword(
- getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD));
- }
-
- if (getProperty(BrokerDetails.OPTIONS_KEY_STORE) != null)
- {
- conSettings.setKeyStorePath(
- getProperty(BrokerDetails.OPTIONS_KEY_STORE));
- }
-
- if (getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD) != null)
- {
- conSettings.setKeyStorePassword(
- getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD));
- }
-
- if (getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS) != null)
- {
- conSettings.setCertAlias(
- getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS));
- }
- // ----------------------------
-
- conSettings.setVerifyHostname(getBooleanProperty(BrokerDetails.OPTIONS_SSL_VERIFY_HOSTNAME));
-
- if (getProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY) != null)
- {
- conSettings.setTcpNodelay(
- getBooleanProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY));
- }
-
- return conSettings;
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index f15af72407..ab59fee020 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -111,7 +111,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/** Maps from session id (Integer) to AMQSession instance */
private final ChannelToSessionMap _sessions = new ChannelToSessionMap();
- private final String _clientName;
+ private String _clientName;
/** The user name to use for authentication */
private String _username;
@@ -126,7 +126,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private ConnectionListener _connectionListener;
- private final ConnectionURL _connectionURL;
+ private ConnectionURL _connectionURL;
/**
* Whether this connection is started, i.e. whether messages are flowing to consumers. It has no meaning for message
@@ -147,6 +147,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
*/
private QpidConnectionMetaData _connectionMetaData;
+ /** Configuration info for SSL */
+ private SSLConfiguration _sslConfiguration;
+
private AMQShortString _defaultTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME;
private AMQShortString _defaultQueueExchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME;
private AMQShortString _temporaryTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME;
@@ -170,8 +173,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
//Indicates the sync publish options (persistent|all)
//By default it's async publish
private String _syncPublish = "";
-
- // Indicates whether to use the old map message format or the
+
+ // Indicates whether to use the old map message format or the
// new amqp-0-10 encoded format.
private boolean _useLegacyMapMessageFormat;
@@ -191,33 +194,69 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
this(new AMQConnectionURL(
ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ ((clientName == null) ? "" : clientName) + "/" + virtualHost + "?brokerlist='"
- + AMQBrokerDetails.checkTransport(broker) + "'"));
+ + AMQBrokerDetails.checkTransport(broker) + "'"), null);
+ }
+
+ /**
+ * @param broker brokerdetails
+ * @param username username
+ * @param password password
+ * @param clientName clientid
+ * @param virtualHost virtualhost
+ *
+ * @throws AMQException
+ * @throws URLSyntaxException
+ */
+ public AMQConnection(String broker, String username, String password, String clientName, String virtualHost,
+ SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ {
+ this(new AMQConnectionURL(
+ ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + "/" + virtualHost + "?brokerlist='"
+ + AMQBrokerDetails.checkTransport(broker) + "'"), sslConfig);
}
public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost)
throws AMQException, URLSyntaxException
{
+ this(host, port, false, username, password, clientName, virtualHost, null);
+ }
+
+ public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost,
+ SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ {
+ this(host, port, false, username, password, clientName, virtualHost, sslConfig);
+ }
+
+ public AMQConnection(String host, int port, boolean useSSL, String username, String password, String clientName,
+ String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ {
this(new AMQConnectionURL(
- ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
- + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port + "'"));
+ useSSL
+ ? (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port
+ + "'" + "," + BrokerDetails.OPTIONS_SSL + "='true'")
+ : (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port
+ + "'" + "," + BrokerDetails.OPTIONS_SSL + "='false'")), sslConfig);
}
public AMQConnection(String connection) throws AMQException, URLSyntaxException
{
- this(new AMQConnectionURL(connection));
+ this(new AMQConnectionURL(connection), null);
+ }
+
+ public AMQConnection(String connection, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ {
+ this(new AMQConnectionURL(connection), sslConfig);
}
/**
* @todo Some horrible stuff going on here with setting exceptions to be non-null to detect if an exception
* was thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon.
*/
- public AMQConnection(ConnectionURL connectionURL) throws AMQException
+ public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException
{
- if (connectionURL == null)
- {
- throw new IllegalArgumentException("Connection must be specified");
- }
-
// set this connection maxPrefetch
if (connectionURL.getOption(ConnectionURL.OPTIONS_MAXPREFETCH) != null)
{
@@ -225,7 +264,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the default value set for all connections
+ // use the defaul value set for all connections
_maxPrefetch = Integer.parseInt(System.getProperties().getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME,
ClientProperties.MAX_PREFETCH_DEFAULT));
}
@@ -239,7 +278,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the default value set for all connections
+ // use the defaul value set for all connections
_syncPersistence = Boolean.getBoolean(ClientProperties.SYNC_PERSISTENT_PROP_NAME);
if (_syncPersistence)
{
@@ -254,7 +293,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else
{
- // use the default value set for all connections
+ // use the defaul value set for all connections
_syncAck = Boolean.getBoolean(ClientProperties.SYNC_ACK_PROP_NAME);
}
@@ -267,7 +306,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
// use the default value set for all connections
_syncPublish = System.getProperty((ClientProperties.SYNC_PUBLISH_PROP_NAME),_syncPublish);
}
-
+
if (connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_MAP_MESSAGE_FORMAT) != null)
{
_useLegacyMapMessageFormat = Boolean.parseBoolean(
@@ -278,16 +317,16 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
// use the default value set for all connections
_useLegacyMapMessageFormat = Boolean.getBoolean(ClientProperties.USE_LEGACY_MAP_MESSAGE_FORMAT);
}
-
+
String amqpVersion = System.getProperty((ClientProperties.AMQP_VERSION), "0-10");
_logger.debug("AMQP version " + amqpVersion);
-
+
_failoverPolicy = new FailoverPolicy(connectionURL, this);
BrokerDetails brokerDetails = _failoverPolicy.getCurrentBrokerDetails();
- if ("0-8".equals(amqpVersion))
+ if (brokerDetails.getTransport().equals(BrokerDetails.VM) || "0-8".equals(amqpVersion))
{
_delegate = new AMQConnectionDelegate_8_0(this);
- }
+ }
else if ("0-9".equals(amqpVersion))
{
_delegate = new AMQConnectionDelegate_0_9(this);
@@ -306,6 +345,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_logger.info("Connection:" + connectionURL);
}
+ _sslConfiguration = sslConfig;
+ if (connectionURL == null)
+ {
+ throw new IllegalArgumentException("Connection must be specified");
+ }
+
_connectionURL = connectionURL;
_clientName = connectionURL.getClientName();
@@ -373,7 +418,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
brokerDetails = _failoverPolicy.getNextBrokerDetails();
}
}
- verifyClientID();
if (_logger.isDebugEnabled())
{
@@ -460,7 +504,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
Class partypes[] = new Class[1];
partypes[0] = AMQConnection.class;
_delegate = (AMQConnectionDelegate) c.getConstructor(partypes).newInstance(this);
- //Update our session to use this new protocol version
+ //Update our session to use this new protocol version
_protocolHandler.getProtocolSession().setProtocolVersion(_delegate.getProtocolVersion());
}
@@ -491,6 +535,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
+ protected AMQConnection(String username, String password, String clientName, String virtualHost)
+ {
+ _clientName = clientName;
+ _username = username;
+ _password = password;
+ setVirtualHost(virtualHost);
+ }
+
private void setVirtualHost(String virtualHost)
{
if (virtualHost != null && virtualHost.startsWith("/"))
@@ -503,7 +555,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public boolean attemptReconnection(String host, int port)
{
- BrokerDetails bd = new AMQBrokerDetails(host, port);
+ BrokerDetails bd = new AMQBrokerDetails(host, port, _sslConfiguration);
_failoverPolicy.setBroker(bd);
@@ -644,6 +696,20 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
+ private void reopenChannel(int channelId, int prefetchHigh, int prefetchLow, boolean transacted)
+ throws AMQException, FailoverException
+ {
+ try
+ {
+ createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted);
+ }
+ catch (AMQException e)
+ {
+ deregisterSession(channelId);
+ throw new AMQException(null, "Error reopening channel " + channelId + " after failover: " + e, e);
+ }
+ }
+
public void setFailoverPolicy(FailoverPolicy policy)
{
_failoverPolicy = policy;
@@ -1030,7 +1096,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_username = id;
}
-
+
public String getPassword()
{
return _password;
@@ -1183,7 +1249,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if (code != null)
{
- je = new JMSException("Exception thrown against " + toString() + ": " + cause, Integer.toString(code.getCode()));
+ je = new JMSException(Integer.toString(code.getCode()), "Exception thrown against " + toString() + ": " + cause);
}
else
{
@@ -1206,7 +1272,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
je.setLinkedException((Exception) cause);
}
-
+
je.initCause(cause);
}
@@ -1239,7 +1305,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_logger.info("Not a hard-error connection not closing: " + cause);
}
-
+
// deliver the exception if there is a listener
if (_exceptionListener != null)
{
@@ -1249,7 +1315,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_logger.error("Throwable Received but no listener set: " + cause);
}
-
+
// if we are closing the connection, close sessions first
if (closer)
{
@@ -1306,20 +1372,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return buf.toString();
}
- /**
- * Returns connection url.
- * @return connection url
- */
- public ConnectionURL getConnectionURL()
- {
- return _connectionURL;
- }
-
- /**
- * Returns stringified connection url. This url is suitable only for display
- * as {@link AMQConnectionURL#toString()} converts any password to asterisks.
- * @return connection url
- */
public String toURL()
{
return _connectionURL.toString();
@@ -1331,6 +1383,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
AMQConnectionFactory.class.getName(), null); // factory location
}
+ public SSLConfiguration getSSLConfiguration()
+ {
+ return _sslConfiguration;
+ }
+
public AMQShortString getDefaultTopicExchangeName()
{
return _defaultTopicExchangeName;
@@ -1385,18 +1442,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _delegate.getProtocolVersion();
}
-
- public String getBrokerUUID()
- {
- if(getProtocolVersion().equals(ProtocolVersion.v0_10))
- {
- return ((AMQConnectionDelegate_0_10)_delegate).getUUID();
- }
- else
- {
- return null;
- }
- }
+
public boolean isFailingOver()
{
return (_protocolHandler.getFailoverLatch() != null);
@@ -1439,27 +1485,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _sessions.getNextChannelId();
}
-
+
public boolean isUseLegacyMapMessageFormat()
{
return _useLegacyMapMessageFormat;
}
-
- private void verifyClientID() throws AMQException
- {
- if (Boolean.getBoolean(ClientProperties.QPID_VERIFY_CLIENT_ID))
- {
- try
- {
- if (!_delegate.verifyClientID())
- {
- throw new AMQException(AMQConstant.ALREADY_EXISTS,"ClientID must be unique");
- }
- }
- catch(JMSException e)
- {
- throw new AMQException(e.getMessage(),e);
- }
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
index 8768f93c8c..9560bd5c7c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
@@ -57,12 +57,10 @@ public interface AMQConnectionDelegate
void closeConnection(long timeout) throws JMSException, AMQException;
<T, E extends Exception> T executeRetrySupport(FailoverProtectedOperation<T,E> operation) throws E;
-
+
int getMaxChannelID();
int getMinChannelID();
ProtocolVersion getProtocolVersion();
-
- boolean verifyClientID() throws JMSException, AMQException;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
index 0ed3db6ecb..b0bd8f8e97 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
@@ -1,6 +1,6 @@
package org.apache.qpid.client;
/*
- *
+ *
* 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
@@ -8,16 +8,16 @@ package org.apache.qpid.client;
* 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.
- *
+ *
*/
@@ -35,7 +35,6 @@ import javax.jms.XASession;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
-import org.apache.qpid.client.transport.ClientConnectionDelegate;
import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.jms.BrokerDetails;
@@ -44,13 +43,10 @@ import org.apache.qpid.jms.Session;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.transport.Connection;
import org.apache.qpid.transport.ConnectionClose;
-import org.apache.qpid.transport.ConnectionCloseCode;
import org.apache.qpid.transport.ConnectionException;
import org.apache.qpid.transport.ConnectionListener;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.transport.ProtocolVersionException;
-import org.apache.qpid.transport.SessionDetachCode;
-import org.apache.qpid.transport.SessionException;
import org.apache.qpid.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,10 +59,6 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionDelegate_0_10.class);
/**
- * The name of the UUID property
- */
- private static final String UUID_NAME = "qpid.federation_tag";
- /**
* The AMQ Connection.
*/
private AMQConnection _conn;
@@ -77,12 +69,6 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
org.apache.qpid.transport.Connection _qpidConnection;
private ConnectionException exception = null;
- static
- {
- // Register any configured SASL client factories.
- org.apache.qpid.client.security.DynamicSaslRegistrar.registerSaslProviders();
- }
-
//--- constructor
public AMQConnectionDelegate_0_10(AMQConnection conn)
{
@@ -94,14 +80,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
/**
* create a Session and start it if required.
*/
-
public Session createSession(boolean transacted, int acknowledgeMode, int prefetchHigh, int prefetchLow)
- throws JMSException
- {
- return createSession(transacted,acknowledgeMode,prefetchHigh,prefetchLow,null);
- }
-
- public Session createSession(boolean transacted, int acknowledgeMode, int prefetchHigh, int prefetchLow, String name)
throws JMSException
{
_conn.checkNotClosed();
@@ -116,7 +95,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
try
{
session = new AMQSession_0_10(_qpidConnection, _conn, channelId, transacted, acknowledgeMode, prefetchHigh,
- prefetchLow,name);
+ prefetchLow);
_conn.registerSession(channelId, session);
if (_conn._started)
{
@@ -194,8 +173,8 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
+ _conn.getPassword());
}
- ConnectionSettings conSettings = retriveConnectionSettings(brokerDetail);
- _qpidConnection.setConnectionDelegate(new ClientConnectionDelegate(conSettings, _conn.getConnectionURL()));
+ ConnectionSettings conSettings = new ConnectionSettings();
+ retriveConnectionSettings(conSettings,brokerDetail);
_qpidConnection.connect(conSettings);
_conn._connected = true;
@@ -232,8 +211,6 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
public void resubscribeSessions() throws JMSException, AMQException, FailoverException
{
- _logger.info("Resuming connection");
- getQpidConnection().resume();
List<AMQSession> sessions = new ArrayList<AMQSession>(_conn.getSessions().values());
_logger.info(String.format("Resubscribing sessions = %s sessions.size=%d", sessions, sessions.size()));
for (AMQSession s : sessions)
@@ -277,10 +254,10 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
}
ConnectionClose close = exc.getClose();
- if (close == null || close.getReplyCode() == ConnectionCloseCode.CONNECTION_FORCED)
+ if (close == null)
{
_conn.getProtocolHandler().setFailoverLatch(new CountDownLatch(1));
-
+
try
{
if (_conn.firePreFailover(false) && _conn.attemptReconnection())
@@ -349,20 +326,78 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
{
return ProtocolVersion.v0_10;
}
-
- public String getUUID()
- {
- return (String)_qpidConnection.getServerProperties().get(UUID_NAME);
- }
-
- private ConnectionSettings retriveConnectionSettings(BrokerDetails brokerDetail)
+
+ private void retriveConnectionSettings(ConnectionSettings conSettings, BrokerDetails brokerDetail)
{
- ConnectionSettings conSettings = brokerDetail.buildConnectionSettings();
+ conSettings.setHost(brokerDetail.getHost());
+ conSettings.setPort(brokerDetail.getPort());
conSettings.setVhost(_conn.getVirtualHost());
conSettings.setUsername(_conn.getUsername());
conSettings.setPassword(_conn.getPassword());
+
+ // ------------ sasl options ---------------
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_MECHS) != null)
+ {
+ conSettings.setSaslMechs(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_MECHS));
+ }
+ // Sun SASL Kerberos client uses the
+ // protocol + servername as the service key.
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME) != null)
+ {
+ conSettings.setSaslProtocol(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_PROTOCOL_NAME));
+ }
+
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME) != null)
+ {
+ conSettings.setSaslServerName(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_SASL_SERVER_NAME));
+ }
+
+ conSettings.setUseSASLEncryption(
+ brokerDetail.getBooleanProperty(BrokerDetails.OPTIONS_SASL_ENCRYPTION));
+
+ // ------------- ssl options ---------------------
+ conSettings.setUseSSL(brokerDetail.getBooleanProperty(BrokerDetails.OPTIONS_SSL));
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_TRUST_STORE) != null)
+ {
+ conSettings.setTrustStorePath(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_TRUST_STORE));
+ }
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD) != null)
+ {
+ conSettings.setTrustStorePassword(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_TRUST_STORE_PASSWORD));
+ }
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_KEY_STORE) != null)
+ {
+ conSettings.setKeyStorePath(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_KEY_STORE));
+ }
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD) != null)
+ {
+ conSettings.setKeyStorePassword(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_KEY_STORE_PASSWORD));
+ }
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS) != null)
+ {
+ conSettings.setCertAlias(
+ brokerDetail.getProperty(BrokerDetails.OPTIONS_SSL_CERT_ALIAS));
+ }
+ // ----------------------------
+
+ conSettings.setVerifyHostname(brokerDetail.getBooleanProperty(BrokerDetails.OPTIONS_SSL_VERIFY_HOSTNAME));
+
// Pass client name from connection URL
Map<String, Object> clientProps = new HashMap<String, Object>();
try
@@ -374,12 +409,16 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
{
// Ignore
}
-
+
+ if (brokerDetail.getProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY) != null)
+ {
+ conSettings.setTcpNodelay(
+ brokerDetail.getBooleanProperty(BrokerDetails.OPTIONS_TCP_NO_DELAY));
+ }
+
conSettings.setHeartbeatInterval(getHeartbeatInterval(brokerDetail));
-
- return conSettings;
}
-
+
// The idle_timeout prop is in milisecs while
// the new heartbeat prop is in secs
private int getHeartbeatInterval(BrokerDetails brokerDetail)
@@ -394,7 +433,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
{
heartbeat = Integer.parseInt(brokerDetail.getProperty(BrokerDetails.OPTIONS_HEARTBEAT));
}
- else if (Integer.getInteger(ClientProperties.IDLE_TIMEOUT_PROP_NAME) != null)
+ else if (Integer.getInteger(ClientProperties.IDLE_TIMEOUT_PROP_NAME) != null)
{
heartbeat = Integer.getInteger(ClientProperties.IDLE_TIMEOUT_PROP_NAME)/1000;
_logger.warn("JVM arg -Didle_timeout=<mili_secs> is deprecated, please use -Dqpid.heartbeat=<secs>");
@@ -402,37 +441,12 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec
else
{
heartbeat = Integer.getInteger(ClientProperties.HEARTBEAT,ClientProperties.HEARTBEAT_DEFAULT);
- }
+ }
return heartbeat;
}
-
+
protected org.apache.qpid.transport.Connection getQpidConnection()
{
return _qpidConnection;
}
-
- public boolean verifyClientID() throws JMSException, AMQException
- {
- int prefetch = (int)_conn.getMaxPrefetch();
- AMQSession_0_10 ssn = (AMQSession_0_10)createSession(false, 1,prefetch,prefetch,_conn.getClientID());
- org.apache.qpid.transport.Session ssn_0_10 = ssn.getQpidSession();
- try
- {
- ssn_0_10.awaitOpen();
- }
- catch(SessionException se)
- {
- //if due to non unique client id for user return false, otherwise wrap and re-throw.
- if (ssn_0_10.getDetachCode() != null &&
- ssn_0_10.getDetachCode() == SessionDetachCode.SESSION_BUSY)
- {
- return false;
- }
- else
- {
- throw new AMQException(AMQConstant.INTERNAL_ERROR, "Unexpected SessionException thrown while awaiting session opening", se);
- }
- }
- return true;
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
index b1a22155d6..40b332d216 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
@@ -23,8 +23,6 @@ package org.apache.qpid.client;
import java.io.IOException;
import java.net.ConnectException;
import java.nio.channels.UnresolvedAddressException;
-import java.security.GeneralSecurityException;
-import java.security.Security;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.EnumSet;
@@ -33,17 +31,15 @@ import java.util.Set;
import javax.jms.JMSException;
import javax.jms.XASession;
-import javax.net.ssl.SSLContext;
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQTimeoutException;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.failover.FailoverRetrySupport;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateWaiter;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.BasicQosBody;
import org.apache.qpid.framing.BasicQosOkBody;
import org.apache.qpid.framing.ChannelOpenBody;
@@ -53,13 +49,6 @@ import org.apache.qpid.framing.TxSelectBody;
import org.apache.qpid.framing.TxSelectOkBody;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ChannelLimitReachedException;
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.network.NetworkConnection;
-import org.apache.qpid.transport.network.OutgoingNetworkTransport;
-import org.apache.qpid.transport.network.Transport;
-import org.apache.qpid.transport.network.security.SecurityLayer;
-import org.apache.qpid.transport.network.security.SecurityLayerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,30 +60,8 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
public void closeConnection(long timeout) throws JMSException, AMQException
{
- final AMQStateManager stateManager = _conn.getProtocolHandler().getStateManager();
- final AMQState currentState = stateManager.getCurrentState();
+ _conn.getProtocolHandler().closeConnection(timeout);
- if (currentState.equals(AMQState.CONNECTION_CLOSED))
- {
- _logger.debug("Connection already closed.");
- }
- else if (currentState.equals(AMQState.CONNECTION_CLOSING))
- {
- _logger.debug("Connection already closing, awaiting closed state.");
- final StateWaiter closeWaiter = new StateWaiter(stateManager, currentState, EnumSet.of(AMQState.CONNECTION_CLOSED));
- try
- {
- closeWaiter.await(timeout);
- }
- catch (AMQTimeoutException te)
- {
- throw new AMQTimeoutException("Close did not complete in timely fashion", te);
- }
- }
- else
- {
- _conn.getProtocolHandler().closeConnection(timeout);
- }
}
public AMQConnectionDelegate_8_0(AMQConnection conn)
@@ -122,34 +89,15 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
StateWaiter waiter = _conn._protocolHandler.createWaiter(openOrClosedStates);
- ConnectionSettings settings = brokerDetail.buildConnectionSettings();
- settings.setProtocol(brokerDetail.getTransport());
-
- SSLContext sslContext = null;
- if (settings.isUseSSL())
+ // TODO: use system property thingy for this
+ if (System.getProperty("UseTransportIo", "false").equals("false"))
{
- try
- {
- sslContext = SSLContextFactory.buildClientContext(
- settings.getTrustStorePath(),
- settings.getTrustStorePassword(),
- settings.getTrustStoreCertType(),
- settings.getKeyStorePath(),
- settings.getKeyStorePassword(),
- settings.getKeyStoreCertType(),
- settings.getCertAlias());
- }
- catch (GeneralSecurityException e)
- {
- throw new AMQException("Unable to create SSLContext: " + e.getMessage(), e);
- }
+ TransportConnection.getInstance(brokerDetail).connect(_conn._protocolHandler, brokerDetail);
+ }
+ else
+ {
+ _conn.getProtocolHandler().createIoTransportSession(brokerDetail);
}
-
- SecurityLayer securityLayer = SecurityLayerFactory.newInstance(settings);
-
- OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(getProtocolVersion());
- NetworkConnection network = transport.connect(settings, securityLayer.receiver(_conn._protocolHandler), sslContext);
- _conn._protocolHandler.setNetworkConnection(network, securityLayer.sender(network.getSender()));
_conn._protocolHandler.getProtocolSession().init();
// this blocks until the connection has been set up or when an error
// has prevented the connection being set up
@@ -374,9 +322,4 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
{
return ProtocolVersion.v8_0;
}
-
- public boolean verifyClientID() throws JMSException
- {
- return true;
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
index f0c003e02a..ec4c668d7e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
@@ -44,34 +44,210 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
ObjectFactory, Referenceable, XATopicConnectionFactory,
XAQueueConnectionFactory, XAConnectionFactory
{
- private final ConnectionURL _connectionDetails;
+ private String _host;
+ private int _port;
+ private String _defaultUsername;
+ private String _defaultPassword;
+ private String _virtualPath;
- public AMQConnectionFactory(final String url) throws URLSyntaxException
+ private ConnectionURL _connectionDetails;
+ private SSLConfiguration _sslConfig;
+
+ public AMQConnectionFactory()
{
- if (url == null)
- {
- throw new IllegalArgumentException("url cannot be null");
- }
+ }
+ /**
+ * This is the Only constructor used!
+ * It is used form the context and from the JNDI objects.
+ */
+ public AMQConnectionFactory(String url) throws URLSyntaxException
+ {
_connectionDetails = new AMQConnectionURL(url);
}
+ /**
+ * This constructor is never used!
+ */
public AMQConnectionFactory(ConnectionURL url)
{
- if (url == null)
+ _connectionDetails = url;
+ }
+
+ /**
+ * This constructor is never used!
+ */
+ public AMQConnectionFactory(String broker, String username, String password, String clientName, String virtualHost)
+ throws URLSyntaxException
+ {
+ this(new AMQConnectionURL(
+ ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" + clientName + "/" + virtualHost + "?brokerlist='" + broker + "'"));
+ }
+
+ /**
+ * This constructor is never used!
+ */
+ public AMQConnectionFactory(String host, int port, String virtualPath)
+ {
+ this(host, port, "guest", "guest", virtualPath);
+ }
+
+ /**
+ * This constructor is never used!
+ */
+ public AMQConnectionFactory(String host, int port, String defaultUsername, String defaultPassword,
+ String virtualPath)
+ {
+ _host = host;
+ _port = port;
+ _defaultUsername = defaultUsername;
+ _defaultPassword = defaultPassword;
+ _virtualPath = virtualPath;
+
+//todo when setting Host/Port has been resolved then we can use this otherwise those methods won't work with the following line.
+// _connectionDetails = new AMQConnectionURL(
+// ConnectionURL.AMQ_PROTOCOL + "://" +
+// _defaultUsername + ":" + _defaultPassword + "@" +
+// virtualPath + "?brokerlist='tcp://" + host + ":" + port + "'");
+ }
+
+ /**
+ * @return The _defaultPassword.
+ */
+ public final String getDefaultPassword(String password)
+ {
+ if (_connectionDetails != null)
{
- throw new IllegalArgumentException("url cannot be null");
+ return _connectionDetails.getPassword();
}
+ else
+ {
+ return _defaultPassword;
+ }
+ }
- _connectionDetails = url;
+ /**
+ * @param password The _defaultPassword to set.
+ */
+ public final void setDefaultPassword(String password)
+ {
+ if (_connectionDetails != null)
+ {
+ _connectionDetails.setPassword(password);
+ }
+ _defaultPassword = password;
+ }
+
+ /**
+ * Getter for SSLConfiguration
+ *
+ * @return SSLConfiguration if set, otherwise null
+ */
+ public final SSLConfiguration getSSLConfiguration()
+ {
+ return _sslConfig;
+ }
+
+ /**
+ * Setter for SSLConfiguration
+ *
+ * @param sslConfig config to store
+ */
+ public final void setSSLConfiguration(SSLConfiguration sslConfig)
+ {
+ _sslConfig = sslConfig;
+ }
+
+ /**
+ * @return The _defaultPassword.
+ */
+ public final String getDefaultUsername(String password)
+ {
+ if (_connectionDetails != null)
+ {
+ return _connectionDetails.getUsername();
+ }
+ else
+ {
+ return _defaultUsername;
+ }
+ }
+
+ /**
+ * @param username The _defaultUsername to set.
+ */
+ public final void setDefaultUsername(String username)
+ {
+ if (_connectionDetails != null)
+ {
+ _connectionDetails.setUsername(username);
+ }
+ _defaultUsername = username;
+ }
+
+ /**
+ * @return The _host .
+ */
+ public final String getHost()
+ {
+ //todo this doesn't make sense in a multi broker URL as we have no current as that is done by AMQConnection
+ return _host;
}
/**
- * @return the virtualPath of the connection details.
+ * @param host The _host to set.
+ */
+ public final void setHost(String host)
+ {
+ //todo if _connectionDetails is set then run _connectionDetails.addBrokerDetails()
+ // Should perhaps have this method changed to setBroker(host,port)
+ _host = host;
+ }
+
+ /**
+ * @return _port The _port to set.
+ */
+ public final int getPort()
+ {
+ //todo see getHost
+ return _port;
+ }
+
+ /**
+ * @param port The port to set.
+ */
+ public final void setPort(int port)
+ {
+ //todo see setHost
+ _port = port;
+ }
+
+ /**
+ * @return he _virtualPath.
*/
public final String getVirtualPath()
{
- return _connectionDetails.getVirtualHost();
+ if (_connectionDetails != null)
+ {
+ return _connectionDetails.getVirtualHost();
+ }
+ else
+ {
+ return _virtualPath;
+ }
+ }
+
+ /**
+ * @param path The _virtualPath to set.
+ */
+ public final void setVirtualPath(String path)
+ {
+ if (_connectionDetails != null)
+ {
+ _connectionDetails.setVirtualHost(path);
+ }
+
+ _virtualPath = path;
}
public static String getUniqueClientID()
@@ -91,11 +267,19 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
{
try
{
- if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
+ if (_connectionDetails != null)
{
- _connectionDetails.setClientName(getUniqueClientID());
+ if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
+ {
+ _connectionDetails.setClientName(getUniqueClientID());
+ }
+ return new AMQConnection(_connectionDetails, _sslConfig);
+ }
+ else
+ {
+ return new AMQConnection(_host, _port, _defaultUsername, _defaultPassword, getUniqueClientID(),
+ _virtualPath);
}
- return new AMQConnection(_connectionDetails);
}
catch (Exception e)
{
@@ -104,6 +288,8 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
jmse.initCause(e);
throw jmse;
}
+
+
}
public Connection createConnection(String userName, String password) throws JMSException
@@ -113,35 +299,34 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
public Connection createConnection(String userName, String password, String id) throws JMSException
{
- if (_connectionDetails != null)
+ try
{
- try
+ if (_connectionDetails != null)
{
- ConnectionURL connectionDetails = new AMQConnectionURL(_connectionDetails.toString());
- connectionDetails.setUsername(userName);
- connectionDetails.setPassword(password);
+ _connectionDetails.setUsername(userName);
+ _connectionDetails.setPassword(password);
if (id != null && !id.equals(""))
{
- connectionDetails.setClientName(id);
+ _connectionDetails.setClientName(id);
}
- else if (connectionDetails.getClientName() == null || connectionDetails.getClientName().equals(""))
+ else if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
{
- connectionDetails.setClientName(getUniqueClientID());
+ _connectionDetails.setClientName(getUniqueClientID());
}
- return new AMQConnection(connectionDetails);
+ return new AMQConnection(_connectionDetails, _sslConfig);
}
- catch (Exception e)
+ else
{
- JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
- jmse.setLinkedException(e);
- jmse.initCause(e);
- throw jmse;
+ return new AMQConnection(_host, _port, userName, password, (id != null ? id : getUniqueClientID()), _virtualPath);
}
}
- else
+ catch (Exception e)
{
- throw new JMSException("The connection factory wasn't created with a proper URL, the connection details are empty");
+ JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
}
}
@@ -176,6 +361,12 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
return _connectionDetails.toString();
}
+
+ public final void setConnectionURLString(String url) throws URLSyntaxException
+ {
+ _connectionDetails = new AMQConnectionURL(url);
+ }
+
/**
* JNDI interface to create objects from References.
*
@@ -266,7 +457,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
{
try
{
- return new XAConnectionImpl(_connectionDetails);
+ return new XAConnectionImpl(_connectionDetails, _sslConfig);
}
catch (Exception e)
{
@@ -293,30 +484,19 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
{
if (_connectionDetails != null)
{
- try
- {
- ConnectionURL connectionDetails = new AMQConnectionURL(_connectionDetails.toString());
- connectionDetails.setUsername(username);
- connectionDetails.setPassword(password);
-
- if (connectionDetails.getClientName() == null || connectionDetails.getClientName().equals(""))
- {
- connectionDetails.setClientName(getUniqueClientID());
- }
- return new XAConnectionImpl(connectionDetails);
- }
- catch (Exception e)
+ _connectionDetails.setUsername(username);
+ _connectionDetails.setPassword(password);
+
+ if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
{
- JMSException jmse = new JMSException("Error creating XA Connection: " + e.getMessage());
- jmse.setLinkedException(e);
- jmse.initCause(e);
- throw jmse;
+ _connectionDetails.setClientName(getUniqueClientID());
}
}
else
{
- throw new JMSException("The connection factory wasn't created with a proper URL, the connection details are empty");
- }
+ throw new JMSException("A URL must be specified to access XA connections");
+ }
+ return createXAConnection();
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
index f9f50d9150..93b4c51a8f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
@@ -27,14 +27,18 @@ import java.util.Map;
import org.apache.qpid.client.url.URLParser;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.url.URLHelper;
import org.apache.qpid.url.URLSyntaxException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class AMQConnectionURL implements ConnectionURL
{
-
+ private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionURL.class);
+
private String _url;
private String _failoverMethod;
private Map<String, String> _failoverOptions;
@@ -291,4 +295,17 @@ public class AMQConnectionURL implements ConnectionURL
return sb.toString();
}
+
+ public static void main(String[] args) throws URLSyntaxException
+ {
+ String url2 =
+ "amqp://ritchiem:bob@temp/testHost?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
+ // "amqp://user:pass@clientid/virtualhost?brokerlist='tcp://host:1?option1=\'value\',option2=\'value\';vm://:3?option1=\'value\'',failover='method?option1=\'value\',option2='value''";
+
+ ConnectionURL connectionurl2 = new AMQConnectionURL(url2);
+
+ System.out.println(url2);
+ System.out.println(connectionurl2);
+
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
index acd46da11a..eb9682a3cf 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
@@ -21,6 +21,8 @@
package org.apache.qpid.client;
import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import javax.jms.Destination;
@@ -32,6 +34,8 @@ import javax.naming.StringRefAddr;
import org.apache.qpid.client.messaging.address.AddressHelper;
import org.apache.qpid.client.messaging.address.Link;
import org.apache.qpid.client.messaging.address.Node;
+import org.apache.qpid.client.messaging.address.QpidExchangeOptions;
+import org.apache.qpid.client.messaging.address.QpidQueueOptions;
import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
@@ -74,6 +78,11 @@ public abstract class AMQDestination implements Destination, Referenceable
private boolean _exchangeExistsChecked;
+ private byte[] _byteEncoding;
+ private static final int IS_DURABLE_MASK = 0x1;
+ private static final int IS_EXCLUSIVE_MASK = 0x2;
+ private static final int IS_AUTODELETE_MASK = 0x4;
+
public static final int QUEUE_TYPE = 1;
public static final int TOPIC_TYPE = 2;
public static final int UNKNOWN_TYPE = 3;
@@ -314,11 +323,7 @@ public abstract class AMQDestination implements Destination, Referenceable
{
if(_urlAsShortString == null)
{
- if (_url == null)
- {
- toURL();
- }
- _urlAsShortString = new AMQShortString(_url);
+ toURL();
}
return _urlAsShortString;
}
@@ -365,6 +370,7 @@ public abstract class AMQDestination implements Destination, Referenceable
// calculated URL now out of date
_url = null;
_urlAsShortString = null;
+ _byteEncoding = null;
}
public AMQShortString getRoutingKey()
@@ -502,10 +508,59 @@ public abstract class AMQDestination implements Destination, Referenceable
sb.deleteCharAt(sb.length() - 1);
url = sb.toString();
_url = url;
+ _urlAsShortString = new AMQShortString(url);
}
return url;
}
+ public byte[] toByteEncoding()
+ {
+ byte[] encoding = _byteEncoding;
+ if(encoding == null)
+ {
+ int size = _exchangeClass.length() + 1 +
+ _exchangeName.length() + 1 +
+ 0 + // in place of the destination name
+ (_queueName == null ? 0 : _queueName.length()) + 1 +
+ 1;
+ encoding = new byte[size];
+ int pos = 0;
+
+ pos = _exchangeClass.writeToByteArray(encoding, pos);
+ pos = _exchangeName.writeToByteArray(encoding, pos);
+
+ encoding[pos++] = (byte)0;
+
+ if(_queueName == null)
+ {
+ encoding[pos++] = (byte)0;
+ }
+ else
+ {
+ pos = _queueName.writeToByteArray(encoding,pos);
+ }
+ byte options = 0;
+ if(_isDurable)
+ {
+ options |= IS_DURABLE_MASK;
+ }
+ if(_isExclusive)
+ {
+ options |= IS_EXCLUSIVE_MASK;
+ }
+ if(_isAutoDelete)
+ {
+ options |= IS_AUTODELETE_MASK;
+ }
+ encoding[pos] = options;
+
+
+ _byteEncoding = encoding;
+
+ }
+ return encoding;
+ }
+
public boolean equals(Object o)
{
if (this == o)
@@ -559,6 +614,53 @@ public abstract class AMQDestination implements Destination, Referenceable
null); // factory location
}
+
+ public static Destination createDestination(byte[] byteEncodedDestination)
+ {
+ AMQShortString exchangeClass;
+ AMQShortString exchangeName;
+ AMQShortString routingKey;
+ AMQShortString queueName;
+ boolean isDurable;
+ boolean isExclusive;
+ boolean isAutoDelete;
+
+ int pos = 0;
+ exchangeClass = AMQShortString.readFromByteArray(byteEncodedDestination, pos);
+ pos+= exchangeClass.length() + 1;
+ exchangeName = AMQShortString.readFromByteArray(byteEncodedDestination, pos);
+ pos+= exchangeName.length() + 1;
+ routingKey = AMQShortString.readFromByteArray(byteEncodedDestination, pos);
+ pos+= (routingKey == null ? 0 : routingKey.length()) + 1;
+ queueName = AMQShortString.readFromByteArray(byteEncodedDestination, pos);
+ pos+= (queueName == null ? 0 : queueName.length()) + 1;
+ int options = byteEncodedDestination[pos];
+ isDurable = (options & IS_DURABLE_MASK) != 0;
+ isExclusive = (options & IS_EXCLUSIVE_MASK) != 0;
+ isAutoDelete = (options & IS_AUTODELETE_MASK) != 0;
+
+ if (exchangeClass.equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))
+ {
+ return new AMQQueue(exchangeName,routingKey,queueName,isExclusive,isAutoDelete,isDurable);
+ }
+ else if (exchangeClass.equals(ExchangeDefaults.TOPIC_EXCHANGE_CLASS))
+ {
+ return new AMQTopic(exchangeName,routingKey,isAutoDelete,queueName,isDurable);
+ }
+ else if (exchangeClass.equals(ExchangeDefaults.HEADERS_EXCHANGE_CLASS))
+ {
+ return new AMQHeadersExchange(routingKey);
+ }
+ else
+ {
+ return new AMQAnyDestination(exchangeName,exchangeClass,
+ routingKey,isExclusive,
+ isAutoDelete,queueName,
+ isDurable, new AMQShortString[0]);
+ }
+
+ }
+
public static Destination createDestination(BindingURL binding)
{
AMQShortString type = binding.getExchangeClass();
@@ -793,7 +895,7 @@ public abstract class AMQDestination implements Destination, Referenceable
return _browseOnly;
}
- private void setBrowseOnly(boolean b)
+ public void setBrowseOnly(boolean b)
{
_browseOnly = b;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index d34290e007..1f940b62f0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -70,6 +70,7 @@ import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.AMQInvalidRoutingKeyException;
+import org.apache.qpid.client.AMQDestination.AddressOption;
import org.apache.qpid.client.AMQDestination.DestSyntax;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverNoopSupport;
@@ -87,6 +88,8 @@ import org.apache.qpid.client.message.JMSTextMessage;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import org.apache.qpid.client.message.UnprocessedMessage;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.util.FlowControllingBlockingQueue;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
@@ -94,10 +97,7 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.thread.Threading;
-import org.apache.qpid.transport.SessionException;
-import org.apache.qpid.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -213,6 +213,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
*/
protected final boolean DEFAULT_MANDATORY = Boolean.parseBoolean(System.getProperty("qpid.default_mandatory", "true"));
+ protected final boolean DEFAULT_WAIT_ON_SEND = Boolean.parseBoolean(System.getProperty("qpid.default_wait_on_send", "false"));
+
/**
* The period to wait while flow controlled before sending a log message confirming that the session is still
* waiting on flow control being revoked
@@ -308,7 +310,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
protected final FlowControllingBlockingQueue _queue;
/** Holds the highest received delivery tag. */
- protected final AtomicLong _highestDeliveryTag = new AtomicLong(-1);
+ private final AtomicLong _highestDeliveryTag = new AtomicLong(-1);
private final AtomicLong _rollbackMark = new AtomicLong(-1);
/** All the not yet acknowledged message tags */
@@ -362,13 +364,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
* Set when recover is called. This is to handle the case where recover() is called by application code during
* onMessage() processing to ensure that an auto ack is not sent.
*/
- private volatile boolean _sessionInRecovery;
-
- /**
- * Set when the dispatcher should direct incoming messages straight into the UnackedMessage list instead of
- * to the syncRecieveQueue or MessageListener. Used during cleanup, e.g. in Session.recover().
- */
- private volatile boolean _usingDispatcherForCleanup;
+ private boolean _inRecovery;
/** Used to indicates that the connection to which this session belongs, has been stopped. */
private boolean _connectionStopped;
@@ -571,8 +567,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
close(-1);
}
- public abstract AMQException getLastException();
-
public void checkNotClosed() throws JMSException
{
try
@@ -581,20 +575,16 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}
catch (IllegalStateException ise)
{
- AMQException ex = getLastException();
- if (ex != null)
- {
- IllegalStateException ssnClosed = new IllegalStateException(
- "Session has been closed", ex.getErrorCode().toString());
+ // if the Connection has closed then we should throw any exception that has occurred that we were not waiting for
+ AMQStateManager manager = _connection.getProtocolHandler().getStateManager();
- ssnClosed.setLinkedException(ex);
- ssnClosed.initCause(ex);
- throw ssnClosed;
- }
- else
+ if (manager.getCurrentState().equals(AMQState.CONNECTION_CLOSED) && manager.getLastException() != null)
{
- throw ise;
+ ise.setLinkedException(manager.getLastException());
+ ise.initCause(ise.getLinkedException());
}
+
+ throw ise;
}
}
@@ -610,36 +600,29 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
* Acknowledges all unacknowledged messages on the session, for all message consumers on the session.
*
* @throws IllegalStateException If the session is closed.
- * @throws JMSException if there is a problem during acknowledge process.
*/
- public void acknowledge() throws IllegalStateException, JMSException
+ public void acknowledge() throws IllegalStateException
{
if (isClosed())
{
throw new IllegalStateException("Session is already closed");
}
- else if (hasFailedOverDirty())
+ else if (hasFailedOver())
{
- //perform an implicit recover in this scenario
- recover();
-
- //notify the consumer
throw new IllegalStateException("has failed over");
}
- try
- {
- acknowledgeImpl();
- markClean();
- }
- catch (TransportException e)
+ while (true)
{
- throw toJMSException("Exception while acknowledging message(s):" + e.getMessage(), e);
+ Long tag = _unacknowledgedMessageTags.poll();
+ if (tag == null)
+ {
+ break;
+ }
+ acknowledgeMessage(tag, false);
}
}
- protected abstract void acknowledgeImpl() throws JMSException;
-
/**
* Acknowledge one or many messages.
*
@@ -774,10 +757,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
_logger.debug(
"Got FailoverException during channel close, ignored as channel already marked as closed.");
}
- catch (TransportException e)
- {
- throw toJMSException("Error closing session:" + e.getMessage(), e);
- }
finally
{
_connection.deregisterSession(_channelId);
@@ -848,44 +827,51 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
* @throws JMSException If the JMS provider fails to commit the transaction due to some internal error. This does
* not mean that the commit is known to have failed, merely that it is not known whether it
* failed or not.
+ * @todo Be aware of possible changes to parameter order as versions change.
*/
public void commit() throws JMSException
{
checkTransacted();
- //Check that we are clean to commit.
- if (_failedOverDirty)
+ try
{
- if (_logger.isDebugEnabled())
+ //Check that we are clean to commit.
+ if (_failedOverDirty)
{
- _logger.debug("Session " + _channelId + " was dirty whilst failing over. Rolling back.");
+ rollback();
+
+ throw new TransactionRolledBackException("Connection failover has occured since last send. " +
+ "Forced rollback");
}
- rollback();
- throw new TransactionRolledBackException("Connection failover has occured with uncommitted transaction activity." +
- "The session transaction was rolled back.");
- }
- try
- {
- commitImpl();
+ // Acknowledge all delivered messages
+ while (true)
+ {
+ Long tag = _deliveredMessageTags.poll();
+ if (tag == null)
+ {
+ break;
+ }
+
+ acknowledgeMessage(tag, false);
+ }
+ // Commits outstanding messages and acknowledgments
+ sendCommit();
markClean();
}
catch (AMQException e)
{
- throw new JMSAMQException("Exception during commit: " + e.getMessage() + ":" + e.getCause(), e);
+ throw new JMSAMQException("Failed to commit: " + e.getMessage() + ":" + e.getCause(), e);
}
catch (FailoverException e)
{
throw new JMSAMQException("Fail-over interrupted commit. Status of the commit is uncertain.", e);
}
- catch(TransportException e)
- {
- throw toJMSException("Session exception occured while trying to commit: " + e.getMessage(), e);
- }
}
- protected abstract void commitImpl() throws AMQException, FailoverException, TransportException;
+ public abstract void sendCommit() throws AMQException, FailoverException;
+
public void confirmConsumerCancelled(int consumerTag)
{
@@ -963,7 +949,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
return new AMQQueueBrowser(this, (AMQQueue) queue, messageSelector);
}
- protected MessageConsumer createBrowserConsumer(Destination destination, String messageSelector, boolean noLocal)
+ public MessageConsumer createBrowserConsumer(Destination destination, String messageSelector, boolean noLocal)
throws JMSException
{
checkValidDestination(destination);
@@ -977,7 +963,15 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
checkValidDestination(destination);
return createConsumerImpl(destination, _prefetchHighMark, _prefetchLowMark, false, (destination instanceof Topic), null, null,
- isBrowseOnlyDestination(destination), false);
+ ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
+ }
+
+ public C createExclusiveConsumer(Destination destination) throws JMSException
+ {
+ checkValidDestination(destination);
+
+ return createConsumerImpl(destination, _prefetchHighMark, _prefetchLowMark, false, true, null, null,
+ ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
}
public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException
@@ -985,7 +979,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
checkValidDestination(destination);
return createConsumerImpl(destination, _prefetchHighMark, _prefetchLowMark, false, (destination instanceof Topic),
- messageSelector, null, isBrowseOnlyDestination(destination), false);
+ messageSelector, null, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
}
public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal)
@@ -994,7 +988,16 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
checkValidDestination(destination);
return createConsumerImpl(destination, _prefetchHighMark, _prefetchLowMark, noLocal, (destination instanceof Topic),
- messageSelector, null, isBrowseOnlyDestination(destination), false);
+ messageSelector, null, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
+ }
+
+ public MessageConsumer createExclusiveConsumer(Destination destination, String messageSelector, boolean noLocal)
+ throws JMSException
+ {
+ checkValidDestination(destination);
+
+ return createConsumerImpl(destination, _prefetchHighMark, _prefetchLowMark, noLocal, true,
+ messageSelector, null, false, false);
}
public MessageConsumer createConsumer(Destination destination, int prefetch, boolean noLocal, boolean exclusive,
@@ -1002,15 +1005,23 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
checkValidDestination(destination);
- return createConsumerImpl(destination, prefetch, prefetch / 2, noLocal, exclusive, selector, null, isBrowseOnlyDestination(destination), false);
+ return createConsumerImpl(destination, prefetch, prefetch / 2, noLocal, exclusive, selector, null, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
}
public MessageConsumer createConsumer(Destination destination, int prefetchHigh, int prefetchLow, boolean noLocal,
- boolean exclusive, String selector) throws JMSException
+ boolean exclusive, String selector) throws JMSException
{
checkValidDestination(destination);
- return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, null, isBrowseOnlyDestination(destination), false);
+ return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, null, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
+ }
+
+ public MessageConsumer createConsumer(Destination destination, int prefetch, boolean noLocal, boolean exclusive,
+ String selector, FieldTable rawSelector) throws JMSException
+ {
+ checkValidDestination(destination);
+
+ return createConsumerImpl(destination, prefetch, prefetch / 2, noLocal, exclusive, selector, rawSelector, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()), false);
}
public MessageConsumer createConsumer(Destination destination, int prefetchHigh, int prefetchLow, boolean noLocal,
@@ -1018,7 +1029,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
checkValidDestination(destination);
- return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, rawSelector, isBrowseOnlyDestination(destination),
+ return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, rawSelector, ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly()),
false);
}
@@ -1032,33 +1043,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
throws JMSException
{
checkNotClosed();
- Topic origTopic = checkValidTopic(topic, true);
-
+ AMQTopic origTopic = checkValidTopic(topic, true);
AMQTopic dest = AMQTopic.createDurableTopic(origTopic, name, _connection);
- if (dest.getDestSyntax() == DestSyntax.ADDR &&
- !dest.isAddressResolved())
- {
- try
- {
- handleAddressBasedDestination(dest,false,true);
- if (dest.getAddressType() != AMQDestination.TOPIC_TYPE)
- {
- throw new JMSException("Durable subscribers can only be created for Topics");
- }
- dest.getSourceNode().setDurable(true);
- }
- catch(AMQException e)
- {
- JMSException ex = new JMSException("Error when verifying destination");
- ex.initCause(e);
- ex.setLinkedException(e);
- throw ex;
- }
- catch(TransportException e)
- {
- throw toJMSException("Error when verifying destination", e);
- }
- }
String messageSelector = ((selector == null) || (selector.trim().length() == 0)) ? null : selector;
@@ -1070,9 +1056,15 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
// Not subscribed to this name in the current session
if (subscriber == null)
{
- // After the address is resolved routing key will not be null.
- AMQShortString topicName = dest.getRoutingKey();
-
+ AMQShortString topicName;
+ if (topic instanceof AMQTopic)
+ {
+ topicName = ((AMQTopic) topic).getRoutingKey();
+ } else
+ {
+ topicName = new AMQShortString(topic.getTopicName());
+ }
+
if (_strictAMQP)
{
if (_strictAMQPFATAL)
@@ -1143,10 +1135,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
return subscriber;
}
- catch (TransportException e)
- {
- throw toJMSException("Exception while creating durable subscriber:" + e.getMessage(), e);
- }
finally
{
_subscriberDetails.unlock();
@@ -1207,6 +1195,12 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
return createProducerImpl(destination, mandatory, immediate);
}
+ public P createProducer(Destination destination, boolean mandatory, boolean immediate,
+ boolean waitUntilSent) throws JMSException
+ {
+ return createProducerImpl(destination, mandatory, immediate, waitUntilSent);
+ }
+
public TopicPublisher createPublisher(Topic topic) throws JMSException
{
checkNotClosed();
@@ -1231,6 +1225,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
else
{
AMQQueue queue = new AMQQueue(queueName);
+ queue.setCreate(AddressOption.ALWAYS);
return queue;
}
@@ -1312,8 +1307,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public QueueReceiver createQueueReceiver(Destination destination) throws JMSException
{
checkValidDestination(destination);
- Queue dest = validateQueue(destination);
- C consumer = (C) createConsumer(dest);
+ AMQQueue dest = (AMQQueue) destination;
+ C consumer = (C) createConsumer(destination);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1331,8 +1326,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public QueueReceiver createQueueReceiver(Destination destination, String messageSelector) throws JMSException
{
checkValidDestination(destination);
- Queue dest = validateQueue(destination);
- C consumer = (C) createConsumer(dest, messageSelector);
+ AMQQueue dest = (AMQQueue) destination;
+ C consumer = (C) createConsumer(destination, messageSelector);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1349,7 +1344,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public QueueReceiver createReceiver(Queue queue) throws JMSException
{
checkNotClosed();
- Queue dest = validateQueue(queue);
+ AMQQueue dest = (AMQQueue) queue;
C consumer = (C) createConsumer(dest);
return new QueueReceiverAdaptor(dest, consumer);
@@ -1368,28 +1363,17 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public QueueReceiver createReceiver(Queue queue, String messageSelector) throws JMSException
{
checkNotClosed();
- Queue dest = validateQueue(queue);
+ AMQQueue dest = (AMQQueue) queue;
C consumer = (C) createConsumer(dest, messageSelector);
return new QueueReceiverAdaptor(dest, consumer);
}
-
- private Queue validateQueue(Destination dest) throws InvalidDestinationException
- {
- if (dest instanceof AMQDestination && dest instanceof javax.jms.Queue)
- {
- return (Queue)dest;
- }
- else
- {
- throw new InvalidDestinationException("The destination object used is not from this provider or of type javax.jms.Queue");
- }
- }
public QueueSender createSender(Queue queue) throws JMSException
{
checkNotClosed();
+ // return (QueueSender) createProducer(queue);
return new QueueSenderAdapter(createProducer(queue), queue);
}
@@ -1424,10 +1408,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public TopicSubscriber createSubscriber(Topic topic) throws JMSException
{
checkNotClosed();
- checkValidTopic(topic);
+ AMQTopic dest = checkValidTopic(topic);
- return new TopicSubscriberAdaptor<C>(topic,
- createConsumerImpl(topic, _prefetchHighMark, _prefetchLowMark, false, true, null, null, false, false));
+ // AMQTopic dest = new AMQTopic(topic.getTopicName());
+ return new TopicSubscriberAdaptor(dest, (C) createExclusiveConsumer(dest));
}
/**
@@ -1444,11 +1428,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public TopicSubscriber createSubscriber(Topic topic, String messageSelector, boolean noLocal) throws JMSException
{
checkNotClosed();
- checkValidTopic(topic);
+ AMQTopic dest = checkValidTopic(topic);
- return new TopicSubscriberAdaptor<C>(topic,
- createConsumerImpl(topic, _prefetchHighMark, _prefetchLowMark, noLocal,
- true, messageSelector, null, false, false));
+ // AMQTopic dest = new AMQTopic(topic.getTopicName());
+ return new TopicSubscriberAdaptor(dest, (C) createExclusiveConsumer(dest, messageSelector, noLocal));
}
public TemporaryQueue createTemporaryQueue() throws JMSException
@@ -1550,8 +1533,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
abstract public void sync() throws AMQException;
- public int getAcknowledgeMode()
+ public int getAcknowledgeMode() throws JMSException
{
+ checkNotClosed();
+
return _acknowledgeMode;
}
@@ -1611,8 +1596,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
return _ticket;
}
- public boolean getTransacted()
+ public boolean getTransacted() throws JMSException
{
+ checkNotClosed();
+
return _transacted;
}
@@ -1708,14 +1695,13 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
// Ensure that the session is not transacted.
checkNotTransacted();
-
+ // flush any acks we are holding in the buffer.
+ flushAcknowledgments();
+
+ // this is set only here, and the before the consumer's onMessage is called it is set to false
+ _inRecovery = true;
try
{
- // flush any acks we are holding in the buffer.
- flushAcknowledgments();
-
- // this is only set true here, and only set false when the consumers preDeliver method is called
- _sessionInRecovery = true;
boolean isSuspended = isSuspended();
@@ -1723,18 +1709,9 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
suspendChannel(true);
}
-
- // Set to true to short circuit delivery of anything currently
- //in the pre-dispatch queue.
- _usingDispatcherForCleanup = true;
-
+
syncDispatchQueue();
-
- // Set to false before sending the recover as 0-8/9/9-1 will
- //send messages back before the recover completes, and we
- //probably shouldn't clean those! ;-)
- _usingDispatcherForCleanup = false;
-
+
if (_dispatcher != null)
{
_dispatcher.recover();
@@ -1743,7 +1720,10 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
sendRecover();
markClean();
-
+
+ // Set inRecovery to false before you start message flow again again.
+ _inRecovery = false;
+
if (!isSuspended)
{
suspendChannel(false);
@@ -1757,10 +1737,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
throw new JMSAMQException("Recovery was interrupted by fail-over. Recovery status is not known.", e);
}
- catch(TransportException e)
- {
- throw toJMSException("Recover failed: " + e.getMessage(), e);
- }
+
}
protected abstract void sendRecover() throws AMQException, FailoverException;
@@ -1818,7 +1795,9 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
suspendChannel(true);
}
- setRollbackMark();
+ // Let the dispatcher know that all the incomming messages
+ // should be rolled back(reject/release)
+ _rollbackMark.set(_highestDeliveryTag.get());
syncDispatchQueue();
@@ -1843,10 +1822,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
throw new JMSAMQException("Fail-over interrupted rollback. Status of the rollback is uncertain.", e);
}
- catch (TransportException e)
- {
- throw toJMSException("Failure to rollback:" + e.getMessage(), e);
- }
}
}
@@ -1893,14 +1868,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
*/
public void unsubscribe(String name) throws JMSException
{
- try
- {
- unsubscribe(name, false);
- }
- catch (TransportException e)
- {
- throw toJMSException("Exception while unsubscribing:" + e.getMessage(), e);
- }
+ unsubscribe(name, false);
}
/**
@@ -1977,12 +1945,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
checkTemporaryDestination(destination);
- if(!noConsume && isBrowseOnlyDestination(destination))
- {
- throw new InvalidDestinationException("The consumer being created is not 'noConsume'," +
- "but a 'browseOnly' Destination has been supplied.");
- }
-
final String messageSelector;
if (_strictAMQP && !((selector == null) || selector.equals("")))
@@ -2027,16 +1989,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
// argument, as specifying null for the arguments when querying means they should not be checked at all
ft.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), messageSelector == null ? "" : messageSelector);
- C consumer;
- try
- {
- consumer = createMessageConsumer(amqd, prefetchHigh, prefetchLow,
- noLocal, exclusive, messageSelector, ft, noConsume, autoClose);
- }
- catch(TransportException e)
- {
- throw toJMSException("Exception while creating consumer: " + e.getMessage(), e);
- }
+ C consumer = createMessageConsumer(amqd, prefetchHigh, prefetchLow,
+ noLocal, exclusive, messageSelector, ft, noConsume, autoClose);
if (_messageListener != null)
{
@@ -2073,10 +2027,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
ex.initCause(e);
throw ex;
}
- catch (TransportException e)
- {
- throw toJMSException("Exception while registering consumer:" + e.getMessage(), e);
- }
+
return consumer;
}
}, _connection).execute();
@@ -2141,7 +2092,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
boolean isInRecovery()
{
- return _sessionInRecovery;
+ return _inRecovery;
}
boolean isQueueBound(AMQShortString exchangeName, AMQShortString queueName) throws JMSException
@@ -2263,7 +2214,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
void setInRecovery(boolean inRecovery)
{
- _sessionInRecovery = inRecovery;
+ _inRecovery = inRecovery;
}
boolean isStarted()
@@ -2444,7 +2395,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
/*
* I could have combined the last 3 methods, but this way it improves readability
*/
- protected Topic checkValidTopic(Topic topic, boolean durable) throws JMSException
+ protected AMQTopic checkValidTopic(Topic topic, boolean durable) throws JMSException
{
if (topic == null)
{
@@ -2463,17 +2414,17 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
("Cannot create a durable subscription with a temporary topic: " + topic);
}
- if (!(topic instanceof AMQDestination && topic instanceof javax.jms.Topic))
+ if (!(topic instanceof AMQTopic))
{
throw new javax.jms.InvalidDestinationException(
"Cannot create a subscription on topic created for another JMS Provider, class of topic provided is: "
+ topic.getClass().getName());
}
- return topic;
+ return (AMQTopic) topic;
}
- protected Topic checkValidTopic(Topic topic) throws JMSException
+ protected AMQTopic checkValidTopic(Topic topic) throws JMSException
{
return checkValidTopic(topic, false);
}
@@ -2602,9 +2553,15 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
public abstract void sendConsume(C consumer, AMQShortString queueName,
AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector, int tag) throws AMQException, FailoverException;
- private P createProducerImpl(final Destination destination, final boolean mandatory, final boolean immediate)
+ private P createProducerImpl(Destination destination, boolean mandatory, boolean immediate)
throws JMSException
{
+ return createProducerImpl(destination, mandatory, immediate, DEFAULT_WAIT_ON_SEND);
+ }
+
+ private P createProducerImpl(final Destination destination, final boolean mandatory,
+ final boolean immediate, final boolean waitUntilSent) throws JMSException
+ {
return new FailoverRetrySupport<P, JMSException>(
new FailoverProtectedOperation<P, JMSException>()
{
@@ -2612,18 +2569,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
checkNotClosed();
long producerId = getNextProducerId();
-
- P producer;
- try
- {
- producer = createMessageProducer(destination, mandatory,
- immediate, producerId);
- }
- catch (TransportException e)
- {
- throw toJMSException("Exception while creating producer:" + e.getMessage(), e);
- }
-
+ P producer = createMessageProducer(destination, mandatory,
+ immediate, waitUntilSent, producerId);
registerProducer(producerId, producer);
return producer;
@@ -2632,7 +2579,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}
public abstract P createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, final long producerId) throws JMSException;
+ final boolean immediate, final boolean waitUntilSent, long producerId) throws JMSException;
private void declareExchange(AMQDestination amqd, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException
{
@@ -2775,21 +2722,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
}
}
- /**
- * Undeclares the specified temporary queue/topic.
- *
- * <p/>Note that this operation automatically retries in the event of fail-over.
- *
- * @param amqQueue The name of the temporary destination to delete.
- *
- * @throws JMSException If the queue could not be deleted for any reason.
- * @todo Be aware of possible changes to parameter order as versions change.
- */
- protected void deleteTemporaryDestination(final TemporaryDestination amqQueue) throws JMSException
- {
- deleteQueue(amqQueue.getAMQQueueName());
- }
-
public abstract void sendQueueDelete(final AMQShortString queueName) throws AMQException, FailoverException;
private long getNextProducerId()
@@ -2887,7 +2819,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
declareQueue(amqd, protocolHandler, consumer.isNoLocal(), nowait);
}
- bindQueue(amqd.getAMQQueueName(), amqd.getRoutingKey(), consumer.getArguments(), amqd.getExchangeName(), amqd, nowait);
}
AMQShortString queueName = amqd.getAMQQueueName();
@@ -2895,6 +2826,8 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
// store the consumer queue name
consumer.setQueuename(queueName);
+ bindQueue(queueName, amqd.getRoutingKey(), consumer.getArguments(), amqd.getExchangeName(), amqd, nowait);
+
// If IMMEDIATE_PREFETCH is not required then suspsend the channel to delay prefetch
if (!_immediatePrefetch)
{
@@ -3045,10 +2978,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
throw new AMQException(null, "Fail-over interrupted suspend/unsuspend channel.", e);
}
- catch (TransportException e)
- {
- throw new AMQException(AMQConstant.getConstant(getErrorCode(e)), e.getMessage(), e);
- }
}
}
@@ -3087,11 +3016,21 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
*
* @return boolean true if failover has occured.
*/
- public boolean hasFailedOverDirty()
+ public boolean hasFailedOver()
{
return _failedOverDirty;
}
+ /**
+ * Check to see if any message have been sent in this transaction and have not been commited.
+ *
+ * @return boolean true if a message has been sent but not commited
+ */
+ public boolean isDirty()
+ {
+ return _dirty;
+ }
+
public void setTicket(int ticket)
{
_ticket = ticket;
@@ -3204,7 +3143,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
setConnectionStopped(true);
}
- setRollbackMark();
+ _rollbackMark.set(_highestDeliveryTag.get());
_dispatcherLogger.debug("Session Pre Dispatch Queue cleared");
@@ -3353,14 +3292,9 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
if (!(message instanceof CloseConsumerMessage)
&& tagLE(deliveryTag, _rollbackMark.get()))
{
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Rejecting message because delivery tag " + deliveryTag
- + " <= rollback mark " + _rollbackMark.get());
- }
rejectMessage(message, true);
}
- else if (_usingDispatcherForCleanup)
+ else if (isInRecovery())
{
_unacknowledgedMessageTags.add(deliveryTag);
}
@@ -3419,11 +3353,6 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
// Don't reject if we're already closing
if (!_closed.get())
{
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Rejecting message with delivery tag " + message.getDeliveryTag()
- + " for closing consumer " + String.valueOf(consumer == null? null: consumer._consumerTag));
- }
rejectMessage(message, true);
}
}
@@ -3521,48 +3450,4 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic
{
return _closing.get()|| _connection.isClosing();
}
-
- public boolean isDeclareExchanges()
- {
- return DECLARE_EXCHANGES;
- }
-
- JMSException toJMSException(String message, TransportException e)
- {
- int code = getErrorCode(e);
- JMSException jmse = new JMSException(message, Integer.toString(code));
- jmse.setLinkedException(e);
- jmse.initCause(e);
- return jmse;
- }
-
- private int getErrorCode(TransportException e)
- {
- int code = AMQConstant.INTERNAL_ERROR.getCode();
- if (e instanceof SessionException)
- {
- SessionException se = (SessionException) e;
- if(se.getException() != null && se.getException().getErrorCode() != null)
- {
- code = se.getException().getErrorCode().getValue();
- }
- }
- return code;
- }
-
- private boolean isBrowseOnlyDestination(Destination destination)
- {
- return ((destination instanceof AMQDestination) && ((AMQDestination)destination).isBrowseOnly());
- }
-
- private void setRollbackMark()
- {
- // Let the dispatcher know that all the incomming messages
- // should be rolled back(reject/release)
- _rollbackMark.set(_highestDeliveryTag.get());
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Rollback mark is set to " + _rollbackMark.get());
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
index c6a64ec894..517a7a5ce8 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
@@ -47,8 +47,6 @@ import org.apache.qpid.client.message.AMQMessageDelegateFactory;
import org.apache.qpid.client.message.FieldTableSupport;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import org.apache.qpid.client.message.UnprocessedMessage_0_10;
-import org.apache.qpid.client.messaging.address.Link;
-import org.apache.qpid.client.messaging.address.Link.Reliability;
import org.apache.qpid.client.messaging.address.Node.ExchangeNode;
import org.apache.qpid.client.messaging.address.Node.QueueNode;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
@@ -58,7 +56,6 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.transport.ExchangeBoundResult;
import org.apache.qpid.transport.ExchangeQueryResult;
-import org.apache.qpid.transport.ExecutionErrorCode;
import org.apache.qpid.transport.ExecutionException;
import org.apache.qpid.transport.MessageAcceptMode;
import org.apache.qpid.transport.MessageAcquireMode;
@@ -72,7 +69,6 @@ import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.Session;
import org.apache.qpid.transport.SessionException;
import org.apache.qpid.transport.SessionListener;
-import org.apache.qpid.transport.TransportException;
import org.apache.qpid.util.Serial;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -160,20 +156,13 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
*/
AMQSession_0_10(org.apache.qpid.transport.Connection qpidConnection, AMQConnection con, int channelId,
boolean transacted, int acknowledgeMode, MessageFactoryRegistry messageFactoryRegistry,
- int defaultPrefetchHighMark, int defaultPrefetchLowMark,String name)
+ int defaultPrefetchHighMark, int defaultPrefetchLowMark)
{
super(con, channelId, transacted, acknowledgeMode, messageFactoryRegistry, defaultPrefetchHighMark,
defaultPrefetchLowMark);
_qpidConnection = qpidConnection;
- if (name == null)
- {
- _qpidSession = _qpidConnection.createSession(1);
- }
- else
- {
- _qpidSession = _qpidConnection.createSession(name,1);
- }
+ _qpidSession = _qpidConnection.createSession(1);
_qpidSession.setSessionListener(this);
if (_transacted)
{
@@ -200,12 +189,11 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
* @param qpidConnection The connection
*/
AMQSession_0_10(org.apache.qpid.transport.Connection qpidConnection, AMQConnection con, int channelId,
- boolean transacted, int acknowledgeMode, int defaultPrefetchHigh, int defaultPrefetchLow,
- String name)
+ boolean transacted, int acknowledgeMode, int defaultPrefetchHigh, int defaultPrefetchLow)
{
this(qpidConnection, con, channelId, transacted, acknowledgeMode, MessageFactoryRegistry.newDefaultRegistry(),
- defaultPrefetchHigh, defaultPrefetchLow,name);
+ defaultPrefetchHigh, defaultPrefetchLow);
}
private void addUnacked(int id)
@@ -270,7 +258,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
long prefetch = getAMQConnection().getMaxPrefetch();
- if (unackedCount >= prefetch/2 || maxAckDelay <= 0 || _acknowledgeMode == javax.jms.Session.AUTO_ACKNOWLEDGE)
+ if (unackedCount >= prefetch/2 || maxAckDelay <= 0)
{
flushAcknowledgments();
}
@@ -294,34 +282,23 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
}
}
- void messageAcknowledge(final RangeSet ranges, final boolean accept)
+ void messageAcknowledge(RangeSet ranges, boolean accept)
{
messageAcknowledge(ranges,accept,false);
}
- void messageAcknowledge(final RangeSet ranges, final boolean accept, final boolean setSyncBit)
+ void messageAcknowledge(RangeSet ranges, boolean accept,boolean setSyncBit)
{
- final Session ssn = getQpidSession();
- flushProcessed(ranges,accept);
- if (accept)
+ Session ssn = getQpidSession();
+ for (Range range : ranges)
{
- ssn.messageAccept(ranges, UNRELIABLE, setSyncBit ? SYNC : NONE);
+ ssn.processed(range);
}
- }
-
- /**
- * Flush any outstanding commands. This causes session complete to be sent.
- * @param ranges the range of command ids.
- * @param batch true if batched.
- */
- void flushProcessed(final RangeSet ranges, final boolean batch)
- {
- final Session ssn = getQpidSession();
- for (final Range range : ranges)
+ ssn.flushProcessed(accept ? BATCH : NONE);
+ if (accept)
{
- ssn.processed(range);
+ ssn.messageAccept(ranges, UNRELIABLE,setSyncBit? SYNC : NONE);
}
- ssn.flushProcessed(batch ? BATCH : NONE);
}
/**
@@ -337,7 +314,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
public void sendQueueBind(final AMQShortString queueName, final AMQShortString routingKey,
final FieldTable arguments, final AMQShortString exchangeName,
final AMQDestination destination, final boolean nowait)
- throws AMQException
+ throws AMQException, FailoverException
{
if (destination.getDestSyntax() == DestSyntax.BURL)
{
@@ -423,6 +400,25 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
}
}
+
+ /**
+ * Commit the receipt and the delivery of all messages exchanged by this session resources.
+ */
+ public void sendCommit() throws AMQException, FailoverException
+ {
+ getQpidSession().setAutoSync(true);
+ try
+ {
+ getQpidSession().txCommit();
+ }
+ finally
+ {
+ getQpidSession().setAutoSync(false);
+ }
+ // We need to sync so that we get notify of an error.
+ sync();
+ }
+
/**
* Create a queue with a given name.
*
@@ -455,14 +451,6 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
public void sendRecover() throws AMQException, FailoverException
{
// release all unacked messages
- RangeSet ranges = gatherUnackedRangeSet();
- getQpidSession().messageRelease(ranges, Option.SET_REDELIVERED);
- // We need to sync so that we get notify of an error.
- sync();
- }
-
- private RangeSet gatherUnackedRangeSet()
- {
RangeSet ranges = new RangeSet();
while (true)
{
@@ -471,11 +459,11 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
{
break;
}
-
- ranges.add(tag.intValue());
+ ranges.add((int) (long) tag);
}
-
- return ranges;
+ getQpidSession().messageRelease(ranges, Option.SET_REDELIVERED);
+ // We need to sync so that we get notify of an error.
+ sync();
}
@@ -549,6 +537,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
}
public boolean isQueueBound(final String exchangeName, final String queueName, final String bindingKey,Map<String,Object> args)
+ throws JMSException
{
boolean res;
ExchangeBoundResult bindingQueryResult =
@@ -611,16 +600,10 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
(Map<? extends String, ? extends Object>) consumer.getDestination().getLink().getSubscription().getArgs());
}
- boolean acceptModeNone = getAcknowledgeMode() == NO_ACKNOWLEDGE;
-
- if (consumer.getDestination().getLink() != null)
- {
- acceptModeNone = consumer.getDestination().getLink().getReliability() == Link.Reliability.UNRELIABLE;
- }
getQpidSession().messageSubscribe
(queueName.toString(), String.valueOf(tag),
- acceptModeNone ? MessageAcceptMode.NONE : MessageAcceptMode.EXPLICIT,
+ getAcknowledgeMode() == NO_ACKNOWLEDGE ? MessageAcceptMode.NONE : MessageAcceptMode.EXPLICIT,
preAcquire ? MessageAcquireMode.PRE_ACQUIRED : MessageAcquireMode.NOT_ACQUIRED, null, 0, arguments,
consumer.isExclusive() ? Option.EXCLUSIVE : Option.NONE);
}
@@ -676,12 +659,13 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
* Create an 0_10 message producer
*/
public BasicMessageProducer_0_10 createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, final long producerId) throws JMSException
+ final boolean immediate, final boolean waitUntilSent,
+ long producerId) throws JMSException
{
try
{
return new BasicMessageProducer_0_10(_connection, (AMQDestination) destination, _transacted, _channelId, this,
- getProtocolHandler(), producerId, immediate, mandatory);
+ getProtocolHandler(), producerId, immediate, mandatory, waitUntilSent);
}
catch (AMQException e)
{
@@ -691,10 +675,6 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
throw ex;
}
- catch(TransportException e)
- {
- throw toJMSException("Exception while creating message producer:" + e.getMessage(), e);
- }
}
@@ -787,7 +767,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
else
{
QueueNode node = (QueueNode)amqd.getSourceNode();
- getQpidSession().queueDeclare(queueName.toString(), node.getAlternateExchange() ,
+ getQpidSession().queueDeclare(queueName.toString(), "" ,
node.getDeclareArgs(),
node.isAutoDelete() ? Option.AUTO_DELETE : Option.NONE,
node.isDurable() ? Option.DURABLE : Option.NONE,
@@ -924,26 +904,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
setCurrentException(exc);
}
- public void closed(Session ssn)
- {
- try
- {
- super.closed(null);
- if (flushTask != null)
- {
- flushTask.cancel();
- flushTask = null;
- }
- } catch (Exception e)
- {
- _logger.error("Error closing JMS session", e);
- }
- }
-
- public AMQException getLastException()
- {
- return getCurrentException();
- }
+ public void closed(Session ssn) {}
protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
final boolean noLocal, final boolean nowait)
@@ -997,26 +958,27 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
}
}
- public void commitImpl() throws AMQException, FailoverException, TransportException
+ @Override public void commit() throws JMSException
{
- if( _txSize > 0 )
+ checkTransacted();
+ try
{
- messageAcknowledge(_txRangeSet, true);
- _txRangeSet.clear();
- _txSize = 0;
+ if( _txSize > 0 )
+ {
+ messageAcknowledge(_txRangeSet, true);
+ _txRangeSet.clear();
+ _txSize = 0;
+ }
+ sendCommit();
}
-
- getQpidSession().setAutoSync(true);
- try
+ catch (AMQException e)
{
- getQpidSession().txCommit();
+ throw new JMSAMQException("Failed to commit: " + e.getMessage(), e);
}
- finally
+ catch (FailoverException e)
{
- getQpidSession().setAutoSync(false);
+ throw new JMSAMQException("Fail-over interrupted commit. Status of the commit is uncertain.", e);
}
- // We need to sync so that we get notify of an error.
- sync();
}
protected final boolean tagLE(long tag1, long tag2)
@@ -1058,9 +1020,11 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
code = ee.getErrorCode().getValue();
}
AMQException amqe = new AMQException(AMQConstant.getConstant(code), se.getMessage(), se.getCause());
+
+ _connection.exceptionReceived(amqe);
+
_currentException = amqe;
}
- _connection.exceptionReceived(_currentException);
}
public AMQMessageDelegateFactory getMessageDelegateFactory()
@@ -1104,37 +1068,22 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
return match;
}
- public boolean isQueueExist(AMQDestination dest,QueueNode node,boolean assertNode) throws AMQException
+ public boolean isQueueExist(AMQDestination dest,QueueNode node,boolean assertNode)
{
boolean match = true;
- try
+ QueueQueryResult result = getQpidSession().queueQuery(dest.getAddressName(), Option.NONE).get();
+ match = dest.getAddressName().equals(result.getQueue());
+
+ if (match && assertNode)
{
- QueueQueryResult result = getQpidSession().queueQuery(dest.getAddressName(), Option.NONE).get();
- match = dest.getAddressName().equals(result.getQueue());
-
- if (match && assertNode)
- {
- match = (result.getDurable() == node.isDurable()) &&
- (result.getAutoDelete() == node.isAutoDelete()) &&
- (result.getExclusive() == node.isExclusive()) &&
- (matchProps(result.getArguments(),node.getDeclareArgs()));
- }
- else if (match)
- {
- // should I use the queried details to update the local data structure.
- }
+ match = (result.getDurable() == node.isDurable()) &&
+ (result.getAutoDelete() == node.isAutoDelete()) &&
+ (result.getExclusive() == node.isExclusive()) &&
+ (matchProps(result.getArguments(),node.getDeclareArgs()));
}
- catch(SessionException e)
+ else if (match)
{
- if (e.getException().getErrorCode() == ExecutionErrorCode.RESOURCE_DELETED)
- {
- match = false;
- }
- else
- {
- throw new AMQException(AMQConstant.getConstant(e.getException().getErrorCode().getValue()),
- "Error querying queue",e);
- }
+ // should I use the queried details to update the local data structure.
}
return match;
@@ -1200,22 +1149,6 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
int type = resolveAddressType(dest);
- if (type == AMQDestination.QUEUE_TYPE &&
- dest.getLink().getReliability() == Reliability.UNSPECIFIED)
- {
- dest.getLink().setReliability(Reliability.AT_LEAST_ONCE);
- }
- else if (type == AMQDestination.TOPIC_TYPE &&
- dest.getLink().getReliability() == Reliability.UNSPECIFIED)
- {
- dest.getLink().setReliability(Reliability.UNRELIABLE);
- }
- else if (type == AMQDestination.TOPIC_TYPE &&
- dest.getLink().getReliability() == Reliability.AT_LEAST_ONCE)
- {
- throw new AMQException("AT-LEAST-ONCE is not yet supported for Topics");
- }
-
switch (type)
{
case AMQDestination.QUEUE_TYPE:
@@ -1229,8 +1162,6 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
{
setLegacyFiledsForQueueType(dest);
send0_10QueueDeclare(dest,null,false,noWait);
- sendQueueBind(dest.getAMQQueueName(), dest.getRoutingKey(),
- null,dest.getExchangeName(),dest, false);
break;
}
}
@@ -1339,8 +1270,6 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
dest.getQueueName(),// should have one by now
dest.getSubject(),
Collections.<String,Object>emptyMap()));
- sendQueueBind(dest.getAMQQueueName(), dest.getRoutingKey(),
- null,dest.getExchangeName(),dest, false);
}
public void setLegacyFiledsForQueueType(AMQDestination dest)
@@ -1378,26 +1307,5 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic
sb.append(">");
return sb.toString();
}
-
- protected void acknowledgeImpl()
- {
- RangeSet range = gatherUnackedRangeSet();
-
- if(range.size() > 0 )
- {
- messageAcknowledge(range, true);
- getQpidSession().sync();
- }
- }
-
- @Override
- void resubscribe() throws AMQException
- {
- // Also reset the delivery tag tracker, to insure we dont
- // return the first <total number of msgs received on session>
- // messages sent by the brokers following the first rollback
- // after failover
- _highestDeliveryTag.set(-1);
- super.resubscribe();
- }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
index 369c8a6e9d..f41b1c94fa 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
@@ -38,7 +38,6 @@ import org.apache.qpid.client.message.ReturnMessage;
import org.apache.qpid.client.message.UnprocessedMessage;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.listener.SpecificMethodFrameListener;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQFrame;
@@ -76,12 +75,12 @@ import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91;
import org.apache.qpid.jms.Session;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
-import org.apache.qpid.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8>
{
+
/** Used for debugging. */
private static final Logger _logger = LoggerFactory.getLogger(AMQSession.class);
@@ -91,7 +90,7 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
* @param con The connection on which to create the session.
* @param channelId The unique identifier for the session.
* @param transacted Indicates whether or not the session is transactional.
- * @param acknowledgeMode The acknowledgement mode for the session.
+ * @param acknowledgeMode The acknoledgement mode for the session.
* @param messageFactoryRegistry The message factory factory for the session.
* @param defaultPrefetchHighMark The maximum number of messages to prefetched before suspending the session.
* @param defaultPrefetchLowMark The number of prefetched messages at which to resume the session.
@@ -109,7 +108,7 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
* @param con The connection on which to create the session.
* @param channelId The unique identifier for the session.
* @param transacted Indicates whether or not the session is transactional.
- * @param acknowledgeMode The acknowledgement mode for the session.
+ * @param acknowledgeMode The acknoledgement mode for the session.
* @param defaultPrefetchHigh The maximum number of messages to prefetched before suspending the session.
* @param defaultPrefetchLow The number of prefetched messages at which to resume the session.
*/
@@ -125,20 +124,6 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
return getProtocolHandler().getProtocolVersion();
}
- protected void acknowledgeImpl()
- {
- while (true)
- {
- Long tag = _unacknowledgedMessageTags.poll();
- if (tag == null)
- {
- break;
- }
-
- acknowledgeMessage(tag, false);
- }
- }
-
public void acknowledgeMessage(long deliveryTag, boolean multiple)
{
BasicAckBody body = getMethodRegistry().createBasicAckBody(deliveryTag, multiple);
@@ -168,7 +153,7 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
// we also need to check the state manager for 08/09 as the
// _connection variable may not be updated in time by the error receiving
// thread.
- // We can't close the session if we are already in the process of
+ // We can't close the session if we are alreadying in the process of
// closing/closed the connection.
if (!(getProtocolHandler().getStateManager().getCurrentState().equals(AMQState.CONNECTION_CLOSED)
@@ -184,20 +169,8 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
}
}
- public void commitImpl() throws AMQException, FailoverException, TransportException
+ public void sendCommit() throws AMQException, FailoverException
{
- // Acknowledge all delivered messages
- while (true)
- {
- Long tag = _deliveredMessageTags.poll();
- if (tag == null)
- {
- break;
- }
-
- acknowledgeMessage(tag, false);
- }
-
final AMQProtocolHandler handler = getProtocolHandler();
handler.syncWrite(getProtocolHandler().getMethodRegistry().createTxCommitBody().generateFrame(_channelId), TxCommitOkBody.class);
@@ -427,12 +400,12 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
public BasicMessageProducer_0_8 createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, long producerId) throws JMSException
+ final boolean immediate, final boolean waitUntilSent, long producerId) throws JMSException
{
try
{
return new BasicMessageProducer_0_8(_connection, (AMQDestination) destination, _transacted, _channelId,
- this, getProtocolHandler(), producerId, immediate, mandatory);
+ this, getProtocolHandler(), producerId, immediate, mandatory, waitUntilSent);
}
catch (AMQException e)
{
@@ -604,18 +577,6 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
}
- @Override
- protected void deleteTemporaryDestination(final TemporaryDestination amqQueue)
- throws JMSException
- {
- // Currently TemporaryDestination is set to be auto-delete which, for 0-8..0-9-1, means that the queue will be deleted
- // by the server when there are no more subscriptions to that queue/topic (rather than when the client disconnects).
- // This is not quite right for JMSCompliance as the queue/topic should remain until the connection closes, or the
- // client explicitly deletes it.
-
- /* intentional no-op */
- }
-
public boolean isQueueBound(String exchangeName, String queueName,
String bindingKey, Map<String, Object> args) throws JMSException
{
@@ -623,34 +584,4 @@ public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, B
queueName == null ? null : new AMQShortString(queueName),
bindingKey == null ? null : new AMQShortString(bindingKey));
}
-
-
- public AMQException getLastException()
- {
- // if the Connection has closed then we should throw any exception that
- // has occurred that we were not waiting for
- AMQStateManager manager = _connection.getProtocolHandler()
- .getStateManager();
-
- Exception e = manager.getLastException();
- if (manager.getCurrentState().equals(AMQState.CONNECTION_CLOSED)
- && e != null)
- {
- if (e instanceof AMQException)
- {
- return (AMQException) e;
- }
- else
- {
- AMQException amqe = new AMQException(AMQConstant
- .getConstant(AMQConstant.INTERNAL_ERROR.getCode()),
- e.getMessage(), e.getCause());
- return amqe;
- }
- }
- else
- {
- return null;
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
index 28f838057e..f54cb782c8 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
@@ -20,13 +20,14 @@
*/
package org.apache.qpid.client;
-import java.util.UUID;
-
import javax.jms.JMSException;
import javax.jms.TemporaryQueue;
import org.apache.qpid.framing.AMQShortString;
+import java.util.Random;
+import java.util.UUID;
+
/** AMQ implementation of a TemporaryQueue. */
final class AMQTemporaryQueue extends AMQQueue implements TemporaryQueue, TemporaryDestination
{
@@ -49,15 +50,11 @@ final class AMQTemporaryQueue extends AMQQueue implements TemporaryQueue, Tempor
{
throw new JMSException("Temporary Queue has consumers so cannot be deleted");
}
+ _deleted = true;
- try
- {
- _session.deleteTemporaryDestination(this);
- }
- finally
- {
- _deleted = true;
- }
+ // Currently TemporaryQueue is set to be auto-delete which means that the queue will be deleted
+ // by the server when there are no more subscriptions to that queue. This is probably not
+ // quite right for JMSCompliance.
}
public AMQSession getSession()
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
index db54b320dc..7b5781530b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
@@ -53,14 +53,10 @@ class AMQTemporaryTopic extends AMQTopic implements TemporaryTopic, TemporaryDes
throw new JMSException("Temporary Topic has consumers so cannot be deleted");
}
- try
- {
- _session.deleteTemporaryDestination(this);
- }
- finally
- {
- _deleted = true;
- }
+ _deleted = true;
+ // Currently TemporaryQueue is set to be auto-delete which means that the queue will be deleted
+ // by the server when there are no more subscriptions to that queue. This is probably not
+ // quite right for JMSCompliance.
}
public AMQSession getSession()
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java b/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
index 780dbcafc2..6217cb534a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
@@ -22,7 +22,6 @@ package org.apache.qpid.client;
import java.net.URISyntaxException;
-import javax.jms.InvalidDestinationException;
import javax.jms.JMSException;
import javax.jms.Topic;
@@ -96,47 +95,39 @@ public class AMQTopic extends AMQDestination implements Topic
super(exchangeName, exchangeClass, routingKey, isExclusive, isAutoDelete, queueName, isDurable,bindingKeys);
}
- public static AMQTopic createDurableTopic(Topic topic, String subscriptionName, AMQConnection connection)
+ public static AMQTopic createDurableTopic(AMQTopic topic, String subscriptionName, AMQConnection connection)
throws JMSException
{
- if (topic instanceof AMQDestination && topic instanceof javax.jms.Topic)
+ if (topic.getDestSyntax() == DestSyntax.ADDR)
{
- AMQDestination qpidTopic = (AMQDestination)topic;
- if (qpidTopic.getDestSyntax() == DestSyntax.ADDR)
+ try
{
- try
- {
- AMQTopic t = new AMQTopic(qpidTopic.getAddress());
- AMQShortString queueName = getDurableTopicQueueName(subscriptionName, connection);
- // link is never null if dest was created using an address string.
- t.getLink().setName(queueName.asString());
- t.getSourceNode().setAutoDelete(false);
- t.getSourceNode().setDurable(true);
-
- // The legacy fields are also populated just in case.
- t.setQueueName(queueName);
- t.setAutoDelete(false);
- t.setDurable(true);
- return t;
- }
- catch(Exception e)
- {
- JMSException ex = new JMSException("Error creating durable topic");
- ex.initCause(e);
- ex.setLinkedException(e);
- throw ex;
- }
+ AMQTopic t = new AMQTopic(topic.getAddress());
+ AMQShortString queueName = getDurableTopicQueueName(subscriptionName, connection);
+ // link is never null if dest was created using an address string.
+ t.getLink().setName(queueName.asString());
+ t.getSourceNode().setAutoDelete(false);
+ t.getSourceNode().setDurable(true);
+
+ // The legacy fields are also populated just in case.
+ t.setQueueName(queueName);
+ t.setAutoDelete(false);
+ t.setDurable(true);
+ return t;
}
- else
+ catch(Exception e)
{
- return new AMQTopic(qpidTopic.getExchangeName(), qpidTopic.getRoutingKey(), false,
- getDurableTopicQueueName(subscriptionName, connection),
- true);
+ JMSException ex = new JMSException("Error creating durable topic");
+ ex.initCause(e);
+ ex.setLinkedException(e);
+ throw ex;
}
}
else
{
- throw new InvalidDestinationException("The destination object used is not from this provider or of type javax.jms.Topic");
+ return new AMQTopic(topic.getExchangeName(), topic.getRoutingKey(), false,
+ getDurableTopicQueueName(subscriptionName, connection),
+ true);
}
}
@@ -147,17 +138,13 @@ public class AMQTopic extends AMQDestination implements Topic
public String getTopicName() throws JMSException
{
- if (getRoutingKey() != null)
+ if (super.getRoutingKey() == null && super.getSubject() != null)
{
- return getRoutingKey().asString();
- }
- else if (getSubject() != null)
- {
- return getSubject();
+ return super.getSubject();
}
else
{
- return null;
+ return super.getRoutingKey().toString();
}
}
@@ -176,18 +163,12 @@ public class AMQTopic extends AMQDestination implements Topic
public AMQShortString getRoutingKey()
{
- if (super.getRoutingKey() != null)
- {
- return super.getRoutingKey();
- }
- else if (getSubject() != null)
+ if (super.getRoutingKey() == null && super.getSubject() != null)
{
- return new AMQShortString(getSubject());
+ return new AMQShortString(super.getSubject());
}
else
{
- setRoutingKey(new AMQShortString(""));
- setSubject("");
return super.getRoutingKey();
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index 3b807591b0..0a78403268 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -27,7 +27,6 @@ import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.*;
import org.apache.qpid.jms.MessageConsumer;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.transport.TransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +36,10 @@ import javax.jms.MessageListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.SortedSet;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.TreeSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -115,10 +117,29 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
protected final int _acknowledgeMode;
/**
+ * Number of messages unacknowledged in DUPS_OK_ACKNOWLEDGE mode
+ */
+ private int _outstanding;
+
+ /**
+ * Switch to enable sending of acknowledgements when using DUPS_OK_ACKNOWLEDGE mode. Enabled when _outstannding
+ * number of msgs >= _prefetchHigh and disabled at < _prefetchLow
+ */
+ private boolean _dups_ok_acknowledge_send;
+
+ /**
* List of tags delievered, The last of which which should be acknowledged on commit in transaction mode.
*/
private ConcurrentLinkedQueue<Long> _receivedDeliveryTags = new ConcurrentLinkedQueue<Long>();
+ /** The last tag that was "multiple" acknowledged on this session (if transacted) */
+ private long _lastAcked;
+
+ /** set of tags which have previously been acked; but not part of the multiple ack (transacted mode only) */
+ private final SortedSet<Long> _previouslyAcked = new TreeSet<Long>();
+
+ private final Object _commitLock = new Object();
+
/**
* The thread that was used to call receive(). This is important for being able to interrupt that thread if a
* receive() is in progress.
@@ -268,6 +289,17 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
}
}
+ protected void preApplicationProcessing(AbstractJMSMessage jmsMsg) throws JMSException
+ {
+ if (_session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ _session.addUnacknowledgedMessage(jmsMsg.getDeliveryTag());
+ }
+
+ _session.setInRecovery(false);
+ preDeliver(jmsMsg);
+ }
+
/**
* @param immediate if true then return immediately if the connection is failing over
*
@@ -290,14 +322,14 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
}
}
- if (isMessageListenerSet())
+ if (!_receiving.compareAndSet(false, true))
{
- throw new javax.jms.IllegalStateException("A listener has already been set.");
+ throw new javax.jms.IllegalStateException("Another thread is already receiving.");
}
- if (!_receiving.compareAndSet(false, true))
+ if (isMessageListenerSet())
{
- throw new javax.jms.IllegalStateException("Another thread is already receiving.");
+ throw new javax.jms.IllegalStateException("A listener has already been set.");
}
_receivingThread = Thread.currentThread();
@@ -376,7 +408,7 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
{
- preDeliver(m);
+ preApplicationProcessing(m);
postDeliver(m);
}
return m;
@@ -387,10 +419,6 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
return null;
}
- catch(TransportException e)
- {
- throw _session.toJMSException("Exception while receiving:" + e.getMessage(), e);
- }
finally
{
releaseReceiving();
@@ -449,7 +477,7 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
{
- preDeliver(m);
+ preApplicationProcessing(m);
postDeliver(m);
}
@@ -461,10 +489,6 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
return null;
}
- catch(TransportException e)
- {
- throw _session.toJMSException("Exception while receiving:" + e.getMessage(), e);
- }
finally
{
releaseReceiving();
@@ -547,7 +571,6 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
if (!_session.isClosed() || _session.isClosing())
{
sendCancel();
- cleanupQueue();
}
}
catch (AMQException e)
@@ -558,10 +581,6 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
{
throw new JMSAMQException("FailoverException interrupted basic cancel.", e);
}
- catch (TransportException e)
- {
- throw _session.toJMSException("Exception while closing consumer: " + e.getMessage(), e);
- }
}
}
else
@@ -589,8 +608,6 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
}
abstract void sendCancel() throws AMQException, FailoverException;
-
- abstract void cleanupQueue() throws AMQException, FailoverException;
/**
* Called when you need to invalidate a consumer. Used for example when failover has occurred and the client has
@@ -701,7 +718,7 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
{
if (isMessageListenerSet())
{
- preDeliver(jmsMessage);
+ preApplicationProcessing(jmsMessage);
getMessageListener().onMessage(jmsMessage);
postDeliver(jmsMessage);
}
@@ -725,42 +742,49 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
}
}
- protected void preDeliver(AbstractJMSMessage msg)
+ void preDeliver(AbstractJMSMessage msg)
{
- _session.setInRecovery(false);
-
switch (_acknowledgeMode)
{
+
case Session.PRE_ACKNOWLEDGE:
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
break;
- case Session.AUTO_ACKNOWLEDGE:
- //fall through
- case Session.DUPS_OK_ACKNOWLEDGE:
- _session.addUnacknowledgedMessage(msg.getDeliveryTag());
- break;
+
case Session.CLIENT_ACKNOWLEDGE:
// we set the session so that when the user calls acknowledge() it can call the method on session
// to send out the appropriate frame
msg.setAMQSession(_session);
- _session.addUnacknowledgedMessage(msg.getDeliveryTag());
- _session.markDirty();
break;
case Session.SESSION_TRANSACTED:
- _session.addDeliveredMessage(msg.getDeliveryTag());
- _session.markDirty();
- break;
- case Session.NO_ACKNOWLEDGE:
- //do nothing.
- //path used for NO-ACK consumers, and browsers (see constructor).
+ if (isNoConsume())
+ {
+ _session.acknowledgeMessage(msg.getDeliveryTag(), false);
+ }
+ else
+ {
+ _session.addDeliveredMessage(msg.getDeliveryTag());
+ _session.markDirty();
+ }
+
break;
}
+
}
- void postDeliver(AbstractJMSMessage msg)
+ void postDeliver(AbstractJMSMessage msg) throws JMSException
{
switch (_acknowledgeMode)
{
+
+ case Session.CLIENT_ACKNOWLEDGE:
+ if (isNoConsume())
+ {
+ _session.acknowledgeMessage(msg.getDeliveryTag(), false);
+ }
+ _session.markDirty();
+ break;
+
case Session.DUPS_OK_ACKNOWLEDGE:
case Session.AUTO_ACKNOWLEDGE:
// we do not auto ack a message if the application code called recover()
@@ -798,6 +822,63 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
return null;
}
+ /**
+ * Acknowledge up to last message delivered (if any). Used when commiting.
+ */
+ void acknowledgeDelivered()
+ {
+ synchronized(_commitLock)
+ {
+ ArrayList<Long> tagsToAck = new ArrayList<Long>();
+
+ while (!_receivedDeliveryTags.isEmpty())
+ {
+ tagsToAck.add(_receivedDeliveryTags.poll());
+ }
+
+ Collections.sort(tagsToAck);
+
+ long prevAcked = _lastAcked;
+ long oldAckPoint = -1;
+
+ while(oldAckPoint != prevAcked)
+ {
+ oldAckPoint = prevAcked;
+
+ Iterator<Long> tagsToAckIterator = tagsToAck.iterator();
+
+ while(tagsToAckIterator.hasNext() && tagsToAckIterator.next() == prevAcked+1)
+ {
+ tagsToAckIterator.remove();
+ prevAcked++;
+ }
+
+ Iterator<Long> previousAckIterator = _previouslyAcked.iterator();
+ while(previousAckIterator.hasNext() && previousAckIterator.next() == prevAcked+1)
+ {
+ previousAckIterator.remove();
+ prevAcked++;
+ }
+
+ }
+ if(prevAcked != _lastAcked)
+ {
+ _session.acknowledgeMessage(prevAcked, true);
+ _lastAcked = prevAcked;
+ }
+
+ Iterator<Long> tagsToAckIterator = tagsToAck.iterator();
+
+ while(tagsToAckIterator.hasNext())
+ {
+ Long tag = tagsToAckIterator.next();
+ _session.acknowledgeMessage(tag, false);
+ _previouslyAcked.add(tag);
+ }
+ }
+ }
+
+
void notifyError(Throwable cause)
{
// synchronized (_closed)
@@ -876,7 +957,7 @@ public abstract class BasicMessageConsumer<U> extends Closeable implements Messa
public boolean isNoConsume()
{
- return _noConsume;
+ return _noConsume || _destination.isBrowseOnly() ;
}
public void rollback()
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
index 548e274571..b5f3501e5a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
@@ -19,11 +19,10 @@ package org.apache.qpid.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.client.AMQDestination.AddressOption;
import org.apache.qpid.client.AMQDestination.DestSyntax;
-import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.message.*;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInternalException;
@@ -66,13 +65,19 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
private boolean _preAcquire = true;
/**
+ * Indicate whether this consumer is started.
+ */
+ private boolean _isStarted = false;
+
+ /**
* Specify whether this consumer is performing a sync receive
*/
private final AtomicBoolean _syncReceive = new AtomicBoolean(false);
private String _consumerTagString;
private long capacity = 0;
-
+
+ //--- constructor
protected BasicMessageConsumer_0_10(int channelId, AMQConnection connection, AMQDestination destination,
String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory,
AMQSession session, AMQProtocolHandler protocolHandler,
@@ -98,6 +103,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
_preAcquire = false;
}
}
+ _isStarted = connection.started();
// Destination setting overrides connection defaults
if (destination.getDestSyntax() == DestSyntax.ADDR &&
@@ -150,20 +156,13 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
{
if (isMessageListenerSet() && capacity == 0)
{
- messageFlow();
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
+ MessageCreditUnit.MESSAGE, 1,
+ Option.UNRELIABLE);
}
_logger.debug("messageOk, trying to notify");
super.notifyMessage(jmsMessage);
}
- else
- {
- // if we are synchronously waiting for a message
- // and messages are not pre-fetched we then need to request another one
- if(capacity == 0)
- {
- messageFlow();
- }
- }
}
catch (AMQException e)
{
@@ -172,6 +171,8 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
}
}
+ //----- overwritten methods
+
/**
* This method is invoked when this consumer is stopped.
* It tells the broker to stop delivering messages to this consumer.
@@ -201,18 +202,11 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
super.notifyMessage(messageFrame);
}
- @Override
- protected void preDeliver(AbstractJMSMessage jmsMsg)
+ @Override protected void preApplicationProcessing(AbstractJMSMessage jmsMsg) throws JMSException
{
- super.preDeliver(jmsMsg);
-
- if (_acknowledgeMode == org.apache.qpid.jms.Session.NO_ACKNOWLEDGE)
+ super.preApplicationProcessing(jmsMsg);
+ if (!_session.getTransacted() && _session.getAcknowledgeMode() != org.apache.qpid.jms.Session.CLIENT_ACKNOWLEDGE)
{
- //For 0-10 we need to ensure that all messages are indicated processed in some way to
- //ensure their AMQP command-id is marked completed, and so we must send a completion
- //even for no-ack messages even though there isnt actually an 'acknowledgement' occurring.
- //Add message to the unacked message list to ensure we dont lose record of it before
- //sending a completion of some sort.
_session.addUnacknowledgedMessage(jmsMsg.getDeliveryTag());
}
}
@@ -224,6 +218,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
return _messageFactory.createMessage(msg.getMessageTransfer());
}
+ // private methods
/**
* Check whether a message can be delivered to this consumer.
*
@@ -252,7 +247,6 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
_logger.debug("messageOk " + messageOk);
_logger.debug("_preAcquire " + _preAcquire);
}
-
if (!messageOk)
{
if (_preAcquire)
@@ -269,12 +263,19 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
{
if (_logger.isDebugEnabled())
{
- _logger.debug("filterMessage - not ack'ing message as not acquired");
+ _logger.debug("Message not OK, releasing");
}
- flushUnwantedMessage(message);
+ releaseMessage(message);
+ }
+ // if we are syncrhonously waiting for a message
+ // and messages are not prefetched we then need to request another one
+ if(capacity == 0)
+ {
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
+ MessageCreditUnit.MESSAGE, 1,
+ Option.UNRELIABLE);
}
}
-
// now we need to acquire this message if needed
// this is the case of queue with a message selector set
if (!_preAcquire && messageOk && !isNoConsume())
@@ -286,7 +287,6 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
messageOk = acquireMessage(message);
_logger.debug("filterMessage - message acquire status : " + messageOk);
}
-
return messageOk;
}
@@ -297,38 +297,38 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
* @param message The message to be acknowledged
* @throws AMQException If the message cannot be acquired due to some internal error.
*/
- private void acknowledgeMessage(final AbstractJMSMessage message) throws AMQException
+ private void acknowledgeMessage(AbstractJMSMessage message) throws AMQException
{
- final RangeSet ranges = new RangeSet();
- ranges.add((int) message.getDeliveryTag());
- _0_10session.messageAcknowledge
- (ranges,
- _acknowledgeMode != org.apache.qpid.jms.Session.NO_ACKNOWLEDGE);
-
- final AMQException amqe = _0_10session.getCurrentException();
- if (amqe != null)
+ if (!_preAcquire)
{
- throw amqe;
+ RangeSet ranges = new RangeSet();
+ ranges.add((int) message.getDeliveryTag());
+ _0_10session.messageAcknowledge
+ (ranges,
+ _acknowledgeMode != org.apache.qpid.jms.Session.NO_ACKNOWLEDGE);
+
+ AMQException amqe = _0_10session.getCurrentException();
+ if (amqe != null)
+ {
+ throw amqe;
+ }
}
}
/**
- * Flush an unwanted message. For 0-10 we need to ensure that all messages are indicated
- * processed to ensure their AMQP command-id is marked completed.
+ * Release a message
*
- * @param message The unwanted message to be flushed
- * @throws AMQException If the unwanted message cannot be flushed due to some internal error.
+ * @param message The message to be released
+ * @throws AMQException If the message cannot be released due to some internal error.
*/
- private void flushUnwantedMessage(final AbstractJMSMessage message) throws AMQException
+ private void releaseMessage(AbstractJMSMessage message) throws AMQException
{
- final RangeSet ranges = new RangeSet();
- ranges.add((int) message.getDeliveryTag());
- _0_10session.flushProcessed(ranges,false);
-
- final AMQException amqe = _0_10session.getCurrentException();
- if (amqe != null)
+ if (_preAcquire)
{
- throw amqe;
+ RangeSet ranges = new RangeSet();
+ ranges.add((int) message.getDeliveryTag());
+ _0_10session.getQpidSession().messageRelease(ranges);
+ _0_10session.sync();
}
}
@@ -339,52 +339,44 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
* @return true if the message has been acquired, false otherwise.
* @throws AMQException If the message cannot be acquired due to some internal error.
*/
- private boolean acquireMessage(final AbstractJMSMessage message) throws AMQException
+ private boolean acquireMessage(AbstractJMSMessage message) throws AMQException
{
boolean result = false;
- final RangeSet ranges = new RangeSet();
- ranges.add((int) message.getDeliveryTag());
+ if (!_preAcquire)
+ {
+ RangeSet ranges = new RangeSet();
+ ranges.add((int) message.getDeliveryTag());
- final Acquired acq = _0_10session.getQpidSession().messageAcquire(ranges).get();
+ Acquired acq = _0_10session.getQpidSession().messageAcquire(ranges).get();
- final RangeSet acquired = acq.getTransfers();
- if (acquired != null && acquired.size() > 0)
- {
- result = true;
+ RangeSet acquired = acq.getTransfers();
+ if (acquired != null && acquired.size() > 0)
+ {
+ result = true;
+ }
}
return result;
}
- private void messageFlow()
- {
- _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
- MessageCreditUnit.MESSAGE, 1,
- Option.UNRELIABLE);
- }
public void setMessageListener(final MessageListener messageListener) throws JMSException
{
super.setMessageListener(messageListener);
- try
+ if (messageListener != null && capacity == 0)
{
- if (messageListener != null && capacity == 0)
- {
- messageFlow();
- }
- if (messageListener != null && !_synchronousQueue.isEmpty())
- {
- Iterator messages=_synchronousQueue.iterator();
- while (messages.hasNext())
- {
- AbstractJMSMessage message=(AbstractJMSMessage) messages.next();
- messages.remove();
- _session.rejectMessage(message, true);
- }
- }
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
+ MessageCreditUnit.MESSAGE, 1,
+ Option.UNRELIABLE);
}
- catch(TransportException e)
+ if (messageListener != null && !_synchronousQueue.isEmpty())
{
- throw _session.toJMSException("Exception while setting message listener:"+ e.getMessage(), e);
+ Iterator messages=_synchronousQueue.iterator();
+ while (messages.hasNext())
+ {
+ AbstractJMSMessage message=(AbstractJMSMessage) messages.next();
+ messages.remove();
+ _session.rejectMessage(message, true);
+ }
}
}
@@ -392,7 +384,9 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
{
if (_0_10session.isStarted() && _syncReceive.get())
{
- messageFlow();
+ _0_10session.getQpidSession().messageFlow
+ (getConsumerTagString(), MessageCreditUnit.MESSAGE, 1,
+ Option.UNRELIABLE);
}
}
@@ -413,7 +407,9 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
}
if (_0_10session.isStarted() && capacity == 0 && _synchronousQueue.isEmpty())
{
- messageFlow();
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
+ MessageCreditUnit.MESSAGE, 1,
+ Option.UNRELIABLE);
}
Object o = super.getMessageFromQueue(l);
if (o == null && _0_10session.isStarted())
@@ -444,7 +440,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
return o;
}
- void postDeliver(AbstractJMSMessage msg)
+ void postDeliver(AbstractJMSMessage msg) throws JMSException
{
super.postDeliver(msg);
if (_acknowledgeMode == org.apache.qpid.jms.Session.NO_ACKNOWLEDGE && !_session.isInRecovery())
@@ -453,8 +449,10 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
}
if (_acknowledgeMode == org.apache.qpid.jms.Session.AUTO_ACKNOWLEDGE &&
- !_session.isInRecovery() && _session.getAMQConnection().getSyncAck())
+ !_session.isInRecovery() &&
+ _session.getAMQConnection().getSyncAck())
{
+ ((AMQSession_0_10) getSession()).flushAcknowledgments();
((AMQSession_0_10) getSession()).getQpidSession().sync();
}
}
@@ -511,18 +509,4 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedM
return _exclusive;
}
}
-
- void cleanupQueue() throws AMQException, FailoverException
- {
- AMQDestination dest = this.getDestination();
- if (dest != null && dest.getDestSyntax() == AMQDestination.DestSyntax.ADDR)
- {
- if (dest.getDelete() == AddressOption.ALWAYS ||
- dest.getDelete() == AddressOption.RECEIVER )
- {
- ((AMQSession_0_10) getSession()).getQpidSession().queueDelete(
- this.getDestination().getQueueName());
- }
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
index 00acd5e866..cdbf57769d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
@@ -88,8 +88,4 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMe
return receive();
}
- void cleanupQueue() throws AMQException, FailoverException
- {
-
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index bf4de782a5..8756ac4d05 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -39,7 +39,6 @@ import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.client.message.MessageConverter;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.transport.TransportException;
import org.apache.qpid.util.UUIDGen;
import org.apache.qpid.util.UUIDs;
import org.slf4j.Logger;
@@ -114,6 +113,8 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private final boolean _mandatory;
+ private final boolean _waitUntilSent;
+
private boolean _disableMessageId;
private UUIDGen _messageIdGenerator = UUIDs.newGenerator();
@@ -125,7 +126,8 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
protected PublishMode publishMode = PublishMode.ASYNC_PUBLISH_ALL;
protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
- AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory) throws AMQException
+ AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory,
+ boolean waitUntilSent) throws AMQException
{
_connection = connection;
_destination = destination;
@@ -141,6 +143,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
_immediate = immediate;
_mandatory = mandatory;
+ _waitUntilSent = waitUntilSent;
_userID = connection.getUsername();
setPublishMode();
}
@@ -263,7 +266,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
return _destination;
}
- public void close() throws JMSException
+ public void close()
{
_closed.set(true);
_session.deregisterProducer(_producerId);
@@ -360,6 +363,19 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
}
}
+ public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive,
+ boolean mandatory, boolean immediate, boolean waitUntilSent) throws JMSException
+ {
+ checkPreConditions();
+ checkDestination(destination);
+ synchronized (_connection.getFailoverMutex())
+ {
+ validateDestination(destination);
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive, mandatory, immediate,
+ waitUntilSent);
+ }
+ }
+
private AbstractJMSMessage convertToNativeMessage(Message message) throws JMSException
{
if (message instanceof AbstractJMSMessage)
@@ -434,6 +450,12 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
}
}
+ protected void sendImpl(AMQDestination destination, Message message, int deliveryMode, int priority, long timeToLive,
+ boolean mandatory, boolean immediate) throws JMSException
+ {
+ sendImpl(destination, message, deliveryMode, priority, timeToLive, mandatory, immediate, _waitUntilSent);
+ }
+
/**
* The caller of this method must hold the failover mutex.
*
@@ -448,13 +470,23 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
* @throws JMSException
*/
protected void sendImpl(AMQDestination destination, Message origMessage, int deliveryMode, int priority, long timeToLive,
- boolean mandatory, boolean immediate) throws JMSException
+ boolean mandatory, boolean immediate, boolean wait) throws JMSException
{
checkTemporaryDestination(destination);
origMessage.setJMSDestination(destination);
AbstractJMSMessage message = convertToNativeMessage(origMessage);
+ if (_transacted)
+ {
+ if (_session.hasFailedOver() && _session.isDirty())
+ {
+ throw new JMSAMQException("Failover has occurred and session is dirty so unable to send.",
+ new AMQSessionDirtyException("Failover has occurred and session is dirty " +
+ "so unable to send."));
+ }
+ }
+
UUID messageId = null;
if (_disableMessageId)
{
@@ -466,14 +498,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
message.setJMSMessageID(messageId);
}
- try
- {
- sendMessage(destination, origMessage, message, messageId, deliveryMode, priority, timeToLive, mandatory, immediate);
- }
- catch (TransportException e)
- {
- throw getSession().toJMSException("Exception whilst sending:" + e.getMessage(), e);
- }
+ sendMessage(destination, origMessage, message, messageId, deliveryMode, priority, timeToLive, mandatory, immediate, wait);
if (message != origMessage)
{
@@ -493,7 +518,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
abstract void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
UUID messageId, int deliveryMode, int priority, long timeToLive, boolean mandatory,
- boolean immediate) throws JMSException;
+ boolean immediate, boolean wait) throws JMSException;
private void checkTemporaryDestination(AMQDestination destination) throws JMSException
{
@@ -571,13 +596,6 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
public boolean isBound(AMQDestination destination) throws JMSException
{
- try
- {
- return _session.isQueueBound(destination.getExchangeName(), null, destination.getRoutingKey());
- }
- catch (TransportException e)
- {
- throw getSession().toJMSException("Exception whilst checking destination binding:" + e.getMessage(), e);
- }
+ return _session.isQueueBound(destination.getExchangeName(), null, destination.getRoutingKey());
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
index 57f64c2f92..53c0457120 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
@@ -19,7 +19,6 @@ package org.apache.qpid.client;
import static org.apache.qpid.transport.Option.NONE;
import static org.apache.qpid.transport.Option.SYNC;
-import static org.apache.qpid.transport.Option.UNRELIABLE;
import java.nio.ByteBuffer;
import java.util.HashMap;
@@ -31,12 +30,9 @@ import javax.jms.JMSException;
import javax.jms.Message;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination.AddressOption;
import org.apache.qpid.client.AMQDestination.DestSyntax;
import org.apache.qpid.client.message.AMQMessageDelegate_0_10;
import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.QpidMessageProperties;
-import org.apache.qpid.client.messaging.address.Link.Reliability;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.transport.Header;
@@ -46,7 +42,6 @@ import org.apache.qpid.transport.MessageDeliveryMode;
import org.apache.qpid.transport.MessageDeliveryPriority;
import org.apache.qpid.transport.MessageProperties;
import org.apache.qpid.transport.Option;
-import org.apache.qpid.transport.TransportException;
import org.apache.qpid.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,9 +56,10 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
BasicMessageProducer_0_10(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
AMQSession session, AMQProtocolHandler protocolHandler, long producerId,
- boolean immediate, boolean mandatory) throws AMQException
+ boolean immediate, boolean mandatory, boolean waitUntilSent) throws AMQException
{
- super(connection, destination, transacted, channelId, session, protocolHandler, producerId, immediate, mandatory);
+ super(connection, destination, transacted, channelId, session, protocolHandler, producerId, immediate,
+ mandatory, waitUntilSent);
userIDBytes = Strings.toUTF8(_userID);
}
@@ -72,15 +68,12 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
{
if (destination.getDestSyntax() == DestSyntax.BURL)
{
- if (getSession().isDeclareExchanges())
- {
- String name = destination.getExchangeName().toString();
- ((AMQSession_0_10) getSession()).getQpidSession().exchangeDeclare
- (name,
- destination.getExchangeClass().toString(),
- null, null,
- name.startsWith("amq.") ? Option.PASSIVE : Option.NONE);
- }
+ String name = destination.getExchangeName().toString();
+ ((AMQSession_0_10) getSession()).getQpidSession().exchangeDeclare
+ (name,
+ destination.getExchangeClass().toString(),
+ null, null,
+ name.startsWith("amq.") ? Option.PASSIVE : Option.NONE);
}
else
{
@@ -103,7 +96,7 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
*/
void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
UUID messageId, int deliveryMode, int priority, long timeToLive, boolean mandatory,
- boolean immediate) throws JMSException
+ boolean immediate, boolean wait) throws JMSException
{
message.prepareForSending();
@@ -178,7 +171,7 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
if (destination.getDestSyntax() == AMQDestination.DestSyntax.ADDR &&
(destination.getSubject() != null ||
- (messageProps.getApplicationHeaders() != null && messageProps.getApplicationHeaders().get(QpidMessageProperties.QPID_SUBJECT) != null))
+ (messageProps.getApplicationHeaders() != null && messageProps.getApplicationHeaders().get("qpid.subject") != null))
)
{
Map<String,Object> appProps = messageProps.getApplicationHeaders();
@@ -188,21 +181,20 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
messageProps.setApplicationHeaders(appProps);
}
- if (appProps.get(QpidMessageProperties.QPID_SUBJECT) == null)
+ if (appProps.get("qpid.subject") == null)
{
// use default subject in address string
- appProps.put(QpidMessageProperties.QPID_SUBJECT,destination.getSubject());
+ appProps.put("qpid.subject",destination.getSubject());
}
- if (destination.getAddressType() == AMQDestination.TOPIC_TYPE)
+ if (destination.getTargetNode().getType() == AMQDestination.TOPIC_TYPE)
{
deliveryProp.setRoutingKey((String)
- messageProps.getApplicationHeaders().get(QpidMessageProperties.QPID_SUBJECT));
+ messageProps.getApplicationHeaders().get("qpid.subject"));
}
}
-
- ByteBuffer data = message.getData();
- messageProps.setContentLength(data.remaining());
+
+ messageProps.setContentLength(message.getContentLength());
// send the message
try
@@ -218,17 +210,14 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
deliveryMode == DeliveryMode.PERSISTENT)
);
- boolean unreliable = (destination.getDestSyntax() == DestSyntax.ADDR) &&
- (destination.getLink().getReliability() == Reliability.UNRELIABLE);
-
-
- ByteBuffer buffer = data == null ? ByteBuffer.allocate(0) : data.slice();
+ org.apache.mina.common.ByteBuffer data = message.getData();
+ ByteBuffer buffer = data == null ? ByteBuffer.allocate(0) : data.buf().slice();
ssn.messageTransfer(destination.getExchangeName() == null ? "" : destination.getExchangeName().toString(),
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
new Header(deliveryProp, messageProps),
- buffer, sync ? SYNC : NONE, unreliable ? UNRELIABLE : NONE);
+ buffer, sync ? SYNC : NONE);
if (sync)
{
ssn.sync();
@@ -245,34 +234,10 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
}
}
- @Override
+
public boolean isBound(AMQDestination destination) throws JMSException
{
return _session.isQueueBound(destination);
}
-
- @Override
- public void close() throws JMSException
- {
- super.close();
- AMQDestination dest = _destination;
- if (dest != null && dest.getDestSyntax() == AMQDestination.DestSyntax.ADDR)
- {
- if (dest.getDelete() == AddressOption.ALWAYS ||
- dest.getDelete() == AddressOption.SENDER )
- {
- try
- {
- ((AMQSession_0_10) getSession()).getQpidSession().queueDelete(
- _destination.getQueueName());
- }
- catch(TransportException e)
- {
- throw getSession().toJMSException("Exception while closing producer:" + e.getMessage(), e);
- }
- }
- }
- }
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
index 34d2ade723..27f7486890 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
@@ -27,13 +27,14 @@ import javax.jms.Message;
import javax.jms.Topic;
import javax.jms.Queue;
-import java.nio.ByteBuffer;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.AbstractJMSMessage;
+import org.apache.qpid.client.message.AMQMessageDelegate;
import org.apache.qpid.client.message.AMQMessageDelegate_0_8;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.BasicConsumeBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.BasicPublishBody;
import org.apache.qpid.framing.CompositeAMQDataBlock;
@@ -45,9 +46,10 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
{
BasicMessageProducer_0_8(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
- AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory) throws AMQException
+ AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory,
+ boolean waitUntilSent) throws AMQException
{
- super(connection, destination,transacted,channelId,session, protocolHandler, producerId, immediate, mandatory);
+ super(connection, destination,transacted,channelId,session, protocolHandler, producerId, immediate, mandatory,waitUntilSent);
}
void declareDestination(AMQDestination destination)
@@ -72,7 +74,7 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
UUID messageId, int deliveryMode,int priority, long timeToLive, boolean mandatory,
- boolean immediate) throws JMSException
+ boolean immediate, boolean wait) throws JMSException
{
BasicPublishBody body = getSession().getMethodRegistry().createBasicPublishBody(_session.getTicket(),
destination.getExchangeName(),
@@ -167,7 +169,7 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
throw jmse;
}
- _protocolHandler.writeFrame(compositeFrame);
+ _protocolHandler.writeFrame(compositeFrame, wait);
}
/**
@@ -184,9 +186,7 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
if (frames.length == (offset + 1))
{
- byte[] data = new byte[payload.remaining()];
- payload.get(data);
- frames[offset] = ContentBody.createAMQFrame(channelId, new ContentBody(data));
+ frames[offset] = ContentBody.createAMQFrame(channelId, new ContentBody(payload));
}
else
{
@@ -198,10 +198,7 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
payload.position((int) framePayloadMax * (i - offset));
int length = (remaining >= framePayloadMax) ? (int) framePayloadMax : (int) remaining;
payload.limit(payload.position() + length);
- byte[] data = new byte[payload.remaining()];
- payload.get(data);
-
- frames[i] = ContentBody.createAMQFrame(channelId, new ContentBody(data));
+ frames[i] = ContentBody.createAMQFrame(channelId, new ContentBody(payload.slice()));
remaining -= length;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/ChannelToSessionMap.java b/java/client/src/main/java/org/apache/qpid/client/ChannelToSessionMap.java
index 2fdb35de49..2b7e3d44da 100644
--- a/java/client/src/main/java/org/apache/qpid/client/ChannelToSessionMap.java
+++ b/java/client/src/main/java/org/apache/qpid/client/ChannelToSessionMap.java
@@ -1,23 +1,3 @@
-/*
- *
- * 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 org.apache.qpid.client;
import java.util.ArrayList;
diff --git a/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java b/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
index e81e754da2..7cc548915c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
+++ b/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
@@ -23,7 +23,6 @@ package org.apache.qpid.client;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
-import java.util.List;
import org.apache.qpid.framing.AMQShortString;
@@ -35,18 +34,6 @@ public enum CustomJMSXProperty
JMSXGroupSeq,
JMSXUserID;
- private static List<String> _names;
-
- static
- {
- CustomJMSXProperty[] properties = values();
- _names = new ArrayList<String>(properties.length);
- for(CustomJMSXProperty property : properties)
- {
- _names.add(property.toString());
- }
-
- }
private final AMQShortString _nameAsShortString;
@@ -60,8 +47,20 @@ public enum CustomJMSXProperty
return _nameAsShortString;
}
- public static Enumeration asEnumeration()
+ private static Enumeration _names;
+
+ public static synchronized Enumeration asEnumeration()
{
- return Collections.enumeration(_names);
+ if(_names == null)
+ {
+ CustomJMSXProperty[] properties = values();
+ ArrayList<String> nameList = new ArrayList<String>(properties.length);
+ for(CustomJMSXProperty property : properties)
+ {
+ nameList.add(property.toString());
+ }
+ _names = Collections.enumeration(nameList);
+ }
+ return _names;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/QpidConnectionMetaData.java b/java/client/src/main/java/org/apache/qpid/client/QpidConnectionMetaData.java
index 5cf767ac35..3bb5707417 100644
--- a/java/client/src/main/java/org/apache/qpid/client/QpidConnectionMetaData.java
+++ b/java/client/src/main/java/org/apache/qpid/client/QpidConnectionMetaData.java
@@ -30,11 +30,9 @@ import org.apache.qpid.common.QpidProperties;
public class QpidConnectionMetaData implements ConnectionMetaData
{
- private AMQConnection con;
QpidConnectionMetaData(AMQConnection conn)
{
- this.con = conn;
}
public int getJMSMajorVersion() throws JMSException
@@ -64,12 +62,12 @@ public class QpidConnectionMetaData implements ConnectionMetaData
public int getProviderMajorVersion() throws JMSException
{
- return con.getProtocolVersion().getMajorVersion();
+ return 0;
}
public int getProviderMinorVersion() throws JMSException
{
- return con.getProtocolVersion().getMinorVersion();
+ return 8;
}
public String getProviderVersion() throws JMSException
@@ -80,7 +78,8 @@ public class QpidConnectionMetaData implements ConnectionMetaData
private String getProtocolVersion()
{
- return con.getProtocolVersion().toString();
+ // TODO - Implement based on connection negotiated protocol
+ return "0.8";
}
public String getBrokerVersion()
diff --git a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
index 295c6a4091..27783bcacf 100644
--- a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
@@ -50,25 +50,25 @@ public class QueueSenderAdapter implements QueueSender
public void send(Message msg) throws JMSException
{
- checkQueuePreConditions(_queue);
+ checkPreConditions();
_delegate.send(msg);
}
public void send(Queue queue, Message msg) throws JMSException
{
- checkQueuePreConditions(queue);
+ checkPreConditions(queue);
_delegate.send(queue, msg);
}
public void publish(Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException
{
- checkQueuePreConditions(_queue);
+ checkPreConditions();
_delegate.send(msg, deliveryMode, priority, timeToLive);
}
public void send(Queue queue, Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException
{
- checkQueuePreConditions(queue);
+ checkPreConditions(queue);
_delegate.send(queue, msg, deliveryMode, priority, timeToLive);
}
@@ -122,19 +122,19 @@ public class QueueSenderAdapter implements QueueSender
public void send(Destination dest, Message msg) throws JMSException
{
- checkQueuePreConditions((Queue) dest);
+ checkPreConditions((Queue) dest);
_delegate.send(dest, msg);
}
public void send(Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException
{
- checkQueuePreConditions(_queue);
+ checkPreConditions();
_delegate.send(msg, deliveryMode, priority, timeToLive);
}
public void send(Destination dest, Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException
{
- checkQueuePreConditions((Queue) dest);
+ checkPreConditions((Queue) dest);
_delegate.send(dest, msg, deliveryMode, priority, timeToLive);
}
@@ -170,6 +170,11 @@ public class QueueSenderAdapter implements QueueSender
private void checkPreConditions() throws JMSException
{
+ checkPreConditions(_queue);
+ }
+
+ private void checkPreConditions(Queue queue) throws JMSException
+ {
if (closed)
{
throw new javax.jms.IllegalStateException("Publisher is closed");
@@ -181,43 +186,39 @@ public class QueueSenderAdapter implements QueueSender
{
throw new javax.jms.IllegalStateException("Invalid Session");
}
- }
- private void checkQueuePreConditions(Queue queue) throws JMSException
- {
- checkPreConditions() ;
-
- if (queue == null)
- {
- throw new UnsupportedOperationException("Queue is null.");
- }
-
- if (!(queue instanceof AMQDestination))
- {
- throw new InvalidDestinationException("Queue: " + queue + " is not a valid Qpid queue");
- }
-
- AMQDestination destination = (AMQDestination) queue;
- if (!destination.isCheckedForQueueBinding() && checkQueueBeforePublish())
- {
- if (_delegate.getSession().isStrictAMQP())
- {
- _delegate._logger.warn("AMQP does not support destination validation before publish, ");
- destination.setCheckedForQueueBinding(true);
- }
- else
- {
- if (_delegate.isBound(destination))
- {
- destination.setCheckedForQueueBinding(true);
- }
- else
- {
- throw new InvalidDestinationException("Queue: " + queue
- + " is not a valid destination (no bindings on server");
- }
- }
- }
+ if (queue == null)
+ {
+ throw new UnsupportedOperationException("Queue is null.");
+ }
+
+ if (!(queue instanceof AMQDestination))
+ {
+ throw new InvalidDestinationException("Queue: " + queue + " is not a valid Qpid queue");
+ }
+
+ AMQDestination destination = (AMQDestination) queue;
+ if (!destination.isCheckedForQueueBinding() && checkQueueBeforePublish())
+ {
+
+ if (_delegate.getSession().isStrictAMQP())
+ {
+ _delegate._logger.warn("AMQP does not support destination validation before publish, ");
+ destination.setCheckedForQueueBinding(true);
+ }
+ else
+ {
+ if (_delegate.isBound(destination))
+ {
+ destination.setCheckedForQueueBinding(true);
+ }
+ else
+ {
+ throw new InvalidDestinationException("Queue: " + queue
+ + " is not a valid destination (no bindings on server");
+ }
+ }
+ }
}
private boolean checkQueueBeforePublish()
diff --git a/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java b/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java
new file mode 100644
index 0000000000..2280cc9870
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/SSLConfiguration.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 org.apache.qpid.client;
+
+public class SSLConfiguration {
+
+ private String _keystorePath;
+
+ private String _keystorePassword;
+
+ private String _certType = "SunX509";
+
+ public void setKeystorePath(String path)
+ {
+ _keystorePath = path;
+ }
+
+ public String getKeystorePath()
+ {
+ return _keystorePath;
+ }
+
+ public void setKeystorePassword(String password)
+ {
+ _keystorePassword = password;
+ }
+
+ public String getKeystorePassword()
+ {
+ return _keystorePassword;
+ }
+
+ public void setCertType(String type)
+ {
+ _certType = type;
+ }
+
+ public String getCertType()
+ {
+ return _certType;
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java b/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
index ca137f5a51..7f8e80c73a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
@@ -24,16 +24,13 @@ package org.apache.qpid.client;
import javax.jms.Destination;
import javax.jms.JMSException;
-import org.apache.qpid.framing.AMQShortString;
-
/**
- * Provides support for convenience interface implemented by both AMQTemporaryTopic and AMQTemporaryQueue
+ * Provides support for covenience interface implemented by both AMQTemporaryTopic and AMQTemporaryQueue
* so that operations related to their "temporary-ness" can be abstracted out.
*/
interface TemporaryDestination extends Destination
{
- public AMQShortString getAMQQueueName();
public void delete() throws JMSException;
public AMQSession getSession();
public boolean isDeleted();
diff --git a/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java b/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java
index 97048f39f4..43025bd724 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XAConnectionImpl.java
@@ -31,9 +31,9 @@ public class XAConnectionImpl extends AMQConnection implements XAConnection, XAQ
/**
* Create a XAConnection from a connectionURL
*/
- public XAConnectionImpl(ConnectionURL connectionURL) throws AMQException
+ public XAConnectionImpl(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException
{
- super(connectionURL);
+ super(connectionURL, sslConfig);
}
//-- interface XAConnection
diff --git a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
index 5b94b342eb..8a75082202 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
@@ -21,14 +21,10 @@ import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
+import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.dtx.XidImpl;
-import org.apache.qpid.transport.DtxXaStatus;
-import org.apache.qpid.transport.ExecutionErrorCode;
-import org.apache.qpid.transport.Future;
-import org.apache.qpid.transport.Option;
-import org.apache.qpid.transport.RecoverResult;
-import org.apache.qpid.transport.SessionException;
-import org.apache.qpid.transport.XaResult;
+import org.apache.qpid.transport.*;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -215,28 +211,9 @@ public class XAResourceImpl implements XAResource
* @throws XAException An error has occurred. Possible exception values are XAER_RMERR, XAER_RMFAIL.
*/
public boolean isSameRM(XAResource xaResource) throws XAException
- {
- if(this == xaResource)
- {
- return true;
- }
- if(!(xaResource instanceof XAResourceImpl))
- {
- return false;
- }
-
- XAResourceImpl other = (XAResourceImpl)xaResource;
-
- String myUUID = ((AMQSession_0_10)_xaSession).getAMQConnection().getBrokerUUID();
- String otherUUID = ((AMQSession_0_10)other._xaSession).getAMQConnection().getBrokerUUID();
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Comparing my UUID " + myUUID + " with other UUID " + otherUUID);
- }
-
- return (myUUID != null && otherUUID != null && myUUID.equals(otherUUID));
-
+ {
+ // TODO : get the server identity of xaResource and compare it with our own one
+ return false;
}
/**
diff --git a/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java b/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
index 6b9121811d..354b67cd35 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
@@ -52,7 +52,7 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
{
super(qpidConnection, con, channelId, false, // this is not a transacted session
Session.AUTO_ACKNOWLEDGE, // the ack mode is transacted
- MessageFactoryRegistry.newDefaultRegistry(), defaultPrefetchHigh, defaultPrefetchLow,null);
+ MessageFactoryRegistry.newDefaultRegistry(), defaultPrefetchHigh, defaultPrefetchLow);
createSession();
_xaResource = new XAResourceImpl(this);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
index 28d19ce817..e9e52cc97c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
+++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
@@ -59,8 +59,8 @@ import org.slf4j.LoggerFactory;
* <tr><td> Automatically retry the continuation accross fail-overs until it succeeds, or raises an exception.
* </table>
*
- * @todo Another continuation. Could use an interface Continuation (as described in other todos)
- * Then have a wrapping continuation (this), which blocks on an arbitrary
+ * @todo Another continuation. Could use an interface Continuation (as described in other todos, for example, see
+ * {@link org.apache.qpid.pool.Job}). Then have a wrapping continuation (this), which blocks on an arbitrary
* Condition or Latch (specified in constructor call), that this blocks on before calling the wrapped Continuation.
* Must work on Java 1.4, so check retrotranslator works on Lock/Condition or latch first. Argument and return type
* to match wrapped condition as type parameters. Rename to AsyncConditionalContinuation or something like that.
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
index b9d4d6fa95..2cf19bf391 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
@@ -78,7 +78,7 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener<Chann
{
throw new AMQNoRouteException("Error: " + reason, null, null);
}
- else if (errorCode == AMQConstant.ARGUMENT_INVALID)
+ else if (errorCode == AMQConstant.INVALID_ARGUMENT)
{
_logger.debug("Broker responded with Invalid Argument.");
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index 939bd181a3..c81ad6422f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -20,13 +20,6 @@
*/
package org.apache.qpid.client.handler;
-import java.io.UnsupportedEncodingException;
-import java.util.StringTokenizer;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.security.AMQCallbackHandler;
@@ -41,9 +34,18 @@ import org.apache.qpid.framing.ConnectionStartOkBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.ProtocolVersion;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
public class ConnectionStartMethodHandler implements StateAwareMethodListener<ConnectionStartBody>
{
private static final Logger _log = LoggerFactory.getLogger(ConnectionStartMethodHandler.class);
@@ -195,20 +197,40 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener<Co
private String chooseMechanism(byte[] availableMechanisms) throws UnsupportedEncodingException
{
final String mechanisms = new String(availableMechanisms, "utf8");
- return CallbackHandlerRegistry.getInstance().selectMechanism(mechanisms);
+ StringTokenizer tokenizer = new StringTokenizer(mechanisms, " ");
+ HashSet mechanismSet = new HashSet();
+ while (tokenizer.hasMoreTokens())
+ {
+ mechanismSet.add(tokenizer.nextToken());
+ }
+
+ String preferredMechanisms = CallbackHandlerRegistry.getInstance().getMechanisms();
+ StringTokenizer prefTokenizer = new StringTokenizer(preferredMechanisms, " ");
+ while (prefTokenizer.hasMoreTokens())
+ {
+ String mech = prefTokenizer.nextToken();
+ if (mechanismSet.contains(mech))
+ {
+ return mech;
+ }
+ }
+
+ return null;
}
private AMQCallbackHandler createCallbackHandler(String mechanism, AMQProtocolSession protocolSession)
throws AMQException
{
+ Class mechanismClass = CallbackHandlerRegistry.getInstance().getCallbackHandlerClass(mechanism);
try
{
- AMQCallbackHandler instance = CallbackHandlerRegistry.getInstance().createCallbackHandler(mechanism);
- instance.initialise(protocolSession.getAMQConnection().getConnectionURL());
+ Object instance = mechanismClass.newInstance();
+ AMQCallbackHandler cbh = (AMQCallbackHandler) instance;
+ cbh.initialise(protocolSession);
- return instance;
+ return cbh;
}
- catch (IllegalArgumentException e)
+ catch (Exception e)
{
throw new AMQException(null, "Unable to create callback handler: " + e, e);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java
index a9434edf49..c2821591d8 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java
@@ -26,7 +26,9 @@ import org.apache.qpid.client.AMQSession;
import javax.jms.Destination;
import javax.jms.JMSException;
+import java.nio.ByteBuffer;
import java.util.Enumeration;
+import java.util.Map;
import java.util.UUID;
public interface AMQMessageDelegate
@@ -128,9 +130,9 @@ public interface AMQMessageDelegate
void removeProperty(final String propertyName) throws JMSException;
- void setAMQSession(final AMQSession<?,?> s);
+ void setAMQSession(final AMQSession s);
- AMQSession<?,?> getAMQSession();
+ AMQSession getAMQSession();
long getDeliveryTag();
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java
index e5b95f54f4..8c3f2fd08f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java
@@ -21,6 +21,11 @@
package org.apache.qpid.client.message;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.AMQException;
+
public interface AMQMessageDelegateFactory<D extends AMQMessageDelegate>
{
public static AMQMessageDelegateFactory DEFAULT_FACTORY = null;
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java
index f360b546b2..92e61984d2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java
@@ -22,12 +22,10 @@
package org.apache.qpid.client.message;
import java.lang.ref.SoftReference;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -37,10 +35,12 @@ import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
import javax.jms.MessageNotWriteableException;
+import javax.jms.Session;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQPInvalidClassException;
import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQSession_0_10;
import org.apache.qpid.client.CustomJMSXProperty;
import org.apache.qpid.framing.AMQShortString;
@@ -53,9 +53,6 @@ import org.apache.qpid.transport.MessageDeliveryMode;
import org.apache.qpid.transport.MessageDeliveryPriority;
import org.apache.qpid.transport.MessageProperties;
import org.apache.qpid.transport.ReplyTo;
-import org.apache.qpid.transport.TransportException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* This extends AbstractAMQMessageDelegate which contains common code between
@@ -64,7 +61,6 @@ import org.slf4j.LoggerFactory;
*/
public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
{
- private static final Logger _logger = LoggerFactory.getLogger(AMQMessageDelegate_0_10.class);
private static final Map<ReplyTo, SoftReference<Destination>> _destinationCache = Collections.synchronizedMap(new HashMap<ReplyTo, SoftReference<Destination>>());
public static final String JMS_TYPE = "x-jms-type";
@@ -74,8 +70,13 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
private Destination _destination;
+
private MessageProperties _messageProps;
private DeliveryProperties _deliveryProps;
+ /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
+ private AMQSession _session;
+ private final long _deliveryTag;
+
protected AMQMessageDelegate_0_10()
{
@@ -85,29 +86,15 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
protected AMQMessageDelegate_0_10(MessageProperties messageProps, DeliveryProperties deliveryProps, long deliveryTag)
{
- super(deliveryTag);
_messageProps = messageProps;
_deliveryProps = deliveryProps;
+ _deliveryTag = deliveryTag;
_readableProperties = (_messageProps != null);
AMQDestination dest;
- if (AMQDestination.getDefaultDestSyntax() == AMQDestination.DestSyntax.BURL)
- {
- dest = generateDestination(new AMQShortString(_deliveryProps.getExchange()),
+ dest = generateDestination(new AMQShortString(_deliveryProps.getExchange()),
new AMQShortString(_deliveryProps.getRoutingKey()));
- }
- else
- {
- String subject = null;
- if (messageProps != null && messageProps.getApplicationHeaders() != null)
- {
- subject = (String)messageProps.getApplicationHeaders().get(QpidMessageProperties.QPID_SUBJECT);
- }
- dest = (AMQDestination) convertToAddressBasedDestination(_deliveryProps.getExchange(),
- _deliveryProps.getRoutingKey(), subject);
- }
-
setJMSDestination(dest);
}
@@ -198,6 +185,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
}
}
+
public long getJMSTimestamp() throws JMSException
{
return _deliveryProps.getTimestamp();
@@ -252,50 +240,13 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
String exchange = replyTo.getExchange();
String routingKey = replyTo.getRoutingKey();
- if (AMQDestination.getDefaultDestSyntax() == AMQDestination.DestSyntax.BURL)
- {
-
- dest = generateDestination(new AMQShortString(exchange), new AMQShortString(routingKey));
- }
- else
- {
- dest = convertToAddressBasedDestination(exchange,routingKey,null);
- }
+ dest = generateDestination(new AMQShortString(exchange), new AMQShortString(routingKey));
_destinationCache.put(replyTo, new SoftReference<Destination>(dest));
}
return dest;
}
}
-
- private Destination convertToAddressBasedDestination(String exchange, String routingKey, String subject)
- {
- String addr;
- if ("".equals(exchange)) // type Queue
- {
- subject = (subject == null) ? "" : "/" + subject;
- addr = routingKey + subject;
- }
- else
- {
- addr = exchange + "/" + routingKey;
- }
-
- try
- {
- return AMQDestination.createDestination("ADDR:" + addr);
- }
- catch(Exception e)
- {
- // An exception is only thrown here if the address syntax is invalid.
- // Logging the exception, but not throwing as this is only important to Qpid developers.
- // An exception here means a bug in the code.
- _logger.error("Exception when constructing an address string from the ReplyTo struct");
-
- // falling back to the old way of doing it to ensure the application continues.
- return generateDestination(new AMQShortString(exchange), new AMQShortString(routingKey));
- }
- }
public void setJMSReplyTo(Destination destination) throws JMSException
{
@@ -317,14 +268,14 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
{
try
{
- int type = ((AMQSession_0_10)getAMQSession()).resolveAddressType(amqd);
+ int type = ((AMQSession_0_10)_session).resolveAddressType(amqd);
if (type == AMQDestination.QUEUE_TYPE)
{
- ((AMQSession_0_10)getAMQSession()).setLegacyFiledsForQueueType(amqd);
+ ((AMQSession_0_10)_session).setLegacyFiledsForQueueType(amqd);
}
else
{
- ((AMQSession_0_10)getAMQSession()).setLegacyFiledsForTopicType(amqd);
+ ((AMQSession_0_10)_session).setLegacyFiledsForTopicType(amqd);
}
}
catch(AMQException ex)
@@ -334,14 +285,6 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
e.setLinkedException(ex);
throw e;
}
- catch (TransportException e)
- {
- JMSException jmse = new JMSException("Exception occured while figuring out the node type:" + e.getMessage());
- jmse.initCause(e);
- jmse.setLinkedException(e);
- throw jmse;
- }
-
}
final ReplyTo replyTo = new ReplyTo(amqd.getExchangeName().toString(), amqd.getRoutingKey().toString());
@@ -392,7 +335,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
Destination replyTo = getJMSReplyTo();
if(replyTo != null)
{
- return ((AMQDestination)replyTo).toString();
+ return ((AMQDestination)replyTo).toURL();
}
else
{
@@ -689,16 +632,6 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
{
return new String(_messageProps.getUserId());
}
- else if (QpidMessageProperties.AMQP_0_10_APP_ID.equals(propertyName) &&
- _messageProps.getAppId() != null)
- {
- return new String(_messageProps.getAppId());
- }
- else if (QpidMessageProperties.AMQP_0_10_ROUTING_KEY.equals(propertyName) &&
- _deliveryProps.getRoutingKey() != null)
- {
- return _deliveryProps.getRoutingKey();
- }
else
{
checkPropertyName(propertyName);
@@ -737,19 +670,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
public Enumeration getPropertyNames() throws JMSException
{
- List<String> props = new ArrayList<String>();
- Map<String, Object> propertyMap = getApplicationHeaders();
- for (String prop: getApplicationHeaders().keySet())
- {
- Object value = propertyMap.get(prop);
- if (value instanceof Boolean || value instanceof Number
- || value instanceof String)
- {
- props.add(prop);
- }
- }
-
- return java.util.Collections.enumeration(props);
+ return java.util.Collections.enumeration(getApplicationHeaders().keySet());
}
public void setBooleanProperty(String propertyName, boolean b) throws JMSException
@@ -805,14 +726,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
{
checkPropertyName(propertyName);
checkWritableProperties();
- if (QpidMessageProperties.AMQP_0_10_APP_ID.equals(propertyName))
- {
- _messageProps.setAppId(value.getBytes());
- }
- else
- {
- setApplicationHeader(propertyName, value);
- }
+ setApplicationHeader(propertyName, value);
}
private static final Set<Class> ALLOWED = new HashSet();
@@ -897,6 +811,64 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate
_readableProperties = false;
}
+
+ public void acknowledgeThis() throws JMSException
+ {
+ // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
+ // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
+ if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ if (_session.getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection is already closed");
+ }
+
+ // we set multiple to true here since acknowledgment implies acknowledge of all previous messages
+ // received on the session
+ _session.acknowledgeMessage(_deliveryTag, true);
+ }
+ }
+
+ public void acknowledge() throws JMSException
+ {
+ if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ _session.acknowledge();
+ }
+ }
+
+
+ /**
+ * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
+ * acknowledge()
+ *
+ * @param s the AMQ session that delivered this message
+ */
+ public void setAMQSession(AMQSession s)
+ {
+ _session = s;
+ }
+
+ public AMQSession getAMQSession()
+ {
+ return _session;
+ }
+
+ /**
+ * Get the AMQ message number assigned to this message
+ *
+ * @return the message number
+ */
+ public long getDeliveryTag()
+ {
+ return _deliveryTag;
+ }
+
+
+
+
+
+
protected void checkPropertyName(CharSequence propertyName)
{
if (propertyName == null)
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java
index 9ab03412fe..cec4268a7b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java
@@ -30,6 +30,7 @@ import java.util.UUID;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageNotWriteableException;
+import javax.jms.Session;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
@@ -59,12 +60,15 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate
Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT));
private ContentHeaderProperties _contentHeaderProperties;
+ /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
+ private AMQSession _session;
+ private final long _deliveryTag;
// The base set of items that needs to be set.
private AMQMessageDelegate_0_8(BasicContentHeaderProperties properties, long deliveryTag)
{
- super(deliveryTag);
_contentHeaderProperties = properties;
+ _deliveryTag = deliveryTag;
_readableProperties = (_contentHeaderProperties != null);
_headerAdapter = new JMSHeaderAdapter(_readableProperties ? ((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders()
: (new BasicContentHeaderProperties()).getHeaders() );
@@ -495,6 +499,7 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate
{
throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
}
+ _contentHeaderProperties.updated();
}
@@ -514,4 +519,58 @@ public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate
_readableProperties = false;
}
+
+
+ public void acknowledgeThis() throws JMSException
+ {
+ // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
+ // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
+ if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ if (_session.getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection is already closed");
+ }
+
+ // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
+ // received on the session
+ _session.acknowledgeMessage(_deliveryTag, true);
+ }
+ }
+
+ public void acknowledge() throws JMSException
+ {
+ if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
+ {
+ _session.acknowledge();
+ }
+ }
+
+
+ /**
+ * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
+ * acknowledge()
+ *
+ * @param s the AMQ session that delivered this message
+ */
+ public void setAMQSession(AMQSession s)
+ {
+ _session = s;
+ }
+
+ public AMQSession getAMQSession()
+ {
+ return _session;
+ }
+
+ /**
+ * Get the AMQ message number assigned to this message
+ *
+ * @return the message number
+ */
+ public long getDeliveryTag()
+ {
+ return _deliveryTag;
+ }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java
index be71c8c657..6e22292ee0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessage.java
@@ -23,12 +23,11 @@ package org.apache.qpid.client.message;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
-import java.nio.ByteBuffer;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.transport.codec.BBDecoder;
import org.apache.qpid.transport.codec.BBEncoder;
@@ -66,7 +65,7 @@ public class AMQPEncodedMapMessage extends JMSMapMessage
if ((value instanceof Boolean) || (value instanceof Byte) || (value instanceof Short) || (value instanceof Integer)
|| (value instanceof Long) || (value instanceof Character) || (value instanceof Float)
|| (value instanceof Double) || (value instanceof String) || (value instanceof byte[])
- || (value instanceof List) || (value instanceof Map) || (value instanceof UUID) || (value == null))
+ || (value instanceof List) || (value instanceof Map) || (value == null))
{
_map.put(propName, value);
}
@@ -81,19 +80,18 @@ public class AMQPEncodedMapMessage extends JMSMapMessage
@ Override
public ByteBuffer getData()
{
- BBEncoder encoder = new BBEncoder(1024);
- encoder.writeMap(_map);
- return encoder.segment();
+ writeMapToData();
+ return _data;
}
@ Override
- protected void populateMapFromData(ByteBuffer data) throws JMSException
+ protected void populateMapFromData() throws JMSException
{
- if (data != null)
+ if (_data != null)
{
- data.rewind();
+ _data.rewind();
BBDecoder decoder = new BBDecoder();
- decoder.init(data);
+ decoder.init(_data.buf());
_map = decoder.readMap();
}
else
@@ -102,8 +100,16 @@ public class AMQPEncodedMapMessage extends JMSMapMessage
}
}
+ @ Override
+ protected void writeMapToData()
+ {
+ BBEncoder encoder = new BBEncoder(1024);
+ encoder.writeMap(_map);
+ _data = ByteBuffer.wrap(encoder.segment());
+ }
+
// for testing
- public Map<String,Object> getMap()
+ Map<String,Object> getMap()
{
return _map;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java
index 2c38f153cb..4978d1ce85 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageFactory.java
@@ -1,6 +1,6 @@
package org.apache.qpid.client.message;
/*
- *
+ *
* 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
@@ -8,23 +8,22 @@ package org.apache.qpid.client.message;
* 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.
- *
+ *
*/
import javax.jms.JMSException;
-import java.nio.ByteBuffer;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
public class AMQPEncodedMapMessageFactory extends AbstractJMSMessageFactory
@@ -37,7 +36,7 @@ public class AMQPEncodedMapMessageFactory extends AbstractJMSMessageFactory
return new AMQPEncodedMapMessage(delegate,data);
}
-
+ @Override
public AbstractJMSMessage createMessage(
AMQMessageDelegateFactory delegateFactory) throws JMSException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java
index 1b6c0c751d..89fbc9722c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java
@@ -23,13 +23,9 @@ package org.apache.qpid.client.message;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import javax.jms.JMSException;
-import javax.jms.Session;
-
import org.apache.qpid.client.AMQAnyDestination;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
@@ -82,25 +78,7 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate
new ExchangeInfo(ExchangeDefaults.HEADERS_EXCHANGE_NAME.toString(),
ExchangeDefaults.HEADERS_EXCHANGE_CLASS.toString(),
AMQDestination.QUEUE_TYPE));
- }
-
- /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
- private AMQSession<?,?> _session;
- private final long _deliveryTag;
-
- protected AbstractAMQMessageDelegate(long deliveryTag)
- {
- _deliveryTag = deliveryTag;
- }
-
- /**
- * Get the AMQ message number assigned to this message
- *
- * @return the message number
- */
- public long getDeliveryTag()
- {
- return _deliveryTag;
+
}
/**
@@ -179,47 +157,6 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate
{
return _exchangeMap.containsKey(exchange);
}
-
- public void acknowledgeThis() throws JMSException
- {
- // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
- // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
- if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
- {
- if (_session.getAMQConnection().isClosed())
- {
- throw new javax.jms.IllegalStateException("Connection is already closed");
- }
-
- // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
- // received on the session
- _session.acknowledgeMessage(getDeliveryTag(), true);
- }
- }
-
- public void acknowledge() throws JMSException
- {
- if (_session != null && _session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE)
- {
- _session.acknowledge();
- }
- }
-
- /**
- * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
- * acknowledge()
- *
- * @param s the AMQ session that delivered this message
- */
- public void setAMQSession(AMQSession<?,?> s)
- {
- _session = s;
- }
-
- public AMQSession<?,?> getAMQSession()
- {
- return _session;
- }
}
class ExchangeInfo
@@ -265,5 +202,5 @@ class ExchangeInfo
public void setDestType(int destType)
{
this.destType = destType;
- }
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
new file mode 100644
index 0000000000..3846ee043d
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 org.apache.qpid.client.message;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import javax.jms.JMSException;
+import javax.jms.MessageEOFException;
+
+import org.apache.mina.common.ByteBuffer;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.transport.util.Functions;
+
+/**
+ * @author Apache Software Foundation
+ */
+public abstract class AbstractBytesMessage extends AbstractJMSMessage
+{
+
+ /**
+ * The default initial size of the buffer. The buffer expands automatically.
+ */
+ private static final int DEFAULT_BUFFER_INITIAL_SIZE = 1024;
+
+ AbstractBytesMessage(AMQMessageDelegateFactory delegateFactory)
+ {
+ this(delegateFactory, null);
+ }
+
+ /**
+ * Construct a bytes message with existing data.
+ *
+ * @param delegateFactory
+ * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
+ */
+ AbstractBytesMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
+ {
+ super(delegateFactory, data); // this instanties a content header
+ setContentType(getMimeType());
+
+ if (_data == null)
+ {
+ allocateInitialBuffer();
+ }
+ }
+
+ protected void allocateInitialBuffer()
+ {
+ _data = ByteBuffer.allocate(DEFAULT_BUFFER_INITIAL_SIZE);
+ _data.setAutoExpand(true);
+ }
+
+ AbstractBytesMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
+ {
+ super(delegate, data);
+ setContentType(getMimeType());
+ }
+
+
+ public void clearBodyImpl() throws JMSException
+ {
+ allocateInitialBuffer();
+ }
+
+ public String toBodyString() throws JMSException
+ {
+ try
+ {
+ if (_data != null)
+ {
+ return Functions.str(_data.buf(), 100,0);
+ }
+ else
+ {
+ return "";
+ }
+
+ }
+ catch (Exception e)
+ {
+ JMSException jmse = new JMSException(e.toString());
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+
+ }
+
+ /**
+ * Check that there is at least a certain number of bytes available to read
+ *
+ * @param len the number of bytes
+ * @throws javax.jms.MessageEOFException if there are less than len bytes available to read
+ */
+ protected void checkAvailable(int len) throws MessageEOFException
+ {
+ if (_data.remaining() < len)
+ {
+ throw new MessageEOFException("Unable to read " + len + " bytes");
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
index ddeb62fbf6..85818dcd2b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
@@ -21,96 +21,784 @@
package org.apache.qpid.client.message;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
-import java.nio.ByteBuffer;
import javax.jms.JMSException;
+import javax.jms.MessageEOFException;
+import javax.jms.MessageFormatException;
import javax.jms.MessageNotReadableException;
import javax.jms.MessageNotWriteableException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
-import org.apache.qpid.transport.util.Functions;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
/**
* @author Apache Software Foundation
*/
-public abstract class AbstractBytesTypedMessage extends AbstractJMSMessage
+public abstract class AbstractBytesTypedMessage extends AbstractBytesMessage
{
- protected boolean _readableMessage = false;
- AbstractBytesTypedMessage(AMQMessageDelegateFactory delegateFactory, boolean fromReceivedMessage)
+ protected static final byte BOOLEAN_TYPE = (byte) 1;
+
+ protected static final byte BYTE_TYPE = (byte) 2;
+
+ protected static final byte BYTEARRAY_TYPE = (byte) 3;
+
+ protected static final byte SHORT_TYPE = (byte) 4;
+
+ protected static final byte CHAR_TYPE = (byte) 5;
+
+ protected static final byte INT_TYPE = (byte) 6;
+
+ protected static final byte LONG_TYPE = (byte) 7;
+
+ protected static final byte FLOAT_TYPE = (byte) 8;
+
+ protected static final byte DOUBLE_TYPE = (byte) 9;
+
+ protected static final byte STRING_TYPE = (byte) 10;
+
+ protected static final byte NULL_STRING_TYPE = (byte) 11;
+
+ /**
+ * This is set when reading a byte array. The readBytes(byte[]) method supports multiple calls to read
+ * a byte array in multiple chunks, hence this is used to track how much is left to be read
+ */
+ private int _byteArrayRemaining = -1;
+
+ AbstractBytesTypedMessage(AMQMessageDelegateFactory delegateFactory)
+ {
+
+ this(delegateFactory, null);
+ }
+
+ /**
+ * Construct a stream message with existing data.
+ *
+ * @param delegateFactory
+ * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
+ */
+ AbstractBytesTypedMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(delegateFactory, fromReceivedMessage); // this instanties a content header
- _readableMessage = fromReceivedMessage;
+ super(delegateFactory, data); // this instanties a content header
}
- AbstractBytesTypedMessage(AMQMessageDelegate delegate, boolean fromReceivedMessage) throws AMQException
+ AbstractBytesTypedMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(delegate, fromReceivedMessage);
- _readableMessage = fromReceivedMessage;
+ super(delegate, data);
+ }
+
+ protected byte readWireType() throws MessageFormatException, MessageEOFException,
+ MessageNotReadableException
+ {
+ checkReadable();
+ checkAvailable(1);
+ return _data.get();
}
- protected void checkReadable() throws MessageNotReadableException
+ protected void writeTypeDiscriminator(byte type) throws MessageNotWriteableException
{
- if (!_readableMessage)
+ checkWritable();
+ _data.put(type);
+ _changedData = true;
+ }
+
+ protected boolean readBoolean() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ boolean result;
+ try
{
- throw new MessageNotReadableException("You need to call reset() to make the message readable");
+ switch (wireType)
+ {
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = readBooleanImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Boolean.parseBoolean(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a boolean");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
}
}
- @Override
- protected void checkWritable() throws MessageNotWriteableException
+ private boolean readBooleanImpl()
{
- super.checkWritable();
- if(_readableMessage)
+ return _data.get() != 0;
+ }
+
+ protected byte readByte() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ byte result;
+ try
{
- throw new MessageNotWriteableException("You need to call clearBody() to make the message writable");
+ switch (wireType)
+ {
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Byte.parseByte(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a byte");
+ }
}
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ return result;
}
- public void clearBody() throws JMSException
+ private byte readByteImpl()
{
- super.clearBody();
- _readableMessage = false;
+ return _data.get();
}
+ protected short readShort() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ short result;
+ try
+ {
+ switch (wireType)
+ {
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Short.parseShort(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a short");
+ }
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ return result;
+ }
- public String toBodyString() throws JMSException
+ private short readShortImpl()
{
+ return _data.getShort();
+ }
+
+ /**
+ * Note that this method reads a unicode character as two bytes from the stream
+ *
+ * @return the character read from the stream
+ * @throws javax.jms.JMSException
+ */
+ protected char readChar() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
try
{
- ByteBuffer data = getData();
- if (data != null)
- {
- return Functions.str(data, 100, 0);
- }
- else
- {
- return "";
+ if(wireType == NULL_STRING_TYPE){
+ throw new NullPointerException();
}
+ if (wireType != CHAR_TYPE)
+ {
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a char");
+ }
+ else
+ {
+ checkAvailable(2);
+ return readCharImpl();
+ }
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private char readCharImpl()
+ {
+ return _data.getChar();
+ }
+
+ protected int readInt() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ int result;
+ try
+ {
+ switch (wireType)
+ {
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Integer.parseInt(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to an int");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected int readIntImpl()
+ {
+ return _data.getInt();
+ }
+
+ protected long readLong() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ long result;
+ try
+ {
+ switch (wireType)
+ {
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = readLongImpl();
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Long.parseLong(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a long");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private long readLongImpl()
+ {
+ return _data.getLong();
+ }
+
+ protected float readFloat() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ float result;
+ try
+ {
+ switch (wireType)
+ {
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Float.parseFloat(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a float");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private float readFloatImpl()
+ {
+ return _data.getFloat();
+ }
+
+ protected double readDouble() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ double result;
+ try
+ {
+ switch (wireType)
+ {
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = readDoubleImpl();
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Double.parseDouble(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a double");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private double readDoubleImpl()
+ {
+ return _data.getDouble();
+ }
+
+ protected String readString() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ String result;
+ try
+ {
+ switch (wireType)
+ {
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = readStringImpl();
+ break;
+ case NULL_STRING_TYPE:
+ result = null;
+ throw new NullPointerException("data is null");
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = String.valueOf(readBooleanImpl());
+ break;
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = String.valueOf(readLongImpl());
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = String.valueOf(readIntImpl());
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = String.valueOf(readShortImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = String.valueOf(readByteImpl());
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = String.valueOf(readFloatImpl());
+ break;
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = String.valueOf(readDoubleImpl());
+ break;
+ case CHAR_TYPE:
+ checkAvailable(2);
+ result = String.valueOf(readCharImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a String");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected String readStringImpl() throws JMSException
+ {
+ try
+ {
+ return _data.getString(Charset.forName("UTF-8").newDecoder());
}
- catch (Exception e)
+ catch (CharacterCodingException e)
{
- JMSException jmse = new JMSException(e.toString());
+ JMSException jmse = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
jmse.setLinkedException(e);
jmse.initCause(e);
throw jmse;
}
+ }
+
+ protected int readBytes(byte[] bytes) throws JMSException
+ {
+ if (bytes == null)
+ {
+ throw new IllegalArgumentException("byte array must not be null");
+ }
+ checkReadable();
+ // first call
+ if (_byteArrayRemaining == -1)
+ {
+ // type discriminator checked separately so you get a MessageFormatException rather than
+ // an EOF even in the case where both would be applicable
+ checkAvailable(1);
+ byte wireType = readWireType();
+ if (wireType != BYTEARRAY_TYPE)
+ {
+ throw new MessageFormatException("Unable to convert " + wireType + " to a byte array");
+ }
+ checkAvailable(4);
+ int size = _data.getInt();
+ // length of -1 indicates null
+ if (size == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ if (size > _data.remaining())
+ {
+ throw new MessageEOFException("Byte array has stated length " + size + " but message only contains " +
+ _data.remaining() + " bytes");
+ }
+ else
+ {
+ _byteArrayRemaining = size;
+ }
+ }
+ }
+ else if (_byteArrayRemaining == 0)
+ {
+ _byteArrayRemaining = -1;
+ return -1;
+ }
+
+ int returnedSize = readBytesImpl(bytes);
+ if (returnedSize < bytes.length)
+ {
+ _byteArrayRemaining = -1;
+ }
+ return returnedSize;
+ }
+
+ private int readBytesImpl(byte[] bytes)
+ {
+ int count = (_byteArrayRemaining >= bytes.length ? bytes.length : _byteArrayRemaining);
+ _byteArrayRemaining -= count;
+
+ if (count == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ _data.get(bytes, 0, count);
+ return count;
+ }
+ }
+
+ protected Object readObject() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ Object result = null;
+ try
+ {
+ switch (wireType)
+ {
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = readBooleanImpl();
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ case BYTEARRAY_TYPE:
+ checkAvailable(4);
+ int size = _data.getInt();
+ if (size == -1)
+ {
+ result = null;
+ }
+ else
+ {
+ _byteArrayRemaining = size;
+ byte[] bytesResult = new byte[size];
+ readBytesImpl(bytesResult);
+ result = bytesResult;
+ }
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case CHAR_TYPE:
+ checkAvailable(2);
+ result = readCharImpl();
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = readLongImpl();
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = readDoubleImpl();
+ break;
+ case NULL_STRING_TYPE:
+ result = null;
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = readStringImpl();
+ break;
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected void writeBoolean(boolean b) throws JMSException
+ {
+ writeTypeDiscriminator(BOOLEAN_TYPE);
+ _data.put(b ? (byte) 1 : (byte) 0);
+ }
+
+ protected void writeByte(byte b) throws JMSException
+ {
+ writeTypeDiscriminator(BYTE_TYPE);
+ _data.put(b);
+ }
+
+ protected void writeShort(short i) throws JMSException
+ {
+ writeTypeDiscriminator(SHORT_TYPE);
+ _data.putShort(i);
+ }
+
+ protected void writeChar(char c) throws JMSException
+ {
+ writeTypeDiscriminator(CHAR_TYPE);
+ _data.putChar(c);
+ }
+
+ protected void writeInt(int i) throws JMSException
+ {
+ writeTypeDiscriminator(INT_TYPE);
+ writeIntImpl(i);
+ }
+
+ protected void writeIntImpl(int i)
+ {
+ _data.putInt(i);
+ }
+
+ protected void writeLong(long l) throws JMSException
+ {
+ writeTypeDiscriminator(LONG_TYPE);
+ _data.putLong(l);
+ }
+ protected void writeFloat(float v) throws JMSException
+ {
+ writeTypeDiscriminator(FLOAT_TYPE);
+ _data.putFloat(v);
}
+ protected void writeDouble(double v) throws JMSException
+ {
+ writeTypeDiscriminator(DOUBLE_TYPE);
+ _data.putDouble(v);
+ }
- abstract public void reset();
+ protected void writeString(String string) throws JMSException
+ {
+ if (string == null)
+ {
+ writeTypeDiscriminator(NULL_STRING_TYPE);
+ }
+ else
+ {
+ writeTypeDiscriminator(STRING_TYPE);
+ try
+ {
+ writeStringImpl(string);
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException jmse = new JMSException("Unable to encode string: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+ }
+ }
+
+ protected void writeStringImpl(String string)
+ throws CharacterCodingException
+ {
+ _data.putString(string, Charset.forName("UTF-8").newEncoder());
+ // we must write the null terminator ourselves
+ _data.put((byte) 0);
+ }
+ protected void writeBytes(byte[] bytes) throws JMSException
+ {
+ writeBytes(bytes, 0, bytes == null ? 0 : bytes.length);
+ }
+ protected void writeBytes(byte[] bytes, int offset, int length) throws JMSException
+ {
+ writeTypeDiscriminator(BYTEARRAY_TYPE);
+ if (bytes == null)
+ {
+ _data.putInt(-1);
+ }
+ else
+ {
+ _data.putInt(length);
+ _data.put(bytes, offset, length);
+ }
+ }
+ protected void writeObject(Object object) throws JMSException
+ {
+ checkWritable();
+ Class clazz;
+ if (object == null)
+ {
+ // string handles the output of null values
+ clazz = String.class;
+ }
+ else
+ {
+ clazz = object.getClass();
+ }
+
+ if (clazz == Byte.class)
+ {
+ writeByte((Byte) object);
+ }
+ else if (clazz == Boolean.class)
+ {
+ writeBoolean((Boolean) object);
+ }
+ else if (clazz == byte[].class)
+ {
+ writeBytes((byte[]) object);
+ }
+ else if (clazz == Short.class)
+ {
+ writeShort((Short) object);
+ }
+ else if (clazz == Character.class)
+ {
+ writeChar((Character) object);
+ }
+ else if (clazz == Integer.class)
+ {
+ writeInt((Integer) object);
+ }
+ else if (clazz == Long.class)
+ {
+ writeLong((Long) object);
+ }
+ else if (clazz == Float.class)
+ {
+ writeFloat((Float) object);
+ }
+ else if (clazz == Double.class)
+ {
+ writeDouble((Double) object);
+ }
+ else if (clazz == String.class)
+ {
+ writeString((String) object);
+ }
+ else
+ {
+ throw new MessageFormatException("Only primitives plus byte arrays and String are valid types");
+ }
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
index f713554bfb..6ba55b207a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
@@ -20,38 +20,66 @@
*/
package org.apache.qpid.client.message;
-import java.nio.ByteBuffer;
+import java.io.IOException;
import java.util.Enumeration;
import java.util.UUID;
import javax.jms.Destination;
import javax.jms.JMSException;
+import javax.jms.MessageNotReadableException;
import javax.jms.MessageNotWriteableException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
{
+
+ protected ByteBuffer _data;
+ protected boolean _readableMessage = false;
+ protected boolean _changedData = true;
+
/** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
+
+
+
protected AMQMessageDelegate _delegate;
private boolean _redelivered;
- private boolean _receivedFromServer;
- protected AbstractJMSMessage(AMQMessageDelegateFactory delegateFactory, boolean fromReceivedData)
+ protected AbstractJMSMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
_delegate = delegateFactory.createDelegate();
- setContentType(getMimeType());
+ _data = data;
+ if (_data != null)
+ {
+ _data.acquire();
+ }
+
+
+ _readableMessage = (data != null);
+ _changedData = (data == null);
+
}
- protected AbstractJMSMessage(AMQMessageDelegate delegate, boolean fromReceivedData) throws AMQException
+ protected AbstractJMSMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
_delegate = delegate;
- setContentType(getMimeType());
+
+ _data = data;
+ if (_data != null)
+ {
+ _data.acquire();
+ }
+
+ _readableMessage = data != null;
+
}
public String getJMSMessageID() throws JMSException
@@ -301,9 +329,12 @@ public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
public void clearBody() throws JMSException
{
- _receivedFromServer = false;
+ clearBodyImpl();
+ _readableMessage = false;
+
}
+
public void acknowledgeThis() throws JMSException
{
_delegate.acknowledgeThis();
@@ -314,7 +345,14 @@ public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
_delegate.acknowledge();
}
- /*
+ /**
+ * This forces concrete classes to implement clearBody()
+ *
+ * @throws JMSException
+ */
+ public abstract void clearBodyImpl() throws JMSException;
+
+ /**
* Get a String representation of the body of the message. Used in the toString() method which outputs this before
* message properties.
*/
@@ -375,24 +413,63 @@ public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
return _delegate;
}
- abstract public ByteBuffer getData() throws JMSException;
+ public ByteBuffer getData()
+ {
+ // make sure we rewind the data just in case any method has moved the
+ // position beyond the start
+ if (_data != null)
+ {
+ reset();
+ }
+ return _data;
+ }
+
+ protected void checkReadable() throws MessageNotReadableException
+ {
+ if (!_readableMessage)
+ {
+ throw new MessageNotReadableException("You need to call reset() to make the message readable");
+ }
+ }
protected void checkWritable() throws MessageNotWriteableException
{
- if (_receivedFromServer)
+ if (_readableMessage)
{
throw new MessageNotWriteableException("You need to call clearBody() to make the message writable");
}
}
-
- public void setReceivedFromServer()
+ public void reset()
{
- _receivedFromServer = true;
+ if (!_changedData)
+ {
+ _data.rewind();
+ }
+ else
+ {
+ _data.flip();
+ _changedData = false;
+ }
}
+ public int getContentLength()
+ {
+ if(_data != null)
+ {
+ return _data.remaining();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ public void receivedFromServer()
+ {
+ _changedData = false;
+ }
/**
* The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
index 967a1fb49f..e719c9a4b2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.client.message;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentBody;
@@ -36,8 +38,6 @@ import javax.jms.JMSException;
import java.util.Iterator;
import java.util.List;
-import java.nio.ByteBuffer;
-
public abstract class AbstractJMSMessageFactory implements MessageFactory
{
private static final Logger _logger = LoggerFactory.getLogger(AbstractJMSMessageFactory.class);
@@ -57,7 +57,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
_logger.debug("Non-fragmented message body (bodySize=" + contentHeader.bodySize + ")");
}
- data = ByteBuffer.wrap(((ContentBody) bodies.get(0))._payload);
+ data = ((ContentBody) bodies.get(0)).payload;
}
else if (bodies != null)
{
@@ -72,7 +72,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
while (it.hasNext())
{
ContentBody cb = (ContentBody) it.next();
- final ByteBuffer payload = ByteBuffer.wrap(cb._payload);
+ final ByteBuffer payload = cb.payload;
if(payload.isDirect() || payload.isReadOnly())
{
data.put(payload);
@@ -82,6 +82,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
data.put(payload.array(), payload.arrayOffset(), payload.limit());
}
+ payload.release();
}
data.flip();
@@ -98,7 +99,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
}
AMQMessageDelegate delegate = new AMQMessageDelegate_0_8(messageNbr,
- (BasicContentHeaderProperties) contentHeader.getProperties(),
+ (BasicContentHeaderProperties) contentHeader.properties,
exchange, routingKey);
return createMessage(delegate, data);
@@ -108,7 +109,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
protected AbstractJMSMessage create010MessageWithBody(long messageNbr, MessageProperties msgProps,
- DeliveryProperties deliveryProps,
+ DeliveryProperties deliveryProps,
java.nio.ByteBuffer body) throws AMQException
{
ByteBuffer data;
@@ -117,7 +118,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
if (body != null)
{
- data = body;
+ data = ByteBuffer.wrap(body);
}
else // body == null
{
@@ -154,7 +155,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
{
final AbstractJMSMessage msg = create08MessageWithBody(messageNbr, contentHeader, exchange, routingKey, bodies);
msg.setJMSRedelivered(redelivered);
- msg.setReceivedFromServer();
+ msg.receivedFromServer();
return msg;
}
@@ -165,7 +166,7 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
final AbstractJMSMessage msg =
create010MessageWithBody(messageNbr,msgProps,deliveryProps, body);
msg.setJMSRedelivered(redelivered);
- msg.setReceivedFromServer();
+ msg.receivedFromServer();
return msg;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
index e252bdb719..b87275a9ce 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.client.message;
-import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
@@ -29,56 +28,47 @@ import java.nio.charset.CharsetEncoder;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
-import javax.jms.MessageEOFException;
import javax.jms.MessageFormatException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesMessage
+public class JMSBytesMessage extends AbstractBytesMessage implements BytesMessage
{
public static final String MIME_TYPE = "application/octet-stream";
- private TypedBytesContentReader _typedBytesContentReader;
- private TypedBytesContentWriter _typedBytesContentWriter;
-
public JMSBytesMessage(AMQMessageDelegateFactory delegateFactory)
{
- super(delegateFactory,false);
- _typedBytesContentWriter = new TypedBytesContentWriter();
+ this(delegateFactory,null);
+
+ }
+
+ /**
+ * Construct a bytes message with existing data.
+ *
+ * @param delegateFactory
+ * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
+ */
+ JMSBytesMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
+ {
+
+ super(delegateFactory, data); // this instanties a content header
}
JMSBytesMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(delegate, data!=null);
- _typedBytesContentReader = new TypedBytesContentReader(data);
+ super(delegate, data);
}
public void reset()
{
+ super.reset();
_readableMessage = true;
-
- if(_typedBytesContentReader != null)
- {
- _typedBytesContentReader.reset();
- }
- else if (_typedBytesContentWriter != null)
- {
- _typedBytesContentReader = new TypedBytesContentReader(_typedBytesContentWriter.getData());
- }
- }
-
- @Override
- public void clearBody() throws JMSException
- {
- super.clearBody();
- _typedBytesContentReader = null;
- _typedBytesContentWriter = new TypedBytesContentWriter();
-
}
protected String getMimeType()
@@ -86,57 +76,45 @@ public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesM
return MIME_TYPE;
}
- @Override
- public java.nio.ByteBuffer getData() throws JMSException
- {
- return _typedBytesContentWriter == null ? _typedBytesContentReader.getData() : _typedBytesContentWriter.getData();
- }
-
public long getBodyLength() throws JMSException
{
checkReadable();
- return _typedBytesContentReader.size();
+ return _data.limit();
}
public boolean readBoolean() throws JMSException
{
checkReadable();
checkAvailable(1);
-
- return _typedBytesContentReader.readBooleanImpl();
- }
-
- private void checkAvailable(final int i) throws MessageEOFException
- {
- _typedBytesContentReader.checkAvailable(1);
+ return _data.get() != 0;
}
public byte readByte() throws JMSException
{
checkReadable();
checkAvailable(1);
- return _typedBytesContentReader.readByteImpl();
+ return _data.get();
}
public int readUnsignedByte() throws JMSException
{
checkReadable();
checkAvailable(1);
- return _typedBytesContentReader.readByteImpl() & 0xFF;
+ return _data.getUnsigned();
}
public short readShort() throws JMSException
{
checkReadable();
checkAvailable(2);
- return _typedBytesContentReader.readShortImpl();
+ return _data.getShort();
}
public int readUnsignedShort() throws JMSException
{
checkReadable();
checkAvailable(2);
- return _typedBytesContentReader.readShortImpl() & 0xFFFF;
+ return _data.getUnsignedShort();
}
/**
@@ -149,35 +127,35 @@ public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesM
{
checkReadable();
checkAvailable(2);
- return _typedBytesContentReader.readCharImpl();
+ return _data.getChar();
}
public int readInt() throws JMSException
{
checkReadable();
checkAvailable(4);
- return _typedBytesContentReader.readIntImpl();
+ return _data.getInt();
}
public long readLong() throws JMSException
{
checkReadable();
checkAvailable(8);
- return _typedBytesContentReader.readLongImpl();
+ return _data.getLong();
}
public float readFloat() throws JMSException
{
checkReadable();
checkAvailable(4);
- return _typedBytesContentReader.readFloatImpl();
+ return _data.getFloat();
}
public double readDouble() throws JMSException
{
checkReadable();
checkAvailable(8);
- return _typedBytesContentReader.readDoubleImpl();
+ return _data.getDouble();
}
public String readUTF() throws JMSException
@@ -186,7 +164,34 @@ public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesM
// we check only for one byte since theoretically the string could be only a
// single byte when using UTF-8 encoding
- return _typedBytesContentReader.readLengthPrefixedUTF();
+ try
+ {
+ short length = readShort();
+ if(length == 0)
+ {
+ return "";
+ }
+ else
+ {
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+ ByteBuffer encodedString = _data.slice();
+ encodedString.limit(length);
+ _data.position(_data.position()+length);
+ CharBuffer string = decoder.decode(encodedString.buf());
+
+ return string.toString();
+ }
+
+
+
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException jmse = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
}
public int readBytes(byte[] bytes) throws JMSException
@@ -196,14 +201,14 @@ public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesM
throw new IllegalArgumentException("byte array must not be null");
}
checkReadable();
- int count = (_typedBytesContentReader.remaining() >= bytes.length ? bytes.length : _typedBytesContentReader.remaining());
+ int count = (_data.remaining() >= bytes.length ? bytes.length : _data.remaining());
if (count == 0)
{
return -1;
}
else
{
- _typedBytesContentReader.readRawBytes(bytes, 0, count);
+ _data.get(bytes, 0, count);
return count;
}
}
@@ -219,82 +224,110 @@ public class JMSBytesMessage extends AbstractBytesTypedMessage implements BytesM
throw new IllegalArgumentException("maxLength must be <= bytes.length");
}
checkReadable();
- int count = (_typedBytesContentReader.remaining() >= maxLength ? maxLength : _typedBytesContentReader.remaining());
+ int count = (_data.remaining() >= maxLength ? maxLength : _data.remaining());
if (count == 0)
{
return -1;
}
else
{
- _typedBytesContentReader.readRawBytes(bytes, 0, count);
+ _data.get(bytes, 0, count);
return count;
}
}
-
public void writeBoolean(boolean b) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeBooleanImpl(b);
+ _changedData = true;
+ _data.put(b ? (byte) 1 : (byte) 0);
}
public void writeByte(byte b) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeByteImpl(b);
+ _changedData = true;
+ _data.put(b);
}
public void writeShort(short i) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeShortImpl(i);
+ _changedData = true;
+ _data.putShort(i);
}
public void writeChar(char c) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeCharImpl(c);
+ _changedData = true;
+ _data.putChar(c);
}
public void writeInt(int i) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeIntImpl(i);
+ _changedData = true;
+ _data.putInt(i);
}
public void writeLong(long l) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeLongImpl(l);
+ _changedData = true;
+ _data.putLong(l);
}
public void writeFloat(float v) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeFloatImpl(v);
+ _changedData = true;
+ _data.putFloat(v);
}
public void writeDouble(double v) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeDoubleImpl(v);
+ _changedData = true;
+ _data.putDouble(v);
}
public void writeUTF(String string) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeLengthPrefixedUTF(string);
+ try
+ {
+ CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
+ java.nio.ByteBuffer encodedString = encoder.encode(CharBuffer.wrap(string));
+
+ _data.putShort((short)encodedString.limit());
+ _data.put(encodedString);
+ _changedData = true;
+ //_data.putString(string, Charset.forName("UTF-8").newEncoder());
+ // we must add the null terminator manually
+ //_data.put((byte)0);
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException jmse = new JMSException("Unable to encode string: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
}
public void writeBytes(byte[] bytes) throws JMSException
{
- writeBytes(bytes, 0, bytes.length);
+ checkWritable();
+ _data.put(bytes);
+ _changedData = true;
}
public void writeBytes(byte[] bytes, int offset, int length) throws JMSException
{
checkWritable();
- _typedBytesContentWriter.writeBytesRaw(bytes, offset, length);
+ _data.put(bytes, offset, length);
+ _changedData = true;
}
public void writeObject(Object object) throws JMSException
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
index 89561b88eb..cb04ebee1b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
@@ -22,12 +22,11 @@ package org.apache.qpid.client.message;
import javax.jms.JMSException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import java.nio.ByteBuffer;
-
public class JMSBytesMessageFactory extends AbstractJMSMessageFactory
{
protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
index 52c0eb263b..e295d4a2a0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
@@ -20,15 +20,12 @@
*/
package org.apache.qpid.client.message;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.util.Enumeration;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
-import java.nio.ByteBuffer;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQPInvalidClassException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -285,7 +282,7 @@ public final class JMSHeaderAdapter
s = String.valueOf(o);
}
}
- }//else return s // null;
+ }//else return s // null;
}
return s;
@@ -461,29 +458,9 @@ public final class JMSHeaderAdapter
return getHeaders().isEmpty();
}
- public void writeToBuffer(final ByteBuffer data)
+ public void writeToBuffer(ByteBuffer data)
{
- try
- {
- getHeaders().writeToBuffer(new DataOutputStream(new OutputStream()
- {
- @Override
- public void write(final int b)
- {
- data.put((byte)b);
- }
-
- @Override
- public void write(final byte[] b, final int off, final int len)
- {
- data.put(b, off, len);
- }
- }));
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("Unexpected IO Exception - should never happen", e);
- }
+ getHeaders().writeToBuffer(data);
}
public Enumeration getMapNames()
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
index fad24a968e..306ffeeadf 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
@@ -20,8 +20,11 @@
*/
package org.apache.qpid.client.message;
-import org.apache.qpid.AMQException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,14 +32,13 @@ import org.slf4j.LoggerFactory;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
-import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
-public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMessage
+public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jms.MapMessage
{
private static final Logger _logger = LoggerFactory.getLogger(JMSMapMessage.class);
@@ -52,10 +54,10 @@ public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMe
JMSMapMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data) throws JMSException
{
- super(delegateFactory, data!=null); // this instantiates a content header
+ super(delegateFactory, data); // this instantiates a content header
if(data != null)
{
- populateMapFromData(data);
+ populateMapFromData();
}
}
@@ -63,10 +65,10 @@ public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMe
JMSMapMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(delegate, data != null);
+ super(delegate, data);
try
{
- populateMapFromData(data);
+ populateMapFromData();
}
catch (JMSException je)
{
@@ -87,10 +89,18 @@ public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMe
return MIME_TYPE;
}
+ public ByteBuffer getData()
+ {
+ // What if _data is null?
+ writeMapToData();
+
+ return super.getData();
+ }
+
@Override
- public void clearBody() throws JMSException
+ public void clearBodyImpl() throws JMSException
{
- super.clearBody();
+ super.clearBodyImpl();
_map.clear();
}
@@ -448,18 +458,17 @@ public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMe
return _map.containsKey(propName);
}
- protected void populateMapFromData(ByteBuffer data) throws JMSException
+ protected void populateMapFromData() throws JMSException
{
- TypedBytesContentReader reader = new TypedBytesContentReader(data);
- if (data != null)
+ if (_data != null)
{
- data.rewind();
+ _data.rewind();
- final int entries = reader.readIntImpl();
+ final int entries = readIntImpl();
for (int i = 0; i < entries; i++)
{
- String propName = reader.readStringImpl();
- Object value = reader.readObject();
+ String propName = readStringImpl();
+ Object value = readObject();
_map.put(propName, value);
}
}
@@ -469,21 +478,35 @@ public class JMSMapMessage extends AbstractJMSMessage implements javax.jms.MapMe
}
}
- public ByteBuffer getData()
- throws JMSException
+ protected void writeMapToData()
{
- TypedBytesContentWriter writer = new TypedBytesContentWriter();
-
+ allocateInitialBuffer();
final int size = _map.size();
- writer.writeIntImpl(size);
+ writeIntImpl(size);
for (Map.Entry<String, Object> entry : _map.entrySet())
{
- writer.writeNullTerminatedStringImpl(entry.getKey());
+ try
+ {
+ writeStringImpl(entry.getKey());
+ }
+ catch (CharacterCodingException e)
+ {
+ throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey(), e);
+
+ }
- writer.writeObject(entry.getValue());
+ try
+ {
+ writeObject(entry.getValue());
+ }
+ catch (JMSException e)
+ {
+ Object value = entry.getValue();
+ throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey() + " value : " + value
+ + " (type: " + value.getClass().getName() + ").", e);
+ }
}
- return writer.getData();
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
index 89408a5c3c..eccb90560b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
@@ -14,16 +14,18 @@
* "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.
- *
+ * under the License.
*
+ *
*/
package org.apache.qpid.client.message;
import javax.jms.JMSException;
-import java.nio.ByteBuffer;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSMapMessageFactory extends AbstractJMSMessageFactory
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
index c981c951c3..637d9dd692 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
@@ -20,28 +20,26 @@
*/
package org.apache.qpid.client.message;
-import java.io.*;
-import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
import javax.jms.ObjectMessage;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.util.ClassLoadingAwareObjectInputStream;
public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessage
{
public static final String MIME_TYPE = "application/java-object-stream";
- private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 256;
-
- private Serializable _readData;
- private ByteBuffer _data;
- private Exception _exception;
-
- private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
+ private static final int DEFAULT_BUFFER_SIZE = 1024;
/**
* Creates empty, writable message for use by producers
@@ -49,57 +47,41 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
*/
public JMSObjectMessage(AMQMessageDelegateFactory delegateFactory)
{
- super(delegateFactory, false);
+ this(delegateFactory, null);
+ }
+
+ private JMSObjectMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
+ {
+ super(delegateFactory, data);
+ if (data == null)
+ {
+ _data = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
+ _data.setAutoExpand(true);
+ }
+
+ setContentType(getMimeType());
}
/**
* Creates read only message for delivery to consumers
*/
- JMSObjectMessage(AMQMessageDelegate delegate, final ByteBuffer data) throws AMQException
+ JMSObjectMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(delegate, data!=null);
-
- try
- {
- ClassLoadingAwareObjectInputStream in = new ClassLoadingAwareObjectInputStream(new InputStream()
- {
-
-
- @Override
- public int read() throws IOException
- {
- return data.get();
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException
- {
- len = data.remaining() < len ? data.remaining() : len;
- data.get(b, off, len);
- return len;
- }
- });
-
- _readData = (Serializable) in.readObject();
- }
- catch (IOException e)
- {
- _exception = e;
- }
- catch (ClassNotFoundException e)
- {
- _exception = e;
- }
+ super(delegate, data);
}
- public void clearBody() throws JMSException
+ public void clearBodyImpl() throws JMSException
{
- super.clearBody();
- _exception = null;
- _readData = null;
- _data = null;
+ if (_data != null)
+ {
+ _data.release();
+ _data = null;
+ }
+
+
+
}
public String toBodyString() throws JMSException
@@ -112,116 +94,83 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
return MIME_TYPE;
}
- @Override
- public ByteBuffer getData() throws JMSException
+ public void setObject(Serializable serializable) throws JMSException
{
- if(_exception != null)
- {
- final MessageFormatException messageFormatException =
- new MessageFormatException("Unable to deserialize message");
- messageFormatException.setLinkedException(_exception);
- throw messageFormatException;
- }
- if(_readData == null)
- {
+ checkWritable();
- return _data == null ? EMPTY_BYTE_BUFFER : _data.duplicate();
+ if (_data == null)
+ {
+ _data = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
+ _data.setAutoExpand(true);
}
else
{
- try
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream(DEFAULT_OUTPUT_BUFFER_SIZE);
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(_readData);
- oos.flush();
- return ByteBuffer.wrap(baos.toByteArray());
- }
- catch (IOException e)
- {
- final JMSException jmsException = new JMSException("Unable to encode object of type: " +
- _readData.getClass().getName() + ", value " + _readData);
- jmsException.setLinkedException(e);
- throw jmsException;
- }
+ _data.rewind();
}
- }
-
- public void setObject(Serializable serializable) throws JMSException
- {
- checkWritable();
- clearBody();
try
{
- ByteArrayOutputStream baos = new ByteArrayOutputStream(DEFAULT_OUTPUT_BUFFER_SIZE);
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(serializable);
- oos.flush();
- _data = ByteBuffer.wrap(baos.toByteArray());
+ ObjectOutputStream out = new ObjectOutputStream(_data.asOutputStream());
+ out.writeObject(serializable);
+ out.flush();
+ out.close();
}
catch (IOException e)
{
- final JMSException jmsException = new JMSException("Unable to encode object of type: " +
- serializable.getClass().getName() + ", value " + serializable);
- jmsException.setLinkedException(e);
- throw jmsException;
+ MessageFormatException mfe = new MessageFormatException("Message not serializable: " + e);
+ mfe.setLinkedException(e);
+ mfe.initCause(e);
+ throw mfe;
}
}
public Serializable getObject() throws JMSException
{
- if(_exception != null)
+ ObjectInputStream in = null;
+ if (_data == null)
{
- final MessageFormatException messageFormatException = new MessageFormatException("Unable to deserialize message");
- messageFormatException.setLinkedException(_exception);
- throw messageFormatException;
+ return null;
}
- else if(_readData != null || _data == null)
+
+ try
{
- return _readData;
+ _data.rewind();
+ in = new ObjectInputStream(_data.asInputStream());
+
+ return (Serializable) in.readObject();
}
- else
+ catch (IOException e)
+ {
+ MessageFormatException mfe = new MessageFormatException("Could not deserialize message: " + e);
+ mfe.setLinkedException(e);
+ mfe.initCause(e);
+ throw mfe;
+ }
+ catch (ClassNotFoundException e)
+ {
+ MessageFormatException mfe = new MessageFormatException("Could not deserialize message: " + e);
+ mfe.setLinkedException(e);
+ mfe.initCause(e);
+ throw mfe;
+ }
+ finally
{
- Exception exception = null;
+ // _data.rewind();
+ close(in);
+ }
+ }
- final ByteBuffer data = _data.duplicate();
- try
- {
- ClassLoadingAwareObjectInputStream in = new ClassLoadingAwareObjectInputStream(new InputStream()
- {
- @Override
- public int read() throws IOException
- {
- return data.get();
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException
- {
- len = data.remaining() < len ? data.remaining() : len;
- data.get(b, off, len);
- return len;
- }
- });
-
- return (Serializable) in.readObject();
- }
- catch (ClassNotFoundException e)
- {
- exception = e;
- }
- catch (IOException e)
+ private static void close(InputStream in)
+ {
+ try
+ {
+ if (in != null)
{
- exception = e;
+ in.close();
}
-
- JMSException jmsException = new JMSException("Could not deserialize object");
- jmsException.setLinkedException(exception);
- throw jmsException;
}
-
+ catch (IOException ignore)
+ { }
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
index 4660c91c1f..03851dfa01 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
@@ -7,9 +7,9 @@
* 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
@@ -22,8 +22,10 @@ package org.apache.qpid.client.message;
import javax.jms.JMSException;
-import java.nio.ByteBuffer;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSObjectMessageFactory extends AbstractJMSMessageFactory
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
index 5c93f6b6f0..ad2620852b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
@@ -23,8 +23,7 @@ package org.apache.qpid.client.message;
import javax.jms.JMSException;
import javax.jms.StreamMessage;
-import java.nio.ByteBuffer;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -37,76 +36,65 @@ public class JMSStreamMessage extends AbstractBytesTypedMessage implements Strea
public static final String MIME_TYPE="jms/stream-message";
- private TypedBytesContentReader _typedBytesContentReader;
- private TypedBytesContentWriter _typedBytesContentWriter;
+
+ /**
+ * This is set when reading a byte array. The readBytes(byte[]) method supports multiple calls to read
+ * a byte array in multiple chunks, hence this is used to track how much is left to be read
+ */
+ private int _byteArrayRemaining = -1;
public JMSStreamMessage(AMQMessageDelegateFactory delegateFactory)
{
- super(delegateFactory,false);
- _typedBytesContentWriter = new TypedBytesContentWriter();
+ this(delegateFactory,null);
}
+ /**
+ * Construct a stream message with existing data.
+ *
+ * @param delegateFactory
+ * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
+ */
+ JMSStreamMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
+ {
+ super(delegateFactory, data); // this instanties a content header
+ }
JMSStreamMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(delegate, data!=null);
- _typedBytesContentReader = new TypedBytesContentReader(data);
+
+ super(delegate, data);
}
+
public void reset()
{
+ super.reset();
_readableMessage = true;
-
- if(_typedBytesContentReader != null)
- {
- _typedBytesContentReader.reset();
- }
- else if (_typedBytesContentWriter != null)
- {
- _typedBytesContentReader = new TypedBytesContentReader(_typedBytesContentWriter.getData());
- }
- }
-
- @Override
- public void clearBody() throws JMSException
- {
- super.clearBody();
- _typedBytesContentReader = null;
- _typedBytesContentWriter = new TypedBytesContentWriter();
-
}
-
protected String getMimeType()
{
return MIME_TYPE;
}
- @Override
- public java.nio.ByteBuffer getData() throws JMSException
- {
- return _typedBytesContentWriter == null ? _typedBytesContentReader.getData() : _typedBytesContentWriter.getData();
- }
+
public boolean readBoolean() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readBoolean();
+ return super.readBoolean();
}
public byte readByte() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readByte();
+ return super.readByte();
}
public short readShort() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readShort();
+ return super.readShort();
}
/**
@@ -117,127 +105,102 @@ public class JMSStreamMessage extends AbstractBytesTypedMessage implements Strea
*/
public char readChar() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readChar();
+ return super.readChar();
}
public int readInt() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readInt();
+ return super.readInt();
}
public long readLong() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readLong();
+ return super.readLong();
}
public float readFloat() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readFloat();
+ return super.readFloat();
}
public double readDouble() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readDouble();
+ return super.readDouble();
}
public String readString() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readString();
+ return super.readString();
}
public int readBytes(byte[] bytes) throws JMSException
{
- if(bytes == null)
- {
- throw new IllegalArgumentException("Must provide non-null array to read into");
- }
-
- checkReadable();
- return _typedBytesContentReader.readBytes(bytes);
+ return super.readBytes(bytes);
}
public Object readObject() throws JMSException
{
- checkReadable();
- return _typedBytesContentReader.readObject();
+ return super.readObject();
}
public void writeBoolean(boolean b) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeBoolean(b);
+ super.writeBoolean(b);
}
public void writeByte(byte b) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeByte(b);
+ super.writeByte(b);
}
public void writeShort(short i) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeShort(i);
+ super.writeShort(i);
}
public void writeChar(char c) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeChar(c);
+ super.writeChar(c);
}
public void writeInt(int i) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeInt(i);
+ super.writeInt(i);
}
public void writeLong(long l) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeLong(l);
+ super.writeLong(l);
}
public void writeFloat(float v) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeFloat(v);
+ super.writeFloat(v);
}
public void writeDouble(double v) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeDouble(v);
+ super.writeDouble(v);
}
public void writeString(String string) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeString(string);
+ super.writeString(string);
}
public void writeBytes(byte[] bytes) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeBytes(bytes);
+ super.writeBytes(bytes);
}
public void writeBytes(byte[] bytes, int offset, int length) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeBytes(bytes, offset, length);
+ super.writeBytes(bytes,offset,length);
}
public void writeObject(Object object) throws JMSException
{
- checkWritable();
- _typedBytesContentWriter.writeObject(object);
+ super.writeObject(object);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
index 359f5157f3..5e25db9ae0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
@@ -22,9 +22,10 @@ package org.apache.qpid.client.message;
import javax.jms.JMSException;
-import java.nio.ByteBuffer;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSStreamMessageFactory extends AbstractJMSMessageFactory
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
index acf3a0ca14..fc2006a119 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
@@ -20,21 +20,15 @@
*/
package org.apache.qpid.client.message;
-import java.io.DataInputStream;
import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
import javax.jms.JMSException;
-import javax.jms.MessageFormatException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.CustomJMSXProperty;
-import org.apache.qpid.framing.AMQFrameDecodingException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.util.Strings;
@@ -43,7 +37,6 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
{
private static final String MIME_TYPE = "text/plain";
- private Exception _exception;
private String _decodedValue;
/**
@@ -52,41 +45,36 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
private static final String PAYLOAD_NULL_PROPERTY = CustomJMSXProperty.JMS_AMQP_NULL.toString();
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
- private CharsetDecoder _decoder = DEFAULT_CHARSET.newDecoder();
- private CharsetEncoder _encoder = DEFAULT_CHARSET.newEncoder();
-
- private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
-
public JMSTextMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- super(delegateFactory, false); // this instantiates a content header
+ this(delegateFactory, null, null);
+ }
+
+ JMSTextMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data, String encoding) throws JMSException
+ {
+ super(delegateFactory, data); // this instantiates a content header
+ setContentType(getMimeType());
+ setEncoding(encoding);
}
JMSTextMessage(AMQMessageDelegate delegate, ByteBuffer data)
throws AMQException
{
- super(delegate, data!=null);
+ super(delegate, data);
+ setContentType(getMimeType());
+ _data = data;
+ }
- try
- {
- if(propertyExists(PAYLOAD_NULL_PROPERTY))
- {
- _decodedValue = null;
- }
- else
- {
- _decodedValue = _decoder.decode(data).toString();
- }
- }
- catch (CharacterCodingException e)
- {
- _exception = e;
- }
- catch (JMSException e)
+
+ public void clearBodyImpl() throws JMSException
+ {
+ if (_data != null)
{
- _exception = e;
+ _data.release();
+ _data = null;
}
+ _decodedValue = null;
}
public String toBodyString() throws JMSException
@@ -99,62 +87,95 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
return MIME_TYPE;
}
- @Override
- public ByteBuffer getData() throws JMSException
+ public void setText(String text) throws JMSException
{
- _encoder.reset();
+ checkWritable();
+
+ clearBody();
try
{
- if(_exception != null)
- {
- final MessageFormatException messageFormatException = new MessageFormatException("Cannot decode original message");
- messageFormatException.setLinkedException(_exception);
- throw messageFormatException;
- }
- else if(_decodedValue == null)
- {
- return EMPTY_BYTE_BUFFER;
- }
- else
+ if (text != null)
{
- return _encoder.encode(CharBuffer.wrap(_decodedValue));
+ final String encoding = getEncoding();
+ if (encoding == null || encoding.equalsIgnoreCase("UTF-8"))
+ {
+ _data = ByteBuffer.wrap(Strings.toUTF8(text));
+ setEncoding("UTF-8");
+ }
+ else
+ {
+ _data = ByteBuffer.wrap(text.getBytes(encoding));
+ }
+ _data.position(_data.limit());
+ _changedData=true;
}
+ _decodedValue = text;
}
- catch (CharacterCodingException e)
+ catch (UnsupportedEncodingException e)
{
- final JMSException jmsException = new JMSException("Cannot encode string in UFT-8: " + _decodedValue);
- jmsException.setLinkedException(e);
- throw jmsException;
+ // should never occur
+ JMSException jmse = new JMSException("Unable to decode text data");
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
}
}
- @Override
- public void clearBody() throws JMSException
- {
- super.clearBody();
- _decodedValue = null;
- _exception = null;
- }
-
- public void setText(String text) throws JMSException
- {
- checkWritable();
-
- clearBody();
- _decodedValue = text;
-
- }
-
public String getText() throws JMSException
{
- return _decodedValue;
+ if (_data == null && _decodedValue == null)
+ {
+ return null;
+ }
+ else if (_decodedValue != null)
+ {
+ return _decodedValue;
+ }
+ else
+ {
+ _data.rewind();
+
+ if (propertyExists(PAYLOAD_NULL_PROPERTY) && getBooleanProperty(PAYLOAD_NULL_PROPERTY))
+ {
+ return null;
+ }
+ if (getEncoding() != null)
+ {
+ try
+ {
+ _decodedValue = _data.getString(Charset.forName(getEncoding()).newDecoder());
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException jmse = new JMSException("Could not decode string data: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+ }
+ else
+ {
+ try
+ {
+ _decodedValue = _data.getString(DEFAULT_CHARSET.newDecoder());
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException jmse = new JMSException("Could not decode string data: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+ }
+ return _decodedValue;
+ }
}
@Override
public void prepareForSending() throws JMSException
{
super.prepareForSending();
- if (_decodedValue == null)
+ if (_data == null)
{
setBooleanProperty(PAYLOAD_NULL_PROPERTY, true);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
index d1af32c10a..1f4d64c78f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
@@ -22,7 +22,7 @@ package org.apache.qpid.client.message;
import javax.jms.JMSException;
-import java.nio.ByteBuffer;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
index cdb75fc9a9..4e4061cf4d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
@@ -104,7 +104,7 @@ public class MessageFactoryRegistry
AMQShortString routingKey, ContentHeaderBody contentHeader, List bodies)
throws AMQException, JMSException
{
- BasicContentHeaderProperties properties = (BasicContentHeaderProperties) contentHeader.getProperties();
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties) contentHeader.properties;
// Get the message content type. This may be null for pure AMQP messages, but will always be set for JMS over
// AMQP. When the type is null, it can only be assumed that the message is a byte message.
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/QpidMessageProperties.java b/java/client/src/main/java/org/apache/qpid/client/message/QpidMessageProperties.java
deleted file mode 100644
index b30afafa35..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/message/QpidMessageProperties.java
+++ /dev/null
@@ -1,34 +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.
- *
- */
-package org.apache.qpid.client.message;
-
-/**
- * Place holder for Qpid specific message properties
- */
-public class QpidMessageProperties
-{
-
- public static final String QPID_SUBJECT = "qpid.subject";
-
- // AMQP 0-10 related properties
- public static final String AMQP_0_10_APP_ID = "x-amqp-0-10.app-id";
- public static final String AMQP_0_10_ROUTING_KEY = "x-amqp-0-10.routing-key";
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesCodes.java b/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesCodes.java
deleted file mode 100644
index 26a0b41cdc..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesCodes.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.client.message;
-
-public interface TypedBytesCodes
-{
- static final byte BOOLEAN_TYPE = (byte) 1;
-
- static final byte BYTE_TYPE = (byte) 2;
-
- static final byte BYTEARRAY_TYPE = (byte) 3;
-
- static final byte SHORT_TYPE = (byte) 4;
-
- static final byte CHAR_TYPE = (byte) 5;
-
- static final byte INT_TYPE = (byte) 6;
-
- static final byte LONG_TYPE = (byte) 7;
-
- static final byte FLOAT_TYPE = (byte) 8;
-
- static final byte DOUBLE_TYPE = (byte) 9;
-
- static final byte STRING_TYPE = (byte) 10;
-
- static final byte NULL_STRING_TYPE = (byte) 11;
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentReader.java b/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentReader.java
deleted file mode 100644
index 1ae25eb1ed..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentReader.java
+++ /dev/null
@@ -1,674 +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.
- *
- */
-package org.apache.qpid.client.message;
-
-import javax.jms.JMSException;
-import javax.jms.MessageEOFException;
-import javax.jms.MessageFormatException;
-import javax.jms.MessageNotReadableException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-
-class TypedBytesContentReader implements TypedBytesCodes
-{
-
- private final ByteBuffer _data;
- private final int _position;
- private final int _limit;
-
-
- private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
-
- private final CharsetDecoder _charsetDecoder = UTF8_CHARSET.newDecoder();
-
- private int _byteArrayRemaining = -1;
-
-
- public TypedBytesContentReader(final ByteBuffer data)
- {
- _data = data.duplicate();
- _position = _data.position();
- _limit = _data.limit();
- }
-
- /**
- * Check that there is at least a certain number of bytes available to read
- *
- * @param len the number of bytes
- * @throws javax.jms.MessageEOFException if there are less than len bytes available to read
- */
- protected void checkAvailable(int len) throws MessageEOFException
- {
- if (_data.remaining() < len)
- {
- throw new MessageEOFException("Unable to read " + len + " bytes");
- }
- }
-
- protected byte readWireType() throws MessageFormatException, MessageEOFException,
- MessageNotReadableException
- {
- checkAvailable(1);
- return _data.get();
- }
-
- protected boolean readBoolean() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- boolean result;
- try
- {
- switch (wireType)
- {
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = readBooleanImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Boolean.parseBoolean(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a boolean");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- boolean readBooleanImpl()
- {
- return _data.get() != 0;
- }
-
- protected byte readByte() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- byte result;
- try
- {
- switch (wireType)
- {
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Byte.parseByte(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a byte");
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- return result;
- }
-
- byte readByteImpl()
- {
- return _data.get();
- }
-
- protected short readShort() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- short result;
- try
- {
- switch (wireType)
- {
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Short.parseShort(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a short");
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- return result;
- }
-
- short readShortImpl()
- {
- return _data.getShort();
- }
-
- /**
- * Note that this method reads a unicode character as two bytes from the stream
- *
- * @return the character read from the stream
- * @throws javax.jms.JMSException
- */
- protected char readChar() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- try
- {
- if (wireType == NULL_STRING_TYPE)
- {
- throw new NullPointerException();
- }
-
- if (wireType != CHAR_TYPE)
- {
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a char");
- }
- else
- {
- checkAvailable(2);
- return readCharImpl();
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- char readCharImpl()
- {
- return _data.getChar();
- }
-
- protected int readInt() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- int result;
- try
- {
- switch (wireType)
- {
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Integer.parseInt(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to an int");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- protected int readIntImpl()
- {
- return _data.getInt();
- }
-
- protected long readLong() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- long result;
- try
- {
- switch (wireType)
- {
- case LONG_TYPE:
- checkAvailable(8);
- result = readLongImpl();
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Long.parseLong(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a long");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- long readLongImpl()
- {
- return _data.getLong();
- }
-
- protected float readFloat() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- float result;
- try
- {
- switch (wireType)
- {
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Float.parseFloat(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a float");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- float readFloatImpl()
- {
- return _data.getFloat();
- }
-
- protected double readDouble() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- double result;
- try
- {
- switch (wireType)
- {
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = readDoubleImpl();
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Double.parseDouble(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a double");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- double readDoubleImpl()
- {
- return _data.getDouble();
- }
-
- protected String readString() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- String result;
- try
- {
- switch (wireType)
- {
- case STRING_TYPE:
- checkAvailable(1);
- result = readStringImpl();
- break;
- case NULL_STRING_TYPE:
- result = null;
- throw new NullPointerException("data is null");
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = String.valueOf(readBooleanImpl());
- break;
- case LONG_TYPE:
- checkAvailable(8);
- result = String.valueOf(readLongImpl());
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = String.valueOf(readIntImpl());
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = String.valueOf(readShortImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = String.valueOf(readByteImpl());
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = String.valueOf(readFloatImpl());
- break;
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = String.valueOf(readDoubleImpl());
- break;
- case CHAR_TYPE:
- checkAvailable(2);
- result = String.valueOf(readCharImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a String");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- protected String readStringImpl() throws JMSException
- {
- try
- {
- _charsetDecoder.reset();
- ByteBuffer dup = _data.duplicate();
- int pos = _data.position();
- byte b;
- while((b = _data.get()) != 0);
- dup.limit(_data.position()-1);
- return _charsetDecoder.decode(dup).toString();
-
- }
- catch (CharacterCodingException e)
- {
- JMSException jmse = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
- jmse.setLinkedException(e);
- jmse.initCause(e);
- throw jmse;
- }
- }
-
- protected int readBytes(byte[] bytes) throws JMSException
- {
- if (bytes == null)
- {
- throw new IllegalArgumentException("byte array must not be null");
- }
- // first call
- if (_byteArrayRemaining == -1)
- {
- // type discriminator checked separately so you get a MessageFormatException rather than
- // an EOF even in the case where both would be applicable
- checkAvailable(1);
- byte wireType = readWireType();
- if (wireType != BYTEARRAY_TYPE)
- {
- throw new MessageFormatException("Unable to convert " + wireType + " to a byte array");
- }
- checkAvailable(4);
- int size = _data.getInt();
- // length of -1 indicates null
- if (size == -1)
- {
- return -1;
- }
- else
- {
- if (size > _data.remaining())
- {
- throw new MessageEOFException("Byte array has stated length "
- + size
- + " but message only contains "
- +
- _data.remaining()
- + " bytes");
- }
- else
- {
- _byteArrayRemaining = size;
- }
- }
- }
- else if (_byteArrayRemaining == 0)
- {
- _byteArrayRemaining = -1;
- return -1;
- }
-
- int returnedSize = readBytesImpl(bytes);
- if (returnedSize < bytes.length)
- {
- _byteArrayRemaining = -1;
- }
- return returnedSize;
- }
-
- private int readBytesImpl(byte[] bytes)
- {
- int count = (_byteArrayRemaining >= bytes.length ? bytes.length : _byteArrayRemaining);
- _byteArrayRemaining -= count;
-
- if (count == 0)
- {
- return 0;
- }
- else
- {
- _data.get(bytes, 0, count);
- return count;
- }
- }
-
- protected Object readObject() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- Object result = null;
- try
- {
- switch (wireType)
- {
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = readBooleanImpl();
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- case BYTEARRAY_TYPE:
- checkAvailable(4);
- int size = _data.getInt();
- if (size == -1)
- {
- result = null;
- }
- else
- {
- _byteArrayRemaining = size;
- byte[] bytesResult = new byte[size];
- readBytesImpl(bytesResult);
- result = bytesResult;
- }
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case CHAR_TYPE:
- checkAvailable(2);
- result = readCharImpl();
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case LONG_TYPE:
- checkAvailable(8);
- result = readLongImpl();
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = readDoubleImpl();
- break;
- case NULL_STRING_TYPE:
- result = null;
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = readStringImpl();
- break;
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- public void reset()
- {
- _byteArrayRemaining = -1;
- _data.position(_position);
- _data.limit(_limit);
- }
-
- public ByteBuffer getData()
- {
- ByteBuffer buf = _data.duplicate();
- buf.position(_position);
- buf.limit(_limit);
- return buf;
- }
-
- public long size()
- {
- return _limit - _position;
- }
-
- public int remaining()
- {
- return _data.remaining();
- }
-
- public void readRawBytes(final byte[] bytes, final int offset, final int count)
- {
- _data.get(bytes, offset, count);
- }
-
- public String readLengthPrefixedUTF() throws JMSException
- {
- try
- {
- short length = readShortImpl();
- if(length == 0)
- {
- return "";
- }
- else
- {
- _charsetDecoder.reset();
- ByteBuffer encodedString = _data.slice();
- encodedString.limit(length);
- _data.position(_data.position()+length);
- CharBuffer string = _charsetDecoder.decode(encodedString);
-
- return string.toString();
- }
- }
- catch(CharacterCodingException e)
- {
- JMSException jmse = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
- jmse.setLinkedException(e);
- jmse.initCause(e);
- throw jmse;
- }
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentWriter.java b/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentWriter.java
deleted file mode 100644
index 7c91db3a32..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/message/TypedBytesContentWriter.java
+++ /dev/null
@@ -1,370 +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.
- *
- */
-package org.apache.qpid.client.message;
-
-import javax.jms.JMSException;
-import javax.jms.MessageFormatException;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-
-class TypedBytesContentWriter implements TypedBytesCodes
-{
- private final ByteArrayOutputStream _baos = new ByteArrayOutputStream();
- private final DataOutputStream _data = new DataOutputStream(_baos);
- private static final Charset UTF8 = Charset.forName("UTF-8");
-
- protected void writeTypeDiscriminator(byte type) throws JMSException
- {
- try
- {
- _data.writeByte(type);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- private JMSException handle(final IOException e)
- {
- JMSException jmsEx = new JMSException("Unable to write value: " + e.getMessage());
- jmsEx.setLinkedException(e);
- return jmsEx;
- }
-
-
- protected void writeBoolean(boolean b) throws JMSException
- {
- writeTypeDiscriminator(BOOLEAN_TYPE);
- writeBooleanImpl(b);
- }
-
- public void writeBooleanImpl(final boolean b) throws JMSException
- {
- try
- {
- _data.writeByte(b ? (byte) 1 : (byte) 0);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeByte(byte b) throws JMSException
- {
- writeTypeDiscriminator(BYTE_TYPE);
- writeByteImpl(b);
- }
-
- public void writeByteImpl(final byte b) throws JMSException
- {
- try
- {
- _data.writeByte(b);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeShort(short i) throws JMSException
- {
- writeTypeDiscriminator(SHORT_TYPE);
- writeShortImpl(i);
- }
-
- public void writeShortImpl(final short i) throws JMSException
- {
- try
- {
- _data.writeShort(i);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeChar(char c) throws JMSException
- {
- writeTypeDiscriminator(CHAR_TYPE);
- writeCharImpl(c);
- }
-
- public void writeCharImpl(final char c) throws JMSException
- {
- try
- {
- _data.writeChar(c);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeInt(int i) throws JMSException
- {
- writeTypeDiscriminator(INT_TYPE);
- writeIntImpl(i);
- }
-
- protected void writeIntImpl(int i) throws JMSException
- {
- try
- {
- _data.writeInt(i);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeLong(long l) throws JMSException
- {
- writeTypeDiscriminator(LONG_TYPE);
- writeLongImpl(l);
- }
-
- public void writeLongImpl(final long l) throws JMSException
- {
- try
- {
- _data.writeLong(l);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeFloat(float v) throws JMSException
- {
- writeTypeDiscriminator(FLOAT_TYPE);
- writeFloatImpl(v);
- }
-
- public void writeFloatImpl(final float v) throws JMSException
- {
- try
- {
- _data.writeFloat(v);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeDouble(double v) throws JMSException
- {
- writeTypeDiscriminator(DOUBLE_TYPE);
- writeDoubleImpl(v);
- }
-
- public void writeDoubleImpl(final double v) throws JMSException
- {
- try
- {
- _data.writeDouble(v);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- protected void writeString(String string) throws JMSException
- {
- if (string == null)
- {
- writeTypeDiscriminator(NULL_STRING_TYPE);
- }
- else
- {
- writeTypeDiscriminator(STRING_TYPE);
- writeNullTerminatedStringImpl(string);
- }
- }
-
- protected void writeNullTerminatedStringImpl(String string)
- throws JMSException
- {
- try
- {
- _data.write(string.getBytes(UTF8));
- _data.writeByte((byte) 0);
- }
- catch (IOException e)
- {
- throw handle(e);
- }
-
- }
-
- protected void writeBytes(byte[] bytes) throws JMSException
- {
- writeBytes(bytes, 0, bytes == null ? 0 : bytes.length);
- }
-
- protected void writeBytes(byte[] bytes, int offset, int length) throws JMSException
- {
- writeTypeDiscriminator(BYTEARRAY_TYPE);
- writeBytesImpl(bytes, offset, length);
- }
-
- public void writeBytesImpl(final byte[] bytes, final int offset, final int length) throws JMSException
- {
- try
- {
- if (bytes == null)
- {
- _data.writeInt(-1);
- }
- else
- {
- _data.writeInt(length);
- _data.write(bytes, offset, length);
- }
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
- public void writeBytesRaw(final byte[] bytes, final int offset, final int length) throws JMSException
- {
- try
- {
- if (bytes != null)
- {
- _data.write(bytes, offset, length);
- }
- }
- catch (IOException e)
- {
- throw handle(e);
- }
- }
-
-
- protected void writeObject(Object object) throws JMSException
- {
- Class clazz;
-
- if (object == null)
- {
- // string handles the output of null values
- clazz = String.class;
- }
- else
- {
- clazz = object.getClass();
- }
-
- if (clazz == Byte.class)
- {
- writeByte((Byte) object);
- }
- else if (clazz == Boolean.class)
- {
- writeBoolean((Boolean) object);
- }
- else if (clazz == byte[].class)
- {
- writeBytes((byte[]) object);
- }
- else if (clazz == Short.class)
- {
- writeShort((Short) object);
- }
- else if (clazz == Character.class)
- {
- writeChar((Character) object);
- }
- else if (clazz == Integer.class)
- {
- writeInt((Integer) object);
- }
- else if (clazz == Long.class)
- {
- writeLong((Long) object);
- }
- else if (clazz == Float.class)
- {
- writeFloat((Float) object);
- }
- else if (clazz == Double.class)
- {
- writeDouble((Double) object);
- }
- else if (clazz == String.class)
- {
- writeString((String) object);
- }
- else
- {
- throw new MessageFormatException("Only primitives plus byte arrays and String are valid types");
- }
- }
-
- public ByteBuffer getData()
- {
- return ByteBuffer.wrap(_baos.toByteArray());
- }
-
- public void writeLengthPrefixedUTF(final String string) throws JMSException
- {
- try
- {
- CharsetEncoder encoder = UTF8.newEncoder();
- java.nio.ByteBuffer encodedString = encoder.encode(CharBuffer.wrap(string));
-
- writeShortImpl((short) encodedString.limit());
- while(encodedString.hasRemaining())
- {
- _data.writeByte(encodedString.get());
- }
- }
- catch (CharacterCodingException e)
- {
- JMSException jmse = new JMSException("Unable to encode string: " + e);
- jmse.setLinkedException(e);
- jmse.initCause(e);
- throw jmse;
- }
- catch (IOException e)
- {
- throw handle(e);
- }
-
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
index ce87a112c9..685e646d85 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
@@ -87,9 +87,9 @@ public class UnprocessedMessage_0_8 extends UnprocessedMessage
public void receiveBody(ContentBody body)
{
- if (body._payload != null)
+ if (body.payload != null)
{
- final long payloadSize = body._payload.length;
+ final long payloadSize = body.payload.remaining();
if (_bodies == null)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java b/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java
index 368ec60525..00503cc650 100644
--- a/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java
+++ b/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java
@@ -27,7 +27,6 @@ import java.util.Map;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQDestination.Binding;
-import org.apache.qpid.client.messaging.address.Link.Reliability;
import org.apache.qpid.client.messaging.address.Link.Subscription;
import org.apache.qpid.client.messaging.address.Node.ExchangeNode;
import org.apache.qpid.client.messaging.address.Node.QueueNode;
@@ -55,7 +54,7 @@ public class AddressHelper
public static final String EXCLUSIVE = "exclusive";
public static final String AUTO_DELETE = "auto-delete";
public static final String TYPE = "type";
- public static final String ALT_EXCHANGE = "alternate-exchange";
+ public static final String ALT_EXCHANGE = "alt-exchange";
public static final String BINDINGS = "bindings";
public static final String BROWSE = "browse";
public static final String MODE = "mode";
@@ -232,9 +231,14 @@ public class AddressHelper
private boolean getDurability(Map map)
{
- Accessor access = new MapAccessor(map);
- Boolean result = access.getBoolean(DURABLE);
- return (result == null) ? false : result.booleanValue();
+ if (map != null && map.get(DURABLE) != null)
+ {
+ return Boolean.parseBoolean((String)map.get(DURABLE));
+ }
+ else
+ {
+ return false;
+ }
}
/**
@@ -258,7 +262,7 @@ public class AddressHelper
}
}
- public Link getLink() throws Exception
+ public Link getLink()
{
Link link = new Link();
link.setSubscription(new Subscription());
@@ -268,25 +272,6 @@ public class AddressHelper
: linkProps.getBoolean(DURABLE));
link.setName(linkProps.getString(NAME));
- String reliability = linkProps.getString(RELIABILITY);
- if ( reliability != null)
- {
- if (reliability.equalsIgnoreCase("unreliable"))
- {
- link.setReliability(Reliability.UNRELIABLE);
- }
- else if (reliability.equalsIgnoreCase("at-least-once"))
- {
- link.setReliability(Reliability.AT_LEAST_ONCE);
- }
- else
- {
- throw new Exception("The reliability mode '" +
- reliability + "' is not yet supported");
- }
-
- }
-
if (((Map) address.getOptions().get(LINK)).get(CAPACITY) instanceof Map)
{
MapAccessor capacityProps = new MapAccessor(
diff --git a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java
index 5f97d625b4..a7d19d1bd5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java
+++ b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.client.messaging.address;
-import static org.apache.qpid.client.messaging.address.Link.Reliability.UNSPECIFIED;
-
import java.util.HashMap;
import java.util.Map;
@@ -31,8 +29,6 @@ public class Link
{
public enum FilterType { SQL92, XQUERY, SUBJECT }
- public enum Reliability { UNRELIABLE, AT_MOST_ONCE, AT_LEAST_ONCE, EXACTLY_ONCE, UNSPECIFIED }
-
protected String name;
protected String _filter;
protected FilterType _filterType = FilterType.SUBJECT;
@@ -42,18 +38,7 @@ public class Link
protected int _producerCapacity = 0;
protected Node node;
protected Subscription subscription;
- protected Reliability reliability = UNSPECIFIED;
- public Reliability getReliability()
- {
- return reliability;
- }
-
- public void setReliability(Reliability reliability)
- {
- this.reliability = reliability;
- }
-
public Node getNode()
{
return node;
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index 284954edba..eb5af119b2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.client.protocol;
-import java.io.DataOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -30,8 +28,10 @@ import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
+import org.apache.mina.filter.codec.ProtocolCodecException;
import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
@@ -46,7 +46,6 @@ import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateWaiter;
import org.apache.qpid.client.state.listener.SpecificMethodFrameListener;
import org.apache.qpid.codec.AMQCodecFactory;
-import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.framing.AMQBody;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.AMQFrame;
@@ -58,13 +57,16 @@ import org.apache.qpid.framing.HeartbeatBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.ProtocolInitiation;
import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.pool.Job;
+import org.apache.qpid.pool.ReferenceCountingExecutorService;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
import org.apache.qpid.protocol.ProtocolEngine;
import org.apache.qpid.thread.Threading;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.network.io.IoTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -162,22 +164,20 @@ public class AMQProtocolHandler implements ProtocolEngine
private FailoverException _lastFailoverException;
/** Defines the default timeout to use for synchronous protocol commands. */
- private final long DEFAULT_SYNC_TIMEOUT = Long.getLong(ClientProperties.QPID_SYNC_OP_TIMEOUT,
- Long.getLong(ClientProperties.AMQJ_DEFAULT_SYNCWRITE_TIMEOUT,
- ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT));
+ private final long DEFAULT_SYNC_TIMEOUT = Long.getLong("amqj.default_syncwrite_timeout", 1000 * 30);
/** Object to lock on when changing the latch */
private Object _failoverLatchChange = new Object();
private AMQCodecFactory _codecFactory;
-
+ private Job _readJob;
+ private Job _writeJob;
+ private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance();
+ private NetworkDriver _networkDriver;
private ProtocolVersion _suggestedProtocolVersion;
private long _writtenBytes;
private long _readBytes;
- private NetworkConnection _network;
- private Sender<ByteBuffer> _sender;
-
/**
* Creates a new protocol handler, associated with the specified client connection instance.
*
@@ -189,10 +189,43 @@ public class AMQProtocolHandler implements ProtocolEngine
_protocolSession = new AMQProtocolSession(this, _connection);
_stateManager = new AMQStateManager(_protocolSession);
_codecFactory = new AMQCodecFactory(false, _protocolSession);
+ _poolReference.setThreadFactory(new ThreadFactory()
+ {
+
+ public Thread newThread(final Runnable runnable)
+ {
+ try
+ {
+ return Threading.getThreadFactory().createThread(runnable);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Failed to create thread", e);
+ }
+ }
+ });
+ _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true);
+ _writeJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, false);
+ _poolReference.acquireExecutorService();
_failoverHandler = new FailoverHandler(this);
}
/**
+ * Called when we want to create a new IoTransport session
+ * @param brokerDetail
+ */
+ public void createIoTransportSession(BrokerDetails brokerDetail)
+ {
+ _protocolSession = new AMQProtocolSession(this, _connection);
+ _stateManager.setProtocolSession(_protocolSession);
+ IoTransport.connect_0_9(getProtocolSession(),
+ brokerDetail.getHost(),
+ brokerDetail.getPort(),
+ brokerDetail.getBooleanProperty(BrokerDetails.OPTIONS_SSL));
+ _protocolSession.init();
+ }
+
+ /**
* Called when the network connection is closed. This can happen, either because the client explicitly requested
* that the connection be closed, in which case nothing is done, or because the connection died. In the case
* where the connection died, an attempt to failover automatically to a new connection may be started. The failover
@@ -282,7 +315,7 @@ public class AMQProtocolHandler implements ProtocolEngine
// failover:
HeartbeatDiagnostics.timeout();
_logger.warn("Timed out while waiting for heartbeat from peer.");
- _network.close();
+ _networkDriver.close();
}
public void writerIdle()
@@ -304,12 +337,22 @@ public class AMQProtocolHandler implements ProtocolEngine
{
_logger.info("Exception caught therefore going to attempt failover: " + cause, cause);
// this will attempt failover
- _network.close();
+ _networkDriver.close();
closed();
}
else
{
+
+ if (cause instanceof ProtocolCodecException)
+ {
+ _logger.info("Protocol Exception caught NOT going to attempt failover as " +
+ "cause isn't AMQConnectionClosedException: " + cause, cause);
+
+ AMQException amqe = new AMQException("Protocol handler error: " + cause, cause);
+ propagateExceptionToAllWaiters(amqe);
+ }
_connection.exceptionReceived(cause);
+
}
// FIXME Need to correctly handle other exceptions. Things like ...
@@ -403,63 +446,76 @@ public class AMQProtocolHandler implements ProtocolEngine
public void received(ByteBuffer msg)
{
- _readBytes += msg.remaining();
try
{
+ _readBytes += msg.remaining();
final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg);
- // Decode buffer
-
- for (AMQDataBlock message : dataBlocks)
+ Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable()
{
- if (PROTOCOL_DEBUG)
- {
- _protocolLogger.info(String.format("RECV: [%s] %s", this, message));
- }
+ public void run()
+ {
+ // Decode buffer
- if(message instanceof AMQFrame)
+ for (AMQDataBlock message : dataBlocks)
{
- final boolean debug = _logger.isDebugEnabled();
- final long msgNumber = ++_messageReceivedCount;
- if (debug && ((msgNumber % 1000) == 0))
+ try
{
- _logger.debug("Received " + _messageReceivedCount + " protocol messages");
+ if (PROTOCOL_DEBUG)
+ {
+ _protocolLogger.info(String.format("RECV: [%s] %s", this, message));
+ }
+
+ if(message instanceof AMQFrame)
+ {
+ final boolean debug = _logger.isDebugEnabled();
+ final long msgNumber = ++_messageReceivedCount;
+
+ if (debug && ((msgNumber % 1000) == 0))
+ {
+ _logger.debug("Received " + _messageReceivedCount + " protocol messages");
+ }
+
+ AMQFrame frame = (AMQFrame) message;
+
+ final AMQBody bodyFrame = frame.getBodyFrame();
+
+ HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody);
+
+ bodyFrame.handle(frame.getChannel(), _protocolSession);
+
+ _connection.bytesReceived(_readBytes);
+ }
+ else if (message instanceof ProtocolInitiation)
+ {
+ // We get here if the server sends a response to our initial protocol header
+ // suggesting an alternate ProtocolVersion; the server will then close the
+ // connection.
+ ProtocolInitiation protocolInit = (ProtocolInitiation) message;
+ _suggestedProtocolVersion = protocolInit.checkVersion();
+ _logger.info("Broker suggested using protocol version:" + _suggestedProtocolVersion);
+
+ // get round a bug in old versions of qpid whereby the connection is not closed
+ _stateManager.changeState(AMQState.CONNECTION_CLOSED);
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.error("Exception processing frame", e);
+ propagateExceptionToFrameListeners(e);
+ exception(e);
}
-
- AMQFrame frame = (AMQFrame) message;
-
- final AMQBody bodyFrame = frame.getBodyFrame();
-
- HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody);
-
- bodyFrame.handle(frame.getChannel(), _protocolSession);
-
- _connection.bytesReceived(_readBytes);
- }
- else if (message instanceof ProtocolInitiation)
- {
- // We get here if the server sends a response to our initial protocol header
- // suggesting an alternate ProtocolVersion; the server will then close the
- // connection.
- ProtocolInitiation protocolInit = (ProtocolInitiation) message;
- _suggestedProtocolVersion = protocolInit.checkVersion();
- _logger.info("Broker suggested using protocol version:" + _suggestedProtocolVersion);
-
- // get round a bug in old versions of qpid whereby the connection is not closed
- _stateManager.changeState(AMQState.CONNECTION_CLOSED);
}
}
+ });
}
catch (Exception e)
{
- _logger.error("Exception processing frame", e);
propagateExceptionToFrameListeners(e);
exception(e);
}
-
-
}
public void methodBodyReceived(final int channelId, final AMQBody bodyFrame)
@@ -514,13 +570,28 @@ public class AMQProtocolHandler implements ProtocolEngine
return getStateManager().createWaiter(states);
}
- public synchronized void writeFrame(AMQDataBlock frame)
+ /**
+ * Convenience method that writes a frame to the protocol session. Equivalent to calling
+ * getProtocolSession().write().
+ *
+ * @param frame the frame to write
+ */
+ public void writeFrame(AMQDataBlock frame)
{
- final ByteBuffer buf = asByteBuffer(frame);
- _writtenBytes += buf.remaining();
- _sender.send(buf);
- _sender.flush();
+ writeFrame(frame, false);
+ }
+ public void writeFrame(AMQDataBlock frame, boolean wait)
+ {
+ final ByteBuffer buf = frame.toNioByteBuffer();
+ _writtenBytes += buf.remaining();
+ Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable()
+ {
+ public void run()
+ {
+ _networkDriver.send(buf);
+ }
+ });
if (PROTOCOL_DEBUG)
{
_protocolLogger.debug(String.format("SEND: [%s] %s", this, frame));
@@ -537,41 +608,12 @@ public class AMQProtocolHandler implements ProtocolEngine
_connection.bytesSent(_writtenBytes);
- }
-
- private ByteBuffer asByteBuffer(AMQDataBlock block)
- {
- final ByteBuffer buf = ByteBuffer.allocate((int) block.getSize());
-
- try
+ if (wait)
{
- block.writePayload(new DataOutputStream(new OutputStream()
- {
-
-
- @Override
- public void write(int b) throws IOException
- {
- buf.put((byte) b);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException
- {
- buf.put(b, off, len);
- }
- }));
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
+ _networkDriver.flush();
}
-
- buf.flip();
- return buf;
}
-
/**
* Convenience method that writes a frame to the protocol session and waits for a particular response. Equivalent to
* calling getProtocolSession().write() then waiting for the response.
@@ -665,23 +707,24 @@ public class AMQProtocolHandler implements ProtocolEngine
* <p/>If a failover exception occurs whilst closing the connection it is ignored, as the connection is closed
* anyway.
*
- * @param timeout The timeout to wait for an acknowledgment to the close request.
+ * @param timeout The timeout to wait for an acknowledgement to the close request.
*
* @throws AMQException If the close fails for any reason.
*/
public void closeConnection(long timeout) throws AMQException
{
+ ConnectionCloseBody body = _protocolSession.getMethodRegistry().createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
+ new AMQShortString("JMS client is closing the connection."), 0, 0);
+
+ final AMQFrame frame = body.generateFrame(0);
+
+ //If the connection is already closed then don't do a syncWrite
if (!getStateManager().getCurrentState().equals(AMQState.CONNECTION_CLOSED))
{
- // Connection is already closed then don't do a syncWrite
try
{
- final ConnectionCloseBody body = _protocolSession.getMethodRegistry().createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
- new AMQShortString("JMS client is closing the connection."), 0, 0);
- final AMQFrame frame = body.generateFrame(0);
-
syncWrite(frame, ConnectionCloseOkBody.class, timeout);
- _network.close();
+ _networkDriver.close();
closed();
}
catch (AMQTimeoutException e)
@@ -690,9 +733,10 @@ public class AMQProtocolHandler implements ProtocolEngine
}
catch (FailoverException e)
{
- _logger.debug("FailoverException interrupted connection close, ignoring as connection closed anyway.");
+ _logger.debug("FailoverException interrupted connection close, ignoring as connection close anyway.");
}
}
+ _poolReference.releaseExecutorService();
}
/** @return the number of bytes read from this protocol session */
@@ -800,23 +844,17 @@ public class AMQProtocolHandler implements ProtocolEngine
public SocketAddress getRemoteAddress()
{
- return _network.getRemoteAddress();
+ return _networkDriver.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _network.getLocalAddress();
- }
-
- public void setNetworkConnection(NetworkConnection network)
- {
- setNetworkConnection(network, network.getSender());
+ return _networkDriver.getLocalAddress();
}
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ public void setNetworkDriver(NetworkDriver driver)
{
- _network = network;
- _sender = sender;
+ _networkDriver = driver;
}
/** @param delay delay in seconds (not ms) */
@@ -824,15 +862,15 @@ public class AMQProtocolHandler implements ProtocolEngine
{
if (delay > 0)
{
- _network.setMaxWriteIdle(delay);
- _network.setMaxReadIdle(HeartbeatConfig.CONFIG.getTimeout(delay));
+ getNetworkDriver().setMaxWriteIdle(delay);
+ getNetworkDriver().setMaxReadIdle(HeartbeatConfig.CONFIG.getTimeout(delay));
HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay));
}
}
- public NetworkConnection getNetworkConnection()
+ public NetworkDriver getNetworkDriver()
{
- return _network;
+ return _networkDriver;
}
public ProtocolVersion getSuggestedProtocolVersion()
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
index b7253e6e9c..7976760696 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
@@ -20,36 +20,27 @@
*/
package org.apache.qpid.client.protocol;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.jms.JMSException;
import javax.security.sasl.SaslClient;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.ConnectionTuneParameters;
-import org.apache.qpid.client.handler.ClientMethodDispatcherImpl;
import org.apache.qpid.client.message.UnprocessedMessage;
import org.apache.qpid.client.message.UnprocessedMessage_0_8;
import org.apache.qpid.client.state.AMQStateManager;
-import org.apache.qpid.framing.AMQDataBlock;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.HeartbeatBody;
-import org.apache.qpid.framing.MethodDispatcher;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.ProtocolInitiation;
-import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.framing.*;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.TransportException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.qpid.client.handler.ClientMethodDispatcherImpl;
/**
* Wrapper for protocol session that provides type-safe access to session attributes. <p/> The underlying protocol
@@ -157,6 +148,16 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
return getAMQConnection().getVirtualHost();
}
+ public String getUsername()
+ {
+ return getAMQConnection().getUsername();
+ }
+
+ public String getPassword()
+ {
+ return getAMQConnection().getPassword();
+ }
+
public SaslClient getSaslClient()
{
return _saslClient;
@@ -298,11 +299,22 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
return _connection.getSession(channelId);
}
+ /**
+ * Convenience method that writes a frame to the protocol session. Equivalent to calling
+ * getProtocolSession().write().
+ *
+ * @param frame the frame to write
+ */
public void writeFrame(AMQDataBlock frame)
{
_protocolHandler.writeFrame(frame);
}
+ public void writeFrame(AMQDataBlock frame, boolean wait)
+ {
+ _protocolHandler.writeFrame(frame, wait);
+ }
+
/**
* Starts the process of closing a session
*
@@ -363,15 +375,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public void closeProtocolSession() throws AMQException
{
- try
- {
- _protocolHandler.getNetworkConnection().close();
- }
- catch(TransportException e)
- {
- //ignore such exceptions, they were already logged
- //and this is a forcible close.
- }
+ _protocolHandler.closeConnection(0);
}
public void failover(String host, int port)
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java b/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java
new file mode 100644
index 0000000000..bbd0a7b144
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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 org.apache.qpid.client.protocol;
+
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A MINA filter that monitors the numbers of messages pending to be sent by MINA. It outputs a message
+ * when a threshold has been exceeded, and has a frequency configuration so that messages are not output
+ * too often.
+ *
+ */
+public class ProtocolBufferMonitorFilter extends IoFilterAdapter
+{
+ private static final Logger _logger = LoggerFactory.getLogger(ProtocolBufferMonitorFilter.class);
+
+ public static final long DEFAULT_FREQUENCY = 5000;
+
+ public static final int DEFAULT_THRESHOLD = 3000;
+
+ private int _bufferedMessages = 0;
+
+ private int _threshold;
+
+ private long _lastMessageOutputTime;
+
+ private long _outputFrequencyInMillis;
+
+ public ProtocolBufferMonitorFilter()
+ {
+ _threshold = DEFAULT_THRESHOLD;
+ _outputFrequencyInMillis = DEFAULT_FREQUENCY;
+ }
+
+ public ProtocolBufferMonitorFilter(int threshold, long frequency)
+ {
+ _threshold = threshold;
+ _outputFrequencyInMillis = frequency;
+ }
+
+ public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception
+ {
+ _bufferedMessages++;
+ if (_bufferedMessages > _threshold)
+ {
+ long now = System.currentTimeMillis();
+ if ((now - _lastMessageOutputTime) > _outputFrequencyInMillis)
+ {
+ _logger.warn("Protocol message buffer exceeded threshold of " + _threshold + ". Current backlog: "
+ + _bufferedMessages);
+ _lastMessageOutputTime = now;
+ }
+ }
+
+ nextFilter.messageReceived(session, message);
+ }
+
+ public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception
+ {
+ _bufferedMessages--;
+ nextFilter.messageSent(session, message);
+ }
+
+ public int getBufferedMessages()
+ {
+ return _bufferedMessages;
+ }
+
+ public int getThreshold()
+ {
+ return _threshold;
+ }
+
+ public void setThreshold(int threshold)
+ {
+ _threshold = threshold;
+ }
+
+ public long getOutputFrequencyInMillis()
+ {
+ return _outputFrequencyInMillis;
+ }
+
+ public void setOutputFrequencyInMillis(long outputFrequencyInMillis)
+ {
+ _outputFrequencyInMillis = outputFrequencyInMillis;
+ }
+
+ public long getLastMessageOutputTime()
+ {
+ return _lastMessageOutputTime;
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
index 67dd1a58b6..fbca444208 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/AMQCallbackHandler.java
@@ -22,9 +22,9 @@ package org.apache.qpid.client.security;
import javax.security.auth.callback.CallbackHandler;
-import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
public interface AMQCallbackHandler extends CallbackHandler
{
- void initialise(ConnectionURL connectionURL);
+ void initialise(AMQProtocolSession protocolSession);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
index 14bae68561..140cbdeb75 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
@@ -20,22 +20,17 @@
*/
package org.apache.qpid.client.security;
+import org.apache.qpid.util.FileUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.IOException;
import java.io.InputStream;
-import java.util.Collection;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-
-import org.apache.qpid.util.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* CallbackHandlerRegistry is a registry for call back handlers for user authentication and interaction during user
@@ -47,7 +42,7 @@ import org.slf4j.LoggerFactory;
* "amp.callbackhandler.properties". The format of the properties file is:
*
* <p/><pre>
- * CallbackHanlder.n.mechanism=fully.qualified.class.name where n is an ordinal
+ * CallbackHanlder.mechanism=fully.qualified.class.name
* </pre>
*
* <p/>Where mechanism is an IANA-registered mechanism name and the fully qualified class name refers to a
@@ -71,15 +66,51 @@ public class CallbackHandlerRegistry
public static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/client/security/CallbackHandlerRegistry.properties";
/** A static reference to the singleton instance of this registry. */
- private static final CallbackHandlerRegistry _instance;
+ private static CallbackHandlerRegistry _instance = new CallbackHandlerRegistry();
/** Holds a map from SASL mechanism names to call back handlers. */
- private Map<String, Class<AMQCallbackHandler>> _mechanismToHandlerClassMap = new HashMap<String, Class<AMQCallbackHandler>>();
+ private Map<String, Class> _mechanismToHandlerClassMap = new HashMap<String, Class>();
+
+ /** Holds a space delimited list of mechanisms that callback handlers exist for. */
+ private String _mechanisms;
+
+ /**
+ * Gets the singleton instance of this registry.
+ *
+ * @return The singleton instance of this registry.
+ */
+ public static CallbackHandlerRegistry getInstance()
+ {
+ return _instance;
+ }
- /** Ordered collection of mechanisms for which callback handlers exist. */
- private Collection<String> _mechanisms;
+ /**
+ * Gets the callback handler class for a given SASL mechanism name.
+ *
+ * @param mechanism The SASL mechanism name.
+ *
+ * @return The callback handler class for the mechanism, or null if none is configured for that mechanism.
+ */
+ public Class getCallbackHandlerClass(String mechanism)
+ {
+ return (Class) _mechanismToHandlerClassMap.get(mechanism);
+ }
- static
+ /**
+ * Gets a space delimited list of supported SASL mechanisms.
+ *
+ * @return A space delimited list of supported SASL mechanisms.
+ */
+ public String getMechanisms()
+ {
+ return _mechanisms;
+ }
+
+ /**
+ * Creates the call back handler registry from its configuration resource or file. This also has the side effect
+ * of configuring and registering the SASL client factory implementations using {@link DynamicSaslRegistrar}.
+ */
+ private CallbackHandlerRegistry()
{
// Register any configured SASL client factories.
DynamicSaslRegistrar.registerSaslProviders();
@@ -89,12 +120,12 @@ public class CallbackHandlerRegistry
FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
CallbackHandlerRegistry.class.getClassLoader());
- final Properties props = new Properties();
-
try
{
-
+ Properties props = new Properties();
props.load(is);
+ parseProperties(props);
+ _logger.info("Callback handlers available for SASL mechanisms: " + _mechanisms);
}
catch (IOException e)
{
@@ -115,68 +146,32 @@ public class CallbackHandlerRegistry
}
}
}
-
- _instance = new CallbackHandlerRegistry(props);
- _logger.info("Callback handlers available for SASL mechanisms: " + _instance._mechanisms);
-
}
- /**
- * Gets the singleton instance of this registry.
- *
- * @return The singleton instance of this registry.
- */
- public static CallbackHandlerRegistry getInstance()
- {
- return _instance;
- }
-
- public AMQCallbackHandler createCallbackHandler(final String mechanism)
+ /*private InputStream openPropertiesInputStream(String filename)
{
- final Class<AMQCallbackHandler> mechanismClass = _mechanismToHandlerClassMap.get(mechanism);
-
- if (mechanismClass == null)
+ boolean useDefault = true;
+ InputStream is = null;
+ if (filename != null)
{
- throw new IllegalArgumentException("Mechanism " + mechanism + " not known");
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(new File(filename)));
+ useDefault = false;
+ }
+ catch (FileNotFoundException e)
+ {
+ _logger.error("Unable to read from file " + filename + ": " + e, e);
+ }
}
- try
- {
- return mechanismClass.newInstance();
- }
- catch (InstantiationException e)
- {
- throw new IllegalArgumentException("Unable to create an instance of mechanism " + mechanism, e);
- }
- catch (IllegalAccessException e)
+ if (useDefault)
{
- throw new IllegalArgumentException("Unable to create an instance of mechanism " + mechanism, e);
+ is = CallbackHandlerRegistry.class.getResourceAsStream(DEFAULT_RESOURCE_NAME);
}
- }
- /**
- * Gets collections of supported SASL mechanism names, ordered by preference
- *
- * @return collection of SASL mechanism names.
- */
- public Collection<String> getMechanisms()
- {
- return Collections.unmodifiableCollection(_mechanisms);
- }
-
- /**
- * Creates the call back handler registry from its configuration resource or file.
- *
- * This also has the side effect of configuring and registering the SASL client factory
- * implementations using {@link DynamicSaslRegistrar}.
- *
- * This constructor is default protection to allow for effective unit testing. Clients must use
- * {@link #getInstance()} to obtain the singleton instance.
- */
- CallbackHandlerRegistry(final Properties props)
- {
- parseProperties(props);
- }
+ return is;
+ }*/
/**
* Scans the specified properties as a mapping from IANA registered SASL mechanism to call back handler
@@ -188,20 +183,20 @@ public class CallbackHandlerRegistry
*/
private void parseProperties(Properties props)
{
-
- final Map<Integer, String> mechanisms = new TreeMap<Integer, String>();
-
Enumeration e = props.propertyNames();
while (e.hasMoreElements())
{
- final String propertyName = (String) e.nextElement();
- final String[] parts = propertyName.split("\\.", 2);
+ String propertyName = (String) e.nextElement();
+ int period = propertyName.indexOf(".");
+ if (period < 0)
+ {
+ _logger.warn("Unable to parse property " + propertyName + " when configuring SASL providers");
- checkPropertyNameFormat(propertyName, parts);
+ continue;
+ }
- final String mechanism = parts[0];
- final int ordinal = getPropertyOrdinal(propertyName, parts);
- final String className = props.getProperty(propertyName);
+ String mechanism = propertyName.substring(period + 1);
+ String className = props.getProperty(propertyName);
Class clazz = null;
try
{
@@ -210,11 +205,20 @@ public class CallbackHandlerRegistry
{
_logger.warn("SASL provider " + clazz + " does not implement " + AMQCallbackHandler.class
+ ". Skipping");
+
continue;
}
- _mechanismToHandlerClassMap.put(mechanism, clazz);
- mechanisms.put(ordinal, mechanism);
+ _mechanismToHandlerClassMap.put(mechanism, clazz);
+ if (_mechanisms == null)
+ {
+ _mechanisms = mechanism;
+ }
+ else
+ {
+ // one time cost
+ _mechanisms = _mechanisms + " " + mechanism;
+ }
}
catch (ClassNotFoundException ex)
{
@@ -223,91 +227,5 @@ public class CallbackHandlerRegistry
continue;
}
}
-
- _mechanisms = mechanisms.values(); // order guaranteed by keys of treemap (i.e. our ordinals)
-
-
- }
-
- private void checkPropertyNameFormat(final String propertyName, final String[] parts)
- {
- if (parts.length != 2)
- {
- throw new IllegalArgumentException("Unable to parse property " + propertyName + " when configuring SASL providers");
- }
- }
-
- private int getPropertyOrdinal(final String propertyName, final String[] parts)
- {
- try
- {
- return Integer.parseInt(parts[1]);
- }
- catch(NumberFormatException nfe)
- {
- throw new IllegalArgumentException("Unable to parse property " + propertyName + " when configuring SASL providers", nfe);
- }
- }
-
- /**
- * Selects a SASL mechanism that is mutually available to both parties. If more than one
- * mechanism is mutually available the one appearing first (by ordinal) will be returned.
- *
- * @param peerMechanismList space separated list of mechanisms
- * @return selected mechanism, or null if none available
- */
- public String selectMechanism(final String peerMechanismList)
- {
- final Set<String> peerList = mechListToSet(peerMechanismList);
-
- return selectMechInternal(peerList, Collections.<String>emptySet());
- }
-
- /**
- * Selects a SASL mechanism that is mutually available to both parties.
- *
- * @param peerMechanismList space separated list of mechanisms
- * @param restrictionList space separated list of mechanisms
- * @return selected mechanism, or null if none available
- */
- public String selectMechanism(final String peerMechanismList, final String restrictionList)
- {
- final Set<String> peerList = mechListToSet(peerMechanismList);
- final Set<String> restrictionSet = mechListToSet(restrictionList);
-
- return selectMechInternal(peerList, restrictionSet);
- }
-
- private String selectMechInternal(final Set<String> peerSet, final Set<String> restrictionSet)
- {
- for (final String mech : _mechanisms)
- {
- if (peerSet.contains(mech))
- {
- if (restrictionSet.isEmpty() || restrictionSet.contains(mech))
- {
- return mech;
- }
- }
- }
-
- return null;
- }
-
- private Set<String> mechListToSet(final String mechanismList)
- {
- if (mechanismList == null)
- {
- return Collections.emptySet();
- }
-
- final StringTokenizer tokenizer = new StringTokenizer(mechanismList, " ");
- final Set<String> mechanismSet = new HashSet<String>(tokenizer.countTokens());
- while (tokenizer.hasMoreTokens())
- {
- mechanismSet.add(tokenizer.nextToken());
- }
- return Collections.unmodifiableSet(mechanismSet);
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
index b04a756e80..1fcfde3579 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
+++ b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
@@ -16,17 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-
-#
-# Format:
-# <mechanism name>.ordinal=<implementation>
-#
-# @see CallbackHandlerRegistry
-#
-
-EXTERNAL.1=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
-GSSAPI.2=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
-CRAM-MD5-HASHED.3=org.apache.qpid.client.security.UsernameHashedPasswordCallbackHandler
-CRAM-MD5.4=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
-AMQPLAIN.5=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
-PLAIN.6=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
+CallbackHandler.CRAM-MD5-HASHED=org.apache.qpid.client.security.UsernameHashedPasswordCallbackHandler
+CallbackHandler.CRAM-MD5=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
+CallbackHandler.AMQPLAIN=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
+CallbackHandler.PLAIN=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
index b903208927..1bff43142b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
+++ b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
@@ -18,4 +18,3 @@
#
AMQPLAIN=org.apache.qpid.client.security.amqplain.AmqPlainSaslClientFactory
CRAM-MD5-HASHED=org.apache.qpid.client.security.crammd5hashed.CRAMMD5HashedSaslClientFactory
-ANONYMOUS=org.apache.qpid.client.security.anonymous.AnonymousSaslClientFactory
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
index 6ec83f0a23..66176dac3c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
@@ -20,29 +20,30 @@
*/
package org.apache.qpid.client.security;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
-import org.apache.qpid.jms.ConnectionURL;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
{
- private ConnectionURL _connectionURL;
+ private static final Logger _logger = LoggerFactory.getLogger(UsernameHashedPasswordCallbackHandler.class);
- /**
- * @see org.apache.qpid.client.security.AMQCallbackHandler#initialise(org.apache.qpid.jms.ConnectionURL)
- */
- @Override
- public void initialise(ConnectionURL connectionURL)
+ private AMQProtocolSession _protocolSession;
+
+ public void initialise(AMQProtocolSession protocolSession)
{
- _connectionURL = connectionURL;
+ _protocolSession = protocolSession;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
@@ -52,13 +53,13 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
Callback cb = callbacks[i];
if (cb instanceof NameCallback)
{
- ((NameCallback) cb).setName(_connectionURL.getUsername());
+ ((NameCallback) cb).setName(_protocolSession.getUsername());
}
else if (cb instanceof PasswordCallback)
{
try
{
- ((PasswordCallback) cb).setPassword(getHash(_connectionURL.getPassword()));
+ ((PasswordCallback) cb).setPassword(getHash(_protocolSession.getPassword()));
}
catch (NoSuchAlgorithmException e)
{
@@ -98,5 +99,4 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
return hash;
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
index ad088722c8..c50c62710f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandler.java
@@ -27,19 +27,15 @@ import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
-import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
{
- private ConnectionURL _connectionURL;
+ private AMQProtocolSession _protocolSession;
- /**
- * @see org.apache.qpid.client.security.AMQCallbackHandler#initialise(org.apache.qpid.jms.ConnectionURL)
- */
- @Override
- public void initialise(final ConnectionURL connectionURL)
+ public void initialise(AMQProtocolSession protocolSession)
{
- _connectionURL = connectionURL;
+ _protocolSession = protocolSession;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
@@ -49,11 +45,11 @@ public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
Callback cb = callbacks[i];
if (cb instanceof NameCallback)
{
- ((NameCallback)cb).setName(_connectionURL.getUsername());
+ ((NameCallback)cb).setName(_protocolSession.getUsername());
}
else if (cb instanceof PasswordCallback)
{
- ((PasswordCallback)cb).setPassword(_connectionURL.getPassword().toCharArray());
+ ((PasswordCallback)cb).setPassword(_protocolSession.getPassword().toCharArray());
}
else
{
@@ -61,5 +57,4 @@ public class UsernamePasswordCallbackHandler implements AMQCallbackHandler
}
}
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClient.java b/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClient.java
deleted file mode 100644
index 0f56b2ef6c..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClient.java
+++ /dev/null
@@ -1,52 +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.
- *
- */
-package org.apache.qpid.client.security.anonymous;
-
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-public class AnonymousSaslClient implements SaslClient
-{
- public String getMechanismName() {
- return "ANONYMOUS";
- }
- public boolean hasInitialResponse() {
- return true;
- }
- public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
- return new byte[0];
- }
- public boolean isComplete() {
- return true;
- }
- public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
- {
- throw new IllegalStateException("No security layer supported");
- }
- public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
- {
- throw new IllegalStateException("No security layer supported");
- }
- public Object getNegotiatedProperty(String propName) {
- return null;
- }
- public void dispose() throws SaslException {}
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClientFactory.java b/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClientFactory.java
deleted file mode 100644
index de698f87c6..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/security/anonymous/AnonymousSaslClientFactory.java
+++ /dev/null
@@ -1,52 +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.
- *
- */
-package org.apache.qpid.client.security.anonymous;
-
-import java.util.Arrays;
-import java.util.Map;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslClientFactory;
-import javax.security.sasl.SaslException;
-import javax.security.auth.callback.CallbackHandler;
-
-public class AnonymousSaslClientFactory implements SaslClientFactory
-{
- public SaslClient createSaslClient(String[] mechanisms, String authId,
- String protocol, String server,
- Map props, CallbackHandler cbh) throws SaslException
- {
- if (Arrays.asList(mechanisms).contains("ANONYMOUS")) {
- return new AnonymousSaslClient();
- } else {
- return null;
- }
- }
- public String[] getMechanismNames(Map props)
- {
- if (props == null || props.isEmpty()) {
- return new String[]{"ANONYMOUS"};
- } else {
- return new String[0];
- }
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
index 0d6fc727c1..9c7d62670c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
@@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.io.IOException;
/**
* The state manager is responsible for managing the state of the protocol session. <p/>
@@ -47,7 +48,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*
* The two step process is required as there is an inherit race condition between starting a process that will cause
* the state to change and then attempting to wait for that change. The interest in the change must be first set up so
- * that any asynchronous errors that occur can be delivered to the correct waiters.
+ * that any asynchrous errors that occur can be delivered to the correct waiters.
*/
public class AMQStateManager implements AMQMethodListener
{
@@ -83,10 +84,7 @@ public class AMQStateManager implements AMQMethodListener
public AMQState getCurrentState()
{
- synchronized (_stateLock)
- {
- return _currentState;
- }
+ return _currentState;
}
public void changeState(AMQState newState)
@@ -116,7 +114,7 @@ public class AMQStateManager implements AMQMethodListener
}
/**
- * Setting of the ProtocolSession will be required when Failover has been successfully completed.
+ * Setting of the ProtocolSession will be required when Failover has been successfuly compeleted.
*
* The new {@link AMQProtocolSession} that has been re-established needs to be provided as that is now the
* connection to the network.
@@ -133,9 +131,9 @@ public class AMQStateManager implements AMQMethodListener
}
/**
- * Propagate error to waiters
+ * Propogate error to waiters
*
- * @param error The error to propagate.
+ * @param error The error to propogate.
*/
public void error(Exception error)
{
@@ -179,7 +177,7 @@ public class AMQStateManager implements AMQMethodListener
}
/**
- * Create and add a new waiter to the notification list.
+ * Create and add a new waiter to the notifcation list.
*
* @param states The waiter will attempt to wait for one of these desired set states to be achived.
*
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
index 732480e1c9..79f438d35d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
@@ -34,7 +34,7 @@ import java.util.Set;
*
* On construction the current state and a set of States to await for is provided.
*
- * When await() is called the state at construction is compared against the awaitStates. If the state at construction is
+ * When await() is called the state at constuction is compared against the awaitStates. If the state at construction is
* a desired state then await() returns immediately.
*
* Otherwise it will block for the set timeout for a desired state to be achieved.
@@ -48,9 +48,9 @@ public class StateWaiter extends BlockingWaiter<AMQState>
{
private static final Logger _logger = LoggerFactory.getLogger(StateWaiter.class);
- private final Set<AMQState> _awaitStates;
- private final AMQState _startState;
- private final AMQStateManager _stateManager;
+ Set<AMQState> _awaitStates;
+ private AMQState _startState;
+ private AMQStateManager _stateManager;
/**
*
@@ -78,9 +78,9 @@ public class StateWaiter extends BlockingWaiter<AMQState>
}
/**
- * Await for the required State to be achieved within the default timeout.
+ * Await for the requried State to be achieved within the default timeout.
* @return The achieved state that was requested.
- * @throws AMQException The exception that prevented the required state from being achieved.
+ * @throws AMQException The exception that prevented the required state from being achived.
*/
public AMQState await() throws AMQException
{
@@ -88,13 +88,13 @@ public class StateWaiter extends BlockingWaiter<AMQState>
}
/**
- * Await for the required State to be achieved.
+ * Await for the requried State to be achieved.
*
* <b>It is the responsibility of this class to remove the waiter from the StateManager
*
- * @param timeout The time in milliseconds to wait for any of the states to be achieved.
+ * @param timeout The time in milliseconds to wait for any of the states to be achived.
* @return The achieved state that was requested.
- * @throws AMQException The exception that prevented the required state from being achieved.
+ * @throws AMQException The exception that prevented the required state from being achived.
*/
public AMQState await(long timeout) throws AMQException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java b/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java
deleted file mode 100644
index 1b483f6948..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java
+++ /dev/null
@@ -1,168 +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.
- *
- */
-package org.apache.qpid.client.transport;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.apache.qpid.client.security.AMQCallbackHandler;
-import org.apache.qpid.client.security.CallbackHandlerRegistry;
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.transport.ClientDelegate;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.ConnectionException;
-import org.apache.qpid.transport.ConnectionOpenOk;
-import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.util.Logger;
-import org.apache.qpid.util.Strings;
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
-import org.ietf.jgss.Oid;
-
-/**
- *
- */
-public class ClientConnectionDelegate extends ClientDelegate
-{
- private static final Logger LOGGER = Logger.get(ClientDelegate.class);
-
- private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2";
- protected static final Oid KRB5_OID;
-
- static
- {
- Oid oid;
- try
- {
- oid = new Oid(KRB5_OID_STR);
- }
- catch (GSSException ignore)
- {
- oid = null;
- }
-
- KRB5_OID = oid;
- }
-
- private final ConnectionURL _connectionURL;
-
- /**
- * @param settings
- * @param connectionURL
- */
- public ClientConnectionDelegate(ConnectionSettings settings, ConnectionURL connectionURL)
- {
- super(settings);
- this._connectionURL = connectionURL;
- }
-
- @Override
- protected SaslClient createSaslClient(List<Object> brokerMechs) throws ConnectionException, SaslException
- {
- final String brokerMechanisms = Strings.join(" ", brokerMechs);
- final String restrictionList = _conSettings.getSaslMechs();
- final String selectedMech = CallbackHandlerRegistry.getInstance().selectMechanism(brokerMechanisms, restrictionList);
- if (selectedMech == null)
- {
- throw new ConnectionException("Client and broker have no SASL mechanisms in common." +
- " Broker allows : " + brokerMechanisms +
- " Client has : " + CallbackHandlerRegistry.getInstance().getMechanisms() +
- " Client restricted itself to : " + (restrictionList != null ? restrictionList : "no restriction"));
- }
-
- Map<String,Object> saslProps = new HashMap<String,Object>();
- if (_conSettings.isUseSASLEncryption())
- {
- saslProps.put(Sasl.QOP, "auth-conf");
- }
-
- final AMQCallbackHandler handler = CallbackHandlerRegistry.getInstance().createCallbackHandler(selectedMech);
- handler.initialise(_connectionURL);
- final SaslClient sc = Sasl.createSaslClient(new String[] {selectedMech}, null, _conSettings.getSaslProtocol(), _conSettings.getSaslServerName(), saslProps, handler);
-
- return sc;
- }
-
- @Override
- public void connectionOpenOk(Connection conn, ConnectionOpenOk ok)
- {
- SaslClient sc = conn.getSaslClient();
- if (sc != null)
- {
- if (sc.getMechanismName().equals("GSSAPI"))
- {
- String id = getKerberosUser();
- if (id != null)
- {
- conn.setUserID(id);
- }
- }
- else if (sc.getMechanismName().equals("EXTERNAL"))
- {
- if (conn.getSecurityLayer() != null)
- {
- conn.setUserID(conn.getSecurityLayer().getUserID());
- }
- }
- }
-
- super.connectionOpenOk(conn, ok);
- }
-
- private String getKerberosUser()
- {
- LOGGER.debug("Obtaining userID from kerberos");
- String service = _conSettings.getSaslProtocol() + "@" + _conSettings.getSaslServerName();
- GSSManager manager = GSSManager.getInstance();
-
- try
- {
- GSSName acceptorName = manager.createName(service,
- GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
-
- GSSContext secCtx = manager.createContext(acceptorName,
- KRB5_OID,
- null,
- GSSContext.INDEFINITE_LIFETIME);
-
- secCtx.initSecContext(new byte[0], 0, 1);
-
- if (secCtx.getSrcName() != null)
- {
- return secCtx.getSrcName().toString();
- }
-
- }
- catch (GSSException e)
- {
- LOGGER.warn("Unable to retrieve userID from Kerberos due to error",e);
- }
-
- return null;
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java
new file mode 100644
index 0000000000..1ac8f62e32
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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 org.apache.qpid.client.transport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+import org.apache.qpid.client.SSLConfiguration;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.network.mina.MINANetworkDriver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SocketTransportConnection implements ITransportConnection
+{
+ private static final Logger _logger = LoggerFactory.getLogger(SocketTransportConnection.class);
+ private static final int DEFAULT_BUFFER_SIZE = 32 * 1024;
+
+ private SocketConnectorFactory _socketConnectorFactory;
+
+ static interface SocketConnectorFactory
+ {
+ IoConnector newSocketConnector();
+ }
+
+ public SocketTransportConnection(SocketConnectorFactory socketConnectorFactory)
+ {
+ _socketConnectorFactory = socketConnectorFactory;
+ }
+
+ public void connect(AMQProtocolHandler protocolHandler, BrokerDetails brokerDetail) throws IOException
+ {
+ ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers"));
+
+ // the MINA default is currently to use the pooled allocator although this may change in future
+ // once more testing of the performance of the simple allocator has been done
+ if (!Boolean.getBoolean("amqj.enablePooledAllocator"))
+ {
+ _logger.info("Using SimpleByteBufferAllocator");
+ ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
+ }
+
+ final IoConnector ioConnector = _socketConnectorFactory.newSocketConnector();
+ final InetSocketAddress address;
+
+ if (brokerDetail.getTransport().equals(BrokerDetails.SOCKET))
+ {
+ address = null;
+ }
+ else
+ {
+ address = new InetSocketAddress(brokerDetail.getHost(), brokerDetail.getPort());
+ _logger.info("Attempting connection to " + address);
+ }
+
+ SSLConfiguration sslConfig = protocolHandler.getConnection().getSSLConfiguration();
+ SSLContextFactory sslFactory = null;
+ if (sslConfig != null)
+ {
+ sslFactory = new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType());
+ }
+
+ MINANetworkDriver driver = new MINANetworkDriver(ioConnector);
+ driver.open(brokerDetail.getPort(), address.getAddress(), protocolHandler, null, sslFactory);
+ protocolHandler.setNetworkDriver(driver);
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
new file mode 100644
index 0000000000..aef3a563af
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
@@ -0,0 +1,351 @@
+/*
+ *
+ * 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 org.apache.qpid.client.transport;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.transport.socket.nio.ExistingSocketConnector;
+import org.apache.mina.transport.socket.nio.MultiThreadSocketConnector;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.transport.vmpipe.VmPipeAcceptor;
+import org.apache.mina.transport.vmpipe.VmPipeAddress;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.thread.QpidThreadExecutor;
+import org.apache.qpid.transport.network.mina.MINANetworkDriver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The TransportConnection is a helper class responsible for connecting to an AMQ server. It sets up the underlying
+ * connector, which currently always uses TCP/IP sockets. It creates the "protocol handler" which deals with MINA
+ * protocol events. <p/> Could be extended in future to support different transport types by turning this into concrete
+ * class/interface combo.
+ */
+public class TransportConnection
+{
+ private static ITransportConnection _instance;
+
+ private static final Map _inVmPipeAddress = new HashMap();
+ private static VmPipeAcceptor _acceptor;
+ private static int _currentInstance = -1;
+ private static int _currentVMPort = -1;
+
+ private static final int TCP = 0;
+ private static final int VM = 1;
+ private static final int SOCKET = 2;
+
+ private static Logger _logger = LoggerFactory.getLogger(TransportConnection.class);
+
+ private static final String DEFAULT_QPID_SERVER = "org.apache.qpid.server.protocol.AMQProtocolEngineFactory";
+
+ private static Map<String, Socket> _openSocketRegister = new ConcurrentHashMap<String, Socket>();
+
+ public static void registerOpenSocket(String socketID, Socket openSocket)
+ {
+ _openSocketRegister.put(socketID, openSocket);
+ }
+
+ public static Socket removeOpenSocket(String socketID)
+ {
+ return _openSocketRegister.remove(socketID);
+ }
+
+ public static synchronized ITransportConnection getInstance(final BrokerDetails details) throws AMQTransportConnectionException
+ {
+ int transport = getTransport(details.getTransport());
+
+ if (transport == -1)
+ {
+ throw new AMQNoTransportForProtocolException(details, null, null);
+ }
+
+ switch (transport)
+ {
+ case SOCKET:
+ return new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
+ {
+ public IoConnector newSocketConnector()
+ {
+ ExistingSocketConnector connector = new ExistingSocketConnector(1,new QpidThreadExecutor());
+
+ Socket socket = TransportConnection.removeOpenSocket(details.getHost());
+
+ if (socket != null)
+ {
+ _logger.info("Using existing Socket:" + socket);
+
+ ((ExistingSocketConnector) connector).setOpenSocket(socket);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Active Socket must be provided for broker " +
+ "with 'socket://<SocketID>' transport:" + details);
+ }
+ return connector;
+ }
+ });
+ case TCP:
+ return new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
+ {
+ public IoConnector newSocketConnector()
+ {
+ SocketConnector result;
+ // FIXME - this needs to be sorted to use the new Mina MultiThread SA.
+ if (Boolean.getBoolean("qpidnio"))
+ {
+ _logger.warn("Using Qpid MultiThreaded NIO - " + (System.getProperties().containsKey("qpidnio")
+ ? "Qpid NIO is new default"
+ : "Sysproperty 'qpidnio' is set"));
+ result = new MultiThreadSocketConnector(1, new QpidThreadExecutor());
+ }
+ else
+ {
+ _logger.info("Using Mina NIO");
+ result = new SocketConnector(1, new QpidThreadExecutor()); // non-blocking connector
+ }
+ // Don't have the connector's worker thread wait around for other connections (we only use
+ // one SocketConnector per connection at the moment anyway). This allows short-running
+ // clients (like unit tests) to complete quickly.
+ result.setWorkerTimeout(0);
+ return result;
+ }
+ });
+ case VM:
+ {
+ return getVMTransport(details, Boolean.getBoolean("amqj.AutoCreateVMBroker"));
+ }
+ default:
+ throw new AMQNoTransportForProtocolException(details, "Transport not recognised:" + transport, null);
+ }
+ }
+
+ private static int getTransport(String transport)
+ {
+ if (transport.equals(BrokerDetails.SOCKET))
+ {
+ return SOCKET;
+ }
+
+ if (transport.equals(BrokerDetails.TCP))
+ {
+ return TCP;
+ }
+
+ if (transport.equals(BrokerDetails.VM))
+ {
+ return VM;
+ }
+
+ return -1;
+ }
+
+ private static ITransportConnection getVMTransport(BrokerDetails details, boolean AutoCreate)
+ throws AMQVMBrokerCreationException
+ {
+ int port = details.getPort();
+
+ synchronized (_inVmPipeAddress)
+ {
+ if (!_inVmPipeAddress.containsKey(port))
+ {
+ if (AutoCreate)
+ {
+ _logger.warn("Auto Creating InVM Broker on port:" + port);
+ createVMBroker(port);
+ }
+ else
+ {
+ throw new AMQVMBrokerCreationException(null, port, "VM Broker on port " + port
+ + " does not exist. Auto create disabled.", null);
+ }
+ }
+ }
+
+ return new VmPipeTransportConnection(port);
+ }
+
+ public static void createVMBroker(int port) throws AMQVMBrokerCreationException
+ {
+ synchronized(TransportConnection.class)
+ {
+ if (_acceptor == null)
+ {
+ _acceptor = new VmPipeAcceptor();
+
+ IoServiceConfig config = _acceptor.getDefaultConfig();
+ }
+ }
+ synchronized (_inVmPipeAddress)
+ {
+
+ if (!_inVmPipeAddress.containsKey(port))
+ {
+ _logger.info("Creating InVM Qpid.AMQP listening on port " + port);
+ IoHandlerAdapter provider = null;
+ try
+ {
+ VmPipeAddress pipe = new VmPipeAddress(port);
+
+ provider = createBrokerInstance(port);
+
+ _acceptor.bind(pipe, provider);
+
+ _inVmPipeAddress.put(port, pipe);
+ _logger.info("Created InVM Qpid.AMQP listening on port " + port);
+ }
+ catch (IOException e)
+ {
+ _logger.error("Got IOException.", e);
+
+ // Try and unbind provider
+ try
+ {
+ VmPipeAddress pipe = new VmPipeAddress(port);
+
+ try
+ {
+ _acceptor.unbind(pipe);
+ }
+ catch (Exception ignore)
+ {
+ // ignore
+ }
+
+ if (provider == null)
+ {
+ provider = createBrokerInstance(port);
+ }
+
+ _acceptor.bind(pipe, provider);
+ _inVmPipeAddress.put(port, pipe);
+ _logger.info("Created InVM Qpid.AMQP listening on port " + port);
+ }
+ catch (IOException justUseFirstException)
+ {
+ String because;
+ if (e.getCause() == null)
+ {
+ because = e.toString();
+ }
+ else
+ {
+ because = e.getCause().toString();
+ }
+
+ throw new AMQVMBrokerCreationException(null, port, because + " Stopped binding of InVM Qpid.AMQP", e);
+ }
+ }
+
+ }
+ else
+ {
+ _logger.info("InVM Qpid.AMQP on port " + port + " already exits.");
+ }
+ }
+ }
+
+ private static IoHandlerAdapter createBrokerInstance(int port) throws AMQVMBrokerCreationException
+ {
+ String protocolProviderClass = System.getProperty("amqj.protocolprovider.class", DEFAULT_QPID_SERVER);
+ _logger.info("Creating Qpid protocol provider: " + protocolProviderClass);
+
+ // can't use introspection to get Provider as it is a server class.
+ // need to go straight to IoHandlerAdapter but that requries the queues and exchange from the ApplicationRegistry which we can't access.
+
+ // get right constructor and pass in instancec ID - "port"
+ IoHandlerAdapter provider;
+ try
+ {
+ Class[] cnstr = {Integer.class};
+ Object[] params = {port};
+
+ provider = new MINANetworkDriver();
+ ProtocolEngineFactory engineFactory = (ProtocolEngineFactory) Class.forName(protocolProviderClass).getConstructor(cnstr).newInstance(params);
+ ((MINANetworkDriver) provider).setProtocolEngineFactory(engineFactory, true);
+ // Give the broker a second to create
+ _logger.info("Created VMBroker Instance:" + port);
+ }
+ catch (Exception e)
+ {
+ _logger.info("Unable to create InVM Qpid.AMQP on port " + port + ". Because: " + e.getCause());
+ String because;
+ if (e.getCause() == null)
+ {
+ because = e.toString();
+ }
+ else
+ {
+ because = e.getCause().toString();
+ }
+
+ AMQVMBrokerCreationException amqbce =
+ new AMQVMBrokerCreationException(null, port, because + " Stopped InVM Qpid.AMQP creation", e);
+ throw amqbce;
+ }
+
+ return provider;
+ }
+
+ public static void killAllVMBrokers()
+ {
+ _logger.info("Killing all VM Brokers");
+ synchronized(TransportConnection.class)
+ {
+ if (_acceptor != null)
+ {
+ _acceptor.unbindAll();
+ }
+ synchronized (_inVmPipeAddress)
+ {
+ _inVmPipeAddress.clear();
+ }
+ _acceptor = null;
+ }
+ _currentInstance = -1;
+ _currentVMPort = -1;
+ }
+
+ public static void killVMBroker(int port)
+ {
+ synchronized (_inVmPipeAddress)
+ {
+ VmPipeAddress pipe = (VmPipeAddress) _inVmPipeAddress.get(port);
+ if (pipe != null)
+ {
+ _logger.info("Killing VM Broker:" + port);
+ _inVmPipeAddress.remove(port);
+ // This does need to be sychronized as otherwise mina can hang
+ // if a new connection is made
+ _acceptor.unbind(pipe);
+ }
+ }
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java
new file mode 100644
index 0000000000..87cc2e7a5a
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java
@@ -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.
+ *
+ */
+package org.apache.qpid.client.transport;
+
+import java.io.IOException;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.transport.vmpipe.QpidVmPipeConnector;
+import org.apache.mina.transport.vmpipe.VmPipeAddress;
+import org.apache.mina.transport.vmpipe.VmPipeConnector;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.transport.network.mina.MINANetworkDriver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VmPipeTransportConnection implements ITransportConnection
+{
+ private static final Logger _logger = LoggerFactory.getLogger(VmPipeTransportConnection.class);
+
+ private int _port;
+
+ private MINANetworkDriver _networkDriver;
+
+ public VmPipeTransportConnection(int port)
+ {
+ _port = port;
+ }
+
+ public void connect(AMQProtocolHandler protocolHandler, BrokerDetails brokerDetail) throws IOException
+ {
+ final VmPipeConnector ioConnector = new QpidVmPipeConnector();
+
+ final VmPipeAddress address = new VmPipeAddress(_port);
+ _logger.info("Attempting connection to " + address);
+ _networkDriver = new MINANetworkDriver(ioConnector, protocolHandler);
+ protocolHandler.setNetworkDriver(_networkDriver);
+ ConnectFuture future = ioConnector.connect(address, _networkDriver);
+ // wait for connection to complete
+ future.join();
+ // we call getSession which throws an IOException if there has been an error connecting
+ future.getSession();
+ _networkDriver.setProtocolEngine(protocolHandler);
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/url/URLParser.java b/java/client/src/main/java/org/apache/qpid/client/url/URLParser.java
index 03167561ef..f3f74dd332 100644
--- a/java/client/src/main/java/org/apache/qpid/client/url/URLParser.java
+++ b/java/client/src/main/java/org/apache/qpid/client/url/URLParser.java
@@ -45,7 +45,7 @@ public class URLParser
private void parseURL(String fullURL) throws URLSyntaxException
{
// Connection URL format
- // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';tcp://host:port?option=\'value\'',failover='method?option=\'value\',option='value''"
+ // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''"
// Options are of course optional except for requiring a single broker in the broker list.
try
{
@@ -195,7 +195,7 @@ public class URLParser
{
String brokerlist = _url.getOptions().get(AMQConnectionURL.OPTIONS_BROKERLIST);
- // brokerlist tcp://host:port?option='value',option='value';tcp://host:port/virtualpath?option='value'
+ // brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'
StringTokenizer st = new StringTokenizer(brokerlist, "" + URLHelper.BROKER_SEPARATOR);
while (st.hasMoreTokens())
diff --git a/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java b/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java
index bec41644fc..208658a5ff 100644
--- a/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java
@@ -28,8 +28,9 @@ import java.util.concurrent.locks.ReentrantLock;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQTimeoutException;
import org.apache.qpid.client.failover.FailoverException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQMethodEvent;
+import org.apache.qpid.protocol.AMQMethodListener;
/**
* BlockingWaiter is a 'rendezvous' which delegates handling of
@@ -63,8 +64,6 @@ import org.slf4j.LoggerFactory;
*/
public abstract class BlockingWaiter<T>
{
- private static final Logger _logger = LoggerFactory.getLogger(BlockingWaiter.class);
-
/** This flag is used to indicate that the blocked for method has been received. */
private volatile boolean _ready = false;
@@ -181,7 +180,7 @@ public abstract class BlockingWaiter<T>
}
catch (InterruptedException e)
{
- _logger.error(e.getMessage(), e);
+ System.err.println(e.getMessage());
// IGNORE -- //fixme this isn't ideal as being interrupted isn't equivellant to sucess
// if (!_ready && timeout != -1)
// {
@@ -229,12 +228,12 @@ public abstract class BlockingWaiter<T>
}
/**
- * This is a callback, called when an error has occurred that should interrupt any waiter.
+ * This is a callback, called when an error has occured that should interupt any waiter.
* It is also called from within this class to avoid code repetition but it should only be called by the MINA threads.
*
* Once closed any notification of an exception will be ignored.
*
- * @param e The exception being propagated.
+ * @param e The exception being propogated.
*/
public void error(Exception e)
{
@@ -256,7 +255,7 @@ public abstract class BlockingWaiter<T>
}
else
{
- _logger.error("WARNING: new error '" + e == null ? "null" : e.getMessage() + "' arrived while old one not yet processed:" + _error.getMessage());
+ System.err.println("WARNING: new error '" + e == null ? "null" : e.getMessage() + "' arrived while old one not yet processed:" + _error.getMessage());
}
if (_waiting.get())
@@ -273,7 +272,7 @@ public abstract class BlockingWaiter<T>
}
catch (InterruptedException e1)
{
- _logger.error(e1.getMessage(), e1);
+ System.err.println(e.getMessage());
}
}
_errorAck = false;
diff --git a/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java b/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java
deleted file mode 100644
index 669a0f1abf..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStream.java
+++ /dev/null
@@ -1,134 +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.
- *
- */
-package org.apache.qpid.client.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
-import java.lang.reflect.Proxy;
-import java.util.HashMap;
-
-
-/**
- * <code>ClassLoadingAwareObjectInputStream</code> is an Extention of Object input stream to be used
- * to de-serialize JMS Object Messages.
- *
- * <p>This was introduced to resolve the class loading issues which can happen when we use the client
- * libraries in a complex class loading Environment.</p>
- */
-public class ClassLoadingAwareObjectInputStream extends ObjectInputStream
-{
- /** <p>Class loader instance which loaded this class.
- * It will be used to load classes when we failed to load classes from dynamic class loading</p> */
- private static final ClassLoader _ON_FAULT_CLASS_LOADER =
- ClassLoadingAwareObjectInputStream.class.getClassLoader();
-
- /** <p>Maps primitive type names to corresponding class objects.</p> */
- private static final HashMap<String, Class> _primitives = new HashMap<String, Class>(8, 1.0F);
-
-
- public ClassLoadingAwareObjectInputStream(InputStream in) throws IOException
- {
- super(in);
- }
-
- @Override
- protected Class resolveClass(ObjectStreamClass classDesc)
- throws IOException, ClassNotFoundException
- {
-
- // Here we use TTCL as our primary class loader to load the classes
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
-
- return load(classDesc.getName(), cl);
- }
-
- @Override
- protected Class resolveProxyClass(String[] interfaces)
- throws IOException, ClassNotFoundException
- {
- // Here we use TTCL as our primary class loader to load the classes
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
-
- Class[] cinterfaces = new Class[interfaces.length];
- for (int i = 0; i < interfaces.length; i++)
- {
- cinterfaces[i] = load(interfaces[i], cl);
- }
-
- try
- {
- return Proxy.getProxyClass(cinterfaces[0].getClassLoader(), cinterfaces);
- }
- catch (IllegalArgumentException e)
- {
- throw new ClassNotFoundException(null, e);
- }
- }
-
- /**
- * <p>
- * Method we used to load class that are needed to de-serialize the objects. </p>
- * <p>
- * Here we first look up for the objects from the given class loader and if its not there
- * we will be using the class loader of this class.
- * </p>
- * @param className Class name to lookup
- * @param cl primary class loader which we 1st use to lookup
- * @return Class instance we are looking for
- * @throws ClassNotFoundException if both primary and secondary lockup's failed.
- */
- private Class load(String className, ClassLoader cl)
- throws ClassNotFoundException
- {
- try
- {
- return Class.forName(className, false, cl);
- }
- catch (ClassNotFoundException e)
- {
- final Class clazz = _primitives.get(className);
-
- if (clazz != null)
- {
- return clazz;
- }
- else
- {
- return Class.forName(className, false, _ON_FAULT_CLASS_LOADER);
- }
- }
- }
-
- static
- {
- _primitives.put("boolean", boolean.class);
- _primitives.put("byte", byte.class);
- _primitives.put("char", char.class);
- _primitives.put("short", short.class);
- _primitives.put("int", int.class);
- _primitives.put("long", long.class);
- _primitives.put("float", float.class);
- _primitives.put("double", double.class);
- _primitives.put("void", void.class);
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java b/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java
new file mode 100644
index 0000000000..dc0d9b8c78
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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 org.apache.qpid.client.vmbroker;
+
+import org.apache.qpid.client.transport.AMQTransportConnectionException;
+import org.apache.qpid.protocol.AMQConstant;
+
+/**
+ * AMQVMBrokerCreationException represents failure to create an in VM broker on the vm transport medium.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represent failure to create an in VM broker.
+ * </table>
+ *
+ * @todo Error code never used. This is not an AMQException.
+ */
+public class AMQVMBrokerCreationException extends AMQTransportConnectionException
+{
+ private int _port;
+
+ /**
+ * @param port
+ *
+ * @deprecated
+ */
+ public AMQVMBrokerCreationException(int port)
+ {
+ this(null, port, "Unable to create vm broker", null);
+ }
+
+ public AMQVMBrokerCreationException(AMQConstant errorCode, int port, String message, Throwable cause)
+ {
+ super(errorCode, message, cause);
+ _port = port;
+ }
+
+ public String toString()
+ {
+ return super.toString() + " on port " + _port;
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java b/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java
index 40718c6435..4159986090 100644
--- a/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java
@@ -37,9 +37,9 @@ public class JMSSelectorFilter implements MessageFilter
public JMSSelectorFilter(String selector) throws AMQInternalException
{
_selector = selector;
- if (_logger.isDebugEnabled())
+ if (JMSSelectorFilter._logger.isDebugEnabled())
{
- _logger.debug("Created JMSSelectorFilter with selector:" + _selector);
+ JMSSelectorFilter._logger.debug("Created JMSSelectorFilter with selector:" + _selector);
}
_matcher = new SelectorParser().parse(selector);
}
@@ -49,16 +49,16 @@ public class JMSSelectorFilter implements MessageFilter
try
{
boolean match = _matcher.matches(message);
- if (_logger.isDebugEnabled())
+ if (JMSSelectorFilter._logger.isDebugEnabled())
{
- _logger.debug(message + " match(" + match + ") selector(" + System
+ JMSSelectorFilter._logger.debug(message + " match(" + match + ") selector(" + System
.identityHashCode(_selector) + "):" + _selector);
}
return match;
}
catch (AMQInternalException e)
{
- _logger.warn("Caught exception when evaluating message selector for message " + message, e);
+ JMSSelectorFilter._logger.warn("Caght exception when evaluating message selector for message " + message, e);
}
return false;
}
diff --git a/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java b/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java
index 574a1b3888..b7b6bd57bc 100644
--- a/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java
@@ -19,7 +19,6 @@ package org.apache.qpid.filter;
import java.util.HashMap;
-import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import org.apache.qpid.AMQInternalException;
@@ -33,7 +32,7 @@ import org.slf4j.LoggerFactory;
public class PropertyExpression implements Expression
{
// Constants - defined the same as JMS
- private static enum JMSDeliveryMode { NON_PERSISTENT, PERSISTENT }
+ private static final int NON_PERSISTENT = 1;
private static final int DEFAULT_PRIORITY = 4;
private static final Logger _logger = LoggerFactory.getLogger(PropertyExpression.class);
@@ -80,24 +79,22 @@ public class PropertyExpression implements Expression
{
public Object evaluate(AbstractJMSMessage message)
{
-
- JMSDeliveryMode mode = JMSDeliveryMode.NON_PERSISTENT;
try
{
- mode = message.getJMSDeliveryMode() == DeliveryMode.PERSISTENT ?
- JMSDeliveryMode.PERSISTENT : JMSDeliveryMode.NON_PERSISTENT;
-
+ int mode = message.getJMSDeliveryMode();
if (_logger.isDebugEnabled())
{
_logger.debug("JMSDeliveryMode is :" + mode);
}
+
+ return mode;
}
catch (JMSException e)
{
_logger.warn("Error evaluating property",e);
}
- return mode.toString();
+ return NON_PERSISTENT;
}
});
diff --git a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
index 0c2f4ce57d..6d81f728c9 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
@@ -22,7 +22,7 @@ package org.apache.qpid.jms;
import java.util.Map;
-import org.apache.qpid.transport.ConnectionSettings;
+import org.apache.qpid.client.SSLConfiguration;
public interface BrokerDetails
{
@@ -52,7 +52,9 @@ public interface BrokerDetails
public static final int DEFAULT_PORT = 5672;
+ public static final String SOCKET = "socket";
public static final String TCP = "tcp";
+ public static final String VM = "vm";
public static final String DEFAULT_TRANSPORT = TCP;
@@ -104,12 +106,14 @@ public interface BrokerDetails
long getTimeout();
void setTimeout(long timeout);
+
+ SSLConfiguration getSSLConfiguration();
+
+ void setSSLConfiguration(SSLConfiguration sslConfiguration);
boolean getBooleanProperty(String propName);
String toString();
boolean equals(Object o);
-
- ConnectionSettings buildConnectionSettings();
}
diff --git a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java
index 26641982d7..0e8ca60686 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java
@@ -27,7 +27,7 @@ import java.util.List;
/**
Connection URL format
- amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\'&option=\'value\';tcp://host:port/virtualpath?option=\'value\''&failover='method?option=\'value\'&option='value''"
+ amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\'&option=\'value\';vm://:3/virtualpath?option=\'value\''&failover='method?option=\'value\'&option='value''"
Options are of course optional except for requiring a single broker in the broker list.
The option seperator is defined to be either '&' or ','
*/
diff --git a/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java b/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
index 56abf03c81..7cdcd32306 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.jms;
+import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.jms.failover.FailoverExchangeMethod;
import org.apache.qpid.jms.failover.FailoverMethod;
import org.apache.qpid.jms.failover.FailoverRoundRobinServers;
@@ -50,7 +51,7 @@ public class FailoverPolicy
private long _lastMethodTime;
private long _lastFailTime;
- public FailoverPolicy(ConnectionURL connectionDetails, Connection conn)
+ public FailoverPolicy(ConnectionURL connectionDetails, AMQConnection conn)
{
FailoverMethod method;
@@ -82,7 +83,7 @@ public class FailoverPolicy
*/
if (failoverMethod.equals(FailoverMethod.SINGLE_BROKER))
{
- method = new FailoverSingleServer(connectionDetails);
+ method = new FailoverRoundRobinServers(connectionDetails);
}
else
{
diff --git a/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java b/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java
index 4ad917fa83..b830c377b8 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java
@@ -51,4 +51,7 @@ public interface MessageProducer extends javax.jms.MessageProducer
int priority, long timeToLive, boolean mandatory, boolean immediate)
throws JMSException;
+ void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive,
+ boolean mandatory, boolean immediate, boolean waitUntilSent) throws JMSException;
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java
index cb3ab718e9..9e6000c472 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverExchangeMethod.java
@@ -32,9 +32,9 @@ import javax.jms.Session;
import org.apache.qpid.client.AMQAnyDestination;
import org.apache.qpid.client.AMQBrokerDetails;
+import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.jms.BrokerDetails;
-import org.apache.qpid.jms.Connection;
import org.apache.qpid.jms.ConnectionURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,7 +58,7 @@ public class FailoverExchangeMethod implements FailoverMethod, MessageListener
private static final Logger _logger = LoggerFactory.getLogger(FailoverExchangeMethod.class);
/** This is not safe to use until attainConnection is called */
- private Connection _conn;
+ private AMQConnection _conn;
/** Protects the broker list when modifications happens */
private Object _brokerListLock = new Object();
@@ -80,7 +80,7 @@ public class FailoverExchangeMethod implements FailoverMethod, MessageListener
/** Denotes the number of failed attempts **/
private int _failedAttemps = 0;
- public FailoverExchangeMethod(ConnectionURL connectionDetails, Connection conn)
+ public FailoverExchangeMethod(ConnectionURL connectionDetails, AMQConnection conn)
{
_connectionDetails = connectionDetails;
_originalBrokerDetail = _connectionDetails.getBrokerDetails(0);
@@ -140,6 +140,7 @@ public class FailoverExchangeMethod implements FailoverMethod, MessageListener
broker.setHost(tokens[1]);
broker.setPort(Integer.parseInt(tokens[2]));
broker.setProperties(_originalBrokerDetail.getProperties());
+ broker.setSSLConfiguration(_originalBrokerDetail.getSSLConfiguration());
brokerList.add(broker);
if (currentBrokerIP.equals(broker.getHost()) &&
diff --git a/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java b/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java
index b480f56c07..fec5af55c1 100644
--- a/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java
@@ -36,7 +36,6 @@ import javax.jms.Queue;
import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.NamingException;
-import javax.naming.ConfigurationException;
import javax.naming.spi.InitialContextFactory;
import org.apache.qpid.client.AMQConnectionFactory;
@@ -140,7 +139,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
return new ReadOnlyContext(environment, data);
}
- protected void createConnectionFactories(Map data, Hashtable environment) throws ConfigurationException
+ protected void createConnectionFactories(Map data, Hashtable environment)
{
for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();)
{
@@ -158,7 +157,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
}
}
- protected void createDestinations(Map data, Hashtable environment) throws ConfigurationException
+ protected void createDestinations(Map data, Hashtable environment)
{
for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();)
{
@@ -226,7 +225,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
/**
* Factory method to create new Connection Factory instances
*/
- protected ConnectionFactory createFactory(String url) throws ConfigurationException
+ protected ConnectionFactory createFactory(String url)
{
try
{
@@ -234,18 +233,16 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
}
catch (URLSyntaxException urlse)
{
- _logger.warn("Unable to create factory:" + urlse);
-
- ConfigurationException ex = new ConfigurationException("Failed to parse entry: " + urlse + " due to : " + urlse.getMessage());
- ex.initCause(urlse);
- throw ex;
+ _logger.warn("Unable to createFactories:" + urlse);
}
+
+ return null;
}
/**
* Factory method to create new Destination instances from an AMQP BindingURL
*/
- protected Destination createDestination(String str) throws ConfigurationException
+ protected Destination createDestination(String str)
{
try
{
@@ -255,9 +252,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor
{
_logger.warn("Unable to create destination:" + e, e);
- ConfigurationException ex = new ConfigurationException("Failed to parse entry: " + str + " due to : " + e.getMessage());
- ex.initCause(e);
- throw ex;
+ return null;
}
}
diff --git a/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindConnectionFactory.java b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindConnectionFactory.java
new file mode 100644
index 0000000000..2c08f1e34a
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindConnectionFactory.java
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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 org.apache.qpid.IBMPerfTest;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.ConnectionFactory;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.File;
+import java.util.Hashtable;
+
+public class JNDIBindConnectionFactory
+{
+
+ public static final String CONNECTION_FACTORY_BINDING = "amq.ConnectionFactory";
+ public static final String DEFAULT_PROVIDER_FILE_PATH = System.getProperty("java.io.tmpdir") + File.separator + "IBMPerfTestsJNDI";
+ public static final String PROVIDER_URL = "file://" + DEFAULT_PROVIDER_FILE_PATH;
+ public static final String FSCONTEXT_FACTORY = "com.sun.jndi.fscontext.RefFSContextFactory";
+ public static final String DEFAULT_CONNECTION_URL = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'";
+
+ private static void printUsage()
+ {
+ System.out.println("Using default values: Usage:java JNDIBindConnectionFactory <connection url> [<Connection Factory Binding>] [<Provider URL>] [<JNDI Context Factory>]");
+
+ }
+
+ public static void main(String[] args)
+ {
+ Logger.getRootLogger().setLevel(Level.OFF);
+
+ String connectionFactoryBinding = CONNECTION_FACTORY_BINDING;
+ String provider = PROVIDER_URL;
+ String contextFactory = FSCONTEXT_FACTORY;
+ if (args.length == 0)
+ {
+ printUsage();
+ System.exit(1);
+ }
+
+ String connectionURL = args[0];
+
+ System.out.println("Using Connection:" + connectionURL + "\n");
+
+
+ if (args.length > 1)
+ {
+ connectionFactoryBinding = args[1];
+
+ if (args.length > 2)
+ {
+ provider = args[2];
+
+ if (args.length > 3)
+ {
+ contextFactory = args[3];
+ }
+ }
+ else
+ {
+ System.out.println("Using default File System Context Factory");
+ System.out.println("Using default Connection Factory Binding:" + connectionFactoryBinding);
+ }
+ }
+ else
+ {
+ printUsage();
+ }
+
+
+ System.out.println("File System Context Factory\n" +
+ "Connection:" + connectionURL + "\n" +
+ "Connection Factory Binding:" + connectionFactoryBinding + "\n" +
+ "JNDI Provider URL:" + provider);
+
+ if (provider.startsWith("file"))
+ {
+ File file = new File(provider.substring(provider.indexOf("://") + 3));
+
+ if (file.exists() && !file.isDirectory())
+ {
+ System.out.println("Couldn't make directory file already exists");
+ System.exit(1);
+ }
+ else
+ {
+ if (!file.exists())
+ {
+ if (!file.mkdirs())
+ {
+ System.out.println("Couldn't make directory");
+ System.exit(1);
+ }
+ }
+ }
+ }
+
+ new JNDIBindConnectionFactory(provider, connectionFactoryBinding, contextFactory, connectionURL);
+
+ }
+
+ public JNDIBindConnectionFactory(String provider, String binding, String contextFactory, String CONNECTION_URL)
+ {
+ // Set up the environment for creating the initial context
+ Hashtable env = new Hashtable(11);
+ env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
+
+ env.put(Context.PROVIDER_URL, provider);
+
+ try
+ {
+ // Create the initial context
+ Context ctx = new InitialContext(env);
+
+ // Create the object to be bound
+ ConnectionFactory factory = null;
+
+ try
+ {
+ factory = new AMQConnectionFactory(CONNECTION_URL);
+
+
+ try
+ {
+ Object obj = ctx.lookup(binding);
+
+ if (obj != null)
+ {
+ System.out.println("Un-binding previous Connection Factory");
+ ctx.unbind(binding);
+ }
+ }
+ catch (NamingException e)
+ {
+ System.out.println("Operation failed: " + e);
+ }
+
+ // Perform the bind
+ ctx.bind(binding, factory);
+ System.out.println("Bound Connection Factory:" + binding);
+
+ // Check that it is bound
+ Object obj = ctx.lookup(binding);
+ System.out.println("Connection URL:" + ((AMQConnectionFactory) obj).getConnectionURL());
+
+ System.out.println("JNDI FS Context:" + provider);
+ }
+ catch (NamingException amqe)
+ {
+ System.out.println("Operation failed: " + amqe);
+ }
+ catch (URLSyntaxException e)
+ {
+ System.out.println("Operation failed: " + e);
+ }
+
+ }
+ catch (NamingException e)
+ {
+ System.out.println("Operation failed: " + e);
+ }
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindQueue.java b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindQueue.java
new file mode 100644
index 0000000000..10e8b94311
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindQueue.java
@@ -0,0 +1,213 @@
+/*
+ *
+ * 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 org.apache.qpid.IBMPerfTest;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQSession;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.File;
+import java.util.Hashtable;
+
+public class JNDIBindQueue
+{
+ public static final String DEFAULT_PROVIDER_FILE_PATH = System.getProperty("java.io.tmpdir") + File.separator + "IBMPerfTestsJNDI";
+ public static final String PROVIDER_URL = "file://" + DEFAULT_PROVIDER_FILE_PATH;
+ public static final String FSCONTEXT_FACTORY = "com.sun.jndi.fscontext.RefFSContextFactory";
+
+ Connection _connection = null;
+ Context _ctx = null;
+
+
+ public JNDIBindQueue(String queueBinding, String queueName, String provider, String contextFactory)
+ {
+ // Set up the environment for creating the initial context
+ Hashtable env = new Hashtable(11);
+ env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
+
+ env.put(Context.PROVIDER_URL, provider);
+
+ try
+ {
+ // Create the initial context
+ _ctx = new InitialContext(env);
+
+ // Create the object to be bound
+
+ try
+ {
+ _connection = new AMQConnection("amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'");
+ System.out.println("Connected");
+ }
+ catch (Exception amqe)
+ {
+ System.out.println("Unable to create AMQConnectionFactory:" + amqe);
+ }
+
+ if (_connection != null)
+ {
+ bindQueue(queueName, queueBinding);
+ }
+
+ // Check that it is bound
+ Object obj = _ctx.lookup(queueBinding);
+
+ System.out.println("Bound Queue:" + ((AMQQueue) obj).toURL());
+
+ System.out.println("JNDI FS Context:" + provider);
+
+ }
+ catch (NamingException e)
+ {
+ System.out.println("Operation failed: " + e);
+ }
+ finally
+ {
+ try
+ {
+ if (_connection != null)
+ {
+ _connection.close();
+ }
+ }
+ catch (JMSException closeE)
+ {
+ System.out.println("Connection closing failed: " + closeE);
+ }
+ }
+
+
+ }
+
+
+ private void bindQueue(String queueName, String queueBinding) throws NamingException
+ {
+
+ try
+ {
+ Object obj = _ctx.lookup(queueBinding);
+
+ if (obj != null)
+ {
+ System.out.println("Un-binding exisiting object");
+ _ctx.unbind(queueBinding);
+ }
+ }
+ catch (NamingException e)
+ {
+
+ }
+
+ Queue queue = null;
+ try
+ {
+
+ Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ if (session != null)
+ {
+ queue = ((AMQSession) session).createQueue(queueName);
+ }
+ }
+ catch (JMSException jmse)
+ {
+ System.out.println("Unable to create Queue:" + jmse);
+ }
+
+ // Perform the bind
+ _ctx.bind(queueBinding, queue);
+ }
+
+
+ public static void main(String[] args)
+ {
+ Logger.getRootLogger().setLevel(Level.OFF);
+
+ String provider = JNDIBindQueue.PROVIDER_URL;
+ String contextFactory = JNDIBindQueue.FSCONTEXT_FACTORY;
+
+ if (args.length > 1)
+ {
+ String binding = args[0];
+ String queueName = args[1];
+
+ if (args.length > 2)
+ {
+ provider = args[2];
+
+ if (args.length > 3)
+ {
+ contextFactory = args[3];
+ }
+ }
+ else
+ {
+ System.out.println("Using default File System Context Factory");
+ }
+
+ System.out.println("File System Context Factory\n" +
+ "Binding Queue:'" + queueName + "' to '" + binding + "'\n" +
+ "JNDI Provider URL:" + provider);
+
+ if (provider.startsWith("file"))
+ {
+ File file = new File(provider.substring(provider.indexOf("://") + 3));
+
+ if (file.exists() && !file.isDirectory())
+ {
+ System.out.println("Couldn't make directory file already exists");
+ System.exit(1);
+ }
+ else
+ {
+ if (!file.exists())
+ {
+ if (!file.mkdirs())
+ {
+ System.out.println("Couldn't make directory");
+ System.exit(1);
+ }
+ }
+ }
+ }
+
+
+ new JNDIBindQueue(binding, queueName, provider, contextFactory);
+
+ }
+ else
+ {
+ System.out.println("Using Defaults: Usage:java JNDIBindQueue <Binding> <queue name> [<Provider URL> [<JNDI Context Factory>]]");
+ }
+
+ }
+
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindTopic.java b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindTopic.java
new file mode 100644
index 0000000000..ca071c1187
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/JNDIBindTopic.java
@@ -0,0 +1,212 @@
+/*
+ *
+ * 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 org.apache.qpid.IBMPerfTest;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQTopic;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.File;
+import java.util.Hashtable;
+
+public class JNDIBindTopic
+{
+ public static final String DEFAULT_PROVIDER_FILE_PATH = System.getProperty("java.io.tmpdir") + File.separator + "IBMPerfTestsJNDI";
+ public static final String PROVIDER_URL = "file://" + DEFAULT_PROVIDER_FILE_PATH;
+
+ public static final String FSCONTEXT_FACTORY = "com.sun.jndi.fscontext.RefFSContextFactory";
+
+ Connection _connection = null;
+ Context _ctx = null;
+
+
+ public JNDIBindTopic(String topicBinding, String topicName, String provider, String contextFactory)
+ {
+ // Set up the environment for creating the initial context
+ Hashtable env = new Hashtable(11);
+ env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory);
+
+ env.put(Context.PROVIDER_URL, provider);
+
+ try
+ {
+ // Create the initial context
+ _ctx = new InitialContext(env);
+
+ // Create the object to be bound
+
+ try
+ {
+ _connection = new AMQConnection("amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'");
+ System.out.println("Connected");
+ }
+ catch (Exception amqe)
+ {
+ System.out.println("Unable to create AMQConnectionFactory:" + amqe);
+ }
+
+ if (_connection != null)
+ {
+ bindTopic(topicName, topicBinding);
+ }
+
+ // Check that it is bound
+ Object obj = _ctx.lookup(topicBinding);
+
+ System.out.println("Bound Queue:" + ((AMQTopic) obj).toURL());
+
+ System.out.println("JNDI FS Context:" + provider);
+
+ }
+ catch (NamingException e)
+ {
+ System.out.println("Operation failed: " + e);
+ }
+ finally
+ {
+ try
+ {
+ if (_connection != null)
+ {
+ _connection.close();
+ }
+ }
+ catch (JMSException closeE)
+ {
+ System.out.println("Operation failed: " + closeE);
+ }
+ }
+ }
+
+
+ private void bindTopic(String topicName, String topicBinding) throws NamingException
+ {
+
+ try
+ {
+ Object obj = _ctx.lookup(topicBinding);
+
+ if (obj != null)
+ {
+ System.out.println("Un-binding exisiting object");
+ _ctx.unbind(topicBinding);
+ }
+ }
+ catch (NamingException e)
+ {
+
+ }
+
+ Topic topic = null;
+ try
+ {
+
+ Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ if (session != null)
+ {
+ topic = ((AMQSession) session).createTopic(topicName);
+ }
+ }
+ catch (JMSException jmse)
+ {
+ System.out.println("Unable to create Topic:" + jmse);
+ }
+
+ // Perform the bind
+ _ctx.bind(topicBinding, topic);
+ }
+
+
+ public static void main(String[] args)
+ {
+ Logger.getRootLogger().setLevel(Level.OFF);
+
+ String provider = JNDIBindTopic.PROVIDER_URL;
+ String contextFactory = JNDIBindTopic.FSCONTEXT_FACTORY;
+
+ if (args.length > 1)
+ {
+ String binding = args[0];
+ String queueName = args[1];
+
+ if (args.length > 2)
+ {
+ provider = args[2];
+
+ if (args.length > 3)
+ {
+ contextFactory = args[3];
+ }
+ }
+ else
+ {
+ System.out.println("Using default File System Context Factory");
+ }
+
+ System.out.println("File System Context Factory\n" +
+ "Binding Topic:'" + queueName + "' to '" + binding + "'\n" +
+ "JNDI Provider URL:" + provider);
+
+
+ if (provider.startsWith("file"))
+ {
+ File file = new File(provider.substring(provider.indexOf("://") + 3));
+
+ if (file.exists() && !file.isDirectory())
+ {
+ System.out.println("Couldn't make directory file already exists");
+ System.exit(1);
+ }
+ else
+ {
+ if (!file.exists())
+ {
+ if (!file.mkdirs())
+ {
+ System.out.println("Couldn't make directory");
+ System.exit(1);
+ }
+ }
+ }
+ }
+
+ new JNDIBindTopic(binding, queueName, provider, contextFactory);
+
+ }
+ else
+ {
+ System.out.println("Usage:java JNDIBindTopic <Binding> <topic name> [<Provider URL> [<JNDI Context Factory>]]");
+ }
+
+ }
+
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/README.txt b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/README.txt
new file mode 100644
index 0000000000..95ee9f9c77
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/IBMPerfTest/README.txt
@@ -0,0 +1,11 @@
+These JNDI setup tools are mainly for use in conjunction with the IBM JMS Performance Harness available here:
+The jar should be placed in the client/test/lib/ directory.
+
+http://www.alphaworks.ibm.com/tech/perfharness
+
+
+These JNDI classes use the the SUN FileSystem context.
+There are two jar files that should be placed in your client/test/lib directory.
+
+http://javashoplm.sun.com/ECom/docs/Welcome.jsp?StoreId=22&PartDetailId=7110-jndi-1.2.1-oth-JPR&SiteId=JSC&TransactionId=noreg
+
diff --git a/java/client/src/old_test/java/org/apache/qpid/cluster/Client.java b/java/client/src/old_test/java/org/apache/qpid/cluster/Client.java
new file mode 100644
index 0000000000..cf8059a143
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/cluster/Client.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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 org.apache.qpid.cluster;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.MessageListener;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.TextMessage;
+import java.util.Random;
+
+public class Client
+{
+ private final Random random = new Random();
+ private final String name;
+ private final Session session;
+ private final MessageProducer topicProducer;
+ private final MessageProducer queueProducer;
+
+ Client(AMQConnection connection, String name) throws JMSException, InterruptedException
+ {
+ this.name = name;
+ session = connection.createSession(false, AMQSession.NO_ACKNOWLEDGE);
+
+ AMQTopic topic = new AMQTopic(((AMQSession)session).getDefaultTopicExchangeName(), new AMQShortString("cluster_test_topic"));
+ AMQQueue queue = new AMQQueue(((AMQSession)session).getDefaultQueueExchangeName(), new AMQShortString("cluster_test_queue"));
+
+ topicProducer = session.createProducer(topic);
+ queueProducer = session.createProducer(queue);
+
+ //subscribe to a known topic
+ session.createConsumer(topic).setMessageListener(new TopicHandler());
+ //subscribe to a known queue
+ session.createConsumer(queue).setMessageListener(new QueueHandler());
+
+ connection.start();
+
+ while(true)
+ {
+ Thread.sleep(random.nextInt(60000));
+ sendToQueue(name + ":" + randomString(5));
+ }
+ }
+
+ private synchronized void sendToTopic(String message) throws JMSException
+ {
+ topicProducer.send(session.createTextMessage(message));
+ }
+
+ private synchronized void sendToQueue(String message) throws JMSException
+ {
+ queueProducer.send(session.createTextMessage(message));
+ }
+
+ private String randomString(int length){
+ char[] c = new char[length];
+ for(int i = 0; i < length; i++)
+ {
+ c[i] = (char) ('A' + random.nextInt(26));
+ }
+ return new String(c);
+ }
+
+ private class QueueHandler implements MessageListener
+ {
+ public void onMessage(Message message)
+ {
+ try
+ {
+ sendToTopic(((TextMessage) message).getText());
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private class TopicHandler implements MessageListener
+ {
+ public void onMessage(Message message)
+ {
+ try
+ {
+ System.out.println(((TextMessage) message).getText());
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void main(String[] argv) throws AMQException, JMSException, InterruptedException, URLSyntaxException
+ {
+ //assume args describe the set of brokers to try
+
+ String clientName = argv.length > 1 ? argv[1] : "testClient";
+ new Client(new AMQConnection(argv.length > 0 ? argv[0] : "vm://:1", "guest", "guest", clientName, "/test"), clientName);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/codec/BasicDeliverTest.java b/java/client/src/old_test/java/org/apache/qpid/codec/BasicDeliverTest.java
new file mode 100644
index 0000000000..1db7e200bd
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/codec/BasicDeliverTest.java
@@ -0,0 +1,277 @@
+/*
+ *
+ * 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 org.apache.qpid.codec;
+
+import org.apache.qpid.framing.*;
+import org.apache.mina.common.*;
+import org.apache.mina.common.support.BaseIoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+import java.net.SocketAddress;
+
+/**
+ */
+public class BasicDeliverTest
+{
+ public static void main(String[] argv) throws Exception
+ {
+ BasicDeliverTest test = new BasicDeliverTest();
+
+ //warm up:
+ test.encode(512, 100000);
+
+ //real tests:
+ test.encode(16, 10000, 15);
+ test.encode(32, 10000, 15);
+ test.encode(64, 10000, 15);
+ test.encode(128, 10000, 15);
+ test.encode(256, 10000, 15);
+ test.encode(512, 10000, 15);
+ test.encode(1024, 10000, 15);
+ test.encode(2048, 10000, 15);
+
+ test.decode(16, 10000, 15);
+ test.decode(32, 10000, 15);
+ test.decode(64, 10000, 15);
+ test.decode(128, 10000, 15);
+ test.decode(256, 10000, 15);
+ test.decode(512, 10000, 15);
+ test.decode(1024, 10000, 15);
+ test.decode(2048, 10000, 15);
+ }
+
+ void decode(int size, int count, int iterations) throws Exception
+ {
+ long min = Long.MAX_VALUE;
+ long max = 0;
+ long total = 0;
+ for (int i = 0; i < iterations; i++)
+ {
+ long time = decode(size, count);
+ total += time;
+ if (time < min)
+ {
+ min = time;
+ }
+ if (time > max)
+ {
+ max = time;
+ }
+ }
+ System.out.println("Decoded " + count + " messages of " + size +
+ " bytes: avg=" + (total / iterations) + ", min=" + min + ", max=" + max);
+ }
+
+
+ long decode(int size, int count) throws Exception
+ {
+ AMQDataBlock block = getDataBlock(size);
+ ByteBuffer data = ByteBuffer.allocate((int) block.getSize()); // XXX: Is cast a problem?
+ block.writePayload(data);
+ data.flip();
+ AMQDecoder decoder = new AMQDecoder(false);
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < count; i++)
+ {
+ decoder.decode(session, data, decoderOutput);
+ data.rewind();
+ }
+ return System.currentTimeMillis() - start;
+ }
+
+ void encode(int size, int count, int iterations) throws Exception
+ {
+ long min = Long.MAX_VALUE;
+ long max = 0;
+ long total = 0;
+ for (int i = 0; i < iterations; i++)
+ {
+ long time = encode(size, count);
+ total += time;
+ if (time < min)
+ {
+ min = time;
+ }
+ if (time > max)
+ {
+ max = time;
+ }
+ }
+ System.out.println("Encoded " + count + " messages of " + size +
+ " bytes: avg=" + (total / iterations) + ", min=" + min + ", max=" + max);
+ }
+
+ long encode(int size, int count) throws Exception
+ {
+ IoSession session = null;
+ AMQDataBlock block = getDataBlock(size);
+ AMQEncoder encoder = new AMQEncoder();
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < count; i++)
+ {
+ encoder.encode(session, block, encoderOutput);
+ }
+ return System.currentTimeMillis() - start;
+ }
+
+ private final ProtocolEncoderOutput encoderOutput = new ProtocolEncoderOutput()
+ {
+
+ public void write(ByteBuffer byteBuffer)
+ {
+ }
+
+ public void mergeAll()
+ {
+ }
+
+ public WriteFuture flush()
+ {
+ return null;
+ }
+ };
+
+ private final ProtocolDecoderOutput decoderOutput = new ProtocolDecoderOutput()
+ {
+ public void write(Object object)
+ {
+ }
+
+ public void flush()
+ {
+ }
+ };
+
+ private final IoSession session = new BaseIoSession()
+ {
+
+ protected void updateTrafficMask()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoService getService()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoServiceConfig getServiceConfig()
+ {
+ return null;
+ }
+
+ public IoHandler getHandler()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoSessionConfig getConfig()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoFilterChain getFilterChain()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public TransportType getTransportType()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getServiceAddress()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getScheduledWriteRequests()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getScheduledWriteBytes()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+ };
+
+ private static final char[] DATA = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+
+ static CompositeAMQDataBlock getDataBlock(int size)
+ {
+ //create a frame representing message delivery
+ AMQFrame[] frames = new AMQFrame[3];
+ frames[0] = wrapBody(createBasicDeliverBody());
+ frames[1] = wrapBody(createContentHeaderBody());
+ frames[2] = wrapBody(createContentBody(size));
+
+ return new CompositeAMQDataBlock(frames);
+ }
+
+ static AMQFrame wrapBody(AMQBody body)
+ {
+ AMQFrame frame = new AMQFrame(1, body);
+ return frame;
+ }
+
+ static ContentBody createContentBody(int size)
+ {
+ ContentBody body = new ContentBody();
+ body.payload = ByteBuffer.allocate(size);
+ for (int i = 0; i < size; i++)
+ {
+ body.payload.put((byte) DATA[i % DATA.length]);
+ }
+ return body;
+ }
+
+ static ContentHeaderBody createContentHeaderBody()
+ {
+ ContentHeaderBody body = new ContentHeaderBody();
+ body.properties = new BasicContentHeaderProperties();
+ body.weight = 1;
+ body.classId = 6;
+ return body;
+ }
+
+ static BasicDeliverBody createBasicDeliverBody()
+ {
+ BasicDeliverBody body = new BasicDeliverBody((byte) 8, (byte) 0,
+ BasicDeliverBody.getClazz((byte) 8, (byte) 0),
+ BasicDeliverBody.getMethod((byte) 8, (byte) 0),
+ new AMQShortString("myConsumerTag"), 1,
+ new AMQShortString("myExchange"), false,
+ new AMQShortString("myRoutingKey"));
+ return body;
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/codec/Client.java b/java/client/src/old_test/java/org/apache/qpid/codec/Client.java
new file mode 100644
index 0000000000..3886021277
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/codec/Client.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.codec;
+
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.BasicDeliverBody;
+import org.apache.qpid.framing.ContentBody;
+
+import java.net.InetSocketAddress;
+
+public class Client extends IoHandlerAdapter
+{
+ //private static final int[] DEFAULT_SIZES = new int[]{1024, 512, 256, 128, 56};
+ //private static final int[] DEFAULT_SIZES = new int[]{256, 256, 256, 256, 256, 512, 512, 512, 512, 512};
+ private static final int[] DEFAULT_SIZES = new int[]{256, 512, 256, 512, 256, 512, 256, 512, 256, 512};
+ //private static final int[] DEFAULT_SIZES = new int[]{1024, 1024, 1024, 1024, 1024};
+
+ private final IoSession _session;
+ private final long _start;
+ private final int _size;
+ private final int _count;
+ private int _received;
+ private boolean _closed;
+
+ Client(String host, int port, int size, int count) throws Exception
+ {
+ _count = count;
+ _size = size;
+ AMQDataBlock block = BasicDeliverTest.getDataBlock(size);
+
+ InetSocketAddress address = new InetSocketAddress(host, port);
+ ConnectFuture future = new SocketConnector().connect(address, this);
+ future.join();
+ _session = future.getSession();
+
+ _start = System.currentTimeMillis();
+ for(int i = 0; i < count; i++)
+ {
+ _session.write(block);
+ }
+ }
+
+ void close()
+ {
+ long time = System.currentTimeMillis() - _start;
+ System.out.println("Received " + _received + " messages of " + _size
+ + " bytes in " + time + "ms.");
+ _session.close();
+ synchronized(this)
+ {
+ _closed = true;
+ notify();
+ }
+ }
+
+ void waitForClose() throws InterruptedException
+ {
+ synchronized(this)
+ {
+ while(!_closed)
+ {
+ wait();
+ }
+ }
+ }
+
+ public void sessionCreated(IoSession session) throws Exception
+ {
+ session.getFilterChain().addLast("protocolFilter", new ProtocolCodecFilter(new AMQCodecFactory(false)));
+ }
+
+ public void messageReceived(IoSession session, Object object) throws Exception
+ {
+ if(isContent(object) && ++_received == _count) close();
+ }
+
+ public void exceptionCaught(IoSession session, Throwable throwable) throws Exception
+ {
+ throwable.printStackTrace();
+ close();
+ }
+
+ private static boolean isDeliver(Object o)
+ {
+ return o instanceof AMQFrame && ((AMQFrame) o).getBodyFrame() instanceof BasicDeliverBody;
+ }
+
+ private static boolean isContent(Object o)
+ {
+ return o instanceof AMQFrame && ((AMQFrame) o).getBodyFrame() instanceof ContentBody;
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ String host = argv.length > 0 ? argv[0] : "localhost";
+ int port = argv.length > 1 ? Integer.parseInt(argv[1]) : 8888;
+ int count = argv.length > 2 ? Integer.parseInt(argv[2]) : 10000;
+ int[] sizes = argv.length > 3 ? new int[]{Integer.parseInt(argv[3])} : DEFAULT_SIZES;
+
+ System.out.println("Connecting to " + host + ":" + port);
+
+ for(int i = 0; i < sizes.length; i++)
+ {
+ new Client(host, port, sizes[i], count).waitForClose();
+ Thread.sleep(1000);
+ }
+ }
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/codec/Server.java b/java/client/src/old_test/java/org/apache/qpid/codec/Server.java
new file mode 100644
index 0000000000..fa4295e0b2
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/codec/Server.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.codec;
+
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.util.SessionUtil;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.CompositeAMQDataBlock;
+
+import java.net.InetSocketAddress;
+
+public class Server extends IoHandlerAdapter
+{
+ Server(int port) throws Exception
+ {
+ new SocketAcceptor().bind(new InetSocketAddress(port), this);
+ System.out.println("Listening on " + port);
+ }
+
+ public void sessionCreated(IoSession session) throws Exception
+ {
+ SessionUtil.initialize(session);
+ session.getFilterChain().addLast("protocolFilter", new ProtocolCodecFilter(new AMQCodecFactory(false)));
+ }
+
+ public void messageReceived(IoSession session, Object object) throws Exception
+ {
+ getAccumulator(session).received(session, (AMQFrame) object);
+ }
+
+ public void sessionOpened(IoSession session) throws Exception
+ {
+ System.out.println("sessionOpened()");
+ }
+
+ public void sessionClosed(IoSession session) throws Exception
+ {
+ System.out.println("sessionClosed()");
+ }
+
+ public void exceptionCaught(IoSession session, Throwable t) throws Exception
+ {
+ System.out.println("exceptionCaught()");
+ t.printStackTrace();
+ session.close();
+ }
+
+ private Accumulator getAccumulator(IoSession session)
+ {
+ Accumulator a = (Accumulator) session.getAttribute(ACCUMULATOR);
+ if(a == null)
+ {
+ a = new Accumulator();
+ session.setAttribute(ACCUMULATOR, a);
+ }
+ return a;
+ }
+
+ private static final String ACCUMULATOR = Accumulator.class.getName();
+
+ private static class Accumulator
+ {
+ private final AMQFrame[] frames = new AMQFrame[3];
+ private int i;
+
+ void received(IoSession session, AMQFrame frame)
+ {
+ frames[i++] = frame;
+ if(i >= frames.length)
+ {
+ i = 0;
+ session.write(new CompositeAMQDataBlock(frames));
+ }
+ }
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ int port = argv.length > 0 ? Integer.parseInt(argv[0]) : 8888;
+ new Server(port);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java b/java/client/src/old_test/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java
new file mode 100644
index 0000000000..cac0064785
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.config;
+
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.config.ConnectionFactoryInitialiser;
+import org.apache.qpid.config.ConnectorConfig;
+
+import javax.jms.ConnectionFactory;
+
+class AMQConnectionFactoryInitialiser implements ConnectionFactoryInitialiser
+{
+ public ConnectionFactory getFactory(ConnectorConfig config)
+ {
+ return new AMQConnectionFactory(config.getHost(), config.getPort(), "/test_path");
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/AbstractConfig.java b/java/client/src/old_test/java/org/apache/qpid/config/AbstractConfig.java
new file mode 100644
index 0000000000..04381d66a0
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/AbstractConfig.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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 org.apache.qpid.config;
+
+public abstract class AbstractConfig
+{
+ public boolean setOptions(String[] argv)
+ {
+ try
+ {
+ for(int i = 0; i < argv.length - 1; i += 2)
+ {
+ String key = argv[i];
+ String value = argv[i+1];
+ setOption(key, value);
+ }
+ return true;
+ }
+ catch(Exception e)
+ {
+ System.out.println(e.getMessage());
+ }
+ return false;
+ }
+
+ protected int parseInt(String msg, String i)
+ {
+ try
+ {
+ return Integer.parseInt(i);
+ }
+ catch(NumberFormatException e)
+ {
+ throw new RuntimeException(msg + ": " + i);
+ }
+ }
+
+ protected long parseLong(String msg, String i)
+ {
+ try
+ {
+ return Long.parseLong(i);
+ }
+ catch(NumberFormatException e)
+ {
+ throw new RuntimeException(msg + ": " + i);
+ }
+ }
+
+ public abstract void setOption(String key, String value);
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java b/java/client/src/old_test/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java
new file mode 100644
index 0000000000..a9984eb09a
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/ConnectionFactoryInitialiser.java
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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 org.apache.qpid.config;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+
+public interface ConnectionFactoryInitialiser
+{
+ public ConnectionFactory getFactory(ConnectorConfig config) throws JMSException;
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/Connector.java b/java/client/src/old_test/java/org/apache/qpid/config/Connector.java
new file mode 100644
index 0000000000..ff2377f087
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/Connector.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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 org.apache.qpid.config;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+
+public class Connector
+{
+ public Connection createConnection(ConnectorConfig config) throws Exception
+ {
+ return getConnectionFactory(config).createConnection();
+ }
+
+ ConnectionFactory getConnectionFactory(ConnectorConfig config) throws Exception
+ {
+ String factory = config.getFactory();
+ if(factory == null) factory = AMQConnectionFactoryInitialiser.class.getName();
+ System.out.println("Using " + factory);
+ return ((ConnectionFactoryInitialiser) Class.forName(factory).newInstance()).getFactory(config);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/ConnectorConfig.java b/java/client/src/old_test/java/org/apache/qpid/config/ConnectorConfig.java
new file mode 100644
index 0000000000..b120ed3f12
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/ConnectorConfig.java
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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 org.apache.qpid.config;
+
+public interface ConnectorConfig
+{
+ public String getHost();
+ public int getPort();
+ public String getFactory();
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java b/java/client/src/old_test/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java
new file mode 100644
index 0000000000..1c86aea56c
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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 org.apache.qpid.config;
+
+import org.apache.qpid.config.ConnectionFactoryInitialiser;
+import org.apache.qpid.config.ConnectorConfig;
+
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.MBeanException;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.NameNotFoundException;
+import java.util.Hashtable;
+
+public class JBossConnectionFactoryInitialiser implements ConnectionFactoryInitialiser
+{
+ public ConnectionFactory getFactory(ConnectorConfig config) throws JMSException
+ {
+ ConnectionFactory cf = null;
+ InitialContext ic = null;
+ Hashtable ht = new Hashtable();
+ ht.put(InitialContext.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+ String jbossHost = System.getProperty("jboss.host", "eqd-lxamq01");
+ String jbossPort = System.getProperty("jboss.port", "1099");
+ ht.put(InitialContext.PROVIDER_URL, "jnp://" + jbossHost + ":" + jbossPort);
+ ht.put(InitialContext.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
+
+ try
+ {
+ ic = new InitialContext(ht);
+ if (!doesDestinationExist("topictest.messages", ic))
+ {
+ deployTopic("topictest.messages", ic);
+ }
+ if (!doesDestinationExist("topictest.control", ic))
+ {
+ deployTopic("topictest.control", ic);
+ }
+
+ cf = (ConnectionFactory) ic.lookup("/ConnectionFactory");
+ return cf;
+ }
+ catch (NamingException e)
+ {
+ JMSException jmse = new JMSException("Unable to lookup object: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+ catch (Exception e)
+ {
+ JMSException jmse = new JMSException("Error creating topic: " + e);
+ jmse.setLinkedException(e);
+ jmse.initCause(e);
+ throw jmse;
+ }
+ }
+
+ private boolean doesDestinationExist(String name, InitialContext ic) throws Exception
+ {
+ try
+ {
+ ic.lookup("/" + name);
+ }
+ catch (NameNotFoundException e)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void deployTopic(String name, InitialContext ic) throws Exception
+ {
+ MBeanServerConnection mBeanServer = lookupMBeanServerProxy(ic);
+
+ ObjectName serverObjectName = new ObjectName("jboss.messaging:service=ServerPeer");
+
+ String jndiName = "/" + name;
+ try
+ {
+ mBeanServer.invoke(serverObjectName, "createTopic",
+ new Object[]{name, jndiName},
+ new String[]{"java.lang.String", "java.lang.String"});
+ }
+ catch (MBeanException e)
+ {
+ System.err.println("Error: " + e);
+ System.err.println("Cause: " + e.getCause());
+ }
+ }
+
+ private MBeanServerConnection lookupMBeanServerProxy(InitialContext ic) throws NamingException
+ {
+ return (MBeanServerConnection) ic.lookup("jmx/invoker/RMIAdaptor");
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/flow/ChannelFlowTest.java b/java/client/src/old_test/java/org/apache/qpid/flow/ChannelFlowTest.java
new file mode 100644
index 0000000000..cb8adae18c
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/flow/ChannelFlowTest.java
@@ -0,0 +1,112 @@
+/*
+ *
+ * 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 org.apache.qpid.flow;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+
+public class ChannelFlowTest implements MessageListener
+{
+ private int sent;
+ private int received;
+
+ ChannelFlowTest(String broker) throws Exception
+ {
+ this(new AMQConnection(broker, "guest", "guest", randomize("Client"), "/test"));
+ }
+
+ ChannelFlowTest(AMQConnection connection) throws Exception
+ {
+ this(connection, new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("ChannelFlowTest")), true));
+ }
+
+ ChannelFlowTest(AMQConnection connection, AMQDestination destination) throws Exception
+ {
+ AMQSession session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE, 50,25);
+
+ //set up a slow consumer
+ session.createConsumer(destination).setMessageListener(this);
+ connection.start();
+
+ //create a publisher
+ MessageProducer producer = session.createProducer(destination);
+ Message msg = session.createTextMessage("Message");
+
+ //publish in bursts that are fast enough to cause channel flow control
+ for(int i = 0; i < 10; i++)
+ {
+ for(int j = 0; j < 100; j++)
+ {
+ producer.send(msg);
+ sent++;
+ }
+ waitUntilReceived(sent - 40);
+ }
+
+ waitUntilReceived(sent);
+
+ session.close();
+ connection.close();
+ }
+
+
+ private synchronized void waitUntilReceived(int count) throws InterruptedException
+ {
+ while(received <count)
+ {
+ wait();
+ }
+ }
+
+ public synchronized void onMessage(Message message)
+ {
+ try
+ {
+ Thread.sleep(50);
+
+ received++;
+ notify();
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private static String randomize(String in)
+ {
+ return in + System.currentTimeMillis();
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ new ChannelFlowTest(argv.length == 0 ? "localhost:5672" : argv[0]);
+ }
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargePublisher.java b/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargePublisher.java
new file mode 100644
index 0000000000..2fe01fc126
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargePublisher.java
@@ -0,0 +1,196 @@
+/*
+ *
+ * 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 org.apache.qpid.fragmentation;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.jms.MessageProducer;
+import org.apache.qpid.jms.Session;
+import org.apache.log4j.Logger;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * A client that behaves as follows:
+ * <ul><li>Connects to a queue, whose name is specified as a cmd-line argument</li>
+ * <li>Creates a temporary queue</li>
+ * <li>Creates messages containing a property that is the name of the temporary queue</li>
+ * <li>Fires off a message on the original queue and waits for a response on the temporary queue</li>
+ * </ul>
+ */
+public class TestLargePublisher
+{
+ private static final Logger _log = Logger.getLogger(TestLargePublisher.class);
+
+ private AMQConnection _connection;
+
+ private AMQSession _session;
+
+ private class CallbackHandler implements MessageListener
+ {
+ private int _expectedMessageCount;
+
+ private int _actualMessageCount;
+
+ private long _startTime;
+
+ public CallbackHandler(int expectedMessageCount, long startTime)
+ {
+ _expectedMessageCount = expectedMessageCount;
+ _startTime = startTime;
+ }
+
+ public void onMessage(Message m)
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("Message received: " + m);
+ }
+ _actualMessageCount++;
+ if (_actualMessageCount%1000 == 0)
+ {
+ _log.info("Received message count: " + _actualMessageCount);
+ }
+ /*if (!"henson".equals(m.toString()))
+ {
+ _log.error("AbstractJMSMessage response not correct: expected 'henson' but got " + m.toString());
+ }
+ else
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("AbstractJMSMessage " + m + " received");
+ }
+ else
+ {
+ _log.info("AbstractJMSMessage received");
+ }
+ } */
+
+ if (_actualMessageCount == _expectedMessageCount)
+ {
+ long timeTaken = System.currentTimeMillis() - _startTime;
+ System.out.println("Total time taken to receive " + _expectedMessageCount+ " messages was " +
+ timeTaken + "ms, equivalent to " +
+ (_expectedMessageCount/(timeTaken/1000.0)) + " messages per second");
+ }
+ }
+ }
+
+ public TestLargePublisher(String host, int port, String clientID,
+ final int messageCount) throws AMQException,URLSyntaxException
+ {
+ try
+ {
+ createConnection(host, port, clientID);
+
+ _session = (AMQSession) _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ AMQTopic destination = new AMQTopic(_session.getDefaultTopicExchangeName(), new AMQShortString("large"));
+ MessageProducer producer = (MessageProducer) _session.createProducer(destination);
+
+ _connection.start();
+ //TextMessage msg = _session.createTextMessage(tempDestination.getQueueName() + "/Presented to in conjunction with Mahnah Mahnah and the Snowths");
+ final long startTime = System.currentTimeMillis();
+
+ for (int i = 0; i < messageCount; i++)
+ {
+ BytesMessage msg = _session.createBytesMessage();
+ populateMessage(msg);
+ producer.send(msg);
+ }
+ _log.info("Finished sending " + messageCount + " messages");
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void createConnection(String host, int port, String clientID) throws AMQException , URLSyntaxException
+ {
+ _connection = new AMQConnection(host, port, "guest", "guest",
+ clientID, "/test");
+ }
+
+ private void populateMessage(BytesMessage msg) throws JMSException
+ {
+ int size = 1024 * 187; // 187k
+ byte[] data = new byte[size];
+ for (int i = 0; i < data.length; i++)
+ {
+ data[i] = (byte)(i%25);
+ }
+ msg.writeBytes(data);
+ }
+
+ /**
+ *
+ * @param args argument 1 if present specifies the name of the temporary queue to create. Leaving it blank
+ * means the server will allocate a name.
+ */
+ public static void main(String[] args) throws URLSyntaxException
+ {
+ final String host;
+ final int port;
+ final int numMessages;
+ if (args.length == 0)
+ {
+ host = "localhost";
+ port = 5672;
+ numMessages = 100;
+// System.err.println("Usage: TestLargePublisher <host> <port> <number of messages>");
+ }
+ else
+ {
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+ numMessages = Integer.parseInt(args[2]);
+ }
+
+ try
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ String clientID = address.getHostName() + System.currentTimeMillis();
+ TestLargePublisher client = new TestLargePublisher(host, port, clientID, numMessages);
+ }
+ catch (UnknownHostException e)
+ {
+ e.printStackTrace();
+ }
+ catch (AMQException e)
+ {
+ System.err.println("Error in client: " + e);
+ e.printStackTrace();
+ }
+
+ //System.exit(0);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargeSubscriber.java b/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargeSubscriber.java
new file mode 100644
index 0000000000..b0cde22349
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/fragmentation/TestLargeSubscriber.java
@@ -0,0 +1,167 @@
+/*
+ *
+ * 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 org.apache.qpid.fragmentation;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.jms.Session;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.log4j.Logger;
+
+import javax.jms.*;
+import java.net.InetAddress;
+
+public class TestLargeSubscriber
+{
+ private static final Logger _logger = Logger.getLogger(TestLargeSubscriber.class);
+
+ private static MessageProducer _destinationProducer;
+
+ private static String _destinationName;
+
+ public static void main(String[] args)
+ {
+ _logger.info("Starting...");
+
+ final String host;
+ final int port;
+ final String username;
+ final String password;
+ final String virtualPath;
+ final int numExpectedMessages;
+ if (args.length == 0)
+ {
+ host = "localhost";
+ port = 5672;
+ username = "guest";
+ password = "guest";
+ virtualPath = "/test";
+ numExpectedMessages = 100;
+ }
+ else if (args.length == 6)
+ {
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+ username = args[2];
+ password = args[3];
+ virtualPath = args[4];
+ numExpectedMessages = Integer.parseInt(args[5]);
+ }
+ else
+ {
+ System.out.println("Usage: host port username password virtual-path expectedMessageCount");
+ System.exit(1);
+ throw new RuntimeException("cannot be reached");
+ }
+
+ try
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ AMQConnection con = new AMQConnection(host, port, username, password,
+ address.getHostName(), virtualPath);
+ final AMQSession session = (AMQSession) con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ final int expectedMessageCount = numExpectedMessages;
+
+ MessageConsumer consumer = session.createConsumer(new AMQTopic(session.getDefaultTopicExchangeName(),
+ new AMQShortString("large")),
+ 100, true, false, null);
+
+ consumer.setMessageListener(new MessageListener()
+ {
+ private int _messageCount;
+
+ private long _startTime = 0;
+
+ public void onMessage(Message message)
+ {
+ validateMessage(message);
+ if (_messageCount++ == 0)
+ {
+ _startTime = System.currentTimeMillis();
+ }
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Got message '" + message + "'");
+ }
+ if (_messageCount == expectedMessageCount)
+ {
+ long totalTime = System.currentTimeMillis() - _startTime;
+ _logger.error("Total time to receive " + _messageCount + " messages was " +
+ totalTime + "ms. Rate is " + (_messageCount/(totalTime/1000.0)));
+ }
+ }
+
+ private void validateMessage(Message message)
+ {
+ if (!(message instanceof BytesMessage))
+ {
+ _logger.error("Message is not of correct type - should be BytesMessage and is " +
+ message.getClass());
+ }
+ BytesMessage bm = (BytesMessage) message;
+ final int expectedSize = 1024 * 187; // 187k
+ try
+ {
+ if (bm.getBodyLength() != expectedSize)
+ {
+ _logger.error("Message is not correct length - should be " + expectedSize + " and is " +
+ bm.getBodyLength());
+ }
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Failed to validate message: " + e, e);
+ }
+ try
+ {
+ byte[] data = new byte[(int)bm.getBodyLength()];
+ bm.readBytes(data);
+ for (int i = 0; i < data.length; i++)
+ {
+ if (data[i] != (byte)(i%25))
+ {
+ _logger.error("byte " + i + " of message is wrong - should be " + i%25 + " but is " +
+ data[i]);
+ }
+ }
+ _logger.info("***** Validated message successfully");
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Failed to validate message: " + e, e);
+ }
+ }
+ });
+ con.start();
+ }
+ catch (Throwable t)
+ {
+ System.err.println("Fatal error: " + t);
+ t.printStackTrace();
+ }
+
+ System.out.println("Waiting...");
+ }
+}
+
diff --git a/java/client/src/old_test/java/org/apache/qpid/headers/Listener.java b/java/client/src/old_test/java/org/apache/qpid/headers/Listener.java
new file mode 100644
index 0000000000..cb5caefc1e
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/headers/Listener.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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 org.apache.qpid.headers;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.jms.Session;
+//import org.apache.qpid.testutil.Config;
+
+import javax.jms.MessageListener;
+import javax.jms.Message;
+import javax.jms.Destination;
+import javax.jms.MessageProducer;
+import javax.jms.JMSException;
+
+public class Listener //implements MessageListener
+{
+/* private final AMQConnection _connection;
+ private final MessageProducer _controller;
+ private final AMQSession _session;
+ private final MessageFactory _factory;
+ private int count;
+ private long start;
+
+ Listener(AMQConnection connection, Destination exchange) throws Exception
+ {
+ _connection = connection;
+ _session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _factory = new MessageFactory(_session, 0, 19);
+
+ //register for events
+ _factory.createConsumer(exchange).setMessageListener(this);
+ _connection.start();
+
+ _controller = _session.createProducer(exchange);
+ }
+
+ private void shutdown()
+ {
+ try
+ {
+ _session.close();
+ _connection.stop();
+ _connection.close();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private void report()
+ {
+ try
+ {
+ String msg = getReport();
+ _controller.send(_factory.createReportResponseMessage(msg));
+ System.out.println("Sent report: " + msg);
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private String getReport() throws JMSException
+ {
+ long time = (System.currentTimeMillis() - start);
+ return "Received " + count + " in " + time + "ms";
+ }
+
+ public void onMessage(Message message)
+ {
+ if(count == 0) start = System.currentTimeMillis();
+
+ if(_factory.isShutdown(message))
+ {
+ shutdown();
+ }
+ else if(_factory.isReport(message))
+ {
+ //send a report:
+ report();
+ }
+ else if (++count % 100 == 0)
+ {
+ System.out.println("Received " + count + " messages.");
+ }
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ Config config = new Config();
+ config.setType(Config.HEADERS);
+ config.setName("test_headers_exchange");
+ config.setOptions(argv);
+ new Listener((AMQConnection) config.getConnection(), config.getDestination());
+ }*/
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/headers/MessageFactory.java b/java/client/src/old_test/java/org/apache/qpid/headers/MessageFactory.java
new file mode 100644
index 0000000000..a2d575fdd4
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/headers/MessageFactory.java
@@ -0,0 +1,175 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.headers;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
+
+import javax.jms.BytesMessage;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.TextMessage;
+
+/**
+ */
+class MessageFactory
+{
+ private static final char[] DATA = "abcdefghijklmnopqrstuvwxyz".toCharArray();
+
+ private final AMQSession _session;
+ private final byte[] _payload;
+
+ private String[] _headerNames;
+
+ MessageFactory(AMQSession session)
+ {
+ this(session, Integer.getInteger("amqj.test.message_size", 256).intValue(), 5);
+ }
+
+ MessageFactory(AMQSession session, int payloadSize, int headerCount)
+ {
+ if (headerCount < 1)
+ {
+ throw new IllegalArgumentException("Header count must be positive");
+ }
+ _session = session;
+ _payload = new byte[payloadSize];
+ for (int i = 0; i < _payload.length; i++)
+ {
+ _payload[i] = (byte) DATA[i % DATA.length];
+ }
+ _headerNames = new String[headerCount];
+ // note that with the standard encoding the headers get prefixed with an S to indicate their type
+ for (int i = 0; i < _headerNames.length; i++)
+ {
+ if (i < 10)
+ {
+ _headerNames[i] = "F000" + i;
+ }
+ else if (i >= 10 && i < 100)
+ {
+ _headerNames[i] = "F00" + i;
+ }
+ else
+ {
+ _headerNames[i] = "F0" + i;
+ }
+ }
+ }
+
+ Message createEventMessage() throws JMSException
+ {
+ BytesMessage msg = _session.createBytesMessage();
+ if (_payload.length != 0)
+ {
+ msg.writeBytes(_payload);
+ }
+ return setHeaders(msg, _headerNames);
+ }
+
+ Message createShutdownMessage() throws JMSException
+ {
+ return setHeaders(_session.createMessage(), new String[]{"F0000", "SHUTDOWN"});
+ }
+
+ Message createReportRequestMessage() throws JMSException
+ {
+ return setHeaders(_session.createMessage(), new String[]{"F0000", "REPORT"});
+ }
+
+ Message createReportResponseMessage(String msg) throws JMSException
+ {
+ return setHeaders(_session.createTextMessage(msg), new String[]{"CONTROL", "REPORT"});
+ }
+
+ boolean isShutdown(Message m)
+ {
+ return checkPresent(m, "SHUTDOWN");
+ }
+
+ boolean isReport(Message m)
+ {
+ return checkPresent(m, "REPORT");
+ }
+
+ Object getReport(Message m)
+ {
+ try
+ {
+ return ((TextMessage) m).getText();
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace(System.out);
+ return e.toString();
+ }
+ }
+
+ FieldTable getConsumerBinding()
+ {
+ FieldTable binding = FieldTableFactory.newFieldTable();
+ binding.setString("SF0000", "value");
+ return binding;
+ }
+
+ FieldTable getControllerBinding()
+ {
+ FieldTable binding = FieldTableFactory.newFieldTable();
+ binding.setString("SCONTROL", "value");
+ return binding;
+ }
+
+ MessageConsumer createConsumer(Destination source) throws Exception
+ {
+ return _session.createConsumer(source, 0, false, true, null, getConsumerBinding());
+ }
+
+ MessageConsumer createController(Destination source) throws Exception
+ {
+ return _session.createConsumer(source, 0, false, true, null, getControllerBinding());
+ }
+
+ private static boolean checkPresent(Message m, String s)
+ {
+ try
+ {
+ return m.getStringProperty(s) != null;
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace(System.out);
+ return false;
+ }
+ }
+
+ private static Message setHeaders(Message m, String[] headers) throws JMSException
+ {
+ for (int i = 0; i < headers.length; i++)
+ {
+ // the value in GRM is 5 bytes
+ m.setStringProperty(headers[i], "value");
+ }
+ return m;
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/headers/Publisher.java b/java/client/src/old_test/java/org/apache/qpid/headers/Publisher.java
new file mode 100644
index 0000000000..d9ef702c48
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/headers/Publisher.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.headers;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+//import org.apache.qpid.testutil.Config;
+
+import javax.jms.*;
+
+public class Publisher // implements MessageListener
+{
+/* private final Object _lock = new Object();
+ private final AMQConnection _connection;
+ private final AMQSession _session;
+ private final Destination _exchange;
+ private final MessageFactory _factory;
+ private final MessageProducer _publisher;
+ private int _count;
+
+ Publisher(AMQConnection connection, Destination exchange) throws Exception
+ {
+ _connection = connection;
+ _exchange = exchange;
+ _session = (AMQSession) _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ _factory = new MessageFactory(_session, 0, 19);
+ _publisher = _session.createProducer(_exchange);
+ }
+
+ Publisher(Config config) throws Exception
+ {
+ this((AMQConnection) config.getConnection(), config.getDestination());
+ }
+
+ private void test(int msgCount, int consumerCount) throws Exception
+ {
+ _count = consumerCount;
+ _factory.createController(_exchange).setMessageListener(this);
+ _connection.start();
+ long start = System.currentTimeMillis();
+ publish(msgCount);
+ waitForCompletion(consumerCount);
+ long end = System.currentTimeMillis();
+
+ System.out.println("Completed in " + (end - start) + " ms.");
+
+ //request shutdown
+ _publisher.send(_factory.createShutdownMessage());
+
+ _connection.stop();
+ _connection.close();
+ }
+
+ private void publish(int count) throws Exception
+ {
+
+ //send events
+ for (int i = 0; i < count; i++)
+ {
+ _publisher.send(_factory.createEventMessage());
+ if ((i + 1) % 100 == 0)
+ {
+ System.out.println("Sent " + (i + 1) + " messages");
+ }
+ }
+
+ //request report
+ _publisher.send(_factory.createReportRequestMessage());
+ }
+
+ private void waitForCompletion(int consumers) throws Exception
+ {
+ System.out.println("Waiting for completion...");
+ synchronized (_lock)
+ {
+ while (_count > 0)
+ {
+ _lock.wait();
+ }
+ }
+ }
+
+
+ public void onMessage(Message message)
+ {
+ System.out.println("Received report " + _factory.getReport(message) + " " + --_count + " remaining");
+ if (_count == 0)
+ {
+ synchronized (_lock)
+ {
+ _lock.notify();
+ }
+ }
+ }
+
+
+ public static void main(String[] argv) throws Exception
+ {
+ if (argv.length >= 2)
+ {
+ int msgCount = Integer.parseInt(argv[argv.length - 2]);
+ int consumerCount = Integer.parseInt(argv[argv.length - 1]);
+
+ Config config = new Config();
+ config.setType(Config.HEADERS);
+ config.setName("test_headers_exchange");
+ String[] options = new String[argv.length - 2];
+ System.arraycopy(argv, 0, options, 0, options.length);
+ config.setOptions(options);
+
+ new Publisher(config).test(msgCount, consumerCount);
+ }
+
+ }*/
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Bind.java b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Bind.java
new file mode 100644
index 0000000000..ee6a12c233
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Bind.java
@@ -0,0 +1,273 @@
+/*
+ *
+ * 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 org.apache.qpid.jndi.referenceable;
+
+import org.apache.qpid.client.*;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.*;
+import javax.naming.*;
+
+import java.util.Properties;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Binds a reference from a JNDI source.
+ * Given a properties file with the JNDI information and a binding string.
+ */
+public class Bind
+{
+ private static final String USAGE="USAGE: java bind <JNDI Properties file> -cf <url> <binding> | -c <url> <binding> [-t <topic Name> <binding>] [-q <queue Name> <binding>]";
+ public Bind(String propertiesFile, String bindingURL, Referenceable reference) throws NameAlreadyBoundException, NoInitialContextException
+ {
+ // Set up the environment for creating the initial context
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+ {
+ qpid_home += "/";
+ }
+
+ try
+ {
+ InputStream inputStream = new FileInputStream(qpid_home + propertiesFile);
+ Properties properties = new Properties();
+ properties.load(inputStream);
+
+ // Create the initial context
+ Context ctx = new InitialContext(properties);
+
+ // Perform the binds
+ ctx.bind(bindingURL, reference);
+
+ // Close the context when we're done
+ ctx.close();
+ }
+ catch (IOException ioe)
+ {
+ System.out.println("Unable to access properties file:" + propertiesFile + " Due to:" + ioe);
+ }
+ catch (NamingException e)
+ {
+ System.out.println("Operation failed: " + e);
+ if (e instanceof NameAlreadyBoundException)
+ {
+ throw (NameAlreadyBoundException) e;
+ }
+
+ if (e instanceof NoInitialContextException)
+ {
+ throw (NoInitialContextException) e;
+ }
+ }
+
+ }
+
+ private static String parse(String[] args, int index, String what, String type)
+ {
+ try
+ {
+ return args[index];
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ System.out.println("ERROR: No " + what + " specified for " + type + ".");
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ // The path is either return normally or exception.. which calls system exit so keep the compiler happy
+ return "Never going to happen";
+ }
+
+
+ public static void main(String[] args) throws NameAlreadyBoundException, NoInitialContextException, URLSyntaxException, AMQException, JMSException
+ {
+
+
+ org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF);
+
+// org.apache.log4j.Logger _logger = org.apache.log4j.Logger.getLogger(AMQConnection.class);
+// _logger.setLevel(org.apache.log4j.Level.OFF);
+
+ boolean exit = false;
+
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ exit = true;
+ }
+
+ if (args.length <= 2)
+ {
+ System.out.println("At least a connection or connection factory must be requested to be bound.");
+ exit = true;
+ }
+ else
+ {
+ if ((args.length - 1) % 3 != 0)
+ {
+ System.out.println("Not all values have full details");
+ exit = true;
+ }
+ }
+ if (exit)
+ {
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+
+ {
+ qpid_home += "/";
+ }
+
+ AMQConnectionFactory cf = null;
+ AMQConnection c = null;
+ AMQSession session = null;
+ Referenceable reference = null;
+
+ for (int index = 1; index < args.length; index ++)
+ {
+ String obj = args[index];
+
+ String what = "Invalid";
+ String binding;
+
+ if (obj.startsWith("-c"))
+ {
+ boolean isFactory = obj.contains("f");
+
+
+ if (isFactory)
+ {
+ what = "ConnectionFactory";
+ }
+ else
+ {
+ what = "Factory";
+ }
+
+ String url = parse(args, ++index, "url", what);
+
+ if (isFactory)
+ {
+
+ cf = new AMQConnectionFactory(url);
+ reference = cf;
+ }
+ else
+ {
+ c = new AMQConnection(url);
+ reference = c;
+ }
+
+ }
+
+ if (obj.equals("-t") || obj.equals("-q"))
+ {
+ if (c == null)
+ {
+ c = (AMQConnection) cf.createConnection();
+ }
+
+ if (session == null)
+ {
+ session = (AMQSession) c.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+
+ }
+
+ if (obj.equals("-t"))
+ {
+
+ String topicName = parse(args, ++index, "Topic Name", "Topic");
+ reference = (AMQTopic) session.createTopic(topicName);
+ what = "Topic";
+ }
+ else
+ {
+ if (obj.equals("-q"))
+ {
+ String topicName = parse(args, ++index, "Queue Name", "Queue");
+ reference = (AMQQueue) session.createQueue(topicName);
+ what = "Queue";
+ }
+ }
+
+ binding = parse(args, ++index, "binding", what);
+ if (binding == null)
+ {
+ System.out.println(obj + " is not a known Object to bind.");
+ System.exit(1);
+ }
+ else
+ {
+ System.out.print("Binding:" + reference + " to " + binding);
+ try
+ {
+ new Bind(args[0], binding, reference);
+ System.out.println(" ..Successful");
+
+ }
+ catch (NameAlreadyBoundException nabe)
+ {
+ System.out.println("");
+ if (!obj.startsWith("-c") || index == args.length - 1)
+ {
+ throw nabe;
+ }
+ else
+ {
+ System.out.println("Continuing with other bindings using the same connection details");
+ }
+ }
+ finally
+ {
+ if (!obj.startsWith("-c") || index == args.length - 1)
+ {
+ if (c != null)
+ {
+ c.close();
+ }
+ }
+ }
+ }
+ }
+
+ if (c != null)
+ {
+ c.close();
+ }
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Lookup.java b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Lookup.java
new file mode 100644
index 0000000000..1c9d8b0fd5
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Lookup.java
@@ -0,0 +1,196 @@
+/*
+ *
+ * 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 org.apache.qpid.jndi.referenceable;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Looksup a reference from a JNDI source.
+ * Given a properties file with the JNDI information and a binding string.
+ */
+public class Lookup
+{
+ private static final String USAGE = "USAGE: java lookup <JNDI Properties file> -b <binding>";
+ private Properties _properties;
+ private Object _object;
+
+ public Lookup(String propertiesFile, String bindingValue) throws NamingException
+ {
+ // Set up the environment for creating the initial context
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+ {
+ qpid_home += "/";
+ }
+
+ try
+ {
+ InputStream inputStream = new FileInputStream(qpid_home + propertiesFile);
+ Properties properties = new Properties();
+ properties.load(inputStream);
+
+ _properties = properties;
+ lookup(bindingValue);
+ }
+ catch (IOException ioe)
+ {
+ System.out.println("Unable to access properties file:" + propertiesFile + " Due to:" + ioe);
+ }
+ }
+
+ public Object lookup(String bindingValue) throws NamingException
+ {
+
+ // Create the initial context
+ Context ctx = new InitialContext(_properties);
+
+ // Perform the binds
+ _object = ctx.lookup(bindingValue);
+
+ // Close the context when we're done
+ ctx.close();
+
+ return getObject();
+ }
+
+ public Object getObject()
+ {
+ return _object;
+ }
+
+ private static String parse(String[] args, int index, String what)
+ {
+ try
+ {
+ return args[index];
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ System.out.println("ERROR: No " + what + " specified.");
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ // The path is either return normally or exception.. which calls system exit so keep the compiler happy
+ return "Never going to happen";
+ }
+
+
+ public static void main(String[] args) throws NamingException
+ {
+ boolean exit = false;
+
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ exit = true;
+ }
+
+ if (args.length <= 2)
+ {
+ System.out.println("At least a connection or connection factory must be requested to be bound.");
+ exit = true;
+ }
+ else
+ {
+ if ((args.length - 1) % 2 != 0)
+ {
+ System.out.println("Not all values have full details");
+ exit = true;
+ }
+ }
+ if (exit)
+ {
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+
+ {
+ qpid_home += "/";
+ }
+
+ for (int index = 1; index < args.length; index ++)
+ {
+ String obj = args[index];
+
+
+ if (obj.equals("-b"))
+ {
+ String binding = parse(args, ++index, "binding");
+
+ if (binding == null)
+ {
+ System.out.println("Binding not specified.");
+ System.exit(1);
+ }
+ else
+ {
+ System.out.print("Looking up:" + binding);
+ try
+ {
+ Lookup l = new Lookup(args[0], binding);
+
+ Object object = l.getObject();
+
+ if (object instanceof Connection)
+ {
+ try
+ {
+ ((Connection) object).close();
+ }
+ catch (JMSException jmse)
+ {
+ ;
+ }
+ }
+ }
+ catch (NamingException nabe)
+ {
+ System.out.println("Problem unbinding " + binding + " continuing with other values.");
+ }
+ }
+ }// if -b
+ else
+ {
+ System.out.println("Continuing with other bindings option not known:" + obj);
+ }
+ }//for
+ }//main
+}//class
diff --git a/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Unbind.java b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Unbind.java
new file mode 100644
index 0000000000..1acead674c
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/jndi/referenceable/Unbind.java
@@ -0,0 +1,166 @@
+/*
+ *
+ * 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 org.apache.qpid.jndi.referenceable;
+
+import javax.naming.*;
+
+import java.util.Properties;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Unbinds a reference from a JNDI source.
+ * Given a properties file with the JNDI information and a binding string.
+ */
+public class Unbind
+{
+ private static final String USAGE = "USAGE: java unbind <JNDI Properties file> -b <binding>";
+
+ public Unbind(String propertiesFile, String bindingValue) throws NamingException
+ {
+ // Set up the environment for creating the initial context
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+ {
+ qpid_home += "/";
+ }
+
+ try
+ {
+ InputStream inputStream = new FileInputStream(qpid_home + propertiesFile);
+ Properties properties = new Properties();
+ properties.load(inputStream);
+
+ // Create the initial context
+ Context ctx = new InitialContext(properties);
+
+ // Perform the binds
+ ctx.unbind(bindingValue);
+
+ // Close the context when we're done
+ ctx.close();
+ }
+ catch (IOException ioe)
+ {
+ System.out.println("Unable to access properties file:" + propertiesFile + " Due to:" + ioe);
+ }
+ }
+
+ private static String parse(String[] args, int index, String what)
+ {
+ try
+ {
+ return args[index];
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ System.out.println("ERROR: No " + what + " specified.");
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ // The path is either return normally or exception.. which calls system exit so keep the compiler happy
+ return "Never going to happen";
+ }
+
+
+ public static void main(String[] args) throws NamingException
+ {
+ boolean exit = false;
+
+ String qpid_home = System.getProperty("QPID_HOME");
+
+ if (qpid_home == null || qpid_home.equals(""))
+ {
+ System.out.println("QPID_HOME is not set");
+ exit = true;
+ }
+
+ if (args.length <= 2)
+ {
+ System.out.println("At least a connection or connection factory must be requested to be bound.");
+ exit = true;
+ }
+ else
+ {
+ if ((args.length - 1) % 2 != 0)
+ {
+ System.out.println("Not all values have full details");
+ exit = true;
+ }
+ }
+ if (exit)
+ {
+ System.out.println(USAGE);
+ System.exit(1);
+ }
+
+ if (qpid_home.charAt(qpid_home.length() - 1) != '/')
+
+ {
+ qpid_home += "/";
+ }
+
+ for (int index = 1; index < args.length; index ++)
+ {
+ String obj = args[index];
+
+
+ if (obj.equals("-b"))
+ {
+ String binding = parse(args, ++index, "binding");
+
+ if (binding == null)
+ {
+ System.out.println("Binding not specified.");
+ System.exit(1);
+ }
+ else
+ {
+ System.out.print("UnBinding:" + binding);
+ try
+ {
+ new Unbind(args[0], binding);
+ System.out.println(" ..Successful");
+ }
+ catch (NamingException nabe)
+ {
+ System.out.println("");
+
+ System.out.println("Problem unbinding " + binding + " continuing with other values.");
+ }
+ }
+ }// if -b
+ else
+ {
+ System.out.println("Continuing with other bindings option not known:" + obj);
+ }
+ }//for
+ }//main
+}//class
diff --git a/java/client/src/old_test/java/org/apache/qpid/latency/LatencyTest.java b/java/client/src/old_test/java/org/apache/qpid/latency/LatencyTest.java
new file mode 100644
index 0000000000..4865a68dc4
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/latency/LatencyTest.java
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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 org.apache.qpid.latency;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+
+import javax.jms.MessageProducer;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.JMSException;
+import javax.jms.TextMessage;
+import javax.jms.BytesMessage;
+
+public class LatencyTest implements MessageListener
+{
+ private volatile boolean waiting;
+ private int sent;
+ private int received;
+
+ private final byte[] data;
+
+ private long min = Long.MAX_VALUE;
+ private long max = 0;
+ private long total = 0;
+
+ LatencyTest(String broker, int count, int delay, int length) throws Exception
+ {
+ this(new AMQConnection(broker, "guest", "guest", randomize("Client"), "/test"), count, delay, length);
+ }
+
+ LatencyTest(AMQConnection connection, int count, int delay, int length) throws Exception
+ {
+ this(connection, new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("LatencyTest")), true), count, delay, length);
+ }
+
+ LatencyTest(AMQConnection connection, AMQDestination destination, int count, int delay, int length) throws Exception
+ {
+ AMQSession session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE);
+
+ data = new byte[length];
+ for(int i = 0; i < data.length; i++)
+ {
+ data[i] = (byte) (i % 100);
+ }
+
+ //set up a consumer
+ session.createConsumer(destination).setMessageListener(this);
+ connection.start();
+
+ //create a publisher
+ MessageProducer producer = session.createProducer(destination, false, false, true);
+
+ //publish at a low volume
+ for(int i = 0; i < count; i++)
+ {
+ BytesMessage msg = session.createBytesMessage();
+ msg.writeBytes(data);
+ msg.setStringProperty("sent-at", Long.toString(System.nanoTime()));
+ producer.send(msg);
+ Thread.sleep(delay);
+ if(++sent % 100 == 0)
+ {
+ System.out.println("Sent " + sent + " of " + count);
+ }
+ }
+
+ waitUntilReceived(sent);
+
+ session.close();
+ connection.close();
+
+ System.out.println("Latency (in nanoseconds): avg=" + (total/sent) + ", min=" + min + ", max=" + max
+ + ", avg(discarding min and max)=" + ((total - min - max) / (sent - 2)));
+ }
+
+
+ private synchronized void waitUntilReceived(int count) throws InterruptedException
+ {
+ waiting = true;
+ while(received < count)
+ {
+ wait();
+ }
+ waiting = false;
+ }
+
+ public void onMessage(Message message)
+ {
+ received++;
+ try
+ {
+ long sent = Long.parseLong(message.getStringProperty("sent-at"));
+ long time = System.nanoTime() - sent;
+ total += time;
+ min = Math.min(min, time);
+ max = Math.max(max, time);
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+
+ if(waiting){
+ synchronized(this)
+ {
+ notify();
+ }
+ }
+ }
+
+ private static String randomize(String in)
+ {
+ return in + System.currentTimeMillis();
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ String host = argv.length > 0 ? argv[0] : "localhost:5672";
+ if("-help".equals(host))
+ {
+ System.out.println("Usage: <broker> <message count> <delay between messages> <message size>");
+ }
+ int count = argv.length > 1 ? Integer.parseInt(argv[1]) : 1000;
+ int delay = argv.length > 2 ? Integer.parseInt(argv[2]) : 1000;
+ int size = argv.length > 3 ? Integer.parseInt(argv[3]) : 512;
+ new LatencyTest(host, count, delay, size);
+ }
+
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/mina/AcceptorTest.java b/java/client/src/old_test/java/org/apache/qpid/mina/AcceptorTest.java
new file mode 100644
index 0000000000..f0ac0e6902
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/mina/AcceptorTest.java
@@ -0,0 +1,102 @@
+/*
+ *
+ * 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 org.apache.qpid.mina;
+
+import org.apache.log4j.Logger;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+import org.apache.qpid.pool.ReadWriteThreadModel;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests MINA socket performance. This acceptor simply reads data from the network and writes it back again.
+ *
+ */
+public class AcceptorTest extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(AcceptorTest.class);
+
+ public static int PORT = 9999;
+
+ private static class TestHandler extends IoHandlerAdapter
+ {
+ private int _sentCount;
+
+ private int _bytesSent;
+
+ public void messageReceived(IoSession session, Object message) throws Exception
+ {
+ ((ByteBuffer) message).acquire();
+ session.write(message);
+ _logger.debug("Sent response " + ++_sentCount);
+ _bytesSent += ((ByteBuffer)message).remaining();
+ _logger.debug("Bytes sent: " + _bytesSent);
+ }
+
+ public void messageSent(IoSession session, Object message) throws Exception
+ {
+ //((ByteBuffer) message).release();
+ }
+
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception
+ {
+ _logger.error("Error: " + cause, cause);
+ }
+ }
+
+ public void testStartAcceptor() throws IOException
+ {
+ IoAcceptor acceptor = null;
+ acceptor = new SocketAcceptor();
+
+ SocketAcceptorConfig config = (SocketAcceptorConfig) acceptor.getDefaultConfig();
+ SocketSessionConfig sc = (SocketSessionConfig) config.getSessionConfig();
+ sc.setTcpNoDelay(true);
+ sc.setSendBufferSize(32768);
+ sc.setReceiveBufferSize(32768);
+
+ config.setThreadModel(ReadWriteThreadModel.getInstance());
+
+ acceptor.bind(new InetSocketAddress(PORT),
+ new TestHandler());
+ _logger.info("Bound on port " + PORT);
+ }
+
+ public static void main(String[] args) throws IOException
+ {
+ AcceptorTest a = new AcceptorTest();
+ a.testStartAcceptor();
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(AcceptorTest.class);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/mina/BlockingAcceptorTest.java b/java/client/src/old_test/java/org/apache/qpid/mina/BlockingAcceptorTest.java
new file mode 100644
index 0000000000..bfe29c47e6
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/mina/BlockingAcceptorTest.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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 org.apache.qpid.mina;
+
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import junit.framework.TestCase;
+
+public class BlockingAcceptorTest extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(BlockingAcceptorTest.class);
+
+ public static int PORT = 9999;
+
+ public void testStartAcceptor() throws IOException
+ {
+
+ ServerSocket sock = new ServerSocket(PORT);
+
+ sock.setReuseAddress(true);
+ sock.setReceiveBufferSize(32768);
+ _logger.info("Bound on port " + PORT);
+
+ while (true)
+ {
+ final Socket s = sock.accept();
+ _logger.info("Received connection from " + s.getRemoteSocketAddress());
+ s.setReceiveBufferSize(32768);
+ s.setSendBufferSize(32768);
+ s.setTcpNoDelay(true);
+ new Thread(new Runnable()
+ {
+ public void run()
+ {
+ byte[] chunk = new byte[32768];
+ try
+ {
+ InputStream is = s.getInputStream();
+ OutputStream os = s.getOutputStream();
+
+ while (true)
+ {
+ int count = is.read(chunk, 0, chunk.length);
+ if (count > 0)
+ {
+ os.write(chunk, 0, count);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ _logger.error("Error - closing connection: " + e, e);
+ }
+ }
+ }, "SocketReaderWriter").start();
+ }
+ }
+
+ public static void main(String[] args) throws IOException
+ {
+ BlockingAcceptorTest a = new BlockingAcceptorTest();
+ a.testStartAcceptor();
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(AcceptorTest.class);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/mina/WriterTest.java b/java/client/src/old_test/java/org/apache/qpid/mina/WriterTest.java
new file mode 100644
index 0000000000..910345624f
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/mina/WriterTest.java
@@ -0,0 +1,271 @@
+/*
+ *
+ * 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 org.apache.qpid.mina;
+
+import org.apache.log4j.Logger;
+import org.apache.mina.common.*;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.transport.socket.nio.SocketConnectorConfig;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.CountDownLatch;
+
+import junit.framework.TestCase;
+
+public class WriterTest extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(WriterTest.class);
+
+ private static class RunnableWriterTest implements Runnable
+ {
+ private Logger _logger;
+
+ private IoSession _session;
+
+ private long _startTime;
+
+ private long[] _chunkTimes;
+
+ private int _chunkCount = 500000;
+
+ private int _chunkSize = 1024;
+
+ private CountDownLatch _notifier;
+
+ public RunnableWriterTest(Logger logger)
+ {
+ _logger = logger;
+ }
+
+ public void run()
+ {
+ _startTime = System.currentTimeMillis();
+ _notifier = new CountDownLatch(1);
+ for (int i = 0; i < _chunkCount; i++)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(_chunkSize, false);
+ byte check = (byte) (i % 128);
+ buf.put(check);
+ buf.fill((byte)88, buf.remaining());
+ buf.flip();
+ _session.write(buf);
+ }
+
+ try
+ {
+ _logger.info("All buffers sent; waiting for receipt from server");
+ _notifier.await();
+ }
+ catch (InterruptedException e)
+ {
+ }
+ _logger.info("Completed");
+ long totalTime = System.currentTimeMillis() - _startTime;
+ _logger.info("Total time: " + totalTime);
+ _logger.info("MB per second: " + (_chunkSize * _chunkCount)/totalTime);
+ long lastChunkTime = _startTime;
+ double average = 0;
+ for (int i = 0; i < _chunkTimes.length; i++)
+ {
+ if (i == 0)
+ {
+ average = _chunkTimes[i] - _startTime;
+ }
+ else
+ {
+ long delta = _chunkTimes[i] - lastChunkTime;
+ if (delta != 0)
+ {
+ average = (average + delta)/2;
+ }
+ }
+ lastChunkTime = _chunkTimes[i];
+ }
+ _logger.info("Average chunk time: " + average + "ms");
+ CloseFuture cf = _session.close();
+ cf.join();
+ }
+
+ private class WriterHandler extends IoHandlerAdapter
+ {
+ private int _chunksReceived = 0;
+
+ private int _partialBytesRead = 0;
+
+ private byte _partialCheckNumber;
+
+ private int _totalBytesReceived = 0;
+
+ public void messageReceived(IoSession session, Object message) throws Exception
+ {
+ ByteBuffer result = (ByteBuffer) message;
+ _totalBytesReceived += result.remaining();
+ int size = result.remaining();
+ long now = System.currentTimeMillis();
+ if (_partialBytesRead > 0)
+ {
+ int offset = _chunkSize - _partialBytesRead;
+ if (size >= offset)
+ {
+ _chunkTimes[_chunksReceived++] = now;
+ result.position(offset);
+ }
+ else
+ {
+ // have not read even one chunk, including the previous partial bytes
+ _partialBytesRead += size;
+ return;
+ }
+ }
+
+ int chunkCount = result.remaining()/_chunkSize;
+
+ for (int i = 0; i < chunkCount; i++)
+ {
+ _chunkTimes[_chunksReceived++] = now;
+ byte check = result.get();
+ _logger.debug("Check number " + check + " read");
+ if (check != (byte)((_chunksReceived - 1)%128))
+ {
+ _logger.error("Check number " + check + " read when expected " + (_chunksReceived%128));
+ }
+ _logger.debug("Chunk times recorded");
+
+ try
+ {
+ result.skip(_chunkSize - 1);
+ }
+ catch (IllegalArgumentException e)
+ {
+ _logger.error("Position was: " + result.position());
+ _logger.error("Tried to skip to: " + (_chunkSize * i));
+ _logger.error("limit was; " + result.limit());
+ }
+ }
+ _logger.debug("Chunks received now " + _chunksReceived);
+ _logger.debug("Bytes received: " + _totalBytesReceived);
+ _partialBytesRead = result.remaining();
+
+ if (_partialBytesRead > 0)
+ {
+ _partialCheckNumber = result.get();
+ }
+
+ if (_chunksReceived >= _chunkCount)
+ {
+ _notifier.countDown();
+ }
+
+ }
+
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception
+ {
+ _logger.error("Error: " + cause, cause);
+ }
+ }
+
+ public void startWriter(int chunkSize) throws IOException, InterruptedException
+ {
+ _chunkSize = chunkSize;
+
+ IoConnector ioConnector = null;
+
+ ioConnector = new SocketConnector();
+
+ SocketConnectorConfig cfg = (SocketConnectorConfig) ioConnector.getDefaultConfig();
+ cfg.setThreadModel(ThreadModel.MANUAL);
+ SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig();
+ scfg.setTcpNoDelay(true);
+ scfg.setSendBufferSize(32768);
+ scfg.setReceiveBufferSize(32768);
+
+ final InetSocketAddress address = new InetSocketAddress("localhost", AcceptorTest.PORT);
+ _logger.info("Attempting connection to " + address);
+ ConnectFuture future = ioConnector.connect(address, new WriterHandler());
+ // wait for connection to complete
+ future.join();
+ _logger.info("Connection completed");
+ // we call getSession which throws an IOException if there has been an error connecting
+ _session = future.getSession();
+ _chunkTimes = new long[_chunkCount];
+ Thread t = new Thread(this);
+ t.start();
+ t.join();
+ _logger.info("Test completed");
+ }
+ }
+
+ private RunnableWriterTest _runnableWriterTest = new RunnableWriterTest(_logger);
+
+ public void test1k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 1k test");
+ _runnableWriterTest.startWriter(1024);
+ }
+
+ public void test2k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 2k test");
+ _runnableWriterTest.startWriter(2048);
+ }
+
+ public void test4k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 4k test");
+ _runnableWriterTest.startWriter(4096);
+ }
+
+ public void test8k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 8k test");
+ _runnableWriterTest.startWriter(8192);
+ }
+
+ public void test16k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 16k test");
+ _runnableWriterTest.startWriter(16384);
+ }
+
+ public void test32k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 32k test");
+ _runnableWriterTest.startWriter(32768);
+ }
+
+ public static void main(String[] args) throws IOException, InterruptedException
+ {
+ WriterTest w = new WriterTest();
+ //w.test1k();
+ //w.test2k();
+ //w.test4k();
+ w.test8k();
+ //w.test16k();
+ //w.test32k();
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(WriterTest.class);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/multiconsumer/AMQTest.java b/java/client/src/old_test/java/org/apache/qpid/multiconsumer/AMQTest.java
new file mode 100644
index 0000000000..db02b9954a
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/multiconsumer/AMQTest.java
@@ -0,0 +1,269 @@
+/*
+ *
+ * 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 org.apache.qpid.multiconsumer;
+
+import java.io.ByteArrayOutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.jms.Connection;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.jms.Session;
+
+/**
+ * Test AMQ.
+ */
+public class AMQTest extends TestCase implements ExceptionListener
+{
+
+ private final static String COMPRESSION_PROPNAME = "_MSGAPI_COMP";
+ private final static String UTF8 = "UTF-8";
+ private static final String SUBJECT = "test.amq";
+ private static final String DUMMYCONTENT = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String HUGECONTENT;
+
+ private AMQConnection connect = null;
+ private Session pubSession = null;
+ private Session subSession = null;
+ private Topic topic = null;
+
+ static
+ {
+ StringBuilder sb = new StringBuilder(DUMMYCONTENT.length() * 115);
+ for (int i = 0; i < 100; i++)
+ {
+ sb.append(DUMMYCONTENT);
+ }
+ HUGECONTENT = sb.toString();
+ }
+
+ private void setup() throws Exception
+ {
+ connect = new AMQConnection("localhost", 5672, "guest", "guest", "client1", "/");
+ connect.setExceptionListener(this);
+ pubSession = connect.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
+ subSession = connect.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
+ topic = new AMQTopic(pubSession.getDefaultTopicExchangeName(), new AMQShortString(SUBJECT));
+
+ connect.start();
+ }
+
+ public void testMultipleListeners() throws Exception
+ {
+ setup();
+ try
+ {
+ // Create 5 listeners
+ MsgHandler[] listeners = new MsgHandler[5];
+ for (int i = 0; i < listeners.length; i++)
+ {
+ listeners[i] = new MsgHandler();
+ MessageConsumer subscriber = subSession.createConsumer(topic);
+ subscriber.setMessageListener(listeners[i]);
+ }
+ MessageProducer publisher = pubSession.createProducer(topic);
+ // Send a single message
+ TextMessage msg = pubSession.createTextMessage();
+ msg.setText(DUMMYCONTENT);
+ publisher.send(msg);
+ Thread.sleep(5000);
+ // Check listeners to ensure they all got it
+ for (int i = 0; i < listeners.length; i++)
+ {
+ if (listeners[i].isGotIt())
+ {
+ System.out.println("Got callback for listener " + i);
+ }
+ else
+ {
+ TestCase.fail("Listener " + i + " did not get callback");
+ }
+ }
+ }
+ catch (Throwable e)
+ {
+ System.err.println("Error: " + e);
+ e.printStackTrace(System.err);
+ }
+ finally
+ {
+ close();
+ }
+ }
+
+ public void testCompression() throws Exception
+ {
+ setup();
+ String comp = this.compressString(HUGECONTENT);
+ try
+ {
+ MsgHandler listener = new MsgHandler();
+ MessageConsumer subscriber = subSession.createConsumer(topic);
+ subscriber.setMessageListener(listener);
+ MessageProducer publisher = pubSession.createProducer(topic);
+
+ // Send a single message
+ TextMessage msg = pubSession.createTextMessage();
+ // Set the compressed text
+ msg.setText(comp);
+ msg.setBooleanProperty(COMPRESSION_PROPNAME, true);
+ publisher.send(msg);
+ Thread.sleep(1000);
+ // Check listeners to ensure we got it
+ if (listener.isGotIt())
+ {
+ System.out.println("Got callback for listener");
+ }
+ else
+ {
+ TestCase.fail("Listener did not get callback");
+ }
+ }
+ finally
+ {
+ close();
+ }
+ }
+
+ private void close() throws Exception
+ {
+ if (connect != null)
+ {
+ connect.close();
+ }
+ }
+
+ private class MsgHandler implements MessageListener
+ {
+ private boolean gotIt = false;
+
+ public void onMessage(Message msg)
+ {
+ try
+ {
+ TextMessage textMessage = (TextMessage) msg;
+ String string = textMessage.getText();
+ if (string != null && string.length() > 0)
+ {
+ gotIt = true;
+ }
+ if (textMessage.getBooleanProperty(COMPRESSION_PROPNAME))
+ {
+ string = inflateString(string);
+ }
+ System.out.println("Got callback of size " + (string==null?0:string.length()));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isGotIt()
+ {
+ return this.gotIt;
+ }
+ }
+
+ private String compressString(String string) throws Exception
+ {
+ long start = System.currentTimeMillis();
+ byte[] input = string.getBytes();
+ Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION);
+ compressor.setInput(input);
+ compressor.finish();
+
+ // Get byte array from output of compressor
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length);
+ byte[] buf = new byte[1024];
+ while (!compressor.finished())
+ {
+ int cnt = compressor.deflate(buf);
+ baos.write(buf, 0, cnt);
+ }
+ baos.close();
+ byte[] output = baos.toByteArray();
+
+ // Convert byte array into String
+ byte[] base64 = Base64.encodeBase64(output);
+ String sComp = new String(base64, UTF8);
+
+ long diff = System.currentTimeMillis() - start;
+ System.out.println("Compressed text from " + input.length + " to "
+ + sComp.getBytes().length + " in " + diff + " ms");
+ System.out.println("Compressed text = '" + sComp + "'");
+
+ return sComp;
+ }
+
+ private String inflateString(String string) throws Exception
+ {
+ byte[] input = string.getBytes();
+
+ // First convert Base64 string back to binary array
+ byte[] bytes = Base64.decodeBase64(input);
+
+ // Set string as input data for decompressor
+ Inflater decompressor = new Inflater();
+ decompressor.setInput(bytes);
+
+ // Decompress the data
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length);
+ byte[] buf = new byte[1024];
+ while (!decompressor.finished())
+ {
+ int count = decompressor.inflate(buf);
+ bos.write(buf, 0, count);
+ }
+ bos.close();
+ byte[] output = bos.toByteArray();
+
+ // Get the decompressed data
+ return new String(output, UTF8);
+ }
+
+ /**
+ * @see javax.jms.ExceptionListener#onException(javax.jms.JMSException)
+ */
+ public void onException(JMSException e)
+ {
+ System.err.println(e.getMessage());
+ e.printStackTrace(System.err);
+ }
+
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestPublisher.java b/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestPublisher.java
new file mode 100644
index 0000000000..37b4ff1498
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestPublisher.java
@@ -0,0 +1,176 @@
+/*
+ *
+ * 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 org.apache.qpid.pubsub1;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.jms.MessageProducer;
+import org.apache.qpid.jms.Session;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * A client that behaves as follows:
+ * <ul><li>Connects to a queue, whose name is specified as a cmd-line argument</li>
+ * <li>Creates a temporary queue</li>
+ * <li>Creates messages containing a property that is the name of the temporary queue</li>
+ * <li>Fires off a message on the original queue and waits for a response on the temporary queue</li>
+ * </ul>
+ *
+ */
+public class TestPublisher
+{
+ private static final Logger _log = Logger.getLogger(TestPublisher.class);
+
+ private AMQConnection _connection;
+
+ private Session _session;
+
+ private class CallbackHandler implements MessageListener
+ {
+ private int _expectedMessageCount;
+
+ private int _actualMessageCount;
+
+ private long _startTime;
+
+ public CallbackHandler(int expectedMessageCount, long startTime)
+ {
+ _expectedMessageCount = expectedMessageCount;
+ _startTime = startTime;
+ }
+
+ public void onMessage(Message m)
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("Message received: " + m);
+ }
+ _actualMessageCount++;
+ if (_actualMessageCount%1000 == 0)
+ {
+ _log.info("Received message count: " + _actualMessageCount);
+ }
+ /*if (!"henson".equals(m.toString()))
+ {
+ _log.error("AbstractJMSMessage response not correct: expected 'henson' but got " + m.toString());
+ }
+ else
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("AbstractJMSMessage " + m + " received");
+ }
+ else
+ {
+ _log.info("AbstractJMSMessage received");
+ }
+ } */
+
+ if (_actualMessageCount == _expectedMessageCount)
+ {
+ long timeTaken = System.currentTimeMillis() - _startTime;
+ System.out.println("Total time taken to receive " + _expectedMessageCount+ " messages was " +
+ timeTaken + "ms, equivalent to " +
+ (_expectedMessageCount/(timeTaken/1000.0)) + " messages per second");
+ }
+ }
+ }
+
+ public TestPublisher(String host, int port, String clientID, String commandQueueName,
+ final int messageCount) throws AMQException, URLSyntaxException
+ {
+ try
+ {
+ createConnection(host, port, clientID);
+
+ _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ AMQTopic destination = new AMQTopic(_session.getDefaultTopicExchangeName(), new AMQShortString(commandQueueName));
+ MessageProducer producer = (MessageProducer) _session.createProducer(destination);
+
+ _connection.start();
+ //TextMessage msg = _session.createTextMessage(tempDestination.getQueueName() + "/Presented to in conjunction with Mahnah Mahnah and the Snowths");
+ final long startTime = System.currentTimeMillis();
+
+ for (int i = 0; i < messageCount; i++)
+ {
+ TextMessage msg = _session.createTextMessage(destination.getTopicName() + "/Presented to in conjunction with Mahnah Mahnah and the Snowths: " + i);
+
+ //msg.setIntProperty("a",i % 2);
+ //msg.setIntProperty("b",i % 4);
+
+ producer.send(msg);
+ }
+ _log.info("Finished sending " + messageCount + " messages");
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void createConnection(String host, int port, String clientID) throws AMQException, URLSyntaxException
+ {
+ _connection = new AMQConnection(host, port, "guest", "guest",
+ clientID, "/test");
+ }
+
+ /**
+ *
+ * @param args argument 1 if present specifies the name of the temporary queue to create. Leaving it blank
+ * means the server will allocate a name.
+ */
+ public static void main(String[] args) throws URLSyntaxException
+ {
+ if (args.length == 0)
+ {
+ System.err.println("Usage: TestPublisher <host> <port> <command queue name> <number of messages>");
+ }
+ try
+ {
+ int port = Integer.parseInt(args[1]);
+ InetAddress address = InetAddress.getLocalHost();
+ String clientID = address.getHostName() + System.currentTimeMillis();
+ TestPublisher client = new TestPublisher(args[0], port, clientID, args[2], Integer.parseInt(args[3]));
+ }
+ catch (UnknownHostException e)
+ {
+ e.printStackTrace();
+ }
+ catch (AMQException e)
+ {
+ System.err.println("Error in client: " + e);
+ e.printStackTrace();
+ }
+
+ //System.exit(0);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestSubscriber.java b/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestSubscriber.java
new file mode 100644
index 0000000000..450d9b3914
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/pubsub1/TestSubscriber.java
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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 org.apache.qpid.pubsub1;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.jms.Session;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.Topic;
+import java.net.InetAddress;
+
+public class TestSubscriber
+{
+ private static final Logger _logger = Logger.getLogger(TestSubscriber.class);
+
+ private static class TestMessageListener implements MessageListener
+ {
+ private String _name;
+
+ private int _expectedMessageCount;
+
+ private int _messageCount;
+
+ private long _startTime = 0;
+
+ public TestMessageListener(String name, int expectedMessageCount)
+ {
+ _name = name;
+ _expectedMessageCount = expectedMessageCount;
+ }
+
+ public void onMessage(javax.jms.Message message)
+ {
+ if (_messageCount++ == 0)
+ {
+ _startTime = System.currentTimeMillis();
+ }
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info(_name + " got message '" + message + "'");
+ }
+ if (_messageCount == _expectedMessageCount)
+ {
+ long totalTime = System.currentTimeMillis() - _startTime;
+ _logger.error(_name + ": Total time to receive " + _messageCount + " messages was " +
+ totalTime + "ms. Rate is " + (_messageCount/(totalTime/1000.0)));
+ }
+ if (_messageCount > _expectedMessageCount)
+ {
+ _logger.error("Oops! More messages received than expected (" + _messageCount + ")");
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ _logger.info("Starting...");
+
+ if (args.length != 7)
+ {
+ System.out.println("Usage: host port username password virtual-path expectedMessageCount selector");
+ System.exit(1);
+ }
+ try
+ {
+ InetAddress address = InetAddress.getLocalHost();
+ AMQConnection con1 = new AMQConnection(args[0], Integer.parseInt(args[1]), args[2], args[3],
+ address.getHostName(), args[4]);
+ final Session session1 = con1.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ AMQConnection con2 = new AMQConnection(args[0], Integer.parseInt(args[1]), args[2], args[3],
+ address.getHostName(), args[4]);
+ final Session session2 = con2.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ String selector = args[6];
+
+ final int expectedMessageCount = Integer.parseInt(args[5]);
+ _logger.info("Message selector is <" + selector + ">...");
+
+ Topic t = new AMQTopic(session1.getDefaultTopicExchangeName(), new AMQShortString("cbr"));
+ MessageConsumer consumer1 = session1.createConsumer(t,
+ 100, false, false, selector);
+ MessageConsumer consumer2 = session2.createConsumer(t,
+ 100, false, false, selector);
+
+ consumer1.setMessageListener(new TestMessageListener("ML 1", expectedMessageCount));
+ consumer2.setMessageListener(new TestMessageListener("ML 2", expectedMessageCount));
+ con1.start();
+ con2.start();
+ }
+ catch (Throwable t)
+ {
+ System.err.println("Fatal error: " + t);
+ t.printStackTrace();
+ }
+
+ System.out.println("Waiting...");
+ }
+}
+
diff --git a/java/client/src/old_test/java/org/apache/qpid/test/unit/client/connection/TestManyConnections.java b/java/client/src/old_test/java/org/apache/qpid/test/unit/client/connection/TestManyConnections.java
new file mode 100644
index 0000000000..f59b36166a
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/test/unit/client/connection/TestManyConnections.java
@@ -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.
+ *
+ */
+package org.apache.qpid.test.unit.client.connection;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.log4j.Logger;
+
+import junit.framework.TestCase;
+
+public class TestManyConnections extends TestCase
+{
+ private static final Logger _log = Logger.getLogger(TestManyConnections.class);
+
+ private AMQConnection[] _connections;
+
+ private void createConnection(int index, String brokerHosts, String clientID, String username, String password,
+ String vpath) throws AMQException, URLSyntaxException
+ {
+ _connections[index] = new AMQConnection(brokerHosts, username, password,
+ clientID, vpath);
+ }
+
+ private void createConnections(int count) throws AMQException, URLSyntaxException
+ {
+ _connections = new AMQConnection[count];
+ long startTime = System.currentTimeMillis();
+ for (int i = 0; i < count; i++)
+ {
+ createConnection(i, "vm://:1", "myClient" + i, "guest", "guest", "test");
+ }
+ long endTime = System.currentTimeMillis();
+ _log.info("Time to create " + count + " connections: " + (endTime - startTime) +
+ "ms");
+ }
+
+ public void testCreate10Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(10);
+ }
+
+ public void testCreate50Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(50);
+ }
+
+ public void testCreate100Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(100);
+ }
+
+ public void testCreate250Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(250);
+ }
+
+ public void testCreate500Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(500);
+ }
+
+ public void testCreate1000Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(1000);
+ }
+
+ public void testCreate5000Connections() throws AMQException, URLSyntaxException
+ {
+ createConnections(5000);
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(TestManyConnections.class);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/PropertiesFileInitialContextFactoryTest.java b/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/PropertiesFileInitialContextFactoryTest.java
new file mode 100644
index 0000000000..5ab5722146
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/PropertiesFileInitialContextFactoryTest.java
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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 org.apache.qpid.test.unit.jndi;
+
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+import java.util.Properties;
+import java.io.InputStream;
+
+
+import junit.framework.TestCase;
+
+public class PropertiesFileInitialContextFactoryTest extends TestCase
+{
+ InitialContextFactory contextFactory;
+ Properties _properties;
+ Properties _fileProperties;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ //create simple set of hardcoded props
+ _properties = new Properties();
+ _properties.put("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory");
+ _properties.put("connectionfactory.local", "amqp://guest:guest@clientid/testpath?brokerlist='vm://:1'");
+ _properties.put("queue.MyQueue", "example.MyQueue");
+ _properties.put("topic.ibmStocks", "stocks.nyse.ibm");
+ _properties.put("destination.direct", "direct://amq.direct//directQueue");
+
+ //create properties from file as a more realistic test
+ _fileProperties = new Properties();
+ ClassLoader cl = this.getClass().getClassLoader();
+ InputStream is = cl.getResourceAsStream("org/apache/qpid/test/unit/jndi/example.properties");
+ _fileProperties.load(is);
+ }
+
+ /**
+ * Test using hardcoded properties
+ */
+ public void testWithoutFile()
+ {
+ Context ctx = null;
+
+ try
+ {
+ ctx = new InitialContext(_properties);
+ }
+ catch (NamingException ne)
+ {
+ fail("Error loading context:" + ne);
+ }
+
+ checkPropertiesMatch(ctx, "Using hardcoded properties: ");
+ }
+
+ /**
+ * Test using properties from example file
+ */
+ public void testWithFile()
+ {
+ Context ctx = null;
+
+ try
+ {
+ ctx = new InitialContext(_fileProperties);
+ }
+ catch (Exception e)
+ {
+ fail("Error loading context:" + e);
+ }
+
+ checkPropertiesMatch(ctx, "Using properties from file: ");
+ }
+
+ public void tearDown()
+ {
+ _properties = null;
+ _fileProperties = null;
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(PropertiesFileInitialContextFactoryTest.class);
+ }
+
+ private void checkPropertiesMatch(Context ctx, String errorInfo)
+ {
+ try
+ {
+ AMQConnectionFactory cf = (AMQConnectionFactory) ctx.lookup("local");
+ assertEquals("amqp://guest:guest@clientid/testpath?brokerlist='vm://:1'", cf.getConnectionURL().toString());
+ }
+ catch (NamingException ne)
+ {
+ fail(errorInfo + "Unable to create Connection Factory:" + ne);
+ }
+
+ try
+ {
+ AMQQueue queue = (AMQQueue) ctx.lookup("MyQueue");
+ assertEquals("example.MyQueue", queue.getRoutingKey().toString());
+ }
+ catch (NamingException ne)
+ {
+ fail(errorInfo + "Unable to create queue:" + ne);
+ }
+
+ try
+ {
+ AMQTopic topic = (AMQTopic) ctx.lookup("ibmStocks");
+ assertEquals("stocks.nyse.ibm", topic.getTopicName().toString());
+ }
+ catch (Exception ne)
+ {
+ fail(errorInfo + "Unable to create topic:" + ne);
+ }
+
+ try
+ {
+ AMQQueue direct = (AMQQueue) ctx.lookup("direct");
+ assertEquals("directQueue", direct.getRoutingKey().toString());
+ }
+ catch (NamingException ne)
+ {
+ fail(errorInfo + "Unable to create direct destination:" + ne);
+ }
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/example.properties b/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/example.properties
new file mode 100644
index 0000000000..ea9dc5ae0e
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/test/unit/jndi/example.properties
@@ -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.
+
+java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
+
+# use the following property to configure the default connector
+#java.naming.provider.url - ignored.
+
+# register some connection factories
+# connectionfactory.[jndiname] = [ConnectionURL]
+connectionfactory.local = amqp://guest:guest@clientid/testpath?brokerlist='vm://:1'
+
+# register some queues in JNDI using the form
+# queue.[jndiName] = [physicalName]
+queue.MyQueue = example.MyQueue
+
+# register some topics in JNDI using the form
+# topic.[jndiName] = [physicalName]
+topic.ibmStocks = stocks.nyse.ibm
+
+# Register an AMQP destination in JNDI
+# NOTE: Qpid currently only supports direct,topics and headers
+# destination.[jniName] = [BindingURL]
+destination.direct = direct://amq.direct//directQueue
diff --git a/java/client/src/old_test/java/org/apache/qpid/topic/Config.java b/java/client/src/old_test/java/org/apache/qpid/topic/Config.java
new file mode 100644
index 0000000000..bb740f9094
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/topic/Config.java
@@ -0,0 +1,243 @@
+/*
+ *
+ * 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 org.apache.qpid.topic;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.config.ConnectorConfig;
+import org.apache.qpid.config.ConnectionFactoryInitialiser;
+import org.apache.qpid.config.Connector;
+import org.apache.qpid.config.AbstractConfig;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+
+class Config extends AbstractConfig implements ConnectorConfig
+{
+
+ private String host = "localhost";
+ private int port = 5672;
+ private String factory = null;
+
+ private int payload = 256;
+ private int messages = 1000;
+ private int clients = 1;
+ private int batch = 1;
+ private long delay = 1;
+ private int warmup;
+ private int ackMode= AMQSession.NO_ACKNOWLEDGE;
+ private String clientId;
+ private String subscriptionId;
+ private boolean persistent;
+
+ public Config()
+ {
+ }
+
+ int getAckMode()
+ {
+ return ackMode;
+ }
+
+ void setPayload(int payload)
+ {
+ this.payload = payload;
+ }
+
+ int getPayload()
+ {
+ return payload;
+ }
+
+ void setClients(int clients)
+ {
+ this.clients = clients;
+ }
+
+ int getClients()
+ {
+ return clients;
+ }
+
+ void setMessages(int messages)
+ {
+ this.messages = messages;
+ }
+
+ int getMessages()
+ {
+ return messages;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public void setHost(String host)
+ {
+ this.host = host;
+ }
+
+ public int getPort()
+ {
+ return port;
+ }
+
+ public String getFactory()
+ {
+ return factory;
+ }
+
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+ int getBatch()
+ {
+ return batch;
+ }
+
+ void setBatch(int batch)
+ {
+ this.batch = batch;
+ }
+
+ int getWarmup()
+ {
+ return warmup;
+ }
+
+ void setWarmup(int warmup)
+ {
+ this.warmup = warmup;
+ }
+
+ public long getDelay()
+ {
+ return delay;
+ }
+
+ public void setDelay(long delay)
+ {
+ this.delay = delay;
+ }
+
+ String getClientId()
+ {
+ return clientId;
+ }
+
+ String getSubscriptionId()
+ {
+ return subscriptionId;
+ }
+
+ boolean usePersistentMessages()
+ {
+ return persistent;
+ }
+
+ public void setOption(String key, String value)
+ {
+ if("-host".equalsIgnoreCase(key))
+ {
+ setHost(value);
+ }
+ else if("-port".equalsIgnoreCase(key))
+ {
+ try
+ {
+ setPort(Integer.parseInt(value));
+ }
+ catch(NumberFormatException e)
+ {
+ throw new RuntimeException("Bad port number: " + value);
+ }
+ }
+ else if("-payload".equalsIgnoreCase(key))
+ {
+ setPayload(parseInt("Bad payload size", value));
+ }
+ else if("-messages".equalsIgnoreCase(key))
+ {
+ setMessages(parseInt("Bad message count", value));
+ }
+ else if("-clients".equalsIgnoreCase(key))
+ {
+ setClients(parseInt("Bad client count", value));
+ }
+ else if("-batch".equalsIgnoreCase(key))
+ {
+ setBatch(parseInt("Bad batch count", value));
+ }
+ else if("-delay".equalsIgnoreCase(key))
+ {
+ setDelay(parseLong("Bad batch delay", value));
+ }
+ else if("-warmup".equalsIgnoreCase(key))
+ {
+ setWarmup(parseInt("Bad warmup count", value));
+ }
+ else if("-ack".equalsIgnoreCase(key))
+ {
+ ackMode = parseInt("Bad ack mode", value);
+ }
+ else if("-factory".equalsIgnoreCase(key))
+ {
+ factory = value;
+ }
+ else if("-clientId".equalsIgnoreCase(key))
+ {
+ clientId = value;
+ }
+ else if("-subscriptionId".equalsIgnoreCase(key))
+ {
+ subscriptionId = value;
+ }
+ else if("-persistent".equalsIgnoreCase(key))
+ {
+ persistent = "true".equalsIgnoreCase(value);
+ }
+ else
+ {
+ System.out.println("Ignoring unrecognised option: " + key);
+ }
+ }
+
+ static String getAckModeDescription(int ackMode)
+ {
+ switch(ackMode)
+ {
+ case AMQSession.NO_ACKNOWLEDGE: return "NO_ACKNOWLEDGE";
+ case AMQSession.AUTO_ACKNOWLEDGE: return "AUTO_ACKNOWLEDGE";
+ case AMQSession.CLIENT_ACKNOWLEDGE: return "CLIENT_ACKNOWLEDGE";
+ case AMQSession.DUPS_OK_ACKNOWLEDGE: return "DUPS_OK_ACKNOWELDGE";
+ case AMQSession.PRE_ACKNOWLEDGE: return "PRE_ACKNOWLEDGE";
+ }
+ return "AckMode=" + ackMode;
+ }
+
+ public Connection createConnection() throws Exception
+ {
+ return new Connector().createConnection(this);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/topic/Listener.java b/java/client/src/old_test/java/org/apache/qpid/topic/Listener.java
new file mode 100644
index 0000000000..47c608cfe4
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/topic/Listener.java
@@ -0,0 +1,141 @@
+/*
+ *
+ * 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 org.apache.qpid.topic;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+public class Listener implements MessageListener
+{
+ private final Connection _connection;
+ private final MessageProducer _controller;
+ private final javax.jms.Session _session;
+ private final MessageFactory _factory;
+ private boolean init;
+ private int count;
+ private long start;
+
+ Listener(Connection connection, int ackMode) throws Exception
+ {
+ this(connection, ackMode, null);
+ }
+
+ Listener(Connection connection, int ackMode, String name) throws Exception
+ {
+ _connection = connection;
+ _session = connection.createSession(false, ackMode);
+ _factory = new MessageFactory(_session);
+
+ //register for events
+ if(name == null)
+ {
+ _factory.createTopicConsumer().setMessageListener(this);
+ }
+ else
+ {
+ _factory.createDurableTopicConsumer(name).setMessageListener(this);
+ }
+
+ _connection.start();
+
+ _controller = _factory.createControlPublisher();
+ System.out.println("Waiting for messages " +
+ Config.getAckModeDescription(ackMode)
+ + (name == null ? "" : " (subscribed with name " + name + " and client id " + connection.getClientID() + ")")
+ + "...");
+
+ }
+
+ private void shutdown()
+ {
+ try
+ {
+ _session.close();
+ _connection.stop();
+ _connection.close();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private void report()
+ {
+ try
+ {
+ String msg = getReport();
+ _controller.send(_factory.createReportResponseMessage(msg));
+ System.out.println("Sent report: " + msg);
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace(System.out);
+ }
+ }
+
+ private String getReport()
+ {
+ long time = (System.currentTimeMillis() - start);
+ return "Received " + count + " in " + time + "ms";
+ }
+
+ public void onMessage(Message message)
+ {
+ if(!init)
+ {
+ start = System.currentTimeMillis();
+ count = 0;
+ init = true;
+ }
+
+ if(_factory.isShutdown(message))
+ {
+ shutdown();
+ }
+ else if(_factory.isReport(message))
+ {
+ //send a report:
+ report();
+ init = false;
+ }
+ else if (++count % 100 == 0)
+ {
+ System.out.println("Received " + count + " messages.");
+ }
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ Config config = new Config();
+ config.setOptions(argv);
+
+ Connection con = config.createConnection();
+ if(config.getClientId() != null)
+ {
+ con.setClientID(config.getClientId());
+ }
+ new Listener(con, config.getAckMode(), config.getSubscriptionId());
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/topic/MessageFactory.java b/java/client/src/old_test/java/org/apache/qpid/topic/MessageFactory.java
new file mode 100644
index 0000000000..39d64069d1
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/topic/MessageFactory.java
@@ -0,0 +1,155 @@
+/*
+ *
+ * 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 org.apache.qpid.topic;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+
+import javax.jms.*;
+
+/**
+ */
+class MessageFactory
+{
+ private static final char[] DATA = "abcdefghijklmnopqrstuvwxyz".toCharArray();
+
+ private final Session _session;
+ private final Topic _topic;
+ private final Topic _control;
+ private final byte[] _payload;
+
+
+ MessageFactory(Session session) throws JMSException
+ {
+ this(session, 256);
+ }
+
+ MessageFactory(Session session, int size) throws JMSException
+ {
+ _session = session;
+ if(session instanceof AMQSession)
+ {
+ _topic = new AMQTopic(((AMQSession)session).getDefaultTopicExchangeName(),new AMQShortString("topictest.messages"));
+ _control = new AMQTopic(((AMQSession)session).getDefaultTopicExchangeName(),new AMQShortString("topictest.control"));
+ }
+ else
+ {
+ _topic = session.createTopic("topictest.messages");
+ _control = session.createTopic("topictest.control");
+ }
+ _payload = new byte[size];
+
+ for(int i = 0; i < size; i++)
+ {
+ _payload[i] = (byte) DATA[i % DATA.length];
+ }
+ }
+
+ Topic getTopic()
+ {
+ return _topic;
+ }
+
+ Message createEventMessage() throws JMSException
+ {
+ BytesMessage msg = _session.createBytesMessage();
+ msg.writeBytes(_payload);
+ return msg;
+ }
+
+ Message createShutdownMessage() throws JMSException
+ {
+ return _session.createTextMessage("SHUTDOWN");
+ }
+
+ Message createReportRequestMessage() throws JMSException
+ {
+ return _session.createTextMessage("REPORT");
+ }
+
+ Message createReportResponseMessage(String msg) throws JMSException
+ {
+ return _session.createTextMessage(msg);
+ }
+
+ boolean isShutdown(Message m)
+ {
+ return checkText(m, "SHUTDOWN");
+ }
+
+ boolean isReport(Message m)
+ {
+ return checkText(m, "REPORT");
+ }
+
+ Object getReport(Message m)
+ {
+ try
+ {
+ return ((TextMessage) m).getText();
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace(System.out);
+ return e.toString();
+ }
+ }
+
+ MessageConsumer createTopicConsumer() throws Exception
+ {
+ return _session.createConsumer(_topic);
+ }
+
+ MessageConsumer createDurableTopicConsumer(String name) throws Exception
+ {
+ return _session.createDurableSubscriber(_topic, name);
+ }
+
+ MessageConsumer createControlConsumer() throws Exception
+ {
+ return _session.createConsumer(_control);
+ }
+
+ MessageProducer createTopicPublisher() throws Exception
+ {
+ return _session.createProducer(_topic);
+ }
+
+ MessageProducer createControlPublisher() throws Exception
+ {
+ return _session.createProducer(_control);
+ }
+
+ private static boolean checkText(Message m, String s)
+ {
+ try
+ {
+ return m instanceof TextMessage && ((TextMessage) m).getText().equals(s);
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace(System.out);
+ return false;
+ }
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/topic/Publisher.java b/java/client/src/old_test/java/org/apache/qpid/topic/Publisher.java
new file mode 100644
index 0000000000..d788029ee9
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/topic/Publisher.java
@@ -0,0 +1,175 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.topic;
+
+import javax.jms.*;
+
+public class Publisher implements MessageListener
+{
+ private final Object _lock = new Object();
+ private final Connection _connection;
+ private final Session _session;
+ private final MessageFactory _factory;
+ private final MessageProducer _publisher;
+ private int _count;
+
+ Publisher(Connection connection, int size, int ackMode, boolean persistent) throws Exception
+ {
+ _connection = connection;
+ _session = _connection.createSession(false, ackMode);
+ _factory = new MessageFactory(_session, size);
+ _publisher = _factory.createTopicPublisher();
+ _publisher.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+ System.out.println("Publishing " + (persistent ? "persistent" : "non-persistent") + " messages of " + size + " bytes, " + Config.getAckModeDescription(ackMode) + ".");
+ }
+
+ private void test(Config config) throws Exception
+ {
+ test(config.getBatch(), config.getDelay(), config.getMessages(), config.getClients(), config.getWarmup());
+ }
+
+ private void test(int batches, long delay, int msgCount, int consumerCount, int warmup) throws Exception
+ {
+ _factory.createControlConsumer().setMessageListener(this);
+ _connection.start();
+
+ if(warmup > 0)
+ {
+ System.out.println("Runing warmup (" + warmup + " msgs)");
+ long time = batch(warmup, consumerCount);
+ System.out.println("Warmup completed in " + time + "ms");
+ }
+
+ long[] times = new long[batches];
+ for(int i = 0; i < batches; i++)
+ {
+ if(i > 0) Thread.sleep(delay*1000);
+ times[i] = batch(msgCount, consumerCount);
+ System.out.println("Batch " + (i+1) + " of " + batches + " completed in " + times[i] + " ms.");
+ }
+
+ long min = min(times);
+ long max = max(times);
+ System.out.println("min: " + min + ", max: " + max + " avg: " + avg(times, min, max));
+
+ //request shutdown
+ _publisher.send(_factory.createShutdownMessage());
+
+ _connection.stop();
+ _connection.close();
+ }
+
+ private long batch(int msgCount, int consumerCount) throws Exception
+ {
+ _count = consumerCount;
+ long start = System.currentTimeMillis();
+ publish(msgCount);
+ waitForCompletion(consumerCount);
+ return System.currentTimeMillis() - start;
+ }
+
+ private void publish(int count) throws Exception
+ {
+
+ //send events
+ for (int i = 0; i < count; i++)
+ {
+ _publisher.send(_factory.createEventMessage());
+ if ((i + 1) % 100 == 0)
+ {
+ System.out.println("Sent " + (i + 1) + " messages");
+ }
+ }
+
+ //request report
+ _publisher.send(_factory.createReportRequestMessage());
+ }
+
+ private void waitForCompletion(int consumers) throws Exception
+ {
+ System.out.println("Waiting for completion...");
+ synchronized (_lock)
+ {
+ while (_count > 0)
+ {
+ _lock.wait();
+ }
+ }
+ }
+
+
+ public void onMessage(Message message)
+ {
+ System.out.println("Received report " + _factory.getReport(message) + " " + --_count + " remaining");
+ if (_count == 0)
+ {
+ synchronized (_lock)
+ {
+ _lock.notify();
+ }
+ }
+ }
+
+ static long min(long[] times)
+ {
+ long min = times.length > 0 ? times[0] : 0;
+ for(int i = 0; i < times.length; i++)
+ {
+ min = Math.min(min, times[i]);
+ }
+ return min;
+ }
+
+ static long max(long[] times)
+ {
+ long max = times.length > 0 ? times[0] : 0;
+ for(int i = 0; i < times.length; i++)
+ {
+ max = Math.max(max, times[i]);
+ }
+ return max;
+ }
+
+ static long avg(long[] times, long min, long max)
+ {
+ long sum = 0;
+ for(int i = 0; i < times.length; i++)
+ {
+ sum += times[i];
+ }
+ sum -= min;
+ sum -= max;
+
+ return (sum / (times.length - 2));
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ Config config = new Config();
+ config.setOptions(argv);
+
+ Connection con = config.createConnection();
+ int size = config.getPayload();
+ int ackMode = config.getAckMode();
+ boolean persistent = config.usePersistentMessages();
+ new Publisher(con, size, ackMode, persistent).test(config);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/Config.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Config.java
new file mode 100644
index 0000000000..bd104e5407
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Config.java
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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 org.apache.qpid.transacted;
+
+import org.apache.qpid.config.ConnectorConfig;
+import org.apache.qpid.config.AbstractConfig;
+import org.apache.qpid.config.Connector;
+
+import javax.jms.Connection;
+
+class Config extends AbstractConfig implements ConnectorConfig
+{
+ private String host = "localhost";
+ private int port = 5672;
+ private String factory;
+ private boolean echo;
+ private int batch = 100;
+ private boolean persistent = true;
+
+ Config(String[] argv)
+ {
+ setOptions(argv);
+ }
+
+ Connection createConnection() throws Exception
+ {
+ return new Connector().createConnection(this);
+ }
+
+ public boolean isEchoOn()
+ {
+ return echo;
+ }
+
+ public boolean usePersistentMessages()
+ {
+ return persistent;
+ }
+
+ public int getBatchSize()
+ {
+ return batch;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public int getPort()
+ {
+ return port;
+ }
+
+ public String getFactory()
+ {
+ return factory;
+ }
+
+ public void setOption(String key, String value)
+ {
+ if("-host".equalsIgnoreCase(key))
+ {
+ host = value;
+ }
+ else if("-port".equalsIgnoreCase(key))
+ {
+ port = parseInt("Bad port number", value);
+ }
+ else if("-factory".equalsIgnoreCase(key))
+ {
+ factory = value;
+ }
+ else if("-echo".equalsIgnoreCase(key))
+ {
+ echo = "true".equalsIgnoreCase(value);
+ }
+ else if("-persistent".equalsIgnoreCase(key))
+ {
+ persistent = "true".equalsIgnoreCase(value);
+ }
+ else if("-batch".equalsIgnoreCase(key))
+ {
+ batch = parseInt("Bad batch size", value);
+ }
+ else
+ {
+ System.out.println("Ignoring nrecognised option " + key);
+ }
+ }
+
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java
new file mode 100644
index 0000000000..8f15bf089e
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transacted;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.client.AMQQueue;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import java.util.Arrays;
+
+public class Ping
+{
+ public static void main(String[] argv) throws Exception
+ {
+ Config config = new Config(argv);
+ Connection con = config.createConnection();
+ con.setClientID("ping");
+ new Relay(new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString("ping")), new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString("pong")), con,
+ config.isEchoOn(),
+ config.getBatchSize(),
+ config.usePersistentMessages()).start();
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java
new file mode 100644
index 0000000000..f4f4b20d7c
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transacted;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.client.AMQQueue;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+
+public class Pong
+{
+ public static void main(String[] argv) throws Exception
+ {
+ Config config = new Config(argv);
+ Connection con = config.createConnection();
+ con.setClientID("pong");
+ new Relay(new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString("pong")), new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString("ping")), con,
+ config.isEchoOn(),
+ config.getBatchSize(),
+ config.usePersistentMessages()).start();
+
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java
new file mode 100644
index 0000000000..cede95e5f0
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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 org.apache.qpid.transacted;
+
+import org.apache.qpid.client.AMQSession;
+
+import javax.jms.MessageProducer;
+import javax.jms.MessageConsumer;
+import javax.jms.Session;
+import javax.jms.Destination;
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.TextMessage;
+import javax.jms.DeliveryMode;
+
+class Relay implements Runnable
+{
+ private final Connection _con;
+ private final Session _session;
+ private final MessageConsumer _src;
+ private final MessageProducer _dest;
+ private final int _batch;
+ private final boolean _echo;
+ private int _counter;
+ private long start;
+ private boolean _running;
+
+ Relay(Destination src, Destination dest, Connection con) throws JMSException
+ {
+ this(src, dest, con, false, 100, true);
+ }
+
+ Relay(Destination src, Destination dest, Connection con, boolean echo, int batch, boolean persistent) throws JMSException
+ {
+ _echo = echo;
+ _batch = batch;
+ _con = con;
+ _session = con.createSession(true, AMQSession.NO_ACKNOWLEDGE);
+ _src = _session.createConsumer(src);
+ _dest = _session.createProducer(dest);
+ _dest.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ }
+
+ public void run()
+ {
+ start = System.currentTimeMillis();
+ try{
+ while(true) relay();
+ }
+ catch(JMSException e)
+ {
+ e.printStackTrace();
+ }
+ try
+ {
+ _session.close();
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ void relay() throws JMSException
+ {
+ _dest.send(relay(_src.receive()));
+ _session.commit();
+ }
+
+ Message relay(Message in) throws JMSException
+ {
+ if(!_running)
+ {
+ System.out.println(_con.getClientID() + " started.");
+ _running = true;
+ }
+ if(++_counter % _batch == 0)
+ {
+ long time = System.currentTimeMillis() - start;
+ System.out.println(_batch + " iterations performed in " + time + " ms");
+ try
+ {
+ Thread.sleep(100);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ start = System.currentTimeMillis();
+ }
+ if(_echo)
+ {
+ System.out.println("Received: " + ((TextMessage) in).getText());
+ }
+ return _session.createTextMessage(_con.getClientID() + _counter);
+ }
+
+ void start() throws InterruptedException, JMSException
+ {
+ Thread runner = new Thread(this);
+ runner.start();
+ _con.start();
+ System.out.println(_con.getClientID() + " waiting...");
+ runner.join();
+ _con.close();
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/Start.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Start.java
new file mode 100644
index 0000000000..de718d828a
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Start.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.transacted;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.client.AMQQueue;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Session;
+
+public class Start
+{
+ public static void main(String[] argv) throws Exception
+ {
+ Connection con = new Config(argv).createConnection();
+ AMQQueue ping = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString("ping"));
+ Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ session.createProducer(ping).send(session.createTextMessage("start"));
+ session.close();
+ con.close();
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java
new file mode 100644
index 0000000000..71d806b338
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java
@@ -0,0 +1,151 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.weblogic;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQDestination;
+
+import javax.jms.*;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.naming.Context;
+import java.net.InetAddress;
+import java.util.Hashtable;
+
+public class ServiceProvider
+{
+ private static final String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
+ private static final String JMS_FACTORY = "transientJMSConnectionFactory";
+
+ private static final Logger _logger = Logger.getLogger(ServiceProvider.class);
+
+ private static MessageProducer _destinationProducer;
+
+ private static Queue _destinationQ;
+
+ public static void main(String[] args)
+ {
+ _logger.info("Starting...");
+
+ if (args.length != 2)
+ {
+ System.out.println("Usage: <WLS URI> <service queue>");
+ System.exit(1);
+ }
+ try
+ {
+ String url = args[0];
+ String receiveQueue = args[1];
+
+ final InitialContext ctx = getInitialContext(url);
+
+ QueueConnectionFactory qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
+ QueueConnection qcon = qconFactory.createQueueConnection();
+ final QueueSession qsession = qcon.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
+ Queue receiveQ = (Queue) ctx.lookup(receiveQueue);
+
+ _logger.info("Service (queue) name is '" + receiveQ + "'...");
+
+ String selector = (args.length > 2 && args[2] != null && args[2].length() > 1) ? args[2] : null;
+
+ _logger.info("Message selector is <" + selector + ">...");
+
+ MessageConsumer consumer = qsession.createConsumer(receiveQ, selector);
+
+ consumer.setMessageListener(new MessageListener()
+ {
+ private int _messageCount;
+
+ public void onMessage(javax.jms.Message message)
+ {
+ //_logger.info("Got message '" + message + "'");
+
+ TextMessage tm = (TextMessage) message;
+
+ try
+ {
+ Queue responseQueue = (Queue)tm.getJMSReplyTo();
+ if (!responseQueue.equals(_destinationQ))
+ {
+ _destinationQ = responseQueue;
+ _logger.info("Creating destination for " + responseQueue);
+
+ try
+ {
+ _destinationProducer = qsession.createProducer(_destinationQ);
+ _destinationProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+ }
+ catch (JMSException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ _messageCount++;
+ if (_messageCount % 1000 == 0)
+ {
+ _logger.info("Received message total: " + _messageCount);
+ _logger.info("Sending response to '" + responseQueue + "'");
+ }
+
+ String payload = "This is a response: sing together: 'Mahnah mahnah...'" + tm.getText();
+ TextMessage msg = qsession.createTextMessage(payload);
+ if (tm.propertyExists("timeSent"))
+ {
+ _logger.info("timeSent property set on message");
+ final long timeSent = tm.getLongProperty("timeSent");
+ msg.setLongProperty("timeSent", timeSent);
+ _logger.info("time taken to go from service request to provider is: " + (System.currentTimeMillis() - timeSent));
+ }
+ _destinationProducer.send(msg);
+ if (_messageCount % 1000 == 0)
+ {
+ tm.acknowledge();
+ _logger.info("Sent response to '" + responseQueue + "'");
+ }
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Error sending message: " + e, e);
+ }
+ }
+ });
+ qcon.start();
+ }
+ catch (Throwable t)
+ {
+ System.err.println("Fatal error: " + t);
+ t.printStackTrace();
+ }
+
+
+ System.out.println("Waiting...");
+ }
+
+ private static InitialContext getInitialContext(String url) throws NamingException
+ {
+ Hashtable env = new Hashtable();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
+ env.put(Context.PROVIDER_URL, url);
+ return new InitialContext(env);
+ }
+}
diff --git a/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java
new file mode 100644
index 0000000000..2f64a1dde5
--- /dev/null
+++ b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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 org.apache.qpid.weblogic;
+
+import org.apache.log4j.Logger;
+
+import javax.jms.*;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.util.Hashtable;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: U806869
+ * Date: 28-May-2005
+ * Time: 21:54:51
+ * To change this template use File | Settings | File Templates.
+ */
+public class ServiceRequestingClient
+{
+ private static final Logger _log = Logger.getLogger(ServiceRequestingClient.class);
+ private static final String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
+ private static final String JMS_FACTORY = "transientJMSConnectionFactory";
+
+ private static class CallbackHandler implements MessageListener
+ {
+ private int _expectedMessageCount;
+
+ private int _actualMessageCount;
+
+ private long _startTime;
+
+ private long _averageLatency;
+
+ public CallbackHandler(int expectedMessageCount, long startTime)
+ {
+ _expectedMessageCount = expectedMessageCount;
+ _startTime = startTime;
+ }
+
+ public void onMessage(Message m)
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("Message received: " + m);
+ }
+ try
+ {
+ if (m.propertyExists("timeSent"))
+ {
+ long timeSent = m.getLongProperty("timeSent");
+ long now = System.currentTimeMillis();
+ if (_averageLatency == 0)
+ {
+ _averageLatency = now - timeSent;
+ _log.info("Latency " + _averageLatency);
+ }
+ else
+ {
+ _log.info("Individual latency: " + (now-timeSent));
+ _averageLatency = (_averageLatency + (now - timeSent))/2;
+ _log.info("Average latency now: " + _averageLatency);
+ }
+ }
+ }
+ catch (JMSException e)
+ {
+ _log.error("Could not calculate latency");
+ }
+
+ _actualMessageCount++;
+ if (_actualMessageCount%1000 == 0)
+ {
+ try
+ {
+ m.acknowledge();
+ }
+ catch (JMSException e)
+ {
+ _log.error("Error acknowledging message");
+ }
+ _log.info("Received message count: " + _actualMessageCount);
+ }
+ /*if (!"henson".equals(m.toString()))
+ {
+ _log.error("Message response not correct: expected 'henson' but got " + m.toString());
+ }
+ else
+ {
+ if (_log.isDebugEnabled())
+ {
+ _log.debug("Message " + m + " received");
+ }
+ else
+ {
+ _log.info("Message received");
+ }
+ } */
+
+ if (_actualMessageCount == _expectedMessageCount)
+ {
+ long timeTaken = System.currentTimeMillis() - _startTime;
+ System.out.println("Total time taken to receive " + _expectedMessageCount+ " messages was " +
+ timeTaken + "ms, equivalent to " +
+ (_expectedMessageCount/(timeTaken/1000.0)) + " messages per second");
+ System.out.println("Average latency is: " + _averageLatency);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ if (args.length != 3)
+ {
+ System.out.println("Usage: IXPublisher <WLS URL> <sendQueue> <count> will publish count messages to ");
+ System.out.println("queue sendQueue and waits for a response on a temp queue");
+ System.exit(1);
+ }
+
+ String url = args[0];
+ String sendQueue = args[1];
+ int messageCount = Integer.parseInt(args[2]);
+
+ InitialContext ctx = getInitialContext(url);
+
+ QueueConnectionFactory qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
+ QueueConnection qcon = qconFactory.createQueueConnection();
+ QueueSession qsession = qcon.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
+ Queue sendQ = (Queue) ctx.lookup(sendQueue);
+ Queue receiveQ = qsession.createTemporaryQueue();
+ QueueSender qsender = qsession.createSender(sendQ);
+ qsender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+ _log.debug("Queue sender created for service queue " + sendQ);
+
+ javax.jms.MessageConsumer messageConsumer = (javax.jms.MessageConsumer) qsession.createConsumer(receiveQ);
+
+ //TextMessage msg = _session.createTextMessage(tempDestination.getQueueName() + "/Presented to in conjunction with Mahnah Mahnah and the Snowths");
+ final long startTime = System.currentTimeMillis();
+
+ messageConsumer.setMessageListener(new CallbackHandler(messageCount, startTime));
+ qcon.start();
+ for (int i = 0; i < messageCount; i++)
+ {
+ TextMessage msg = qsession.createTextMessage("/Presented to in conjunction with Mahnah Mahnah and the Snowths:" + i);
+ msg.setJMSReplyTo(receiveQ);
+ if (i%1000 == 0)
+ {
+ long timeNow = System.currentTimeMillis();
+ msg.setLongProperty("timeSent", timeNow);
+ }
+ qsender.send(msg);
+ }
+
+ new Thread("foo").start();
+ //qsession.close();
+ //qcon.close();
+ }
+
+ private static InitialContext getInitialContext(String url) throws NamingException
+ {
+ Hashtable env = new Hashtable();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
+ env.put(Context.PROVIDER_URL, url);
+ return new InitialContext(env);
+ }
+}
diff --git a/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java b/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
new file mode 100644
index 0000000000..5323ad28bf
--- /dev/null
+++ b/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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 org.apache.mina.transport.vmpipe.support;
+
+import org.apache.mina.common.IdleStatus;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This file is a patch to override MINA, because of the IdentityHashMap bug. Workaround to be supplied in MINA 1.0.7.
+ * This patched file will be removed once upgraded onto a newer MINA.
+ *
+ * Dectects idle sessions and fires <tt>sessionIdle</tt> events to them.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class VmPipeIdleStatusChecker
+{
+ private static final VmPipeIdleStatusChecker INSTANCE = new VmPipeIdleStatusChecker();
+
+ public static VmPipeIdleStatusChecker getInstance()
+ {
+ return INSTANCE;
+ }
+
+ private final Map sessions = new HashMap(); // will use as a set
+
+ private final Worker worker = new Worker();
+
+ private VmPipeIdleStatusChecker()
+ {
+ worker.start();
+ }
+
+ public void addSession(VmPipeSessionImpl session)
+ {
+ synchronized (sessions)
+ {
+ sessions.put(session, session);
+ }
+ }
+
+ private class Worker extends Thread
+ {
+ private Worker()
+ {
+ super("VmPipeIdleStatusChecker");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ for (;;)
+ {
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ { }
+
+ long currentTime = System.currentTimeMillis();
+
+ synchronized (sessions)
+ {
+ Iterator it = sessions.keySet().iterator();
+ while (it.hasNext())
+ {
+ VmPipeSessionImpl session = (VmPipeSessionImpl) it.next();
+ if (!session.isConnected())
+ {
+ it.remove();
+ }
+ else
+ {
+ notifyIdleSession(session, currentTime);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyIdleSession(VmPipeSessionImpl session, long currentTime)
+ {
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE,
+ Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE,
+ Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE)));
+ }
+
+ private void notifyIdleSession0(VmPipeSessionImpl session, long currentTime, long idleTime, IdleStatus status,
+ long lastIoTime)
+ {
+ if ((idleTime > 0) && (lastIoTime != 0) && ((currentTime - lastIoTime) >= idleTime))
+ {
+ session.increaseIdleCount(status);
+ session.getFilterChain().fireSessionIdle(session, status);
+ }
+ }
+
+}
diff --git a/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java b/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java
deleted file mode 100644
index 849827216c..0000000000
--- a/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java
+++ /dev/null
@@ -1,765 +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.
- */
-package org.apache.qpid.client;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.transport.Binary;
-import org.apache.qpid.transport.Connection;
-import org.apache.qpid.transport.Connection.SessionFactory;
-import org.apache.qpid.transport.Connection.State;
-import org.apache.qpid.transport.ExchangeBound;
-import org.apache.qpid.transport.ExchangeBoundResult;
-import org.apache.qpid.transport.ExchangeDeclare;
-import org.apache.qpid.transport.ExchangeDelete;
-import org.apache.qpid.transport.ExchangeQuery;
-import org.apache.qpid.transport.ExchangeQueryResult;
-import org.apache.qpid.transport.ExecutionErrorCode;
-import org.apache.qpid.transport.ExecutionException;
-import org.apache.qpid.transport.ExecutionResult;
-import org.apache.qpid.transport.ExecutionSync;
-import org.apache.qpid.transport.Future;
-import org.apache.qpid.transport.MessageCancel;
-import org.apache.qpid.transport.MessageFlow;
-import org.apache.qpid.transport.MessageRelease;
-import org.apache.qpid.transport.MessageSubscribe;
-import org.apache.qpid.transport.MessageTransfer;
-import org.apache.qpid.transport.Method;
-import org.apache.qpid.transport.Option;
-import org.apache.qpid.transport.ProtocolEvent;
-import org.apache.qpid.transport.QueueDelete;
-import org.apache.qpid.transport.QueueQuery;
-import org.apache.qpid.transport.QueueQueryResult;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.Session;
-import org.apache.qpid.transport.SessionAttach;
-import org.apache.qpid.transport.SessionDelegate;
-import org.apache.qpid.transport.SessionDetach;
-import org.apache.qpid.transport.SessionException;
-import org.apache.qpid.transport.SessionRequestTimeout;
-import org.apache.qpid.transport.TxCommit;
-import org.apache.qpid.transport.TxRollback;
-import org.apache.qpid.transport.TxSelect;
-
-/**
- * Tests AMQSession_0_10 methods.
- * <p>
- * The main purpose of the tests in this test suite is to check that
- * {@link SessionException} is not thrown from methods of
- * {@link AMQSession_0_10}.
- */
-public class AMQSession_0_10Test extends TestCase
-{
-
- public void testExceptionOnCommit()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- session.commit();
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnCreateMessageProducer()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- session.createMessageProducer(createDestination(), true, true, 1l);
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected but got:" + e, e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnRollback()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- session.rollback();
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- }
- }
-
- public void testExceptionOnRecover()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10(javax.jms.Session.AUTO_ACKNOWLEDGE);
- try
- {
- session.recover();
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- }
- }
-
- public void testExceptionOnCreateBrowser()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- AMQQueue destination = createQueue();
- try
- {
- session.createBrowser(destination);
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnCreateConsumer()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- AMQAnyDestination destination = createDestination();
- try
- {
- session.createConsumer(destination);
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnCreateSubscriber()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- AMQAnyDestination destination = createDestination();
- try
- {
- session.createSubscriber(destination);
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnUnsubscribe()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- session.unsubscribe("whatever");
- fail("JMSExceptiuon should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testCommit()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.commit();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, TxCommit.class, false);
- assertNotNull("TxCommit was not sent", event);
- }
-
- public void testRollback()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.rollback();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, TxRollback.class, false);
- assertNotNull("TxRollback was not sent", event);
- }
-
- public void testRecover()
- {
- AMQSession_0_10 session = createAMQSession_0_10(javax.jms.Session.AUTO_ACKNOWLEDGE);
- try
- {
- session.recover();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageRelease.class, false);
- assertNotNull("MessageRelease was not sent", event);
- }
-
- public void testCreateProducer()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.createProducer(createQueue());
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, ExchangeDeclare.class, false);
- assertNotNull("ExchangeDeclare was not sent", event);
- }
-
- public void testCreateConsumer()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.createConsumer(createQueue());
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageSubscribe.class, false);
- assertNotNull("MessageSubscribe was not sent", event);
- }
-
- public void testSync()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.sync();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, ExecutionSync.class, false);
- assertNotNull("ExecutionSync was not sent", event);
- }
-
- public void testRejectMessage()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- session.rejectMessage(1l, true);
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageRelease.class, false);
- assertNotNull("MessageRelease event was not sent", event);
- }
-
- public void testReleaseForRollback()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.releaseForRollback();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageRelease.class, false);
- assertNotNull("MessageRelease event was not sent", event);
- }
-
- public void testSendQueueDelete()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.sendQueueDelete(new AMQShortString("test"));
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, QueueDelete.class, false);
- assertNotNull("QueueDelete event was not sent", event);
- QueueDelete exchangeDelete = (QueueDelete) event;
- assertEquals("test", exchangeDelete.getQueue());
- }
-
- public void testSendConsume()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- session.sendConsume(consumer, new AMQShortString("test"), null, true, null, 1);
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageSubscribe.class, false);
- assertNotNull("MessageSubscribe event was not sent", event);
- }
-
- public void testCreateMessageProducer()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.createMessageProducer(createDestination(), true, true, 1l);
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, ExchangeDeclare.class, false);
- assertNotNull("ExchangeDeclare event was not sent", event);
- }
-
- public void testSendExchangeDelete()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- session.sendExchangeDelete("test", true);
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, ExchangeDelete.class, false);
- assertNotNull("ExchangeDelete event was not sent", event);
- ExchangeDelete exchangeDelete = (ExchangeDelete) event;
- assertEquals("test", exchangeDelete.getExchange());
- }
-
- public void testExceptionOnMessageConsumerReceive()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- session.start();
- consumer.receive(1);
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testMessageConsumerReceive()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- session.start();
- consumer.receive(1);
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageFlow.class, false);
- assertNotNull("MessageFlow event was not sent", event);
- }
-
- public void testExceptionOnMessageConsumerReceiveNoWait()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- session.start();
- consumer.receiveNoWait();
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testExceptionOnMessageConsumerSetMessageListener()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- consumer.setMessageListener(new MockMessageListener());
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testMessageConsumerSetMessageListener()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- consumer.setMessageListener(new MockMessageListener());
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageFlow.class, false);
- assertNotNull("MessageFlow event was not sent", event);
- }
-
- public void testMessageConsumerClose()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- consumer.close();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageCancel.class, false);
- assertNotNull("MessageCancel event was not sent", event);
- }
-
- public void testExceptionOnMessageConsumerClose()
- {
- AMQSession_0_10 session = createThrowingExceptionAMQSession_0_10();
- try
- {
- BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false,
- null, new FieldTable(), false, true);
- consumer.close();
- fail("JMSException should be thrown");
- }
- catch (Exception e)
- {
- assertTrue("JMSException is expected", e instanceof JMSException);
- assertEquals("541 error code is expected", "541", ((JMSException) e).getErrorCode());
- }
- }
-
- public void testMessageProducerSend()
- {
- AMQSession_0_10 session = createAMQSession_0_10();
- try
- {
- MessageProducer producer = session.createProducer(createQueue());
- producer.send(session.createTextMessage("Test"));
- session.commit();
- }
- catch (Exception e)
- {
- fail("Unexpected exception is cought:" + e.getMessage());
- }
- ProtocolEvent event = findSentProtocolEventOfClass(session, MessageTransfer.class, false);
- assertNotNull("MessageTransfer event was not sent", event);
- event = findSentProtocolEventOfClass(session, ExchangeDeclare.class, false);
- assertNotNull("ExchangeDeclare event was not sent", event);
- }
-
- private AMQAnyDestination createDestination()
- {
- AMQAnyDestination destination = null;
- try
- {
- destination = new AMQAnyDestination(new AMQShortString("amq.direct"), new AMQShortString("direct"),
- new AMQShortString("test"), false, true, new AMQShortString("test"), true, null);
- }
- catch (Exception e)
- {
- fail("Failued to create destination:" + e.getMessage());
- }
- return destination;
- }
-
- private AMQQueue createQueue()
- {
- AMQQueue destination = null;
- try
- {
- destination = new AMQQueue(new AMQShortString("amq.direct"), new AMQShortString("test"),
- new AMQShortString("test"));
- }
- catch (Exception e)
- {
- fail("Failued to create destination:" + e.getMessage());
- }
- return destination;
- }
-
- private AMQSession_0_10 createThrowingExceptionAMQSession_0_10()
- {
- return createAMQSession_0_10(true, javax.jms.Session.SESSION_TRANSACTED);
- }
-
- private AMQSession_0_10 createThrowingExceptionAMQSession_0_10(int akcnowledgeMode)
- {
- return createAMQSession_0_10(true, akcnowledgeMode);
- }
-
- private ProtocolEvent findSentProtocolEventOfClass(AMQSession_0_10 session, Class<? extends ProtocolEvent> class1,
- boolean isLast)
- {
- ProtocolEvent found = null;
- List<ProtocolEvent> events = ((MockSession) session.getQpidSession()).getSender().getSendEvents();
- assertNotNull("Events list should not be null", events);
- assertFalse("Events list should not be empty", events.isEmpty());
- if (isLast)
- {
- ProtocolEvent event = events.get(events.size() - 1);
- if (event.getClass().isAssignableFrom(class1))
- {
- found = event;
- }
- }
- else
- {
- for (ProtocolEvent protocolEvent : events)
- {
- if (protocolEvent.getClass().isAssignableFrom(class1))
- {
- found = protocolEvent;
- break;
- }
- }
-
- }
- return found;
- }
-
- private AMQSession_0_10 createAMQSession_0_10()
- {
- return createAMQSession_0_10(false, javax.jms.Session.SESSION_TRANSACTED);
- }
-
- private AMQSession_0_10 createAMQSession_0_10(int acknowledgeMode)
- {
- return createAMQSession_0_10(false, acknowledgeMode);
- }
-
- private AMQSession_0_10 createAMQSession_0_10(boolean throwException, int acknowledgeMode)
- {
- AMQConnection amqConnection = null;
- try
- {
- amqConnection = new MockAMQConnection(
- "amqp://guest:guest@client/test?brokerlist='tcp://localhost:1'&maxprefetch='0'");
- }
- catch (Exception e)
- {
- fail("Failure to create a mock connection:" + e.getMessage());
- }
- boolean isTransacted = acknowledgeMode == javax.jms.Session.SESSION_TRANSACTED ? true : false;
- AMQSession_0_10 session = new AMQSession_0_10(createConnection(throwException), amqConnection, 1, isTransacted, acknowledgeMode,
- 1, 1, "test");
- return session;
- }
-
- private Connection createConnection(final boolean throwException)
- {
- MockTransportConnection connection = new MockTransportConnection();
- connection.setState(State.OPEN);
- connection.setSender(new MockSender());
- connection.setSessionFactory(new SessionFactory()
- {
-
- @Override
- public Session newSession(Connection conn, Binary name, long expiry)
- {
- return new MockSession(conn, new SessionDelegate(), name, expiry, throwException);
- }
- });
- return connection;
- }
-
- private final class MockMessageListener implements MessageListener
- {
- @Override
- public void onMessage(Message arg0)
- {
- }
- }
-
- class MockSession extends Session
- {
- private final boolean _throwException;
- private final Connection _connection;
- private final SessionDelegate _delegate;
-
- protected MockSession(Connection connection, SessionDelegate delegate, Binary name, long expiry,
- boolean throwException)
- {
- super(connection, delegate, name, expiry);
- _throwException = throwException;
- setState(State.OPEN);
- _connection = connection;
- _delegate = delegate;
- }
-
- public void invoke(Method m, Runnable postIdSettingAction)
- {
- if (_throwException)
- {
- if (m instanceof SessionAttach || m instanceof SessionRequestTimeout || m instanceof TxSelect)
- {
- // do not throw exception for SessionAttach,
- // SessionRequestTimeout and TxSelect
- // session needs to be instantiated
- return;
- }
- ExecutionException e = new ExecutionException();
- e.setErrorCode(ExecutionErrorCode.INTERNAL_ERROR);
- throw new SessionException(e);
- }
- else
- {
- super.invoke(m, postIdSettingAction);
- if (m instanceof SessionDetach)
- {
- setState(State.CLOSED);
- }
- }
- }
-
- public void sync()
- {
- // to avoid recursive calls
- setAutoSync(false);
- // simply send sync command
- super.executionSync(Option.SYNC);
- }
-
- protected <T> Future<T> invoke(Method m, Class<T> klass)
- {
- int commandId = getCommandsOut();
- Future<T> future = super.invoke(m, klass);
- ExecutionResult result = new ExecutionResult();
- result.setCommandId(commandId);
- if (m instanceof ExchangeBound)
- {
- ExchangeBoundResult struc = new ExchangeBoundResult();
- struc.setQueueNotFound(true);
- result.setValue(struc);
- }
- else if (m instanceof ExchangeQuery)
- {
- ExchangeQueryResult struc = new ExchangeQueryResult();
- result.setValue(struc);
- }
- else if (m instanceof QueueQuery)
- {
- QueueQueryResult struc = new QueueQueryResult();
- result.setValue(struc);
- }
- _delegate.executionResult(this, result);
- return future;
- }
-
- public MockSender getSender()
- {
- return (MockSender) _connection.getSender();
- }
- }
-
- class MockTransportConnection extends Connection
- {
- public void setState(State state)
- {
- super.setState(state);
- }
- }
-
- class MockSender implements Sender<ProtocolEvent>
- {
- private List<ProtocolEvent> _sendEvents = new ArrayList<ProtocolEvent>();
-
- @Override
- public void setIdleTimeout(int i)
- {
- }
-
- @Override
- public void send(ProtocolEvent msg)
- {
- _sendEvents.add(msg);
- }
-
- @Override
- public void flush()
- {
- }
-
- @Override
- public void close()
- {
- }
-
- public List<ProtocolEvent> getSendEvents()
- {
- return _sendEvents;
- }
-
- }
-
-}
diff --git a/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java b/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
index 73e67469ae..da44822ec3 100644
--- a/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
+++ b/java/client/src/test/java/org/apache/qpid/client/MockAMQConnection.java
@@ -23,6 +23,7 @@ package org.apache.qpid.client;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.url.URLSyntaxException;
@@ -36,18 +37,53 @@ public class MockAMQConnection extends AMQConnection
super(broker, username, password, clientName, virtualHost);
}
+ public MockAMQConnection(String broker, String username, String password, String clientName, String virtualHost, SSLConfiguration sslConfig)
+ throws AMQException, URLSyntaxException
+ {
+ super(broker, username, password, clientName, virtualHost, sslConfig);
+ }
+
public MockAMQConnection(String host, int port, String username, String password, String clientName, String virtualHost)
throws AMQException, URLSyntaxException
{
super(host, port, username, password, clientName, virtualHost);
}
+ public MockAMQConnection(String host, int port, String username, String password, String clientName, String virtualHost, SSLConfiguration sslConfig)
+ throws AMQException, URLSyntaxException
+ {
+ super(host, port, username, password, clientName, virtualHost, sslConfig);
+ }
+
+ public MockAMQConnection(String host, int port, boolean useSSL, String username, String password, String clientName, String virtualHost, SSLConfiguration sslConfig)
+ throws AMQException, URLSyntaxException
+ {
+ super(host, port, useSSL, username, password, clientName, virtualHost, sslConfig);
+ }
+
public MockAMQConnection(String connection)
throws AMQException, URLSyntaxException
{
super(connection);
}
+ public MockAMQConnection(String connection, SSLConfiguration sslConfig)
+ throws AMQException, URLSyntaxException
+ {
+ super(connection, sslConfig);
+ }
+
+ public MockAMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig)
+ throws AMQException
+ {
+ super(connectionURL, sslConfig);
+ }
+
+ protected MockAMQConnection(String username, String password, String clientName, String virtualHost)
+ {
+ super(username, password, clientName, virtualHost);
+ }
+
@Override
public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException
{
diff --git a/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java b/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
index b5c31e7c5e..7ee991b63c 100644
--- a/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
+++ b/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
@@ -43,9 +43,4 @@ public class TestMessageHelper
{
return new JMSStreamMessage(AMQMessageDelegateFactory.FACTORY_0_8);
}
-
- public static JMSObjectMessage newJMSObjectMessage()
- {
- return new JMSObjectMessage(AMQMessageDelegateFactory.FACTORY_0_8);
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java b/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
index e159ceb148..f520a21ba0 100644
--- a/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
+++ b/java/client/src/test/java/org/apache/qpid/client/protocol/AMQProtocolHandlerTest.java
@@ -20,24 +20,23 @@
*/
package org.apache.qpid.client.protocol;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
import junit.framework.TestCase;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQAuthenticationException;
-import org.apache.qpid.client.MockAMQConnection;
-import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.framing.AMQBody;
import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQBody;
import org.apache.qpid.framing.AMQMethodBody;
import org.apache.qpid.framing.amqp_8_0.BasicRecoverOkBodyImpl;
+import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.transport.TestNetworkConnection;
+import org.apache.qpid.transport.TestNetworkDriver;
+import org.apache.qpid.client.MockAMQConnection;
+import org.apache.qpid.client.AMQAuthenticationException;
+import org.apache.qpid.client.state.AMQState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* This is a test address QPID-1431 where frame listeners would fail to be notified of an incomming exception.
*
@@ -73,8 +72,8 @@ public class AMQProtocolHandlerTest extends TestCase
public void setUp() throws Exception
{
//Create a new ProtocolHandler with a fake connection.
- _handler = new AMQProtocolHandler(new MockAMQConnection("amqp://guest:guest@client/test?brokerlist='tcp://localhost:1'"));
- _handler.setNetworkConnection(new TestNetworkConnection());
+ _handler = new AMQProtocolHandler(new MockAMQConnection("amqp://guest:guest@client/test?brokerlist='vm://:1'"));
+ _handler.setNetworkDriver(new TestNetworkDriver());
AMQBody body = BasicRecoverOkBodyImpl.getFactory().newInstance(null, 1);
_blockFrame = new AMQFrame(0, body);
diff --git a/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java b/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
new file mode 100644
index 0000000000..f0938a4bc0
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/client/protocol/MockIoSession.java
@@ -0,0 +1,312 @@
+/*
+ *
+ * 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 org.apache.qpid.client.protocol;
+
+import org.apache.mina.common.*;
+import org.apache.mina.common.support.DefaultCloseFuture;
+import org.apache.mina.common.support.DefaultWriteFuture;
+import org.apache.mina.common.support.AbstractIoFilterChain;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.util.Set;
+
+public class MockIoSession implements IoSession
+{
+ private AMQProtocolSession _protocolSession;
+
+ /**
+ * Stores the last response written
+ */
+ private Object _lastWrittenObject;
+
+ private boolean _closing;
+ private IoFilterChain _filterChain;
+
+ public MockIoSession()
+ {
+ _filterChain = new AbstractIoFilterChain(this)
+ {
+ protected void doWrite(IoSession ioSession, IoFilter.WriteRequest writeRequest) throws Exception
+ {
+
+ }
+
+ protected void doClose(IoSession ioSession) throws Exception
+ {
+
+ }
+ };
+ }
+
+ public Object getLastWrittenObject()
+ {
+ return _lastWrittenObject;
+ }
+
+ public IoService getService()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoServiceConfig getServiceConfig()
+ {
+ return null;
+ }
+
+ public IoHandler getHandler()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoSessionConfig getConfig()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public IoFilterChain getFilterChain()
+ {
+ return _filterChain;
+ }
+
+ public WriteFuture write(Object message)
+ {
+ WriteFuture wf = new DefaultWriteFuture(null);
+ _lastWrittenObject = message;
+ return wf;
+ }
+
+ public CloseFuture close()
+ {
+ _closing = true;
+ CloseFuture cf = new DefaultCloseFuture(null);
+ cf.setClosed();
+ return cf;
+ }
+
+ public Object getAttachment()
+ {
+ return _protocolSession;
+ }
+
+ public Object setAttachment(Object attachment)
+ {
+ Object current = _protocolSession;
+ _protocolSession = (AMQProtocolSession) attachment;
+ return current;
+ }
+
+ public Object getAttribute(String key)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Object setAttribute(String key, Object value)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Object setAttribute(String key)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Object removeAttribute(String key)
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean containsAttribute(String key)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Set getAttributeKeys()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public TransportType getTransportType()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isConnected()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isClosing()
+ {
+ return _closing;
+ }
+
+ public CloseFuture getCloseFuture()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return new InetSocketAddress("127.0.0.1", 1234); //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public SocketAddress getServiceAddress()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getIdleTime(IdleStatus status)
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getIdleTimeInMillis(IdleStatus status)
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setIdleTime(IdleStatus status, int idleTime)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getWriteTimeout()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getWriteTimeoutInMillis()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setWriteTimeout(int writeTimeout)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public TrafficMask getTrafficMask()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setTrafficMask(TrafficMask trafficMask)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void suspendRead()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void suspendWrite()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void resumeRead()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void resumeWrite()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getReadBytes()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getWrittenBytes()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getReadMessages()
+ {
+ return 0L;
+ }
+
+ public long getWrittenMessages()
+ {
+ return 0L;
+ }
+
+ public long getWrittenWriteRequests()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getScheduledWriteRequests()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getScheduledWriteBytes()
+ {
+ return 0; //TODO
+ }
+
+ public long getCreationTime()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getLastIoTime()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getLastReadTime()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getLastWriteTime()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isIdle(IdleStatus status)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int getIdleCount(IdleStatus status)
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getLastIdleTime(IdleStatus status)
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/client/security/CallbackHandlerRegistryTest.java b/java/client/src/test/java/org/apache/qpid/client/security/CallbackHandlerRegistryTest.java
deleted file mode 100644
index cc5d48fbef..0000000000
--- a/java/client/src/test/java/org/apache/qpid/client/security/CallbackHandlerRegistryTest.java
+++ /dev/null
@@ -1,185 +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.
- *
- */
-package org.apache.qpid.client.security;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-
-/**
- * Tests the ability of {@link CallbackHandlerRegistry} to correctly parse
- * the properties describing the available callback handlers. Ensures also
- * that it is able to select the mechanism and create an implementation
- * given a variety of starting conditions.
- *
- */
-public class CallbackHandlerRegistryTest extends QpidTestCase
-{
- private CallbackHandlerRegistry _registry; // Object under test
-
- public void testCreateHandlerSuccess()
- {
- final Properties props = new Properties();
- props.put("TESTA.1", TestACallbackHandler.class.getName());
-
- _registry = new CallbackHandlerRegistry(props);
- assertEquals(1,_registry.getMechanisms().size());
-
- final CallbackHandler handler = _registry.createCallbackHandler("TESTA");
- assertTrue(handler instanceof TestACallbackHandler);
- }
-
- public void testCreateHandlerForUnknownMechanismName()
- {
- final Properties props = new Properties();
- props.put("TEST1.1", TestACallbackHandler.class.getName());
-
- _registry = new CallbackHandlerRegistry(props);
-
- try
- {
- _registry.createCallbackHandler("NOTFOUND");
- fail("Exception not thrown");
- }
- catch (IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
- public void testSelectMechanism()
- {
- final Properties props = new Properties();
- props.put("TESTA.1", TestACallbackHandler.class.getName());
- props.put("TESTB.2", TestBCallbackHandler.class.getName());
-
- _registry = new CallbackHandlerRegistry(props);
- assertEquals(2,_registry.getMechanisms().size());
-
- final String selectedMechanism = _registry.selectMechanism("TESTA");
- assertEquals("TESTA", selectedMechanism);
- }
-
- public void testSelectReturnsFirstMutallyAvailableMechanism()
- {
- final Properties props = new Properties();
- props.put("TESTA.1", TestACallbackHandler.class.getName());
- props.put("TESTB.2", TestBCallbackHandler.class.getName());
-
- _registry = new CallbackHandlerRegistry(props);
-
- final String selectedMechanism = _registry.selectMechanism("TESTD TESTB TESTA");
- // TESTA should be returned as it is higher than TESTB in the properties file.
- assertEquals("Selected mechanism should respect the ordinal", "TESTA", selectedMechanism);
- }
-
- public void testRestrictedSelectReturnsMechanismFromRestrictedList()
- {
- final Properties props = new Properties();
- props.put("TESTA.1", TestACallbackHandler.class.getName());
- props.put("TESTB.2", TestBCallbackHandler.class.getName());
- props.put("TESTC.3", TestCCallbackHandler.class.getName());
-
- _registry = new CallbackHandlerRegistry(props);
-
- final String selectedMechanism = _registry.selectMechanism("TESTC TESTB TESTA", "TESTB TESTC");
- // TESTB should be returned as client has restricted the mechanism list to TESTB and TESTC
- assertEquals("Selected mechanism should respect the ordinal and be limitted by restricted list","TESTB", selectedMechanism);
- }
-
- public void testOldPropertyFormatRejected()
- {
- final Properties props = new Properties();
- props.put("CallbackHandler.TESTA", TestACallbackHandler.class.getName());
-
- try
- {
- new CallbackHandlerRegistry(props);
- fail("exception not thrown");
- }
- catch(IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
- public void testPropertyWithNonnumericalOrdinal()
- {
- final Properties props = new Properties();
- props.put("TESTA.z", TestACallbackHandler.class.getName());
- try
- {
- new CallbackHandlerRegistry(props);
- fail("exception not thrown");
- }
- catch(IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
- public void testUnexpectedCallbackImplementationsIgnored()
- {
- final Properties props = new Properties();
- props.put("TESTA.1", TestACallbackHandler.class.getName());
- props.put("TESTB.2", "NotFound");
- props.put("TESTC.3", "java.lang.String");
-
- _registry = new CallbackHandlerRegistry(props);
-
- assertEquals(1,_registry.getMechanisms().size());
- }
-
- static class TestACallbackHandler extends TestCallbackHandler
- {
- }
-
- static class TestBCallbackHandler extends TestCallbackHandler
- {
- }
-
- static class TestCCallbackHandler extends TestCallbackHandler
- {
- }
-
- static abstract class TestCallbackHandler implements AMQCallbackHandler
- {
- @Override
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void initialise(ConnectionURL connectionURL)
- {
- throw new UnsupportedOperationException();
- }
- }
-
-}
diff --git a/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java b/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java
deleted file mode 100644
index 9e23f722eb..0000000000
--- a/java/client/src/test/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandlerTest.java
+++ /dev/null
@@ -1,99 +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.
- *
- */
-package org.apache.qpid.client.security;
-
-import java.security.MessageDigest;
-import java.util.Arrays;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.client.MockAMQConnection;
-import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
-
-/**
- * Unit tests for the UsernameHashPasswordCallbackHandler. This callback handler is
- * used by the CRAM-MD5-HASHED SASL mechanism.
- *
- */
-public class UsernameHashedPasswordCallbackHandlerTest extends TestCase
-{
- private AMQCallbackHandler _callbackHandler = new UsernameHashedPasswordCallbackHandler(); // Class under test
- private static final String PROMPT_UNUSED = "unused";
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
-
- final String url = "amqp://username:password@client/test?brokerlist='tcp://localhost:1'";
- _callbackHandler.initialise(new AMQConnectionURL(url));
- }
-
- /**
- * Tests that the callback handler can correctly retrieve the username from the connection url.
- */
- public void testNameCallback() throws Exception
- {
- final String expectedName = "username";
- NameCallback nameCallback = new NameCallback(PROMPT_UNUSED);
-
- assertNull("Unexpected name before test", nameCallback.getName());
- _callbackHandler.handle(new Callback[] {nameCallback});
- assertEquals("Unexpected name", expectedName, nameCallback.getName());
- }
-
- /**
- * Tests that the callback handler can correctly retrieve the password from the connection url
- * and calculate a MD5.
- */
- public void testDigestedPasswordCallback() throws Exception
- {
- final char[] expectedPasswordDigested = getHashPassword("password");
-
- PasswordCallback passwordCallback = new PasswordCallback(PROMPT_UNUSED, false);
- assertNull("Unexpected password before test", passwordCallback.getPassword());
- _callbackHandler.handle(new Callback[] {passwordCallback});
- assertTrue("Unexpected password", Arrays.equals(expectedPasswordDigested, passwordCallback.getPassword()));
- }
-
- private char[] getHashPassword(final String password) throws Exception
- {
- MessageDigest md5Digester = MessageDigest.getInstance("MD5");
- final byte[] digest = md5Digester.digest(password.getBytes("UTF-8"));
-
- char[] hash = new char[digest.length];
-
- int index = 0;
- for (byte b : digest)
- {
- hash[index++] = (char) b;
- }
-
- return hash;
- }
-}
diff --git a/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java b/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java
deleted file mode 100644
index 83ddfd72fa..0000000000
--- a/java/client/src/test/java/org/apache/qpid/client/security/UsernamePasswordCallbackHandlerTest.java
+++ /dev/null
@@ -1,78 +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.
- *
- */
-package org.apache.qpid.client.security;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.client.MockAMQConnection;
-import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
-
-/**
- * Unit tests for the UsernamePasswordCallbackHandler.
- *
- */
-public class UsernamePasswordCallbackHandlerTest extends TestCase
-{
- private AMQCallbackHandler _callbackHandler = new UsernamePasswordCallbackHandler(); // Class under test
- private static final String PROMPT_UNUSED = "unused";
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
-
- final String url = "amqp://username:password@client/test?brokerlist='tcp://localhost:1'";
-
- _callbackHandler.initialise(new AMQConnectionURL(url));
- }
-
- /**
- * Tests that the callback handler can correctly retrieve the username from the connection url.
- */
- public void testNameCallback() throws Exception
- {
- final String expectedName = "username";
- NameCallback nameCallback = new NameCallback(PROMPT_UNUSED);
-
- assertNull("Unexpected name before test", nameCallback.getName());
- _callbackHandler.handle(new Callback[] {nameCallback});
- assertEquals("Unexpected name", expectedName, nameCallback.getName());
- }
-
- /**
- * Tests that the callback handler can correctly retrieve the password from the connection url.
- */
- public void testPasswordCallback() throws Exception
- {
- final String expectedPassword = "password";
- PasswordCallback passwordCallback = new PasswordCallback(PROMPT_UNUSED, false);
- assertNull("Unexpected password before test", passwordCallback.getPassword());
- _callbackHandler.handle(new Callback[] {passwordCallback});
- assertEquals("Unexpected password", expectedPassword, new String(passwordCallback.getPassword()));
- }
-}
diff --git a/java/client/src/test/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStreamTest.java b/java/client/src/test/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStreamTest.java
deleted file mode 100644
index a12e4ce977..0000000000
--- a/java/client/src/test/java/org/apache/qpid/client/util/ClassLoadingAwareObjectInputStreamTest.java
+++ /dev/null
@@ -1,86 +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.
- *
- */
-package org.apache.qpid.client.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.ObjectOutputStream;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class ClassLoadingAwareObjectInputStreamTest extends QpidTestCase
-{
- InputStream _in;
- ClassLoadingAwareObjectInputStream _claOIS;
-
- protected void setUp() throws Exception
- {
- //Create a viable input stream for instantiating the CLA OIS
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- ObjectOutputStream out = new ObjectOutputStream(baos);
- out.writeObject("testString");
- out.flush();
- out.close();
-
-
- _in = new ByteArrayInputStream(baos.toByteArray());
-
- _claOIS = new ClassLoadingAwareObjectInputStream(_in);
- }
-
- /**
- * Test that the resolveProxyClass method returns a proxy class implementing the desired interface
- */
- public void testResolveProxyClass() throws Exception
- {
- //try to proxy an interface
- Class<?> clazz = _claOIS.resolveProxyClass(new String[]{"java.lang.CharSequence"});
-
- //verify the proxy supports the expected interface (only)
- List<Class<?>> interfaces = Arrays.asList(clazz.getInterfaces());
- assertTrue("Unexpected interfaces supported by proxy", interfaces.contains(CharSequence.class));
- assertEquals("Unexpected interfaces supported by proxy", 1, interfaces.size());
- }
-
- /**
- * Test that the resolveProxyClass method throws a ClassNotFoundException wrapping an
- * IllegalArgumentException if it is provided arguments which violate the restrictions allowed
- * by Proxy.getProxyClass (as required by the ObjectInputStream.resolveProxyClass javadoc).
- */
- public void testResolveProxyClassThrowsCNFEWrappingIAE() throws Exception
- {
- try
- {
- //try to proxy a *class* rather than an interface, which is illegal
- _claOIS.resolveProxyClass(new String[]{"java.lang.String"});
- fail("should have thrown an exception");
- }
- catch(ClassNotFoundException cnfe)
- {
- //expected, but must verify it is wrapping an IllegalArgumentException
- assertTrue(cnfe.getCause() instanceof IllegalArgumentException);
- }
- }
-}
diff --git a/java/client/src/test/java/org/apache/qpid/jms/FailoverPolicyTest.java b/java/client/src/test/java/org/apache/qpid/jms/FailoverPolicyTest.java
deleted file mode 100644
index 438995aedc..0000000000
--- a/java/client/src/test/java/org/apache/qpid/jms/FailoverPolicyTest.java
+++ /dev/null
@@ -1,338 +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.
- *
- */
-package org.apache.qpid.jms;
-
-import javax.jms.ConnectionConsumer;
-import javax.jms.ConnectionMetaData;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.ServerSessionPool;
-import javax.jms.Topic;
-
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.jms.failover.FailoverExchangeMethod;
-import org.apache.qpid.jms.failover.FailoverMethod;
-import org.apache.qpid.jms.failover.FailoverRoundRobinServers;
-import org.apache.qpid.jms.failover.FailoverSingleServer;
-import org.apache.qpid.jms.failover.NoFailover;
-
-import junit.framework.TestCase;
-
-/**
- * Tests the ability of FailoverPolicy to instantiate the correct FailoverMethod.
- *
- * This test presently does <i>not</i> test {@link FailoverPolicy#FailoverPolicy(FailoverMethod) or
- * {@link FailoverPolicy#addMethod(FailoverMethod)} as it appears that this functionality
- * is no longer in use.
- *
- */
-public class FailoverPolicyTest extends TestCase
-{
- private FailoverPolicy _failoverPolicy = null; // class under test
- private String _url;
- private Connection _connection = null;
- private ConnectionURL _connectionUrl = null;
-
- /**
- * Tests single server method is selected for a brokerlist with one broker when
- * the failover option is not specified.
- */
- public void testBrokerListWithOneBrokerDefaultsToSingleServerPolicy() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof FailoverSingleServer);
- }
-
- /**
- * Tests round robin method is selected for a brokerlist with two brokers when
- * the failover option is not specified.
- */
- public void testBrokerListWithTwoBrokersDefaultsToRoundRobinPolicy() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672;tcp://localhost:5673'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof FailoverRoundRobinServers);
- }
-
- /**
- * Tests single server method is selected for a brokerlist with one broker when
- * the failover option passed as 'singlebroker'.
- */
- public void testExplictFailoverOptionSingleBroker() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'&failover='singlebroker'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof FailoverSingleServer);
- }
-
- /**
- * Tests round robin method is selected for a brokerlist with two brokers when
- * the failover option passed as 'roundrobin'.
- */
- public void testExplictFailoverOptionRoundrobin() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672;tcp://localhost:5673'&failover='roundrobin'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof FailoverRoundRobinServers);
- }
-
- /**
- * Tests no failover method is selected for a brokerlist with one broker when
- * the failover option passed as 'nofailover'.
- */
- public void testExplictFailoverOptionNofailover() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'&failover='nofailover'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof NoFailover);
- }
-
- /**
- * Tests failover exchange method is selected for a brokerlist with one broker when
- * the failover option passed as 'failover_exchange'.
- */
- public void testExplictFailoverOptionFailoverExchange() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'&failover='failover_exchange'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof FailoverExchangeMethod);
- }
-
- /**
- * Tests that a custom method can be selected for a brokerlist with one brokers when
- * the failover option passed as a qualified class-name.
- */
- public void testExplictFailoverOptionDynamicallyLoadedFailoverMethod() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'&failover='org.apache.qpid.jms.FailoverPolicyTest$MyFailoverMethod'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- _failoverPolicy = new FailoverPolicy(_connectionUrl, _connection);
-
- assertTrue("Unexpected failover method", _failoverPolicy.getCurrentMethod() instanceof MyFailoverMethod);
- }
-
- /**
- * Tests that an unknown method caused an exception.
- */
- public void testUnknownFailoverMethod() throws Exception
- {
- _url = "amqp://user:pass@clientid/test?brokerlist='tcp://localhost:5672'&failover='unknown'";
- _connectionUrl = new AMQConnectionURL(_url);
- _connection = createStubConnection();
-
- try
- {
- new FailoverPolicy(_connectionUrl, _connection);
- fail("Exception not thrown");
- }
- catch(IllegalArgumentException iae)
- {
- // PASS
- }
- }
-
- private Connection createStubConnection()
- {
- return new Connection()
- {
-
- @Override
- public Session createSession(boolean transacted,
- int acknowledgeMode, int prefetch) throws JMSException
- {
- return null;
- }
-
- @Override
- public Session createSession(boolean transacted,
- int acknowledgeMode, int prefetchHigh, int prefetchLow)
- throws JMSException
- {
- return null;
- }
-
- @Override
- public ConnectionListener getConnectionListener()
- {
- return null;
- }
-
- @Override
- public long getMaximumChannelCount() throws JMSException
- {
- return 0;
- }
-
- @Override
- public void setConnectionListener(ConnectionListener listener)
- {
- }
-
- @Override
- public void close() throws JMSException
- {
- }
-
- @Override
- public ConnectionConsumer createConnectionConsumer(
- Destination arg0, String arg1, ServerSessionPool arg2,
- int arg3) throws JMSException
- {
- return null;
- }
-
- @Override
- public ConnectionConsumer createDurableConnectionConsumer(
- Topic arg0, String arg1, String arg2,
- ServerSessionPool arg3, int arg4) throws JMSException
- {
- return null;
- }
-
- @Override
- public javax.jms.Session createSession(boolean arg0, int arg1)
- throws JMSException
- {
- return null;
- }
-
- @Override
- public String getClientID() throws JMSException
- {
- return null;
- }
-
- @Override
- public ExceptionListener getExceptionListener() throws JMSException
- {
- return null;
- }
-
- @Override
- public ConnectionMetaData getMetaData() throws JMSException
- {
- return null;
- }
-
- @Override
- public void setClientID(String arg0) throws JMSException
- {
- }
-
- @Override
- public void setExceptionListener(ExceptionListener arg0)
- throws JMSException
- {
- }
-
- @Override
- public void start() throws JMSException
- {
- }
-
- @Override
- public void stop() throws JMSException
- {
- }
- };
- }
-
- // Class used to test the ability of FailoverPolicy to load an implementation.
- static class MyFailoverMethod implements FailoverMethod
- {
- public MyFailoverMethod(ConnectionURL connectionDetails)
- {
- }
-
- @Override
- public void attainedConnection()
- {
- }
-
- @Override
- public boolean failoverAllowed()
- {
- return false;
- }
-
- @Override
- public BrokerDetails getCurrentBrokerDetails()
- {
- return null;
- }
-
- @Override
- public BrokerDetails getNextBrokerDetails()
- {
- return null;
- }
-
- @Override
- public String methodName()
- {
- return null;
- }
-
- @Override
- public void reset()
- {
- }
-
- @Override
- public void setBroker(BrokerDetails broker)
- {
- }
-
- @Override
- public void setRetries(int maxRetries)
- {
- }
- }
-
-}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java
index 9095f94960..1b27ff6300 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java
@@ -43,6 +43,15 @@ public class BrokerDetailsTest extends TestCase
assertTrue(broker.getProperty("immediatedelivery").equals("true"));
}
+ public void testVMBroker() throws URLSyntaxException
+ {
+ String url = "vm://:2";
+
+ AMQBrokerDetails broker = new AMQBrokerDetails(url);
+ assertTrue(broker.getTransport().equals("vm"));
+ assertEquals(broker.getPort(), 2);
+ }
+
public void testTransportsDefaultToTCP() throws URLSyntaxException
{
String url = "localhost:5672";
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
index d560c413e6..66f220643c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
@@ -73,7 +73,7 @@ public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListe
{
throw new AMQNoRouteException("Error: " + reason, null, null);
}
- else if (errorCode == AMQConstant.ARGUMENT_INVALID)
+ else if (errorCode == AMQConstant.INVALID_ARGUMENT)
{
_logger.debug("Broker responded with Invalid Argument.");
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
index 4624b36fea..2be3720c20 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
@@ -300,6 +300,53 @@ public class ConnectionURLTest extends TestCase
assertTrue(connectionurl.getOption("immediatedelivery").equals("true"));
}
+ public void testSinglevmURL() throws URLSyntaxException
+ {
+ String url = "amqp://guest:guest@/test?brokerlist='vm://:2'";
+
+ ConnectionURL connectionurl = new AMQConnectionURL(url);
+
+ assertTrue(connectionurl.getFailoverMethod() == null);
+ assertTrue(connectionurl.getUsername().equals("guest"));
+ assertTrue(connectionurl.getPassword().equals("guest"));
+ assertTrue(connectionurl.getVirtualHost().equals("/test"));
+
+ assertTrue(connectionurl.getBrokerCount() == 1);
+
+ BrokerDetails service = connectionurl.getBrokerDetails(0);
+
+ assertTrue(service.getTransport().equals("vm"));
+ assertTrue(service.getHost().equals(""));
+ assertTrue(service.getPort() == 2);
+
+ }
+
+ public void testFailoverVMURL() throws URLSyntaxException
+ {
+ String url = "amqp://ritchiem:bob@/test?brokerlist='vm://:2;vm://:3',failover='roundrobin'";
+
+ ConnectionURL connectionurl = new AMQConnectionURL(url);
+
+ assertTrue(connectionurl.getFailoverMethod().equals("roundrobin"));
+ assertTrue(connectionurl.getUsername().equals("ritchiem"));
+ assertTrue(connectionurl.getPassword().equals("bob"));
+ assertTrue(connectionurl.getVirtualHost().equals("/test"));
+
+ assertTrue(connectionurl.getBrokerCount() == 2);
+
+ BrokerDetails service = connectionurl.getBrokerDetails(0);
+
+ assertTrue(service.getTransport().equals("vm"));
+ assertTrue(service.getHost().equals(""));
+ assertTrue(service.getPort() == 2);
+
+ service = connectionurl.getBrokerDetails(1);
+ assertTrue(service.getTransport().equals("vm"));
+ assertTrue(service.getHost().equals(""));
+ assertTrue(service.getPort() == 3);
+ }
+
+
public void testNoVirtualHostURL()
{
String url = "amqp://user@?brokerlist='tcp://localhost:5672'";
@@ -440,6 +487,27 @@ public class ConnectionURLTest extends TestCase
}
+ public void testSocketProtocol() throws URLSyntaxException
+ {
+ String url = "amqp://guest:guest@id/test" + "?brokerlist='socket://VM-Unique-socketID'";
+
+ try
+ {
+ AMQConnectionURL curl = new AMQConnectionURL(url);
+ assertNotNull(curl);
+ assertEquals(1, curl.getBrokerCount());
+ assertNotNull(curl.getBrokerDetails(0));
+ assertEquals(BrokerDetails.SOCKET, curl.getBrokerDetails(0).getTransport());
+ assertEquals("VM-Unique-socketID", curl.getBrokerDetails(0).getHost());
+ assertEquals("URL does not toString as expected",
+ url.replace(":guest", ":********"), curl.toString());
+ }
+ catch (URLSyntaxException e)
+ {
+ fail(e.getMessage());
+ }
+ }
+
public void testSingleTransportMultiOptionOnBrokerURL() throws URLSyntaxException
{
String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672?foo='jim'&bar='bob'&fred='jimmy'',routingkey='jim',timeout='200',immediatedelivery='true'";
@@ -481,37 +549,6 @@ public class ConnectionURLTest extends TestCase
assertTrue("String representation should contain options and values", url.toString().contains("maxprefetch='12345'"));
}
- public void testHostNamesWithUnderScore() throws URLSyntaxException
- {
- String url = "amqp://guest:guest@clientid/test?brokerlist='tcp://under_score:6672'";
-
- ConnectionURL connectionurl = new AMQConnectionURL(url);
-
- assertTrue(connectionurl.getUsername().equals("guest"));
- assertTrue(connectionurl.getPassword().equals("guest"));
- assertTrue(connectionurl.getVirtualHost().equals("/test"));
-
- assertTrue(connectionurl.getBrokerCount() == 1);
- BrokerDetails service = connectionurl.getBrokerDetails(0);
- assertTrue(service.getTransport().equals("tcp"));
- assertTrue(service.getHost().equals("under_score"));
- assertTrue(service.getPort() == 6672);
-
- url = "amqp://guest:guest@clientid/test?brokerlist='tcp://under_score'";
-
- connectionurl = new AMQConnectionURL(url);
-
- assertTrue(connectionurl.getUsername().equals("guest"));
- assertTrue(connectionurl.getPassword().equals("guest"));
- assertTrue(connectionurl.getVirtualHost().equals("/test"));
-
- assertTrue(connectionurl.getBrokerCount() == 1);
- service = connectionurl.getBrokerDetails(0);
- assertTrue(service.getTransport().equals("tcp"));
- assertTrue(service.getHost().equals("under_score"));
- assertTrue(service.getPort() == 5672);
- }
-
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(ConnectionURLTest.class);
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageUnitTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageUnitTest.java
deleted file mode 100644
index e37970e9a2..0000000000
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageUnitTest.java
+++ /dev/null
@@ -1,105 +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.
- *
- */
-package org.apache.qpid.test.unit.client.message;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.apache.qpid.client.message.JMSObjectMessage;
-import org.apache.qpid.client.message.TestMessageHelper;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class ObjectMessageUnitTest extends QpidTestCase
-{
- private JMSObjectMessage _om;
-
- protected void setUp() throws Exception
- {
- super.setUp();
- _om = TestMessageHelper.newJMSObjectMessage();
- }
-
- /**
- * Test that setObject with a primitive works
- */
- public void testSetObjectWithBooleanPrimitive() throws Exception
- {
- _om.setObject(true);
-
- //make the message readable
- Object object = _om.getObject();
-
- assertTrue("Unexpected type returned", object instanceof Boolean);
- assertEquals("Unexpected value returned", true, object);
- }
-
- /**
- * Test that setObject with a serializable Object works
- */
- public void testSetObjectWithString() throws Exception
- {
- _om.setObject("test string");
-
- //make the message readable
- Object object = _om.getObject();
-
- assertTrue("Unexpected type returned", object instanceof String);
- assertEquals("Unexpected value returned", "test string", object);
- }
-
- /**
- * Test that setObject with a Collection of serializable's works, returning
- * the items in the list when deserialized and ignoring any values
- * added to the collection after setObject() is called on the message.
- */
- public void testSetObjectWithArrayListOfInteger() throws Exception
- {
- ArrayList<Integer> list = new ArrayList<Integer>();
- list.add(1234);
- list.add(Integer.MIN_VALUE);
- list.add(Integer.MAX_VALUE);
-
- _om.setObject(list);
-
- //add something extra to the list now, and check it isn't in the value read back
- list.add(0);
-
- //make the message readable
-
- //retrieve the Object
- Object object = _om.getObject();
-
- ArrayList<?> returnedList = null;
- if(object instanceof ArrayList<?>)
- {
- returnedList = (ArrayList<?>) object;
- }
- else
- {
- fail("returned object was not an ArrayList");
- }
-
- //verify the extra added Integer was not present, then remove it from original list again and compare contents with the returned list
- assertFalse("returned list should not have had the value added after setObject() was used", returnedList.contains(0));
- list.remove(Integer.valueOf(0));
- assertTrue("list contents were not equal", Arrays.equals(list.toArray(), returnedList.toArray()));
- }
-}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java
index 20496026ce..9e76b0d468 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/jndi/ConnectionFactoryTest.java
@@ -21,10 +21,10 @@
package org.apache.qpid.test.unit.jndi;
import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.url.URLSyntaxException;
public class ConnectionFactoryTest extends TestCase
{
@@ -34,9 +34,21 @@ public class ConnectionFactoryTest extends TestCase
public static final String URL = "amqp://guest:guest@clientID/test?brokerlist='tcp://localhost:5672'";
public static final String URL_STAR_PWD = "amqp://guest:********@clientID/test?brokerlist='tcp://localhost:5672'";
- public void testConnectionURLStringMasksPassword() throws Exception
+ public void testConnectionURLString()
{
- AMQConnectionFactory factory = new AMQConnectionFactory(URL);
+ AMQConnectionFactory factory = new AMQConnectionFactory();
+
+ assertNull("ConnectionURL should have no value at start",
+ factory.getConnectionURL());
+
+ try
+ {
+ factory.setConnectionURLString(URL);
+ }
+ catch (URLSyntaxException e)
+ {
+ fail(e.getMessage());
+ }
//URL will be returned with the password field swapped for '********'
assertEquals("Connection URL not correctly set", URL_STAR_PWD, factory.getConnectionURLString());
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java
index 2052312f54..a1b14d5723 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/jndi/JNDIPropertyFileTest.java
@@ -24,7 +24,6 @@ import java.util.Properties;
import javax.jms.Queue;
import javax.jms.Topic;
-import javax.naming.ConfigurationException;
import javax.naming.Context;
import javax.naming.InitialContext;
@@ -68,22 +67,4 @@ public class JNDIPropertyFileTest extends TestCase
assertEquals("Topic" + i + "WithSpace",bindingKey.asString());
}
}
-
- public void testConfigurationErrors() throws Exception
- {
- Properties properties = new Properties();
- properties.put("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory");
- properties.put("destination.my-queue","amq.topic/test;create:always}");
-
- try
- {
- ctx = new InitialContext(properties);
- fail("A configuration exception should be thrown with details about the address syntax error");
- }
- catch(ConfigurationException e)
- {
- assertTrue("Incorrect exception", e.getMessage().contains("Failed to parse entry: amq.topic/test;create:always}"));
- }
-
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
index 6759b43387..47c0359b94 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
@@ -20,24 +20,17 @@
*/
package org.apache.qpid.test.unit.message;
-import java.util.Map;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.TemporaryQueue;
-import javax.jms.Topic;
-import javax.jms.TopicSubscriber;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.BasicMessageConsumer_0_8;
-import org.apache.qpid.client.BasicMessageProducer_0_8;
-import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.client.*;
import org.apache.qpid.client.message.AMQMessageDelegateFactory;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+
+import javax.jms.*;
+
+import java.util.Map;
public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8>
{
@@ -64,12 +57,7 @@ public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMe
}
- public void commitImpl() throws AMQException, FailoverException
- {
-
- }
-
- public void acknowledgeImpl()
+ public void sendCommit() throws AMQException, FailoverException
{
}
@@ -129,7 +117,7 @@ public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMe
}
- public BasicMessageProducer_0_8 createMessageProducer(Destination destination, boolean mandatory, boolean immediate, long producerId)
+ public BasicMessageProducer_0_8 createMessageProducer(Destination destination, boolean mandatory, boolean immediate, boolean waitUntilSent, long producerId)
{
return null;
}
@@ -207,10 +195,4 @@ public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMe
{
return false;
}
-
- @Override
- public AMQException getLastException()
- {
- return null;
- }
}
diff --git a/java/common.xml b/java/common.xml
index c6688ee2de..066859b29f 100644
--- a/java/common.xml
+++ b/java/common.xml
@@ -23,9 +23,7 @@
<dirname property="project.root" file="${ant.file.common}"/>
<property name="project.name" value="qpid"/>
- <property name="project.version" value="0.13"/>
- <property name="project.url" value="http://qpid.apache.org"/>
- <property name="project.groupid" value="org.apache.qpid"/>
+ <property name="project.version" value="0.9"/>
<property name="project.namever" value="${project.name}-${project.version}"/>
<property name="resources" location="${project.root}/resources"/>
@@ -42,6 +40,7 @@
<property name="build.report" location="${build}/report"/>
<property name="build.release" location="${build}/release"/>
<property name="build.release.prepare" location="${build.release}/prepare"/>
+ <property name="build.data" location="${build.scratch}/data"/>
<property name="build.plugins" location="${build}/lib/plugins"/>
<property name="build.coveragereport" location="${build}/coverage"/>
<property name="build.findbugs" location="${build}/findbugs"/>
@@ -64,11 +63,6 @@
<property name="mllib.dir" value="${project.root}/../python" />
<property name="findbugs.dir" value="${project.root}/lib/findbugs" />
- <!-- properties used to control Ant Eclipse for Eclipse classpath/project files etc -->
- <property name="eclipse.updatealways" value="false"/>
- <property name="eclipse.compilercompliance" value="5.0"/>
- <property name="eclipse.container" value="JVM 1.5"/>
-
<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura.jar" />
@@ -77,7 +71,6 @@
</path>
<property name="maven.local.repo" value="${build.scratch}/maven-local-repo"/>
- <property name="maven.settings.xml" value="${project.root}/maven-settings.xml"/>
<property name="maven.unique.version" value="false"/>
<property name="maven.snapshot" value="true"/>
<condition property="maven.version.suffix" value="" else="-SNAPSHOT">
@@ -131,6 +124,8 @@
</sequential>
</macrodef>
+
+
<macrodef name="jython">
<attribute name="path"/>
<element name="args"/>
@@ -327,20 +322,6 @@
results directory:
${build.results}
-
- ant eclipse
-
- Generates project and classpath files for the Eclispe IDE. Requires that
- the Ant Eclipse task (http://ant-eclipse.sourceforge.net/) has been installed
- in $ANT_HOME/lib.
-
- The following system properties will be passed to the task. These can be usefully
- overridden from the command line.
-
- eclipse.updatealways - forces Eclipse files to be regenerated even if they are newer then the build.xml (default ${eclipse.updatealways}).
- eclipse.container - controls the Eclipse container (default ${eclipse.container}).
- eclipse.compilercompliance" - controls the Eclipse compiler compliance (default ${eclipse.compilercompliance}).
-
</echo>
</target>
diff --git a/java/common/bin/qpid-run b/java/common/bin/qpid-run
index ef4363e88b..15d88992df 100755
--- a/java/common/bin/qpid-run
+++ b/java/common/bin/qpid-run
@@ -77,10 +77,7 @@ fi
#Set the default system properties that we'll use now that they have
#all been initialised
-declare -a SYSTEM_PROPS
-SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL"
-SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-DQPID_HOME=$QPID_HOME"
-SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-DQPID_WORK=$QPID_WORK"
+SYSTEM_PROPS="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL -DQPID_HOME=$QPID_HOME -DQPID_WORK=$QPID_WORK"
#If logprefix or logsuffix set to use PID make that happen
#Otherwise just pass the value through for these props
@@ -93,7 +90,7 @@ if [ -n "$QPID_LOG_PREFIX" ]; then
log $INFO Using qpid logprefix property
LOG_PREFIX=" -Dlogprefix=$QPID_LOG_PREFIX"
fi
- SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_PREFIX}"
+ SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_PREFIX}"
fi
if [ -n "$QPID_LOG_SUFFIX" ]; then
@@ -104,10 +101,10 @@ if [ -n "$QPID_LOG_SUFFIX" ]; then
log $INFO Using qpig logsuffix property
LOG_SUFFIX=" -Dlogsuffix=$QPID_LOG_SUFFIX"
fi
- SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_SUFFIX}"
+ SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_SUFFIX}"
fi
-log $INFO System Properties set to ${SYSTEM_PROPS[@]}
+log $INFO System Properties set to $SYSTEM_PROPS
log $INFO QPID_OPTS set to $QPID_OPTS
program=$(basename $0)
@@ -257,6 +254,6 @@ if $cygwin; then
JAVA=$(cygpath -u $JAVA)
fi
-COMMAND=($JAVA $JAVA_VM $QPID_PNAME $JAVA_GC $JAVA_MEM "${SYSTEM_PROPS[@]}" $JAVA_OPTS $QPID_OPTS "${JAVA_ARGS[@]}")
+COMMAND=($JAVA $JAVA_VM $QPID_PNAME $JAVA_GC $JAVA_MEM $SYSTEM_PROPS $JAVA_OPTS $QPID_OPTS "${JAVA_ARGS[@]}")
DISPATCH
diff --git a/java/common/src/main/java/common.bnd b/java/common/src/main/java/common.bnd
index f12fbf9273..ef56ecec9e 100755
--- a/java/common/src/main/java/common.bnd
+++ b/java/common/src/main/java/common.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.13.0
+ver: 0.9.0
Bundle-SymbolicName: qpid-common
Bundle-Version: ${ver}
diff --git a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java
new file mode 100644
index 0000000000..0c311b6645
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java
@@ -0,0 +1,467 @@
+package org.apache.mina.common;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.nio.*;
+
+/*
+*
+* 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.
+*
+*/
+public class FixedSizeByteBufferAllocator implements ByteBufferAllocator
+{
+
+
+ private static final int MINIMUM_CAPACITY = 1;
+
+ public FixedSizeByteBufferAllocator ()
+ {
+ }
+
+ public ByteBuffer allocate( int capacity, boolean direct )
+ {
+ java.nio.ByteBuffer nioBuffer;
+ if( direct )
+ {
+ nioBuffer = java.nio.ByteBuffer.allocateDirect( capacity );
+ }
+ else
+ {
+ nioBuffer = java.nio.ByteBuffer.allocate( capacity );
+ }
+ return new FixedSizeByteBuffer( nioBuffer );
+ }
+
+ public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
+ {
+ return new FixedSizeByteBuffer( nioBuffer );
+ }
+
+ public void dispose()
+ {
+ }
+
+
+
+ private static final class FixedSizeByteBuffer extends ByteBuffer
+ {
+ private java.nio.ByteBuffer buf;
+ private int mark = -1;
+
+
+ protected FixedSizeByteBuffer( java.nio.ByteBuffer buf )
+ {
+ this.buf = buf;
+ buf.order( ByteOrder.BIG_ENDIAN );
+ }
+
+ public synchronized void acquire()
+ {
+ }
+
+ public void release()
+ {
+ }
+
+ public java.nio.ByteBuffer buf()
+ {
+ return buf;
+ }
+
+ public boolean isPooled()
+ {
+ return false;
+ }
+
+ public void setPooled( boolean pooled )
+ {
+ }
+
+ public ByteBuffer duplicate() {
+ return new FixedSizeByteBuffer( this.buf.duplicate() );
+ }
+
+ public ByteBuffer slice() {
+ return new FixedSizeByteBuffer( this.buf.slice() );
+ }
+
+ public ByteBuffer asReadOnlyBuffer() {
+ return new FixedSizeByteBuffer( this.buf.asReadOnlyBuffer() );
+ }
+
+ public byte[] array()
+ {
+ return buf.array();
+ }
+
+ public int arrayOffset()
+ {
+ return buf.arrayOffset();
+ }
+
+ public boolean isDirect()
+ {
+ return buf.isDirect();
+ }
+
+ public boolean isReadOnly()
+ {
+ return buf.isReadOnly();
+ }
+
+ public int capacity()
+ {
+ return buf.capacity();
+ }
+
+ public ByteBuffer capacity( int newCapacity )
+ {
+ if( newCapacity > capacity() )
+ {
+ throw new IllegalArgumentException();
+ }
+
+ return this;
+ }
+
+
+
+ public boolean isAutoExpand()
+ {
+ return false;
+ }
+
+ public ByteBuffer setAutoExpand( boolean autoExpand )
+ {
+ if(autoExpand) throw new IllegalArgumentException();
+ else return this;
+ }
+
+ public ByteBuffer expand( int pos, int expectedRemaining )
+ {
+ int end = pos + expectedRemaining;
+ if( end > capacity() )
+ {
+ // The buffer needs expansion.
+ capacity( end );
+ }
+
+ if( end > limit() )
+ {
+ // We call limit() directly to prevent StackOverflowError
+ buf.limit( end );
+ }
+ return this;
+ }
+
+ public int position()
+ {
+ return buf.position();
+ }
+
+ public ByteBuffer position( int newPosition )
+ {
+
+ buf.position( newPosition );
+ if( mark > newPosition )
+ {
+ mark = -1;
+ }
+ return this;
+ }
+
+ public int limit()
+ {
+ return buf.limit();
+ }
+
+ public ByteBuffer limit( int newLimit )
+ {
+ buf.limit( newLimit );
+ if( mark > newLimit )
+ {
+ mark = -1;
+ }
+ return this;
+ }
+
+ public ByteBuffer mark()
+ {
+ buf.mark();
+ mark = position();
+ return this;
+ }
+
+ public int markValue()
+ {
+ return mark;
+ }
+
+ public ByteBuffer reset()
+ {
+ buf.reset();
+ return this;
+ }
+
+ public ByteBuffer clear()
+ {
+ buf.clear();
+ mark = -1;
+ return this;
+ }
+
+ public ByteBuffer flip()
+ {
+ buf.flip();
+ mark = -1;
+ return this;
+ }
+
+ public ByteBuffer rewind()
+ {
+ buf.rewind();
+ mark = -1;
+ return this;
+ }
+
+ public byte get()
+ {
+ return buf.get();
+ }
+
+ public ByteBuffer put( byte b )
+ {
+ buf.put( b );
+ return this;
+ }
+
+ public byte get( int index )
+ {
+ return buf.get( index );
+ }
+
+ public ByteBuffer put( int index, byte b )
+ {
+ buf.put( index, b );
+ return this;
+ }
+
+ public ByteBuffer get( byte[] dst, int offset, int length )
+ {
+ buf.get( dst, offset, length );
+ return this;
+ }
+
+ public ByteBuffer put( java.nio.ByteBuffer src )
+ {
+ buf.put( src );
+ return this;
+ }
+
+ public ByteBuffer put( byte[] src, int offset, int length )
+ {
+ buf.put( src, offset, length );
+ return this;
+ }
+
+ public ByteBuffer compact()
+ {
+ buf.compact();
+ mark = -1;
+ return this;
+ }
+
+ public ByteOrder order()
+ {
+ return buf.order();
+ }
+
+ public ByteBuffer order( ByteOrder bo )
+ {
+ buf.order( bo );
+ return this;
+ }
+
+ public char getChar()
+ {
+ return buf.getChar();
+ }
+
+ public ByteBuffer putChar( char value )
+ {
+ buf.putChar( value );
+ return this;
+ }
+
+ public char getChar( int index )
+ {
+ return buf.getChar( index );
+ }
+
+ public ByteBuffer putChar( int index, char value )
+ {
+ buf.putChar( index, value );
+ return this;
+ }
+
+ public CharBuffer asCharBuffer()
+ {
+ return buf.asCharBuffer();
+ }
+
+ public short getShort()
+ {
+ return buf.getShort();
+ }
+
+ public ByteBuffer putShort( short value )
+ {
+ buf.putShort( value );
+ return this;
+ }
+
+ public short getShort( int index )
+ {
+ return buf.getShort( index );
+ }
+
+ public ByteBuffer putShort( int index, short value )
+ {
+ buf.putShort( index, value );
+ return this;
+ }
+
+ public ShortBuffer asShortBuffer()
+ {
+ return buf.asShortBuffer();
+ }
+
+ public int getInt()
+ {
+ return buf.getInt();
+ }
+
+ public ByteBuffer putInt( int value )
+ {
+ buf.putInt( value );
+ return this;
+ }
+
+ public int getInt( int index )
+ {
+ return buf.getInt( index );
+ }
+
+ public ByteBuffer putInt( int index, int value )
+ {
+ buf.putInt( index, value );
+ return this;
+ }
+
+ public IntBuffer asIntBuffer()
+ {
+ return buf.asIntBuffer();
+ }
+
+ public long getLong()
+ {
+ return buf.getLong();
+ }
+
+ public ByteBuffer putLong( long value )
+ {
+ buf.putLong( value );
+ return this;
+ }
+
+ public long getLong( int index )
+ {
+ return buf.getLong( index );
+ }
+
+ public ByteBuffer putLong( int index, long value )
+ {
+ buf.putLong( index, value );
+ return this;
+ }
+
+ public LongBuffer asLongBuffer()
+ {
+ return buf.asLongBuffer();
+ }
+
+ public float getFloat()
+ {
+ return buf.getFloat();
+ }
+
+ public ByteBuffer putFloat( float value )
+ {
+ buf.putFloat( value );
+ return this;
+ }
+
+ public float getFloat( int index )
+ {
+ return buf.getFloat( index );
+ }
+
+ public ByteBuffer putFloat( int index, float value )
+ {
+ buf.putFloat( index, value );
+ return this;
+ }
+
+ public FloatBuffer asFloatBuffer()
+ {
+ return buf.asFloatBuffer();
+ }
+
+ public double getDouble()
+ {
+ return buf.getDouble();
+ }
+
+ public ByteBuffer putDouble( double value )
+ {
+ buf.putDouble( value );
+ return this;
+ }
+
+ public double getDouble( int index )
+ {
+ return buf.getDouble( index );
+ }
+
+ public ByteBuffer putDouble( int index, double value )
+ {
+ buf.putDouble( index, value );
+ return this;
+ }
+
+ public DoubleBuffer asDoubleBuffer()
+ {
+ return buf.asDoubleBuffer();
+ }
+
+
+ }
+
+
+}
diff --git a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
new file mode 100644
index 0000000000..4fd28c4eb5
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.mina.common.support;
+
+import org.apache.mina.common.IoFuture;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoFutureListener;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * A default implementation of {@link org.apache.mina.common.IoFuture}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class DefaultIoFuture implements IoFuture
+{
+ private final IoSession session;
+ private final Object lock;
+ private List listeners;
+ private Object result;
+ private boolean ready;
+
+
+ /**
+ * Creates a new instance.
+ *
+ * @param session an {@link IoSession} which is associated with this future
+ */
+ public DefaultIoFuture( IoSession session )
+ {
+ this.session = session;
+ this.lock = this;
+ }
+
+ /**
+ * Creates a new instance which uses the specified object as a lock.
+ */
+ public DefaultIoFuture( IoSession session, Object lock )
+ {
+ if( lock == null )
+ {
+ throw new NullPointerException( "lock" );
+ }
+ this.session = session;
+ this.lock = lock;
+ }
+
+ public IoSession getSession()
+ {
+ return session;
+ }
+
+ public Object getLock()
+ {
+ return lock;
+ }
+
+ public void join()
+ {
+ synchronized( lock )
+ {
+ while( !ready )
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch( InterruptedException e )
+ {
+ }
+ }
+ }
+ }
+
+ public boolean join( long timeoutInMillis )
+ {
+ long startTime = ( timeoutInMillis <= 0 ) ? 0 : System
+ .currentTimeMillis();
+ long waitTime = timeoutInMillis;
+
+ synchronized( lock )
+ {
+ if( ready )
+ {
+ return ready;
+ }
+ else if( waitTime <= 0 )
+ {
+ return ready;
+ }
+
+ for( ;; )
+ {
+ try
+ {
+ lock.wait( waitTime );
+ }
+ catch( InterruptedException e )
+ {
+ }
+
+ if( ready )
+ return true;
+ else
+ {
+ waitTime = timeoutInMillis - ( System.currentTimeMillis() - startTime );
+ if( waitTime <= 0 )
+ {
+ return ready;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean isReady()
+ {
+ synchronized( lock )
+ {
+ return ready;
+ }
+ }
+
+ /**
+ * Sets the result of the asynchronous operation, and mark it as finished.
+ */
+ protected void setValue( Object newValue )
+ {
+ synchronized( lock )
+ {
+ // Allow only once.
+ if( ready )
+ {
+ return;
+ }
+
+ result = newValue;
+ ready = true;
+ lock.notifyAll();
+
+ notifyListeners();
+ }
+ }
+
+ /**
+ * Returns the result of the asynchronous operation.
+ */
+ protected Object getValue()
+ {
+ synchronized( lock )
+ {
+ return result;
+ }
+ }
+
+ public void addListener( IoFutureListener listener )
+ {
+ if( listener == null )
+ {
+ throw new NullPointerException( "listener" );
+ }
+
+ synchronized( lock )
+ {
+ if(listeners == null)
+ {
+ listeners = new ArrayList();
+ }
+ listeners.add( listener );
+ if( ready )
+ {
+ listener.operationComplete( this );
+ }
+ }
+ }
+
+ public void removeListener( IoFutureListener listener )
+ {
+ if( listener == null )
+ {
+ throw new NullPointerException( "listener" );
+ }
+
+ synchronized( lock )
+ {
+ listeners.remove( listener );
+ }
+ }
+
+ private void notifyListeners()
+ {
+ synchronized( lock )
+ {
+
+ if(listeners != null)
+ {
+
+ for( Iterator i = listeners.iterator(); i.hasNext(); ) {
+ ( ( IoFutureListener ) i.next() ).operationComplete( this );
+ }
+ }
+ }
+ }
+}
+
+
+
diff --git a/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java b/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java
new file mode 100644
index 0000000000..5723ffbaa9
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/common/support/IoServiceListenerSupport.java
@@ -0,0 +1,351 @@
+/*
+ * 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 org.apache.mina.common.support;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.mina.common.IoAcceptorConfig;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoFuture;
+import org.apache.mina.common.IoFutureListener;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoService;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.IoServiceListener;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.util.IdentityHashSet;
+
+/**
+ * A helper which provides addition and removal of {@link IoServiceListener}s and firing
+ * events.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 446526 $, $Date: 2006-09-15 01:44:11 -0400 (Fri, 15 Sep 2006) $
+ */
+public class IoServiceListenerSupport
+{
+ /**
+ * A list of {@link IoServiceListener}s.
+ */
+ private final List listeners = new ArrayList();
+
+ /**
+ * Tracks managed <tt>serviceAddress</tt>es.
+ */
+ private final Set managedServiceAddresses = new HashSet();
+
+ /**
+ * Tracks managed sesssions with <tt>serviceAddress</tt> as a key.
+ */
+ private final Map managedSessions = new HashMap();
+
+ /**
+ * Creates a new instance.
+ */
+ public IoServiceListenerSupport()
+ {
+ }
+
+ /**
+ * Adds a new listener.
+ */
+ public void add( IoServiceListener listener )
+ {
+ synchronized( listeners )
+ {
+ listeners.add( listener );
+ }
+ }
+
+ /**
+ * Removes an existing listener.
+ */
+ public void remove( IoServiceListener listener )
+ {
+ synchronized( listeners )
+ {
+ listeners.remove( listener );
+ }
+ }
+
+ public Set getManagedServiceAddresses()
+ {
+ return Collections.unmodifiableSet( managedServiceAddresses );
+ }
+
+ public boolean isManaged( SocketAddress serviceAddress )
+ {
+ synchronized( managedServiceAddresses )
+ {
+ return managedServiceAddresses.contains( serviceAddress );
+ }
+ }
+
+ public Set getManagedSessions( SocketAddress serviceAddress )
+ {
+ Set sessions;
+ synchronized( managedSessions )
+ {
+ sessions = ( Set ) managedSessions.get( serviceAddress );
+ if( sessions == null )
+ {
+ sessions = new IdentityHashSet();
+ }
+ }
+
+ synchronized( sessions )
+ {
+ return new IdentityHashSet( sessions );
+ }
+ }
+
+ /**
+ * Calls {@link IoServiceListener#serviceActivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
+ * for all registered listeners.
+ */
+ public void fireServiceActivated(
+ IoService service, SocketAddress serviceAddress,
+ IoHandler handler, IoServiceConfig config )
+ {
+ synchronized( managedServiceAddresses )
+ {
+ if( !managedServiceAddresses.add( serviceAddress ) )
+ {
+ return;
+ }
+ }
+
+ synchronized( listeners )
+ {
+ for( Iterator i = listeners.iterator(); i.hasNext(); )
+ {
+ ( ( IoServiceListener ) i.next() ).serviceActivated(
+ service, serviceAddress, handler, config );
+ }
+ }
+ }
+
+ /**
+ * Calls {@link IoServiceListener#serviceDeactivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
+ * for all registered listeners.
+ */
+ public synchronized void fireServiceDeactivated(
+ IoService service, SocketAddress serviceAddress,
+ IoHandler handler, IoServiceConfig config )
+ {
+ synchronized( managedServiceAddresses )
+ {
+ if( !managedServiceAddresses.remove( serviceAddress ) )
+ {
+ return;
+ }
+ }
+
+ try
+ {
+ synchronized( listeners )
+ {
+ for( Iterator i = listeners.iterator(); i.hasNext(); )
+ {
+ ( ( IoServiceListener ) i.next() ).serviceDeactivated(
+ service, serviceAddress, handler, config );
+ }
+ }
+ }
+ finally
+ {
+ disconnectSessions( serviceAddress, config );
+ }
+ }
+
+
+ /**
+ * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners.
+ */
+ public void fireSessionCreated( IoSession session )
+ {
+ SocketAddress serviceAddress = session.getServiceAddress();
+
+ // Get the session set.
+ boolean firstSession = false;
+ Set sessions;
+ synchronized( managedSessions )
+ {
+ sessions = ( Set ) managedSessions.get( serviceAddress );
+ if( sessions == null )
+ {
+ sessions = new IdentityHashSet();
+ managedSessions.put( serviceAddress, sessions );
+ firstSession = true;
+ }
+ }
+
+ // If already registered, ignore.
+ synchronized( sessions )
+ {
+ if ( !sessions.add( session ) )
+ {
+ return;
+ }
+ }
+
+ // If the first connector session, fire a virtual service activation event.
+ if( session.getService() instanceof IoConnector && firstSession )
+ {
+ fireServiceActivated(
+ session.getService(), session.getServiceAddress(),
+ session.getHandler(), session.getServiceConfig() );
+ }
+
+ // Fire session events.
+ session.getFilterChain().fireSessionCreated( session );
+ session.getFilterChain().fireSessionOpened( session);
+
+ // Fire listener events.
+ synchronized( listeners )
+ {
+ for( Iterator i = listeners.iterator(); i.hasNext(); )
+ {
+ ( ( IoServiceListener ) i.next() ).sessionCreated( session );
+ }
+ }
+ }
+
+ /**
+ * Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners.
+ */
+ public void fireSessionDestroyed( IoSession session )
+ {
+ SocketAddress serviceAddress = session.getServiceAddress();
+
+ // Get the session set.
+ Set sessions;
+ boolean lastSession = false;
+ synchronized( managedSessions )
+ {
+ sessions = ( Set ) managedSessions.get( serviceAddress );
+ // Ignore if unknown.
+ if( sessions == null )
+ {
+ return;
+ }
+
+ // Try to remove the remaining empty seession set after removal.
+ synchronized( sessions )
+ {
+ sessions.remove( session );
+ if( sessions.isEmpty() )
+ {
+ managedSessions.remove( serviceAddress );
+ lastSession = true;
+ }
+ }
+ }
+
+ // Fire session events.
+ session.getFilterChain().fireSessionClosed( session );
+
+ // Fire listener events.
+ try
+ {
+ synchronized( listeners )
+ {
+ for( Iterator i = listeners.iterator(); i.hasNext(); )
+ {
+ ( ( IoServiceListener ) i.next() ).sessionDestroyed( session );
+ }
+ }
+ }
+ finally
+ {
+ // Fire a virtual service deactivation event for the last session of the connector.
+ //TODO double-check that this is *STILL* the last session. May not be the case
+ if( session.getService() instanceof IoConnector && lastSession )
+ {
+ fireServiceDeactivated(
+ session.getService(), session.getServiceAddress(),
+ session.getHandler(), session.getServiceConfig() );
+ }
+ }
+ }
+
+ private void disconnectSessions( SocketAddress serviceAddress, IoServiceConfig config )
+ {
+ if( !( config instanceof IoAcceptorConfig ) )
+ {
+ return;
+ }
+
+ if( !( ( IoAcceptorConfig ) config ).isDisconnectOnUnbind() )
+ {
+ return;
+ }
+
+ Set sessions;
+ synchronized( managedSessions )
+ {
+ sessions = ( Set ) managedSessions.get( serviceAddress );
+ }
+
+ if( sessions == null )
+ {
+ return;
+ }
+
+ Set sessionsCopy;
+
+ // Create a copy to avoid ConcurrentModificationException
+ synchronized( sessions )
+ {
+ sessionsCopy = new IdentityHashSet( sessions );
+ }
+
+ final CountDownLatch latch = new CountDownLatch(sessionsCopy.size());
+
+ for( Iterator i = sessionsCopy.iterator(); i.hasNext(); )
+ {
+ ( ( IoSession ) i.next() ).close().addListener( new IoFutureListener()
+ {
+ public void operationComplete( IoFuture future )
+ {
+ latch.countDown();
+ }
+ } );
+ }
+
+ try
+ {
+ latch.await();
+ }
+ catch( InterruptedException ie )
+ {
+ // Ignored
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java b/java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java
new file mode 100644
index 0000000000..47f19aa76d
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/filter/WriteBufferFullExeception.java
@@ -0,0 +1,48 @@
+package org.apache.mina.filter;
+
+import org.apache.mina.common.IoFilter;/*
+ *
+ * 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.
+ *
+ */
+
+public class WriteBufferFullExeception extends RuntimeException
+{
+ private IoFilter.WriteRequest _writeRequest;
+
+ public WriteBufferFullExeception()
+ {
+ this(null);
+ }
+
+ public WriteBufferFullExeception(IoFilter.WriteRequest writeRequest)
+ {
+ _writeRequest = writeRequest;
+ }
+
+
+ public void setWriteRequest(IoFilter.WriteRequest writeRequest)
+ {
+ _writeRequest = writeRequest;
+ }
+
+ public IoFilter.WriteRequest getWriteRequest()
+ {
+ return _writeRequest;
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java b/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java
new file mode 100644
index 0000000000..4e9db9071a
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/filter/WriteBufferLimitFilterBuilder.java
@@ -0,0 +1,272 @@
+/*
+ * 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 org.apache.mina.filter;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.DefaultIoFilterChainBuilder;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.executor.ExecutorFilter;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This filter will turn the asynchronous filterWrite method in to a blocking send when there are more than
+ * the prescribed number of messages awaiting filterWrite. It should be used in conjunction with the
+ * {@link ReadThrottleFilterBuilder} on a server as the blocking writes will allow the read thread to
+ * cause an Out of Memory exception due to a back log of unprocessed messages.
+ *
+ * This is should only be viewed as a temporary work around for DIRMINA-302.
+ *
+ * A true solution should not be implemented as a filter as this issue will always occur. On a machine
+ * where the network is slower than the local producer.
+ *
+ * Suggested improvement is to allow implementation of policices on what to do when buffer is full.
+ *
+ * They could be:
+ * Block - As this does
+ * Wait on a given Future - to drain more of the queue.. in essence this filter with high/low watermarks
+ * Throw Exception - through the client filterWrite() method to allow them to get immediate feedback on buffer state
+ *
+ * <p/>
+ * <p>Usage:
+ * <p/>
+ * <pre><code>
+ * DefaultFilterChainBuilder builder = ...
+ * WriteBufferLimitFilterBuilder filter = new WriteBufferLimitFilterBuilder();
+ * filter.attach( builder );
+ * </code></pre>
+ * <p/>
+ * or
+ * <p/>
+ * <pre><code>
+ * IoFilterChain chain = ...
+ * WriteBufferLimitFilterBuilder filter = new WriteBufferLimitFilterBuilder();
+ * filter.attach( chain );
+ * </code></pre>
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public class WriteBufferLimitFilterBuilder
+{
+ public static final String PENDING_SIZE = WriteBufferLimitFilterBuilder.class.getName() + ".pendingSize";
+
+ private static int DEFAULT_CONNECTION_BUFFER_MESSAGE_COUNT = 5000;
+
+ private volatile boolean throwNotBlock = false;
+
+ private volatile int maximumConnectionBufferCount;
+ private volatile long maximumConnectionBufferSize;
+
+ private final Object _blockLock = new Object();
+
+ private int _blockWaiters = 0;
+
+
+ public WriteBufferLimitFilterBuilder()
+ {
+ this(DEFAULT_CONNECTION_BUFFER_MESSAGE_COUNT);
+ }
+
+ public WriteBufferLimitFilterBuilder(int maxWriteBufferSize)
+ {
+ setMaximumConnectionBufferCount(maxWriteBufferSize);
+ }
+
+
+ /**
+ * Set the maximum amount pending items in the writeQueue for a given session.
+ * Changing the value will only take effect when new data is received for a
+ * connection, including existing connections. Default value is 5000 msgs.
+ *
+ * @param maximumConnectionBufferCount New buffer size. Must be > 0
+ */
+ public void setMaximumConnectionBufferCount(int maximumConnectionBufferCount)
+ {
+ this.maximumConnectionBufferCount = maximumConnectionBufferCount;
+ this.maximumConnectionBufferSize = 0;
+ }
+
+ public void setMaximumConnectionBufferSize(long maximumConnectionBufferSize)
+ {
+ this.maximumConnectionBufferSize = maximumConnectionBufferSize;
+ this.maximumConnectionBufferCount = 0;
+ }
+
+ /**
+ * Attach this filter to the specified filter chain. It will search for the ThreadPoolFilter, and attach itself
+ * before and after that filter.
+ *
+ * @param chain {@link IoFilterChain} to attach self to.
+ */
+ public void attach(IoFilterChain chain)
+ {
+ String name = getThreadPoolFilterEntryName(chain.getAll());
+
+ chain.addBefore(name, getClass().getName() + ".sendlimit", new SendLimit());
+ }
+
+ /**
+ * Attach this filter to the specified builder. It will search for the
+ * {@link ExecutorFilter}, and attach itself before and after that filter.
+ *
+ * @param builder {@link DefaultIoFilterChainBuilder} to attach self to.
+ */
+ public void attach(DefaultIoFilterChainBuilder builder)
+ {
+ String name = getThreadPoolFilterEntryName(builder.getAll());
+
+ builder.addBefore(name, getClass().getName() + ".sendlimit", new SendLimit());
+ }
+
+ private String getThreadPoolFilterEntryName(List entries)
+ {
+ Iterator i = entries.iterator();
+
+ while (i.hasNext())
+ {
+ IoFilterChain.Entry entry = (IoFilterChain.Entry) i.next();
+
+ if (entry.getFilter().getClass().isAssignableFrom(ExecutorFilter.class))
+ {
+ return entry.getName();
+ }
+ }
+
+ throw new IllegalStateException("Chain does not contain a ExecutorFilter");
+ }
+
+
+ public class SendLimit extends IoFilterAdapter
+ {
+ public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception
+ {
+ try
+ {
+ waitTillSendAllowed(session);
+ }
+ catch (WriteBufferFullExeception wbfe)
+ {
+ nextFilter.exceptionCaught(session, wbfe);
+ }
+
+ if (writeRequest.getMessage() instanceof ByteBuffer)
+ {
+ increasePendingWriteSize(session, (ByteBuffer) writeRequest.getMessage());
+ }
+
+ nextFilter.filterWrite(session, writeRequest);
+ }
+
+ private void increasePendingWriteSize(IoSession session, ByteBuffer message)
+ {
+ synchronized (session)
+ {
+ Long pendingSize = getScheduledWriteBytes(session) + message.remaining();
+ session.setAttribute(PENDING_SIZE, pendingSize);
+ }
+ }
+
+ private boolean sendAllowed(IoSession session)
+ {
+ if (session.isClosing())
+ {
+ return true;
+ }
+
+ int lmswm = maximumConnectionBufferCount;
+ long lmswb = maximumConnectionBufferSize;
+
+ return (lmswm == 0 || session.getScheduledWriteRequests() < lmswm)
+ && (lmswb == 0 || getScheduledWriteBytes(session) < lmswb);
+ }
+
+ private long getScheduledWriteBytes(IoSession session)
+ {
+ synchronized (session)
+ {
+ Long i = (Long) session.getAttribute(PENDING_SIZE);
+ return null == i ? 0 : i;
+ }
+ }
+
+ private void waitTillSendAllowed(IoSession session)
+ {
+ synchronized (_blockLock)
+ {
+ if (throwNotBlock)
+ {
+ throw new WriteBufferFullExeception();
+ }
+
+ _blockWaiters++;
+
+ while (!sendAllowed(session))
+ {
+ try
+ {
+ _blockLock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore.
+ }
+ }
+ _blockWaiters--;
+ }
+ }
+
+ public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception
+ {
+ if (message instanceof ByteBuffer)
+ {
+ decrementPendingWriteSize(session, (ByteBuffer) message);
+ }
+ notifyWaitingWriters();
+ nextFilter.messageSent(session, message);
+ }
+
+ private void decrementPendingWriteSize(IoSession session, ByteBuffer message)
+ {
+ synchronized (session)
+ {
+ session.setAttribute(PENDING_SIZE, getScheduledWriteBytes(session) - message.remaining());
+ }
+ }
+
+ private void notifyWaitingWriters()
+ {
+ synchronized (_blockLock)
+ {
+ if (_blockWaiters != 0)
+ {
+ _blockLock.notifyAll();
+ }
+ }
+
+ }
+
+ }//SentLimit
+
+
+}
diff --git a/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java b/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java
new file mode 100644
index 0000000000..3f7e206cb4
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/filter/codec/OurCumulativeProtocolDecoder.java
@@ -0,0 +1,197 @@
+/*
+ * 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 org.apache.mina.filter.codec;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+
+/**
+ * A {@link ProtocolDecoder} that cumulates the content of received
+ * buffers to a <em>cumulative buffer</em> to help users implement decoders.
+ * <p>
+ * If the received {@link ByteBuffer} is only a part of a message.
+ * decoders should cumulate received buffers to make a message complete or
+ * to postpone decoding until more buffers arrive.
+ * <p>
+ * Here is an example decoder that decodes CRLF terminated lines into
+ * <code>Command</code> objects:
+ * <pre>
+ * public class CRLFTerminatedCommandLineDecoder
+ * extends CumulativeProtocolDecoder {
+ *
+ * private Command parseCommand(ByteBuffer in) {
+ * // Convert the bytes in the specified buffer to a
+ * // Command object.
+ * ...
+ * }
+ *
+ * protected boolean doDecode(IoSession session, ByteBuffer in,
+ * ProtocolDecoderOutput out)
+ * throws Exception {
+ *
+ * // Remember the initial position.
+ * int start = in.position();
+ *
+ * // Now find the first CRLF in the buffer.
+ * byte previous = 0;
+ * while (in.hasRemaining()) {
+ * byte current = in.get();
+ *
+ * if (previous == '\r' && current == '\n') {
+ * // Remember the current position and limit.
+ * int position = in.position();
+ * int limit = in.limit();
+ * try {
+ * in.position(start);
+ * in.limit(position);
+ * // The bytes between in.position() and in.limit()
+ * // now contain a full CRLF terminated line.
+ * out.write(parseCommand(in.slice()));
+ * } finally {
+ * // Set the position to point right after the
+ * // detected line and set the limit to the old
+ * // one.
+ * in.position(position);
+ * in.limit(limit);
+ * }
+ * // Decoded one line; CumulativeProtocolDecoder will
+ * // call me again until I return false. So just
+ * // return true until there are no more lines in the
+ * // buffer.
+ * return true;
+ * }
+ *
+ * previous = current;
+ * }
+ *
+ * // Could not find CRLF in the buffer. Reset the initial
+ * // position to the one we recorded above.
+ * in.position(start);
+ *
+ * return false;
+ * }
+ * }
+ * </pre>
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public abstract class OurCumulativeProtocolDecoder extends ProtocolDecoderAdapter {
+
+ private static final String BUFFER = OurCumulativeProtocolDecoder.class
+ .getName()
+ + ".Buffer";
+
+ /**
+ * Creates a new instance.
+ */
+ protected OurCumulativeProtocolDecoder() {
+ }
+
+ /**
+ * Cumulates content of <tt>in</tt> into internal buffer and forwards
+ * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
+ * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
+ * and the cumulative buffer is NOT compacted after decoding ends.
+ *
+ * @throws IllegalStateException if your <tt>doDecode()</tt> returned
+ * <tt>true</tt> not consuming the cumulative buffer.
+ */
+ public void decode(IoSession session, ByteBuffer in,
+ ProtocolDecoderOutput out) throws Exception {
+ boolean usingSessionBuffer = true;
+ ByteBuffer buf = (ByteBuffer) session.getAttribute(BUFFER);
+ // If we have a session buffer, append data to that; otherwise
+ // use the buffer read from the network directly.
+ if (buf != null) {
+ buf.put(in);
+ buf.flip();
+ } else {
+ buf = in;
+ usingSessionBuffer = false;
+ }
+
+ for (;;) {
+ int oldPos = buf.position();
+ boolean decoded = doDecode(session, buf, out);
+ if (decoded) {
+ if (buf.position() == oldPos) {
+ throw new IllegalStateException(
+ "doDecode() can't return true when buffer is not consumed.");
+ }
+
+ if (!buf.hasRemaining()) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+
+ // if there is any data left that cannot be decoded, we store
+ // it in a buffer in the session and next time this decoder is
+ // invoked the session buffer gets appended to
+ if (buf.hasRemaining()) {
+ storeRemainingInSession(buf, session);
+ } else {
+ if (usingSessionBuffer)
+ removeSessionBuffer(session);
+ }
+ }
+
+ /**
+ * Implement this method to consume the specified cumulative buffer and
+ * decode its content into message(s).
+ *
+ * @param in the cumulative buffer
+ * @return <tt>true</tt> if and only if there's more to decode in the buffer
+ * and you want to have <tt>doDecode</tt> method invoked again.
+ * Return <tt>false</tt> if remaining data is not enough to decode,
+ * then this method will be invoked again when more data is cumulated.
+ * @throws Exception if cannot decode <tt>in</tt>.
+ */
+ protected abstract boolean doDecode(IoSession session, ByteBuffer in,
+ ProtocolDecoderOutput out) throws Exception;
+
+ /**
+ * Releases the cumulative buffer used by the specified <tt>session</tt>.
+ * Please don't forget to call <tt>super.dispose( session )</tt> when
+ * you override this method.
+ */
+ public void dispose(IoSession session) throws Exception {
+ removeSessionBuffer(session);
+ }
+
+ private void removeSessionBuffer(IoSession session) {
+ ByteBuffer buf = (ByteBuffer) session.removeAttribute(BUFFER);
+ if (buf != null) {
+ buf.release();
+ }
+ }
+
+ private void storeRemainingInSession(ByteBuffer buf, IoSession session) {
+ ByteBuffer remainingBuf = ByteBuffer.allocate(buf.capacity());
+ remainingBuf.setAutoExpand(true);
+ remainingBuf.order(buf.order());
+ remainingBuf.put(buf);
+ session.setAttribute(BUFFER, remainingBuf);
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java b/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java
new file mode 100644
index 0000000000..b8c6f29720
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/filter/codec/QpidProtocolCodecFilter.java
@@ -0,0 +1,440 @@
+package org.apache.mina.filter.codec;
+
+
+/*
+*
+* 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.
+*
+*/
+
+import org.apache.mina.common.*;
+import org.apache.mina.common.support.DefaultWriteFuture;
+import org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput;
+import org.apache.mina.util.SessionLog;
+import org.apache.mina.util.Queue;
+
+
+public class QpidProtocolCodecFilter extends IoFilterAdapter
+{
+ public static final String ENCODER = QpidProtocolCodecFilter.class.getName() + ".encoder";
+ public static final String DECODER = QpidProtocolCodecFilter.class.getName() + ".decoder";
+
+ private static final Class[] EMPTY_PARAMS = new Class[0];
+ private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap( new byte[0] );
+
+ private final ProtocolCodecFactory factory;
+
+ public QpidProtocolCodecFilter( ProtocolCodecFactory factory )
+ {
+ if( factory == null )
+ {
+ throw new NullPointerException( "factory" );
+ }
+ this.factory = factory;
+ }
+
+ public QpidProtocolCodecFilter( final ProtocolEncoder encoder, final ProtocolDecoder decoder )
+ {
+ if( encoder == null )
+ {
+ throw new NullPointerException( "encoder" );
+ }
+ if( decoder == null )
+ {
+ throw new NullPointerException( "decoder" );
+ }
+
+ this.factory = new ProtocolCodecFactory()
+ {
+ public ProtocolEncoder getEncoder()
+ {
+ return encoder;
+ }
+
+ public ProtocolDecoder getDecoder()
+ {
+ return decoder;
+ }
+ };
+ }
+
+ public QpidProtocolCodecFilter( final Class encoderClass, final Class decoderClass )
+ {
+ if( encoderClass == null )
+ {
+ throw new NullPointerException( "encoderClass" );
+ }
+ if( decoderClass == null )
+ {
+ throw new NullPointerException( "decoderClass" );
+ }
+ if( !ProtocolEncoder.class.isAssignableFrom( encoderClass ) )
+ {
+ throw new IllegalArgumentException( "encoderClass: " + encoderClass.getName() );
+ }
+ if( !ProtocolDecoder.class.isAssignableFrom( decoderClass ) )
+ {
+ throw new IllegalArgumentException( "decoderClass: " + decoderClass.getName() );
+ }
+ try
+ {
+ encoderClass.getConstructor( EMPTY_PARAMS );
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new IllegalArgumentException( "encoderClass doesn't have a public default constructor." );
+ }
+ try
+ {
+ decoderClass.getConstructor( EMPTY_PARAMS );
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new IllegalArgumentException( "decoderClass doesn't have a public default constructor." );
+ }
+
+ this.factory = new ProtocolCodecFactory()
+ {
+ public ProtocolEncoder getEncoder() throws Exception
+ {
+ return ( ProtocolEncoder ) encoderClass.newInstance();
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception
+ {
+ return ( ProtocolDecoder ) decoderClass.newInstance();
+ }
+ };
+ }
+
+ public void onPreAdd( IoFilterChain parent, String name, IoFilter.NextFilter nextFilter ) throws Exception
+ {
+ if( parent.contains( ProtocolCodecFilter.class ) )
+ {
+ throw new IllegalStateException( "A filter chain cannot contain more than one QpidProtocolCodecFilter." );
+ }
+ }
+
+ public void messageReceived( IoFilter.NextFilter nextFilter, IoSession session, Object message ) throws Exception
+ {
+ if( !( message instanceof ByteBuffer ) )
+ {
+ nextFilter.messageReceived( session, message );
+ return;
+ }
+
+ ByteBuffer in = ( ByteBuffer ) message;
+ ProtocolDecoder decoder = getDecoder( session );
+ ProtocolDecoderOutput decoderOut = getDecoderOut( session, nextFilter );
+
+ try
+ {
+ decoder.decode( session, in, decoderOut );
+ }
+ catch( Throwable t )
+ {
+ ProtocolDecoderException pde;
+ if( t instanceof ProtocolDecoderException )
+ {
+ pde = ( ProtocolDecoderException ) t;
+ }
+ else
+ {
+ pde = new ProtocolDecoderException( t );
+ }
+ pde.setHexdump( in.getHexDump() );
+ throw pde;
+ }
+ finally
+ {
+ // Dispose the decoder if this session is connectionless.
+ if( session.getTransportType().isConnectionless() )
+ {
+ disposeDecoder( session );
+ }
+
+ // Release the read buffer.
+ in.release();
+
+ decoderOut.flush();
+ }
+ }
+
+ public void messageSent( IoFilter.NextFilter nextFilter, IoSession session, Object message ) throws Exception
+ {
+ if( message instanceof HiddenByteBuffer )
+ {
+ return;
+ }
+
+ if( !( message instanceof MessageByteBuffer ) )
+ {
+ nextFilter.messageSent( session, message );
+ return;
+ }
+
+ nextFilter.messageSent( session, ( ( MessageByteBuffer ) message ).message );
+ }
+
+ public void filterWrite( IoFilter.NextFilter nextFilter, IoSession session, IoFilter.WriteRequest writeRequest ) throws Exception
+ {
+ Object message = writeRequest.getMessage();
+ if( message instanceof ByteBuffer )
+ {
+ nextFilter.filterWrite( session, writeRequest );
+ return;
+ }
+
+ ProtocolEncoder encoder = getEncoder( session );
+ ProtocolEncoderOutputImpl encoderOut = getEncoderOut( session, nextFilter, writeRequest );
+
+ try
+ {
+ encoder.encode( session, message, encoderOut );
+ encoderOut.flush();
+ nextFilter.filterWrite(
+ session,
+ new IoFilter.WriteRequest(
+ new MessageByteBuffer( writeRequest.getMessage() ),
+ writeRequest.getFuture(), writeRequest.getDestination() ) );
+ }
+ catch( Throwable t )
+ {
+ ProtocolEncoderException pee;
+ if( t instanceof ProtocolEncoderException )
+ {
+ pee = ( ProtocolEncoderException ) t;
+ }
+ else
+ {
+ pee = new ProtocolEncoderException( t );
+ }
+ throw pee;
+ }
+ finally
+ {
+ // Dispose the encoder if this session is connectionless.
+ if( session.getTransportType().isConnectionless() )
+ {
+ disposeEncoder( session );
+ }
+ }
+ }
+
+ public void sessionClosed( IoFilter.NextFilter nextFilter, IoSession session ) throws Exception
+ {
+ // Call finishDecode() first when a connection is closed.
+ ProtocolDecoder decoder = getDecoder( session );
+ ProtocolDecoderOutput decoderOut = getDecoderOut( session, nextFilter );
+ try
+ {
+ decoder.finishDecode( session, decoderOut );
+ }
+ catch( Throwable t )
+ {
+ ProtocolDecoderException pde;
+ if( t instanceof ProtocolDecoderException )
+ {
+ pde = ( ProtocolDecoderException ) t;
+ }
+ else
+ {
+ pde = new ProtocolDecoderException( t );
+ }
+ throw pde;
+ }
+ finally
+ {
+ // Dispose all.
+ disposeEncoder( session );
+ disposeDecoder( session );
+
+ decoderOut.flush();
+ }
+
+ nextFilter.sessionClosed( session );
+ }
+
+ private ProtocolEncoder getEncoder( IoSession session ) throws Exception
+ {
+ ProtocolEncoder encoder = ( ProtocolEncoder ) session.getAttribute( ENCODER );
+ if( encoder == null )
+ {
+ encoder = factory.getEncoder();
+ session.setAttribute( ENCODER, encoder );
+ }
+ return encoder;
+ }
+
+ private ProtocolEncoderOutputImpl getEncoderOut( IoSession session, IoFilter.NextFilter nextFilter, IoFilter.WriteRequest writeRequest )
+ {
+ return new ProtocolEncoderOutputImpl( session, nextFilter, writeRequest );
+ }
+
+ private ProtocolDecoder getDecoder( IoSession session ) throws Exception
+ {
+ ProtocolDecoder decoder = ( ProtocolDecoder ) session.getAttribute( DECODER );
+ if( decoder == null )
+ {
+ decoder = factory.getDecoder();
+ session.setAttribute( DECODER, decoder );
+ }
+ return decoder;
+ }
+
+ private ProtocolDecoderOutput getDecoderOut( IoSession session, IoFilter.NextFilter nextFilter )
+ {
+ return new SimpleProtocolDecoderOutput( session, nextFilter );
+ }
+
+ private void disposeEncoder( IoSession session )
+ {
+ ProtocolEncoder encoder = ( ProtocolEncoder ) session.removeAttribute( ENCODER );
+ if( encoder == null )
+ {
+ return;
+ }
+
+ try
+ {
+ encoder.dispose( session );
+ }
+ catch( Throwable t )
+ {
+ SessionLog.warn(
+ session,
+ "Failed to dispose: " + encoder.getClass().getName() +
+ " (" + encoder + ')' );
+ }
+ }
+
+ private void disposeDecoder( IoSession session )
+ {
+ ProtocolDecoder decoder = ( ProtocolDecoder ) session.removeAttribute( DECODER );
+ if( decoder == null )
+ {
+ return;
+ }
+
+ try
+ {
+ decoder.dispose( session );
+ }
+ catch( Throwable t )
+ {
+ SessionLog.warn(
+ session,
+ "Falied to dispose: " + decoder.getClass().getName() +
+ " (" + decoder + ')' );
+ }
+ }
+
+ private static class HiddenByteBuffer extends ByteBufferProxy
+ {
+ private HiddenByteBuffer( ByteBuffer buf )
+ {
+ super( buf );
+ }
+ }
+
+ private static class MessageByteBuffer extends ByteBufferProxy
+ {
+ private final Object message;
+
+ private MessageByteBuffer( Object message )
+ {
+ super( EMPTY_BUFFER );
+ this.message = message;
+ }
+
+ public void acquire()
+ {
+ // no-op since we are wraping a zero-byte buffer, this instance is to just curry the message
+ }
+
+ public void release()
+ {
+ // no-op since we are wraping a zero-byte buffer, this instance is to just curry the message
+ }
+ }
+
+ private static class ProtocolEncoderOutputImpl implements ProtocolEncoderOutput
+ {
+ private ByteBuffer buffer;
+
+ private final IoSession session;
+ private final IoFilter.NextFilter nextFilter;
+ private final IoFilter.WriteRequest writeRequest;
+
+ public ProtocolEncoderOutputImpl( IoSession session, IoFilter.NextFilter nextFilter, IoFilter.WriteRequest writeRequest )
+ {
+ this.session = session;
+ this.nextFilter = nextFilter;
+ this.writeRequest = writeRequest;
+ }
+
+
+
+ public void write( ByteBuffer buf )
+ {
+ if(buffer != null)
+ {
+ flush();
+ }
+ buffer = buf;
+ }
+
+ public void mergeAll()
+ {
+ }
+
+ public WriteFuture flush()
+ {
+ WriteFuture future = null;
+ if( buffer == null )
+ {
+ return null;
+ }
+ else
+ {
+ ByteBuffer buf = buffer;
+ // Flush only when the buffer has remaining.
+ if( buf.hasRemaining() )
+ {
+ future = doFlush( buf );
+ }
+
+ }
+
+ return future;
+ }
+
+
+ protected WriteFuture doFlush( ByteBuffer buf )
+ {
+ WriteFuture future = new DefaultWriteFuture( session );
+ nextFilter.filterWrite(
+ session,
+ new IoFilter.WriteRequest(
+ buf,
+ future, writeRequest.getDestination() ) );
+ return future;
+ }
+ }
+}
+
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java
new file mode 100644
index 0000000000..e5360d32e0
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketAcceptor.java
@@ -0,0 +1,547 @@
+/*
+ * 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 org.apache.mina.transport.socket.nio;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.support.BaseIoAcceptor;
+import org.apache.mina.util.Queue;
+import org.apache.mina.util.NewThreadExecutor;
+import org.apache.mina.util.NamePreservingRunnable;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+
+/**
+ * {@link IoAcceptor} for socket transport (TCP/IP).
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public class MultiThreadSocketAcceptor extends SocketAcceptor
+{
+ /**
+ * @noinspection StaticNonFinalField
+ */
+ private static volatile int nextId = 0;
+
+ private final Executor executor;
+ private final Object lock = new Object();
+ private final int id = nextId ++;
+ private final String threadName = "SocketAcceptor-" + id;
+ private final Map channels = new HashMap();
+
+ private final Queue registerQueue = new Queue();
+ private final Queue cancelQueue = new Queue();
+
+ private final MultiThreadSocketIoProcessor[] ioProcessors;
+ private final int processorCount;
+
+ /**
+ * @noinspection FieldAccessedSynchronizedAndUnsynchronized
+ */
+ private Selector selector;
+ private Worker worker;
+ private int processorDistributor = 0;
+
+ /**
+ * Create an acceptor with a single processing thread using a NewThreadExecutor
+ */
+ public MultiThreadSocketAcceptor()
+ {
+ this( 1, new NewThreadExecutor() );
+ }
+
+ /**
+ * Create an acceptor with the desired number of processing threads
+ *
+ * @param processorCount Number of processing threads
+ * @param executor Executor to use for launching threads
+ */
+ public MultiThreadSocketAcceptor( int processorCount, Executor executor )
+ {
+ if( processorCount < 1 )
+ {
+ throw new IllegalArgumentException( "Must have at least one processor" );
+ }
+
+ this.executor = executor;
+ this.processorCount = processorCount;
+ ioProcessors = new MultiThreadSocketIoProcessor[processorCount];
+
+ for( int i = 0; i < processorCount; i++ )
+ {
+ ioProcessors[i] = new MultiThreadSocketIoProcessor( "SocketAcceptorIoProcessor-" + id + "." + i, executor );
+ }
+ }
+
+
+ /**
+ * Binds to the specified <code>address</code> and handles incoming connections with the specified
+ * <code>handler</code>. Backlog value is configured to the value of <code>backlog</code> property.
+ *
+ * @throws IOException if failed to bind
+ */
+ public void bind( SocketAddress address, IoHandler handler, IoServiceConfig config ) throws IOException
+ {
+ if( handler == null )
+ {
+ throw new NullPointerException( "handler" );
+ }
+
+ if( address != null && !( address instanceof InetSocketAddress ) )
+ {
+ throw new IllegalArgumentException( "Unexpected address type: " + address.getClass() );
+ }
+
+ if( config == null )
+ {
+ config = getDefaultConfig();
+ }
+
+ RegistrationRequest request = new RegistrationRequest( address, handler, config );
+
+ synchronized( registerQueue )
+ {
+ registerQueue.push( request );
+ }
+
+ startupWorker();
+
+ selector.wakeup();
+
+ synchronized( request )
+ {
+ while( !request.done )
+ {
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+ }
+ }
+ }
+
+ if( request.exception != null )
+ {
+ throw request.exception;
+ }
+ }
+
+
+ private synchronized void startupWorker() throws IOException
+ {
+ synchronized( lock )
+ {
+ if( worker == null )
+ {
+ selector = Selector.open();
+ worker = new Worker();
+
+ executor.execute( new NamePreservingRunnable( worker ) );
+ }
+ }
+ }
+
+ public void unbind( SocketAddress address )
+ {
+ if( address == null )
+ {
+ throw new NullPointerException( "address" );
+ }
+
+ CancellationRequest request = new CancellationRequest( address );
+
+ try
+ {
+ startupWorker();
+ }
+ catch( IOException e )
+ {
+ // IOException is thrown only when Worker thread is not
+ // running and failed to open a selector. We simply throw
+ // IllegalArgumentException here because we can simply
+ // conclude that nothing is bound to the selector.
+ throw new IllegalArgumentException( "Address not bound: " + address );
+ }
+
+ synchronized( cancelQueue )
+ {
+ cancelQueue.push( request );
+ }
+
+ selector.wakeup();
+
+ synchronized( request )
+ {
+ while( !request.done )
+ {
+ try
+ {
+ request.wait();
+ }
+ catch( InterruptedException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+ }
+ }
+ }
+
+ if( request.exception != null )
+ {
+ request.exception.fillInStackTrace();
+
+ throw request.exception;
+ }
+ }
+
+
+ private class Worker implements Runnable
+ {
+ public void run()
+ {
+ Thread.currentThread().setName(MultiThreadSocketAcceptor.this.threadName );
+
+ for( ; ; )
+ {
+ try
+ {
+ int nKeys = selector.select();
+
+ registerNew();
+
+ if( nKeys > 0 )
+ {
+ processSessions( selector.selectedKeys() );
+ }
+
+ cancelKeys();
+
+ if( selector.keys().isEmpty() )
+ {
+ synchronized( lock )
+ {
+ if( selector.keys().isEmpty() &&
+ registerQueue.isEmpty() &&
+ cancelQueue.isEmpty() )
+ {
+ worker = null;
+ try
+ {
+ selector.close();
+ }
+ catch( IOException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+ }
+ finally
+ {
+ selector = null;
+ }
+ break;
+ }
+ }
+ }
+ }
+ catch( IOException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+
+ try
+ {
+ Thread.sleep( 1000 );
+ }
+ catch( InterruptedException e1 )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e1 );
+ }
+ }
+ }
+ }
+
+ private void processSessions( Set keys ) throws IOException
+ {
+ Iterator it = keys.iterator();
+ while( it.hasNext() )
+ {
+ SelectionKey key = ( SelectionKey ) it.next();
+
+ it.remove();
+
+ if( !key.isAcceptable() )
+ {
+ continue;
+ }
+
+ ServerSocketChannel ssc = ( ServerSocketChannel ) key.channel();
+
+ SocketChannel ch = ssc.accept();
+
+ if( ch == null )
+ {
+ continue;
+ }
+
+ boolean success = false;
+ try
+ {
+
+ RegistrationRequest req = ( RegistrationRequest ) key.attachment();
+
+ MultiThreadSocketSessionImpl session = new MultiThreadSocketSessionImpl(
+ MultiThreadSocketAcceptor.this, nextProcessor(), getListeners(),
+ req.config, ch, req.handler, req.address );
+
+ // New Interface
+// SocketSessionImpl session = new SocketSessionImpl(
+// SocketAcceptor.this, nextProcessor(), getListeners(),
+// req.config, ch, req.handler, req.address );
+
+
+ getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
+ req.config.getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
+ req.config.getThreadModel().buildFilterChain( session.getFilterChain() );
+ session.getIoProcessor().addNew( session );
+ success = true;
+ }
+ catch( Throwable t )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( t );
+ }
+ finally
+ {
+ if( !success )
+ {
+ ch.close();
+ }
+ }
+ }
+ }
+ }
+
+ private MultiThreadSocketIoProcessor nextProcessor()
+ {
+ return ioProcessors[processorDistributor++ % processorCount];
+ }
+
+
+ private void registerNew()
+ {
+ if( registerQueue.isEmpty() )
+ {
+ return;
+ }
+
+ for( ; ; )
+ {
+ RegistrationRequest req;
+
+ synchronized( registerQueue )
+ {
+ req = ( RegistrationRequest ) registerQueue.pop();
+ }
+
+ if( req == null )
+ {
+ break;
+ }
+
+ ServerSocketChannel ssc = null;
+
+ try
+ {
+ ssc = ServerSocketChannel.open();
+ ssc.configureBlocking( false );
+
+ // Configure the server socket,
+ SocketAcceptorConfig cfg;
+ if( req.config instanceof SocketAcceptorConfig )
+ {
+ cfg = ( SocketAcceptorConfig ) req.config;
+ }
+ else
+ {
+ cfg = ( SocketAcceptorConfig ) getDefaultConfig();
+ }
+
+ ssc.socket().setReuseAddress( cfg.isReuseAddress() );
+ ssc.socket().setReceiveBufferSize(
+ ( ( SocketSessionConfig ) cfg.getSessionConfig() ).getReceiveBufferSize() );
+
+ // and bind.
+ ssc.socket().bind( req.address, cfg.getBacklog() );
+ if( req.address == null || req.address.getPort() == 0 )
+ {
+ req.address = ( InetSocketAddress ) ssc.socket().getLocalSocketAddress();
+ }
+ ssc.register( selector, SelectionKey.OP_ACCEPT, req );
+
+ synchronized( channels )
+ {
+ channels.put( req.address, ssc );
+ }
+
+ getListeners().fireServiceActivated(
+ this, req.address, req.handler, req.config );
+ }
+ catch( IOException e )
+ {
+ req.exception = e;
+ }
+ finally
+ {
+ synchronized( req )
+ {
+ req.done = true;
+
+ req.notifyAll();
+ }
+
+ if( ssc != null && req.exception != null )
+ {
+ try
+ {
+ ssc.close();
+ }
+ catch( IOException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+ }
+ }
+ }
+ }
+ }
+
+
+ private void cancelKeys()
+ {
+ if( cancelQueue.isEmpty() )
+ {
+ return;
+ }
+
+ for( ; ; )
+ {
+ CancellationRequest request;
+
+ synchronized( cancelQueue )
+ {
+ request = ( CancellationRequest ) cancelQueue.pop();
+ }
+
+ if( request == null )
+ {
+ break;
+ }
+
+ ServerSocketChannel ssc;
+ synchronized( channels )
+ {
+ ssc = ( ServerSocketChannel ) channels.remove( request.address );
+ }
+
+ // close the channel
+ try
+ {
+ if( ssc == null )
+ {
+ request.exception = new IllegalArgumentException( "Address not bound: " + request.address );
+ }
+ else
+ {
+ SelectionKey key = ssc.keyFor( selector );
+ request.registrationRequest = ( RegistrationRequest ) key.attachment();
+ key.cancel();
+
+ selector.wakeup(); // wake up again to trigger thread death
+
+ ssc.close();
+ }
+ }
+ catch( IOException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( e );
+ }
+ finally
+ {
+ synchronized( request )
+ {
+ request.done = true;
+ request.notifyAll();
+ }
+
+ if( request.exception == null )
+ {
+ getListeners().fireServiceDeactivated(
+ this, request.address,
+ request.registrationRequest.handler,
+ request.registrationRequest.config );
+ }
+ }
+ }
+ }
+
+ private static class RegistrationRequest
+ {
+ private InetSocketAddress address;
+ private final IoHandler handler;
+ private final IoServiceConfig config;
+ private IOException exception;
+ private boolean done;
+
+ private RegistrationRequest( SocketAddress address, IoHandler handler, IoServiceConfig config )
+ {
+ this.address = ( InetSocketAddress ) address;
+ this.handler = handler;
+ this.config = config;
+ }
+ }
+
+
+ private static class CancellationRequest
+ {
+ private final SocketAddress address;
+ private boolean done;
+ private RegistrationRequest registrationRequest;
+ private RuntimeException exception;
+
+ private CancellationRequest( SocketAddress address )
+ {
+ this.address = address;
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java
new file mode 100644
index 0000000000..7344f70078
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketConnector.java
@@ -0,0 +1,486 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.mina.transport.socket.nio;
+
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoConnectorConfig;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
+import org.apache.mina.common.support.DefaultConnectFuture;
+import org.apache.mina.util.NamePreservingRunnable;
+import org.apache.mina.util.NewThreadExecutor;
+import org.apache.mina.util.Queue;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * {@link IoConnector} for socket transport (TCP/IP).
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public class MultiThreadSocketConnector extends SocketConnector
+{
+ /** @noinspection StaticNonFinalField */
+ private static volatile int nextId = 0;
+
+ private final Object lock = new Object();
+ private final int id = nextId++;
+ private final String threadName = "SocketConnector-" + id;
+
+ private final Queue connectQueue = new Queue();
+ private final MultiThreadSocketIoProcessor[] ioProcessors;
+ private final int processorCount;
+ private final Executor executor;
+
+ /** @noinspection FieldAccessedSynchronizedAndUnsynchronized */
+ private Selector selector;
+ private Worker worker;
+ private int processorDistributor = 0;
+ private int workerTimeout = 60; // 1 min.
+
+ /** Create a connector with a single processing thread using a NewThreadExecutor */
+ public MultiThreadSocketConnector()
+ {
+ this(1, new NewThreadExecutor());
+ }
+
+ /**
+ * Create a connector with the desired number of processing threads
+ *
+ * @param processorCount Number of processing threads
+ * @param executor Executor to use for launching threads
+ */
+ public MultiThreadSocketConnector(int processorCount, Executor executor)
+ {
+ if (processorCount < 1)
+ {
+ throw new IllegalArgumentException("Must have at least one processor");
+ }
+
+ this.executor = executor;
+ this.processorCount = processorCount;
+ ioProcessors = new MultiThreadSocketIoProcessor[processorCount];
+
+ for (int i = 0; i < processorCount; i++)
+ {
+ ioProcessors[i] = new MultiThreadSocketIoProcessor("SocketConnectorIoProcessor-" + id + "." + i, executor);
+ }
+ }
+
+ /**
+ * How many seconds to keep the connection thread alive between connection requests
+ *
+ * @return Number of seconds to keep connection thread alive
+ */
+ public int getWorkerTimeout()
+ {
+ return workerTimeout;
+ }
+
+ /**
+ * Set how many seconds the connection worker thread should remain alive once idle before terminating itself.
+ *
+ * @param workerTimeout Number of seconds to keep thread alive. Must be >=0
+ */
+ public void setWorkerTimeout(int workerTimeout)
+ {
+ if (workerTimeout < 0)
+ {
+ throw new IllegalArgumentException("Must be >= 0");
+ }
+ this.workerTimeout = workerTimeout;
+ }
+
+ public ConnectFuture connect(SocketAddress address, IoHandler handler, IoServiceConfig config)
+ {
+ return connect(address, null, handler, config);
+ }
+
+ public ConnectFuture connect(SocketAddress address, SocketAddress localAddress,
+ IoHandler handler, IoServiceConfig config)
+ {
+ if (address == null)
+ {
+ throw new NullPointerException("address");
+ }
+ if (handler == null)
+ {
+ throw new NullPointerException("handler");
+ }
+
+ if (!(address instanceof InetSocketAddress))
+ {
+ throw new IllegalArgumentException("Unexpected address type: "
+ + address.getClass());
+ }
+
+ if (localAddress != null && !(localAddress instanceof InetSocketAddress))
+ {
+ throw new IllegalArgumentException("Unexpected local address type: "
+ + localAddress.getClass());
+ }
+
+ if (config == null)
+ {
+ config = getDefaultConfig();
+ }
+
+ SocketChannel ch = null;
+ boolean success = false;
+ try
+ {
+ ch = SocketChannel.open();
+ ch.socket().setReuseAddress(true);
+ if (localAddress != null)
+ {
+ ch.socket().bind(localAddress);
+ }
+
+ ch.configureBlocking(false);
+
+ if (ch.connect(address))
+ {
+ DefaultConnectFuture future = new DefaultConnectFuture();
+ newSession(ch, handler, config, future);
+ success = true;
+ return future;
+ }
+
+ success = true;
+ }
+ catch (IOException e)
+ {
+ return DefaultConnectFuture.newFailedFuture(e);
+ }
+ finally
+ {
+ if (!success && ch != null)
+ {
+ try
+ {
+ ch.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ }
+ }
+
+ ConnectionRequest request = new ConnectionRequest(ch, handler, config);
+ synchronized (lock)
+ {
+ try
+ {
+ startupWorker();
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ ch.close();
+ }
+ catch (IOException e2)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e2);
+ }
+
+ return DefaultConnectFuture.newFailedFuture(e);
+ }
+ }
+
+ synchronized (connectQueue)
+ {
+ connectQueue.push(request);
+ }
+ selector.wakeup();
+
+ return request;
+ }
+
+ private synchronized void startupWorker() throws IOException
+ {
+ if (worker == null)
+ {
+ selector = Selector.open();
+ worker = new Worker();
+ executor.execute(new NamePreservingRunnable(worker));
+ }
+ }
+
+ private void registerNew()
+ {
+ if (connectQueue.isEmpty())
+ {
+ return;
+ }
+
+ for (; ;)
+ {
+ ConnectionRequest req;
+ synchronized (connectQueue)
+ {
+ req = (ConnectionRequest) connectQueue.pop();
+ }
+
+ if (req == null)
+ {
+ break;
+ }
+
+ SocketChannel ch = req.channel;
+ try
+ {
+ ch.register(selector, SelectionKey.OP_CONNECT, req);
+ }
+ catch (IOException e)
+ {
+ req.setException(e);
+ }
+ }
+ }
+
+ private void processSessions(Set keys)
+ {
+ Iterator it = keys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+
+ if (!key.isConnectable())
+ {
+ continue;
+ }
+
+ SocketChannel ch = (SocketChannel) key.channel();
+ ConnectionRequest entry = (ConnectionRequest) key.attachment();
+
+ boolean success = false;
+ try
+ {
+ ch.finishConnect();
+ newSession(ch, entry.handler, entry.config, entry);
+ success = true;
+ }
+ catch (Throwable e)
+ {
+ entry.setException(e);
+ }
+ finally
+ {
+ key.cancel();
+ if (!success)
+ {
+ try
+ {
+ ch.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ }
+ }
+ }
+
+ keys.clear();
+ }
+
+ private void processTimedOutSessions(Set keys)
+ {
+ long currentTime = System.currentTimeMillis();
+ Iterator it = keys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+
+ if (!key.isValid())
+ {
+ continue;
+ }
+
+ ConnectionRequest entry = (ConnectionRequest) key.attachment();
+
+ if (currentTime >= entry.deadline)
+ {
+ entry.setException(new ConnectException());
+ try
+ {
+ key.channel().close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ key.cancel();
+ }
+ }
+ }
+ }
+
+ private void newSession(SocketChannel ch, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture)
+ throws IOException
+ {
+ MultiThreadSocketSessionImpl session =
+ new MultiThreadSocketSessionImpl(this, nextProcessor(), getListeners(),
+ config, ch, handler, ch.socket().getRemoteSocketAddress());
+
+ //new interface
+// SocketSessionImpl session = new SocketSessionImpl(
+// this, nextProcessor(), getListeners(),
+// config, ch, handler, ch.socket().getRemoteSocketAddress() );
+ try
+ {
+ getFilterChainBuilder().buildFilterChain(session.getFilterChain());
+ config.getFilterChainBuilder().buildFilterChain(session.getFilterChain());
+ config.getThreadModel().buildFilterChain(session.getFilterChain());
+ }
+ catch (Throwable e)
+ {
+ throw (IOException) new IOException("Failed to create a session.").initCause(e);
+ }
+
+ // Set the ConnectFuture of the specified session, which will be
+ // removed and notified by AbstractIoFilterChain eventually.
+ session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, connectFuture );
+
+ // Forward the remaining process to the SocketIoProcessor.
+ session.getIoProcessor().addNew(session);
+ }
+
+ private MultiThreadSocketIoProcessor nextProcessor()
+ {
+ return ioProcessors[processorDistributor++ % processorCount];
+ }
+
+ private class Worker implements Runnable
+ {
+ private long lastActive = System.currentTimeMillis();
+
+ public void run()
+ {
+ Thread.currentThread().setName(MultiThreadSocketConnector.this.threadName);
+
+ for (; ;)
+ {
+ try
+ {
+ int nKeys = selector.select(1000);
+
+ registerNew();
+
+ if (nKeys > 0)
+ {
+ processSessions(selector.selectedKeys());
+ }
+
+ processTimedOutSessions(selector.keys());
+
+ if (selector.keys().isEmpty())
+ {
+ if (System.currentTimeMillis() - lastActive > workerTimeout * 1000L)
+ {
+ synchronized (lock)
+ {
+ if (selector.keys().isEmpty() &&
+ connectQueue.isEmpty())
+ {
+ worker = null;
+ try
+ {
+ selector.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ selector = null;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ lastActive = System.currentTimeMillis();
+ }
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e1)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e1);
+ }
+ }
+ }
+ }
+ }
+
+ private class ConnectionRequest extends DefaultConnectFuture
+ {
+ private final SocketChannel channel;
+ private final long deadline;
+ private final IoHandler handler;
+ private final IoServiceConfig config;
+
+ private ConnectionRequest(SocketChannel channel, IoHandler handler, IoServiceConfig config)
+ {
+ this.channel = channel;
+ long timeout;
+ if (config instanceof IoConnectorConfig)
+ {
+ timeout = ((IoConnectorConfig) config).getConnectTimeoutMillis();
+ }
+ else
+ {
+ timeout = ((IoConnectorConfig) getDefaultConfig()).getConnectTimeoutMillis();
+ }
+ this.deadline = System.currentTimeMillis() + timeout;
+ this.handler = handler;
+ this.config = config;
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java
new file mode 100644
index 0000000000..67b8c8d820
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketFilterChain.java
@@ -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.
+ *
+ */
+package org.apache.mina.transport.socket.nio;
+
+import java.io.IOException;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoFilter.WriteRequest;
+import org.apache.mina.common.support.AbstractIoFilterChain;
+import org.apache.mina.util.Queue;
+
+/**
+ * An {@link IoFilterChain} for socket transport (TCP/IP).
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+class MultiThreadSocketFilterChain extends AbstractIoFilterChain {
+
+ MultiThreadSocketFilterChain( IoSession parent )
+ {
+ super( parent );
+ }
+
+ protected void doWrite( IoSession session, WriteRequest writeRequest )
+ {
+ MultiThreadSocketSessionImpl s = (MultiThreadSocketSessionImpl) session;
+ Queue writeRequestQueue = s.getWriteRequestQueue();
+
+ // SocketIoProcessor.doFlush() will reset it after write is finished
+ // because the buffer will be passed with messageSent event.
+ ( ( ByteBuffer ) writeRequest.getMessage() ).mark();
+ synchronized( writeRequestQueue )
+ {
+ writeRequestQueue.push( writeRequest );
+ if( writeRequestQueue.size() == 1 && session.getTrafficMask().isWritable() )
+ {
+ // Notify SocketIoProcessor only when writeRequestQueue was empty.
+ s.getIoProcessor().flush( s );
+ }
+ }
+ }
+
+ protected void doClose( IoSession session ) throws IOException
+ {
+ MultiThreadSocketSessionImpl s = (MultiThreadSocketSessionImpl) session;
+ s.getIoProcessor().remove( s );
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java
new file mode 100644
index 0000000000..c23ad8686f
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketIoProcessor.java
@@ -0,0 +1,1026 @@
+/*
+ * 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 org.apache.mina.transport.socket.nio;
+
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
+import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoFilter.WriteRequest;
+import org.apache.mina.common.WriteTimeoutException;
+import org.apache.mina.util.IdentityHashSet;
+import org.apache.mina.util.NamePreservingRunnable;
+import org.apache.mina.util.Queue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Performs all I/O operations for sockets which is connected or bound. This class is used by MINA internally.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $,
+ */
+class MultiThreadSocketIoProcessor extends SocketIoProcessor
+{
+ Logger _logger = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class);
+ Logger _loggerRead = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class + ".Reader");
+ Logger _loggerWrite = LoggerFactory.getLogger(MultiThreadSocketIoProcessor.class + ".Writer");
+
+ private static final long SELECTOR_TIMEOUT = 1000L;
+
+ private int MAX_READ_BYTES_PER_SESSION = 524288; //512K
+ private int MAX_FLUSH_BYTES_PER_SESSION = 524288; //512K
+
+ private final Object readLock = new Object();
+ private final Object writeLock = new Object();
+
+ private final String threadName;
+ private final Executor executor;
+
+ private ReentrantLock trafficMaskUpdateLock = new ReentrantLock();
+
+ /** @noinspection FieldAccessedSynchronizedAndUnsynchronized */
+ private volatile Selector selector, writeSelector;
+
+ private final Queue newSessions = new Queue();
+ private final Queue removingSessions = new Queue();
+ private final BlockingQueue flushingSessions = new LinkedBlockingQueue();
+ private final IdentityHashSet flushingSessionsSet = new IdentityHashSet();
+
+ private final Queue trafficControllingSessions = new Queue();
+
+ private ReadWorker readWorker;
+ private WriteWorker writeWorker;
+ private long lastIdleReadCheckTime = System.currentTimeMillis();
+ private long lastIdleWriteCheckTime = System.currentTimeMillis();
+
+ MultiThreadSocketIoProcessor(String threadName, Executor executor)
+ {
+ super(threadName, executor);
+ this.threadName = threadName;
+ this.executor = executor;
+ }
+
+ void addNew(SocketSessionImpl session) throws IOException
+ {
+ synchronized (newSessions)
+ {
+ newSessions.push(session);
+ }
+
+ startupWorker();
+
+ selector.wakeup();
+ writeSelector.wakeup();
+ }
+
+ void remove(SocketSessionImpl session) throws IOException
+ {
+ scheduleRemove(session);
+ startupWorker();
+ selector.wakeup();
+ }
+
+ private void startupWorker() throws IOException
+ {
+ synchronized (readLock)
+ {
+ if (readWorker == null)
+ {
+ selector = Selector.open();
+ readWorker = new ReadWorker();
+ executor.execute(new NamePreservingRunnable(readWorker));
+ }
+ }
+
+ synchronized (writeLock)
+ {
+ if (writeWorker == null)
+ {
+ writeSelector = Selector.open();
+ writeWorker = new WriteWorker();
+ executor.execute(new NamePreservingRunnable(writeWorker));
+ }
+ }
+
+ }
+
+ void flush(SocketSessionImpl session)
+ {
+ scheduleFlush(session);
+ Selector selector = this.writeSelector;
+
+ if (selector != null)
+ {
+ selector.wakeup();
+ }
+ }
+
+ void updateTrafficMask(SocketSessionImpl session)
+ {
+ scheduleTrafficControl(session);
+ Selector selector = this.selector;
+ if (selector != null)
+ {
+ selector.wakeup();
+ }
+ }
+
+ private void scheduleRemove(SocketSessionImpl session)
+ {
+ synchronized (removingSessions)
+ {
+ removingSessions.push(session);
+ }
+ }
+
+ private void scheduleFlush(SocketSessionImpl session)
+ {
+ synchronized (flushingSessionsSet)
+ {
+ //if flushingSessions grows to contain Integer.MAX_VALUE sessions
+ // then this will fail.
+ if (flushingSessionsSet.add(session))
+ {
+ flushingSessions.offer(session);
+ }
+ }
+ }
+
+ private void scheduleTrafficControl(SocketSessionImpl session)
+ {
+ synchronized (trafficControllingSessions)
+ {
+ trafficControllingSessions.push(session);
+ }
+ }
+
+ private void doAddNewReader() throws InterruptedException
+ {
+ if (newSessions.isEmpty())
+ {
+ return;
+ }
+
+ for (; ;)
+ {
+ MultiThreadSocketSessionImpl session;
+
+ synchronized (newSessions)
+ {
+ session = (MultiThreadSocketSessionImpl) newSessions.peek();
+ }
+
+ if (session == null)
+ {
+ break;
+ }
+
+ SocketChannel ch = session.getChannel();
+
+
+ try
+ {
+
+ ch.configureBlocking(false);
+ session.setSelectionKey(ch.register(selector,
+ SelectionKey.OP_READ,
+ session));
+
+ //System.out.println("ReadDebug:"+"Awaiting Registration");
+ session.awaitRegistration();
+ sessionCreated(session);
+ }
+ catch (IOException e)
+ {
+ // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute
+ // and call ConnectFuture.setException().
+ session.getFilterChain().fireExceptionCaught(session, e);
+ }
+ }
+ }
+
+
+ private void doAddNewWrite() throws InterruptedException
+ {
+ if (newSessions.isEmpty())
+ {
+ return;
+ }
+
+ for (; ;)
+ {
+ MultiThreadSocketSessionImpl session;
+
+ synchronized (newSessions)
+ {
+ session = (MultiThreadSocketSessionImpl) newSessions.peek();
+ }
+
+ if (session == null)
+ {
+ break;
+ }
+
+ SocketChannel ch = session.getChannel();
+
+ try
+ {
+ ch.configureBlocking(false);
+ synchronized (flushingSessionsSet)
+ {
+ flushingSessionsSet.add(session);
+ }
+
+ session.setWriteSelectionKey(ch.register(writeSelector,
+ SelectionKey.OP_WRITE,
+ session));
+
+ //System.out.println("WriteDebug:"+"Awaiting Registration");
+ session.awaitRegistration();
+ sessionCreated(session);
+ }
+ catch (IOException e)
+ {
+
+ // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute
+ // and call ConnectFuture.setException().
+ session.getFilterChain().fireExceptionCaught(session, e);
+ }
+ }
+ }
+
+
+ private void sessionCreated(SocketSessionImpl sessionParam) throws InterruptedException
+ {
+ MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) sessionParam;
+ synchronized (newSessions)
+ {
+ if (!session.created())
+ {
+ _logger.debug("Popping new session");
+ newSessions.pop();
+
+ // AbstractIoFilterChain.CONNECT_FUTURE is cleared inside here
+ // in AbstractIoFilterChain.fireSessionOpened().
+ session.getServiceListeners().fireSessionCreated(session);
+
+ session.doneCreation();
+ }
+ }
+ }
+
+ private void doRemove()
+ {
+ if (removingSessions.isEmpty())
+ {
+ return;
+ }
+
+ for (; ;)
+ {
+ MultiThreadSocketSessionImpl session;
+
+ synchronized (removingSessions)
+ {
+ session = (MultiThreadSocketSessionImpl) removingSessions.pop();
+ }
+
+ if (session == null)
+ {
+ break;
+ }
+
+ SocketChannel ch = session.getChannel();
+ SelectionKey key = session.getReadSelectionKey();
+ SelectionKey writeKey = session.getWriteSelectionKey();
+
+ // Retry later if session is not yet fully initialized.
+ // (In case that Session.close() is called before addSession() is processed)
+ if (key == null || writeKey == null)
+ {
+ scheduleRemove(session);
+ break;
+ }
+ // skip if channel is already closed
+ if (!key.isValid() || !writeKey.isValid())
+ {
+ continue;
+ }
+
+ try
+ {
+ //System.out.println("ReadDebug:"+"Removing Session: " + System.identityHashCode(session));
+ synchronized (readLock)
+ {
+ key.cancel();
+ }
+ synchronized (writeLock)
+ {
+ writeKey.cancel();
+ }
+ ch.close();
+ }
+ catch (IOException e)
+ {
+ session.getFilterChain().fireExceptionCaught(session, e);
+ }
+ finally
+ {
+ releaseWriteBuffers(session);
+ session.getServiceListeners().fireSessionDestroyed(session);
+ }
+ }
+ }
+
+ private void processRead(Set selectedKeys)
+ {
+ Iterator it = selectedKeys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+ MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) key.attachment();
+
+ synchronized (readLock)
+ {
+ if (key.isValid() && key.isReadable() && session.getTrafficMask().isReadable())
+ {
+ read(session);
+ }
+ }
+
+ }
+
+ selectedKeys.clear();
+ }
+
+ private void processWrite(Set selectedKeys)
+ {
+ Iterator it = selectedKeys.iterator();
+
+ while (it.hasNext())
+ {
+ SelectionKey key = (SelectionKey) it.next();
+ SocketSessionImpl session = (SocketSessionImpl) key.attachment();
+
+ synchronized (writeLock)
+ {
+ if (key.isValid() && key.isWritable() && session.getTrafficMask().isWritable())
+ {
+
+ // Clear OP_WRITE
+ key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
+
+ synchronized (flushingSessionsSet)
+ {
+ flushingSessions.offer(session);
+ }
+ }
+ }
+ }
+
+ selectedKeys.clear();
+ }
+
+ private void read(SocketSessionImpl session)
+ {
+
+ //if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Starting read for Session:" + System.identityHashCode(session));
+ }
+
+ int totalReadBytes = 0;
+
+ while (totalReadBytes <= MAX_READ_BYTES_PER_SESSION)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(session.getReadBufferSize());
+ SocketChannel ch = session.getChannel();
+
+ try
+ {
+ buf.clear();
+
+ int readBytes = 0;
+ int ret;
+
+ try
+ {
+ while ((ret = ch.read(buf.buf())) > 0)
+ {
+ readBytes += ret;
+ totalReadBytes += ret;
+ }
+ }
+ finally
+ {
+ buf.flip();
+ }
+
+
+ if (readBytes > 0)
+ {
+ session.increaseReadBytes(readBytes);
+
+ session.getFilterChain().fireMessageReceived(session, buf);
+ buf = null;
+ }
+
+ if (ret <= 0)
+ {
+ if (ret == 0)
+ {
+ if (readBytes == session.getReadBufferSize())
+ {
+ continue;
+ }
+ }
+ else
+ {
+ scheduleRemove(session);
+ }
+
+ break;
+ }
+ }
+ catch (Throwable e)
+ {
+ if (e instanceof IOException)
+ {
+ scheduleRemove(session);
+ }
+ session.getFilterChain().fireExceptionCaught(session, e);
+
+ //Stop Reading this session.
+ return;
+ }
+ finally
+ {
+ if (buf != null)
+ {
+ buf.release();
+ }
+ }
+ }//for
+
+ // if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Read for Session:" + System.identityHashCode(session) + " got: " + totalReadBytes);
+ }
+ }
+
+
+ private void notifyReadIdleness()
+ {
+ // process idle sessions
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - lastIdleReadCheckTime) >= 1000)
+ {
+ lastIdleReadCheckTime = currentTime;
+ Set keys = selector.keys();
+ if (keys != null)
+ {
+ for (Iterator it = keys.iterator(); it.hasNext();)
+ {
+ SelectionKey key = (SelectionKey) it.next();
+ SocketSessionImpl session = (SocketSessionImpl) key.attachment();
+ notifyReadIdleness(session, currentTime);
+ }
+ }
+ }
+ }
+
+ private void notifyWriteIdleness()
+ {
+ // process idle sessions
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - lastIdleWriteCheckTime) >= 1000)
+ {
+ lastIdleWriteCheckTime = currentTime;
+ Set keys = writeSelector.keys();
+ if (keys != null)
+ {
+ for (Iterator it = keys.iterator(); it.hasNext();)
+ {
+ SelectionKey key = (SelectionKey) it.next();
+ SocketSessionImpl session = (SocketSessionImpl) key.attachment();
+ notifyWriteIdleness(session, currentTime);
+ }
+ }
+ }
+ }
+
+ private void notifyReadIdleness(SocketSessionImpl session, long currentTime)
+ {
+ notifyIdleness0(
+ session, currentTime,
+ session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE),
+ IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleness0(
+ session, currentTime,
+ session.getIdleTimeInMillis(IdleStatus.READER_IDLE),
+ IdleStatus.READER_IDLE,
+ Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE)));
+
+ notifyWriteTimeout(session, currentTime, session
+ .getWriteTimeoutInMillis(), session.getLastWriteTime());
+ }
+
+ private void notifyWriteIdleness(SocketSessionImpl session, long currentTime)
+ {
+ notifyIdleness0(
+ session, currentTime,
+ session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE),
+ IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleness0(
+ session, currentTime,
+ session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE),
+ IdleStatus.WRITER_IDLE,
+ Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE)));
+
+ notifyWriteTimeout(session, currentTime, session
+ .getWriteTimeoutInMillis(), session.getLastWriteTime());
+ }
+
+ private void notifyIdleness0(SocketSessionImpl session, long currentTime,
+ long idleTime, IdleStatus status,
+ long lastIoTime)
+ {
+ if (idleTime > 0 && lastIoTime != 0
+ && (currentTime - lastIoTime) >= idleTime)
+ {
+ session.increaseIdleCount(status);
+ session.getFilterChain().fireSessionIdle(session, status);
+ }
+ }
+
+ private void notifyWriteTimeout(SocketSessionImpl session,
+ long currentTime,
+ long writeTimeout, long lastIoTime)
+ {
+
+ MultiThreadSocketSessionImpl sesh = (MultiThreadSocketSessionImpl) session;
+ SelectionKey key = sesh.getWriteSelectionKey();
+
+ synchronized (writeLock)
+ {
+ if (writeTimeout > 0
+ && (currentTime - lastIoTime) >= writeTimeout
+ && key != null && key.isValid()
+ && (key.interestOps() & SelectionKey.OP_WRITE) != 0)
+ {
+ session.getFilterChain().fireExceptionCaught(session, new WriteTimeoutException());
+ }
+ }
+ }
+
+ private SocketSessionImpl getNextFlushingSession()
+ {
+ return (SocketSessionImpl) flushingSessions.poll();
+ }
+
+ private void releaseSession(SocketSessionImpl session)
+ {
+ synchronized (session.getWriteRequestQueue())
+ {
+ synchronized (flushingSessionsSet)
+ {
+ if (session.getScheduledWriteRequests() > 0)
+ {
+ if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Reflush" + System.identityHashCode(session));
+ }
+ flushingSessions.offer(session);
+ }
+ else
+ {
+ if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Releasing session " + System.identityHashCode(session));
+ }
+ flushingSessionsSet.remove(session);
+ }
+ }
+ }
+ }
+
+ private void releaseWriteBuffers(SocketSessionImpl session)
+ {
+ Queue writeRequestQueue = session.getWriteRequestQueue();
+ WriteRequest req;
+
+ //Should this be synchronized?
+ synchronized (writeRequestQueue)
+ {
+ while ((req = (WriteRequest) writeRequestQueue.pop()) != null)
+ {
+ try
+ {
+ ((ByteBuffer) req.getMessage()).release();
+ }
+ catch (IllegalStateException e)
+ {
+ session.getFilterChain().fireExceptionCaught(session, e);
+ }
+ finally
+ {
+ req.getFuture().setWritten(false);
+ }
+ }
+ }
+ }
+
+ private void doFlush()
+ {
+ MultiThreadSocketSessionImpl session;
+
+ while ((session = (MultiThreadSocketSessionImpl) getNextFlushingSession()) != null)
+ {
+ if (!session.isConnected())
+ {
+ releaseWriteBuffers(session);
+ releaseSession(session);
+ continue;
+ }
+
+ SelectionKey key = session.getWriteSelectionKey();
+ // Retry later if session is not yet fully initialized.
+ // (In case that Session.write() is called before addSession() is processed)
+ if (key == null)
+ {
+ scheduleFlush(session);
+ releaseSession(session);
+ continue;
+ }
+ // skip if channel is already closed
+ if (!key.isValid())
+ {
+ releaseSession(session);
+ continue;
+ }
+
+ try
+ {
+ if (doFlush(session))
+ {
+ releaseSession(session);
+ }
+ }
+ catch (IOException e)
+ {
+ releaseSession(session);
+ scheduleRemove(session);
+ session.getFilterChain().fireExceptionCaught(session, e);
+ }
+
+ }
+
+ }
+
+ private boolean doFlush(SocketSessionImpl sessionParam) throws IOException
+ {
+ MultiThreadSocketSessionImpl session = (MultiThreadSocketSessionImpl) sessionParam;
+ // Clear OP_WRITE
+ SelectionKey key = session.getWriteSelectionKey();
+ synchronized (writeLock)
+ {
+ key.interestOps(key.interestOps() & (~SelectionKey.OP_WRITE));
+ }
+ SocketChannel ch = session.getChannel();
+ Queue writeRequestQueue = session.getWriteRequestQueue();
+
+ long totalFlushedBytes = 0;
+ while (true)
+ {
+ WriteRequest req;
+
+ synchronized (writeRequestQueue)
+ {
+ req = (WriteRequest) writeRequestQueue.first();
+ }
+
+ if (req == null)
+ {
+ break;
+ }
+
+ ByteBuffer buf = (ByteBuffer) req.getMessage();
+ if (buf.remaining() == 0)
+ {
+ synchronized (writeRequestQueue)
+ {
+ writeRequestQueue.pop();
+ }
+
+ session.increaseWrittenMessages();
+
+ buf.reset();
+ session.getFilterChain().fireMessageSent(session, req);
+ continue;
+ }
+
+
+ int writtenBytes = 0;
+
+ // Reported as DIRMINA-362
+ //note: todo: fixme: Not sure it is important but if we see NoyYetConnected exceptions or 100% CPU in the kernel then this is it.
+ if (key.isWritable())
+ {
+ writtenBytes = ch.write(buf.buf());
+ totalFlushedBytes += writtenBytes;
+ }
+
+ if (writtenBytes > 0)
+ {
+ session.increaseWrittenBytes(writtenBytes);
+ }
+
+ if (buf.hasRemaining() || (totalFlushedBytes <= MAX_FLUSH_BYTES_PER_SESSION))
+ {
+ // Kernel buffer is full
+ synchronized (writeLock)
+ {
+ key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
+ }
+ if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Written BF: " + (session.getWrittenBytes() - totalFlushedBytes) + " bytes");
+ }
+ return false;
+ }
+ }
+
+ if (_loggerWrite.isDebugEnabled())
+ {
+ //System.out.println("WriteDebug:"+"Written : " + (session.getWrittenBytes() - totalFlushedBytes) + " bytes");
+ }
+ return true;
+ }
+
+ private void doUpdateTrafficMask()
+ {
+ if (trafficControllingSessions.isEmpty() || trafficMaskUpdateLock.isLocked())
+ {
+ return;
+ }
+
+ // Synchronize over entire operation as this method should be called
+ // from both read and write thread and we don't want the order of the
+ // updates to get changed.
+ trafficMaskUpdateLock.lock();
+ try
+ {
+ for (; ;)
+ {
+ MultiThreadSocketSessionImpl session;
+
+ session = (MultiThreadSocketSessionImpl) trafficControllingSessions.pop();
+
+ if (session == null)
+ {
+ break;
+ }
+
+ SelectionKey key = session.getReadSelectionKey();
+ // Retry later if session is not yet fully initialized.
+ // (In case that Session.suspend??() or session.resume??() is
+ // called before addSession() is processed)
+ if (key == null)
+ {
+ scheduleTrafficControl(session);
+ break;
+ }
+ // skip if channel is already closed
+ if (!key.isValid())
+ {
+ continue;
+ }
+
+ // The normal is OP_READ and, if there are write requests in the
+ // session's write queue, set OP_WRITE to trigger flushing.
+
+ //Sset to Read and Write if there is nothing then the cost
+ // is one loop through the flusher.
+ int ops = SelectionKey.OP_READ;
+
+ // Now mask the preferred ops with the mask of the current session
+ int mask = session.getTrafficMask().getInterestOps();
+ synchronized (readLock)
+ {
+ key.interestOps(ops & mask);
+ }
+ //Change key to the WriteSelection Key
+ key = session.getWriteSelectionKey();
+ if (key != null && key.isValid())
+ {
+ Queue writeRequestQueue = session.getWriteRequestQueue();
+ synchronized (writeRequestQueue)
+ {
+ if (!writeRequestQueue.isEmpty())
+ {
+ ops = SelectionKey.OP_WRITE;
+ synchronized (writeLock)
+ {
+ key.interestOps(ops & mask);
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ trafficMaskUpdateLock.unlock();
+ }
+
+ }
+
+ private class WriteWorker implements Runnable
+ {
+
+ public void run()
+ {
+ Thread.currentThread().setName(MultiThreadSocketIoProcessor.this.threadName + "Writer");
+
+ //System.out.println("WriteDebug:"+"Startup");
+ for (; ;)
+ {
+ try
+ {
+ int nKeys = writeSelector.select(SELECTOR_TIMEOUT);
+
+ doAddNewWrite();
+ doUpdateTrafficMask();
+
+ if (nKeys > 0)
+ {
+ //System.out.println("WriteDebug:"+nKeys + " keys from writeselector");
+ processWrite(writeSelector.selectedKeys());
+ }
+ else
+ {
+ //System.out.println("WriteDebug:"+"No keys from writeselector");
+ }
+
+ doRemove();
+ notifyWriteIdleness();
+
+ if (flushingSessionsSet.size() > 0)
+ {
+ doFlush();
+ }
+
+ if (writeSelector.keys().isEmpty())
+ {
+ synchronized (writeLock)
+ {
+
+ if (writeSelector.keys().isEmpty() && newSessions.isEmpty())
+ {
+ writeWorker = null;
+ try
+ {
+ writeSelector.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ writeSelector = null;
+ }
+
+ break;
+ }
+ }
+ }
+
+ }
+ catch (Throwable t)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(t);
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e1)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e1);
+ }
+ }
+ }
+ //System.out.println("WriteDebug:"+"Shutdown");
+ }
+
+ }
+
+ private class ReadWorker implements Runnable
+ {
+
+ public void run()
+ {
+ Thread.currentThread().setName(MultiThreadSocketIoProcessor.this.threadName + "Reader");
+
+ //System.out.println("ReadDebug:"+"Startup");
+ for (; ;)
+ {
+ try
+ {
+ int nKeys = selector.select(SELECTOR_TIMEOUT);
+
+ doAddNewReader();
+ doUpdateTrafficMask();
+
+ if (nKeys > 0)
+ {
+ //System.out.println("ReadDebug:"+nKeys + " keys from selector");
+
+ processRead(selector.selectedKeys());
+ }
+ else
+ {
+ //System.out.println("ReadDebug:"+"No keys from selector");
+ }
+
+
+ doRemove();
+ notifyReadIdleness();
+
+ if (selector.keys().isEmpty())
+ {
+
+ synchronized (readLock)
+ {
+ if (selector.keys().isEmpty() && newSessions.isEmpty())
+ {
+ readWorker = null;
+ try
+ {
+ selector.close();
+ }
+ catch (IOException e)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ finally
+ {
+ selector = null;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(t);
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e1)
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e1);
+ }
+ }
+ }
+ //System.out.println("ReadDebug:"+"Shutdown");
+ }
+
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java
new file mode 100644
index 0000000000..043d4800b6
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionConfigImpl.java
@@ -0,0 +1,240 @@
+/*
+ * 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 org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoConnectorConfig;
+import org.apache.mina.common.support.BaseIoSessionConfig;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+
+/**
+ * An {@link IoConnectorConfig} for {@link SocketConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public class MultiThreadSocketSessionConfigImpl extends org.apache.mina.transport.socket.nio.SocketSessionConfigImpl
+{
+ private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
+ private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false;
+ private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false;
+ private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false;
+
+ private static boolean DEFAULT_REUSE_ADDRESS;
+ private static int DEFAULT_RECEIVE_BUFFER_SIZE;
+ private static int DEFAULT_SEND_BUFFER_SIZE;
+ private static int DEFAULT_TRAFFIC_CLASS;
+ private static boolean DEFAULT_KEEP_ALIVE;
+ private static boolean DEFAULT_OOB_INLINE;
+ private static int DEFAULT_SO_LINGER;
+ private static boolean DEFAULT_TCP_NO_DELAY;
+
+ static
+ {
+ initialize();
+ }
+
+ private static void initialize()
+ {
+ Socket socket = null;
+
+ socket = new Socket();
+
+ try
+ {
+ DEFAULT_REUSE_ADDRESS = socket.getReuseAddress();
+ DEFAULT_RECEIVE_BUFFER_SIZE = socket.getReceiveBufferSize();
+ DEFAULT_SEND_BUFFER_SIZE = socket.getSendBufferSize();
+ DEFAULT_KEEP_ALIVE = socket.getKeepAlive();
+ DEFAULT_OOB_INLINE = socket.getOOBInline();
+ DEFAULT_SO_LINGER = socket.getSoLinger();
+ DEFAULT_TCP_NO_DELAY = socket.getTcpNoDelay();
+
+ // Check if setReceiveBufferSize is supported.
+ try
+ {
+ socket.setReceiveBufferSize(DEFAULT_RECEIVE_BUFFER_SIZE);
+ SET_RECEIVE_BUFFER_SIZE_AVAILABLE = true;
+ }
+ catch( SocketException e )
+ {
+ SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
+ }
+
+ // Check if setSendBufferSize is supported.
+ try
+ {
+ socket.setSendBufferSize(DEFAULT_SEND_BUFFER_SIZE);
+ SET_SEND_BUFFER_SIZE_AVAILABLE = true;
+ }
+ catch( SocketException e )
+ {
+ SET_SEND_BUFFER_SIZE_AVAILABLE = false;
+ }
+
+ // Check if getTrafficClass is supported.
+ try
+ {
+ DEFAULT_TRAFFIC_CLASS = socket.getTrafficClass();
+ GET_TRAFFIC_CLASS_AVAILABLE = true;
+ }
+ catch( SocketException e )
+ {
+ GET_TRAFFIC_CLASS_AVAILABLE = false;
+ DEFAULT_TRAFFIC_CLASS = 0;
+ }
+ }
+ catch( SocketException e )
+ {
+ throw new ExceptionInInitializerError(e);
+ }
+ finally
+ {
+ if( socket != null )
+ {
+ try
+ {
+ socket.close();
+ }
+ catch( IOException e )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught(e);
+ }
+ }
+ }
+ }
+
+ public static boolean isSetReceiveBufferSizeAvailable() {
+ return SET_RECEIVE_BUFFER_SIZE_AVAILABLE;
+ }
+
+ public static boolean isSetSendBufferSizeAvailable() {
+ return SET_SEND_BUFFER_SIZE_AVAILABLE;
+ }
+
+ public static boolean isGetTrafficClassAvailable() {
+ return GET_TRAFFIC_CLASS_AVAILABLE;
+ }
+
+ public static boolean isSetTrafficClassAvailable() {
+ return SET_TRAFFIC_CLASS_AVAILABLE;
+ }
+
+ private boolean reuseAddress = DEFAULT_REUSE_ADDRESS;
+ private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
+ private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE;
+ private int trafficClass = DEFAULT_TRAFFIC_CLASS;
+ private boolean keepAlive = DEFAULT_KEEP_ALIVE;
+ private boolean oobInline = DEFAULT_OOB_INLINE;
+ private int soLinger = DEFAULT_SO_LINGER;
+ private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY;
+
+ /**
+ * Creates a new instance.
+ */
+ MultiThreadSocketSessionConfigImpl()
+ {
+ }
+
+ public boolean isReuseAddress()
+ {
+ return reuseAddress;
+ }
+
+ public void setReuseAddress( boolean reuseAddress )
+ {
+ this.reuseAddress = reuseAddress;
+ }
+
+ public int getReceiveBufferSize()
+ {
+ return receiveBufferSize;
+ }
+
+ public void setReceiveBufferSize( int receiveBufferSize )
+ {
+ this.receiveBufferSize = receiveBufferSize;
+ }
+
+ public int getSendBufferSize()
+ {
+ return sendBufferSize;
+ }
+
+ public void setSendBufferSize( int sendBufferSize )
+ {
+ this.sendBufferSize = sendBufferSize;
+ }
+
+ public int getTrafficClass()
+ {
+ return trafficClass;
+ }
+
+ public void setTrafficClass( int trafficClass )
+ {
+ this.trafficClass = trafficClass;
+ }
+
+ public boolean isKeepAlive()
+ {
+ return keepAlive;
+ }
+
+ public void setKeepAlive( boolean keepAlive )
+ {
+ this.keepAlive = keepAlive;
+ }
+
+ public boolean isOobInline()
+ {
+ return oobInline;
+ }
+
+ public void setOobInline( boolean oobInline )
+ {
+ this.oobInline = oobInline;
+ }
+
+ public int getSoLinger()
+ {
+ return soLinger;
+ }
+
+ public void setSoLinger( int soLinger )
+ {
+ this.soLinger = soLinger;
+ }
+
+ public boolean isTcpNoDelay()
+ {
+ return tcpNoDelay;
+ }
+
+ public void setTcpNoDelay( boolean tcpNoDelay )
+ {
+ this.tcpNoDelay = tcpNoDelay;
+ }
+
+
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java
new file mode 100644
index 0000000000..be4a2d289d
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/socket/nio/MultiThreadSocketSessionImpl.java
@@ -0,0 +1,488 @@
+/*
+ * 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 org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoFilter.WriteRequest;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoService;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoSessionConfig;
+import org.apache.mina.common.RuntimeIOException;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.common.support.BaseIoSessionConfig;
+import org.apache.mina.common.support.IoServiceListenerSupport;
+import org.apache.mina.util.Queue;
+
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * An {@link IoSession} for socket transport (TCP/IP).
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+class MultiThreadSocketSessionImpl extends SocketSessionImpl
+{
+ private final IoService manager;
+ private final IoServiceConfig serviceConfig;
+ private final SocketSessionConfig config = new SessionConfigImpl();
+ private final MultiThreadSocketIoProcessor ioProcessor;
+ private final MultiThreadSocketFilterChain filterChain;
+ private final SocketChannel ch;
+ private final Queue writeRequestQueue;
+ private final IoHandler handler;
+ private final SocketAddress remoteAddress;
+ private final SocketAddress localAddress;
+ private final SocketAddress serviceAddress;
+ private final IoServiceListenerSupport serviceListeners;
+ private SelectionKey readKey, writeKey;
+ private int readBufferSize;
+ private CountDownLatch registeredReadyLatch = new CountDownLatch(2);
+ private AtomicBoolean created = new AtomicBoolean(false);
+
+ /**
+ * Creates a new instance.
+ */
+ MultiThreadSocketSessionImpl( IoService manager,
+ SocketIoProcessor ioProcessor,
+ IoServiceListenerSupport listeners,
+ IoServiceConfig serviceConfig,
+ SocketChannel ch,
+ IoHandler defaultHandler,
+ SocketAddress serviceAddress )
+ {
+ super(manager, ioProcessor, listeners, serviceConfig, ch,defaultHandler,serviceAddress);
+ this.manager = manager;
+ this.serviceListeners = listeners;
+ this.ioProcessor = (MultiThreadSocketIoProcessor) ioProcessor;
+ this.filterChain = new MultiThreadSocketFilterChain(this);
+ this.ch = ch;
+ this.writeRequestQueue = new Queue();
+ this.handler = defaultHandler;
+ this.remoteAddress = ch.socket().getRemoteSocketAddress();
+ this.localAddress = ch.socket().getLocalSocketAddress();
+ this.serviceAddress = serviceAddress;
+ this.serviceConfig = serviceConfig;
+
+ // Apply the initial session settings
+ IoSessionConfig sessionConfig = serviceConfig.getSessionConfig();
+ if( sessionConfig instanceof SocketSessionConfig )
+ {
+ SocketSessionConfig cfg = ( SocketSessionConfig ) sessionConfig;
+ this.config.setKeepAlive( cfg.isKeepAlive() );
+ this.config.setOobInline( cfg.isOobInline() );
+ this.config.setReceiveBufferSize( cfg.getReceiveBufferSize() );
+ this.readBufferSize = cfg.getReceiveBufferSize();
+ this.config.setReuseAddress( cfg.isReuseAddress() );
+ this.config.setSendBufferSize( cfg.getSendBufferSize() );
+ this.config.setSoLinger( cfg.getSoLinger() );
+ this.config.setTcpNoDelay( cfg.isTcpNoDelay() );
+
+ if( this.config.getTrafficClass() != cfg.getTrafficClass() )
+ {
+ this.config.setTrafficClass( cfg.getTrafficClass() );
+ }
+ }
+ }
+
+ void awaitRegistration() throws InterruptedException
+ {
+ registeredReadyLatch.countDown();
+
+ registeredReadyLatch.await();
+ }
+
+ boolean created() throws InterruptedException
+ {
+ return created.get();
+ }
+
+ void doneCreation()
+ {
+ created.getAndSet(true);
+ }
+
+ public IoService getService()
+ {
+ return manager;
+ }
+
+ public IoServiceConfig getServiceConfig()
+ {
+ return serviceConfig;
+ }
+
+ public IoSessionConfig getConfig()
+ {
+ return config;
+ }
+
+ SocketIoProcessor getIoProcessor()
+ {
+ return ioProcessor;
+ }
+
+ public IoFilterChain getFilterChain()
+ {
+ return filterChain;
+ }
+
+ SocketChannel getChannel()
+ {
+ return ch;
+ }
+
+ IoServiceListenerSupport getServiceListeners()
+ {
+ return serviceListeners;
+ }
+
+ SelectionKey getSelectionKey()
+ {
+ return readKey;
+ }
+
+ SelectionKey getReadSelectionKey()
+ {
+ return readKey;
+ }
+
+ SelectionKey getWriteSelectionKey()
+ {
+ return writeKey;
+ }
+
+ void setSelectionKey(SelectionKey key)
+ {
+ this.readKey = key;
+ }
+
+ void setWriteSelectionKey(SelectionKey key)
+ {
+ this.writeKey = key;
+ }
+
+ public IoHandler getHandler()
+ {
+ return handler;
+ }
+
+ protected void close0()
+ {
+ filterChain.fireFilterClose( this );
+ }
+
+ Queue getWriteRequestQueue()
+ {
+ return writeRequestQueue;
+ }
+
+ /**
+ @return int Number of write scheduled write requests
+ @deprecated
+ */
+ public int getScheduledWriteMessages()
+ {
+ return getScheduledWriteRequests();
+ }
+
+ public int getScheduledWriteRequests()
+ {
+ synchronized( writeRequestQueue )
+ {
+ return writeRequestQueue.size();
+ }
+ }
+
+ public int getScheduledWriteBytes()
+ {
+ synchronized( writeRequestQueue )
+ {
+ return writeRequestQueue.byteSize();
+ }
+ }
+
+ protected void write0( WriteRequest writeRequest )
+ {
+ filterChain.fireFilterWrite( this, writeRequest );
+ }
+
+ public TransportType getTransportType()
+ {
+ return TransportType.SOCKET;
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ //This is what I had previously
+// return ch.socket().getRemoteSocketAddress();
+ return remoteAddress;
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ //This is what I had previously
+// return ch.socket().getLocalSocketAddress();
+ return localAddress;
+ }
+
+ public SocketAddress getServiceAddress()
+ {
+ return serviceAddress;
+ }
+
+ protected void updateTrafficMask()
+ {
+ this.ioProcessor.updateTrafficMask( this );
+ }
+
+ int getReadBufferSize()
+ {
+ return readBufferSize;
+ }
+
+ private class SessionConfigImpl extends BaseIoSessionConfig implements SocketSessionConfig
+ {
+ public boolean isKeepAlive()
+ {
+ try
+ {
+ return ch.socket().getKeepAlive();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setKeepAlive( boolean on )
+ {
+ try
+ {
+ ch.socket().setKeepAlive( on );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public boolean isOobInline()
+ {
+ try
+ {
+ return ch.socket().getOOBInline();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setOobInline( boolean on )
+ {
+ try
+ {
+ ch.socket().setOOBInline( on );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public boolean isReuseAddress()
+ {
+ try
+ {
+ return ch.socket().getReuseAddress();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setReuseAddress( boolean on )
+ {
+ try
+ {
+ ch.socket().setReuseAddress( on );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public int getSoLinger()
+ {
+ try
+ {
+ return ch.socket().getSoLinger();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setSoLinger( int linger )
+ {
+ try
+ {
+ if( linger < 0 )
+ {
+ ch.socket().setSoLinger( false, 0 );
+ }
+ else
+ {
+ ch.socket().setSoLinger( true, linger );
+ }
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public boolean isTcpNoDelay()
+ {
+ try
+ {
+ return ch.socket().getTcpNoDelay();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setTcpNoDelay( boolean on )
+ {
+ try
+ {
+ ch.socket().setTcpNoDelay( on );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public int getTrafficClass()
+ {
+ if( SocketSessionConfigImpl.isGetTrafficClassAvailable() )
+ {
+ try
+ {
+ return ch.socket().getTrafficClass();
+ }
+ catch( SocketException e )
+ {
+ // Throw an exception only when setTrafficClass is also available.
+ if( SocketSessionConfigImpl.isSetTrafficClassAvailable() )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ public void setTrafficClass( int tc )
+ {
+ if( SocketSessionConfigImpl.isSetTrafficClassAvailable() )
+ {
+ try
+ {
+ ch.socket().setTrafficClass( tc );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+ }
+
+ public int getSendBufferSize()
+ {
+ try
+ {
+ return ch.socket().getSendBufferSize();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setSendBufferSize( int size )
+ {
+ if( SocketSessionConfigImpl.isSetSendBufferSizeAvailable() )
+ {
+ try
+ {
+ ch.socket().setSendBufferSize( size );
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+ }
+
+ public int getReceiveBufferSize()
+ {
+ try
+ {
+ return ch.socket().getReceiveBufferSize();
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+
+ public void setReceiveBufferSize( int size )
+ {
+ if( SocketSessionConfigImpl.isSetReceiveBufferSizeAvailable() )
+ {
+ try
+ {
+ ch.socket().setReceiveBufferSize( size );
+ MultiThreadSocketSessionImpl.this.readBufferSize = size;
+ }
+ catch( SocketException e )
+ {
+ throw new RuntimeIOException( e );
+ }
+ }
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java b/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java
new file mode 100644
index 0000000000..a23e546af5
--- /dev/null
+++ b/java/common/src/main/java/org/apache/mina/transport/vmpipe/QpidVmPipeConnector.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.mina.transport.vmpipe;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.IoSessionConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
+import org.apache.mina.common.support.BaseIoConnector;
+import org.apache.mina.common.support.BaseIoConnectorConfig;
+import org.apache.mina.common.support.BaseIoSessionConfig;
+import org.apache.mina.common.support.DefaultConnectFuture;
+import org.apache.mina.transport.vmpipe.support.VmPipe;
+import org.apache.mina.transport.vmpipe.support.VmPipeIdleStatusChecker;
+import org.apache.mina.transport.vmpipe.support.VmPipeSessionImpl;
+import org.apache.mina.util.AnonymousSocketAddress;
+
+/**
+ * Connects to {@link IoHandler}s which is bound on the specified
+ * {@link VmPipeAddress}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev: 619823 $, $Date: 2008-02-08 10:09:37 +0000 (Fri, 08 Feb 2008) $
+ */
+public class QpidVmPipeConnector extends VmPipeConnector
+{
+ private static final IoSessionConfig CONFIG = new BaseIoSessionConfig() {};
+ private final IoServiceConfig defaultConfig = new BaseIoConnectorConfig()
+ {
+ public IoSessionConfig getSessionConfig()
+ {
+ return CONFIG;
+ }
+ };
+
+ /**
+ * Creates a new instance.
+ */
+ public QpidVmPipeConnector()
+ {
+ }
+
+ public ConnectFuture connect( SocketAddress address, IoHandler handler, IoServiceConfig config )
+ {
+ return connect( address, null, handler, config );
+ }
+
+ public ConnectFuture connect( SocketAddress address, SocketAddress localAddress, IoHandler handler, IoServiceConfig config )
+ {
+ if( address == null )
+ throw new NullPointerException( "address" );
+ if( handler == null )
+ throw new NullPointerException( "handler" );
+ if( ! ( address instanceof VmPipeAddress ) )
+ throw new IllegalArgumentException(
+ "address must be VmPipeAddress." );
+
+ if( config == null )
+ {
+ config = getDefaultConfig();
+ }
+
+ VmPipe entry = ( VmPipe ) VmPipeAcceptor.boundHandlers.get( address );
+ if( entry == null )
+ {
+ return DefaultConnectFuture.newFailedFuture(
+ new IOException( "Endpoint unavailable: " + address ) );
+ }
+
+ DefaultConnectFuture future = new DefaultConnectFuture();
+ VmPipeSessionImpl localSession =
+ new VmPipeSessionImpl(
+ this,
+ config,
+ getListeners(),
+ new Object(), // lock
+ new AnonymousSocketAddress(),
+ handler,
+ entry );
+
+ // initialize acceptor session
+ VmPipeSessionImpl remoteSession = localSession.getRemoteSession();
+ try
+ {
+ IoFilterChain filterChain = remoteSession.getFilterChain();
+ entry.getAcceptor().getFilterChainBuilder().buildFilterChain( filterChain );
+ entry.getConfig().getFilterChainBuilder().buildFilterChain( filterChain );
+ entry.getConfig().getThreadModel().buildFilterChain( filterChain );
+
+ // The following sentences don't throw any exceptions.
+ entry.getListeners().fireSessionCreated( remoteSession );
+ VmPipeIdleStatusChecker.getInstance().addSession( remoteSession );
+ }
+ catch( Throwable t )
+ {
+ ExceptionMonitor.getInstance().exceptionCaught( t );
+ remoteSession.close();
+ }
+
+
+ // initialize connector session
+ try
+ {
+ IoFilterChain filterChain = localSession.getFilterChain();
+ this.getFilterChainBuilder().buildFilterChain( filterChain );
+ config.getFilterChainBuilder().buildFilterChain( filterChain );
+ config.getThreadModel().buildFilterChain( filterChain );
+
+ // The following sentences don't throw any exceptions.
+ localSession.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, future );
+ getListeners().fireSessionCreated( localSession );
+ VmPipeIdleStatusChecker.getInstance().addSession( localSession);
+ }
+ catch( Throwable t )
+ {
+ future.setException( t );
+ }
+
+
+
+ return future;
+ }
+
+ public IoServiceConfig getDefaultConfig()
+ {
+ return defaultConfig;
+ }
+} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
index 2f6290b55a..ef9420ba87 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
@@ -54,7 +54,6 @@ public class AMQChannelException extends AMQException
public AMQFrame getCloseFrame(int channel)
{
MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
- return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), getMessageAsShortString(),_classId,_methodId));
+ return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId));
}
-
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
index ca9c9f9dc4..8ef6facef1 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
@@ -62,10 +62,9 @@ public class AMQConnectionException extends AMQException
MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
return new AMQFrame(0,
reg.createConnectionCloseBody(getErrorCode().getCode(),
- getMessageAsShortString(),
+ new AMQShortString(getMessage()),
_classId,
_methodId));
}
-
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQException.java b/java/common/src/main/java/org/apache/qpid/AMQException.java
index 86d439d269..b0c6fccc9e 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQException.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.protocol.AMQConstant;
/**
@@ -122,19 +121,4 @@ public class AMQException extends Exception
return newAMQE;
}
-
- /**
- * Truncates the exception message to 255 characters if its length exceeds 255.
- *
- * @return exception message
- */
- public AMQShortString getMessageAsShortString()
- {
- String message = getMessage();
- if (message != null && message.length() > AMQShortString.MAX_LENGTH)
- {
- message = message.substring(0, AMQShortString.MAX_LENGTH - 3) + "...";
- }
- return new AMQShortString(message);
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java b/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java
index 2bbaaef1fc..baca2a4773 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQInvalidArgumentException.java
@@ -34,7 +34,7 @@ public class AMQInvalidArgumentException extends AMQException
{
public AMQInvalidArgumentException(String message, Throwable cause)
{
- super(AMQConstant.ARGUMENT_INVALID, message, cause);
+ super(AMQConstant.INVALID_ARGUMENT, message, cause);
}
public boolean isHardError()
diff --git a/java/common/src/main/java/org/apache/qpid/ToyBroker.java b/java/common/src/main/java/org/apache/qpid/ToyBroker.java
new file mode 100644
index 0000000000..5423bbb68f
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/ToyBroker.java
@@ -0,0 +1,208 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import org.apache.qpid.transport.*;
+import org.apache.qpid.transport.network.mina.MinaHandler;
+
+import static org.apache.qpid.transport.util.Functions.str;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+
+
+/**
+ * ToyBroker
+ *
+ * @author Rafael H. Schloming
+ */
+
+class ToyBroker extends SessionDelegate
+{
+
+ private ToyExchange exchange;
+ private Map<String,Consumer> consumers = new ConcurrentHashMap<String,Consumer>();
+
+ public ToyBroker(ToyExchange exchange)
+ {
+ this.exchange = exchange;
+ }
+
+ public void messageAcquire(Session context, MessageAcquire struct)
+ {
+ System.out.println("\n==================> messageAcquire " );
+ context.executionResult((int) struct.getId(), new Acquired(struct.getTransfers()));
+ }
+
+ @Override public void queueDeclare(Session ssn, QueueDeclare qd)
+ {
+ exchange.createQueue(qd.getQueue());
+ System.out.println("\n==================> declared queue: " + qd.getQueue() + "\n");
+ }
+
+ @Override public void exchangeBind(Session ssn, ExchangeBind qb)
+ {
+ exchange.bindQueue(qb.getExchange(), qb.getBindingKey(),qb.getQueue());
+ System.out.println("\n==================> bound queue: " + qb.getQueue() + " with binding key " + qb.getBindingKey() + "\n");
+ }
+
+ @Override public void queueQuery(Session ssn, QueueQuery qq)
+ {
+ QueueQueryResult result = new QueueQueryResult().queue(qq.getQueue());
+ ssn.executionResult((int) qq.getId(), result);
+ }
+
+ @Override public void messageSubscribe(Session ssn, MessageSubscribe ms)
+ {
+ Consumer c = new Consumer();
+ c._queueName = ms.getQueue();
+ consumers.put(ms.getDestination(),c);
+ System.out.println("\n==================> message subscribe : " + ms.getDestination() + " queue: " + ms.getQueue() + "\n");
+ }
+
+ @Override public void messageFlow(Session ssn,MessageFlow struct)
+ {
+ Consumer c = consumers.get(struct.getDestination());
+ c._credit = struct.getValue();
+ System.out.println("\n==================> message flow : " + struct.getDestination() + " credit: " + struct.getValue() + "\n");
+ }
+
+ @Override public void messageFlush(Session ssn,MessageFlush struct)
+ {
+ System.out.println("\n==================> message flush for consumer : " + struct.getDestination() + "\n");
+ checkAndSendMessagesToConsumer(ssn,struct.getDestination());
+ }
+
+ @Override public void messageTransfer(Session ssn, MessageTransfer xfr)
+ {
+ String dest = xfr.getDestination();
+ System.out.println("received transfer " + dest);
+ Header header = xfr.getHeader();
+ DeliveryProperties props = header.get(DeliveryProperties.class);
+ if (props != null)
+ {
+ System.out.println("received headers routing_key " + props.getRoutingKey());
+ }
+
+ MessageProperties mp = header.get(MessageProperties.class);
+ System.out.println("MP: " + mp);
+ if (mp != null)
+ {
+ System.out.println(mp.getApplicationHeaders());
+ }
+
+ if (exchange.route(dest,props == null ? null : props.getRoutingKey(),xfr))
+ {
+ System.out.println("queued " + xfr);
+ dispatchMessages(ssn);
+ }
+ else
+ {
+
+ if (props == null || !props.getDiscardUnroutable())
+ {
+ RangeSet ranges = new RangeSet();
+ ranges.add(xfr.getId());
+ ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE,
+ "no such destination");
+ }
+ }
+ ssn.processed(xfr);
+ }
+
+ private void transferMessageToPeer(Session ssn,String dest, MessageTransfer m)
+ {
+ System.out.println("\n==================> Transfering message to: " +dest + "\n");
+ ssn.messageTransfer(m.getDestination(), MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ m.getHeader(), m.getBody());
+ }
+
+ private void dispatchMessages(Session ssn)
+ {
+ for (String dest: consumers.keySet())
+ {
+ checkAndSendMessagesToConsumer(ssn,dest);
+ }
+ }
+
+ private void checkAndSendMessagesToConsumer(Session ssn,String dest)
+ {
+ Consumer c = consumers.get(dest);
+ LinkedBlockingQueue<MessageTransfer> queue = exchange.getQueue(c._queueName);
+ MessageTransfer m = queue.poll();
+ while (m != null && c._credit>0)
+ {
+ transferMessageToPeer(ssn,dest,m);
+ c._credit--;
+ m = queue.poll();
+ }
+ }
+
+ // ugly, but who cares :)
+ // assumes unit is always no of messages, not bytes
+ // assumes it's credit mode and not window
+ private static class Consumer
+ {
+ long _credit;
+ String _queueName;
+ }
+
+ private static final class ToyBrokerSession extends Session
+ {
+
+ public ToyBrokerSession(Connection connection, Binary name, long expiry, ToyExchange exchange)
+ {
+ super(connection, new ToyBroker(exchange), name, expiry);
+ }
+ }
+
+ public static final void main(String[] args) throws IOException
+ {
+ final ToyExchange exchange = new ToyExchange();
+ ConnectionDelegate delegate = new ServerDelegate()
+ {
+ @Override
+ public void init(Connection conn, ProtocolHeader hdr)
+ {
+ conn.setSessionFactory(new Connection.SessionFactory()
+ {
+ public Session newSession(Connection conn, Binary name, long expiry)
+ {
+ return new ToyBrokerSession(conn, name, expiry, exchange);
+ }
+ });
+
+ super.init(conn, hdr); //To change body of overridden methods use File | Settings | File Templates.
+ }
+
+ };
+
+ MinaHandler.accept("0.0.0.0", 5672, delegate);
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/ToyClient.java b/java/common/src/main/java/org/apache/qpid/ToyClient.java
new file mode 100644
index 0000000000..5b2db10613
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/ToyClient.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import java.nio.*;
+import java.util.*;
+
+import org.apache.qpid.transport.*;
+import org.apache.qpid.transport.network.mina.MinaHandler;
+
+
+/**
+ * ToyClient
+ *
+ * @author Rafael H. Schloming
+ */
+
+class ToyClient implements SessionListener
+{
+ public void opened(Session ssn) {}
+
+ public void resumed(Session ssn) {}
+
+ public void exception(Session ssn, SessionException exc)
+ {
+ exc.printStackTrace();
+ }
+
+ public void message(Session ssn, MessageTransfer xfr)
+ {
+ System.out.println("msg: " + xfr);
+ }
+
+ public void closed(Session ssn) {}
+
+ public static final void main(String[] args)
+ {
+ Connection conn = new Connection();
+ conn.connect("0.0.0.0", 5672, null, "guest", "guest", false);
+ Session ssn = conn.createSession();
+ ssn.setSessionListener(new ToyClient());
+
+ ssn.queueDeclare("asdf", null, null);
+ ssn.sync();
+
+ Map<String,Object> nested = new LinkedHashMap<String,Object>();
+ nested.put("list", Arrays.asList("one", "two", "three"));
+ Map<String,Object> map = new LinkedHashMap<String,Object>();
+
+ map.put("str", "this is a string");
+
+ map.put("+int", 3);
+ map.put("-int", -3);
+ map.put("maxint", Integer.MAX_VALUE);
+ map.put("minint", Integer.MIN_VALUE);
+
+ map.put("+short", (short) 1);
+ map.put("-short", (short) -1);
+ map.put("maxshort", (short) Short.MAX_VALUE);
+ map.put("minshort", (short) Short.MIN_VALUE);
+
+ map.put("float", (float) 3.3);
+ map.put("double", 4.9);
+ map.put("char", 'c');
+
+ map.put("table", nested);
+ map.put("list", Arrays.asList(1, 2, 3));
+ map.put("binary", new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
+
+ ssn.messageTransfer("asdf", MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties(),
+ new MessageProperties()
+ .setApplicationHeaders(map)),
+ "this is the data");
+
+ ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ null,
+ "this should be rejected");
+ ssn.sync();
+
+ Future<QueueQueryResult> future = ssn.queueQuery("asdf");
+ System.out.println(future.get().getQueue());
+ ssn.sync();
+ ssn.close();
+ conn.close();
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/ToyExchange.java b/java/common/src/main/java/org/apache/qpid/ToyExchange.java
new file mode 100644
index 0000000000..da6aed9629
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/ToyExchange.java
@@ -0,0 +1,154 @@
+package org.apache.qpid;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.qpid.transport.MessageTransfer;
+
+
+public class ToyExchange
+{
+ final static String DIRECT = "amq.direct";
+ final static String TOPIC = "amq.topic";
+
+ private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> directEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>();
+ private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> topicEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>();
+ private Map<String,LinkedBlockingQueue<MessageTransfer>> queues = new HashMap<String,LinkedBlockingQueue<MessageTransfer>>();
+
+ public void createQueue(String name)
+ {
+ queues.put(name, new LinkedBlockingQueue<MessageTransfer>());
+ }
+
+ public LinkedBlockingQueue<MessageTransfer> getQueue(String name)
+ {
+ return queues.get(name);
+ }
+
+ public void bindQueue(String type,String binding,String queueName)
+ {
+ LinkedBlockingQueue<MessageTransfer> queue = queues.get(queueName);
+ binding = normalizeKey(binding);
+ if(DIRECT.equals(type))
+ {
+
+ if (directEx.containsKey(binding))
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> list = directEx.get(binding);
+ list.add(queue);
+ }
+ else
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>();
+ list.add(queue);
+ directEx.put(binding,list);
+ }
+ }
+ else
+ {
+ if (topicEx.containsKey(binding))
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> list = topicEx.get(binding);
+ list.add(queue);
+ }
+ else
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>();
+ list.add(queue);
+ topicEx.put(binding,list);
+ }
+ }
+ }
+
+ public boolean route(String dest, String routingKey, MessageTransfer msg)
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> queues;
+ if(DIRECT.equals(dest))
+ {
+ queues = directEx.get(routingKey);
+ }
+ else
+ {
+ queues = matchWildCard(routingKey);
+ }
+ if(queues != null && queues.size()>0)
+ {
+ System.out.println("Message stored in " + queues.size() + " queues");
+ storeMessage(msg,queues);
+ return true;
+ }
+ else
+ {
+ System.out.println("Message unroutable " + msg);
+ return false;
+ }
+ }
+
+ private String normalizeKey(String routingKey)
+ {
+ if(routingKey.indexOf(".*")>1)
+ {
+ return routingKey.substring(0,routingKey.indexOf(".*"));
+ }
+ else
+ {
+ return routingKey;
+ }
+ }
+
+ private List<LinkedBlockingQueue<MessageTransfer>> matchWildCard(String routingKey)
+ {
+ List<LinkedBlockingQueue<MessageTransfer>> selected = new ArrayList<LinkedBlockingQueue<MessageTransfer>>();
+
+ for(String key: topicEx.keySet())
+ {
+ Pattern p = Pattern.compile(key);
+ Matcher m = p.matcher(routingKey);
+ if (m.find())
+ {
+ for(LinkedBlockingQueue<MessageTransfer> queue : topicEx.get(key))
+ {
+ selected.add(queue);
+ }
+ }
+ }
+
+ return selected;
+ }
+
+ private void storeMessage(MessageTransfer msg,List<LinkedBlockingQueue<MessageTransfer>> selected)
+ {
+ for(LinkedBlockingQueue<MessageTransfer> queue : selected)
+ {
+ queue.offer(msg);
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java b/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java
index c81af9760b..591dbd085b 100644
--- a/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/codec/AMQCodecFactory.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.codec;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
/**
@@ -28,11 +31,14 @@ import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
*
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations.
+ * <tr><td> Supply the protocol encoder. <td> {@link AMQEncoder}
* <tr><td> Supply the protocol decoder. <td> {@link AMQDecoder}
* </table>
*/
-public class AMQCodecFactory
+public class AMQCodecFactory implements ProtocolCodecFactory
{
+ /** Holds the protocol encoder. */
+ private final AMQEncoder _encoder = new AMQEncoder();
/** Holds the protocol decoder. */
private final AMQDecoder _frameDecoder;
@@ -50,6 +56,15 @@ public class AMQCodecFactory
_frameDecoder = new AMQDecoder(expectProtocolInitiation, session);
}
+ /**
+ * Gets the AMQP encoder.
+ *
+ * @return The AMQP encoder.
+ */
+ public ProtocolEncoder getEncoder()
+ {
+ return _encoder;
+ }
/**
* Gets the AMQP decoder.
diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java
index 69bf73bb49..281c0761d9 100644
--- a/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java
+++ b/java/common/src/main/java/org/apache/qpid/codec/AMQDecoder.java
@@ -20,9 +20,13 @@
*/
package org.apache.qpid.codec;
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.util.*;
+import java.util.ArrayList;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.AMQDataBlockDecoder;
@@ -50,8 +54,11 @@ import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
* @todo If protocol initiation decoder not needed, then don't create it. Probably not a big deal, but it adds to the
* per-session overhead.
*/
-public class AMQDecoder
+public class AMQDecoder extends CumulativeProtocolDecoder
{
+
+ private static final String BUFFER = AMQDecoder.class.getName() + ".Buffer";
+
/** Holds the 'normal' AMQP data decoder. */
private AMQDataBlockDecoder _dataBlockDecoder = new AMQDataBlockDecoder();
@@ -60,11 +67,12 @@ public class AMQDecoder
/** Flag to indicate whether this decoder needs to handle protocol initiation. */
private boolean _expectProtocolInitiation;
+ private boolean firstDecode = true;
private AMQMethodBodyFactory _bodyFactory;
- private List<ByteArrayInputStream> _remainingBufs = new ArrayList<ByteArrayInputStream>();
-
+ private ByteBuffer _remainingBuf;
+
/**
* Creates a new AMQP decoder.
*
@@ -76,7 +84,98 @@ public class AMQDecoder
_bodyFactory = new AMQMethodBodyFactory(session);
}
+ /**
+ * Delegates decoding AMQP from the data buffer that Mina has retrieved from the wire, to the data or protocol
+ * intiation decoders.
+ *
+ * @param session The Mina session.
+ * @param in The raw byte buffer.
+ * @param out The Mina object output gatherer to write decoded objects to.
+ *
+ * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate.
+ *
+ * @throws Exception If the data cannot be decoded for any reason.
+ */
+ protected boolean doDecode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception
+ {
+
+ boolean decoded;
+ if (_expectProtocolInitiation
+ || (firstDecode
+ && (in.remaining() > 0)
+ && (in.get(in.position()) == (byte)'A')))
+ {
+ decoded = doDecodePI(session, in, out);
+ }
+ else
+ {
+ decoded = doDecodeDataBlock(session, in, out);
+ }
+ if(firstDecode && decoded)
+ {
+ firstDecode = false;
+ }
+ return decoded;
+ }
+
+ /**
+ * Decodes AMQP data, delegating the decoding to an {@link AMQDataBlockDecoder}.
+ *
+ * @param session The Mina session.
+ * @param in The raw byte buffer.
+ * @param out The Mina object output gatherer to write decoded objects to.
+ *
+ * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate.
+ *
+ * @throws Exception If the data cannot be decoded for any reason.
+ */
+ protected boolean doDecodeDataBlock(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception
+ {
+ int pos = in.position();
+ boolean enoughData = _dataBlockDecoder.decodable(in.buf());
+ in.position(pos);
+ if (!enoughData)
+ {
+ // returning false means it will leave the contents in the buffer and
+ // call us again when more data has been read
+ return false;
+ }
+ else
+ {
+ _dataBlockDecoder.decode(session, in, out);
+
+ return true;
+ }
+ }
+
+ /**
+ * Decodes an AMQP initiation, delegating the decoding to a {@link ProtocolInitiation.Decoder}.
+ *
+ * @param session The Mina session.
+ * @param in The raw byte buffer.
+ * @param out The Mina object output gatherer to write decoded objects to.
+ *
+ * @return <tt>true</tt> if the data was decoded, <tt>false<tt> if more is needed and the data should accumulate.
+ *
+ * @throws Exception If the data cannot be decoded for any reason.
+ */
+ private boolean doDecodePI(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception
+ {
+ boolean enoughData = _piDecoder.decodable(in.buf());
+ if (!enoughData)
+ {
+ // returning false means it will leave the contents in the buffer and
+ // call us again when more data has been read
+ return false;
+ }
+ else
+ {
+ ProtocolInitiation pi = new ProtocolInitiation(in.buf());
+ out.write(pi);
+ return true;
+ }
+ }
/**
* Sets the protocol initation flag, that determines whether decoding is handled by the data decoder of the protocol
@@ -90,169 +189,152 @@ public class AMQDecoder
_expectProtocolInitiation = expectProtocolInitiation;
}
- private class RemainingByteArrayInputStream extends InputStream
- {
- private int _currentListPos;
- private int _markPos;
-
- @Override
- public int read() throws IOException
+ /**
+ * Cumulates content of <tt>in</tt> into internal buffer and forwards
+ * decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
+ * <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
+ * and the cumulative buffer is compacted after decoding ends.
+ *
+ * @throws IllegalStateException if your <tt>doDecode()</tt> returned
+ * <tt>true</tt> not consuming the cumulative buffer.
+ */
+ public void decode( IoSession session, ByteBuffer in,
+ ProtocolDecoderOutput out ) throws Exception
+ {
+ ByteBuffer buf = ( ByteBuffer ) session.getAttribute( BUFFER );
+ // if we have a session buffer, append data to that otherwise
+ // use the buffer read from the network directly
+ if( buf != null )
{
- ByteArrayInputStream currentStream = _remainingBufs.get(_currentListPos);
- if(currentStream.available() > 0)
- {
- return currentStream.read();
- }
- else if((_currentListPos == _remainingBufs.size())
- || (++_currentListPos == _remainingBufs.size()))
- {
- return -1;
- }
- else
- {
-
- ByteArrayInputStream stream = _remainingBufs.get(_currentListPos);
- stream.mark(0);
- return stream.read();
- }
+ buf.put( in );
+ buf.flip();
}
-
- @Override
- public int read(final byte[] b, final int off, final int len) throws IOException
+ else
{
+ buf = in;
+ }
- if(_currentListPos == _remainingBufs.size())
- {
- return -1;
- }
- else
+ for( ;; )
+ {
+ int oldPos = buf.position();
+ boolean decoded = doDecode( session, buf, out );
+ if( decoded )
{
- ByteArrayInputStream currentStream = _remainingBufs.get(_currentListPos);
- final int available = currentStream.available();
- int read = currentStream.read(b, off, len > available ? available : len);
- if(read < len)
+ if( buf.position() == oldPos )
{
- if(_currentListPos++ != _remainingBufs.size())
- {
- _remainingBufs.get(_currentListPos).mark(0);
- }
- int correctRead = read == -1 ? 0 : read;
- int subRead = read(b, off+correctRead, len-correctRead);
- if(subRead == -1)
- {
- return read;
- }
- else
- {
- return correctRead+subRead;
- }
+ throw new IllegalStateException(
+ "doDecode() can't return true when buffer is not consumed." );
}
- else
+
+ if( !buf.hasRemaining() )
{
- return len;
+ break;
}
}
- }
-
- @Override
- public int available() throws IOException
- {
- int total = 0;
- for(int i = _currentListPos; i < _remainingBufs.size(); i++)
+ else
{
- total += _remainingBufs.get(i).available();
+ break;
}
- return total;
}
- @Override
- public void mark(final int readlimit)
+ // if there is any data left that cannot be decoded, we store
+ // it in a buffer in the session and next time this decoder is
+ // invoked the session buffer gets appended to
+ if ( buf.hasRemaining() )
{
- _markPos = _currentListPos;
- final ByteArrayInputStream stream = _remainingBufs.get(_currentListPos);
- if(stream != null)
- {
- stream.mark(readlimit);
- }
+ storeRemainingInSession( buf, session );
}
+ else
+ {
+ removeSessionBuffer( session );
+ }
+ }
+
+ /**
+ * Releases the cumulative buffer used by the specified <tt>session</tt>.
+ * Please don't forget to call <tt>super.dispose( session )</tt> when
+ * you override this method.
+ */
+ public void dispose( IoSession session ) throws Exception
+ {
+ removeSessionBuffer( session );
+ }
- @Override
- public void reset() throws IOException
+ private void removeSessionBuffer(IoSession session)
+ {
+ ByteBuffer buf = ( ByteBuffer ) session.getAttribute( BUFFER );
+ if( buf != null )
{
- _currentListPos = _markPos;
- final int size = _remainingBufs.size();
- if(_currentListPos < size)
- {
- _remainingBufs.get(_currentListPos).reset();
- }
- for(int i = _currentListPos+1; i<size; i++)
- {
- _remainingBufs.get(i).reset();
- }
+ buf.release();
+ session.removeAttribute( BUFFER );
}
}
+ private static final SimpleByteBufferAllocator SIMPLE_BYTE_BUFFER_ALLOCATOR = new SimpleByteBufferAllocator();
+
+ private void storeRemainingInSession(ByteBuffer buf, IoSession session)
+ {
+ ByteBuffer remainingBuf = SIMPLE_BYTE_BUFFER_ALLOCATOR.allocate( buf.remaining(), false );
+ remainingBuf.setAutoExpand( true );
+ remainingBuf.put( buf );
+ session.setAttribute( BUFFER, remainingBuf );
+ }
- public ArrayList<AMQDataBlock> decodeBuffer(ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
+ public ArrayList<AMQDataBlock> decodeBuffer(java.nio.ByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException
{
// get prior remaining data from accumulator
ArrayList<AMQDataBlock> dataBlocks = new ArrayList<AMQDataBlock>();
- DataInputStream msg;
-
-
- ByteArrayInputStream bais = new ByteArrayInputStream(buf.array(),buf.arrayOffset()+buf.position(), buf.remaining());
- if(!_remainingBufs.isEmpty())
+ ByteBuffer msg;
+ // if we have a session buffer, append data to that otherwise
+ // use the buffer read from the network directly
+ if( _remainingBuf != null )
{
- _remainingBufs.add(bais);
- msg = new DataInputStream(new RemainingByteArrayInputStream());
+ _remainingBuf.put(buf);
+ _remainingBuf.flip();
+ msg = _remainingBuf;
}
else
{
- msg = new DataInputStream(bais);
+ msg = ByteBuffer.wrap(buf);
}
-
- boolean enoughData = true;
- while (enoughData)
+
+ if (_expectProtocolInitiation
+ || (firstDecode
+ && (msg.remaining() > 0)
+ && (msg.get(msg.position()) == (byte)'A')))
{
- if(!_expectProtocolInitiation)
+ if (_piDecoder.decodable(msg.buf()))
{
- enoughData = _dataBlockDecoder.decodable(msg);
- if (enoughData)
- {
- dataBlocks.add(_dataBlockDecoder.createAndPopulateFrame(_bodyFactory, msg));
- }
+ dataBlocks.add(new ProtocolInitiation(msg.buf()));
}
- else
+ }
+ else
+ {
+ boolean enoughData = true;
+ while (enoughData)
{
- enoughData = _piDecoder.decodable(msg);
- if (enoughData)
- {
- dataBlocks.add(new ProtocolInitiation(msg));
- }
-
- }
+ int pos = msg.position();
- if(!enoughData)
- {
- if(!_remainingBufs.isEmpty())
+ enoughData = _dataBlockDecoder.decodable(msg);
+ msg.position(pos);
+ if (enoughData)
{
- _remainingBufs.remove(_remainingBufs.size()-1);
- ListIterator<ByteArrayInputStream> iterator = _remainingBufs.listIterator();
- while(iterator.hasNext() && iterator.next().available() == 0)
- {
- iterator.remove();
- }
+ dataBlocks.add(_dataBlockDecoder.createAndPopulateFrame(_bodyFactory, msg));
}
- if(bais.available()!=0)
+ else
{
- byte[] remaining = new byte[bais.available()];
- bais.read(remaining);
- _remainingBufs.add(new ByteArrayInputStream(remaining));
+ _remainingBuf = SIMPLE_BYTE_BUFFER_ALLOCATOR.allocate(msg.remaining(), false);
+ _remainingBuf.setAutoExpand(true);
+ _remainingBuf.put(msg);
}
}
}
+ if(firstDecode && dataBlocks.size() > 0)
+ {
+ firstDecode = false;
+ }
return dataBlocks;
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java b/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java
new file mode 100644
index 0000000000..53f48ae1c8
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/codec/AMQEncoder.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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 org.apache.qpid.codec;
+
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+import org.apache.qpid.framing.AMQDataBlockEncoder;
+
+/**
+ * AMQEncoder delegates encoding of AMQP to a data encoder.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Delegate AMQP encoding. <td> {@link AMQDataBlockEncoder}
+ * </table>
+ *
+ * @todo This class just delegates to another, so seems to be pointless. Unless it is going to handle some
+ * responsibilities in the future, then drop it.
+ */
+public class AMQEncoder implements ProtocolEncoder
+{
+ /** The data encoder that is delegated to. */
+ private AMQDataBlockEncoder _dataBlockEncoder = new AMQDataBlockEncoder();
+
+ /**
+ * Encodes AMQP.
+ *
+ * @param session The Mina session.
+ * @param message The data object to encode.
+ * @param out The Mina writer to output the raw byte data to.
+ *
+ * @throws Exception If the data cannot be encoded for any reason.
+ */
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception
+ {
+ _dataBlockEncoder.encode(session, message, out);
+ }
+
+ /**
+ * Does nothing. Called by Mina to allow this to clean up resources when it is no longer needed.
+ *
+ * @param session The Mina session.
+ */
+ public void dispose(IoSession session)
+ { }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java
index 62ded5b2d8..0dd21238a7 100644
--- a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java
@@ -23,7 +23,7 @@ package org.apache.qpid.configuration;
*/
public class ClientProperties
{
-
+
/**
* Currently with Qpid it is not possible to change the client ID.
* If one is not specified upon connection construction, an id is generated automatically.
@@ -68,50 +68,67 @@ public class ClientProperties
* by the broker in TuneOK it will be used as the heartbeat interval.
* If not a warning will be printed and the max value specified for
* heartbeat in TuneOK will be used
- *
+ *
* The default idle timeout is set to 120 secs
*/
public static final String IDLE_TIMEOUT_PROP_NAME = "idle_timeout";
public static final long DEFAULT_IDLE_TIMEOUT = 120000;
-
+
public static final String HEARTBEAT = "qpid.heartbeat";
public static final int HEARTBEAT_DEFAULT = 120;
-
+
/**
* This value will be used to determine the default destination syntax type.
* Currently the two types are Binding URL (java only) and the Addressing format (used by
- * all clients).
+ * all clients).
*/
public static final String DEST_SYNTAX = "qpid.dest_syntax";
-
+
public static final String USE_LEGACY_MAP_MESSAGE_FORMAT = "qpid.use_legacy_map_message";
- public static final String AMQP_VERSION = "qpid.amqp.version";
-
- public static final String QPID_VERIFY_CLIENT_ID = "qpid.verify_client_id";
+ /**
+ * ==========================================================
+ * Those properties are used when the io size should be bounded
+ * ==========================================================
+ */
/**
- * System properties to change the default timeout used during
- * synchronous operations.
+ * When set to true the io layer throttle down producers and consumers
+ * when written or read messages are accumulating and exceeding a certain size.
+ * This is especially useful when a the producer rate is greater than the network
+ * speed.
+ * type: boolean
*/
- public static final String QPID_SYNC_OP_TIMEOUT = "qpid.sync_op_timeout";
- public static final String AMQJ_DEFAULT_SYNCWRITE_TIMEOUT = "amqj.default_syncwrite_timeout";
+ public static final String PROTECTIO_PROP_NAME = "protectio";
+ //=== The following properties are only used when the previous one is true.
/**
- * A default timeout value for synchronous operations
+ * Max size of read messages that can be stored within the MINA layer
+ * type: int
*/
- public static final int DEFAULT_SYNC_OPERATION_TIMEOUT = 60000;
+ public static final String READ_BUFFER_LIMIT_PROP_NAME = "qpid.read.buffer.limit";
+ public static final String READ_BUFFER_LIMIT_DEFAULT = "262144";
+ /**
+ * Max size of written messages that can be stored within the MINA layer
+ * type: int
+ */
+ public static final String WRITE_BUFFER_LIMIT_PROP_NAME = "qpid.read.buffer.limit";
+ public static final String WRITE_BUFFER_LIMIT_DEFAULT = "262144";
+ public static final String AMQP_VERSION = "qpid.amqp.version";
+
+ private static ClientProperties _instance = new ClientProperties();
+
/*
- public static final QpidProperty<Boolean> IGNORE_SET_CLIENTID_PROP_NAME =
+ public static final QpidProperty<Boolean> IGNORE_SET_CLIENTID_PROP_NAME =
QpidProperty.booleanProperty(false,"qpid.ignore_set_client_id","ignore_setclientID");
-
+
public static final QpidProperty<Boolean> SYNC_PERSISTENT_PROP_NAME =
QpidProperty.booleanProperty(false,"qpid.sync_persistence","sync_persistence");
-
-
+
+
public static final QpidProperty<Integer> MAX_PREFETCH_PROP_NAME =
QpidProperty.intProperty(500,"qpid.max_prefetch","max_prefetch"); */
-
-
+
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
index ebdad12178..fe04155bb8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.AMQException;
@@ -36,7 +34,7 @@ public interface AMQBody
*/
public abstract int getSize();
- public void writePayload(DataOutputStream buffer) throws IOException;
+ public void writePayload(ByteBuffer buffer);
- void handle(final int channelId, final AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException;
+ void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) throws AMQException;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
index 00c1f5aae5..a2fc3a03ef 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
@@ -20,10 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
/**
* A data block represents something that has a size in bytes and the ability to write itself to a byte
@@ -42,6 +39,25 @@ public abstract class AMQDataBlock implements EncodableAMQDataBlock
* Writes the datablock to the specified buffer.
* @param buffer
*/
- public abstract void writePayload(DataOutputStream buffer) throws IOException;
+ public abstract void writePayload(ByteBuffer buffer);
+
+ public ByteBuffer toByteBuffer()
+ {
+ final ByteBuffer buffer = ByteBuffer.allocate((int)getSize());
+
+ writePayload(buffer);
+ buffer.flip();
+ return buffer;
+ }
+
+ public java.nio.ByteBuffer toNioByteBuffer()
+ {
+ final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate((int) getSize());
+
+ ByteBuffer buf = ByteBuffer.wrap(buffer);
+ writePayload(buf);
+ buffer.flip();
+ return buffer;
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
index 2165cadd14..228867b2b0 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
@@ -20,14 +20,18 @@
*/
package org.apache.qpid.framing;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.DataInputStream;
-import java.io.IOException;
-
public class AMQDataBlockDecoder
{
+ private static final String SESSION_METHOD_BODY_FACTORY = "QPID_SESSION_METHOD_BODY_FACTORY";
private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE];
@@ -43,32 +47,27 @@ public class AMQDataBlockDecoder
public AMQDataBlockDecoder()
{ }
- public boolean decodable(DataInputStream in) throws AMQFrameDecodingException, IOException
+ public boolean decodable(java.nio.ByteBuffer in) throws AMQFrameDecodingException
{
- final int remainingAfterAttributes = in.available() - (1 + 2 + 4 + 1);
+ final int remainingAfterAttributes = in.remaining() - (1 + 2 + 4 + 1);
// type, channel, body length and end byte
if (remainingAfterAttributes < 0)
{
return false;
}
- in.mark(8);
- in.skip(1 + 2);
-
-
+ in.position(in.position() + 1 + 2);
// Get an unsigned int, lifted from MINA ByteBuffer getUnsignedInt()
- final long bodySize = in.readInt() & 0xffffffffL;
-
- in.reset();
+ final long bodySize = in.getInt() & 0xffffffffL;
return (remainingAfterAttributes >= bodySize);
}
- public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, DataInputStream in)
- throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
+ public AMQFrame createAndPopulateFrame(AMQMethodBodyFactory methodBodyFactory, ByteBuffer in)
+ throws AMQFrameDecodingException, AMQProtocolVersionException
{
- final byte type = in.readByte();
+ final byte type = in.get();
BodyFactory bodyFactory;
if (type == AMQMethodBody.TYPE)
@@ -85,8 +84,8 @@ public class AMQDataBlockDecoder
throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null);
}
- final int channel = in.readUnsignedShort();
- final long bodySize = EncodingUtils.readUnsignedInteger(in);
+ final int channel = in.getUnsignedShort();
+ final long bodySize = in.getUnsignedInt();
// bodySize can be zero
if ((channel < 0) || (bodySize < 0))
@@ -97,7 +96,7 @@ public class AMQDataBlockDecoder
AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory);
- byte marker = in.readByte();
+ byte marker = in.get();
if ((marker & 0xFF) != 0xCE)
{
throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize
@@ -107,4 +106,26 @@ public class AMQDataBlockDecoder
return frame;
}
+ public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception
+ {
+ AMQMethodBodyFactory bodyFactory = (AMQMethodBodyFactory) session.getAttribute(SESSION_METHOD_BODY_FACTORY);
+ if (bodyFactory == null)
+ {
+ AMQVersionAwareProtocolSession protocolSession = (AMQVersionAwareProtocolSession) session.getAttachment();
+ bodyFactory = new AMQMethodBodyFactory(protocolSession);
+ session.setAttribute(SESSION_METHOD_BODY_FACTORY, bodyFactory);
+ }
+
+ out.write(createAndPopulateFrame(bodyFactory, in));
+ }
+
+ public boolean decodable(ByteBuffer msg) throws AMQFrameDecodingException
+ {
+ return decodable(msg.buf());
+ }
+
+ public AMQDataBlock createAndPopulateFrame(AMQMethodBodyFactory factory, java.nio.ByteBuffer msg) throws AMQProtocolVersionException, AMQFrameDecodingException
+ {
+ return createAndPopulateFrame(factory, ByteBuffer.wrap(msg));
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java
new file mode 100644
index 0000000000..374644b4f2
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockEncoder.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.filter.codec.demux.MessageEncoder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Set;
+
+public final class AMQDataBlockEncoder implements MessageEncoder
+{
+ private static final Logger _logger = LoggerFactory.getLogger(AMQDataBlockEncoder.class);
+
+ private final Set _messageTypes = Collections.singleton(EncodableAMQDataBlock.class);
+
+ public AMQDataBlockEncoder()
+ { }
+
+ public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception
+ {
+ final AMQDataBlock frame = (AMQDataBlock) message;
+
+ final ByteBuffer buffer = frame.toByteBuffer();
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Encoded frame byte-buffer is '" + EncodingUtils.convertToHexString(buffer) + "'");
+ }
+
+ out.write(buffer);
+ }
+
+ public Set getMessageTypes()
+ {
+ return _messageTypes;
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
index 6acf60a5b3..02a46f3748 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
{
@@ -38,7 +36,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
_bodyFrame = bodyFrame;
}
- public AMQFrame(final DataInputStream in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException, IOException
+ public AMQFrame(final ByteBuffer in, final int channel, final long bodySize, final BodyFactory bodyFactory) throws AMQFrameDecodingException
{
this._channel = channel;
this._bodyFrame = bodyFactory.createBody(in,bodySize);
@@ -55,13 +53,13 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
- buffer.writeByte(_bodyFrame.getFrameType());
+ buffer.put(_bodyFrame.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, _channel);
EncodingUtils.writeUnsignedInteger(buffer, _bodyFrame.getSize());
_bodyFrame.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
+ buffer.put(FRAME_END_BYTE);
}
public final int getChannel()
@@ -79,48 +77,48 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
return "Frame channelId: " + _channel + ", bodyFrame: " + String.valueOf(_bodyFrame);
}
- public static void writeFrame(DataOutputStream buffer, final int channel, AMQBody body) throws IOException
+ public static void writeFrame(ByteBuffer buffer, final int channel, AMQBody body)
{
- buffer.writeByte(body.getFrameType());
+ buffer.put(body.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body.getSize());
body.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
+ buffer.put(FRAME_END_BYTE);
}
- public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2) throws IOException
+ public static void writeFrames(ByteBuffer buffer, final int channel, AMQBody body1, AMQBody body2)
{
- buffer.writeByte(body1.getFrameType());
+ buffer.put(body1.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body1.getSize());
body1.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
- buffer.writeByte(body2.getFrameType());
+ buffer.put(FRAME_END_BYTE);
+ buffer.put(body2.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body2.getSize());
body2.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
+ buffer.put(FRAME_END_BYTE);
}
- public static void writeFrames(DataOutputStream buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3) throws IOException
+ public static void writeFrames(ByteBuffer buffer, final int channel, AMQBody body1, AMQBody body2, AMQBody body3)
{
- buffer.writeByte(body1.getFrameType());
+ buffer.put(body1.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body1.getSize());
body1.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
- buffer.writeByte(body2.getFrameType());
+ buffer.put(FRAME_END_BYTE);
+ buffer.put(body2.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body2.getSize());
body2.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
- buffer.writeByte(body3.getFrameType());
+ buffer.put(FRAME_END_BYTE);
+ buffer.put(body3.getFrameType());
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, body3.getSize());
body3.writePayload(buffer);
- buffer.writeByte(FRAME_END_BYTE);
+ buffer.put(FRAME_END_BYTE);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
index a076d0e5a1..4763b22290 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
@@ -20,14 +20,12 @@
*/
package org.apache.qpid.framing;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
public interface AMQMethodBody extends AMQBody
{
public static final byte TYPE = 1;
@@ -45,12 +43,12 @@ public interface AMQMethodBody extends AMQBody
/** @return unsigned short */
public int getMethod();
- public void writeMethodPayload(DataOutputStream buffer) throws IOException;
+ public void writeMethodPayload(ByteBuffer buffer);
public int getSize();
- public void writePayload(DataOutputStream buffer) throws IOException;
+ public void writePayload(ByteBuffer buffer);
//public abstract void populateMethodBodyFromBuffer(ByteBuffer buffer) throws AMQFrameDecodingException;
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java
index 7fceb082ee..1a7022c11b 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyFactory.java
@@ -20,14 +20,13 @@
*/
package org.apache.qpid.framing;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.DataInputStream;
-import java.io.IOException;
-
public class AMQMethodBodyFactory implements BodyFactory
{
private static final Logger _log = LoggerFactory.getLogger(AMQMethodBodyFactory.class);
@@ -39,7 +38,7 @@ public class AMQMethodBodyFactory implements BodyFactory
_protocolSession = protocolSession;
}
- public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException
+ public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException
{
return _protocolSession.getMethodRegistry().convertToBody(in, bodySize);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
index c73c1df701..cd3d721065 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
@@ -21,16 +21,13 @@ package org.apache.qpid.framing;
*
*/
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
public abstract class AMQMethodBodyImpl implements AMQMethodBody
{
public static final byte TYPE = 1;
@@ -101,7 +98,7 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody
return 2 + 2 + getBodySize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
EncodingUtils.writeUnsignedShort(buffer, getClazz());
EncodingUtils.writeUnsignedShort(buffer, getMethod());
@@ -109,12 +106,12 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody
}
- protected byte readByte(DataInputStream buffer) throws IOException
+ protected byte readByte(ByteBuffer buffer)
{
- return buffer.readByte();
+ return buffer.get();
}
- protected AMQShortString readAMQShortString(DataInputStream buffer) throws IOException
+ protected AMQShortString readAMQShortString(ByteBuffer buffer)
{
return EncodingUtils.readAMQShortString(buffer);
}
@@ -124,27 +121,27 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody
return EncodingUtils.encodedShortStringLength(string);
}
- protected void writeByte(DataOutputStream buffer, byte b) throws IOException
+ protected void writeByte(ByteBuffer buffer, byte b)
{
- buffer.writeByte(b);
+ buffer.put(b);
}
- protected void writeAMQShortString(DataOutputStream buffer, AMQShortString string) throws IOException
+ protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string)
{
EncodingUtils.writeShortStringBytes(buffer, string);
}
- protected int readInt(DataInputStream buffer) throws IOException
+ protected int readInt(ByteBuffer buffer)
{
- return buffer.readInt();
+ return buffer.getInt();
}
- protected void writeInt(DataOutputStream buffer, int i) throws IOException
+ protected void writeInt(ByteBuffer buffer, int i)
{
- buffer.writeInt(i);
+ buffer.putInt(i);
}
- protected FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException
+ protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
{
return EncodingUtils.readFieldTable(buffer);
}
@@ -154,19 +151,19 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody
return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates.
}
- protected void writeFieldTable(DataOutputStream buffer, FieldTable table) throws IOException
+ protected void writeFieldTable(ByteBuffer buffer, FieldTable table)
{
EncodingUtils.writeFieldTableBytes(buffer, table);
}
- protected long readLong(DataInputStream buffer) throws IOException
+ protected long readLong(ByteBuffer buffer)
{
- return buffer.readLong();
+ return buffer.getLong();
}
- protected void writeLong(DataOutputStream buffer, long l) throws IOException
+ protected void writeLong(ByteBuffer buffer, long l)
{
- buffer.writeLong(l);
+ buffer.putLong(l);
}
protected int getSizeOf(byte[] response)
@@ -174,86 +171,87 @@ public abstract class AMQMethodBodyImpl implements AMQMethodBody
return (response == null) ? 4 : response.length + 4;
}
- protected void writeBytes(DataOutputStream buffer, byte[] data) throws IOException
+ protected void writeBytes(ByteBuffer buffer, byte[] data)
{
EncodingUtils.writeBytes(buffer,data);
}
- protected byte[] readBytes(DataInputStream buffer) throws IOException
+ protected byte[] readBytes(ByteBuffer buffer)
{
return EncodingUtils.readBytes(buffer);
}
- protected short readShort(DataInputStream buffer) throws IOException
+ protected short readShort(ByteBuffer buffer)
{
return EncodingUtils.readShort(buffer);
}
- protected void writeShort(DataOutputStream buffer, short s) throws IOException
+ protected void writeShort(ByteBuffer buffer, short s)
{
EncodingUtils.writeShort(buffer, s);
}
- protected Content readContent(DataInputStream buffer)
+ protected Content readContent(ByteBuffer buffer)
{
- return null;
+ return null; //To change body of created methods use File | Settings | File Templates.
}
protected int getSizeOf(Content body)
{
- return 0;
+ return 0; //To change body of created methods use File | Settings | File Templates.
}
- protected void writeContent(DataOutputStream buffer, Content body)
+ protected void writeContent(ByteBuffer buffer, Content body)
{
+ //To change body of created methods use File | Settings | File Templates.
}
- protected byte readBitfield(DataInputStream buffer) throws IOException
+ protected byte readBitfield(ByteBuffer buffer)
{
- return readByte(buffer);
+ return readByte(buffer); //To change body of created methods use File | Settings | File Templates.
}
- protected int readUnsignedShort(DataInputStream buffer) throws IOException
+ protected int readUnsignedShort(ByteBuffer buffer)
{
- return buffer.readUnsignedShort();
+ return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates.
}
- protected void writeBitfield(DataOutputStream buffer, byte bitfield0) throws IOException
+ protected void writeBitfield(ByteBuffer buffer, byte bitfield0)
{
- buffer.writeByte(bitfield0);
+ buffer.put(bitfield0);
}
- protected void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException
+ protected void writeUnsignedShort(ByteBuffer buffer, int s)
{
EncodingUtils.writeUnsignedShort(buffer, s);
}
- protected long readUnsignedInteger(DataInputStream buffer) throws IOException
+ protected long readUnsignedInteger(ByteBuffer buffer)
{
- return EncodingUtils.readUnsignedInteger(buffer);
+ return buffer.getUnsignedInt();
}
- protected void writeUnsignedInteger(DataOutputStream buffer, long i) throws IOException
+ protected void writeUnsignedInteger(ByteBuffer buffer, long i)
{
EncodingUtils.writeUnsignedInteger(buffer, i);
}
- protected short readUnsignedByte(DataInputStream buffer) throws IOException
+ protected short readUnsignedByte(ByteBuffer buffer)
{
- return (short) buffer.readUnsignedByte();
+ return buffer.getUnsigned();
}
- protected void writeUnsignedByte(DataOutputStream buffer, short unsignedByte) throws IOException
+ protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte)
{
EncodingUtils.writeUnsignedByte(buffer, unsignedByte);
}
- protected long readTimestamp(DataInputStream buffer) throws IOException
+ protected long readTimestamp(ByteBuffer buffer)
{
return EncodingUtils.readTimestamp(buffer);
}
- protected void writeTimestamp(DataOutputStream buffer, long t) throws IOException
+ protected void writeTimestamp(ByteBuffer buffer, long t)
{
EncodingUtils.writeTimestamp(buffer, t);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
index df4d8bdcb6..0c61d9db3c 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
@@ -21,11 +21,10 @@
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
public abstract interface AMQMethodBodyInstanceFactory
{
- public AMQMethodBody newInstance(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException;
+ public AMQMethodBody newInstance(ByteBuffer buffer, long size) throws AMQFrameDecodingException;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java
new file mode 100644
index 0000000000..bfcc38ad60
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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 org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+
+public interface AMQMethodFactory
+{
+
+ // Connection Methods
+
+ ConnectionCloseBody createConnectionClose();
+
+ // Access Methods
+
+ AccessRequestBody createAccessRequest(boolean active, boolean exclusive, boolean passive, boolean read, AMQShortString realm, boolean write);
+
+
+ // Tx Methods
+
+ TxSelectBody createTxSelect();
+
+ TxCommitBody createTxCommit();
+
+ TxRollbackBody createTxRollback();
+
+ // Channel Methods
+
+ ChannelOpenBody createChannelOpen();
+
+ ChannelCloseBody createChannelClose(int replyCode, AMQShortString replyText);
+
+ ChannelFlowBody createChannelFlow(boolean active);
+
+
+ // Exchange Methods
+
+
+ ExchangeBoundBody createExchangeBound(AMQShortString exchangeName,
+ AMQShortString queueName,
+ AMQShortString routingKey);
+
+ ExchangeDeclareBody createExchangeDeclare(AMQShortString name, AMQShortString type, int ticket);
+
+
+ // Queue Methods
+
+ QueueDeclareBody createQueueDeclare(AMQShortString name, FieldTable arguments, boolean autoDelete, boolean durable, boolean exclusive, boolean passive, int ticket);
+
+ QueueBindBody createQueueBind(AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey, FieldTable arguments, int ticket);
+
+ QueueDeleteBody createQueueDelete(AMQShortString queueName, boolean ifEmpty, boolean ifUnused, int ticket);
+
+
+ // Message Methods
+
+ // In different versions of the protocol we change the class used for message transfer
+ // abstract this out so the appropriate methods are created
+ AMQMethodBody createRecover(boolean requeue);
+
+ AMQMethodBody createConsumer(AMQShortString tag, AMQShortString queueName, FieldTable arguments, boolean noAck, boolean exclusive, boolean noLocal, int ticket);
+
+ AMQMethodBody createConsumerCancel(AMQShortString consumerTag);
+
+ AMQMethodBody createAcknowledge(long deliveryTag, boolean multiple);
+
+ AMQMethodBody createRejectBody(long deliveryTag, boolean requeue);
+
+ AMQMethodBody createMessageQos(int prefetchCount, int prefetchSize);
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
index cc9a33f4cf..39a9beb9e8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
@@ -21,12 +21,11 @@
package org.apache.qpid.framing;
+import org.apache.mina.common.ByteBuffer;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.util.*;
import java.lang.ref.WeakReference;
@@ -38,10 +37,6 @@ import java.lang.ref.WeakReference;
*/
public final class AMQShortString implements CharSequence, Comparable<AMQShortString>
{
- /**
- * The maximum number of octets in AMQ short string as defined in AMQP specification
- */
- public static final int MAX_LENGTH = 255;
private static final byte MINUS = (byte)'-';
private static final byte ZERO = (byte) '0';
@@ -123,19 +118,22 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
public AMQShortString(byte[] data)
{
- if (data == null)
- {
- throw new NullPointerException("Cannot create AMQShortString with null data[]");
- }
- if (data.length > MAX_LENGTH)
- {
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
- }
+
_data = data.clone();
_length = data.length;
_offset = 0;
}
+ public AMQShortString(byte[] data, int pos)
+ {
+ final int size = data[pos++];
+ final byte[] dataCopy = new byte[size];
+ System.arraycopy(data,pos,dataCopy,0,size);
+ _length = size;
+ _data = dataCopy;
+ _offset = 0;
+ }
+
public AMQShortString(String data)
{
this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray());
@@ -148,12 +146,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
{
throw new NullPointerException("Cannot create AMQShortString with null char[]");
}
- // the current implementation of 0.8/0.9.x short string encoding
- // supports only ASCII characters
- if (data.length> MAX_LENGTH)
- {
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
- }
+
final int length = data.length;
final byte[] stringBytes = new byte[length];
int hash = 0;
@@ -172,17 +165,6 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
public AMQShortString(CharSequence charSequence)
{
- if (charSequence == null)
- {
- // it should be possible to create short string for null data
- charSequence = "";
- }
- // the current implementation of 0.8/0.9.x short string encoding
- // supports only ASCII characters
- if (charSequence.length() > MAX_LENGTH)
- {
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
- }
final int length = charSequence.length();
final byte[] stringBytes = new byte[length];
int hash = 0;
@@ -200,33 +182,31 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
}
- private AMQShortString(DataInputStream data, final int length) throws IOException
+ private AMQShortString(ByteBuffer data, final int length)
{
- if (length > MAX_LENGTH)
+ if(data.isDirect() || data.isReadOnly())
{
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+ byte[] dataBytes = new byte[length];
+ data.get(dataBytes);
+ _data = dataBytes;
+ _offset = 0;
+ }
+ else
+ {
+
+ _data = data.array();
+ _offset = data.arrayOffset() + data.position();
+ data.skip(length);
+
}
- byte[] dataBytes = new byte[length];
- data.read(dataBytes);
- _data = dataBytes;
- _offset = 0;
_length = length;
}
private AMQShortString(final byte[] data, final int from, final int to)
{
- if (data == null)
- {
- throw new NullPointerException("Cannot create AMQShortString with null data[]");
- }
- int length = to - from;
- if (length > MAX_LENGTH)
- {
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
- }
_offset = from;
- _length = length;
+ _length = to - from;
_data = data;
}
@@ -265,9 +245,32 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
return new CharSubSequence(start, end);
}
- public static AMQShortString readFromBuffer(DataInputStream buffer) throws IOException
+ public int writeToByteArray(byte[] encoding, int pos)
+ {
+ final int size = length();
+ encoding[pos++] = (byte) size;
+ System.arraycopy(_data,_offset,encoding,pos,size);
+ return pos+size;
+ }
+
+ public static AMQShortString readFromByteArray(byte[] byteEncodedDestination, int pos)
+ {
+
+
+ final AMQShortString shortString = new AMQShortString(byteEncodedDestination, pos);
+ if(shortString.length() == 0)
+ {
+ return null;
+ }
+ else
+ {
+ return shortString;
+ }
+ }
+
+ public static AMQShortString readFromBuffer(ByteBuffer buffer)
{
- final int length = buffer.readUnsignedByte();
+ final short length = buffer.getUnsigned();
if (length == 0)
{
return null;
@@ -293,13 +296,13 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
}
}
- public void writeToBuffer(DataOutputStream buffer) throws IOException
+ public void writeToBuffer(ByteBuffer buffer)
{
final int size = length();
//buffer.setAutoExpand(true);
- buffer.write((byte) size);
- buffer.write(_data, _offset, size);
+ buffer.put((byte) size);
+ buffer.put(_data, _offset, size);
}
@@ -687,10 +690,6 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
size += term.length();
}
- if (size > MAX_LENGTH)
- {
- throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
- }
byte[] data = new byte[size];
int pos = 0;
final byte[] delimData = delim._data;
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
index f3da64e639..14fb63da03 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
@@ -20,9 +20,8 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
+
import java.math.BigDecimal;
/**
@@ -61,12 +60,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLongStringBytes(buffer, (String) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLongString(buffer);
}
@@ -107,12 +106,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeUnsignedInteger(buffer, (Long) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readUnsignedInteger(buffer);
}
@@ -138,7 +137,7 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
BigDecimal bd = (BigDecimal) value;
@@ -151,7 +150,7 @@ public enum AMQType
EncodingUtils.writeInteger(buffer, unscaled);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
byte places = EncodingUtils.readByte(buffer);
@@ -183,12 +182,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLong(buffer, (Long) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLong(buffer);
}
@@ -247,7 +246,7 @@ public enum AMQType
* @param value An instance of the type.
* @param buffer The byte buffer to write it to.
*/
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
// Ensure that the value is a FieldTable.
if (!(value instanceof FieldTable))
@@ -268,7 +267,7 @@ public enum AMQType
*
* @return An instance of the type.
*/
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
try
{
@@ -302,10 +301,10 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer)
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{ }
- public Object readValueFromBuffer(DataInputStream buffer)
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return null;
}
@@ -331,12 +330,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLongstr(buffer, (byte[]) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLongstr(buffer);
}
@@ -361,12 +360,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLongStringBytes(buffer, (String) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLongString(buffer);
}
@@ -392,12 +391,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLongStringBytes(buffer, (String) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLongString(buffer);
}
@@ -427,12 +426,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeBoolean(buffer, (Boolean) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readBoolean(buffer);
}
@@ -462,12 +461,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeChar(buffer, (Character) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readChar(buffer);
}
@@ -497,12 +496,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeByte(buffer, (Byte) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readByte(buffer);
}
@@ -536,12 +535,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeShort(buffer, (Short) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readShort(buffer);
}
@@ -578,12 +577,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeInteger(buffer, (Integer) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readInteger(buffer);
}
@@ -625,12 +624,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeLong(buffer, (Long) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readLong(buffer);
}
@@ -660,12 +659,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeFloat(buffer, (Float) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readFloat(buffer);
}
@@ -699,12 +698,12 @@ public enum AMQType
}
}
- public void writeValueImpl(Object value, DataOutputStream buffer) throws IOException
+ public void writeValueImpl(Object value, ByteBuffer buffer)
{
EncodingUtils.writeDouble(buffer, (Double) value);
}
- public Object readValueFromBuffer(DataInputStream buffer) throws IOException
+ public Object readValueFromBuffer(ByteBuffer buffer)
{
return EncodingUtils.readDouble(buffer);
}
@@ -771,9 +770,9 @@ public enum AMQType
* @param value An instance of the type.
* @param buffer The byte buffer to write it to.
*/
- public void writeToBuffer(Object value, DataOutputStream buffer) throws IOException
+ public void writeToBuffer(Object value, ByteBuffer buffer)
{
- buffer.writeByte(identifier());
+ buffer.put(identifier());
writeValueImpl(value, buffer);
}
@@ -783,7 +782,7 @@ public enum AMQType
* @param value An instance of the type.
* @param buffer The byte buffer to write it to.
*/
- abstract void writeValueImpl(Object value, DataOutputStream buffer) throws IOException;
+ abstract void writeValueImpl(Object value, ByteBuffer buffer);
/**
* Reads an instance of the type from a specified byte buffer.
@@ -792,5 +791,5 @@ public enum AMQType
*
* @return An instance of the type.
*/
- abstract Object readValueFromBuffer(DataInputStream buffer) throws IOException;
+ abstract Object readValueFromBuffer(ByteBuffer buffer);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
index 1dbedca362..647d531476 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
@@ -20,9 +20,8 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
+
import java.util.Date;
import java.util.Map;
import java.math.BigDecimal;
@@ -61,7 +60,7 @@ public class AMQTypedValue
_value = type.toNativeValue(value);
}
- private AMQTypedValue(AMQType type, DataInputStream buffer) throws IOException
+ private AMQTypedValue(AMQType type, ByteBuffer buffer)
{
_type = type;
_value = type.readValueFromBuffer(buffer);
@@ -77,7 +76,7 @@ public class AMQTypedValue
return _value;
}
- public void writeToBuffer(DataOutputStream buffer) throws IOException
+ public void writeToBuffer(ByteBuffer buffer)
{
_type.writeToBuffer(_value, buffer);
}
@@ -87,9 +86,9 @@ public class AMQTypedValue
return _type.getEncodingSize(_value);
}
- public static AMQTypedValue readFromBuffer(DataInputStream buffer) throws IOException
+ public static AMQTypedValue readFromBuffer(ByteBuffer buffer)
{
- AMQType type = AMQTypeMap.getType(buffer.readByte());
+ AMQType type = AMQTypeMap.getType(buffer.get());
return new AMQTypedValue(type, buffer);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
index 57622b5054..c7d89a9927 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +35,27 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
private static final AMQShortString ZERO_STRING = null;
+ /**
+ * We store the encoded form when we decode the content header so that if we need to write it out without modifying
+ * it we can do so without incurring the expense of reencoding it
+ */
+ private byte[] _encodedForm;
+
+ /** Flag indicating whether the entire content header has been decoded yet */
+ private boolean _decoded = true;
+
+ /**
+ * We have some optimisations for partial decoding for maximum performance. The headers are used in the broker for
+ * routing in some cases so we can decode that separately.
+ */
+ private boolean _decodedHeaders = true;
+
+ /**
+ * We have some optimisations for partial decoding for maximum performance. The content type is used by all clients
+ * to determine the message type
+ */
+ private boolean _decodedContentType = true;
+
private AMQShortString _contentType;
private AMQShortString _encoding;
@@ -67,10 +86,10 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
private int _propertyFlags = 0;
private static final int CONTENT_TYPE_MASK = 1 << 15;
- private static final int ENCODING_MASK = 1 << 14;
+ private static final int ENCONDING_MASK = 1 << 14;
private static final int HEADERS_MASK = 1 << 13;
private static final int DELIVERY_MODE_MASK = 1 << 12;
- private static final int PRIORITY_MASK = 1 << 11;
+ private static final int PROPRITY_MASK = 1 << 11;
private static final int CORRELATION_ID_MASK = 1 << 10;
private static final int REPLY_TO_MASK = 1 << 9;
private static final int EXPIRATION_MASK = 1 << 8;
@@ -82,11 +101,34 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
private static final int CLUSTER_ID_MASK = 1 << 2;
+ /**
+ * This is 0_10 specific. We use this property to check if some message properties have been changed.
+ */
+ private boolean _hasBeenUpdated = false;
+
+ public boolean reset()
+ {
+ boolean result = _hasBeenUpdated;
+ _hasBeenUpdated = false;
+ return result;
+ }
+
+ public void updated()
+ {
+ _hasBeenUpdated = true;
+ }
+
public BasicContentHeaderProperties()
{ }
public int getPropertyListSize()
{
+ if (_encodedForm != null)
+ {
+ return _encodedForm.length;
+ }
+ else
+ {
int size = 0;
if ((_propertyFlags & (CONTENT_TYPE_MASK)) > 0)
@@ -94,7 +136,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
size += EncodingUtils.encodedShortStringLength(_contentType);
}
- if ((_propertyFlags & ENCODING_MASK) > 0)
+ if ((_propertyFlags & ENCONDING_MASK) > 0)
{
size += EncodingUtils.encodedShortStringLength(_encoding);
}
@@ -109,7 +151,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
size += 1;
}
- if ((_propertyFlags & PRIORITY_MASK) > 0)
+ if ((_propertyFlags & PROPRITY_MASK) > 0)
{
size += 1;
}
@@ -167,10 +209,23 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
}
return size;
+ }
+ }
+
+ private void clearEncodedForm()
+ {
+ if (!_decoded && (_encodedForm != null))
+ {
+ // decode();
+ }
+
+ _encodedForm = null;
}
public void setPropertyFlags(int propertyFlags)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags = propertyFlags;
}
@@ -179,87 +234,94 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
return _propertyFlags;
}
- public void writePropertyListPayload(DataOutputStream buffer) throws IOException
+ public void writePropertyListPayload(ByteBuffer buffer)
{
- if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0)
+ if (_encodedForm != null)
{
- EncodingUtils.writeShortStringBytes(buffer, _contentType);
+ buffer.put(_encodedForm);
}
-
- if ((_propertyFlags & ENCODING_MASK) != 0)
+ else
{
- EncodingUtils.writeShortStringBytes(buffer, _encoding);
- }
+ if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _contentType);
+ }
- if ((_propertyFlags & HEADERS_MASK) != 0)
- {
- EncodingUtils.writeFieldTableBytes(buffer, _headers);
- }
+ if ((_propertyFlags & ENCONDING_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _encoding);
+ }
- if ((_propertyFlags & DELIVERY_MODE_MASK) != 0)
- {
- buffer.writeByte(_deliveryMode);
- }
+ if ((_propertyFlags & HEADERS_MASK) != 0)
+ {
+ EncodingUtils.writeFieldTableBytes(buffer, _headers);
+ }
- if ((_propertyFlags & PRIORITY_MASK) != 0)
- {
- buffer.writeByte(_priority);
- }
+ if ((_propertyFlags & DELIVERY_MODE_MASK) != 0)
+ {
+ buffer.put(_deliveryMode);
+ }
- if ((_propertyFlags & CORRELATION_ID_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _correlationId);
- }
+ if ((_propertyFlags & PROPRITY_MASK) != 0)
+ {
+ buffer.put(_priority);
+ }
- if ((_propertyFlags & REPLY_TO_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _replyTo);
- }
+ if ((_propertyFlags & CORRELATION_ID_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _correlationId);
+ }
- if ((_propertyFlags & EXPIRATION_MASK) != 0)
- {
- if (_expiration == 0L)
+ if ((_propertyFlags & REPLY_TO_MASK) != 0)
{
- EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING);
+ EncodingUtils.writeShortStringBytes(buffer, _replyTo);
}
- else
+
+ if ((_propertyFlags & EXPIRATION_MASK) != 0)
{
- EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration));
+ if (_expiration == 0L)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, ZERO_STRING);
+ }
+ else
+ {
+ EncodingUtils.writeShortStringBytes(buffer, String.valueOf(_expiration));
+ }
}
- }
- if ((_propertyFlags & MESSAGE_ID_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _messageId);
- }
+ if ((_propertyFlags & MESSAGE_ID_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _messageId);
+ }
- if ((_propertyFlags & TIMESTAMP_MASK) != 0)
- {
- EncodingUtils.writeTimestamp(buffer, _timestamp);
- }
+ if ((_propertyFlags & TIMESTAMP_MASK) != 0)
+ {
+ EncodingUtils.writeTimestamp(buffer, _timestamp);
+ }
- if ((_propertyFlags & TYPE_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _type);
- }
+ if ((_propertyFlags & TYPE_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _type);
+ }
- if ((_propertyFlags & USER_ID_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _userId);
- }
+ if ((_propertyFlags & USER_ID_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _userId);
+ }
- if ((_propertyFlags & APPLICATION_ID_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _appId);
- }
+ if ((_propertyFlags & APPLICATION_ID_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _appId);
+ }
- if ((_propertyFlags & CLUSTER_ID_MASK) != 0)
- {
- EncodingUtils.writeShortStringBytes(buffer, _clusterId);
+ if ((_propertyFlags & CLUSTER_ID_MASK) != 0)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, _clusterId);
+ }
}
}
- public void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException
+ public void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size) throws AMQFrameDecodingException
{
_propertyFlags = propertyFlags;
@@ -269,18 +331,25 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
}
decode(buffer);
+ /*_encodedForm = new byte[size];
+ buffer.get(_encodedForm, 0, size);
+ _decoded = false;
+ _decodedHeaders = false;
+ _decodedContentType = false;*/
}
- private void decode(DataInputStream buffer) throws IOException, AMQFrameDecodingException
+ private void decode(ByteBuffer buffer)
{
// ByteBuffer buffer = ByteBuffer.wrap(_encodedForm);
-
+ int pos = buffer.position();
+ try
+ {
if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0)
{
_contentType = EncodingUtils.readAMQShortString(buffer);
}
- if ((_propertyFlags & ENCODING_MASK) != 0)
+ if ((_propertyFlags & ENCONDING_MASK) != 0)
{
_encoding = EncodingUtils.readAMQShortString(buffer);
}
@@ -292,12 +361,12 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
if ((_propertyFlags & DELIVERY_MODE_MASK) != 0)
{
- _deliveryMode = buffer.readByte();
+ _deliveryMode = buffer.get();
}
- if ((_propertyFlags & PRIORITY_MASK) != 0)
+ if ((_propertyFlags & PROPRITY_MASK) != 0)
{
- _priority = buffer.readByte();
+ _priority = buffer.get();
}
if ((_propertyFlags & CORRELATION_ID_MASK) != 0)
@@ -344,29 +413,116 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
{
_clusterId = EncodingUtils.readAMQShortString(buffer);
}
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ throw new RuntimeException("Error in content header data: " + e, e);
+ }
+ final int endPos = buffer.position();
+ buffer.position(pos);
+ final int len = endPos - pos;
+ _encodedForm = new byte[len];
+ final int limit = buffer.limit();
+ buffer.limit(endPos);
+ buffer.get(_encodedForm, 0, len);
+ buffer.limit(limit);
+ buffer.position(endPos);
+ _decoded = true;
+ }
+ private void decodeUpToHeaders()
+ {
+ ByteBuffer buffer = ByteBuffer.wrap(_encodedForm);
+ try
+ {
+ if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0)
+ {
+ byte length = buffer.get();
+ buffer.skip(length);
+ }
+
+ if ((_propertyFlags & ENCONDING_MASK) != 0)
+ {
+ byte length = buffer.get();
+ buffer.skip(length);
+ }
+
+ if ((_propertyFlags & HEADERS_MASK) != 0)
+ {
+ _headers = EncodingUtils.readFieldTable(buffer);
+
+ }
+
+ _decodedHeaders = true;
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ throw new RuntimeException("Error in content header data: " + e, e);
+ }
}
+ private void decodeUpToContentType()
+ {
+ ByteBuffer buffer = ByteBuffer.wrap(_encodedForm);
+
+ if ((_propertyFlags & (CONTENT_TYPE_MASK)) != 0)
+ {
+ _contentType = EncodingUtils.readAMQShortString(buffer);
+ }
+
+ _decodedContentType = true;
+ }
+
+ private void decodeIfNecessary()
+ {
+ if (!_decoded)
+ {
+ // decode();
+ }
+ }
+
+ private void decodeHeadersIfNecessary()
+ {
+ if (!_decoded && !_decodedHeaders)
+ {
+ decodeUpToHeaders();
+ }
+ }
+
+ private void decodeContentTypeIfNecessary()
+ {
+ if (!_decoded && !_decodedContentType)
+ {
+ decodeUpToContentType();
+ }
+ }
public AMQShortString getContentType()
{
+ decodeContentTypeIfNecessary();
+
return _contentType;
}
public String getContentTypeAsString()
{
+ decodeContentTypeIfNecessary();
+
return (_contentType == null) ? null : _contentType.toString();
}
public void setContentType(AMQShortString contentType)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= (CONTENT_TYPE_MASK);
_contentType = contentType;
}
public void setContentType(String contentType)
{
+ _hasBeenUpdated = true;
setContentType((contentType == null) ? null : new AMQShortString(contentType));
}
@@ -378,23 +534,31 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
public AMQShortString getEncoding()
{
+ decodeIfNecessary();
+
return _encoding;
}
public void setEncoding(String encoding)
{
- _propertyFlags |= ENCODING_MASK;
+ _hasBeenUpdated = true;
+ clearEncodedForm();
+ _propertyFlags |= ENCONDING_MASK;
_encoding = (encoding == null) ? null : new AMQShortString(encoding);
}
public void setEncoding(AMQShortString encoding)
{
- _propertyFlags |= ENCODING_MASK;
+ _hasBeenUpdated = true;
+ clearEncodedForm();
+ _propertyFlags |= ENCONDING_MASK;
_encoding = encoding;
}
public FieldTable getHeaders()
{
+ decodeHeadersIfNecessary();
+
if (_headers == null)
{
setHeaders(FieldTableFactory.newFieldTable());
@@ -405,146 +569,191 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
public void setHeaders(FieldTable headers)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= HEADERS_MASK;
_headers = headers;
}
public byte getDeliveryMode()
{
+ decodeIfNecessary();
+
return _deliveryMode;
}
public void setDeliveryMode(byte deliveryMode)
{
+ clearEncodedForm();
_propertyFlags |= DELIVERY_MODE_MASK;
_deliveryMode = deliveryMode;
}
public byte getPriority()
{
+ decodeIfNecessary();
+
return _priority;
}
public void setPriority(byte priority)
{
- _propertyFlags |= PRIORITY_MASK;
+ clearEncodedForm();
+ _propertyFlags |= PROPRITY_MASK;
_priority = priority;
}
public AMQShortString getCorrelationId()
{
+ decodeIfNecessary();
+
return _correlationId;
}
public String getCorrelationIdAsString()
{
+ decodeIfNecessary();
+
return (_correlationId == null) ? null : _correlationId.toString();
}
public void setCorrelationId(String correlationId)
{
+ _hasBeenUpdated = true;
setCorrelationId((correlationId == null) ? null : new AMQShortString(correlationId));
}
public void setCorrelationId(AMQShortString correlationId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= CORRELATION_ID_MASK;
_correlationId = correlationId;
}
public String getReplyToAsString()
{
+ decodeIfNecessary();
+
return (_replyTo == null) ? null : _replyTo.toString();
}
public AMQShortString getReplyTo()
{
+ decodeIfNecessary();
+
return _replyTo;
}
public void setReplyTo(String replyTo)
{
+ _hasBeenUpdated = true;
setReplyTo((replyTo == null) ? null : new AMQShortString(replyTo));
}
public void setReplyTo(AMQShortString replyTo)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= REPLY_TO_MASK;
_replyTo = replyTo;
}
public long getExpiration()
{
+ decodeIfNecessary();
return _expiration;
}
public void setExpiration(long expiration)
{
+ clearEncodedForm();
_propertyFlags |= EXPIRATION_MASK;
_expiration = expiration;
}
public AMQShortString getMessageId()
{
+ decodeIfNecessary();
+
return _messageId;
}
public String getMessageIdAsString()
{
+ decodeIfNecessary();
+
return (_messageId == null) ? null : _messageId.toString();
}
public void setMessageId(String messageId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= MESSAGE_ID_MASK;
_messageId = (messageId == null) ? null : new AMQShortString(messageId);
}
public void setMessageId(AMQShortString messageId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= MESSAGE_ID_MASK;
_messageId = messageId;
}
public long getTimestamp()
{
+ decodeIfNecessary();
return _timestamp;
}
public void setTimestamp(long timestamp)
{
+ clearEncodedForm();
_propertyFlags |= TIMESTAMP_MASK;
_timestamp = timestamp;
}
public String getTypeAsString()
{
+ decodeIfNecessary();
+
return (_type == null) ? null : _type.toString();
}
public AMQShortString getType()
{
+ decodeIfNecessary();
+
return _type;
}
public void setType(String type)
{
+ _hasBeenUpdated = true;
setType((type == null) ? null : new AMQShortString(type));
}
public void setType(AMQShortString type)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= TYPE_MASK;
_type = type;
}
public String getUserIdAsString()
{
+ decodeIfNecessary();
+
return (_userId == null) ? null : _userId.toString();
}
public AMQShortString getUserId()
{
+ decodeIfNecessary();
+
return _userId;
}
@@ -555,48 +764,65 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
public void setUserId(AMQShortString userId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= USER_ID_MASK;
_userId = userId;
}
public String getAppIdAsString()
{
+ decodeIfNecessary();
+
return (_appId == null) ? null : _appId.toString();
}
public AMQShortString getAppId()
{
+ decodeIfNecessary();
+
return _appId;
}
public void setAppId(String appId)
{
+ _hasBeenUpdated = true;
setAppId((appId == null) ? null : new AMQShortString(appId));
}
public void setAppId(AMQShortString appId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= APPLICATION_ID_MASK;
_appId = appId;
+ _hasBeenUpdated = true;
}
public String getClusterIdAsString()
{
+ _hasBeenUpdated = true;
+ decodeIfNecessary();
return (_clusterId == null) ? null : _clusterId.toString();
}
public AMQShortString getClusterId()
{
+ _hasBeenUpdated = true;
+ decodeIfNecessary();
return _clusterId;
}
public void setClusterId(String clusterId)
{
+ _hasBeenUpdated = true;
setClusterId((clusterId == null) ? null : new AMQShortString(clusterId));
}
public void setClusterId(AMQShortString clusterId)
{
+ _hasBeenUpdated = true;
+ clearEncodedForm();
_propertyFlags |= CLUSTER_ID_MASK;
_clusterId = clusterId;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java
index f9580d82b1..59646577e1 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/BodyFactory.java
@@ -20,13 +20,12 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
/**
* Any class that is capable of turning a stream of bytes into an AMQ structure must implement this interface.
*/
public interface BodyFactory
{
- AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException;
+ AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
index 15bc20c52d..94030f383e 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock
{
@@ -50,7 +49,7 @@ public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQD
return frameSize;
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
for (int i = 0; i < _blocks.length; i++)
{
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
index aedb35f92a..9d39f8aa86 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
@@ -20,10 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.AMQException;
@@ -31,22 +28,27 @@ public class ContentBody implements AMQBody
{
public static final byte TYPE = 3;
- public byte[] _payload;
+ public ByteBuffer payload;
public ContentBody()
{
}
- public ContentBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException
+ public ContentBody(ByteBuffer buffer, long size) throws AMQFrameDecodingException
{
- _payload = new byte[(int)size];
- buffer.read(_payload);
+ if (size > 0)
+ {
+ payload = buffer.slice();
+ payload.limit((int) size);
+ buffer.skip((int) size);
+ }
+
}
- public ContentBody(byte[] payload)
+ public ContentBody(ByteBuffer payload)
{
- _payload = payload;
+ this.payload = payload;
}
public byte getFrameType()
@@ -56,12 +58,23 @@ public class ContentBody implements AMQBody
public int getSize()
{
- return _payload == null ? 0 : _payload.length;
+ return (payload == null ? 0 : payload.limit());
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
- buffer.write(_payload);
+ if (payload != null)
+ {
+ if(payload.isDirect() || payload.isReadOnly())
+ {
+ ByteBuffer copy = payload.duplicate();
+ buffer.put(copy.rewind());
+ }
+ else
+ {
+ buffer.put(payload.array(),payload.arrayOffset(),payload.limit());
+ }
+ }
}
public void handle(final int channelId, final AMQVersionAwareProtocolSession session)
@@ -70,18 +83,32 @@ public class ContentBody implements AMQBody
session.contentBodyReceived(channelId, this);
}
- protected void populateFromBuffer(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException
+ protected void populateFromBuffer(ByteBuffer buffer, long size) throws AMQFrameDecodingException
{
if (size > 0)
{
- _payload = new byte[(int)size];
- buffer.read(_payload);
+ payload = buffer.slice();
+ payload.limit((int) size);
+ buffer.skip((int) size);
}
}
public void reduceBufferToFit()
{
+ if (payload != null && (payload.remaining() < payload.capacity() / 2))
+ {
+ int size = payload.limit();
+ ByteBuffer newPayload = ByteBuffer.allocate(size);
+
+ newPayload.put(payload);
+ newPayload.flip();
+
+ //reduce reference count on payload
+ payload.release();
+
+ payload = newPayload;
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java
index a0b030ab6b..c42995d148 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBodyFactory.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +41,7 @@ public class ContentBodyFactory implements BodyFactory
_log.debug("Creating content body factory");
}
- public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException
+ public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException
{
return new ContentBody(in, bodySize);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
index 18d0f26152..83e5a7e341 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
@@ -20,10 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.AMQException;
@@ -39,18 +36,18 @@ public class ContentHeaderBody implements AMQBody
public long bodySize;
/** must never be null */
- private ContentHeaderProperties properties;
+ public ContentHeaderProperties properties;
public ContentHeaderBody()
{
}
- public ContentHeaderBody(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException
+ public ContentHeaderBody(ByteBuffer buffer, long size) throws AMQFrameDecodingException
{
- classId = buffer.readUnsignedShort();
- weight = buffer.readUnsignedShort();
- bodySize = buffer.readLong();
- int propertyFlags = buffer.readUnsignedShort();
+ classId = buffer.getUnsignedShort();
+ weight = buffer.getUnsignedShort();
+ bodySize = buffer.getLong();
+ int propertyFlags = buffer.getUnsignedShort();
ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.getInstance();
properties = factory.createContentHeaderProperties(classId, propertyFlags, buffer, (int)size - 14);
@@ -75,13 +72,13 @@ public class ContentHeaderBody implements AMQBody
return TYPE;
}
- protected void populateFromBuffer(DataInputStream buffer, long size)
- throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
+ protected void populateFromBuffer(ByteBuffer buffer, long size)
+ throws AMQFrameDecodingException, AMQProtocolVersionException
{
- classId = buffer.readUnsignedShort();
- weight = buffer.readUnsignedShort();
- bodySize = buffer.readLong();
- int propertyFlags = buffer.readUnsignedShort();
+ classId = buffer.getUnsignedShort();
+ weight = buffer.getUnsignedShort();
+ bodySize = buffer.getLong();
+ int propertyFlags = buffer.getUnsignedShort();
ContentHeaderPropertiesFactory factory = ContentHeaderPropertiesFactory.getInstance();
properties = factory.createContentHeaderProperties(classId, propertyFlags, buffer, (int)size - 14);
}
@@ -93,8 +90,8 @@ public class ContentHeaderBody implements AMQBody
* @return
* @throws AMQFrameDecodingException
*/
- public static ContentHeaderBody createFromBuffer(DataInputStream buffer, long size)
- throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
+ public static ContentHeaderBody createFromBuffer(ByteBuffer buffer, long size)
+ throws AMQFrameDecodingException, AMQProtocolVersionException
{
ContentHeaderBody body = new ContentHeaderBody(buffer, size);
@@ -106,11 +103,11 @@ public class ContentHeaderBody implements AMQBody
return 2 + 2 + 8 + 2 + properties.getPropertyListSize();
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
EncodingUtils.writeUnsignedShort(buffer, classId);
EncodingUtils.writeUnsignedShort(buffer, weight);
- buffer.writeLong(bodySize);
+ buffer.putLong(bodySize);
EncodingUtils.writeUnsignedShort(buffer, properties.getPropertyFlags());
properties.writePropertyListPayload(buffer);
}
@@ -131,25 +128,4 @@ public class ContentHeaderBody implements AMQBody
{
return new AMQFrame(channelId, body);
}
-
- public ContentHeaderProperties getProperties()
- {
- return properties;
- }
-
- public void setProperties(ContentHeaderProperties props)
- {
- properties = props;
- }
-
- @Override
- public String toString()
- {
- return "ContentHeaderBody{" +
- "classId=" + classId +
- ", weight=" + weight +
- ", bodySize=" + bodySize +
- ", properties=" + properties +
- '}';
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java
index a474e337b7..8d5e2f9fb4 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBodyFactory.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,7 +41,7 @@ public class ContentHeaderBodyFactory implements BodyFactory
_log.debug("Creating content header body factory");
}
- public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException, IOException
+ public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException
{
// all content headers are the same - it is only the properties that differ.
// the content header body further delegates construction of properties
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java
index 237929f9a3..7ef538cfdc 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderProperties.java
@@ -20,10 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
/**
* There will be an implementation of this interface for each content type. All content types have associated
@@ -35,7 +32,7 @@ public interface ContentHeaderProperties
* Writes the property list to the buffer, in a suitably encoded form.
* @param buffer The buffer to write to
*/
- void writePropertyListPayload(DataOutputStream buffer) throws IOException;
+ void writePropertyListPayload(ByteBuffer buffer);
/**
* Populates the properties from buffer.
@@ -43,8 +40,8 @@ public interface ContentHeaderProperties
* @param propertyFlags he property flags.
* @throws AMQFrameDecodingException when the buffer does not contain valid data
*/
- void populatePropertiesFromBuffer(DataInputStream buffer, int propertyFlags, int size)
- throws AMQFrameDecodingException, IOException;
+ void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size)
+ throws AMQFrameDecodingException;
/**
* @return the size of the encoded property list in bytes.
@@ -59,4 +56,5 @@ public interface ContentHeaderProperties
*/
int getPropertyFlags();
+ void updated();
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
index 43ee8cd1f1..46189b63d7 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.amqp_8_0.BasicConsumeBodyImpl;
@@ -39,8 +38,8 @@ public class ContentHeaderPropertiesFactory
}
public ContentHeaderProperties createContentHeaderProperties(int classId, int propertyFlags,
- DataInputStream buffer, int size)
- throws AMQFrameDecodingException, IOException
+ ByteBuffer buffer, int size)
+ throws AMQFrameDecodingException
{
ContentHeaderProperties properties;
// AMQP version change: "Hardwired" version to major=8, minor=0
diff --git a/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java
new file mode 100644
index 0000000000..f6795ff200
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/framing/DeferredDataBlock.java
@@ -0,0 +1,50 @@
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+/*
+*
+* 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.
+*
+*/
+public abstract class DeferredDataBlock extends AMQDataBlock
+{
+ private AMQDataBlock _underlyingDataBlock;
+
+
+ public long getSize()
+ {
+ if(_underlyingDataBlock == null)
+ {
+ _underlyingDataBlock = createAMQDataBlock();
+ }
+ return _underlyingDataBlock.getSize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ if(_underlyingDataBlock == null)
+ {
+ _underlyingDataBlock = createAMQDataBlock();
+ }
+ _underlyingDataBlock.writePayload(buffer);
+ }
+
+ abstract protected AMQDataBlock createAMQDataBlock();
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
index 2d7e27405c..6425f8c591 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
@@ -20,12 +20,11 @@
*/
package org.apache.qpid.framing;
-import java.io.*;
+import org.apache.mina.common.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.nio.ByteBuffer;
import java.nio.charset.Charset;
public class EncodingUtils
@@ -219,7 +218,7 @@ public class EncodingUtils
return 0;
}
- public static void writeShortStringBytes(DataOutputStream buffer, String s) throws IOException
+ public static void writeShortStringBytes(ByteBuffer buffer, String s)
{
if (s != null)
{
@@ -232,18 +231,18 @@ public class EncodingUtils
// TODO: check length fits in an unsigned byte
writeUnsignedByte(buffer, (short)encodedString.length);
- buffer.write(encodedString);
+ buffer.put(encodedString);
}
else
{
// really writing out unsigned byte
- buffer.write((byte) 0);
+ buffer.put((byte) 0);
}
}
- public static void writeShortStringBytes(DataOutputStream buffer, AMQShortString s) throws IOException
+ public static void writeShortStringBytes(ByteBuffer buffer, AMQShortString s)
{
if (s != null)
{
@@ -253,11 +252,11 @@ public class EncodingUtils
else
{
// really writing out unsigned byte
- buffer.write((byte) 0);
+ buffer.put((byte) 0);
}
}
- public static void writeLongStringBytes(DataOutputStream buffer, String s) throws IOException
+ public static void writeLongStringBytes(ByteBuffer buffer, String s)
{
assert (s == null) || (s.length() <= 0xFFFE);
if (s != null)
@@ -271,7 +270,7 @@ public class EncodingUtils
encodedString[i] = (byte) cha[i];
}
- buffer.write(encodedString);
+ buffer.put(encodedString);
}
else
{
@@ -279,7 +278,7 @@ public class EncodingUtils
}
}
- public static void writeLongStringBytes(DataOutputStream buffer, char[] s) throws IOException
+ public static void writeLongStringBytes(ByteBuffer buffer, char[] s)
{
assert (s == null) || (s.length <= 0xFFFE);
if (s != null)
@@ -292,7 +291,7 @@ public class EncodingUtils
encodedString[i] = (byte) s[i];
}
- buffer.write(encodedString);
+ buffer.put(encodedString);
}
else
{
@@ -300,13 +299,13 @@ public class EncodingUtils
}
}
- public static void writeLongStringBytes(DataOutputStream buffer, byte[] bytes) throws IOException
+ public static void writeLongStringBytes(ByteBuffer buffer, byte[] bytes)
{
assert (bytes == null) || (bytes.length <= 0xFFFE);
if (bytes != null)
{
writeUnsignedInteger(buffer, bytes.length);
- buffer.write(bytes);
+ buffer.put(bytes);
}
else
{
@@ -314,24 +313,24 @@ public class EncodingUtils
}
}
- public static void writeUnsignedByte(DataOutputStream buffer, short b) throws IOException
+ public static void writeUnsignedByte(ByteBuffer buffer, short b)
{
byte bv = (byte) b;
- buffer.write(bv);
+ buffer.put(bv);
}
- public static void writeUnsignedShort(DataOutputStream buffer, int s) throws IOException
+ public static void writeUnsignedShort(ByteBuffer buffer, int s)
{
// TODO: Is this comparison safe? Do I need to cast RHS to long?
if (s < Short.MAX_VALUE)
{
- buffer.writeShort(s);
+ buffer.putShort((short) s);
}
else
{
short sv = (short) s;
- buffer.write((byte) (0xFF & (sv >> 8)));
- buffer.write((byte) (0xFF & sv));
+ buffer.put((byte) (0xFF & (sv >> 8)));
+ buffer.put((byte) (0xFF & sv));
}
}
@@ -340,12 +339,12 @@ public class EncodingUtils
return 4;
}
- public static void writeUnsignedInteger(DataOutputStream buffer, long l) throws IOException
+ public static void writeUnsignedInteger(ByteBuffer buffer, long l)
{
// TODO: Is this comparison safe? Do I need to cast RHS to long?
if (l < Integer.MAX_VALUE)
{
- buffer.writeInt((int) l);
+ buffer.putInt((int) l);
}
else
{
@@ -353,14 +352,14 @@ public class EncodingUtils
// FIXME: This *may* go faster if we build this into a local 4-byte array and then
// put the array in a single call.
- buffer.write((byte) (0xFF & (iv >> 24)));
- buffer.write((byte) (0xFF & (iv >> 16)));
- buffer.write((byte) (0xFF & (iv >> 8)));
- buffer.write((byte) (0xFF & iv));
+ buffer.put((byte) (0xFF & (iv >> 24)));
+ buffer.put((byte) (0xFF & (iv >> 16)));
+ buffer.put((byte) (0xFF & (iv >> 8)));
+ buffer.put((byte) (0xFF & iv));
}
}
- public static void writeFieldTableBytes(DataOutputStream buffer, FieldTable table) throws IOException
+ public static void writeFieldTableBytes(ByteBuffer buffer, FieldTable table)
{
if (table != null)
{
@@ -372,12 +371,12 @@ public class EncodingUtils
}
}
- public static void writeContentBytes(DataOutputStream buffer, Content content)
+ public static void writeContentBytes(ByteBuffer buffer, Content content)
{
// TODO: New Content class required for AMQP 0-9.
}
- public static void writeBooleans(DataOutputStream buffer, boolean[] values) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean[] values)
{
byte packedValue = 0;
for (int i = 0; i < values.length; i++)
@@ -388,16 +387,16 @@ public class EncodingUtils
}
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value)
{
- buffer.write(value ? (byte) 1 : (byte) 0);
+ buffer.put(value ? (byte) 1 : (byte) 0);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -406,10 +405,10 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 1));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -423,10 +422,10 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 2));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -445,11 +444,11 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 3));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3,
- boolean value4) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -473,11 +472,11 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 4));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3,
- boolean value4, boolean value5) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -506,11 +505,11 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 5));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3,
- boolean value4, boolean value5, boolean value6) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5, boolean value6)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -544,11 +543,11 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 6));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
- public static void writeBooleans(DataOutputStream buffer, boolean value0, boolean value1, boolean value2, boolean value3,
- boolean value4, boolean value5, boolean value6, boolean value7) throws IOException
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5, boolean value6, boolean value7)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
@@ -587,7 +586,7 @@ public class EncodingUtils
packedValue = (byte) (packedValue | (byte) (1 << 7));
}
- buffer.write(packedValue);
+ buffer.put(packedValue);
}
/**
@@ -596,12 +595,12 @@ public class EncodingUtils
* @param buffer
* @param data
*/
- public static void writeLongstr(DataOutputStream buffer, byte[] data) throws IOException
+ public static void writeLongstr(ByteBuffer buffer, byte[] data)
{
if (data != null)
{
writeUnsignedInteger(buffer, data.length);
- buffer.write(data);
+ buffer.put(data);
}
else
{
@@ -609,14 +608,14 @@ public class EncodingUtils
}
}
- public static void writeTimestamp(DataOutputStream buffer, long timestamp) throws IOException
+ public static void writeTimestamp(ByteBuffer buffer, long timestamp)
{
writeLong(buffer, timestamp);
}
- public static boolean[] readBooleans(DataInputStream buffer) throws IOException
+ public static boolean[] readBooleans(ByteBuffer buffer)
{
- final byte packedValue = buffer.readByte();
+ final byte packedValue = buffer.get();
if (packedValue == 0)
{
return ALL_FALSE_ARRAY;
@@ -641,9 +640,9 @@ public class EncodingUtils
return result;
}
- public static FieldTable readFieldTable(DataInputStream buffer) throws AMQFrameDecodingException, IOException
+ public static FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
{
- long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL;
+ long length = buffer.getUnsignedInt();
if (length == 0)
{
return null;
@@ -654,21 +653,21 @@ public class EncodingUtils
}
}
- public static Content readContent(DataInputStream buffer) throws AMQFrameDecodingException
+ public static Content readContent(ByteBuffer buffer) throws AMQFrameDecodingException
{
// TODO: New Content class required for AMQP 0-9.
return null;
}
- public static AMQShortString readAMQShortString(DataInputStream buffer) throws IOException
+ public static AMQShortString readAMQShortString(ByteBuffer buffer)
{
return AMQShortString.readFromBuffer(buffer);
}
- public static String readShortString(DataInputStream buffer) throws IOException
+ public static String readShortString(ByteBuffer buffer)
{
- short length = (short) (((short)buffer.readByte()) & 0xFF);
+ short length = buffer.getUnsigned();
if (length == 0)
{
return null;
@@ -681,7 +680,7 @@ public class EncodingUtils
// this approach here is valid since we know that all the chars are
// ASCII (0-127)
byte[] stringBytes = new byte[length];
- buffer.read(stringBytes, 0, length);
+ buffer.get(stringBytes, 0, length);
char[] stringChars = new char[length];
for (int i = 0; i < stringChars.length; i++)
{
@@ -692,9 +691,9 @@ public class EncodingUtils
}
}
- public static String readLongString(DataInputStream buffer) throws IOException
+ public static String readLongString(ByteBuffer buffer)
{
- long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL;
+ long length = buffer.getUnsignedInt();
if (length == 0)
{
return "";
@@ -707,7 +706,7 @@ public class EncodingUtils
// this approach here is valid since we know that all the chars are
// ASCII (0-127)
byte[] stringBytes = new byte[(int) length];
- buffer.read(stringBytes, 0, (int) length);
+ buffer.get(stringBytes, 0, (int) length);
char[] stringChars = new char[(int) length];
for (int i = 0; i < stringChars.length; i++)
{
@@ -718,9 +717,9 @@ public class EncodingUtils
}
}
- public static byte[] readLongstr(DataInputStream buffer) throws IOException
+ public static byte[] readLongstr(ByteBuffer buffer)
{
- long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL;
+ long length = buffer.getUnsignedInt();
if (length == 0)
{
return null;
@@ -728,17 +727,17 @@ public class EncodingUtils
else
{
byte[] result = new byte[(int) length];
- buffer.read(result);
+ buffer.get(result);
return result;
}
}
- public static long readTimestamp(DataInputStream buffer) throws IOException
+ public static long readTimestamp(ByteBuffer buffer)
{
// Discard msb from AMQ timestamp
// buffer.getUnsignedInt();
- return buffer.readLong();
+ return buffer.getLong();
}
static byte[] hexToByteArray(String id)
@@ -818,14 +817,14 @@ public class EncodingUtils
// AMQP_BOOLEAN_PROPERTY_PREFIX
- public static void writeBoolean(DataOutputStream buffer, Boolean aBoolean) throws IOException
+ public static void writeBoolean(ByteBuffer buffer, Boolean aBoolean)
{
- buffer.write(aBoolean ? 1 : 0);
+ buffer.put((byte) (aBoolean ? 1 : 0));
}
- public static boolean readBoolean(DataInputStream buffer) throws IOException
+ public static boolean readBoolean(ByteBuffer buffer)
{
- byte packedValue = buffer.readByte();
+ byte packedValue = buffer.get();
return (packedValue == 1);
}
@@ -836,14 +835,14 @@ public class EncodingUtils
}
// AMQP_BYTE_PROPERTY_PREFIX
- public static void writeByte(DataOutputStream buffer, Byte aByte) throws IOException
+ public static void writeByte(ByteBuffer buffer, Byte aByte)
{
- buffer.writeByte(aByte);
+ buffer.put(aByte);
}
- public static byte readByte(DataInputStream buffer) throws IOException
+ public static byte readByte(ByteBuffer buffer)
{
- return buffer.readByte();
+ return buffer.get();
}
public static int encodedByteLength()
@@ -852,14 +851,14 @@ public class EncodingUtils
}
// AMQP_SHORT_PROPERTY_PREFIX
- public static void writeShort(DataOutputStream buffer, Short aShort) throws IOException
+ public static void writeShort(ByteBuffer buffer, Short aShort)
{
- buffer.writeShort(aShort);
+ buffer.putShort(aShort);
}
- public static short readShort(DataInputStream buffer) throws IOException
+ public static short readShort(ByteBuffer buffer)
{
- return buffer.readShort();
+ return buffer.getShort();
}
public static int encodedShortLength()
@@ -868,14 +867,14 @@ public class EncodingUtils
}
// INTEGER_PROPERTY_PREFIX
- public static void writeInteger(DataOutputStream buffer, Integer aInteger) throws IOException
+ public static void writeInteger(ByteBuffer buffer, Integer aInteger)
{
- buffer.writeInt(aInteger);
+ buffer.putInt(aInteger);
}
- public static int readInteger(DataInputStream buffer) throws IOException
+ public static int readInteger(ByteBuffer buffer)
{
- return buffer.readInt();
+ return buffer.getInt();
}
public static int encodedIntegerLength()
@@ -884,14 +883,14 @@ public class EncodingUtils
}
// AMQP_LONG_PROPERTY_PREFIX
- public static void writeLong(DataOutputStream buffer, Long aLong) throws IOException
+ public static void writeLong(ByteBuffer buffer, Long aLong)
{
- buffer.writeLong(aLong);
+ buffer.putLong(aLong);
}
- public static long readLong(DataInputStream buffer) throws IOException
+ public static long readLong(ByteBuffer buffer)
{
- return buffer.readLong();
+ return buffer.getLong();
}
public static int encodedLongLength()
@@ -900,14 +899,14 @@ public class EncodingUtils
}
// Float_PROPERTY_PREFIX
- public static void writeFloat(DataOutputStream buffer, Float aFloat) throws IOException
+ public static void writeFloat(ByteBuffer buffer, Float aFloat)
{
- buffer.writeFloat(aFloat);
+ buffer.putFloat(aFloat);
}
- public static float readFloat(DataInputStream buffer) throws IOException
+ public static float readFloat(ByteBuffer buffer)
{
- return buffer.readFloat();
+ return buffer.getFloat();
}
public static int encodedFloatLength()
@@ -916,14 +915,14 @@ public class EncodingUtils
}
// Double_PROPERTY_PREFIX
- public static void writeDouble(DataOutputStream buffer, Double aDouble) throws IOException
+ public static void writeDouble(ByteBuffer buffer, Double aDouble)
{
- buffer.writeDouble(aDouble);
+ buffer.putDouble(aDouble);
}
- public static double readDouble(DataInputStream buffer) throws IOException
+ public static double readDouble(ByteBuffer buffer)
{
- return buffer.readDouble();
+ return buffer.getDouble();
}
public static int encodedDoubleLength()
@@ -931,9 +930,9 @@ public class EncodingUtils
return 8;
}
- public static byte[] readBytes(DataInputStream buffer) throws IOException
+ public static byte[] readBytes(ByteBuffer buffer)
{
- long length = ((long)(buffer.readInt())) & 0xFFFFFFFFL;
+ long length = buffer.getUnsignedInt();
if (length == 0)
{
return null;
@@ -941,19 +940,19 @@ public class EncodingUtils
else
{
byte[] dataBytes = new byte[(int)length];
- buffer.read(dataBytes, 0, (int) length);
+ buffer.get(dataBytes, 0, (int)length);
return dataBytes;
}
}
- public static void writeBytes(DataOutputStream buffer, byte[] data) throws IOException
+ public static void writeBytes(ByteBuffer buffer, byte[] data)
{
if (data != null)
{
// TODO: check length fits in an unsigned byte
writeUnsignedInteger(buffer, (long)data.length);
- buffer.write(data);
+ buffer.put(data);
}
else
{
@@ -969,35 +968,35 @@ public class EncodingUtils
return encodedByteLength();
}
- public static char readChar(DataInputStream buffer) throws IOException
+ public static char readChar(ByteBuffer buffer)
{
// This is valid as we know that the Character is ASCII 0..127
- return (char) buffer.read();
+ return (char) buffer.get();
}
- public static void writeChar(DataOutputStream buffer, char character) throws IOException
+ public static void writeChar(ByteBuffer buffer, char character)
{
// This is valid as we know that the Character is ASCII 0..127
writeByte(buffer, (byte) character);
}
- public static long readLongAsShortString(DataInputStream buffer) throws IOException
+ public static long readLongAsShortString(ByteBuffer buffer)
{
- short length = (short) buffer.readUnsignedByte();
+ short length = buffer.getUnsigned();
short pos = 0;
if (length == 0)
{
return 0L;
}
- byte digit = buffer.readByte();
+ byte digit = buffer.get();
boolean isNegative;
long result = 0;
if (digit == (byte) '-')
{
isNegative = true;
pos++;
- digit = buffer.readByte();
+ digit = buffer.get();
}
else
{
@@ -1010,7 +1009,7 @@ public class EncodingUtils
while (pos < length)
{
pos++;
- digit = buffer.readByte();
+ digit = buffer.get();
result = (result << 3) + (result << 1);
result += digit - (byte) '0';
}
@@ -1018,15 +1017,15 @@ public class EncodingUtils
return result;
}
- public static long readUnsignedInteger(DataInputStream buffer) throws IOException
+ public static long readUnsignedInteger(ByteBuffer buffer)
{
- long l = 0xFF & buffer.readByte();
+ long l = 0xFF & buffer.get();
l <<= 8;
- l = l | (0xFF & buffer.readByte());
+ l = l | (0xFF & buffer.get());
l <<= 8;
- l = l | (0xFF & buffer.readByte());
+ l = l | (0xFF & buffer.get());
l <<= 8;
- l = l | (0xFF & buffer.readByte());
+ l = l | (0xFF & buffer.get());
return l;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index 721c821bab..22205d49f8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -20,16 +20,12 @@
*/
package org.apache.qpid.framing;
+import org.apache.mina.common.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.AMQPInvalidClassException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Enumeration;
@@ -47,8 +43,8 @@ public class FieldTable
private static final String STRICT_AMQP = "STRICT_AMQP";
private final boolean _strictAMQP = Boolean.valueOf(System.getProperty(STRICT_AMQP, "false"));
- private byte[] _encodedForm;
- private LinkedHashMap<AMQShortString, AMQTypedValue> _properties = null;
+ private ByteBuffer _encodedForm;
+ private LinkedHashMap<AMQShortString, AMQTypedValue> _properties;
private long _encodedSize;
private static final int INITIAL_HASHMAP_CAPACITY = 16;
private static final int INITIAL_ENCODED_FORM_SIZE = 256;
@@ -56,6 +52,9 @@ public class FieldTable
public FieldTable()
{
super();
+ // _encodedForm = ByteBuffer.allocate(INITIAL_ENCODED_FORM_SIZE);
+ // _encodedForm.setAutoExpand(true);
+ // _encodedForm.limit(0);
}
/**
@@ -64,12 +63,16 @@ public class FieldTable
* @param buffer the buffer from which to read data. The length byte must be read already
* @param length the length of the field table. Must be > 0.
*/
- public FieldTable(DataInputStream buffer, long length) throws IOException
+ public FieldTable(ByteBuffer buffer, long length)
{
this();
- _encodedForm = new byte[(int) length];
- buffer.read(_encodedForm);
+ ByteBuffer encodedForm = buffer.slice();
+ encodedForm.limit((int) length);
+ _encodedForm = ByteBuffer.allocate((int)length);
+ _encodedForm.put(encodedForm);
+ _encodedForm.flip();
_encodedSize = length;
+ buffer.skip((int) length);
}
public AMQTypedValue getProperty(AMQShortString string)
@@ -105,19 +108,13 @@ public class FieldTable
{
try
{
- setFromBuffer();
+ setFromBuffer(_encodedForm, _encodedSize);
}
catch (AMQFrameDecodingException e)
{
_logger.error("Error decoding FieldTable in deferred decoding mode ", e);
throw new IllegalArgumentException(e);
}
- catch (IOException e)
- {
- _logger.error("Unexpected IO exception decoding field table");
- throw new IllegalArgumentException(e);
-
- }
}
private AMQTypedValue setProperty(AMQShortString key, AMQTypedValue val)
@@ -769,7 +766,7 @@ public class FieldTable
// ************************* Byte Buffer Processing
- public void writeToBuffer(DataOutputStream buffer) throws IOException
+ public void writeToBuffer(ByteBuffer buffer)
{
final boolean trace = _logger.isDebugEnabled();
@@ -789,21 +786,17 @@ public class FieldTable
public byte[] getDataAsBytes()
{
- if(_encodedForm == null)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try
- {
- putDataInBuffer(new DataOutputStream(baos));
- return baos.toByteArray();
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("IO Exception should never be thrown here");
- }
+ final int encodedSize = (int) getEncodedSize();
+ final ByteBuffer buffer = ByteBuffer.allocate(encodedSize); // FIXME XXX: Is cast a problem?
- }
- return _encodedForm.clone();
+ putDataInBuffer(buffer);
+
+ final byte[] result = new byte[encodedSize];
+ buffer.flip();
+ buffer.get(result);
+ buffer.release();
+
+ return result;
}
public long getEncodedSize()
@@ -933,8 +926,15 @@ public class FieldTable
public Iterator<Map.Entry<AMQShortString, AMQTypedValue>> iterator()
{
- initMapIfNecessary();
- return _properties.entrySet().iterator();
+ if(_encodedForm != null)
+ {
+ return new FieldTableIterator(_encodedForm.duplicate().rewind(),(int)_encodedSize);
+ }
+ else
+ {
+ initMapIfNecessary();
+ return _properties.entrySet().iterator();
+ }
}
public Object get(String key)
@@ -1002,12 +1002,26 @@ public class FieldTable
return _properties.keySet();
}
- private void putDataInBuffer(DataOutputStream buffer) throws IOException
+ private void putDataInBuffer(ByteBuffer buffer)
{
if (_encodedForm != null)
{
- buffer.write(_encodedForm);
+ if(buffer.isDirect() || buffer.isReadOnly())
+ {
+ ByteBuffer encodedForm = _encodedForm.duplicate();
+
+ if (encodedForm.position() != 0)
+ {
+ encodedForm.flip();
+ }
+
+ buffer.put(encodedForm);
+ }
+ else
+ {
+ buffer.put(_encodedForm.array(),_encodedForm.arrayOffset(),(int)_encodedSize);
+ }
}
else if (_properties != null)
{
@@ -1021,27 +1035,41 @@ public class FieldTable
final Map.Entry<AMQShortString, AMQTypedValue> me = it.next();
try
{
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Writing Property:" + me.getKey() + " Type:" + me.getValue().getType() + " Value:"
+ + me.getValue().getValue());
+ _logger.debug("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining());
+ }
+
// Write the actual parameter name
EncodingUtils.writeShortStringBytes(buffer, me.getKey());
me.getValue().writeToBuffer(buffer);
}
catch (Exception e)
{
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Exception thrown:" + e);
+ _logger.debug("Writing Property:" + me.getKey() + " Type:" + me.getValue().getType() + " Value:"
+ + me.getValue().getValue());
+ _logger.debug("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining());
+ }
+
throw new RuntimeException(e);
}
}
}
}
- private void setFromBuffer() throws AMQFrameDecodingException, IOException
+ private void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException
{
- final ByteArrayInputStream in = new ByteArrayInputStream(_encodedForm);
- DataInputStream buffer = new DataInputStream(in);
final boolean trace = _logger.isDebugEnabled();
- if (_encodedSize > 0)
+ if (length > 0)
{
+ final int expectedRemaining = buffer.remaining() - (int) length;
_properties = new LinkedHashMap<AMQShortString, AMQTypedValue>(INITIAL_HASHMAP_CAPACITY);
@@ -1049,16 +1077,121 @@ public class FieldTable
{
final AMQShortString key = EncodingUtils.readAMQShortString(buffer);
+
+ _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read key '" + key);
+
AMQTypedValue value = AMQTypedValue.readFromBuffer(buffer);
+
+ if (trace)
+ {
+ _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + value.getType()
+ + "', key '" + key + "', value '" + value.getValue() + "'");
+ }
+
_properties.put(key, value);
}
- while (in.available() > 0);
+ while (buffer.remaining() > expectedRemaining);
+
+ }
+
+ _encodedSize = length;
+
+ if (trace)
+ {
+ _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done.");
+ }
+ }
+
+ private static final class FieldTableEntry implements Map.Entry<AMQShortString, AMQTypedValue>
+ {
+ private final AMQTypedValue _value;
+ private final AMQShortString _key;
+
+ public FieldTableEntry(final AMQShortString key, final AMQTypedValue value)
+ {
+ _key = key;
+ _value = value;
+ }
+
+ public AMQShortString getKey()
+ {
+ return _key;
+ }
+
+ public AMQTypedValue getValue()
+ {
+ return _value;
+ }
+
+ public AMQTypedValue setValue(final AMQTypedValue value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object o)
+ {
+ if(o instanceof FieldTableEntry)
+ {
+ FieldTableEntry other = (FieldTableEntry) o;
+ return (_key == null ? other._key == null : _key.equals(other._key))
+ && (_value == null ? other._value == null : _value.equals(other._value));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ return (getKey()==null ? 0 : getKey().hashCode())
+ ^ (getValue()==null ? 0 : getValue().hashCode());
+ }
+
+ }
+
+
+ private static final class FieldTableIterator implements Iterator<Map.Entry<AMQShortString, AMQTypedValue>>
+ {
+ private final ByteBuffer _buffer;
+ private int _expectedRemaining;
+
+ public FieldTableIterator(ByteBuffer buffer, int length)
+ {
+ _buffer = buffer;
+ _expectedRemaining = buffer.remaining() - length;
+ }
+
+ public boolean hasNext()
+ {
+ return (_buffer.remaining() > _expectedRemaining);
}
+ public Map.Entry<AMQShortString, AMQTypedValue> next()
+ {
+ if(hasNext())
+ {
+ final AMQShortString key = EncodingUtils.readAMQShortString(_buffer);
+ AMQTypedValue value = AMQTypedValue.readFromBuffer(_buffer);
+ return new FieldTableEntry(key, value);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
}
+
+
+
public int hashCode()
{
initMapIfNecessary();
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
index 438a46f28b..e9d75137ef 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
public class FieldTableFactory
{
@@ -30,7 +29,7 @@ public class FieldTableFactory
return new FieldTable();
}
- public static FieldTable newFieldTable(DataInputStream byteBuffer, long length) throws AMQFrameDecodingException, IOException
+ public static FieldTable newFieldTable(ByteBuffer byteBuffer, long length) throws AMQFrameDecodingException
{
return new FieldTable(byteBuffer, length);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
index a6ce721a50..18ab05ffa1 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
@@ -20,10 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.AMQException;
@@ -37,12 +34,12 @@ public class HeartbeatBody implements AMQBody
}
- public HeartbeatBody(DataInputStream buffer, long size) throws IOException
+ public HeartbeatBody(ByteBuffer buffer, long size)
{
if(size > 0)
{
//allow other implementations to have a payload, but ignore it:
- buffer.skip(size);
+ buffer.skip((int) size);
}
}
@@ -56,7 +53,7 @@ public class HeartbeatBody implements AMQBody
return 0;//heartbeats we generate have no payload
}
- public void writePayload(DataOutputStream buffer)
+ public void writePayload(ByteBuffer buffer)
{
}
@@ -66,12 +63,12 @@ public class HeartbeatBody implements AMQBody
session.heartbeatBodyReceived(channelId, this);
}
- protected void populateFromBuffer(DataInputStream buffer, long size) throws AMQFrameDecodingException, IOException
+ protected void populateFromBuffer(ByteBuffer buffer, long size) throws AMQFrameDecodingException
{
if(size > 0)
{
//allow other implementations to have a payload, but ignore it:
- buffer.skip(size);
+ buffer.skip((int) size);
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java
index dfc49c6167..c7ada708dc 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBodyFactory.java
@@ -20,11 +20,11 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
+import org.apache.mina.common.ByteBuffer;
public class HeartbeatBodyFactory implements BodyFactory
{
- public AMQBody createBody(DataInputStream in, long bodySize) throws AMQFrameDecodingException
+ public AMQBody createBody(ByteBuffer in, long bodySize) throws AMQFrameDecodingException
{
return new HeartbeatBody();
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
index 8c018316f0..fb3dd89717 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
@@ -22,10 +22,6 @@ package org.apache.qpid.framing;
import org.apache.qpid.AMQException;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
@@ -66,30 +62,35 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
pv.equals(ProtocolVersion.v0_91) ? 1 : pv.getMinorVersion());
}
- public ProtocolInitiation(DataInputStream in) throws IOException
+ public ProtocolInitiation(ByteBuffer in)
{
_protocolHeader = new byte[4];
- in.read(_protocolHeader);
+ in.get(_protocolHeader);
- _protocolClass = in.readByte();
- _protocolInstance = in.readByte();
- _protocolMajor = in.readByte();
- _protocolMinor = in.readByte();
+ _protocolClass = in.get();
+ _protocolInstance = in.get();
+ _protocolMajor = in.get();
+ _protocolMinor = in.get();
}
+ public void writePayload(org.apache.mina.common.ByteBuffer buffer)
+ {
+ writePayload(buffer.buf());
+ }
+
public long getSize()
{
return 4 + 1 + 1 + 1 + 1;
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
- buffer.write(_protocolHeader);
- buffer.write(_protocolClass);
- buffer.write(_protocolInstance);
- buffer.write(_protocolMajor);
- buffer.write(_protocolMinor);
+ buffer.put(_protocolHeader);
+ buffer.put(_protocolClass);
+ buffer.put(_protocolInstance);
+ buffer.put(_protocolMajor);
+ buffer.put(_protocolMinor);
}
public boolean equals(Object o)
@@ -143,9 +144,9 @@ public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQData
* @return true if we have enough data to decode the PI frame fully, false if more
* data is required
*/
- public boolean decodable(DataInputStream in) throws IOException
+ public boolean decodable(ByteBuffer in)
{
- return (in.available() >= 8);
+ return (in.remaining() >= 8);
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
index d2925d13a8..bd763599b0 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
@@ -21,8 +21,7 @@
package org.apache.qpid.framing;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
public class SmallCompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock
{
@@ -69,7 +68,7 @@ public class SmallCompositeAMQDataBlock extends AMQDataBlock implements Encodabl
return frameSize;
}
- public void writePayload(DataOutputStream buffer) throws IOException
+ public void writePayload(ByteBuffer buffer)
{
if (_firstFrame != null)
{
diff --git a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
index ed9136f7c9..76c154581d 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
@@ -145,7 +144,7 @@ public class VersionSpecificRegistry
}
- public AMQMethodBody get(short classID, short methodID, DataInputStream in, long size) throws AMQFrameDecodingException, IOException
+ public AMQMethodBody get(short classID, short methodID, ByteBuffer in, long size) throws AMQFrameDecodingException
{
AMQMethodBodyInstanceFactory bodyFactory;
try
diff --git a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
index 470b7b05e3..0695349f76 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
@@ -21,10 +21,12 @@
package org.apache.qpid.framing.abstraction;
+import org.apache.mina.common.ByteBuffer;
+
public interface ContentChunk
{
int getSize();
- byte[] getData();
+ ByteBuffer getData();
void reduceToFit();
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
index d1e53d6907..7544d9b7e7 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
@@ -23,6 +23,8 @@ package org.apache.qpid.framing.abstraction;
import org.apache.qpid.framing.AMQBody;
+import java.nio.ByteBuffer;
+
public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter
{
AMQBody convertToBody(ContentChunk contentBody);
@@ -30,5 +32,5 @@ public interface ProtocolVersionMethodConverter extends MessagePublishInfoConver
void configure();
- AMQBody convertToBody(byte[] input);
+ AMQBody convertToBody(ByteBuffer buf);
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
index 90a730d6f7..1c4a29b106 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
@@ -21,13 +21,16 @@
package org.apache.qpid.framing.amqp_0_9;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl;
import org.apache.qpid.framing.*;
-
+import org.apache.qpid.framing.amqp_0_9.*;
+import org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl;
public class MethodConverter_0_9 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
{
@@ -69,9 +72,9 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot
}
- public AMQBody convertToBody(byte[] data)
+ public AMQBody convertToBody(java.nio.ByteBuffer buf)
{
- return new ContentBody(data);
+ return new ContentBody(ByteBuffer.wrap(buf));
}
public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
@@ -113,9 +116,9 @@ public class MethodConverter_0_9 extends AbstractMethodConverter implements Prot
return _contentBodyChunk.getSize();
}
- public byte[] getData()
+ public ByteBuffer getData()
{
- return _contentBodyChunk._payload;
+ return _contentBodyChunk.payload;
}
public void reduceToFit()
diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java
index 3b0cc3cebc..6e330574bc 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_0_91/MethodConverter_0_91.java
@@ -21,6 +21,8 @@
package org.apache.qpid.framing.amqp_0_91;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.framing.abstraction.ContentChunk;
@@ -68,9 +70,9 @@ public class MethodConverter_0_91 extends AbstractMethodConverter implements Pro
}
- public AMQBody convertToBody(byte[] data)
+ public AMQBody convertToBody(java.nio.ByteBuffer buf)
{
- return new ContentBody(data);
+ return new ContentBody(ByteBuffer.wrap(buf));
}
public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
@@ -112,9 +114,9 @@ public class MethodConverter_0_91 extends AbstractMethodConverter implements Pro
return _contentBodyChunk.getSize();
}
- public byte[] getData()
+ public ByteBuffer getData()
{
- return _contentBodyChunk._payload;
+ return _contentBodyChunk.payload;
}
public void reduceToFit()
diff --git a/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
index e6d0482f0d..c87820b9b2 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
@@ -26,8 +26,11 @@ import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl;
+import org.apache.qpid.framing.amqp_8_0.BasicPublishBodyImpl;
import org.apache.qpid.framing.*;
+import org.apache.mina.common.ByteBuffer;
+
public class MethodConverter_8_0 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
{
private int _basicPublishClassId;
@@ -57,9 +60,9 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot
return contentBodyChunk.getSize();
}
- public byte[] getData()
+ public ByteBuffer getData()
{
- return contentBodyChunk._payload;
+ return contentBodyChunk.payload;
}
public void reduceToFit()
@@ -78,9 +81,9 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot
}
- public AMQBody convertToBody(byte[] data)
+ public AMQBody convertToBody(java.nio.ByteBuffer buf)
{
- return new ContentBody(data);
+ return new ContentBody(ByteBuffer.wrap(buf));
}
public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
diff --git a/java/common/src/main/java/org/apache/qpid/pool/Job.java b/java/common/src/main/java/org/apache/qpid/pool/Job.java
new file mode 100644
index 0000000000..82b600de88
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/pool/Job.java
@@ -0,0 +1,253 @@
+/*
+ *
+ * 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 org.apache.qpid.pool;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Job is a continuation that batches together other continuations, specifically {@link Event}s, into one continuation.
+ * The {@link Event}s themselves provide methods to process themselves, so processing a job simply consists of sequentially
+ * processing all of its aggregated events.
+ *
+ * The constructor accepts a maximum number of events for the job, and only runs up to that maximum number when
+ * processing the job, but the add method does not enforce this maximum. In other words, not all the enqueued events
+ * may be processed in each run of the job, several runs may be required to clear the queue.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Aggregate many coninuations together into a single continuation.
+ * <tr><td> Sequentially process aggregated continuations. <td> {@link Event}
+ * <tr><td> Provide running and completion status of the aggregate continuation.
+ * <tr><td> Execute a terminal continuation upon job completion. <td> {@link JobCompletionHandler}
+ * </table>
+ *
+ * @todo Could make Job implement Runnable, FutureTask, or a custom Continuation interface, to clarify its status as a
+ * continuation. Job is a continuation that aggregates other continuations and as such is a usefull re-usable
+ * piece of code. There may be other palces than the mina filter chain where continuation batching is used within
+ * qpid, so abstracting this out could provide a usefull building block. This also opens the way to different
+ * kinds of job with a common interface, e.g. parallel or sequential jobs etc.
+ *
+ * @todo For better re-usability could make the completion handler optional. Only run it when one is set.
+ */
+public class Job implements ReadWriteRunnable
+{
+
+ /** Defines the maximum number of events that will be batched into a single job. */
+ public static final int MAX_JOB_EVENTS = Integer.getInteger("amqj.server.read_write_pool.max_events", 10);
+
+ /** The maximum number of events to process per run of the job. More events than this may be queued in the job. */
+ private final int _maxEvents;
+
+ /** Holds the queue of events that make up the job. */
+ private final java.util.Queue<Runnable> _eventQueue = new ConcurrentLinkedQueue<Runnable>();
+
+ /** Holds a status flag, that indicates when the job is actively running. */
+ private final AtomicBoolean _active = new AtomicBoolean();
+
+ private final boolean _readJob;
+
+ private ReferenceCountingExecutorService _poolReference;
+
+ private final static Logger _logger = LoggerFactory.getLogger(Job.class);
+
+ public Job(ReferenceCountingExecutorService poolReference, int maxEvents, boolean readJob)
+ {
+ _poolReference = poolReference;
+ _maxEvents = maxEvents;
+ _readJob = readJob;
+ }
+
+ /**
+ * Enqueus a continuation for sequential processing by this job.
+ *
+ * @param evt The continuation to enqueue.
+ */
+ public void add(Runnable evt)
+ {
+ _eventQueue.add(evt);
+ }
+
+ /**
+ * Sequentially processes, up to the maximum number per job, the aggregated continuations in enqueued in this job.
+ */
+ boolean processAll()
+ {
+ // limit the number of events processed in one run
+ int i = _maxEvents;
+ while( --i != 0 )
+ {
+ Runnable e = _eventQueue.poll();
+ if (e == null)
+ {
+ return true;
+ }
+ else
+ {
+ e.run();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests if there are no more enqueued continuations to process.
+ *
+ * @return <tt>true</tt> if there are no enqueued continuations in this job, <tt>false</tt> otherwise.
+ */
+ public boolean isComplete()
+ {
+ return _eventQueue.peek() == null;
+ }
+
+ /**
+ * Marks this job as active if it is inactive. This method is thread safe.
+ *
+ * @return <tt>true</tt> if this job was inactive and has now been marked as active, <tt>false</tt> otherwise.
+ */
+ public boolean activate()
+ {
+ return _active.compareAndSet(false, true);
+ }
+
+ /**
+ * Marks this job as inactive. This method is thread safe.
+ */
+ public void deactivate()
+ {
+ _active.set(false);
+ }
+
+ /**
+ * Processes a batch of aggregated continuations, marks this job as inactive and call the terminal continuation.
+ */
+ public void run()
+ {
+ if(processAll())
+ {
+ deactivate();
+ completed();
+ }
+ else
+ {
+ notCompleted();
+ }
+ }
+
+ public boolean isRead()
+ {
+ return _readJob;
+ }
+
+ /**
+ * Adds an {@link Event} to a {@link Job}, triggering the execution of the job if it is not already running.
+ *
+ * @param job The job.
+ * @param event The event to hand off asynchronously.
+ */
+ public static void fireAsynchEvent(ExecutorService pool, Job job, Runnable event)
+ {
+
+ job.add(event);
+
+
+ if(pool == null)
+ {
+ return;
+ }
+
+ // rather than perform additional checks on pool to check that it hasn't shutdown.
+ // catch the RejectedExecutionException that will result from executing on a shutdown pool
+ if (job.activate())
+ {
+ try
+ {
+ pool.execute(job);
+ }
+ catch(RejectedExecutionException e)
+ {
+ _logger.warn("Thread pool shutdown while tasks still outstanding");
+ }
+ }
+
+ }
+
+ /**
+ * Implements a terminal continuation for the {@link Job} for this filter. Whenever the Job completes its processing
+ * of a batch of events this is called. This method simply re-activates the job, if it has more events to process.
+ *
+ * @param session The Mina session to work in.
+ * @param job The job that completed.
+ */
+ public void completed()
+ {
+ if (!isComplete())
+ {
+ final ExecutorService pool = _poolReference.getPool();
+
+ if(pool == null)
+ {
+ return;
+ }
+
+
+ // ritchiem : 2006-12-13 Do we need to perform the additional checks here?
+ // Can the pool be shutdown at this point?
+ if (activate())
+ {
+ try
+ {
+ pool.execute(this);
+ }
+ catch(RejectedExecutionException e)
+ {
+ _logger.warn("Thread pool shutdown while tasks still outstanding");
+ }
+
+ }
+ }
+ }
+
+ public void notCompleted()
+ {
+ final ExecutorService pool = _poolReference.getPool();
+
+ if(pool == null)
+ {
+ return;
+ }
+
+ try
+ {
+ pool.execute(this);
+ }
+ catch(RejectedExecutionException e)
+ {
+ _logger.warn("Thread pool shutdown while tasks still outstanding");
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java b/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java
index 14d1befaf1..f0f2652ce3 100644
--- a/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java
+++ b/java/common/src/main/java/org/apache/qpid/protocol/AMQConstant.java
@@ -80,7 +80,7 @@ public final class AMQConstant
/**
* An operator intervened to close the connection for some reason. The client may retry at some later date.
*/
- public static final AMQConstant CONNECTION_FORCED = new AMQConstant(320, "connection forced", true);
+ public static final AMQConstant CONTEXT_IN_USE = new AMQConstant(320, "context in use", true);
/** The client tried to work with an unknown virtual host or cluster. */
public static final AMQConstant INVALID_PATH = new AMQConstant(402, "invalid path", true);
@@ -104,7 +104,7 @@ public final class AMQConstant
public static final AMQConstant REQUEST_TIMEOUT = new AMQConstant(408, "Request Timeout", true);
- public static final AMQConstant ARGUMENT_INVALID = new AMQConstant(409, "argument invalid", true);
+ public static final AMQConstant INVALID_ARGUMENT = new AMQConstant(409, "argument invalid", true);
/**
* The client sent a malformed frame that the server could not decode. This strongly implies a programming error
@@ -153,7 +153,10 @@ public final class AMQConstant
public static final AMQConstant FRAME_MIN_SIZE = new AMQConstant(4096, "frame min size", true);
- public static final AMQConstant INVALID_ARGUMENT = new AMQConstant(542, "invalid argument", true);
+ /**
+ * The server does not support the protocol version
+ */
+ public static final AMQConstant UNSUPPORTED_BROKER_PROTOCOL_ERROR = new AMQConstant(542, "broker unsupported protocol", true);
/**
* The client imp does not support the protocol version
*/
diff --git a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
index fd651a2b66..31953ea6ab 100644
--- a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
+++ b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
@@ -21,11 +21,10 @@
package org.apache.qpid.protocol;
import java.net.SocketAddress;
-import java.nio.ByteBuffer;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
/**
* A ProtocolEngine is a Receiver for java.nio.ByteBuffers. It takes the data passed to it in the received
@@ -33,6 +32,9 @@ import org.apache.qpid.transport.network.NetworkConnection;
*/
public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer>
{
+ // Sets the network driver providing data for this ProtocolEngine
+ void setNetworkDriver (NetworkDriver driver);
+
// Returns the remote address of the NetworkDriver
SocketAddress getRemoteAddress();
@@ -56,6 +58,4 @@ public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer>
void readerIdle();
- public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender);
-
} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java
index 7378edff0c..9df84eef90 100644
--- a/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngineFactory.java
@@ -20,12 +20,12 @@
*/
package org.apache.qpid.protocol;
-import org.apache.qpid.transport.network.NetworkConnection;
+import org.apache.qpid.transport.NetworkDriver;
public interface ProtocolEngineFactory
{
// Returns a new instance of a ProtocolEngine
- ProtocolEngine newProtocolEngine();
+ ProtocolEngine newProtocolEngine(NetworkDriver networkDriver);
} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java b/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
deleted file mode 100644
index e8362f79f0..0000000000
--- a/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
+++ /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.
- *
- */
-package org.apache.qpid.protocol;
-
-public interface ServerProtocolEngine extends ProtocolEngine
-{
- /**
- * Gets the connection ID associated with this ProtocolEngine
- */
- long getConnectionId();
-}
diff --git a/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java
new file mode 100644
index 0000000000..a3dad9acdc
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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 org.apache.qpid.security;
+
+import javax.security.auth.callback.CallbackHandler;
+
+public interface AMQPCallbackHandler extends CallbackHandler
+{
+ void initialise(String username,String password);
+}
diff --git a/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java
new file mode 100644
index 0000000000..89a63abeab
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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 org.apache.qpid.security;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public class UsernamePasswordCallbackHandler implements AMQPCallbackHandler
+{
+ private String _username;
+ private String _password;
+
+ public void initialise(String username,String password)
+ {
+ _username = username;
+ _password = password;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ Callback cb = callbacks[i];
+ if (cb instanceof NameCallback)
+ {
+ ((NameCallback)cb).setName(_username);
+ }
+ else if (cb instanceof PasswordCallback)
+ {
+ ((PasswordCallback)cb).setPassword((_password).toCharArray());
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(cb);
+ }
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
index 01f13408b0..702746b3da 100644
--- a/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java
@@ -20,17 +20,18 @@
*/
package org.apache.qpid.ssl;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
-import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;
/**
@@ -38,92 +39,157 @@ import org.apache.qpid.transport.network.security.ssl.SSLUtil;
* before this will work.
*
*/
-public class SSLContextFactory
-{
- public static final String JAVA_KEY_STORE_CODE = "JKS";
- public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS";
- public static final String KEY_STORE_CERTIFICATE_TYPE = "SunX509";
-
- private SSLContextFactory()
+public class SSLContextFactory {
+
+ /**
+ * Path to the Java keystore file
+ */
+ private String _keyStorePath;
+
+ /**
+ * Password for the keystore
+ */
+ private String _keyStorePassword;
+
+ /**
+ * Cert type to use in keystore
+ */
+ private String _keyStoreCertType;
+
+ /**
+ * Path to the Java truststore file
+ */
+ private String _trustStorePath;
+
+ /**
+ * Password for the truststore
+ */
+ private String _trustStorePassword;
+
+ /**
+ * Cert type to use in truststore
+ */
+ private String _trustStoreCertType;
+
+ private KeyManager customKeyManager;
+
+ public SSLContextFactory(String trustStorePath, String trustStorePassword,
+ String trustStoreCertType)
{
- //no instances
+ this(trustStorePath,trustStorePassword,trustStoreCertType,
+ trustStorePath,trustStorePassword,trustStoreCertType);
}
- public static SSLContext buildServerContext(final String keyStorePath,
- final String keyStorePassword, final String keyStoreCertType)
- throws GeneralSecurityException, IOException
- {
- return buildContext(null, null, null, keyStorePath, keyStorePassword,
- keyStoreCertType, null);
- }
+ /**
+ * Create a factory instance
+ * @param keystorePath path to the Java keystore file
+ * @param keystorePassword password for the Java keystore
+ * @param certType certificate type
+ */
+ public SSLContextFactory(String trustStorePath, String trustStorePassword, String trustStoreCertType,
+ String keyStorePath, String keyStorePassword, String keyStoreCertType)
+ {
- public static SSLContext buildClientContext(final String trustStorePath,
- final String trustStorePassword, final String trustStoreCertType,
- final String keyStorePath, final String keyStorePassword,
- final String keyStoreCertType, final String certAlias)
- throws GeneralSecurityException, IOException
- {
- return buildContext(trustStorePath, trustStorePassword,
- trustStoreCertType, keyStorePath, keyStorePassword,
- keyStoreCertType, certAlias);
- }
-
- private static SSLContext buildContext(final String trustStorePath,
- final String trustStorePassword, final String trustStoreCertType,
- final String keyStorePath, final String keyStorePassword,
- final String keyStoreCertType, final String certAlias)
- throws GeneralSecurityException, IOException
+ _trustStorePath = trustStorePath;
+ _trustStorePassword = trustStorePassword;
+
+ if (_trustStorePassword != null && _trustStorePassword.equals("none"))
+ {
+ _trustStorePassword = null;
+ }
+ _trustStoreCertType = trustStoreCertType;
+
+ _keyStorePath = keyStorePath;
+ _keyStorePassword = keyStorePassword;
+
+ if (_keyStorePassword != null && _keyStorePassword.equals("none"))
+ {
+ _keyStorePassword = null;
+ }
+ _keyStoreCertType = keyStoreCertType;
+
+ if (_trustStorePath == null) {
+ throw new IllegalArgumentException("A TrustStore path or KeyStore path must be specified");
+ }
+ if (_trustStoreCertType == null) {
+ throw new IllegalArgumentException("Cert type must be specified");
+ }
+ }
+
+ public SSLContextFactory(String trustStorePath, String trustStorePassword, String trustStoreCertType,
+ KeyManager customKeyManager)
{
- // Initialize the SSLContext to work with our key managers.
- final SSLContext sslContext = SSLContext
- .getInstance(TRANSPORT_LAYER_SECURITY_CODE);
- final TrustManager[] trustManagers;
- final KeyManager[] keyManagers;
-
- if (trustStorePath != null)
+ _trustStorePath = trustStorePath;
+ _trustStorePassword = trustStorePassword;
+
+ if (_trustStorePassword != null && _trustStorePassword.equals("none"))
{
- final KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath,
- trustStorePassword);
- final TrustManagerFactory tmf = TrustManagerFactory
- .getInstance(trustStoreCertType);
- tmf.init(ts);
-
- trustManagers = tmf.getTrustManagers();
+ _trustStorePassword = null;
}
- else
- {
- trustManagers = null;
+ _trustStoreCertType = trustStoreCertType;
+
+ if (_trustStorePath == null) {
+ throw new IllegalArgumentException("A TrustStore path or KeyStore path must be specified");
+ }
+ if (_trustStoreCertType == null) {
+ throw new IllegalArgumentException("Cert type must be specified");
}
+
+ this.customKeyManager = customKeyManager;
+ }
+
+
+ /**
+ * Builds a SSLContext appropriate for use with a server
+ * @return SSLContext
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
- if (keyStorePath != null)
+ public SSLContext buildServerContext() throws GeneralSecurityException, IOException
+ {
+ KeyStore ts = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType);
+ tmf.init(ts);
+
+ // Initialize the SSLContext to work with our key managers.
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+
+ if (customKeyManager != null)
{
- if (certAlias != null)
- {
- keyManagers = new KeyManager[] { new QpidClientX509KeyManager(
- certAlias, keyStorePath, keyStorePassword,
- keyStoreCertType) };
- }
- else
- {
- final KeyStore ks = SSLUtil.getInitializedKeyStore(
- keyStorePath, keyStorePassword);
-
- char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray();
- // Set up key manager factory to use our key store
- final KeyManagerFactory kmf = KeyManagerFactory
- .getInstance(keyStoreCertType);
- kmf.init(ks, keyStoreCharPassword);
- keyManagers = kmf.getKeyManagers();
- }
+ sslContext.init(new KeyManager[]{customKeyManager},
+ tmf.getTrustManagers(), null);
+
}
else
{
- keyManagers = null;
- }
+ // Create keystore
+ KeyStore ks = SSLUtil.getInitializedKeyStore(_keyStorePath,_keyStorePassword);
+ // Set up key manager factory to use our key store
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(_keyStoreCertType);
+ kmf.init(ks, _keyStorePassword.toCharArray());
- sslContext.init(keyManagers, trustManagers, null);
-
- return sslContext;
- }
+ sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ }
+
+ return sslContext;
+ }
+
+ /**
+ * Creates a SSLContext factory appropriate for use with a client
+ * @return SSLContext
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public SSLContext buildClientContext() throws GeneralSecurityException, IOException
+ {
+ KeyStore ks = SSLUtil.getInitializedKeyStore(_trustStorePath,_trustStorePassword);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(_trustStoreCertType);
+ tmf.init(ks);
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, tmf.getTrustManagers(), null);
+ return context;
+ }
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java b/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java
index 30010a2d89..38f60c04fe 100644
--- a/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java
+++ b/java/common/src/main/java/org/apache/qpid/thread/QpidThreadExecutor.java
@@ -23,7 +23,7 @@ package org.apache.qpid.thread;
import org.apache.qpid.thread.Threading;
-import java.util.concurrent.Executor;
+import edu.emory.mathcs.backport.java.util.concurrent.Executor;
public class QpidThreadExecutor implements Executor
{
diff --git a/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
index 9bdad6b00e..0d9f8c0b28 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
@@ -20,20 +20,28 @@
*/
package org.apache.qpid.transport;
+import org.ietf.jgss.GSSContext;
+import org.ietf.jgss.GSSException;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+
+import org.apache.qpid.security.UsernamePasswordCallbackHandler;
import static org.apache.qpid.transport.Connection.State.OPEN;
import static org.apache.qpid.transport.Connection.State.RESUMING;
+import org.apache.qpid.transport.util.Logger;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.apache.qpid.transport.util.Logger;
-
/**
* ClientDelegate
@@ -44,13 +52,31 @@ public class ClientDelegate extends ConnectionDelegate
{
private static final Logger log = Logger.get(ClientDelegate.class);
+ private static final String KRB5_OID_STR = "1.2.840.113554.1.2.2";
+ protected static final Oid KRB5_OID;
+ static
+ {
+ Oid oid;
+ try
+ {
+ oid = new Oid(KRB5_OID_STR);
+ }
+ catch (GSSException ignore)
+ {
+ oid = null;
+ }
- protected final ConnectionSettings _conSettings;
+ KRB5_OID = oid;
+ }
+
+ private List<String> clientMechs;
+ private ConnectionSettings conSettings;
public ClientDelegate(ConnectionSettings settings)
{
- this._conSettings = settings;
+ this.conSettings = settings;
+ this.clientMechs = Arrays.asList(settings.getSaslMechs().split(" "));
}
public void init(Connection conn, ProtocolHeader hdr)
@@ -66,9 +92,9 @@ public class ClientDelegate extends ConnectionDelegate
{
Map<String,Object> clientProperties = new HashMap<String,Object>();
- if(this._conSettings.getClientProperties() != null)
+ if(this.conSettings.getClientProperties() != null)
{
- clientProperties.putAll(_conSettings.getClientProperties());
+ clientProperties.putAll(this.conSettings.getClientProperties());
}
clientProperties.put("qpid.session_flow", 1);
@@ -83,12 +109,41 @@ public class ClientDelegate extends ConnectionDelegate
(clientProperties, null, null, conn.getLocale());
return;
}
+
+ List<String> choosenMechs = new ArrayList<String>();
+ for (String mech:clientMechs)
+ {
+ if (brokerMechs.contains(mech))
+ {
+ choosenMechs.add(mech);
+ }
+ }
+
+ if (choosenMechs.size() == 0)
+ {
+ conn.exception(new ConnectionException("The following SASL mechanisms " +
+ clientMechs.toString() +
+ " specified by the client are not supported by the broker"));
+ return;
+ }
+
+ String[] mechs = new String[choosenMechs.size()];
+ choosenMechs.toArray(mechs);
+
conn.setServerProperties(start.getServerProperties());
try
{
- final SaslClient sc = createSaslClient(brokerMechs);
-
+ Map<String,Object> saslProps = new HashMap<String,Object>();
+ if (conSettings.isUseSASLEncryption())
+ {
+ saslProps.put(Sasl.QOP, "auth-conf");
+ }
+ UsernamePasswordCallbackHandler handler =
+ new UsernamePasswordCallbackHandler();
+ handler.initialise(conSettings.getUsername(), conSettings.getPassword());
+ SaslClient sc = Sasl.createSaslClient
+ (mechs, null, conSettings.getSaslProtocol(), conSettings.getSaslServerName(), saslProps, handler);
conn.setSaslClient(sc);
byte[] response = sc.hasInitialResponse() ?
@@ -97,22 +152,12 @@ public class ClientDelegate extends ConnectionDelegate
(clientProperties, sc.getMechanismName(), response,
conn.getLocale());
}
- catch (ConnectionException ce)
- {
- conn.exception(ce);
- }
catch (SaslException e)
{
conn.exception(e);
}
}
-
- protected SaslClient createSaslClient(List<Object> brokerMechs) throws ConnectionException, SaslException
- {
- throw new UnsupportedOperationException();
- }
-
@Override
public void connectionSecure(Connection conn, ConnectionSecure secure)
{
@@ -131,7 +176,7 @@ public class ClientDelegate extends ConnectionDelegate
@Override
public void connectionTune(Connection conn, ConnectionTune tune)
{
- int hb_interval = calculateHeartbeatInterval(_conSettings.getHeartbeatInterval(),
+ int hb_interval = calculateHeartbeatInterval(conSettings.getHeartbeatInterval(),
tune.getHeartbeatMin(),
tune.getHeartbeatMax()
);
@@ -146,12 +191,32 @@ public class ClientDelegate extends ConnectionDelegate
//(or that forced by protocol limitations [0xFFFF])
conn.setChannelMax(channelMax == 0 ? Connection.MAX_CHANNEL_MAX : channelMax);
- conn.connectionOpen(_conSettings.getVhost(), null, Option.INSIST);
+ conn.connectionOpen(conSettings.getVhost(), null, Option.INSIST);
}
@Override
public void connectionOpenOk(Connection conn, ConnectionOpenOk ok)
{
+ SaslClient sc = conn.getSaslClient();
+ if (sc != null)
+ {
+ if (sc.getMechanismName().equals("GSSAPI"))
+ {
+ String id = getKerberosUser();
+ if (id != null)
+ {
+ conn.setUserID(id);
+ }
+ }
+ else if (sc.getMechanismName().equals("EXTERNAL"))
+ {
+ if (conn.getSecurityLayer() != null)
+ {
+ conn.setUserID(conn.getSecurityLayer().getUserID());
+ }
+ }
+ }
+
if (conn.isConnectionResuming())
{
conn.setState(RESUMING);
@@ -182,7 +247,7 @@ public class ClientDelegate extends ConnectionDelegate
int i = heartbeat;
if (i == 0)
{
- log.info("Idle timeout is 0 sec. Heartbeats are disabled.");
+ log.warn("Idle timeout is zero. Heartbeats are disabled");
return 0; // heartbeats are disabled.
}
else if (i >= min && i <= max)
@@ -191,8 +256,8 @@ public class ClientDelegate extends ConnectionDelegate
}
else
{
- log.info("The broker does not support the configured connection idle timeout of %s sec," +
- " using the brokers max supported value of %s sec instead.", i,max);
+ log.warn("Ignoring the idle timeout %s set by the connection," +
+ " using the brokers max value %s", i,max);
return max;
}
}
@@ -221,7 +286,35 @@ public class ClientDelegate extends ConnectionDelegate
}
+ private String getKerberosUser()
+ {
+ log.debug("Obtaining userID from kerberos");
+ String service = conSettings.getSaslProtocol() + "@" + conSettings.getSaslServerName();
+ GSSManager manager = GSSManager.getInstance();
+
+ try
+ {
+ GSSName acceptorName = manager.createName(service,
+ GSSName.NT_HOSTBASED_SERVICE, KRB5_OID);
+
+ GSSContext secCtx = manager.createContext(acceptorName,
+ KRB5_OID,
+ null,
+ GSSContext.INDEFINITE_LIFETIME);
+ secCtx.initSecContext(new byte[0], 0, 1);
+ if (secCtx.getSrcName() != null)
+ {
+ return secCtx.getSrcName().toString();
+ }
+ }
+ catch (GSSException e)
+ {
+ log.warn("Unable to retrieve userID from Kerberos due to error",e);
+ }
+
+ return null;
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/java/common/src/main/java/org/apache/qpid/transport/Connection.java
index 1c521244d0..e5e10c0e07 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/Connection.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java
@@ -25,29 +25,21 @@ import static org.apache.qpid.transport.Connection.State.CLOSING;
import static org.apache.qpid.transport.Connection.State.NEW;
import static org.apache.qpid.transport.Connection.State.OPEN;
import static org.apache.qpid.transport.Connection.State.OPENING;
+import static org.apache.qpid.transport.Connection.State.RESUMING;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslServer;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.transport.network.Assembler;
-import org.apache.qpid.transport.network.Disassembler;
-import org.apache.qpid.transport.network.InputHandler;
-import org.apache.qpid.transport.network.NetworkConnection;
-import org.apache.qpid.transport.network.OutgoingNetworkTransport;
-import org.apache.qpid.transport.network.Transport;
import org.apache.qpid.transport.network.security.SecurityLayer;
-import org.apache.qpid.transport.network.security.SecurityLayerFactory;
import org.apache.qpid.transport.util.Logger;
import org.apache.qpid.transport.util.Waiter;
import org.apache.qpid.util.Strings;
@@ -73,7 +65,6 @@ public class Connection extends ConnectionInvoker
public static final int MAX_CHANNEL_MAX = 0xFFFF;
public static final int MIN_USABLE_CHANNEL_NUM = 0;
-
public enum State { NEW, CLOSED, OPENING, OPEN, CLOSING, CLOSE_RCVD, RESUMING }
static class DefaultConnectionListener implements ConnectionListener
@@ -121,14 +112,17 @@ public class Connection extends ConnectionInvoker
private SaslServer saslServer;
private SaslClient saslClient;
private int idleTimeout = 0;
+ private String _authorizationID;
private Map<String,Object> _serverProperties;
private String userID;
private ConnectionSettings conSettings;
private SecurityLayer securityLayer;
private String _clientId;
-
+
+ private static final AtomicLong idGenerator = new AtomicLong(0);
+ private final long _connectionId = idGenerator.incrementAndGet();
private final AtomicBoolean connectionLost = new AtomicBoolean(false);
-
+
public Connection() {}
public void setConnectionDelegate(ConnectionDelegate delegate)
@@ -239,24 +233,14 @@ public class Connection extends ConnectionInvoker
conSettings = settings;
state = OPENING;
userID = settings.getUsername();
-
- securityLayer = SecurityLayerFactory.newInstance(getConnectionSettings());
-
- OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10);
- Receiver<ByteBuffer> secureReceiver = securityLayer.receiver(new InputHandler(new Assembler(this)));
- if(secureReceiver instanceof ConnectionListener)
- {
- addConnectionListener((ConnectionListener)secureReceiver);
- }
-
- NetworkConnection network = transport.connect(settings, secureReceiver, null);
- final Sender<ByteBuffer> secureSender = securityLayer.sender(network.getSender());
- if(secureSender instanceof ConnectionListener)
- {
- addConnectionListener((ConnectionListener)secureSender);
- }
- sender = new Disassembler(secureSender, settings.getMaxFrameSize());
-
+ delegate = new ClientDelegate(settings);
+
+ TransportBuilder transport = new TransportBuilder();
+ transport.init(this);
+ this.sender = transport.buildSenderPipe();
+ transport.buildReceiverPipe(this);
+ this.securityLayer = transport.getSecurityLayer();
+
send(new ProtocolHeader(1, 0, 10));
Waiter w = new Waiter(lock, timeout);
@@ -337,31 +321,23 @@ public class Connection extends ConnectionInvoker
Waiter w = new Waiter(lock, timeout);
while (w.hasTime() && state != OPEN && error == null)
{
- w.await();
+ w.await();
}
-
+
if (state != OPEN)
{
throw new ConnectionException("Timed out waiting for connection to be ready. Current state is :" + state);
}
-
+
Session ssn = _sessionFactory.newSession(this, name, expiry);
- registerSession(ssn);
+ sessions.put(name, ssn);
map(ssn);
ssn.attach();
return ssn;
}
}
- public void registerSession(Session ssn)
- {
- synchronized (lock)
- {
- sessions.put(ssn.getName(),ssn);
- }
- }
-
- public void removeSession(Session ssn)
+ void removeSession(Session ssn)
{
synchronized (lock)
{
@@ -376,6 +352,11 @@ public class Connection extends ConnectionInvoker
_sessionFactory = sessionFactory;
}
+ public long getConnectionId()
+ {
+ return _connectionId;
+ }
+
public ConnectionDelegate getConnectionDelegate()
{
return delegate;
@@ -424,7 +405,7 @@ public class Connection extends ConnectionInvoker
else
{
throw new ProtocolViolationException(
- "Received frames for an already detached session", null);
+ "Received frames for an already dettached session", null);
}
}
@@ -473,7 +454,7 @@ public class Connection extends ConnectionInvoker
}
}
- public Session getSession(int channel)
+ protected Session getSession(int channel)
{
synchronized (lock)
{
@@ -487,10 +468,18 @@ public class Connection extends ConnectionInvoker
{
for (Session ssn : sessions.values())
{
- map(ssn);
- ssn.resume();
+ if (ssn.isTransacted())
+ {
+ removeSession(ssn);
+ ssn.setState(Session.State.CLOSED);
+ }
+ else
+ {
+ map(ssn);
+ ssn.attach();
+ ssn.resume();
+ }
}
-
setState(OPEN);
}
}
@@ -577,12 +566,12 @@ public class Connection extends ConnectionInvoker
{
close(ConnectionCloseCode.NORMAL, null);
}
-
+
public void mgmtClose()
{
close(ConnectionCloseCode.CONNECTION_FORCED, "The connection was closed using the broker's management interface.");
}
-
+
public void close(ConnectionCloseCode replyCode, String replyText, Option ... _options)
{
synchronized (lock)
@@ -656,6 +645,16 @@ public class Connection extends ConnectionInvoker
return idleTimeout;
}
+ public void setAuthorizationID(String authorizationID)
+ {
+ _authorizationID = authorizationID;
+ }
+
+ public String getAuthorizationID()
+ {
+ return _authorizationID;
+ }
+
public String getUserID()
{
return userID;
@@ -685,24 +684,15 @@ public class Connection extends ConnectionInvoker
{
return conSettings;
}
-
+
public SecurityLayer getSecurityLayer()
{
return securityLayer;
}
-
+
public boolean isConnectionResuming()
{
return connectionLost.get();
}
- protected Collection<Session> getChannels()
- {
- return channels.values();
- }
-
- public boolean hasSessionWithName(final String name)
- {
- return sessions.containsKey(new Binary(name.getBytes()));
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java
index 393301659d..88dd2d6afa 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java
@@ -85,7 +85,7 @@ public abstract class ConnectionDelegate
@Override public void sessionDetach(Connection conn, SessionDetach dtc)
{
Session ssn = conn.getSession(dtc.getChannel());
- ssn.sessionDetached(dtc.getName(), ssn.getDetachCode() == null? SessionDetachCode.NORMAL: ssn.getDetachCode());
+ ssn.sessionDetached(dtc.getName(), SessionDetachCode.NORMAL);
conn.unmap(ssn);
ssn.closed();
}
@@ -95,7 +95,6 @@ public abstract class ConnectionDelegate
Session ssn = conn.getSession(dtc.getChannel());
if (ssn != null)
{
- ssn.setDetachCode(dtc.getCode());
conn.unmap(ssn);
ssn.closed();
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java
index 37a8e594c0..08678b213b 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionSettings.java
@@ -30,8 +30,6 @@ import java.util.Map;
*/
public class ConnectionSettings
{
- public static final String WILDCARD_ADDRESS = "*";
-
String protocol = "tcp";
String host = "localhost";
String vhost;
@@ -58,7 +56,7 @@ public class ConnectionSettings
boolean verifyHostname;
// SASL props
- String saslMechs = System.getProperty("qpid.sasl_mechs", null);
+ String saslMechs = System.getProperty("qpid.sasl_mechs", "PLAIN");
String saslProtocol = System.getProperty("qpid.sasl_protocol", "AMQP");
String saslServerName = System.getProperty("qpid.sasl_server_name", "localhost");
boolean useSASLEncryption;
diff --git a/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java
new file mode 100644
index 0000000000..86af97bf7e
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/NetworkDriver.java
@@ -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.
+ *
+ */
+package org.apache.qpid.transport;
+
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.SocketAddress;
+
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.ssl.SSLContextFactory;
+
+public interface NetworkDriver extends Sender<java.nio.ByteBuffer>
+{
+ // Creates a NetworkDriver which attempts to connect to destination on port and attaches the ProtocolEngine to
+ // it using the SSLContextFactory if provided
+ void open(int port, InetAddress destination, ProtocolEngine engine,
+ NetworkDriverConfiguration config, SSLContextFactory sslFactory)
+ throws OpenException;
+
+ // listens for incoming connections on the specified ports and address and creates a new NetworkDriver which
+ // processes incoming connections with ProtocolEngines and SSLEngines created from the factories
+ // (in the case of an SSLContextFactory, if provided)
+ void bind (int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory,
+ NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException;
+
+ // Returns the remote address of the underlying socket
+ SocketAddress getRemoteAddress();
+
+ // Returns the local address of the underlying socket
+ SocketAddress getLocalAddress();
+
+ /**
+ * The length of time after which the ProtocolEngines readIdle() method should be called if no data has been
+ * read in seconds
+ */
+ void setMaxReadIdle(int idleTime);
+
+ /**
+ * The length of time after which the ProtocolEngines writeIdle() method should be called if no data has been
+ * written in seconds
+ */
+ void setMaxWriteIdle(int idleTime);
+
+} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java
new file mode 100644
index 0000000000..c38afe5dd5
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/NetworkDriverConfiguration.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.transport;
+
+/**
+ * This interface provides a means for NetworkDrivers to configure TCP options such as incoming and outgoing
+ * buffer sizes and set particular options on the socket. NetworkDrivers should honour the values returned
+ * from here if the underlying implementation supports them.
+ */
+public interface NetworkDriverConfiguration
+{
+ // Taken from Socket
+ Boolean getKeepAlive();
+ Boolean getOOBInline();
+ Boolean getReuseAddress();
+ Integer getSoLinger(); // null means off
+ Integer getSoTimeout();
+ Boolean getTcpNoDelay();
+ Integer getTrafficClass();
+
+ // The amount of memory in bytes to allocate to the incoming buffer
+ Integer getReceiveBufferSize();
+
+ // The amount of memory in bytes to allocate to the outgoing buffer
+ Integer getSendBufferSize();
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
deleted file mode 100644
index 8d3f7a779a..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java
+++ /dev/null
@@ -1,46 +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.
- *
- */
-package org.apache.qpid.transport;
-
-/**
- * This interface provides a means for NetworkDrivers to configure TCP options such as incoming and outgoing
- * buffer sizes and set particular options on the socket. NetworkDrivers should honour the values returned
- * from here if the underlying implementation supports them.
- */
-public interface NetworkTransportConfiguration
-{
- // Taken from Socket
- Boolean getTcpNoDelay();
-
- // The amount of memory in bytes to allocate to the incoming buffer
- Integer getReceiveBufferSize();
-
- // The amount of memory in bytes to allocate to the outgoing buffer
- Integer getSendBufferSize();
-
- Integer getPort();
-
- String getHost();
-
- String getTransport();
-
- Integer getConnectorProcessors();
-}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java b/java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java
deleted file mode 100644
index 924c327861..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/SenderClosedException.java
+++ /dev/null
@@ -1,52 +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.
- *
- */
-package org.apache.qpid.transport;
-
-
-/**
- * SenderClosedException
- *
- */
-
-public class SenderClosedException extends SenderException
-{
-
- public SenderClosedException(String message, Throwable cause)
- {
- super(message, cause);
- }
-
- public SenderClosedException(String message)
- {
- super(message);
- }
-
- public SenderClosedException(Throwable cause)
- {
- super(cause);
- }
-
- public void rethrow()
- {
- throw new SenderClosedException(getMessage(), this);
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
index 82fa6ca473..f21df251da 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
@@ -75,7 +75,10 @@ public class ServerDelegate extends ConnectionDelegate
if (mechanism == null || mechanism.length() == 0)
{
- tuneAuthorizedConnection(conn);
+ conn.connectionTune
+ (getChannelMax(),
+ org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE,
+ 0, getHeartbeatMax());
return;
}
@@ -94,7 +97,8 @@ public class ServerDelegate extends ConnectionDelegate
}
catch (SaslException e)
{
- connectionAuthFailed(conn, e);
+ conn.exception(e);
+ conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage());
}
}
@@ -105,52 +109,33 @@ public class ServerDelegate extends ConnectionDelegate
return ss;
}
- protected void secure(final SaslServer ss, final Connection conn, final byte[] response)
+ private void secure(Connection conn, byte[] response)
{
+ SaslServer ss = conn.getSaslServer();
try
{
byte[] challenge = ss.evaluateResponse(response);
if (ss.isComplete())
{
ss.dispose();
- tuneAuthorizedConnection(conn);
+ conn.connectionTune
+ (getChannelMax(),
+ org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE,
+ 0, getHeartbeatMax());
+ conn.setAuthorizationID(ss.getAuthorizationID());
}
else
{
- connectionAuthContinue(conn, challenge);
+ conn.connectionSecure(challenge);
}
}
catch (SaslException e)
{
- connectionAuthFailed(conn, e);
+ conn.exception(e);
+ conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage());
}
}
- protected void connectionAuthFailed(final Connection conn, Exception e)
- {
- conn.exception(e);
- conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage());
- }
-
- protected void connectionAuthContinue(final Connection conn, byte[] challenge)
- {
- conn.connectionSecure(challenge);
- }
-
- protected void tuneAuthorizedConnection(final Connection conn)
- {
- conn.connectionTune
- (getChannelMax(),
- org.apache.qpid.transport.network.ConnectionBinding.MAX_FRAME_SIZE,
- 0, getHeartbeatMax());
- }
-
- protected void secure(final Connection conn, final byte[] response)
- {
- final SaslServer ss = conn.getSaslServer();
- secure(ss, conn, response);
- }
-
protected int getHeartbeatMax()
{
return 0xFFFF;
@@ -170,7 +155,22 @@ public class ServerDelegate extends ConnectionDelegate
@Override
public void connectionTuneOk(Connection conn, ConnectionTuneOk ok)
{
+ int okChannelMax = ok.getChannelMax();
+
+ if (okChannelMax > getChannelMax())
+ {
+ _logger.error("Connection '" + conn.getConnectionId() + "' being severed, " +
+ "client connectionTuneOk returned a channelMax (" + okChannelMax +
+ ") above the servers offered limit (" + getChannelMax() +")");
+ //Due to the error we must forcefully close the connection without negotiation
+ conn.getSender().close();
+ return;
+ }
+
+ //0 means no implied limit, except available server resources
+ //(or that forced by protocol limitations [0xFFFF])
+ conn.setChannelMax(okChannelMax == 0 ? Connection.MAX_CHANNEL_MAX : okChannelMax);
}
@Override
@@ -200,11 +200,4 @@ public class ServerDelegate extends ConnectionDelegate
ssn.sessionAttached(atc.getName());
ssn.setState(Session.State.OPEN);
}
-
- protected void setConnectionTuneOkChannelMax(final Connection conn, final int okChannelMax)
- {
- //0 means no implied limit, except available server resources
- //(or that forced by protocol limitations [0xFFFF])
- conn.setChannelMax(okChannelMax == 0 ? Connection.MAX_CHANNEL_MAX : okChannelMax);
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java
index 0de558d152..214d4534c1 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/Session.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java
@@ -30,8 +30,6 @@ import static org.apache.qpid.transport.Session.State.DETACHED;
import static org.apache.qpid.transport.Session.State.NEW;
import static org.apache.qpid.transport.Session.State.OPEN;
import static org.apache.qpid.transport.Session.State.RESUMING;
-
-import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.transport.network.Frame;
import static org.apache.qpid.transport.util.Functions.mod;
import org.apache.qpid.transport.util.Logger;
@@ -44,9 +42,7 @@ import static org.apache.qpid.util.Serial.max;
import static org.apache.qpid.util.Strings.toUTF8;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -59,6 +55,7 @@ import java.util.concurrent.TimeUnit;
public class Session extends SessionInvoker
{
+
private static final Logger log = Logger.get(Session.class);
public enum State { NEW, DETACHED, RESUMING, OPEN, CLOSING, CLOSED }
@@ -92,9 +89,7 @@ public class Session extends SessionInvoker
private int channel;
private SessionDelegate delegate;
private SessionListener listener = new DefaultSessionListener();
- private final long timeout = Long.getLong(ClientProperties.QPID_SYNC_OP_TIMEOUT,
- Long.getLong(ClientProperties.AMQJ_DEFAULT_SYNCWRITE_TIMEOUT,
- ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT));
+ private long timeout = 60000;
private boolean autoSync = false;
private boolean incomingInit;
@@ -122,9 +117,7 @@ public class Session extends SessionInvoker
private Thread resumer = null;
private boolean transacted = false;
- private SessionDetachCode detachCode;
- private final Object stateLock = new Object();
-
+
protected Session(Connection connection, Binary name, long expiry)
{
this(connection, new SessionDelegate(), name, expiry);
@@ -259,8 +252,6 @@ public class Session extends SessionInvoker
{
synchronized (commands)
{
- attach();
-
for (int i = maxComplete + 1; lt(i, commandsOut); i++)
{
Method m = commands[mod(i, commands.length)];
@@ -271,48 +262,16 @@ public class Session extends SessionInvoker
}
else if (m instanceof MessageTransfer)
{
- MessageTransfer xfr = (MessageTransfer)m;
-
- if (xfr.getHeader() != null)
- {
- if (xfr.getHeader().get(DeliveryProperties.class) != null)
- {
- xfr.getHeader().get(DeliveryProperties.class).setRedelivered(true);
- }
- else
- {
- Struct[] structs = xfr.getHeader().getStructs();
- DeliveryProperties deliveryProps = new DeliveryProperties();
- deliveryProps.setRedelivered(true);
-
- List<Struct> list = Arrays.asList(structs);
- list.add(deliveryProps);
- xfr.setHeader(new Header(list));
- }
-
- }
- else
- {
- DeliveryProperties deliveryProps = new DeliveryProperties();
- deliveryProps.setRedelivered(true);
- xfr.setHeader(new Header(deliveryProps));
- }
+ ((MessageTransfer)m).getHeader().get(DeliveryProperties.class).setRedelivered(true);
}
sessionCommandPoint(m.getId(), 0);
send(m);
}
-
+
sessionCommandPoint(commandsOut, 0);
-
sessionFlush(COMPLETED);
resumer = Thread.currentThread();
state = RESUMING;
-
- if(isTransacted())
- {
- txSelect();
- }
-
listener.resumed(this);
resumer = null;
}
@@ -463,10 +422,7 @@ public class Session extends SessionInvoker
{
return;
}
- if (copy.size() > 0)
- {
- sessionCompleted(copy, options);
- }
+ sessionCompleted(copy, options);
}
}
@@ -576,6 +532,17 @@ public class Session extends SessionInvoker
{
if (m.getEncodedTrack() == Frame.L4)
{
+
+ if (state == DETACHED && transacted)
+ {
+ state = CLOSED;
+ delegate.closed(this);
+ connection.removeSession(this);
+ throw new SessionException(
+ "Session failed over, possibly in the middle of a transaction. " +
+ "Closing the session. Any Transaction in progress will be rolledback.");
+ }
+
if (m.hasPayload())
{
acquireCredit();
@@ -583,30 +550,24 @@ public class Session extends SessionInvoker
synchronized (commands)
{
- //allow the txSelect operation to be invoked during resume
- boolean skipWait = m instanceof TxSelect && state == RESUMING;
-
- if(!skipWait)
+ if (state == DETACHED && m.isUnreliable())
{
- if (state == DETACHED && m.isUnreliable())
+ Thread current = Thread.currentThread();
+ if (!current.equals(resumer))
{
- Thread current = Thread.currentThread();
- if (!current.equals(resumer))
- {
- return;
- }
+ return;
}
+ }
- if (state != OPEN && state != CLOSED && state != CLOSING)
+ if (state != OPEN && state != CLOSED && state != CLOSING)
+ {
+ Thread current = Thread.currentThread();
+ if (!current.equals(resumer))
{
- Thread current = Thread.currentThread();
- if (!current.equals(resumer))
+ Waiter w = new Waiter(commands, timeout);
+ while (w.hasTime() && (state != OPEN && state != CLOSED))
{
- Waiter w = new Waiter(commands, timeout);
- while (w.hasTime() && (state != OPEN && state != CLOSED))
- {
- w.await();
- }
+ w.await();
}
}
}
@@ -700,12 +661,7 @@ public class Session extends SessionInvoker
{
sessionCommandPoint(0, 0);
}
-
- boolean replayTransfer = !closing && !transacted &&
- m instanceof MessageTransfer &&
- ! m.isUnreliable();
-
- if ((replayTransfer) || m.hasCompletionListener())
+ if ((!closing && !transacted && m instanceof MessageTransfer) || m.hasCompletionListener())
{
commands[mod(next, commands.length)] = m;
commandBytes += m.getBodySize();
@@ -970,29 +926,16 @@ public class Session extends SessionInvoker
public void close()
{
- if (log.isDebugEnabled())
- {
- log.debug("Closing [%s] in state [%s]", this, state);
- }
synchronized (commands)
{
- switch(state)
- {
- case DETACHED:
- state = CLOSED;
- delegate.closed(this);
- connection.removeSession(this);
- listener.closed(this);
- break;
- case CLOSED:
- break;
- default:
- state = CLOSING;
- setClose(true);
- sessionRequestTimeout(0);
- sessionDetach(name.getBytes());
- awaitClose();
- }
+ state = CLOSING;
+ setClose(true);
+ sessionRequestTimeout(0);
+ sessionDetach(name.getBytes());
+
+ awaitClose();
+
+
}
}
@@ -1052,8 +995,7 @@ public class Session extends SessionInvoker
if(state == CLOSED)
{
- connection.removeSession(this);
- listener.closed(this);
+ connection.removeSession(this);
}
}
@@ -1066,55 +1008,13 @@ public class Session extends SessionInvoker
{
return String.format("ssn:%s", name);
}
-
+
public void setTransacted(boolean b) {
this.transacted = b;
}
-
+
public boolean isTransacted(){
return transacted;
}
-
- public void setDetachCode(SessionDetachCode dtc)
- {
- this.detachCode = dtc;
- }
-
- public SessionDetachCode getDetachCode()
- {
- return this.detachCode;
- }
-
- public void awaitOpen()
- {
- switch (state)
- {
- case NEW:
- synchronized(stateLock)
- {
- Waiter w = new Waiter(stateLock, timeout);
- while (w.hasTime() && state == NEW)
- {
- w.await();
- }
- }
-
- if (state != OPEN)
- {
- throw new SessionException("Timed out waiting for Session to open");
- }
- break;
- case DETACHED:
- case CLOSING:
- case CLOSED:
- throw new SessionException("Session closed");
- default :
- break;
- }
- }
-
- public Object getStateLock()
- {
- return stateLock;
- }
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
index 3341149e5f..5d8e4d5565 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
@@ -76,10 +76,6 @@ public class SessionDelegate
@Override public void sessionAttached(Session ssn, SessionAttached atc)
{
ssn.setState(Session.State.OPEN);
- synchronized (ssn.getStateLock())
- {
- ssn.getStateLock().notifyAll();
- }
}
@Override public void sessionTimeout(Session ssn, SessionTimeout t)
@@ -206,19 +202,11 @@ public class SessionDelegate
public void closed(Session session)
{
- log.debug("CLOSED: [%s]", session);
- synchronized (session.getStateLock())
- {
- session.getStateLock().notifyAll();
- }
+ log.warn("CLOSED: [%s]", session);
}
public void detached(Session session)
{
- log.debug("DETACHED: [%s]", session);
- synchronized (session.getStateLock())
- {
- session.getStateLock().notifyAll();
- }
+ log.warn("DETACHED: [%s]", session);
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java b/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java
new file mode 100644
index 0000000000..c08909c6e4
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/TransportBuilder.java
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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 org.apache.qpid.transport;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
+import org.apache.qpid.transport.network.NetworkTransport;
+import org.apache.qpid.transport.network.Transport;
+import org.apache.qpid.transport.network.security.SecurityLayer;
+
+public class TransportBuilder
+{
+ private Connection con;
+ private ConnectionSettings settings;
+ private NetworkTransport transport;
+ private SecurityLayer securityLayer = new SecurityLayer();
+
+ public void init(Connection con) throws TransportException
+ {
+ this.con = con;
+ this.settings = con.getConnectionSettings();
+ transport = Transport.getTransport();
+ transport.init(settings);
+ securityLayer.init(con);
+ }
+
+ public Sender<ProtocolEvent> buildSenderPipe()
+ {
+ ConnectionSettings settings = con.getConnectionSettings();
+
+ // Io layer
+ Sender<ByteBuffer> sender = transport.sender();
+
+ // Security layer
+ sender = securityLayer.sender(sender);
+
+ Disassembler dis = new Disassembler(sender, settings.getMaxFrameSize());
+ return dis;
+ }
+
+ public void buildReceiverPipe(Receiver<ProtocolEvent> delegate)
+ {
+ Receiver<ByteBuffer> receiver = new InputHandler(new Assembler(delegate));
+
+ // Security layer
+ receiver = securityLayer.receiver(receiver);
+
+ //Io layer
+ transport.receiver(receiver);
+ }
+
+ public SecurityLayer getSecurityLayer()
+ {
+ return securityLayer;
+ }
+
+} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
index 0ccfcfcb70..908d14a307 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
@@ -63,7 +63,6 @@ abstract class AbstractEncoder implements Encoder
ENCODINGS.put(Double.class, Type.DOUBLE);
ENCODINGS.put(Character.class, Type.CHAR);
ENCODINGS.put(byte[].class, Type.VBIN32);
- ENCODINGS.put(UUID.class, Type.UUID);
}
private final Map<String,byte[]> str8cache = new LinkedHashMap<String,byte[]>()
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java
deleted file mode 100644
index b371df639e..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java
+++ /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.
- *
- */
-package org.apache.qpid.transport.network;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-
-public interface IncomingNetworkTransport extends NetworkTransport
-{
- public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext);
-} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
deleted file mode 100644
index 7384702525..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
+++ /dev/null
@@ -1,49 +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.
- *
- */
-package org.apache.qpid.transport.network;
-
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.transport.Sender;
-
-public interface NetworkConnection
-{
- Sender<ByteBuffer> getSender();
-
- void start();
-
- void close();
-
- /**
- * Returns the remote address of the underlying socket.
- */
- SocketAddress getRemoteAddress();
-
- /**
- * Returns the local address of the underlying socket.
- */
- SocketAddress getLocalAddress();
-
- void setMaxWriteIdle(int sec);
-
- void setMaxReadIdle(int sec);
-} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java
index f71d39c381..5e12d7e7c6 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkTransport.java
@@ -20,11 +20,19 @@
*/
package org.apache.qpid.transport.network;
-/**
- * A network transport is responsible for the establishment of network connections.
- * NetworkTransport implementations are pluggable via the {@link Transport} class.
- */
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ConnectionSettings;
+
public interface NetworkTransport
{
+ public void init(ConnectionSettings settings);
+
+ public Sender<ByteBuffer> sender();
+
+ public void receiver(Receiver<ByteBuffer> delegate);
+
public void close();
-}
+} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java
deleted file mode 100644
index c3c248761c..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java
+++ /dev/null
@@ -1,35 +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.
- *
- */
-package org.apache.qpid.transport.network;
-
-import java.nio.ByteBuffer;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.Receiver;
-
-public interface OutgoingNetworkTransport extends NetworkTransport
-{
- public NetworkConnection getConnection();
-
- public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext);
-} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java b/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java
index da4349ba86..f0bf04d04f 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/Transport.java
@@ -1,5 +1,5 @@
/*
- *
+ *
* 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
@@ -7,128 +7,50 @@
* 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 org.apache.qpid.transport.network;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+package org.apache.qpid.transport.network;
-import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.transport.TransportException;
public class Transport
-{
- public static final String QPID_TRANSPORT_PROPNAME = "qpid.transport";
- public static final String QPID_TRANSPORT_V0_8_PROPNAME = "qpid.transport.v0_8";
- public static final String QPID_TRANSPORT_V0_9_PROPNAME = "qpid.transport.v0_9";
- public static final String QPID_TRANSPORT_V0_9_1_PROPNAME = "qpid.transport.v0_9_1";
- public static final String QPID_TRANSPORT_V0_10_PROPNAME = "qpid.transport.v0_10";
- public static final String QPID_BROKER_TRANSPORT_PROPNAME = "qpid.broker.transport";
-
- // Can't reference the class directly here, as this would preclude the ability to bundle transports separately.
- private static final String IO_TRANSPORT_CLASSNAME = "org.apache.qpid.transport.network.io.IoNetworkTransport";
-
- public static final String TCP = "tcp";
-
- private final static Map<ProtocolVersion,String> OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP;
-
- static
- {
- final Map<ProtocolVersion,String> map = new HashMap<ProtocolVersion, String>();
- map.put(ProtocolVersion.v8_0, IO_TRANSPORT_CLASSNAME);
- map.put(ProtocolVersion.v0_9, IO_TRANSPORT_CLASSNAME);
- map.put(ProtocolVersion.v0_91, IO_TRANSPORT_CLASSNAME);
- map.put(ProtocolVersion.v0_10, IO_TRANSPORT_CLASSNAME);
-
- OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP = Collections.unmodifiableMap(map);
- }
-
- public static IncomingNetworkTransport getIncomingTransportInstance()
+{
+ private final static Class<?> transportClass;
+
+ static
{
- return (IncomingNetworkTransport) loadTransportClass(
- System.getProperty(QPID_BROKER_TRANSPORT_PROPNAME, IO_TRANSPORT_CLASSNAME));
- }
-
- public static OutgoingNetworkTransport getOutgoingTransportInstance(
- final ProtocolVersion protocolVersion)
- {
-
- final String overrride = getOverrideClassNameFromSystemProperty(protocolVersion);
- final String networkTransportClassName;
- if (overrride != null)
- {
- networkTransportClassName = overrride;
- }
- else
- {
- networkTransportClassName = OUTGOING_PROTOCOL_TO_IMPLDEFAULTS_MAP.get(protocolVersion);
- }
-
- return (OutgoingNetworkTransport) loadTransportClass(networkTransportClassName);
- }
-
- private static NetworkTransport loadTransportClass(final String networkTransportClassName)
- {
- if (networkTransportClassName == null)
- {
- throw new IllegalArgumentException("transport class name must not be null");
- }
-
try
{
- final Class<?> clazz = Class.forName(networkTransportClassName);
- return (NetworkTransport) clazz.newInstance();
+ transportClass =
+ Class.forName(System.getProperty("qpid.transport",
+ "org.apache.qpid.transport.network.io.IoNetworkTransport"));
+
}
- catch (InstantiationException e)
+ catch(Exception e)
{
- throw new TransportException("Unable to instantiate transport class " + networkTransportClassName, e);
- }
- catch (IllegalAccessException e)
- {
- throw new TransportException("Access exception " + networkTransportClassName, e);
- }
- catch (ClassNotFoundException e)
- {
- throw new TransportException("Unable to load transport class " + networkTransportClassName, e);
+ throw new Error("Error occured while loading Qpid Transport",e);
}
}
-
- private static String getOverrideClassNameFromSystemProperty(final ProtocolVersion protocolVersion)
+
+ public static NetworkTransport getTransport() throws TransportException
{
- final String protocolSpecificSystemProperty;
-
- if (ProtocolVersion.v0_10.equals(protocolVersion))
- {
- protocolSpecificSystemProperty = QPID_TRANSPORT_V0_10_PROPNAME;
- }
- else if (ProtocolVersion.v0_91.equals(protocolVersion))
- {
- protocolSpecificSystemProperty = QPID_TRANSPORT_V0_9_1_PROPNAME;
- }
- else if (ProtocolVersion.v0_9.equals(protocolVersion))
- {
- protocolSpecificSystemProperty = QPID_TRANSPORT_V0_9_PROPNAME;
- }
- else if (ProtocolVersion.v8_0.equals(protocolVersion))
+ try
{
- protocolSpecificSystemProperty = QPID_TRANSPORT_V0_8_PROPNAME;
+ return (NetworkTransport)transportClass.newInstance();
}
- else
+ catch (Exception e)
{
- throw new IllegalArgumentException("Unknown ProtocolVersion " + protocolVersion);
+ throw new TransportException("Error while creating a new transport instance",e);
}
-
- return System.getProperty(protocolSpecificSystemProperty, System.getProperty(QPID_TRANSPORT_PROPNAME));
}
-}
+} \ No newline at end of file
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java
new file mode 100644
index 0000000000..ecc5f6d07c
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java
@@ -0,0 +1,130 @@
+package org.apache.qpid.transport.network.io;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQMethodBodyFactory;
+import org.apache.qpid.framing.BodyFactory;
+import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.framing.ContentBodyFactory;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.ContentHeaderBodyFactory;
+import org.apache.qpid.framing.HeartbeatBody;
+import org.apache.qpid.framing.HeartbeatBodyFactory;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.Receiver;
+
+public class InputHandler_0_9 implements Receiver<ByteBuffer>
+{
+
+ private AMQVersionAwareProtocolSession _session;
+ private MethodRegistry _registry;
+ private BodyFactory bodyFactory;
+ private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE];
+
+ static
+ {
+ _bodiesSupported[ContentHeaderBody.TYPE] = ContentHeaderBodyFactory.getInstance();
+ _bodiesSupported[ContentBody.TYPE] = ContentBodyFactory.getInstance();
+ _bodiesSupported[HeartbeatBody.TYPE] = new HeartbeatBodyFactory();
+ }
+
+ public InputHandler_0_9(AMQVersionAwareProtocolSession session)
+ {
+ _session = session;
+ _registry = _session.getMethodRegistry();
+ }
+
+ public void closed()
+ {
+ // AS FIXME: implement
+ }
+
+ public void exception(Throwable t)
+ {
+ // TODO: propogate exception to things
+ t.printStackTrace();
+ }
+
+ public void received(ByteBuffer buf)
+ {
+ org.apache.mina.common.ByteBuffer in = org.apache.mina.common.ByteBuffer.wrap(buf);
+ try
+ {
+ final byte type = in.get();
+ if (type == AMQMethodBody.TYPE)
+ {
+ bodyFactory = new AMQMethodBodyFactory(_session);
+ }
+ else
+ {
+ bodyFactory = _bodiesSupported[type];
+ }
+
+ if (bodyFactory == null)
+ {
+ throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null);
+ }
+
+ final int channel = in.getUnsignedShort();
+ final long bodySize = in.getUnsignedInt();
+
+ // bodySize can be zero
+ if ((channel < 0) || (bodySize < 0))
+ {
+ throw new AMQFrameDecodingException(null, "Undecodable frame: type = " + type + " channel = " + channel
+ + " bodySize = " + bodySize, null);
+ }
+
+ AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory);
+
+ byte marker = in.get();
+ if ((marker & 0xFF) != 0xCE)
+ {
+ throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize
+ + " type=" + type, null);
+ }
+
+ try
+ {
+ frame.getBodyFrame().handle(frame.getChannel(), _session);
+ }
+ catch (AMQException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java
new file mode 100644
index 0000000000..8530240dcc
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.network.io;
+
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.TransportException;
+
+import java.io.IOException;
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * IoAcceptor
+ *
+ */
+
+public class IoAcceptor<E> extends Thread
+{
+
+
+ private ServerSocket socket;
+ private Binding<E,ByteBuffer> binding;
+
+ public IoAcceptor(SocketAddress address, Binding<E,ByteBuffer> binding)
+ throws IOException
+ {
+ socket = new ServerSocket();
+ socket.setReuseAddress(true);
+ socket.bind(address);
+ this.binding = binding;
+
+ setName(String.format("IoAcceptor - %s", socket.getInetAddress()));
+ }
+
+ /**
+ Close the underlying ServerSocket if it has not already been closed.
+ */
+ public void close() throws IOException
+ {
+ if (!socket.isClosed())
+ {
+ socket.close();
+ }
+ }
+
+ public IoAcceptor(String host, int port, Binding<E,ByteBuffer> binding)
+ throws IOException
+ {
+ this(new InetSocketAddress(host, port), binding);
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ Socket sock = socket.accept();
+ IoTransport<E> transport = new IoTransport<E>(sock, binding,false);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java
new file mode 100644
index 0000000000..69b3a0ce45
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoContext.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network.io;
+
+import java.net.Socket;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.Sender;
+
+public interface IoContext
+{
+ Sender<ByteBuffer> getSender();
+
+ IoReceiver getReceiver();
+
+ Socket getSocket();
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
deleted file mode 100644
index bfc77539ce..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
+++ /dev/null
@@ -1,99 +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.
- *
- */
-package org.apache.qpid.transport.network.io;
-
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class IoNetworkConnection implements NetworkConnection
-{
- private static final Logger LOGGER = LoggerFactory.getLogger(IoNetworkConnection.class);
- private final Socket _socket;
- private final long _timeout;
- private final IoSender _ioSender;
- private final IoReceiver _ioReceiver;
-
- public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate,
- int sendBufferSize, int receiveBufferSize, long timeout)
- {
- _socket = socket;
- _timeout = timeout;
-
- _ioReceiver = new IoReceiver(_socket, delegate, receiveBufferSize,_timeout);
-
- _ioSender = new IoSender(_socket, 2 * sendBufferSize, _timeout);
-
- _ioSender.registerCloseListener(_ioReceiver);
-
- }
-
- public void start()
- {
- _ioSender.initiate();
- _ioReceiver.initiate();
- }
-
- public Sender<ByteBuffer> getSender()
- {
- return _ioSender;
- }
-
- public void close()
- {
- try
- {
- _ioSender.close();
- }
- finally
- {
- _ioReceiver.close(false);
- }
- }
-
- public SocketAddress getRemoteAddress()
- {
- return _socket.getRemoteSocketAddress();
- }
-
- public SocketAddress getLocalAddress()
- {
- return _socket.getLocalSocketAddress();
- }
-
- public void setMaxWriteIdle(int sec)
- {
- // TODO implement support for setting heartbeating config in this way
- // Currently a socket timeout is used in IoSender
- }
-
- public void setMaxReadIdle(int sec)
- {
- // TODO implement support for setting heartbeating config in this way
- // Currently a socket timeout is used in IoSender
- }
-}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
index e1d1596ec5..dd6a37eca2 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
@@ -21,49 +21,57 @@
package org.apache.qpid.transport.network.io;
import java.io.IOException;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
import java.nio.ByteBuffer;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocketFactory;
-
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.transport.*;
-import org.apache.qpid.transport.network.IncomingNetworkTransport;
-import org.apache.qpid.transport.network.NetworkConnection;
-import org.apache.qpid.transport.network.OutgoingNetworkTransport;
+import org.apache.qpid.transport.ConnectionSettings;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.NetworkTransport;
import org.apache.qpid.transport.util.Logger;
-public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport
+public class IoNetworkTransport implements NetworkTransport, IoContext
{
+ static
+ {
+ org.apache.mina.common.ByteBuffer.setAllocator
+ (new org.apache.mina.common.SimpleByteBufferAllocator());
+ org.apache.mina.common.ByteBuffer.setUseDirectBuffers
+ (Boolean.getBoolean("amqj.enableDirectBuffers"));
+ }
- private static final Logger LOGGER = Logger.get(IoNetworkTransport.class);
-
- private Socket _socket;
- private IoNetworkConnection _connection;
- private long _timeout = 60000;
- private AcceptingThread _acceptor;
+ private static final Logger log = Logger.get(IoNetworkTransport.class);
- public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext)
+ private Socket socket;
+ private Sender<ByteBuffer> sender;
+ private IoReceiver receiver;
+ private long timeout = 60000;
+ private ConnectionSettings settings;
+
+ public void init(ConnectionSettings settings)
{
- int sendBufferSize = settings.getWriteBufferSize();
- int receiveBufferSize = settings.getReadBufferSize();
-
try
{
- _socket = new Socket();
- _socket.setReuseAddress(true);
- _socket.setTcpNoDelay(settings.isTcpNodelay());
- _socket.setSendBufferSize(sendBufferSize);
- _socket.setReceiveBufferSize(receiveBufferSize);
+ this.settings = settings;
+ InetAddress address = InetAddress.getByName(settings.getHost());
+ socket = new Socket();
+ socket.setReuseAddress(true);
+ socket.setTcpNoDelay(settings.isTcpNodelay());
- LOGGER.debug("SO_RCVBUF : %s", _socket.getReceiveBufferSize());
- LOGGER.debug("SO_SNDBUF : %s", _socket.getSendBufferSize());
+ log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize());
- InetAddress address = InetAddress.getByName(settings.getHost());
+ socket.setSendBufferSize(settings.getWriteBufferSize());
+ socket.setReceiveBufferSize(settings.getReadBufferSize());
+
+ log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize());
- _socket.connect(new InetSocketAddress(address, settings.getPort()));
+ socket.connect(new InetSocketAddress(address, settings.getPort()));
}
catch (SocketException e)
{
@@ -73,159 +81,36 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet
{
throw new TransportException("Error connecting to broker", e);
}
+ }
- try
- {
- _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, _timeout);
- _connection.start();
- }
- catch(Exception e)
- {
- try
- {
- _socket.close();
- }
- catch(IOException ioe)
- {
- //ignored, throw based on original exception
- }
-
- throw new TransportException("Error creating network connection", e);
- }
+ public void receiver(Receiver<ByteBuffer> delegate)
+ {
+ receiver = new IoReceiver(this, delegate,
+ 2*settings.getReadBufferSize() , timeout);
+ }
- return _connection;
+ public Sender<ByteBuffer> sender()
+ {
+ return new IoSender(this, 2*settings.getWriteBufferSize(), timeout);
}
public void close()
{
- if(_connection != null)
- {
- _connection.close();
- }
- if(_acceptor != null)
- {
- _acceptor.close();
- }
+
}
- public NetworkConnection getConnection()
+ public Sender<ByteBuffer> getSender()
{
- return _connection;
+ return sender;
}
- public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext)
+ public IoReceiver getReceiver()
{
-
- try
- {
- _acceptor = new AcceptingThread(config, factory, sslContext);
-
- _acceptor.start();
- }
- catch (IOException e)
- {
- throw new TransportException("Unable to start server socket", e);
- }
-
-
+ return receiver;
}
- private class AcceptingThread extends Thread
+ public Socket getSocket()
{
- private NetworkTransportConfiguration _config;
- private ProtocolEngineFactory _factory;
- private SSLContext _sslContent;
- private ServerSocket _serverSocket;
-
- private AcceptingThread(NetworkTransportConfiguration config,
- ProtocolEngineFactory factory,
- SSLContext sslContext)
- throws IOException
- {
- _config = config;
- _factory = factory;
- _sslContent = sslContext;
-
- InetSocketAddress address = new InetSocketAddress(config.getHost(), config.getPort());
-
- if(sslContext == null)
- {
- _serverSocket = new ServerSocket();
- }
- else
- {
- SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();
- _serverSocket = socketFactory.createServerSocket();
- }
-
- _serverSocket.bind(address);
- _serverSocket.setReuseAddress(true);
-
-
- }
-
-
- /**
- Close the underlying ServerSocket if it has not already been closed.
- */
- public void close()
- {
- if (!_serverSocket.isClosed())
- {
- try
- {
- _serverSocket.close();
- }
- catch (IOException e)
- {
- throw new TransportException(e);
- }
- }
- }
-
- @Override
- public void run()
- {
- try
- {
- while (true)
- {
- try
- {
- Socket socket = _serverSocket.accept();
- socket.setTcpNoDelay(_config.getTcpNoDelay());
-
- final Integer sendBufferSize = _config.getSendBufferSize();
- final Integer receiveBufferSize = _config.getReceiveBufferSize();
-
- socket.setSendBufferSize(sendBufferSize);
- socket.setReceiveBufferSize(receiveBufferSize);
-
- ProtocolEngine engine = _factory.newProtocolEngine();
-
- NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout);
-
-
- engine.setNetworkConnection(connection, connection.getSender());
-
- connection.start();
-
-
- }
- catch(RuntimeException e)
- {
- LOGGER.error(e, "Error in Acceptor thread " + _config.getPort());
- }
- }
- }
- catch (IOException e)
- {
- LOGGER.debug(e, "SocketException - no new connections will be accepted on port "
- + _config.getPort());
- }
- }
-
-
+ return socket;
}
-
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
index d4b5975e54..19a683d505 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
@@ -20,7 +20,6 @@
*/
package org.apache.qpid.transport.network.io;
-import org.apache.qpid.common.Closeable;
import org.apache.qpid.thread.Threading;
import org.apache.qpid.transport.Receiver;
import org.apache.qpid.transport.TransportException;
@@ -38,77 +37,56 @@ import java.util.concurrent.atomic.AtomicBoolean;
*
*/
-final class IoReceiver implements Runnable, Closeable
+final class IoReceiver implements Runnable
{
private static final Logger log = Logger.get(IoReceiver.class);
+ private final IoContext ioCtx;
private final Receiver<ByteBuffer> receiver;
private final int bufferSize;
private final Socket socket;
private final long timeout;
private final AtomicBoolean closed = new AtomicBoolean(false);
private final Thread receiverThread;
- private static final boolean shutdownBroken;
- static
- {
- String osName = System.getProperty("os.name");
- shutdownBroken = osName == null ? false : osName.matches("(?i).*windows.*");
- }
+ private final boolean shutdownBroken =
+ ((String) System.getProperties().get("os.name")).matches("(?i).*windows.*");
- public IoReceiver(Socket socket, Receiver<ByteBuffer> receiver, int bufferSize, long timeout)
+ public IoReceiver(IoContext ioCtx, Receiver<ByteBuffer> receiver,
+ int bufferSize, long timeout)
{
+ this.ioCtx = ioCtx;
this.receiver = receiver;
this.bufferSize = bufferSize;
- this.socket = socket;
+ this.socket = ioCtx.getSocket();
this.timeout = timeout;
try
{
- //Create but deliberately don't start the thread.
receiverThread = Threading.getThreadFactory().createThread(this);
}
catch(Exception e)
{
- throw new RuntimeException("Error creating IOReceiver thread",e);
+ throw new Error("Error creating IOReceiver thread",e);
}
receiverThread.setDaemon(true);
receiverThread.setName(String.format("IoReceiver - %s", socket.getRemoteSocketAddress()));
- }
-
- public void initiate()
- {
receiverThread.start();
}
- public void close()
- {
- close(false);
- }
-
void close(boolean block)
{
if (!closed.getAndSet(true))
{
try
{
- try
+ if (shutdownBroken)
{
- if (shutdownBroken)
- {
- socket.close();
- }
- else
- {
- socket.shutdownInput();
- }
+ socket.close();
}
- catch(SocketException se)
+ else
{
- if(!socket.isClosed() && !socket.isInputShutdown())
- {
- throw se;
- }
+ socket.shutdownInput();
}
if (block && Thread.currentThread() != receiverThread)
{
@@ -127,7 +105,6 @@ final class IoReceiver implements Runnable, Closeable
{
throw new TransportException(e);
}
-
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
index 427487c879..66b97e8225 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
@@ -24,14 +24,10 @@ import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.qpid.common.Closeable;
import org.apache.qpid.thread.Threading;
import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.SenderClosedException;
import org.apache.qpid.transport.SenderException;
import org.apache.qpid.transport.TransportException;
import org.apache.qpid.transport.util.Logger;
@@ -47,6 +43,7 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
// we can test other cases as well
private final static int START = Integer.MAX_VALUE - 10;
+ private final IoContext ioCtx;
private final long timeout;
private final Socket socket;
private final OutputStream out;
@@ -59,13 +56,14 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
private final Object notEmpty = new Object();
private final AtomicBoolean closed = new AtomicBoolean(false);
private final Thread senderThread;
- private final List<Closeable> _listeners = new ArrayList<Closeable>();
-
+
private volatile Throwable exception = null;
- public IoSender(Socket socket, int bufferSize, long timeout)
+
+ public IoSender(IoContext ioCtx, int bufferSize, long timeout)
{
- this.socket = socket;
+ this.ioCtx = ioCtx;
+ this.socket = ioCtx.getSocket();
this.buffer = new byte[pof2(bufferSize)]; // buffer size must be a power of 2
this.timeout = timeout;
@@ -80,20 +78,15 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
try
{
- //Create but deliberately don't start the thread.
- senderThread = Threading.getThreadFactory().createThread(this);
+ senderThread = Threading.getThreadFactory().createThread(this);
}
catch(Exception e)
{
throw new Error("Error creating IOSender thread",e);
}
-
+
senderThread.setDaemon(true);
senderThread.setName(String.format("IoSender - %s", socket.getRemoteSocketAddress()));
- }
-
- public void initiate()
- {
senderThread.start();
}
@@ -111,11 +104,7 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
{
if (closed.get())
{
- throw new SenderClosedException("sender is closed", exception);
- }
- if(!senderThread.isAlive())
- {
- throw new SenderException("sender thread not alive");
+ throw new SenderException("sender is closed", exception);
}
final int size = buffer.length;
@@ -148,7 +137,7 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
if (closed.get())
{
- throw new SenderClosedException("sender is closed", exception);
+ throw new SenderException("sender is closed", exception);
}
if (head - tail >= size)
@@ -215,20 +204,16 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
senderThread.join(timeout);
if (senderThread.isAlive())
{
- log.error("join timed out");
throw new SenderException("join timed out");
}
}
+ ioCtx.getReceiver().close(false);
}
catch (InterruptedException e)
{
- log.error("interrupted whilst waiting for sender thread to stop");
throw new SenderException(e);
}
- finally
- {
- closeListeners();
- }
+
if (reportException && exception != null)
{
throw new SenderException(exception);
@@ -236,31 +221,9 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
}
}
- private void closeListeners()
- {
- Exception ex = null;
- for(Closeable listener : _listeners)
- {
- try
- {
- listener.close();
- }
- catch(Exception e)
- {
- log.error("Exception closing listener: " + e.getMessage());
- ex = e;
- }
- }
-
- if (ex != null)
- {
- throw new SenderException(ex.getMessage(), ex);
- }
- }
-
public void run()
{
- final int size = buffer.length;
+ final int size = buffer.length;
while (true)
{
final int hd = head;
@@ -341,9 +304,4 @@ public final class IoSender implements Runnable, Sender<ByteBuffer>
throw new SenderException(e);
}
}
-
- public void registerCloseListener(Closeable listener)
- {
- _listeners.add(listener);
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java
new file mode 100644
index 0000000000..bfdbb34978
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java
@@ -0,0 +1,231 @@
+/*
+ * 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 org.apache.qpid.transport.network.io;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.security.ssl.SSLReceiver;
+import org.apache.qpid.transport.network.security.ssl.SSLSender;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * This class provides a socket based transport using the java.io
+ * classes.
+ *
+ * The following params are configurable via JVM arguments
+ * TCP_NO_DELAY - amqj.tcpNoDelay
+ * SO_RCVBUF - amqj.receiveBufferSize
+ * SO_SNDBUF - amqj.sendBufferSize
+ */
+public final class IoTransport<E> implements IoContext
+{
+
+ static
+ {
+ org.apache.mina.common.ByteBuffer.setAllocator
+ (new org.apache.mina.common.SimpleByteBufferAllocator());
+ org.apache.mina.common.ByteBuffer.setUseDirectBuffers
+ (Boolean.getBoolean("amqj.enableDirectBuffers"));
+ }
+
+ private static final Logger log = Logger.get(IoTransport.class);
+
+ private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024;
+ private static int readBufferSize = Integer.getInteger
+ ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
+ private static int writeBufferSize = Integer.getInteger
+ ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
+
+ private Socket socket;
+ private Sender<ByteBuffer> sender;
+ private E endpoint;
+ private IoReceiver receiver;
+ private long timeout = 60000;
+
+ IoTransport(Socket socket, Binding<E,ByteBuffer> binding, boolean ssl)
+ {
+ this.socket = socket;
+
+ if (ssl)
+ {
+ SSLEngine engine = null;
+ SSLContext sslCtx;
+ try
+ {
+ sslCtx = createSSLContext();
+ }
+ catch (Exception e)
+ {
+ throw new TransportException("Error creating SSL Context", e);
+ }
+
+ try
+ {
+ engine = sslCtx.createSSLEngine();
+ engine.setUseClientMode(true);
+ }
+ catch(Exception e)
+ {
+ throw new TransportException("Error creating SSL Engine", e);
+ }
+
+ this.sender = new SSLSender(engine,new IoSender(this, 2*writeBufferSize, timeout));
+ this.endpoint = binding.endpoint(sender);
+ this.receiver = new IoReceiver(this, new SSLReceiver(engine,binding.receiver(endpoint),(SSLSender)sender),
+ 2*readBufferSize, timeout);
+
+ log.info("SSL Sender and Receiver initiated");
+ }
+ else
+ {
+ this.sender = new IoSender(this, 2*writeBufferSize, timeout);
+ this.endpoint = binding.endpoint(sender);
+ this.receiver = new IoReceiver(this, binding.receiver(endpoint),
+ 2*readBufferSize, timeout);
+ }
+ }
+
+ public Sender<ByteBuffer> getSender()
+ {
+ return sender;
+ }
+
+ public IoReceiver getReceiver()
+ {
+ return receiver;
+ }
+
+ public Socket getSocket()
+ {
+ return socket;
+ }
+
+ public static final <E> E connect(String host, int port,
+ Binding<E,ByteBuffer> binding,
+ boolean ssl)
+ {
+ Socket socket = createSocket(host, port);
+ IoTransport<E> transport = new IoTransport<E>(socket, binding,ssl);
+ return transport.endpoint;
+ }
+
+ public static final Connection connect(String host, int port,
+ ConnectionDelegate delegate,
+ boolean ssl)
+ {
+ return connect(host, port, ConnectionBinding.get(delegate),ssl);
+ }
+
+ public static void connect_0_9(AMQVersionAwareProtocolSession session, String host, int port, boolean ssl)
+ {
+ connect(host, port, new Binding_0_9(session),ssl);
+ }
+
+ private static class Binding_0_9
+ implements Binding<AMQVersionAwareProtocolSession,ByteBuffer>
+ {
+
+ private AMQVersionAwareProtocolSession session;
+
+ Binding_0_9(AMQVersionAwareProtocolSession session)
+ {
+ this.session = session;
+ }
+
+ public AMQVersionAwareProtocolSession endpoint(Sender<ByteBuffer> sender)
+ {
+ session.setSender(sender);
+ return session;
+ }
+
+ public Receiver<ByteBuffer> receiver(AMQVersionAwareProtocolSession ssn)
+ {
+ return new InputHandler_0_9(ssn);
+ }
+
+ }
+
+ private static Socket createSocket(String host, int port)
+ {
+ try
+ {
+ InetAddress address = InetAddress.getByName(host);
+ Socket socket = new Socket();
+ socket.setReuseAddress(true);
+ socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay"));
+
+ log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize());
+
+ socket.setSendBufferSize(writeBufferSize);
+ socket.setReceiveBufferSize(readBufferSize);
+
+ log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize());
+
+ socket.connect(new InetSocketAddress(address, port));
+ return socket;
+ }
+ catch (SocketException e)
+ {
+ throw new TransportException("Error connecting to broker", e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException("Error connecting to broker", e);
+ }
+ }
+
+ private SSLContext createSSLContext() throws Exception
+ {
+ String trustStorePath = System.getProperty("javax.net.ssl.trustStore");
+ String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword");
+ String trustStoreCertType = System.getProperty("qpid.ssl.trustStoreCertType","SunX509");
+
+ String keyStorePath = System.getProperty("javax.net.ssl.keyStore",trustStorePath);
+ String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword",trustStorePassword);
+ String keyStoreCertType = System.getProperty("qpid.ssl.keyStoreCertType","SunX509");
+
+ SSLContextFactory sslContextFactory = new SSLContextFactory(trustStorePath,trustStorePassword,
+ trustStoreCertType,keyStorePath,
+ keyStorePassword,keyStoreCertType);
+
+ return sslContextFactory.buildServerContext();
+
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java
new file mode 100644
index 0000000000..0f2c0d0226
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MINANetworkDriver.java
@@ -0,0 +1,435 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.network.mina;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExecutorThreadModel;
+import org.apache.mina.common.IdleStatus;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+import org.apache.mina.common.WriteFuture;
+import org.apache.mina.filter.ReadThrottleFilterBuilder;
+import org.apache.mina.filter.SSLFilter;
+import org.apache.mina.filter.WriteBufferLimitFilterBuilder;
+import org.apache.mina.filter.executor.ExecutorFilter;
+import org.apache.mina.transport.socket.nio.MultiThreadSocketConnector;
+import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.transport.socket.nio.SocketConnectorConfig;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+import org.apache.mina.util.NewThreadExecutor;
+import org.apache.mina.util.SessionUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.thread.QpidThreadExecutor;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.NetworkDriverConfiguration;
+import org.apache.qpid.transport.OpenException;
+
+import java.io.IOException;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+
+public class MINANetworkDriver extends IoHandlerAdapter implements NetworkDriver
+{
+
+ private static final int DEFAULT_BUFFER_SIZE = 32 * 1024;
+
+ ProtocolEngine _protocolEngine;
+ private boolean _useNIO = false;
+ private int _processors = 4;
+ private boolean _executorPool = false;
+ private SSLContextFactory _sslFactory = null;
+ private IoConnector _socketConnector;
+ private IoAcceptor _acceptor;
+ private IoSession _ioSession;
+ private ProtocolEngineFactory _factory;
+ private boolean _protectIO;
+ private NetworkDriverConfiguration _config;
+ private Throwable _lastException;
+ private boolean _acceptingConnections = false;
+
+ private WriteFuture _lastWriteFuture;
+
+ private static final Logger _logger = LoggerFactory.getLogger(MINANetworkDriver.class);
+
+ static
+ {
+ org.apache.mina.common.ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers"));
+
+ //override the MINA defaults to prevent use of the PooledByteBufferAllocator
+ org.apache.mina.common.ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
+ }
+
+ public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO)
+ {
+ _useNIO = useNIO;
+ _processors = processors;
+ _executorPool = executorPool;
+ _protectIO = protectIO;
+ }
+
+ public MINANetworkDriver(boolean useNIO, int processors, boolean executorPool, boolean protectIO,
+ ProtocolEngine protocolEngine, IoSession session)
+ {
+ _useNIO = useNIO;
+ _processors = processors;
+ _executorPool = executorPool;
+ _protectIO = protectIO;
+ _protocolEngine = protocolEngine;
+ _ioSession = session;
+ _ioSession.setAttachment(_protocolEngine);
+ }
+
+ public MINANetworkDriver()
+ {
+
+ }
+
+ public MINANetworkDriver(IoConnector ioConnector)
+ {
+ _socketConnector = ioConnector;
+ }
+
+ public MINANetworkDriver(IoConnector ioConnector, ProtocolEngine engine)
+ {
+ _socketConnector = ioConnector;
+ _protocolEngine = engine;
+ }
+
+ public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory factory,
+ NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException
+ {
+
+ _factory = factory;
+ _config = config;
+
+ if (_useNIO)
+ {
+ _acceptor = new org.apache.mina.transport.socket.nio.MultiThreadSocketAcceptor(_processors,
+ new NewThreadExecutor());
+ }
+ else
+ {
+ _acceptor = new org.apache.mina.transport.socket.nio.SocketAcceptor(_processors, new NewThreadExecutor());
+ }
+
+ SocketAcceptorConfig sconfig = (SocketAcceptorConfig) _acceptor.getDefaultConfig();
+ sconfig.setThreadModel(ExecutorThreadModel.getInstance("MINANetworkDriver(Acceptor)"));
+ SocketSessionConfig sc = (SocketSessionConfig) sconfig.getSessionConfig();
+
+ if (config != null)
+ {
+ sc.setReceiveBufferSize(config.getReceiveBufferSize());
+ sc.setSendBufferSize(config.getSendBufferSize());
+ sc.setTcpNoDelay(config.getTcpNoDelay());
+ }
+
+ if (sslFactory != null)
+ {
+ _sslFactory = sslFactory;
+ }
+
+ if (addresses != null && addresses.length > 0)
+ {
+ for (InetAddress addr : addresses)
+ {
+ try
+ {
+ _acceptor.bind(new InetSocketAddress(addr, port), this, sconfig);
+ }
+ catch (IOException e)
+ {
+ throw new BindException(String.format("Could not bind to %1s:%2s", addr, port));
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ _acceptor.bind(new InetSocketAddress(port), this, sconfig);
+ }
+ catch (IOException e)
+ {
+ throw new BindException(String.format("Could not bind to *:%1s", port));
+ }
+ }
+ _acceptingConnections = true;
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return _ioSession.getRemoteAddress();
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return _ioSession.getLocalAddress();
+ }
+
+
+ public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config,
+ SSLContextFactory sslFactory) throws OpenException
+ {
+ if (sslFactory != null)
+ {
+ _sslFactory = sslFactory;
+ }
+
+ if (_useNIO)
+ {
+ _socketConnector = new MultiThreadSocketConnector(1, new QpidThreadExecutor());
+ }
+ else
+ {
+ _socketConnector = new SocketConnector(1, new QpidThreadExecutor()); // non-blocking
+ // connector
+ }
+
+ SocketConnectorConfig cfg = (SocketConnectorConfig) _socketConnector.getDefaultConfig();
+ String s = "";
+ StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+ for(StackTraceElement elt : trace)
+ {
+ if(elt.getClassName().contains("Test"))
+ {
+ s = elt.getClassName();
+ break;
+ }
+ }
+ cfg.setThreadModel(ExecutorThreadModel.getInstance("MINANetworkDriver(Client)-"+s));
+
+ SocketSessionConfig scfg = (SocketSessionConfig) cfg.getSessionConfig();
+ scfg.setTcpNoDelay((config != null) ? config.getTcpNoDelay() : true);
+ scfg.setSendBufferSize((config != null) ? config.getSendBufferSize() : DEFAULT_BUFFER_SIZE);
+ scfg.setReceiveBufferSize((config != null) ? config.getReceiveBufferSize() : DEFAULT_BUFFER_SIZE);
+
+ // Don't have the connector's worker thread wait around for other
+ // connections (we only use
+ // one SocketConnector per connection at the moment anyway). This allows
+ // short-running
+ // clients (like unit tests) to complete quickly.
+ if (_socketConnector instanceof SocketConnector)
+ {
+ ((SocketConnector) _socketConnector).setWorkerTimeout(0);
+ }
+
+ ConnectFuture future = _socketConnector.connect(new InetSocketAddress(destination, port), this, cfg);
+ future.join();
+ if (!future.isConnected())
+ {
+ throw new OpenException("Could not open connection", _lastException);
+ }
+ _ioSession = future.getSession();
+ _ioSession.setAttachment(engine);
+ engine.setNetworkDriver(this);
+ _protocolEngine = engine;
+ }
+
+ public void setMaxReadIdle(int idleTime)
+ {
+ _ioSession.setIdleTime(IdleStatus.READER_IDLE, idleTime);
+ }
+
+ public void setMaxWriteIdle(int idleTime)
+ {
+ _ioSession.setIdleTime(IdleStatus.WRITER_IDLE, idleTime);
+ }
+
+ public void close()
+ {
+ if (_lastWriteFuture != null)
+ {
+ _lastWriteFuture.join();
+ }
+ if (_acceptor != null)
+ {
+ _acceptor.unbindAll();
+ }
+ if (_ioSession != null)
+ {
+ _ioSession.close();
+ }
+ }
+
+ public void flush()
+ {
+ if (_lastWriteFuture != null)
+ {
+ _lastWriteFuture.join();
+ }
+ }
+
+ public void send(ByteBuffer msg)
+ {
+ org.apache.mina.common.ByteBuffer minaBuf = org.apache.mina.common.ByteBuffer.allocate(msg.capacity());
+ minaBuf.put(msg);
+ minaBuf.flip();
+ _lastWriteFuture = _ioSession.write(minaBuf);
+ }
+
+ public void setIdleTimeout(int i)
+ {
+ // MINA doesn't support setting SO_TIMEOUT
+ }
+
+ public void exceptionCaught(IoSession protocolSession, Throwable throwable) throws Exception
+ {
+ if (_protocolEngine != null)
+ {
+ _protocolEngine.exception(throwable);
+ }
+ else
+ {
+ _logger.error("Exception thrown and no ProtocolEngine to handle it", throwable);
+ }
+ _lastException = throwable;
+ }
+
+ /**
+ * Invoked when a message is received on a particular protocol session. Note
+ * that a protocol session is directly tied to a particular physical
+ * connection.
+ *
+ * @param protocolSession
+ * the protocol session that received the message
+ * @param message
+ * the message itself (i.e. a decoded frame)
+ *
+ * @throws Exception
+ * if the message cannot be processed
+ */
+ public void messageReceived(IoSession protocolSession, Object message) throws Exception
+ {
+ if (message instanceof org.apache.mina.common.ByteBuffer)
+ {
+ ((ProtocolEngine) protocolSession.getAttachment()).received(((org.apache.mina.common.ByteBuffer) message).buf());
+ }
+ else
+ {
+ throw new IllegalStateException("Handed unhandled message. message.class = " + message.getClass() + " message = " + message);
+ }
+ }
+
+ public void sessionClosed(IoSession protocolSession) throws Exception
+ {
+ ((ProtocolEngine) protocolSession.getAttachment()).closed();
+ }
+
+ public void sessionCreated(IoSession protocolSession) throws Exception
+ {
+ // Configure the session with SSL if necessary
+ SessionUtil.initialize(protocolSession);
+ if (_executorPool)
+ {
+ if (_sslFactory != null)
+ {
+ protocolSession.getFilterChain().addAfter("AsynchronousReadFilter", "sslFilter",
+ new SSLFilter(_sslFactory.buildServerContext()));
+ }
+ }
+ else
+ {
+ if (_sslFactory != null)
+ {
+ protocolSession.getFilterChain().addBefore("protocolFilter", "sslFilter",
+ new SSLFilter(_sslFactory.buildServerContext()));
+ }
+ }
+ // Do we want to have read/write buffer limits?
+ if (_protectIO)
+ {
+ //Add IO Protection Filters
+ IoFilterChain chain = protocolSession.getFilterChain();
+
+ protocolSession.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter());
+
+ ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder();
+ readfilter.setMaximumConnectionBufferSize(_config.getReceiveBufferSize());
+ readfilter.attach(chain);
+
+ WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder();
+ writefilter.setMaximumConnectionBufferSize(_config.getSendBufferSize());
+ writefilter.attach(chain);
+
+ protocolSession.getFilterChain().remove("tempExecutorFilterForFilterBuilder");
+ }
+
+ if (_ioSession == null)
+ {
+ _ioSession = protocolSession;
+ }
+
+ if (_acceptingConnections)
+ {
+ // Set up the protocol engine
+ ProtocolEngine protocolEngine = _factory.newProtocolEngine(this);
+ MINANetworkDriver newDriver = new MINANetworkDriver(_useNIO, _processors, _executorPool, _protectIO, protocolEngine, protocolSession);
+ protocolEngine.setNetworkDriver(newDriver);
+ }
+ }
+
+ public void sessionIdle(IoSession session, IdleStatus status) throws Exception
+ {
+ if (IdleStatus.WRITER_IDLE.equals(status))
+ {
+ ((ProtocolEngine) session.getAttachment()).writerIdle();
+ }
+ else if (IdleStatus.READER_IDLE.equals(status))
+ {
+ ((ProtocolEngine) session.getAttachment()).readerIdle();
+ }
+ }
+
+ private ProtocolEngine getProtocolEngine()
+ {
+ return _protocolEngine;
+ }
+
+ public void setProtocolEngineFactory(ProtocolEngineFactory engineFactory, boolean acceptingConnections)
+ {
+ _factory = engineFactory;
+ _acceptingConnections = acceptingConnections;
+ }
+
+ public void setProtocolEngine(ProtocolEngine protocolEngine)
+ {
+ _protocolEngine = protocolEngine;
+ if (_ioSession != null)
+ {
+ _ioSession.setAttachment(protocolEngine);
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java
new file mode 100644
index 0000000000..b89eed48b0
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java
@@ -0,0 +1,274 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.network.mina;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.apache.mina.common.*;
+
+import org.apache.mina.transport.socket.nio.SocketAcceptor;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+import org.apache.mina.transport.socket.nio.SocketConnector;
+import org.apache.mina.filter.ReadThrottleFilterBuilder;
+import org.apache.mina.filter.WriteBufferLimitFilterBuilder;
+import org.apache.mina.filter.executor.ExecutorFilter;
+
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.ConnectionBinding;
+
+import org.apache.qpid.transport.util.Logger;
+
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
+
+import static org.apache.qpid.transport.util.Functions.*;
+
+/**
+ * MinaHandler
+ *
+ * @author Rafael H. Schloming
+ */
+//RA making this public until we sort out the package issues
+public class MinaHandler<E> implements IoHandler
+{
+ /** Default buffer size for pending messages reads */
+ private static final String DEFAULT_READ_BUFFER_LIMIT = "262144";
+ /** Default buffer size for pending messages writes */
+ private static final String DEFAULT_WRITE_BUFFER_LIMIT = "262144";
+ private static final int MAX_RCVBUF = 64*1024;
+
+ private static final Logger log = Logger.get(MinaHandler.class);
+
+ static
+ {
+ ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
+ ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers"));
+ }
+
+ private final Binding<E,java.nio.ByteBuffer> binding;
+
+ private MinaHandler(Binding<E,java.nio.ByteBuffer> binding)
+ {
+ this.binding = binding;
+ }
+
+ public void messageReceived(IoSession ssn, Object obj)
+ {
+ Attachment<E> attachment = (Attachment<E>) ssn.getAttachment();
+ ByteBuffer buf = (ByteBuffer) obj;
+ try
+ {
+ attachment.receiver.received(buf.buf());
+ }
+ catch (Throwable t)
+ {
+ log.error(t, "exception handling buffer %s", str(buf.buf()));
+ throw new RuntimeException(t);
+ }
+ }
+
+ public void messageSent(IoSession ssn, Object obj)
+ {
+ // do nothing
+ }
+
+ public void exceptionCaught(IoSession ssn, Throwable e)
+ {
+ Attachment<E> attachment = (Attachment<E>) ssn.getAttachment();
+ attachment.receiver.exception(e);
+ }
+
+ /**
+ * Invoked by MINA when a MINA session for a new connection is created. This method sets up the filter chain on the
+ * session, which filters the events handled by this handler. The filter chain consists of, handing off events
+ * to an optional protectio
+ *
+ * @param session The MINA session.
+ * @throws Exception Any underlying exceptions are allowed to fall through to MINA.
+ */
+ public void sessionCreated(IoSession session) throws Exception
+ {
+ log.debug("Protocol session created for session " + System.identityHashCode(session));
+
+ if (Boolean.getBoolean("protectio"))
+ {
+ try
+ {
+ //Add IO Protection Filters
+ IoFilterChain chain = session.getFilterChain();
+
+ session.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter());
+
+ ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder();
+ readfilter.setMaximumConnectionBufferSize(
+ Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER_LIMIT)));
+ readfilter.attach(chain);
+
+ WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder();
+ writefilter.setMaximumConnectionBufferSize(
+ Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER_LIMIT)));
+ writefilter.attach(chain);
+ session.getFilterChain().remove("tempExecutorFilterForFilterBuilder");
+
+ log.info("Using IO Read/Write Filter Protection");
+ }
+ catch (Exception e)
+ {
+ log.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage());
+ }
+ }
+ }
+
+ public void sessionOpened(final IoSession ssn)
+ {
+ log.debug("opened: %s", this);
+ E endpoint = binding.endpoint(new MinaSender(ssn));
+ Attachment<E> attachment =
+ new Attachment<E>(endpoint, binding.receiver(endpoint));
+
+ // We need to synchronize and notify here because the MINA
+ // connect future returns the session prior to the attachment
+ // being set. This is arguably a bug in MINA.
+ synchronized (ssn)
+ {
+ ssn.setAttachment(attachment);
+ ssn.notifyAll();
+ }
+ }
+
+ public void sessionClosed(IoSession ssn)
+ {
+ log.debug("closed: %s", ssn);
+ Attachment<E> attachment = (Attachment<E>) ssn.getAttachment();
+ attachment.receiver.closed();
+ ssn.setAttachment(null);
+ }
+
+ public void sessionIdle(IoSession ssn, IdleStatus status)
+ {
+ // do nothing
+ }
+
+ private static class Attachment<E>
+ {
+
+ E endpoint;
+ Receiver<java.nio.ByteBuffer> receiver;
+
+ Attachment(E endpoint, Receiver<java.nio.ByteBuffer> receiver)
+ {
+ this.endpoint = endpoint;
+ this.receiver = receiver;
+ }
+ }
+
+ public static final void accept(String host, int port,
+ Binding<?,java.nio.ByteBuffer> binding)
+ throws IOException
+ {
+ accept(new InetSocketAddress(host, port), binding);
+ }
+
+ public static final <E> void accept(SocketAddress address,
+ Binding<E,java.nio.ByteBuffer> binding)
+ throws IOException
+ {
+ IoAcceptor acceptor = new SocketAcceptor();
+ acceptor.bind(address, new MinaHandler<E>(binding));
+ }
+
+ public static final <E> E connect(String host, int port,
+ Binding<E,java.nio.ByteBuffer> binding)
+ {
+ return connect(new InetSocketAddress(host, port), binding);
+ }
+
+ public static final <E> E connect(SocketAddress address,
+ Binding<E,java.nio.ByteBuffer> binding)
+ {
+ MinaHandler<E> handler = new MinaHandler<E>(binding);
+ SocketConnector connector = new SocketConnector();
+ IoServiceConfig acceptorConfig = connector.getDefaultConfig();
+ acceptorConfig.setThreadModel(ThreadModel.MANUAL);
+ SocketSessionConfig scfg = (SocketSessionConfig) acceptorConfig.getSessionConfig();
+ scfg.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay"));
+ Integer sendBufferSize = Integer.getInteger("amqj.sendBufferSize");
+ if (sendBufferSize != null && sendBufferSize > 0)
+ {
+ scfg.setSendBufferSize(sendBufferSize);
+ }
+ Integer receiveBufferSize = Integer.getInteger("amqj.receiveBufferSize");
+ if (receiveBufferSize != null && receiveBufferSize > 0)
+ {
+ scfg.setReceiveBufferSize(receiveBufferSize);
+ }
+ else if (scfg.getReceiveBufferSize() > MAX_RCVBUF)
+ {
+ scfg.setReceiveBufferSize(MAX_RCVBUF);
+ }
+ connector.setWorkerTimeout(0);
+ ConnectFuture cf = connector.connect(address, handler);
+ cf.join();
+ IoSession ssn = cf.getSession();
+
+ // We need to synchronize and wait here because the MINA
+ // connect future returns the session prior to the attachment
+ // being set. This is arguably a bug in MINA.
+ synchronized (ssn)
+ {
+ while (ssn.getAttachment() == null)
+ {
+ try
+ {
+ ssn.wait();
+ }
+ catch (InterruptedException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ Attachment<E> attachment = (Attachment<E>) ssn.getAttachment();
+ return attachment.endpoint;
+ }
+
+ public static final void accept(String host, int port,
+ ConnectionDelegate delegate)
+ throws IOException
+ {
+ accept(host, port, ConnectionBinding.get(delegate));
+ }
+
+ public static final Connection connect(String host, int port,
+ ConnectionDelegate delegate)
+ {
+ return connect(host, port, ConnectionBinding.get(delegate));
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java
new file mode 100644
index 0000000000..22b9c5e784
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.network.mina;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.CloseFuture;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.WriteFuture;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+
+
+/**
+ * MinaSender
+ */
+
+public class MinaSender implements Sender<java.nio.ByteBuffer>
+{
+ private static final int TIMEOUT = 2 * 60 * 1000;
+
+ private final IoSession session;
+ private WriteFuture lastWrite = null;
+
+ public MinaSender(IoSession session)
+ {
+ this.session = session;
+ }
+
+ public void send(java.nio.ByteBuffer buf)
+ {
+ if (session.isClosing())
+ {
+ throw new TransportException("attempted to write to a closed socket");
+ }
+
+ synchronized (this)
+ {
+ lastWrite = session.write(ByteBuffer.wrap(buf));
+ }
+ }
+
+ public void flush()
+ {
+ // pass
+ }
+
+ public synchronized void close()
+ {
+ // MINA will sometimes throw away in-progress writes when you
+ // ask it to close
+ synchronized (this)
+ {
+ if (lastWrite != null)
+ {
+ lastWrite.join();
+ }
+ }
+ CloseFuture closed = session.close();
+ closed.join();
+ }
+
+ public void setIdleTimeout(int i)
+ {
+ //noop
+ }
+
+ public long getIdleTimeout()
+ {
+ return 0;
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java
new file mode 100644
index 0000000000..84e66c25bd
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java
@@ -0,0 +1,135 @@
+package org.apache.qpid.transport.network.nio;
+/*
+ *
+ * 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.
+ *
+ */
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
+
+public class NioHandler implements Runnable
+{
+ private Receiver<ByteBuffer> _receiver;
+ private SocketChannel _ch;
+ private ByteBuffer _readBuf;
+ private static Map<Long,NioSender> _handlers = new ConcurrentHashMap<Long,NioSender>();
+
+ private NioHandler(){}
+
+ public static final Connection connect(String host, int port,
+ ConnectionDelegate delegate)
+ {
+ NioHandler handler = new NioHandler();
+ return handler.connectInternal(host,port,delegate);
+ }
+
+ private Connection connectInternal(String host, int port,
+ ConnectionDelegate delegate)
+ {
+ try
+ {
+ SocketAddress address = new InetSocketAddress(host,port);
+ _ch = SocketChannel.open();
+ _ch.socket().setReuseAddress(true);
+ _ch.configureBlocking(true);
+ _ch.socket().setTcpNoDelay(true);
+ if (address != null)
+ {
+ _ch.socket().connect(address);
+ }
+ while (_ch.isConnectionPending())
+ {
+
+ }
+
+ }
+ catch (SocketException e)
+ {
+
+ e.printStackTrace();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ NioSender sender = new NioSender(_ch);
+ Connection con = new Connection();
+ con.setSender(new Disassembler(sender, 64*1024 - 1));
+ con.setConnectionDelegate(delegate);
+
+ _handlers.put(con.getConnectionId(),sender);
+
+ _receiver = new InputHandler(new Assembler(con), InputHandler.State.FRAME_HDR);
+
+ Thread t = new Thread(this);
+ t.start();
+
+ return con;
+ }
+
+ public void run()
+ {
+ _readBuf = ByteBuffer.allocate(512);
+ long read = 0;
+ while(_ch.isConnected() && _ch.isOpen())
+ {
+ try
+ {
+ read = _ch.read(_readBuf);
+ if (read > 0)
+ {
+ _readBuf.flip();
+ ByteBuffer b = ByteBuffer.allocate(_readBuf.remaining());
+ b.put(_readBuf);
+ b.flip();
+ _readBuf.clear();
+ _receiver.received(b);
+ }
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ //throw new EOFException("The underlying socket/channel has closed");
+ }
+
+ public static void startBatchingFrames(int connectionId)
+ {
+ NioSender sender = _handlers.get(connectionId);
+ sender.setStartBatching();
+ }
+
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java
new file mode 100644
index 0000000000..2fa875f279
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java
@@ -0,0 +1,126 @@
+package org.apache.qpid.transport.network.nio;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+
+import org.apache.qpid.transport.Sender;
+
+public class NioSender implements Sender<java.nio.ByteBuffer>
+{
+ private final Object lock = new Object();
+ private SocketChannel _ch;
+ private boolean _batch = false;
+ private ByteBuffer _batcher;
+
+ public NioSender(SocketChannel ch)
+ {
+ this._ch = ch;
+ }
+
+ public void send(java.nio.ByteBuffer buf)
+ {
+ if (_batch)
+ {
+ //System.out.println(_batcher.position() + " , " + buf.remaining() + " , " + buf.position() + ","+_batcher.capacity());
+ if (_batcher.position() + buf.remaining() >= _batcher.capacity())
+ {
+ _batcher.flip();
+ write(_batcher);
+ _batcher.clear();
+ if (buf.remaining() > _batcher.capacity())
+ {
+ write(buf);
+ }
+ else
+ {
+ _batcher.put(buf);
+ }
+ }
+ else
+ {
+ _batcher.put(buf);
+ }
+ }
+ else
+ {
+ write(buf);
+ }
+ }
+
+ public void flush()
+ {
+ // pass
+ }
+
+ private void write(java.nio.ByteBuffer buf)
+ {
+ synchronized (lock)
+ {
+ if( _ch.isConnected() && _ch.isOpen())
+ {
+ try
+ {
+ _ch.write(buf);
+ }
+ catch(Exception e)
+ {
+ e.fillInStackTrace();
+ }
+ }
+ else
+ {
+ throw new RuntimeException("Trying to write on a closed socket");
+ }
+
+ }
+ }
+
+ public void setStartBatching()
+ {
+ _batch = true;
+ _batcher = ByteBuffer.allocate(1024);
+ }
+
+ public void close()
+ {
+ // MINA will sometimes throw away in-progress writes when you
+ // ask it to close
+ synchronized (lock)
+ {
+ try
+ {
+ _ch.close();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void setIdleTimeout(int i)
+ {
+ //noop
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java
deleted file mode 100644
index 9db7dd557a..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/SSLStatus.java
+++ /dev/null
@@ -1,49 +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.
- *
- */
-
-package org.apache.qpid.transport.network.security;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class SSLStatus
-{
- private final Object _sslLock = new Object();
- private final AtomicBoolean _sslErrorFlag = new AtomicBoolean(false);
-
- /**
- * Lock used to coordinate the SSL sender with the SSL receiver.
- *
- * @return lock
- */
- public Object getSslLock()
- {
- return _sslLock;
- }
-
- public boolean getSslErrorFlag()
- {
- return _sslErrorFlag.get();
- }
-
- public void setSslErrorFlag()
- {
- _sslErrorFlag.set(true);
- }
-}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
index 9fd65c6e51..3f0966903d 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
@@ -25,8 +25,8 @@ import java.nio.ByteBuffer;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import org.apache.qpid.ssl.SSLContextFactory;
import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionListener;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.transport.Receiver;
import org.apache.qpid.transport.Sender;
@@ -37,12 +37,149 @@ import org.apache.qpid.transport.network.security.ssl.SSLReceiver;
import org.apache.qpid.transport.network.security.ssl.SSLSender;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;
-public interface SecurityLayer
+public class SecurityLayer
{
-
- public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate);
- public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate);
- public String getUserID();
-
+ ConnectionSettings settings;
+ Connection con;
+ SSLSecurityLayer sslLayer;
+ SASLSecurityLayer saslLayer;
+
+ public void init(Connection con) throws TransportException
+ {
+ this.con = con;
+ this.settings = con.getConnectionSettings();
+ if (settings.isUseSSL())
+ {
+ sslLayer = new SSLSecurityLayer();
+ }
+ if (settings.isUseSASLEncryption())
+ {
+ saslLayer = new SASLSecurityLayer();
+ }
+
+ }
+
+ public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate)
+ {
+ Sender<ByteBuffer> sender = delegate;
+
+ if (settings.isUseSSL())
+ {
+ sender = sslLayer.sender(sender);
+ }
+
+ if (settings.isUseSASLEncryption())
+ {
+ sender = saslLayer.sender(sender);
+ }
+
+ return sender;
+ }
+
+ public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate)
+ {
+ Receiver<ByteBuffer> receiver = delegate;
+
+ if (settings.isUseSSL())
+ {
+ receiver = sslLayer.receiver(receiver);
+ }
+
+ if (settings.isUseSASLEncryption())
+ {
+ receiver = saslLayer.receiver(receiver);
+ }
+
+ return receiver;
+ }
+
+ public String getUserID()
+ {
+ if (settings.isUseSSL())
+ {
+ return sslLayer.getUserID();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ class SSLSecurityLayer
+ {
+ SSLEngine engine;
+ SSLSender sender;
+
+ public SSLSecurityLayer()
+ {
+ SSLContext sslCtx;
+ try
+ {
+ sslCtx = SSLUtil.createSSLContext(settings);
+ }
+ catch (Exception e)
+ {
+ throw new TransportException("Error creating SSL Context", e);
+ }
+
+ try
+ {
+ engine = sslCtx.createSSLEngine();
+ engine.setUseClientMode(true);
+ }
+ catch(Exception e)
+ {
+ throw new TransportException("Error creating SSL Engine", e);
+ }
+ }
+
+ public SSLSender sender(Sender<ByteBuffer> delegate)
+ {
+ sender = new SSLSender(engine,delegate);
+ sender.setConnectionSettings(settings);
+ return sender;
+ }
+
+ public SSLReceiver receiver(Receiver<ByteBuffer> delegate)
+ {
+ if (sender == null)
+ {
+ throw new
+ IllegalStateException("SecurityLayer.sender method should be " +
+ "invoked before SecurityLayer.receiver");
+ }
+
+ SSLReceiver receiver = new SSLReceiver(engine,delegate,sender);
+ receiver.setConnectionSettings(settings);
+ return receiver;
+ }
+
+ public String getUserID()
+ {
+ return SSLUtil.retriveIdentity(engine);
+ }
+
+ }
+
+ class SASLSecurityLayer
+ {
+ public SASLSecurityLayer()
+ {
+ }
+
+ public SASLSender sender(Sender<ByteBuffer> delegate)
+ {
+ SASLSender sender = new SASLSender(delegate);
+ con.addConnectionListener((ConnectionListener)sender);
+ return sender;
+ }
+
+ public SASLReceiver receiver(Receiver<ByteBuffer> delegate)
+ {
+ SASLReceiver receiver = new SASLReceiver(delegate);
+ con.addConnectionListener((ConnectionListener)receiver);
+ return receiver;
+ }
+
+ }
}
-
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java
deleted file mode 100644
index 17f89c34ef..0000000000
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package org.apache.qpid.transport.network.security;
-
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.*;
-import org.apache.qpid.transport.network.security.sasl.SASLReceiver;
-import org.apache.qpid.transport.network.security.sasl.SASLSender;
-import org.apache.qpid.transport.network.security.ssl.SSLReceiver;
-import org.apache.qpid.transport.network.security.ssl.SSLSender;
-import org.apache.qpid.transport.network.security.ssl.SSLUtil;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import java.nio.ByteBuffer;
-
-public class SecurityLayerFactory
-{
- public static SecurityLayer newInstance(ConnectionSettings settings)
- {
-
- SecurityLayer layer = NullSecurityLayer.getInstance();
-
- if (settings.isUseSSL())
- {
- layer = new SSLSecurityLayer(settings, layer);
- }
- if (settings.isUseSASLEncryption())
- {
- layer = new SASLSecurityLayer(layer);
- }
-
- return layer;
-
- }
-
- static class SSLSecurityLayer implements SecurityLayer
- {
-
- private final SSLEngine _engine;
- private final SSLStatus _sslStatus = new SSLStatus();
- private String _hostname;
- private SecurityLayer _layer;
-
-
- public SSLSecurityLayer(ConnectionSettings settings, SecurityLayer layer)
- {
-
- SSLContext sslCtx;
- _layer = layer;
- try
- {
- sslCtx = SSLContextFactory
- .buildClientContext(settings.getTrustStorePath(),
- settings.getTrustStorePassword(),
- settings.getTrustStoreCertType(),
- settings.getKeyStorePath(),
- settings.getKeyStorePassword(),
- settings.getKeyStoreCertType(),
- settings.getCertAlias());
- }
- catch (Exception e)
- {
- throw new TransportException("Error creating SSL Context", e);
- }
-
- if(settings.isVerifyHostname())
- {
- _hostname = settings.getHost();
- }
-
- try
- {
- _engine = sslCtx.createSSLEngine();
- _engine.setUseClientMode(true);
- }
- catch(Exception e)
- {
- throw new TransportException("Error creating SSL Engine", e);
- }
-
- }
-
- public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate)
- {
- SSLSender sender = new SSLSender(_engine, _layer.sender(delegate), _sslStatus);
- sender.setHostname(_hostname);
- return sender;
- }
-
- public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate)
- {
- SSLReceiver receiver = new SSLReceiver(_engine, _layer.receiver(delegate), _sslStatus);
- receiver.setHostname(_hostname);
- return receiver;
- }
-
- public String getUserID()
- {
- return SSLUtil.retriveIdentity(_engine);
- }
- }
-
-
- static class SASLSecurityLayer implements SecurityLayer
- {
-
- private SecurityLayer _layer;
-
- SASLSecurityLayer(SecurityLayer layer)
- {
- _layer = layer;
- }
-
- public SASLSender sender(Sender<ByteBuffer> delegate)
- {
- SASLSender sender = new SASLSender(_layer.sender(delegate));
- return sender;
- }
-
- public SASLReceiver receiver(Receiver<ByteBuffer> delegate)
- {
- SASLReceiver receiver = new SASLReceiver(_layer.receiver(delegate));
- return receiver;
- }
-
- public String getUserID()
- {
- return _layer.getUserID();
- }
- }
-
-
- static class NullSecurityLayer implements SecurityLayer
- {
-
- private static final NullSecurityLayer INSTANCE = new NullSecurityLayer();
-
- private NullSecurityLayer()
- {
- }
-
- public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate)
- {
- return delegate;
- }
-
- public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate)
- {
- return delegate;
- }
-
- public String getUserID()
- {
- return null;
- }
-
- public static NullSecurityLayer getInstance()
- {
- return INSTANCE;
- }
- }
-}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
index 2d9e4e9a7e..27255f79f6 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
@@ -43,7 +43,8 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> {
this.delegate = delegate;
log.debug("SASL Sender enabled");
}
-
+
+ @Override
public void close()
{
@@ -64,11 +65,13 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> {
}
}
+ @Override
public void flush()
{
delegate.flush();
}
+ @Override
public void send(ByteBuffer buf)
{
if (closed.get())
@@ -105,6 +108,7 @@ public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> {
}
}
+ @Override
public void setIdleTimeout(int i)
{
delegate.setIdleTimeout(i);
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
index 4391e8adfc..14f28f8828 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/QpidClientX509KeyManager.java
@@ -20,9 +20,7 @@
*/
package org.apache.qpid.transport.network.security.ssl;
-import java.io.IOException;
import java.net.Socket;
-import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
@@ -42,7 +40,7 @@ public class QpidClientX509KeyManager extends X509ExtendedKeyManager
String alias;
public QpidClientX509KeyManager(String alias, String keyStorePath,
- String keyStorePassword,String keyStoreCertType) throws GeneralSecurityException, IOException
+ String keyStorePassword,String keyStoreCertType) throws Exception
{
this.alias = alias;
KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath,keyStorePassword);
@@ -50,45 +48,51 @@ public class QpidClientX509KeyManager extends X509ExtendedKeyManager
kmf.init(ks, keyStorePassword.toCharArray());
this.delegate = (X509ExtendedKeyManager)kmf.getKeyManagers()[0];
}
-
+
+ @Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)
{
log.debug("chooseClientAlias:Returning alias " + alias);
return alias;
}
+ @Override
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket)
{
return delegate.chooseServerAlias(keyType, issuers, socket);
}
+ @Override
public X509Certificate[] getCertificateChain(String alias)
{
return delegate.getCertificateChain(alias);
}
+ @Override
public String[] getClientAliases(String keyType, Principal[] issuers)
{
log.debug("getClientAliases:Returning alias " + alias);
return new String[]{alias};
}
+ @Override
public PrivateKey getPrivateKey(String alias)
{
return delegate.getPrivateKey(alias);
}
+ @Override
public String[] getServerAliases(String keyType, Principal[] issuers)
{
return delegate.getServerAliases(keyType, issuers);
}
-
+
public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine)
{
log.debug("chooseEngineClientAlias:Returning alias " + alias);
return alias;
}
-
+
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine)
{
return delegate.chooseEngineServerAlias(keyType, issuers, engine);
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
index 8ad40bbfd3..e227a51729 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
@@ -24,43 +24,43 @@ import java.nio.ByteBuffer;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLException;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.transport.Receiver;
import org.apache.qpid.transport.TransportException;
-import org.apache.qpid.transport.network.security.SSLStatus;
import org.apache.qpid.transport.util.Logger;
public class SSLReceiver implements Receiver<ByteBuffer>
{
- private static final Logger log = Logger.get(SSLReceiver.class);
-
- private final Receiver<ByteBuffer> delegate;
- private final SSLEngine engine;
- private final int sslBufSize;
- private final ByteBuffer localBuffer;
- private final SSLStatus _sslStatus;
+ private Receiver<ByteBuffer> delegate;
+ private SSLEngine engine;
+ private SSLSender sender;
+ private int sslBufSize;
private ByteBuffer appData;
+ private ByteBuffer localBuffer;
private boolean dataCached = false;
+ private final Object notificationToken;
+ private ConnectionSettings settings;
+
+ private static final Logger log = Logger.get(SSLReceiver.class);
- private String _hostname;
-
- public SSLReceiver(final SSLEngine engine, final Receiver<ByteBuffer> delegate, final SSLStatus sslStatus)
+ public SSLReceiver(SSLEngine engine, Receiver<ByteBuffer> delegate,SSLSender sender)
{
this.engine = engine;
this.delegate = delegate;
+ this.sender = sender;
this.sslBufSize = engine.getSession().getApplicationBufferSize();
appData = ByteBuffer.allocate(sslBufSize);
localBuffer = ByteBuffer.allocate(sslBufSize);
- _sslStatus = sslStatus;
+ notificationToken = sender.getNotificationToken();
}
- public void setHostname(String hostname)
+ public void setConnectionSettings(ConnectionSettings settings)
{
- _hostname = hostname;
+ this.settings = settings;
}
public void closed()
@@ -102,9 +102,9 @@ public class SSLReceiver implements Receiver<ByteBuffer>
try
{
SSLEngineResult result = engine.unwrap(netData, appData);
- synchronized (_sslStatus.getSslLock())
+ synchronized (notificationToken)
{
- _sslStatus.getSslLock().notifyAll();
+ notificationToken.notifyAll();
}
int read = result.bytesProduced();
@@ -129,9 +129,9 @@ public class SSLReceiver implements Receiver<ByteBuffer>
switch(status)
{
case CLOSED:
- synchronized(_sslStatus.getSslLock())
+ synchronized(notificationToken)
{
- _sslStatus.getSslLock().notifyAll();
+ notificationToken.notifyAll();
}
return;
@@ -163,20 +163,20 @@ public class SSLReceiver implements Receiver<ByteBuffer>
break;
case NEED_TASK:
- doTasks();
+ sender.doTasks();
handshakeStatus = engine.getHandshakeStatus();
case FINISHED:
- if (_hostname != null)
+ if (this.settings != null && this.settings.isVerifyHostname() )
{
- SSLUtil.verifyHostname(engine, _hostname);
+ SSLUtil.verifyHostname(engine, this.settings.getHost());
}
case NEED_WRAP:
case NOT_HANDSHAKING:
- synchronized(_sslStatus.getSslLock())
+ synchronized(notificationToken)
{
- _sslStatus.getSslLock().notifyAll();
+ notificationToken.notifyAll();
}
break;
@@ -189,23 +189,14 @@ public class SSLReceiver implements Receiver<ByteBuffer>
catch(SSLException e)
{
log.error(e, "Error caught in SSLReceiver");
- _sslStatus.setSslErrorFlag();
- synchronized(_sslStatus.getSslLock())
+ sender.setErrorFlag();
+ synchronized(notificationToken)
{
- _sslStatus.getSslLock().notifyAll();
+ notificationToken.notifyAll();
}
exception(new TransportException("Error in SSLReceiver",e));
}
}
}
-
- private void doTasks()
- {
- Runnable runnable;
- while ((runnable = engine.getDelegatedTask()) != null) {
- runnable.run();
- }
- }
-
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
index 6f5aa6d86e..cd47a11825 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
@@ -31,38 +31,35 @@ import javax.net.ssl.SSLEngineResult.Status;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.SenderException;
-import org.apache.qpid.transport.network.security.SSLStatus;
import org.apache.qpid.transport.util.Logger;
public class SSLSender implements Sender<ByteBuffer>
{
- private static final Logger log = Logger.get(SSLSender.class);
-
- private final Sender<ByteBuffer> delegate;
- private final SSLEngine engine;
- private final int sslBufSize;
- private final ByteBuffer netData;
- private final long timeout;
- private final SSLStatus _sslStatus;
-
- private String _hostname;
-
+ private Sender<ByteBuffer> delegate;
+ private SSLEngine engine;
+ private int sslBufSize;
+ private ByteBuffer netData;
+ private long timeout = 30000;
+ private ConnectionSettings settings;
+
+ private final Object engineState = new Object();
private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final AtomicBoolean error = new AtomicBoolean(false);
+ private static final Logger log = Logger.get(SSLSender.class);
- public SSLSender(SSLEngine engine, Sender<ByteBuffer> delegate, SSLStatus sslStatus)
+ public SSLSender(SSLEngine engine, Sender<ByteBuffer> delegate)
{
this.engine = engine;
this.delegate = delegate;
sslBufSize = engine.getSession().getPacketBufferSize();
netData = ByteBuffer.allocate(sslBufSize);
timeout = Long.getLong("qpid.ssl_timeout", 60000);
- _sslStatus = sslStatus;
}
- public void setHostname(String hostname)
+ public void setConnectionSettings(ConnectionSettings settings)
{
- _hostname = hostname;
+ this.settings = settings;
}
public void close()
@@ -86,13 +83,13 @@ public class SSLSender implements Sender<ByteBuffer>
}
- synchronized(_sslStatus.getSslLock())
+ synchronized(engineState)
{
while (!engine.isOutboundDone())
{
try
{
- _sslStatus.getSslLock().wait();
+ engineState.wait();
}
catch(InterruptedException e)
{
@@ -151,7 +148,7 @@ public class SSLSender implements Sender<ByteBuffer>
HandshakeStatus handshakeStatus;
Status status;
- while(appData.hasRemaining() && !_sslStatus.getSslErrorFlag())
+ while(appData.hasRemaining() && !error.get())
{
int read = 0;
try
@@ -163,7 +160,6 @@ public class SSLSender implements Sender<ByteBuffer>
}
catch(SSLException e)
{
- // Should this set _sslError??
throw new SenderException("SSL, Error occurred while encrypting data",e);
}
@@ -211,7 +207,7 @@ public class SSLSender implements Sender<ByteBuffer>
case NEED_UNWRAP:
flush();
- synchronized(_sslStatus.getSslLock())
+ synchronized(engineState)
{
switch (engine.getHandshakeStatus())
{
@@ -219,7 +215,7 @@ public class SSLSender implements Sender<ByteBuffer>
long start = System.currentTimeMillis();
try
{
- _sslStatus.getSslLock().wait(timeout);
+ engineState.wait(timeout);
}
catch(InterruptedException e)
{
@@ -238,9 +234,9 @@ public class SSLSender implements Sender<ByteBuffer>
break;
case FINISHED:
- if (_hostname != null)
+ if (this.settings != null && this.settings.isVerifyHostname() )
{
- SSLUtil.verifyHostname(engine, _hostname);
+ SSLUtil.verifyHostname(engine, this.settings.getHost());
}
case NOT_HANDSHAKING:
@@ -253,7 +249,7 @@ public class SSLSender implements Sender<ByteBuffer>
}
}
- private void doTasks()
+ public void doTasks()
{
Runnable runnable;
while ((runnable = engine.getDelegatedTask()) != null) {
@@ -261,6 +257,16 @@ public class SSLSender implements Sender<ByteBuffer>
}
}
+ public Object getNotificationToken()
+ {
+ return engineState;
+ }
+
+ public void setErrorFlag()
+ {
+ error.set(true);
+ }
+
public void setIdleTimeout(int i)
{
delegate.setIdleTimeout(i);
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
index 6bb038a581..fd73915b65 100644
--- a/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
@@ -125,6 +125,38 @@ public class SSLUtil
return id.toString();
}
+ public static SSLContext createSSLContext(ConnectionSettings settings) throws Exception
+ {
+ SSLContextFactory sslContextFactory;
+
+ if (settings.getCertAlias() == null)
+ {
+ sslContextFactory =
+ new SSLContextFactory(settings.getTrustStorePath(),
+ settings.getTrustStorePassword(),
+ settings.getTrustStoreCertType(),
+ settings.getKeyStorePath(),
+ settings.getKeyStorePassword(),
+ settings.getKeyStoreCertType());
+
+ } else
+ {
+ sslContextFactory =
+ new SSLContextFactory(settings.getTrustStorePath(),
+ settings.getTrustStorePassword(),
+ settings.getTrustStoreCertType(),
+ new QpidClientX509KeyManager(settings.getCertAlias(),
+ settings.getKeyStorePath(),
+ settings.getKeyStorePassword(),
+ settings.getKeyStoreCertType()));
+
+ log.debug("Using custom key manager");
+ }
+
+ return sslContextFactory.buildServerContext();
+
+ }
+
public static KeyStore getInitializedKeyStore(String storePath, String storePassword) throws GeneralSecurityException, IOException
{
KeyStore ks = KeyStore.getInstance("JKS");
@@ -144,10 +176,7 @@ public class SSLUtil
{
throw new IOException("Unable to load keystore resource: " + storePath);
}
-
- char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray();
-
- ks.load(in, storeCharPassword);
+ ks.load(in, storePassword.toCharArray());
}
finally
{
diff --git a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
index e261860bf3..6f21c327e7 100644
--- a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
+++ b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
@@ -31,6 +31,9 @@ public class URLHelper
public static void parseOptions(Map<String, String> optionMap, String options) throws URLSyntaxException
{
+ // options looks like this
+ // brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value''
+
if ((options == null) || (options.indexOf('=') == -1))
{
return;
diff --git a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
index ac8e3da3c2..516204fbd3 100644
--- a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
+++ b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
@@ -143,9 +143,8 @@ public class FileUtils
}
/**
- * Either opens the specified filename as an input stream or either the filesystem or classpath,
- * or uses the default resource loaded using the specified class loader, if opening the file fails
- * or no file name is specified.
+ * Either opens the specified filename as an input stream, or uses the default resource loaded using the
+ * specified class loader, if opening the file fails or no file name is specified.
*
* @param filename The name of the file to open.
* @param defaultResource The name of the default resource on the classpath if the file cannot be opened.
@@ -157,28 +156,28 @@ public class FileUtils
{
InputStream is = null;
+ // Flag to indicate whether the default resource should be used. By default this is true, so that the default
+ // is used when opening the file fails.
+ boolean useDefault = true;
+
// Try to open the file if one was specified.
if (filename != null)
{
- // try on filesystem
try
{
is = new BufferedInputStream(new FileInputStream(new File(filename)));
+
+ // Clear the default flag because the file was succesfully opened.
+ useDefault = false;
}
catch (FileNotFoundException e)
{
- is = null;
- }
-
- if (is == null)
- {
- // failed on filesystem, so try on classpath
- is = cl.getResourceAsStream(filename);
+ // Ignore this exception, the default will be used instead.
}
}
// Load the default resource if a file was not specified, or if opening the file failed.
- if (is == null)
+ if (useDefault)
{
is = cl.getResourceAsStream(defaultResource);
}
@@ -340,7 +339,7 @@ public class FileUtils
}
//else we have a source directory
- if (!dst.isDirectory() && !dst.mkdirs())
+ if (!dst.isDirectory() && !dst.mkdir())
{
throw new UnableToCopyException("Unable to create destination directory");
}
diff --git a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java
new file mode 100644
index 0000000000..b93dc46741
--- /dev/null
+++ b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterClient.java
@@ -0,0 +1,396 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+package org.apache.mina.SocketIOTest;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.CloseFuture;
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+import org.apache.mina.filter.ReadThrottleFilterBuilder;
+import org.apache.mina.filter.WriteBufferLimitFilterBuilder;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.CountDownLatch;
+
+public class IOWriterClient implements Runnable
+{
+ private static final Logger _logger = LoggerFactory.getLogger(IOWriterClient.class);
+
+ public static int DEFAULT_TEST_SIZE = 2;
+
+ private IoSession _session;
+
+ private long _startTime;
+
+ private long[] _chunkTimes;
+
+ public int _chunkCount = 200000;
+
+ private int _chunkSize = 1024;
+
+ private CountDownLatch _notifier;
+
+ private int _maximumWriteQueueLength;
+
+ static public int _PORT = IOWriterServer._PORT;
+
+ public void run()
+ {
+ _logger.info("Starting to send " + _chunkCount + " buffers of " + _chunkSize + "B");
+ _startTime = System.currentTimeMillis();
+ _notifier = new CountDownLatch(1);
+
+ for (int i = 0; i < _chunkCount; i++)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(_chunkSize, false);
+ byte check = (byte) (i % 128);
+ buf.put(check);
+ buf.fill((byte) 88, buf.remaining());
+ buf.flip();
+
+ _session.write(buf);
+ }
+
+ long _sentall = System.currentTimeMillis();
+ long _receivedall = _sentall;
+ try
+ {
+ _logger.info("All buffers sent; waiting for receipt from server");
+ _notifier.await();
+ _receivedall = System.currentTimeMillis();
+ }
+ catch (InterruptedException e)
+ {
+ //Ignore
+ }
+ _logger.info("Completed");
+ _logger.info("Total time waiting for server after last write: " + (_receivedall - _sentall));
+
+ long totalTime = System.currentTimeMillis() - _startTime;
+
+ _logger.info("Total time: " + totalTime);
+ _logger.info("MB per second: " + (int) ((1.0 * _chunkSize * _chunkCount) / totalTime));
+ long lastChunkTime = _startTime;
+ double average = 0;
+ for (int i = 0; i < _chunkTimes.length; i++)
+ {
+ if (i == 0)
+ {
+ average = _chunkTimes[i] - _startTime;
+ }
+ else
+ {
+ long delta = _chunkTimes[i] - lastChunkTime;
+ if (delta != 0)
+ {
+ average = (average + delta) / 2;
+ }
+ }
+ lastChunkTime = _chunkTimes[i];
+ }
+ _logger.info("Average chunk time: " + average + "ms");
+ _logger.info("Maximum WriteRequestQueue size: " + _maximumWriteQueueLength);
+
+ CloseFuture cf = _session.close();
+ _logger.info("Closing session");
+ cf.join();
+ }
+
+ private class WriterHandler extends IoHandlerAdapter
+ {
+ private int _chunksReceived = 0;
+
+ private int _partialBytesRead = 0;
+
+ private byte _partialCheckNumber;
+
+ private int _totalBytesReceived = 0;
+
+ private int _receivedCount = 0;
+ private int _sentCount = 0;
+ private static final String DEFAULT_READ_BUFFER = "262144";
+ private static final String DEFAULT_WRITE_BUFFER = "262144";
+
+ public void sessionCreated(IoSession session) throws Exception
+ {
+ IoFilterChain chain = session.getFilterChain();
+
+ ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder();
+ readfilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER)));
+ readfilter.attach(chain);
+
+ WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder();
+
+ writefilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER)));
+
+ writefilter.attach(chain);
+ }
+
+ public void messageSent(IoSession session, Object message) throws Exception
+ {
+ _maximumWriteQueueLength = Math.max(session.getScheduledWriteRequests(), _maximumWriteQueueLength);
+
+ if (_logger.isDebugEnabled())
+ {
+ ++_sentCount;
+ if (_sentCount % 1000 == 0)
+ {
+ _logger.debug("Sent count " + _sentCount + ":WQueue" + session.getScheduledWriteRequests());
+
+ }
+ }
+ }
+
+ public void messageReceived(IoSession session, Object message) throws Exception
+ {
+ if (_logger.isDebugEnabled())
+ {
+ ++_receivedCount;
+
+ if (_receivedCount % 1000 == 0)
+ {
+ _logger.debug("Receieved count " + _receivedCount);
+ }
+ }
+
+ ByteBuffer result = (ByteBuffer) message;
+ _totalBytesReceived += result.remaining();
+ int size = result.remaining();
+ long now = System.currentTimeMillis();
+ if (_partialBytesRead > 0)
+ {
+ int offset = _chunkSize - _partialBytesRead;
+ if (size >= offset)
+ {
+ _chunkTimes[_chunksReceived++] = now;
+ result.position(offset);
+ }
+ else
+ {
+ // have not read even one chunk, including the previous partial bytes
+ _partialBytesRead += size;
+ return;
+ }
+ }
+
+
+ int chunkCount = result.remaining() / _chunkSize;
+
+ for (int i = 0; i < chunkCount; i++)
+ {
+ _chunkTimes[_chunksReceived++] = now;
+ byte check = result.get();
+ _logger.debug("Check number " + check + " read");
+ if (check != (byte) ((_chunksReceived - 1) % 128))
+ {
+ _logger.error("Check number " + check + " read when expected " + (_chunksReceived % 128));
+ }
+ _logger.debug("Chunk times recorded");
+
+ try
+ {
+ result.skip(_chunkSize - 1);
+ }
+ catch (IllegalArgumentException e)
+ {
+ _logger.error("Position was: " + result.position());
+ _logger.error("Tried to skip to: " + (_chunkSize * i));
+ _logger.error("limit was; " + result.limit());
+ }
+ }
+ _logger.debug("Chunks received now " + _chunksReceived);
+ _logger.debug("Bytes received: " + _totalBytesReceived);
+ _partialBytesRead = result.remaining();
+
+ if (_partialBytesRead > 0)
+ {
+ _partialCheckNumber = result.get();
+ }
+
+
+ if (_chunksReceived >= _chunkCount)
+ {
+ _notifier.countDown();
+ }
+
+ }
+
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception
+ {
+ _logger.error("Error: " + cause, cause);
+ }
+ }
+
+ public void startWriter() throws IOException, InterruptedException
+ {
+
+ _maximumWriteQueueLength = 0;
+
+ IoConnector ioConnector = null;
+
+ if (Boolean.getBoolean("multinio"))
+ {
+ _logger.warn("Using MultiThread NIO");
+ ioConnector = new org.apache.mina.transport.socket.nio.MultiThreadSocketConnector();
+ }
+ else
+ {
+ _logger.warn("Using MINA NIO");
+ ioConnector = new org.apache.mina.transport.socket.nio.SocketConnector();
+ }
+
+ SocketSessionConfig scfg = (SocketSessionConfig) ioConnector.getDefaultConfig().getSessionConfig();
+ scfg.setTcpNoDelay(true);
+ scfg.setSendBufferSize(32768);
+ scfg.setReceiveBufferSize(32768);
+
+ ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
+
+
+ final InetSocketAddress address = new InetSocketAddress("localhost", _PORT);
+ _logger.info("Attempting connection to " + address);
+
+ //Old mina style
+// ioConnector.setHandler(new WriterHandler());
+// ConnectFuture future = ioConnector.connect(address);
+ ConnectFuture future = ioConnector.connect(address, new WriterHandler());
+ // wait for connection to complete
+ future.join();
+ _logger.info("Connection completed");
+ // we call getSession which throws an IOException if there has been an error connecting
+ _session = future.getSession();
+
+ _chunkTimes = new long[_chunkCount];
+ Thread t = new Thread(this);
+ t.start();
+ t.join();
+ _logger.info("Test Complete");
+ }
+
+
+ public void test1k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 1k test");
+ _chunkSize = 1024;
+ startWriter();
+ }
+
+
+ public void test2k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 2k test");
+ _chunkSize = 2048;
+ startWriter();
+ }
+
+
+ public void test4k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 4k test");
+ _chunkSize = 4096;
+ startWriter();
+ }
+
+
+ public void test8k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 8k test");
+ _chunkSize = 8192;
+ startWriter();
+ }
+
+
+ public void test16k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 16k test");
+ _chunkSize = 16384;
+ startWriter();
+ }
+
+
+ public void test32k() throws IOException, InterruptedException
+ {
+ _logger.info("Starting 32k test");
+ _chunkSize = 32768;
+ startWriter();
+ }
+
+
+ public static int getIntArg(String[] args, int index, int defaultValue)
+ {
+ if (args.length > index)
+ {
+ try
+ {
+ return Integer.parseInt(args[index]);
+ }
+ catch (NumberFormatException e)
+ {
+ //Do nothing
+ }
+ }
+ return defaultValue;
+ }
+
+ public static void main(String[] args) throws IOException, InterruptedException
+ {
+ _PORT = getIntArg(args, 0, _PORT);
+
+ int test = getIntArg(args, 1, DEFAULT_TEST_SIZE);
+
+ IOWriterClient w = new IOWriterClient();
+ w._chunkCount = getIntArg(args, 2, w._chunkCount);
+ switch (test)
+ {
+ case 0:
+ w.test1k();
+ w.test2k();
+ w.test4k();
+ w.test8k();
+ w.test16k();
+ w.test32k();
+ break;
+ case 1:
+ w.test1k();
+ break;
+ case 2:
+ w.test2k();
+ break;
+ case 4:
+ w.test4k();
+ break;
+ case 8:
+ w.test8k();
+ break;
+ case 16:
+ w.test16k();
+ break;
+ case 32:
+ w.test32k();
+ break;
+ }
+ }
+}
diff --git a/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java
new file mode 100644
index 0000000000..423e98c67b
--- /dev/null
+++ b/java/common/src/test/java/org/apache/mina/SocketIOTest/IOWriterServer.java
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * 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.
+ *
+ */
+package org.apache.mina.SocketIOTest;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+import org.apache.mina.filter.ReadThrottleFilterBuilder;
+import org.apache.mina.filter.WriteBufferLimitFilterBuilder;
+import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+/** Tests MINA socket performance. This acceptor simply reads data from the network and writes it back again. */
+public class IOWriterServer
+{
+ private static final Logger _logger = LoggerFactory.getLogger(IOWriterServer.class);
+
+ static public int _PORT = 9999;
+
+ private static final String DEFAULT_READ_BUFFER = "262144";
+ private static final String DEFAULT_WRITE_BUFFER = "262144";
+
+
+ private static class TestHandler extends IoHandlerAdapter
+ {
+ private int _sentCount = 0;
+
+ private int _bytesSent = 0;
+
+ private int _receivedCount = 0;
+
+ public void sessionCreated(IoSession ioSession) throws java.lang.Exception
+ {
+ IoFilterChain chain = ioSession.getFilterChain();
+
+ ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder();
+ readfilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER)));
+ readfilter.attach(chain);
+
+ WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder();
+
+ writefilter.setMaximumConnectionBufferSize(Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER)));
+
+ writefilter.attach(chain);
+
+ }
+
+ public void messageReceived(IoSession session, Object message) throws Exception
+ {
+ ((ByteBuffer) message).acquire();
+ session.write(message);
+
+ if (_logger.isDebugEnabled())
+ {
+ _bytesSent += ((ByteBuffer) message).remaining();
+
+ _sentCount++;
+
+ if (_sentCount % 1000 == 0)
+ {
+ _logger.debug("Bytes sent: " + _bytesSent);
+ }
+ }
+ }
+
+ public void messageSent(IoSession session, Object message) throws Exception
+ {
+ if (_logger.isDebugEnabled())
+ {
+ ++_receivedCount;
+
+ if (_receivedCount % 1000 == 0)
+ {
+ _logger.debug("Receieved count " + _receivedCount);
+ }
+ }
+ }
+
+ public void exceptionCaught(IoSession session, Throwable cause) throws Exception
+ {
+ _logger.error("Error: " + cause, cause);
+ }
+ }
+
+ public void startAcceptor() throws IOException
+ {
+ IoAcceptor acceptor;
+ if (Boolean.getBoolean("multinio"))
+ {
+ _logger.warn("Using MultiThread NIO");
+ acceptor = new org.apache.mina.transport.socket.nio.MultiThreadSocketAcceptor();
+ }
+ else
+ {
+ _logger.warn("Using MINA NIO");
+ acceptor = new org.apache.mina.transport.socket.nio.SocketAcceptor();
+ }
+
+
+ SocketSessionConfig sc = (SocketSessionConfig) acceptor.getDefaultConfig().getSessionConfig();
+ sc.setTcpNoDelay(true);
+ sc.setSendBufferSize(32768);
+ sc.setReceiveBufferSize(32768);
+
+ ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
+
+ //The old mina style
+// acceptor.setLocalAddress(new InetSocketAddress(_PORT));
+// acceptor.setHandler(new TestHandler());
+// acceptor.bind();
+ acceptor.bind(new InetSocketAddress(_PORT), new TestHandler());
+
+ _logger.info("Bound on port " + _PORT + ":" + _logger.isDebugEnabled());
+ _logger.debug("debug on");
+ }
+
+ public static void main(String[] args) throws IOException
+ {
+
+ if (args.length > 0)
+ {
+ try
+ {
+ _PORT = Integer.parseInt(args[0]);
+ }
+ catch (NumberFormatException e)
+ {
+ //IGNORE so use default port 9999;
+ }
+ }
+
+ IOWriterServer a = new IOWriterServer();
+ a.startAcceptor();
+ }
+}
diff --git a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
index f65427e583..ef6cd41492 100644
--- a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
+++ b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
@@ -23,7 +23,6 @@ package org.apache.qpid;
import junit.framework.TestCase;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.AMQShortString;
/**
* This test is to ensure that when an AMQException is rethrown that the specified exception is correctly wrapped up.
@@ -92,18 +91,6 @@ public class AMQExceptionTest extends TestCase
return amqe;
}
- public void testGetMessageAsString()
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 25; i++)
- {
- sb.append("message [" + i + "]");
- }
- AMQException e = new AMQException(AMQConstant.INTERNAL_ERROR, sb.toString(), null);
- AMQShortString message = e.getMessageAsShortString();
- assertEquals(sb.substring(0, AMQShortString.MAX_LENGTH - 3) + "...", message.toString());
- }
-
/**
* Private class that extends AMQException but does not have a default exception.
*/
diff --git a/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java b/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java
index 272eb75800..62e25e7d79 100644
--- a/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java
+++ b/java/common/src/test/java/org/apache/qpid/codec/AMQDecoderTest.java
@@ -21,9 +21,6 @@ package org.apache.qpid.codec;
*/
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -49,16 +46,9 @@ public class AMQDecoderTest extends TestCase
}
- private ByteBuffer getHeartbeatBodyBuffer() throws IOException
+ public void testSingleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException
{
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- HeartbeatBody.FRAME.writePayload(new DataOutputStream(baos));
- return ByteBuffer.wrap(baos.toByteArray());
- }
-
- public void testSingleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException
- {
- ByteBuffer msg = getHeartbeatBodyBuffer();
+ ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer();
ArrayList<AMQDataBlock> frames = _decoder.decodeBuffer(msg);
if (frames.get(0) instanceof AMQFrame)
{
@@ -70,9 +60,9 @@ public class AMQDecoderTest extends TestCase
}
}
- public void testPartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException
+ public void testPartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException
{
- ByteBuffer msg = getHeartbeatBodyBuffer();
+ ByteBuffer msg = HeartbeatBody.FRAME.toNioByteBuffer();
ByteBuffer msgA = msg.slice();
int msgbPos = msg.remaining() / 2;
int msgaLimit = msg.remaining() - msgbPos;
@@ -93,10 +83,10 @@ public class AMQDecoderTest extends TestCase
}
}
- public void testMultipleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException
+ public void testMultipleFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException
{
- ByteBuffer msgA = getHeartbeatBodyBuffer();
- ByteBuffer msgB = getHeartbeatBodyBuffer();
+ ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer();
+ ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer();
ByteBuffer msg = ByteBuffer.allocate(msgA.remaining() + msgB.remaining());
msg.put(msgA);
msg.put(msgB);
@@ -116,11 +106,11 @@ public class AMQDecoderTest extends TestCase
}
}
- public void testMultiplePartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException, IOException
+ public void testMultiplePartialFrameDecode() throws AMQProtocolVersionException, AMQFrameDecodingException
{
- ByteBuffer msgA = getHeartbeatBodyBuffer();
- ByteBuffer msgB = getHeartbeatBodyBuffer();
- ByteBuffer msgC = getHeartbeatBodyBuffer();
+ ByteBuffer msgA = HeartbeatBody.FRAME.toNioByteBuffer();
+ ByteBuffer msgB = HeartbeatBody.FRAME.toNioByteBuffer();
+ ByteBuffer msgC = HeartbeatBody.FRAME.toNioByteBuffer();
ByteBuffer sliceA = ByteBuffer.allocate(msgA.remaining() + msgB.remaining() / 2);
sliceA.put(msgA);
diff --git a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
index 9a805d87b3..92e7ce0a80 100644
--- a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
+++ b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
@@ -20,10 +20,6 @@
package org.apache.qpid.framing;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-
import junit.framework.TestCase;
public class AMQShortStringTest extends TestCase
{
@@ -109,215 +105,5 @@ public class AMQShortStringTest extends TestCase
assertFalse(new AMQShortString("A").equals(new AMQShortString("a")));
}
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}.
- */
- public void testCreateAMQShortStringByteArray()
- {
- byte[] bytes = null;
- try
- {
- bytes = "test".getBytes("UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage());
- }
- AMQShortString string = new AMQShortString(bytes);
- assertEquals("constructed amq short string length differs from expected", 4, string.length());
- assertTrue("constructed amq short string differs from expected", string.equals("test"));
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)}
- * <p>
- * Tests short string construction from string with length less than 255.
- */
- public void testCreateAMQShortStringString()
- {
- AMQShortString string = new AMQShortString("test");
- assertEquals("constructed amq short string length differs from expected", 4, string.length());
- assertTrue("constructed amq short string differs from expected", string.equals("test"));
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}.
- * <p>
- * Tests short string construction from char array with length less than 255.
- */
- public void testCreateAMQShortStringCharArray()
- {
- char[] chars = "test".toCharArray();
- AMQShortString string = new AMQShortString(chars);
- assertEquals("constructed amq short string length differs from expected", 4, string.length());
- assertTrue("constructed amq short string differs from expected", string.equals("test"));
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)}
- * <p>
- * Tests short string construction from char sequence with length less than 255.
- */
- public void testCreateAMQShortStringCharSequence()
- {
- AMQShortString string = new AMQShortString((CharSequence) "test");
- assertEquals("constructed amq short string length differs from expected", 4, string.length());
- assertTrue("constructed amq short string differs from expected", string.equals("test"));
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}.
- * <p>
- * Tests an attempt to create an AMQP short string from byte array with length over 255.
- */
- public void testCreateAMQShortStringByteArrayOver255()
- {
- String test = buildString('a', 256);
- byte[] bytes = null;
- try
- {
- bytes = test.getBytes("UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage());
- }
- try
- {
- new AMQShortString(bytes);
- fail("It should not be possible to create AMQShortString with length over 255");
- }
- catch (IllegalArgumentException e)
- {
- assertEquals("Exception message differs from expected",
- "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
- }
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)}
- * <p>
- * Tests an attempt to create an AMQP short string from string with length over 255
- */
- public void testCreateAMQShortStringStringOver255()
- {
- String test = buildString('a', 256);
- try
- {
- new AMQShortString(test);
- fail("It should not be possible to create AMQShortString with length over 255");
- }
- catch (IllegalArgumentException e)
- {
- assertEquals("Exception message differs from expected",
- "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
- }
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}.
- * <p>
- * Tests an attempt to create an AMQP short string from char array with length over 255.
- */
- public void testCreateAMQShortStringCharArrayOver255()
- {
- String test = buildString('a', 256);
- char[] chars = test.toCharArray();
- try
- {
- new AMQShortString(chars);
- fail("It should not be possible to create AMQShortString with length over 255");
- }
- catch (IllegalArgumentException e)
- {
- assertEquals("Exception message differs from expected",
- "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
- }
- }
-
- /**
- * Test method for
- * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)}
- * <p>
- * Tests an attempt to create an AMQP short string from char sequence with length over 255.
- */
- public void testCreateAMQShortStringCharSequenceOver255()
- {
- String test = buildString('a', 256);
- try
- {
- new AMQShortString((CharSequence) test);
- fail("It should not be possible to create AMQShortString with length over 255");
- }
- catch (IllegalArgumentException e)
- {
- assertEquals("Exception message differs from expected",
- "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
- }
- }
-
- /**
- * Tests joining of short strings into a short string with length over 255.
- */
- public void testJoinOverflow()
- {
- List<AMQShortString> data = new ArrayList<AMQShortString>();
- for (int i = 0; i < 25; i++)
- {
- data.add(new AMQShortString("test data!"));
- }
- try
- {
- AMQShortString.join(data, new AMQShortString(" "));
- fail("It should not be possible to create AMQShortString with length over 255");
- }
- catch (IllegalArgumentException e)
- {
- assertEquals("Exception message differs from expected",
- "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
- }
- }
-
- /**
- * Tests joining of short strings into a short string with length less than 255.
- */
- public void testJoin()
- {
- StringBuilder expected = new StringBuilder();
- List<AMQShortString> data = new ArrayList<AMQShortString>();
- data.add(new AMQShortString("test data 1"));
- expected.append("test data 1");
- data.add(new AMQShortString("test data 2"));
- expected.append(" test data 2");
- AMQShortString result = AMQShortString.join(data, new AMQShortString(" "));
- assertEquals("join result differs from expected", expected.toString(), result.asString());
- }
-
- /**
- * A helper method to generate a string with given length containing given
- * character
- *
- * @param ch
- * char to build string with
- * @param length
- * target string length
- * @return string
- */
- private String buildString(char ch, int length)
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++)
- {
- sb.append(ch);
- }
- return sb.toString();
- }
}
diff --git a/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java b/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java
index 5e7783f492..4fd1f60d69 100644
--- a/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java
+++ b/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java
@@ -20,9 +20,9 @@
*/
package org.apache.qpid.framing;
-import junit.framework.TestCase;
+import org.apache.mina.common.ByteBuffer;
-import java.io.*;
+import junit.framework.TestCase;
public class BasicContentHeaderPropertiesTest extends TestCase
@@ -76,14 +76,15 @@ public class BasicContentHeaderPropertiesTest extends TestCase
assertEquals(99, _testProperties.getPropertyFlags());
}
- public void testWritePropertyListPayload() throws IOException
+ public void testWritePropertyListPayload()
{
- _testProperties.writePropertyListPayload(new DataOutputStream(new ByteArrayOutputStream(300)));
+ ByteBuffer buf = ByteBuffer.allocate(300);
+ _testProperties.writePropertyListPayload(buf);
}
public void testPopulatePropertiesFromBuffer() throws Exception
{
- DataInputStream buf = new DataInputStream(new ByteArrayInputStream(new byte[300]));
+ ByteBuffer buf = ByteBuffer.allocate(300);
_testProperties.populatePropertiesFromBuffer(buf, 99, 99);
}
diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
index bb4c9c3884..d4691ba097 100644
--- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
+++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
@@ -23,14 +23,14 @@ package org.apache.qpid.framing;
import junit.framework.Assert;
import junit.framework.TestCase;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.AMQPInvalidClassException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.*;
-
public class PropertyFieldTableTest extends TestCase
{
private static final Logger _logger = LoggerFactory.getLogger(PropertyFieldTableTest.class);
@@ -441,7 +441,7 @@ public class PropertyFieldTableTest extends TestCase
}
/** Check that a nested field table parameter correctly encodes and decodes to a byte buffer. */
- public void testNestedFieldTable() throws IOException
+ public void testNestedFieldTable()
{
byte[] testBytes = new byte[] { 0, 1, 2, 3, 4, 5 };
@@ -465,16 +465,14 @@ public class PropertyFieldTableTest extends TestCase
outerTable.setFieldTable("innerTable", innerTable);
// Write the outer table into the buffer.
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- outerTable.writeToBuffer(new DataOutputStream(baos));
-
- byte[] data = baos.toByteArray();
+ final ByteBuffer buffer = ByteBuffer.allocate((int) outerTable.getEncodedSize() + 4);
+ outerTable.writeToBuffer(buffer);
+ buffer.flip();
// Extract the table back from the buffer again.
try
{
- FieldTable extractedOuterTable = EncodingUtils.readFieldTable(new DataInputStream(new ByteArrayInputStream(data)));
+ FieldTable extractedOuterTable = EncodingUtils.readFieldTable(buffer);
FieldTable extractedTable = extractedOuterTable.getFieldTable("innerTable");
@@ -569,7 +567,7 @@ public class PropertyFieldTableTest extends TestCase
Assert.assertEquals("Hello", table.getObject("object-string"));
}
- public void testwriteBuffer() throws IOException
+ public void testwriteBuffer()
{
byte[] bytes = { 99, 98, 97, 96, 95 };
@@ -587,17 +585,15 @@ public class PropertyFieldTableTest extends TestCase
table.setString("string", "hello");
table.setString("null-string", null);
+ final ByteBuffer buffer = ByteBuffer.allocate((int) table.getEncodedSize() + 4); // FIXME XXX: Is cast a problem?
- ByteArrayOutputStream baos = new ByteArrayOutputStream((int) table.getEncodedSize() + 4);
- table.writeToBuffer(new DataOutputStream(baos));
-
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- DataInputStream dis = new DataInputStream(bais);
+ table.writeToBuffer(buffer);
+ buffer.flip();
- long length = dis.readInt() & 0xFFFFFFFFL;
+ long length = buffer.getUnsignedInt();
- FieldTable table2 = new FieldTable(dis, length);
+ FieldTable table2 = new FieldTable(buffer, length);
Assert.assertEquals((Boolean) true, table2.getBoolean("bool"));
Assert.assertEquals((Byte) Byte.MAX_VALUE, table2.getByte("byte"));
diff --git a/java/common/src/test/java/org/apache/qpid/session/TestSession.java b/java/common/src/test/java/org/apache/qpid/session/TestSession.java
new file mode 100644
index 0000000000..aafc91b03b
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/session/TestSession.java
@@ -0,0 +1,277 @@
+/*
+ *
+ * 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 org.apache.qpid.session;
+
+import org.apache.mina.common.*;
+
+import java.net.SocketAddress;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class TestSession implements IoSession
+{
+ private final ConcurrentMap attributes = new ConcurrentHashMap();
+
+ public TestSession()
+ {
+ }
+
+ public IoService getService()
+ {
+ return null; //TODO
+ }
+
+ public IoServiceConfig getServiceConfig()
+ {
+ return null; //TODO
+ }
+
+ public IoHandler getHandler()
+ {
+ return null; //TODO
+ }
+
+ public IoSessionConfig getConfig()
+ {
+ return null; //TODO
+ }
+
+ public IoFilterChain getFilterChain()
+ {
+ return null; //TODO
+ }
+
+ public WriteFuture write(Object message)
+ {
+ return null; //TODO
+ }
+
+ public CloseFuture close()
+ {
+ return null; //TODO
+ }
+
+ public Object getAttachment()
+ {
+ return getAttribute("");
+ }
+
+ public Object setAttachment(Object attachment)
+ {
+ return setAttribute("",attachment);
+ }
+
+ public Object getAttribute(String key)
+ {
+ return attributes.get(key);
+ }
+
+ public Object setAttribute(String key, Object value)
+ {
+ return attributes.put(key,value);
+ }
+
+ public Object setAttribute(String key)
+ {
+ return attributes.put(key, Boolean.TRUE);
+ }
+
+ public Object removeAttribute(String key)
+ {
+ return attributes.remove(key);
+ }
+
+ public boolean containsAttribute(String key)
+ {
+ return attributes.containsKey(key);
+ }
+
+ public Set getAttributeKeys()
+ {
+ return attributes.keySet();
+ }
+
+ public TransportType getTransportType()
+ {
+ return null; //TODO
+ }
+
+ public boolean isConnected()
+ {
+ return false; //TODO
+ }
+
+ public boolean isClosing()
+ {
+ return false; //TODO
+ }
+
+ public CloseFuture getCloseFuture()
+ {
+ return null; //TODO
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return null; //TODO
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return null; //TODO
+ }
+
+ public SocketAddress getServiceAddress()
+ {
+ return null; //TODO
+ }
+
+ public int getIdleTime(IdleStatus status)
+ {
+ return 0; //TODO
+ }
+
+ public long getIdleTimeInMillis(IdleStatus status)
+ {
+ return 0; //TODO
+ }
+
+ public void setIdleTime(IdleStatus status, int idleTime)
+ {
+ //TODO
+ }
+
+ public int getWriteTimeout()
+ {
+ return 0; //TODO
+ }
+
+ public long getWriteTimeoutInMillis()
+ {
+ return 0; //TODO
+ }
+
+ public void setWriteTimeout(int writeTimeout)
+ {
+ //TODO
+ }
+
+ public TrafficMask getTrafficMask()
+ {
+ return null; //TODO
+ }
+
+ public void setTrafficMask(TrafficMask trafficMask)
+ {
+ //TODO
+ }
+
+ public void suspendRead()
+ {
+ //TODO
+ }
+
+ public void suspendWrite()
+ {
+ //TODO
+ }
+
+ public void resumeRead()
+ {
+ //TODO
+ }
+
+ public void resumeWrite()
+ {
+ //TODO
+ }
+
+ public long getReadBytes()
+ {
+ return 0; //TODO
+ }
+
+ public long getWrittenBytes()
+ {
+ return 0; //TODO
+ }
+
+ public long getReadMessages()
+ {
+ return 0;
+ }
+
+ public long getWrittenMessages()
+ {
+ return 0;
+ }
+
+ public long getWrittenWriteRequests()
+ {
+ return 0; //TODO
+ }
+
+ public int getScheduledWriteRequests()
+ {
+ return 0; //TODO
+ }
+
+ public int getScheduledWriteBytes()
+ {
+ return 0; //TODO
+ }
+
+ public long getCreationTime()
+ {
+ return 0; //TODO
+ }
+
+ public long getLastIoTime()
+ {
+ return 0; //TODO
+ }
+
+ public long getLastReadTime()
+ {
+ return 0; //TODO
+ }
+
+ public long getLastWriteTime()
+ {
+ return 0; //TODO
+ }
+
+ public boolean isIdle(IdleStatus status)
+ {
+ return false; //TODO
+ }
+
+ public int getIdleCount(IdleStatus status)
+ {
+ return 0; //TODO
+ }
+
+ public long getLastIdleTime(IdleStatus status)
+ {
+ return 0; //TODO
+ }
+}
diff --git a/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java b/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java
deleted file mode 100644
index 288946e064..0000000000
--- a/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java
+++ /dev/null
@@ -1,84 +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.
- */
-package org.apache.qpid.ssl;
-
-import java.io.IOException;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.qpid.test.utils.QpidTestCase;
-
-public class SSLContextFactoryTest extends QpidTestCase
-{
- private static final String BROKER_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_broker_keystore.jks";
- private static final String CLIENT_KEYSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_client_keystore.jks";
- private static final String CLIENT_TRUSTSTORE_PATH = TEST_RESOURCES_DIR + "/ssl/java_client_truststore.jks";
- private static final String STORE_PASSWORD = "password";
- private static final String CERT_TYPE = "SunX509";
- private static final String CERT_ALIAS_APP1 = "app1";
-
- public void testBuildServerContext() throws Exception
- {
- SSLContext context = SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE);
- assertNotNull("SSLContext should not be null", context);
- }
-
- public void testBuildServerContextWithIncorrectPassword() throws Exception
- {
- try
- {
- SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, "sajdklsad", CERT_TYPE);
- fail("Exception was not thrown due to incorrect password");
- }
- catch (IOException e)
- {
- //expected
- }
- }
-
- public void testTrustStoreDoesNotExist() throws Exception
- {
- try
- {
- SSLContextFactory.buildClientContext("/path/to/nothing", STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null);
- fail("Exception was not thrown due to incorrect path");
- }
- catch (IOException e)
- {
- //expected
- }
- }
-
- public void testBuildClientContextForSSLEncryptionOnly() throws Exception
- {
- SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null, null, null, null);
- assertNotNull("SSLContext should not be null", context);
- }
-
- public void testBuildClientContextWithForClientAuth() throws Exception
- {
- SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, null);
- assertNotNull("SSLContext should not be null", context);
- }
-
- public void testBuildClientContextWithForClientAuthWithCertAlias() throws Exception
- {
- SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, CERT_TYPE, CERT_ALIAS_APP1);
- assertNotNull("SSLContext should not be null", context);
- }
-}
diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java
index e69f95f916..8b470d555e 100644
--- a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java
+++ b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java
@@ -24,28 +24,17 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.ServerSocket;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
import junit.framework.TestCase;
import junit.framework.TestResult;
-import org.apache.log4j.Level;
import org.apache.log4j.Logger;
-
public class QpidTestCase extends TestCase
{
- public static final String QPID_HOME = System.getProperty("QPID_HOME");
- public static final String TEST_RESOURCES_DIR = QPID_HOME + "/../test-profiles/test_resources/";
-
- private static final Logger _logger = Logger.getLogger(QpidTestCase.class);
-
- private final Map<Logger, Level> _loggerLevelSetForTest = new HashMap<Logger, Level>();
- private final Map<String, String> _propertiesSetForTest = new HashMap<String, String>();
-
- private String _testName;
+ protected static final Logger _logger = Logger.getLogger(QpidTestCase.class);
/**
* Some tests are excluded when the property test.excludes is set to true.
@@ -65,7 +54,7 @@ public class QpidTestCase extends TestCase
String exclusionListString = System.getProperties().getProperty("test.excludelist", "");
List<String> exclusionList = new ArrayList<String>();
- for (String uri : exclusionListURIs.split(";\\s*"))
+ for (String uri : exclusionListURIs.split("\\s+"))
{
File file = new File(uri);
if (file.exists())
@@ -87,10 +76,6 @@ public class QpidTestCase extends TestCase
_logger.warn("Exception when reading exclusion list", e);
}
}
- else
- {
- _logger.info("Specified exclude file does not exist: " + uri);
- }
}
if (!exclusionListString.equals(""))
@@ -142,187 +127,4 @@ public class QpidTestCase extends TestCase
return storeClass != null ? storeClass : MEMORY_STORE_CLASS_NAME ;
}
-
-
- public static final int MIN_PORT_NUMBER = 1;
- public static final int MAX_PORT_NUMBER = 49151;
-
-
- /**
- * Gets the next available port starting at a port.
- *
- * @param fromPort the port to scan for availability
- * @throws NoSuchElementException if there are no ports available
- */
- protected int getNextAvailable(int fromPort)
- {
- if ((fromPort < MIN_PORT_NUMBER) || (fromPort > MAX_PORT_NUMBER))
- {
- throw new IllegalArgumentException("Invalid start port: " + fromPort);
- }
-
- for (int i = fromPort; i <= MAX_PORT_NUMBER; i++)
- {
- if (available(i)) {
- return i;
- }
- }
-
- throw new NoSuchElementException("Could not find an available port above " + fromPort);
- }
-
- /**
- * Checks to see if a specific port is available.
- *
- * @param port the port to check for availability
- */
- private boolean available(int port)
- {
- if ((port < MIN_PORT_NUMBER) || (port > MAX_PORT_NUMBER))
- {
- throw new IllegalArgumentException("Invalid start port: " + port);
- }
-
- ServerSocket ss = null;
- DatagramSocket ds = null;
- try
- {
- ss = new ServerSocket(port);
- ss.setReuseAddress(true);
- ds = new DatagramSocket(port);
- ds.setReuseAddress(true);
- return true;
- }
- catch (IOException e)
- {
- }
- finally
- {
- if (ds != null)
- {
- ds.close();
- }
-
- if (ss != null)
- {
- try
- {
- ss.close();
- }
- catch (IOException e)
- {
- /* should not be thrown */
- }
- }
- }
-
- return false;
- }
-
- public int findFreePort()
- {
- return getNextAvailable(10000);
- }
-
- /**
- * Set a System property for duration of this test only. The tearDown will
- * guarantee to reset the property to its previous value after the test
- * completes.
- *
- * @param property The property to set
- * @param value the value to set it to, if null, the property will be cleared
- */
- protected void setTestSystemProperty(final String property, final String value)
- {
- if (!_propertiesSetForTest.containsKey(property))
- {
- // Record the current value so we can revert it later.
- _propertiesSetForTest.put(property, System.getProperty(property));
- }
-
- if (value == null)
- {
- System.clearProperty(property);
- }
- else
- {
- System.setProperty(property, value);
- }
- }
-
- /**
- * Restore the System property values that were set by this test run.
- */
- protected void revertTestSystemProperties()
- {
- if(!_propertiesSetForTest.isEmpty())
- {
- _logger.debug("reverting " + _propertiesSetForTest.size() + " test properties");
- for (String key : _propertiesSetForTest.keySet())
- {
- String value = _propertiesSetForTest.get(key);
- if (value != null)
- {
- System.setProperty(key, value);
- }
- else
- {
- System.clearProperty(key);
- }
- }
-
- _propertiesSetForTest.clear();
- }
- }
-
- /**
- * Adjust the VMs Log4j Settings just for this test run
- *
- * @param logger the logger to change
- * @param level the level to set
- */
- protected void setLoggerLevel(Logger logger, Level level)
- {
- assertNotNull("Cannot set level of null logger", logger);
- assertNotNull("Cannot set Logger("+logger.getName()+") to null level.",level);
-
- if (!_loggerLevelSetForTest.containsKey(logger))
- {
- // Record the current value so we can revert it later.
- _loggerLevelSetForTest.put(logger, logger.getLevel());
- }
-
- logger.setLevel(level);
- }
-
- /**
- * Restore the logging levels defined by this test.
- */
- protected void revertLoggingLevels()
- {
- for (Logger logger : _loggerLevelSetForTest.keySet())
- {
- logger.setLevel(_loggerLevelSetForTest.get(logger));
- }
-
- _loggerLevelSetForTest.clear();
- }
-
- protected void tearDown() throws java.lang.Exception
- {
- _logger.info("========== tearDown " + _testName + " ==========");
- revertTestSystemProperties();
- revertLoggingLevels();
- }
-
- protected void setUp() throws Exception
- {
- _testName = getClass().getSimpleName() + "." + getName();
- _logger.info("========== start " + _testName + " ==========");
- }
-
- protected String getTestName()
- {
- return _testName;
- }
}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java
index 49f6a08007..375a326654 100644
--- a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java
+++ b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java
@@ -20,27 +20,32 @@
*/
package org.apache.qpid.transport;
-import static org.apache.qpid.transport.Option.EXPECTED;
-import static org.apache.qpid.transport.Option.NONE;
-import static org.apache.qpid.transport.Option.SYNC;
+import org.apache.mina.util.AvailablePortFinder;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.io.IoAcceptor;
+import org.apache.qpid.transport.util.Logger;
+import org.apache.qpid.transport.util.Waiter;
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
+import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.io.IOException;
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.transport.network.ConnectionBinding;
-import org.apache.qpid.transport.network.io.IoAcceptor;
-import org.apache.qpid.transport.util.Waiter;
+import static org.apache.qpid.transport.Option.*;
/**
* ConnectionTest
*/
+
public class ConnectionTest extends QpidTestCase implements SessionListener
{
+
+ private static final Logger log = Logger.get(ConnectionTest.class);
+
private int port;
private volatile boolean queue = false;
private List<MessageTransfer> messages = new ArrayList<MessageTransfer>();
@@ -53,7 +58,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
{
super.setUp();
- port = findFreePort();
+ port = AvailablePortFinder.getNextAvailable(12000);
}
protected void tearDown() throws Exception
@@ -153,8 +158,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
private Connection connect(final CountDownLatch closed)
{
- final Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
+ Connection conn = new Connection();
conn.addConnectionListener(new ConnectionListener()
{
public void opened(Connection conn) {}
@@ -178,9 +182,9 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
{
// Force os.name to be windows to exercise code in IoReceiver
// that looks for the value of os.name
- setTestSystemProperty("os.name","windows");
+ System.setProperty("os.name","windows");
- // Start server as 0-9 to force a ProtocolVersionException
+ // Start server as 0-9 to froce a ProtocolVersionException
startServer(new ProtocolHeader(1, 0, 9));
CountDownLatch closed = new CountDownLatch(1);
@@ -215,7 +219,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
conn.send(protocolHeader);
List<Object> utf8 = new ArrayList<Object>();
utf8.add("utf8");
- conn.connectionStart(null, Collections.emptyList(), utf8);
+ conn.connectionStart(null, Collections.EMPTY_LIST, utf8);
}
@Override
@@ -266,7 +270,40 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
}
}
+ class FailoverConnectionListener implements ConnectionListener
+ {
+ public void opened(Connection conn) {}
+
+ public void exception(Connection conn, ConnectionException e)
+ {
+ throw e;
+ }
+
+ public void closed(Connection conn)
+ {
+ queue = true;
+ conn.connect("localhost", port, null, "guest", "guest");
+ conn.resume();
+ }
+ }
+
+ class TestSessionListener implements SessionListener
+ {
+ public void opened(Session s) {}
+ public void resumed(Session s) {}
+ public void exception(Session s, SessionException e) {}
+ public void message(Session s, MessageTransfer xfr)
+ {
+ synchronized (incoming)
+ {
+ incoming.add(xfr);
+ incoming.notifyAll();
+ }
+ s.processed(xfr);
+ }
+ public void closed(Session s) {}
+ }
public void testResumeNonemptyReplayBuffer() throws Exception
{
@@ -274,7 +311,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
Connection conn = new Connection();
conn.addConnectionListener(new FailoverConnectionListener());
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.connect("localhost", port, null, "guest", "guest");
Session ssn = conn.createSession(1);
ssn.setSessionListener(new TestSessionListener());
@@ -329,7 +365,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
startServer();
Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.addConnectionListener(new FailoverConnectionListener());
conn.connect("localhost", port, null, "guest", "guest");
Session ssn = conn.createSession(1);
@@ -352,7 +387,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
startServer();
Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.connect("localhost", port, null, "guest", "guest");
Session ssn = conn.createSession();
ssn.sessionFlush(EXPECTED);
@@ -366,7 +400,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
{
startServer();
Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.connect("localhost", port, null, "guest", "guest");
conn.connectionHeartbeat();
conn.close();
@@ -377,7 +410,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
startServer();
Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.connect("localhost", port, null, "guest", "guest");
Session ssn = conn.createSession();
send(ssn, "EXCP 0");
@@ -397,7 +429,6 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
startServer();
Connection conn = new Connection();
- conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()));
conn.connect("localhost", port, null, "guest", "guest");
Session ssn = conn.createSession();
send(ssn, "EXCP 0", true);
@@ -412,38 +443,4 @@ public class ConnectionTest extends QpidTestCase implements SessionListener
}
}
- class FailoverConnectionListener implements ConnectionListener
- {
- public void opened(Connection conn) {}
-
- public void exception(Connection conn, ConnectionException e)
- {
- throw e;
- }
-
- public void closed(Connection conn)
- {
- queue = true;
- conn.connect("localhost", port, null, "guest", "guest");
- conn.resume();
- }
- }
-
- class TestSessionListener implements SessionListener
- {
- public void opened(Session s) {}
- public void resumed(Session s) {}
- public void exception(Session s, SessionException e) {}
- public void message(Session s, MessageTransfer xfr)
- {
- synchronized (incoming)
- {
- incoming.add(xfr);
- incoming.notifyAll();
- }
-
- s.processed(xfr);
- }
- public void closed(Session s) {}
- }
}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/MockSender.java b/java/common/src/test/java/org/apache/qpid/transport/MockSender.java
deleted file mode 100644
index 4b38b7318a..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/MockSender.java
+++ /dev/null
@@ -1,47 +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.
- *
- */
-package org.apache.qpid.transport;
-
-import java.nio.ByteBuffer;
-
-public class MockSender implements Sender<ByteBuffer>
-{
-
- public void setIdleTimeout(int i)
- {
-
- }
-
- public void send(ByteBuffer msg)
- {
-
- }
-
- public void flush()
- {
-
- }
-
- public void close()
- {
-
- }
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java b/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java
deleted file mode 100644
index 5f1c1254a2..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/SessionTimeoutTest.java
+++ /dev/null
@@ -1,81 +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.
- */
-package org.apache.qpid.transport;
-
-import org.apache.qpid.configuration.ClientProperties;
-import org.apache.qpid.test.utils.QpidTestCase;
-
-
-public class SessionTimeoutTest extends QpidTestCase
-{
- public void testSessionTimeout()
- {
- try
- {
- long timeout = 1;
- setTestSystemProperty("qpid.sync_op_timeout", Long.toString(timeout));
- assertSessionTimeout(timeout);
- }
- finally
- {
- revertTestSystemProperties();
- }
- }
-
- public void testSessionTimeoutSetWith_amqj_default_syncwrite_timeout()
- {
- try
- {
- long timeout = 1;
- setTestSystemProperty("amqj.default_syncwrite_timeout", Long.toString(timeout));
- setTestSystemProperty("qpid.sync_op_timeout", null);
- assertSessionTimeout(timeout);
- }
- finally
- {
- revertTestSystemProperties();
- }
- }
-
- private void assertSessionTimeout(long timeout)
- {
- Session session = new TestSession(null, null, 0);
- long startTime = System.currentTimeMillis();
- try
- {
- session.awaitOpen();
- fail("SessionTimeoutException is expected!");
- }
- catch (SessionException e)
- {
- long elapsedTime = System.currentTimeMillis() - startTime;
- assertTrue("Expected timeout should happened in " + timeout + " ms but timeout occured in "
- + elapsedTime + " ms!", elapsedTime >= timeout && elapsedTime < ClientProperties.DEFAULT_SYNC_OPERATION_TIMEOUT);
- }
- }
-
- class TestSession extends Session
- {
- public TestSession(Connection connection, Binary name, long expiry)
- {
- super(connection, name, expiry);
- }
- }
-
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
deleted file mode 100644
index 8533c64fab..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java
+++ /dev/null
@@ -1,144 +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.
- *
- */
-package org.apache.qpid.transport;
-
-import java.net.BindException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.network.NetworkConnection;
-
-/**
- * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented,
- * so if this class is being used and some methods are to be used, then please update those.
- */
-public class TestNetworkConnection implements NetworkConnection
-{
- private String _remoteHost = "127.0.0.1";
- private String _localHost = "127.0.0.1";
- private int _port = 1;
- private SocketAddress _localAddress = null;
- private SocketAddress _remoteAddress = null;
- private final MockSender _sender;
-
- public TestNetworkConnection()
- {
- _sender = new MockSender();
- }
-
-
-
- public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory,
- NetworkTransportConfiguration config, SSLContextFactory sslFactory) throws BindException
- {
-
- }
-
- public SocketAddress getLocalAddress()
- {
- return (_localAddress != null) ? _localAddress : new InetSocketAddress(_localHost, _port);
- }
-
- public SocketAddress getRemoteAddress()
- {
- return (_remoteAddress != null) ? _remoteAddress : new InetSocketAddress(_remoteHost, _port);
- }
-
- public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkTransportConfiguration config,
- SSLContextFactory sslFactory) throws OpenException
- {
-
- }
-
- public void setMaxReadIdle(int idleTime)
- {
-
- }
-
- public void setMaxWriteIdle(int idleTime)
- {
-
- }
-
- public void close()
- {
-
- }
-
- public void flush()
- {
-
- }
-
- public void send(ByteBuffer msg)
- {
-
- }
-
- public void setIdleTimeout(int i)
- {
-
- }
-
- public void setPort(int port)
- {
- _port = port;
- }
-
- public int getPort()
- {
- return _port;
- }
-
- public void setLocalHost(String host)
- {
- _localHost = host;
- }
-
- public void setRemoteHost(String host)
- {
- _remoteHost = host;
- }
-
- public void setLocalAddress(SocketAddress address)
- {
- _localAddress = address;
- }
-
- public void setRemoteAddress(SocketAddress address)
- {
- _remoteAddress = address;
- }
-
- public Sender<ByteBuffer> getSender()
- {
- return _sender;
- }
-
- public void start()
- {
- }
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java
new file mode 100644
index 0000000000..957a7190ee
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkDriver.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport;
+
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.ssl.SSLContextFactory;
+
+/**
+ * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented,
+ * so if this class is being used and some methods are to be used, then please update those.
+ */
+public class TestNetworkDriver implements NetworkDriver
+{
+ private final ConcurrentMap attributes = new ConcurrentHashMap();
+ private String _remoteHost = "127.0.0.1";
+ private String _localHost = "127.0.0.1";
+ private int _port = 1;
+ private SocketAddress _localAddress = null;
+ private SocketAddress _remoteAddress = null;
+
+ public TestNetworkDriver()
+ {
+ }
+
+ public void bind(int port, InetAddress[] addresses, ProtocolEngineFactory protocolFactory,
+ NetworkDriverConfiguration config, SSLContextFactory sslFactory) throws BindException
+ {
+
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ return (_localAddress != null) ? _localAddress : new InetSocketAddress(_localHost, _port);
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ return (_remoteAddress != null) ? _remoteAddress : new InetSocketAddress(_remoteHost, _port);
+ }
+
+ public void open(int port, InetAddress destination, ProtocolEngine engine, NetworkDriverConfiguration config,
+ SSLContextFactory sslFactory) throws OpenException
+ {
+
+ }
+
+ public void setMaxReadIdle(int idleTime)
+ {
+
+ }
+
+ public void setMaxWriteIdle(int idleTime)
+ {
+
+ }
+
+ public void close()
+ {
+
+ }
+
+ public void flush()
+ {
+
+ }
+
+ public void send(ByteBuffer msg)
+ {
+
+ }
+
+ public void setIdleTimeout(int i)
+ {
+
+ }
+
+ public void setPort(int port)
+ {
+ _port = port;
+ }
+
+ public int getPort()
+ {
+ return _port;
+ }
+
+ public void setLocalHost(String host)
+ {
+ _localHost = host;
+ }
+
+ public void setRemoteHost(String host)
+ {
+ _remoteHost = host;
+ }
+
+ public void setLocalAddress(SocketAddress address)
+ {
+ _localAddress = address;
+ }
+
+ public void setRemoteAddress(SocketAddress address)
+ {
+ _remoteAddress = address;
+ }
+}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java
deleted file mode 100644
index 7039b904e3..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java
+++ /dev/null
@@ -1,157 +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.
- *
- */
-package org.apache.qpid.transport.network;
-
-
-import java.nio.ByteBuffer;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.TransportException;
-import org.apache.qpid.transport.network.io.IoNetworkTransport;
-
-public class TransportTest extends QpidTestCase
-{
-
-
-
- public void testDefaultGetOutgoingTransportForv0_8() throws Exception
- {
- final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0);
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof IoNetworkTransport);
- }
-
- public void testGloballyOverriddenOutgoingTransportForv0_8() throws Exception
- {
- setTestSystemProperty(Transport.QPID_TRANSPORT_PROPNAME, TestOutgoingNetworkTransport.class.getName());
-
- final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0);
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof TestOutgoingNetworkTransport);
- }
-
- public void testProtocolSpecificOverriddenOutgoingTransportForv0_8() throws Exception
- {
- setTestSystemProperty(Transport.QPID_TRANSPORT_V0_8_PROPNAME, TestOutgoingNetworkTransport.class.getName());
-
- final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v8_0);
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof TestOutgoingNetworkTransport);
- }
-
- public void testDefaultGetOutgoingTransportForv0_10() throws Exception
- {
- final OutgoingNetworkTransport networkTransport = Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10);
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof IoNetworkTransport);
- }
-
- public void testDefaultGetIncomingTransport() throws Exception
- {
- final IncomingNetworkTransport networkTransport = Transport.getIncomingTransportInstance();
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof IoNetworkTransport);
- }
-
- public void testOverriddenGetIncomingTransport() throws Exception
- {
- setTestSystemProperty(Transport.QPID_BROKER_TRANSPORT_PROPNAME, TestIncomingNetworkTransport.class.getName());
-
- final IncomingNetworkTransport networkTransport = Transport.getIncomingTransportInstance();
- assertNotNull(networkTransport);
- assertTrue(networkTransport instanceof TestIncomingNetworkTransport);
- }
-
- public void testInvalidOutgoingTransportClassName() throws Exception
- {
- setTestSystemProperty(Transport.QPID_TRANSPORT_PROPNAME, "invalid");
-
- try
- {
- Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10);
- fail("Should have failed to load the invalid class");
- }
- catch(TransportException te)
- {
- //expected, ignore
- }
- }
-
- public void testInvalidOutgoingTransportProtocolVersion() throws Exception
- {
- try
- {
- Transport.getOutgoingTransportInstance(new ProtocolVersion((byte)0, (byte)0));
- fail("Should have failed to load the transport for invalid protocol version");
- }
- catch(IllegalArgumentException iae)
- {
- //expected, ignore
- }
- }
-
- public static class TestOutgoingNetworkTransport implements OutgoingNetworkTransport
- {
-
- public void close()
- {
- throw new UnsupportedOperationException();
- }
-
- public NetworkConnection getConnection()
- {
- throw new UnsupportedOperationException();
- }
-
- public NetworkConnection connect(ConnectionSettings settings,
- Receiver<ByteBuffer> delegate, SSLContext sslContext)
- {
- throw new UnsupportedOperationException();
- }
- }
-
- public static class TestIncomingNetworkTransport implements IncomingNetworkTransport
- {
-
- public void close()
- {
- throw new UnsupportedOperationException();
- }
-
- public NetworkConnection getConnection()
- {
- throw new UnsupportedOperationException();
- }
-
- public void accept(NetworkTransportConfiguration config,
- ProtocolEngineFactory factory, SSLContext sslContext)
- {
- throw new UnsupportedOperationException();
- }
- }
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java
deleted file mode 100644
index e075681acb..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java
+++ /dev/null
@@ -1,92 +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.
- *
- */
-package org.apache.qpid.transport.network.io;
-
-import org.apache.qpid.transport.Binding;
-import org.apache.qpid.transport.TransportException;
-
-import java.io.IOException;
-
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketAddress;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * IoAcceptor
- *
- */
-
-public class IoAcceptor<E> extends Thread
-{
-
-
- private ServerSocket socket;
- private Binding<E,ByteBuffer> binding;
-
- public IoAcceptor(SocketAddress address, Binding<E,ByteBuffer> binding)
- throws IOException
- {
- socket = new ServerSocket();
- socket.setReuseAddress(true);
- socket.bind(address);
- this.binding = binding;
-
- setName(String.format("IoAcceptor - %s", socket.getInetAddress()));
- }
-
- /**
- Close the underlying ServerSocket if it has not already been closed.
- */
- public void close() throws IOException
- {
- if (!socket.isClosed())
- {
- socket.close();
- }
- }
-
- public IoAcceptor(String host, int port, Binding<E,ByteBuffer> binding)
- throws IOException
- {
- this(new InetSocketAddress(host, port), binding);
- }
-
- public void run()
- {
- while (true)
- {
- try
- {
- Socket sock = socket.accept();
- IoTransport<E> transport = new IoTransport<E>(sock, binding);
- }
- catch (IOException e)
- {
- throw new TransportException(e);
- }
- }
- }
-
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java
deleted file mode 100644
index 215c6d9931..0000000000
--- a/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java
+++ /dev/null
@@ -1,91 +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.
- */
-
-package org.apache.qpid.transport.network.io;
-
-import java.net.Socket;
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.transport.Binding;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.util.Logger;
-
-/**
- * This class provides a socket based transport using the java.io
- * classes.
- *
- * The following params are configurable via JVM arguments
- * TCP_NO_DELAY - amqj.tcpNoDelay
- * SO_RCVBUF - amqj.receiveBufferSize
- * SO_SNDBUF - amqj.sendBufferSize
- */
-public final class IoTransport<E>
-{
-
-
- private static final Logger log = Logger.get(IoTransport.class);
-
- private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024;
- private static int readBufferSize = Integer.getInteger
- ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
- private static int writeBufferSize = Integer.getInteger
- ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
-
- private Socket socket;
- private Sender<ByteBuffer> sender;
- private E endpoint;
- private IoReceiver receiver;
- private long timeout = 60000;
-
- IoTransport(Socket socket, Binding<E,ByteBuffer> binding)
- {
- this.socket = socket;
- setupTransport(socket, binding);
- }
-
- private void setupTransport(Socket socket, Binding<E, ByteBuffer> binding)
- {
- IoSender ios = new IoSender(socket, 2*writeBufferSize, timeout);
- ios.initiate();
-
- this.sender = ios;
- this.endpoint = binding.endpoint(sender);
- this.receiver = new IoReceiver(socket, binding.receiver(endpoint),
- 2*readBufferSize, timeout);
- this.receiver.initiate();
-
- ios.registerCloseListener(this.receiver);
- }
-
- public Sender<ByteBuffer> getSender()
- {
- return sender;
- }
-
- public IoReceiver getReceiver()
- {
- return receiver;
- }
-
- public Socket getSocket()
- {
- return socket;
- }
-
-}
diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java
new file mode 100644
index 0000000000..fc8e689ca4
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/transport/network/mina/MINANetworkDriverTest.java
@@ -0,0 +1,494 @@
+/*
+ *
+ * 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 org.apache.qpid.transport.network.mina;
+
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.OpenException;
+
+public class MINANetworkDriverTest extends TestCase
+{
+
+ private static final String TEST_DATA = "YHALOTHAR";
+ private static int TEST_PORT = 2323;
+ private NetworkDriver _server;
+ private NetworkDriver _client;
+ private CountingProtocolEngine _countingEngine; // Keeps a count of how many bytes it's read
+ private Exception _thrownEx;
+
+ @Override
+ public void setUp()
+ {
+ _server = new MINANetworkDriver();
+ _client = new MINANetworkDriver();
+ _thrownEx = null;
+ _countingEngine = new CountingProtocolEngine();
+ // increment the port to prevent tests clashing with each other when
+ // the port is in TIMED_WAIT state.
+ TEST_PORT++;
+ }
+
+ @Override
+ public void tearDown()
+ {
+ if (_server != null)
+ {
+ _server.close();
+ }
+
+ if (_client != null)
+ {
+ _client.close();
+ }
+ }
+
+ /**
+ * Tests that a socket can't be opened if a driver hasn't been bound
+ * to the port and can be opened if a driver has been bound.
+ * @throws BindException
+ * @throws UnknownHostException
+ * @throws OpenException
+ */
+ public void testBindOpen() throws BindException, UnknownHostException, OpenException
+ {
+ try
+ {
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ }
+ catch (OpenException e)
+ {
+ _thrownEx = e;
+ }
+
+ assertNotNull("Open should have failed since no engine bound", _thrownEx);
+
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ }
+
+ /**
+ * Tests that a socket can't be opened after a bound NetworkDriver has been closed
+ * @throws BindException
+ * @throws UnknownHostException
+ * @throws OpenException
+ */
+ public void testBindOpenCloseOpen() throws BindException, UnknownHostException, OpenException
+ {
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ _client.close();
+ _server.close();
+
+ try
+ {
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ }
+ catch (OpenException e)
+ {
+ _thrownEx = e;
+ }
+ assertNotNull("Open should have failed", _thrownEx);
+ }
+
+ /**
+ * Checks that the right exception is thrown when binding a NetworkDriver to an already
+ * existing socket.
+ */
+ public void testBindPortInUse()
+ {
+ try
+ {
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ }
+ catch (BindException e)
+ {
+ fail("First bind should not fail");
+ }
+
+ try
+ {
+ _client.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ }
+ catch (BindException e)
+ {
+ _thrownEx = e;
+ }
+ assertNotNull("Second bind should throw BindException", _thrownEx);
+ }
+
+ /**
+ * tests that bytes sent on a network driver are received at the other end
+ *
+ * @throws UnknownHostException
+ * @throws OpenException
+ * @throws InterruptedException
+ * @throws BindException
+ */
+ public void testSend() throws UnknownHostException, OpenException, InterruptedException, BindException
+ {
+ // Open a connection from a counting engine to an echo engine
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+
+ // Tell the counting engine how much data we're sending
+ _countingEngine.setNewLatch(TEST_DATA.getBytes().length);
+
+ // Send the data and wait for up to 2 seconds to get it back
+ _client.send(ByteBuffer.wrap(TEST_DATA.getBytes()));
+ _countingEngine.getLatch().await(2, TimeUnit.SECONDS);
+
+ // Check what we got
+ assertEquals("Wrong amount of data recieved", TEST_DATA.getBytes().length, _countingEngine.getReadBytes());
+ }
+
+ /**
+ * Opens a connection with a low read idle and check that it gets triggered
+ * @throws BindException
+ * @throws OpenException
+ * @throws UnknownHostException
+ *
+ */
+ public void testSetReadIdle() throws BindException, UnknownHostException, OpenException
+ {
+ // Open a connection from a counting engine to an echo engine
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ assertFalse("Reader should not have been idle", _countingEngine.getReaderHasBeenIdle());
+ _client.setMaxReadIdle(1);
+ sleepForAtLeast(1500);
+ assertTrue("Reader should have been idle", _countingEngine.getReaderHasBeenIdle());
+ }
+
+ /**
+ * Opens a connection with a low write idle and check that it gets triggered
+ * @throws BindException
+ * @throws OpenException
+ * @throws UnknownHostException
+ *
+ */
+ public void testSetWriteIdle() throws BindException, UnknownHostException, OpenException
+ {
+ // Open a connection from a counting engine to an echo engine
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ assertFalse("Reader should not have been idle", _countingEngine.getWriterHasBeenIdle());
+ _client.setMaxWriteIdle(1);
+ sleepForAtLeast(1500);
+ assertTrue("Reader should have been idle", _countingEngine.getWriterHasBeenIdle());
+ }
+
+
+ /**
+ * Creates and then closes a connection from client to server and checks that the server
+ * has its closed() method called. Then creates a new client and closes the server to check
+ * that the client has its closed() method called.
+ * @throws BindException
+ * @throws UnknownHostException
+ * @throws OpenException
+ */
+ public void testClosed() throws BindException, UnknownHostException, OpenException
+ {
+ // Open a connection from a counting engine to an echo engine
+ EchoProtocolEngineSingletonFactory factory = new EchoProtocolEngineSingletonFactory();
+ _server.bind(TEST_PORT, null, factory, null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ EchoProtocolEngine serverEngine = null;
+ while (serverEngine == null)
+ {
+ serverEngine = factory.getEngine();
+ if (serverEngine == null)
+ {
+ try
+ {
+ Thread.sleep(10);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+ assertFalse("Server should not have been closed", serverEngine.getClosed());
+ serverEngine.setNewLatch(1);
+ _client.close();
+ try
+ {
+ serverEngine.getLatch().await(2, TimeUnit.SECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ assertTrue("Server should have been closed", serverEngine.getClosed());
+
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ _countingEngine.setClosed(false);
+ assertFalse("Client should not have been closed", _countingEngine.getClosed());
+ _countingEngine.setNewLatch(1);
+ _server.close();
+ try
+ {
+ _countingEngine.getLatch().await(2, TimeUnit.SECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ assertTrue("Client should have been closed", _countingEngine.getClosed());
+ }
+
+ /**
+ * Create a connection and instruct the client to throw an exception when it gets some data
+ * and that the latch gets counted down.
+ * @throws BindException
+ * @throws UnknownHostException
+ * @throws OpenException
+ * @throws InterruptedException
+ */
+ public void testExceptionCaught() throws BindException, UnknownHostException, OpenException, InterruptedException
+ {
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+
+
+ assertEquals("Exception should not have been thrown", 1,
+ _countingEngine.getExceptionLatch().getCount());
+ _countingEngine.setErrorOnNextRead(true);
+ _countingEngine.setNewLatch(TEST_DATA.getBytes().length);
+ _client.send(ByteBuffer.wrap(TEST_DATA.getBytes()));
+ _countingEngine.getExceptionLatch().await(2, TimeUnit.SECONDS);
+ assertEquals("Exception should have been thrown", 0,
+ _countingEngine.getExceptionLatch().getCount());
+ }
+
+ /**
+ * Opens a connection and checks that the remote address is the one that was asked for
+ * @throws BindException
+ * @throws UnknownHostException
+ * @throws OpenException
+ */
+ public void testGetRemoteAddress() throws BindException, UnknownHostException, OpenException
+ {
+ _server.bind(TEST_PORT, null, new EchoProtocolEngineSingletonFactory(), null, null);
+ _client.open(TEST_PORT, InetAddress.getLocalHost(), _countingEngine, null, null);
+ assertEquals(new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT),
+ _client.getRemoteAddress());
+ }
+
+ private class EchoProtocolEngineSingletonFactory implements ProtocolEngineFactory
+ {
+ EchoProtocolEngine _engine = null;
+
+ public ProtocolEngine newProtocolEngine(NetworkDriver driver)
+ {
+ if (_engine == null)
+ {
+ _engine = new EchoProtocolEngine();
+ _engine.setNetworkDriver(driver);
+ }
+ return getEngine();
+ }
+
+ public EchoProtocolEngine getEngine()
+ {
+ return _engine;
+ }
+ }
+
+ public class CountingProtocolEngine implements ProtocolEngine
+ {
+
+ protected NetworkDriver _driver;
+ public ArrayList<ByteBuffer> _receivedBytes = new ArrayList<ByteBuffer>();
+ private int _readBytes;
+ private CountDownLatch _latch = new CountDownLatch(0);
+ private boolean _readerHasBeenIdle;
+ private boolean _writerHasBeenIdle;
+ private boolean _closed = false;
+ private boolean _nextReadErrors = false;
+ private CountDownLatch _exceptionLatch = new CountDownLatch(1);
+
+ public void closed()
+ {
+ setClosed(true);
+ _latch.countDown();
+ }
+
+ public void setErrorOnNextRead(boolean b)
+ {
+ _nextReadErrors = b;
+ }
+
+ public void setNewLatch(int length)
+ {
+ _latch = new CountDownLatch(length);
+ }
+
+ public long getReadBytes()
+ {
+ return _readBytes;
+ }
+
+ public SocketAddress getRemoteAddress()
+ {
+ if (_driver != null)
+ {
+ return _driver.getRemoteAddress();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public SocketAddress getLocalAddress()
+ {
+ if (_driver != null)
+ {
+ return _driver.getLocalAddress();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public long getWrittenBytes()
+ {
+ return 0;
+ }
+
+ public void readerIdle()
+ {
+ _readerHasBeenIdle = true;
+ }
+
+ public void setNetworkDriver(NetworkDriver driver)
+ {
+ _driver = driver;
+ }
+
+ public void writeFrame(AMQDataBlock frame)
+ {
+
+ }
+
+ public void writerIdle()
+ {
+ _writerHasBeenIdle = true;
+ }
+
+ public void exception(Throwable t)
+ {
+ _exceptionLatch.countDown();
+ }
+
+ public CountDownLatch getExceptionLatch()
+ {
+ return _exceptionLatch;
+ }
+
+ public void received(ByteBuffer msg)
+ {
+ // increment read bytes and count down the latch for that many
+ int bytes = msg.remaining();
+ _readBytes += bytes;
+ for (int i = 0; i < bytes; i++)
+ {
+ _latch.countDown();
+ }
+
+ // Throw an error if we've been asked too, but we can still count
+ if (_nextReadErrors)
+ {
+ throw new RuntimeException("Was asked to error");
+ }
+ }
+
+ public CountDownLatch getLatch()
+ {
+ return _latch;
+ }
+
+ public boolean getWriterHasBeenIdle()
+ {
+ return _writerHasBeenIdle;
+ }
+
+ public boolean getReaderHasBeenIdle()
+ {
+ return _readerHasBeenIdle;
+ }
+
+ public void setClosed(boolean _closed)
+ {
+ this._closed = _closed;
+ }
+
+ public boolean getClosed()
+ {
+ return _closed;
+ }
+
+ }
+
+ private class EchoProtocolEngine extends CountingProtocolEngine
+ {
+
+ public void received(ByteBuffer msg)
+ {
+ super.received(msg);
+ msg.rewind();
+ _driver.send(msg);
+ }
+ }
+
+ public static void sleepForAtLeast(long period)
+ {
+ long start = System.currentTimeMillis();
+ long timeLeft = period;
+ while (timeLeft > 0)
+ {
+ try
+ {
+ Thread.sleep(timeLeft);
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore it
+ }
+ timeLeft = period - (System.currentTimeMillis() - start);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java b/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java
index d6767eb9c0..7eba5f092e 100644
--- a/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java
+++ b/java/common/src/test/java/org/apache/qpid/util/FileUtilsTest.java
@@ -27,9 +27,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
-import java.io.InputStream;
import java.util.List;
-import java.util.Properties;
public class FileUtilsTest extends TestCase
{
@@ -184,20 +182,6 @@ public class FileUtilsTest extends TestCase
}
}
-
- /**
- * Helper method to create a temporary file with test content.
- *
- * @param test_data The data to store in the file
- *
- * @return The File reference
- */
- private File createTestFileInTmpDir(final String testData) throws Exception
- {
- final File tmpFile = File.createTempFile("test", "tmp");
-
- return createTestFile(tmpFile.getCanonicalPath(), testData);
- }
/**
* Helper method to create a test file with a string content
*
@@ -318,74 +302,8 @@ public class FileUtilsTest extends TestCase
// expected path
}
}
-
- /**
- * Tests that openFileOrDefaultResource can open a file on the filesystem.
- *
- */
- public void testOpenFileOrDefaultResourceOpensFileOnFileSystem() throws Exception
- {
- final File testFile = createTestFileInTmpDir("src=tmpfile");
- final String filenameOnFilesystem = testFile.getCanonicalPath();
- final String defaultResource = "org/apache/qpid/util/default.properties";
-
-
- final InputStream is = FileUtils.openFileOrDefaultResource(filenameOnFilesystem, defaultResource, this.getClass().getClassLoader());
- assertNotNull("Stream must not be null", is);
- final Properties p = new Properties();
- p.load(is);
- assertEquals("tmpfile", p.getProperty("src"));
- }
/**
- * Tests that openFileOrDefaultResource can open a file on the classpath.
- *
- */
- public void testOpenFileOrDefaultResourceOpensFileOnClasspath() throws Exception
- {
- final String mydefaultsResource = "org/apache/qpid/util/mydefaults.properties";
- final String defaultResource = "org/apache/qpid/util/default.properties";
-
-
- final InputStream is = FileUtils.openFileOrDefaultResource(mydefaultsResource, defaultResource, this.getClass().getClassLoader());
- assertNotNull("Stream must not be null", is);
- final Properties p = new Properties();
- p.load(is);
- assertEquals("mydefaults", p.getProperty("src"));
- }
-
- /**
- * Tests that openFileOrDefaultResource returns the default resource when file cannot be found.
- */
- public void testOpenFileOrDefaultResourceOpensDefaultResource() throws Exception
- {
- final File fileThatDoesNotExist = new File("/does/not/exist.properties");
- assertFalse("Test must not exist", fileThatDoesNotExist.exists());
-
- final String defaultResource = "org/apache/qpid/util/default.properties";
-
- final InputStream is = FileUtils.openFileOrDefaultResource(fileThatDoesNotExist.getCanonicalPath(), defaultResource, this.getClass().getClassLoader());
- assertNotNull("Stream must not be null", is);
- Properties p = new Properties();
- p.load(is);
- assertEquals("default.properties", p.getProperty("src"));
- }
-
- /**
- * Tests that openFileOrDefaultResource returns null if neither the file nor
- * the default resource can be found..
- */
- public void testOpenFileOrDefaultResourceReturnsNullWhenNeitherCanBeFound() throws Exception
- {
-
- final String mydefaultsResource = "org/apache/qpid/util/doesnotexisteiether.properties";
- final String defaultResource = "org/apache/qpid/util/doesnotexisteiether.properties";
-
- final InputStream is = FileUtils.openFileOrDefaultResource(mydefaultsResource, defaultResource, this.getClass().getClassLoader());
- assertNull("Stream must be null", is);
- }
-
- /**
* Given two lists of File arrays ensure they are the same length and all entries in Before are in After
*
* @param filesBefore File[]
diff --git a/java/common/src/test/java/org/apache/qpid/util/default.properties b/java/common/src/test/java/org/apache/qpid/util/default.properties
deleted file mode 100644
index cb522ea9a7..0000000000
--- a/java/common/src/test/java/org/apache/qpid/util/default.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Used by FileUtilsTests
-src=default.properties \ No newline at end of file
diff --git a/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties b/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties
deleted file mode 100644
index 6a49d927d0..0000000000
--- a/java/common/src/test/java/org/apache/qpid/util/mydefaults.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Used by FileUtilsTests
-src=mydefaults \ No newline at end of file
diff --git a/java/common/templates/method/version/MethodBodyClass.vm b/java/common/templates/method/version/MethodBodyClass.vm
index ce8a453eeb..a739110d70 100644
--- a/java/common/templates/method/version/MethodBodyClass.vm
+++ b/java/common/templates/method/version/MethodBodyClass.vm
@@ -46,11 +46,9 @@
package org.apache.qpid.framing.amqp_$version.getMajor()_$version.getMinor();
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
import java.util.HashMap;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.*;
import org.apache.qpid.AMQException;
@@ -58,7 +56,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version
{
private static final AMQMethodBodyInstanceFactory FACTORY_INSTANCE = new AMQMethodBodyInstanceFactory()
{
- public AMQMethodBody newInstance(DataInputStream in, long size) throws AMQFrameDecodingException, IOException
+ public AMQMethodBody newInstance(ByteBuffer in, long size) throws AMQFrameDecodingException
{
return new ${javaClassName}(in);
}
@@ -86,7 +84,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version
// Constructor
- public ${javaClassName}(DataInputStream buffer) throws AMQFrameDecodingException, IOException
+ public ${javaClassName}(ByteBuffer buffer) throws AMQFrameDecodingException
{
#foreach( $field in $method.ConsolidatedFields )
_$field.Name = read$field.getEncodingType()( buffer );
@@ -171,7 +169,7 @@ public class ${javaClassName} extends AMQMethodBody_$version.getMajor()_$version
return size;
}
- public void writeMethodPayload(DataOutputStream buffer) throws IOException
+ public void writeMethodPayload(ByteBuffer buffer)
{
#foreach( $field in $method.ConsolidatedFields )
write$field.getEncodingType()( buffer, _$field.Name );
diff --git a/java/common/templates/model/MethodRegistryClass.vm b/java/common/templates/model/MethodRegistryClass.vm
index 8258175ce7..759e5e4a42 100644
--- a/java/common/templates/model/MethodRegistryClass.vm
+++ b/java/common/templates/model/MethodRegistryClass.vm
@@ -30,8 +30,7 @@
package org.apache.qpid.framing;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
@@ -54,8 +53,8 @@ public abstract class MethodRegistry
#end
- public abstract AMQMethodBody convertToBody(DataInputStream in, long size)
- throws AMQFrameDecodingException, IOException;
+ public abstract AMQMethodBody convertToBody(ByteBuffer in, long size)
+ throws AMQFrameDecodingException;
public abstract int getMaxClassId();
@@ -102,4 +101,4 @@ public abstract class MethodRegistry
public abstract ProtocolVersionMethodConverter getProtocolVersionMethodConverter();
-}
+} \ No newline at end of file
diff --git a/java/common/templates/model/version/MethodRegistryClass.vm b/java/common/templates/model/version/MethodRegistryClass.vm
index 79553f7748..277605e34b 100644
--- a/java/common/templates/model/version/MethodRegistryClass.vm
+++ b/java/common/templates/model/version/MethodRegistryClass.vm
@@ -35,33 +35,32 @@ import org.apache.qpid.protocol.AMQConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.DataInputStream;
-import java.io.IOException;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
public class MethodRegistry_$version.getMajor()_$version.getMinor() extends MethodRegistry
{
-
+
private static final Logger _log = LoggerFactory.getLogger(MethodRegistry.class);
- private ProtocolVersionMethodConverter _protocolVersionConverter = new MethodConverter_$version.getMajor()_$version.getMinor()();
-
-#set( $specificModel = $model.asSingleVersionModel() )
-
-
-#set( $maxClassId = $specificModel.getMaximumClassId()+1 )
- private final AMQMethodBodyInstanceFactory[][] _factories = new AMQMethodBodyInstanceFactory[$maxClassId][];
-
- public MethodRegistry_$version.getMajor()_$version.getMinor()()
- {
- this(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor()));
+ private ProtocolVersionMethodConverter _protocolVersionConverter = new MethodConverter_$version.getMajor()_$version.getMinor()();
+
+#set( $specificModel = $model.asSingleVersionModel() )
+
+
+#set( $maxClassId = $specificModel.getMaximumClassId()+1 )
+ private final AMQMethodBodyInstanceFactory[][] _factories = new AMQMethodBodyInstanceFactory[$maxClassId][];
+
+ public MethodRegistry_$version.getMajor()_$version.getMinor()()
+ {
+ this(new ProtocolVersion((byte)$version.getMajor(),(byte)$version.getMinor()));
}
-
- public MethodRegistry_$version.getMajor()_$version.getMinor()(ProtocolVersion pv)
- {
- super(pv);
+
+ public MethodRegistry_$version.getMajor()_$version.getMinor()(ProtocolVersion pv)
+ {
+ super(pv);
#foreach( $amqpClass in $specificModel.getClassList() )
#set( $amqpClassNameFirstChar = $amqpClass.getName().substring(0,1) )
#set( $amqpClassNameFirstCharU = $amqpClassNameFirstChar.toUpperCase() )
@@ -69,30 +68,30 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth
- // Register method body instance factories for the $amqpClassNameUpperCamel class.
+ // Register method body instance factories for the $amqpClassNameUpperCamel class.
-#set( $maxMethodId = $amqpClass.getMaximumMethodId()+1 )
+#set( $maxMethodId = $amqpClass.getMaximumMethodId()+1 )
_factories[$amqpClass.getClassId()] = new AMQMethodBodyInstanceFactory[$maxMethodId];
-
+
#foreach( $amqpMethod in $amqpClass.getMethodList() )
#set( $amqpMethodNameFirstChar = $amqpMethod.getName().substring(0,1) )
#set( $amqpMethodNameFirstCharU = $amqpMethodNameFirstChar.toUpperCase() )
#set( $amqpMethodNameUpperCamel = "$amqpMethodNameFirstCharU$amqpMethod.getName().substring(1)" )
_factories[$amqpClass.getClassId()][$amqpMethod.getMethodId()] = ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl.getFactory();
-#end
-
+#end
+
#end
-
-
- }
+
+
+ }
- public AMQMethodBody convertToBody(DataInputStream in, long size)
- throws AMQFrameDecodingException, IOException
+ public AMQMethodBody convertToBody(ByteBuffer in, long size)
+ throws AMQFrameDecodingException
{
- int classId = in.readUnsignedShort();
- int methodId = in.readUnsignedShort();
-
+ int classId = in.getUnsignedShort();
+ int methodId = in.getUnsignedShort();
+
AMQMethodBodyInstanceFactory bodyFactory;
try
{
@@ -138,15 +137,15 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth
public int getMaxClassId()
- {
- return $specificModel.getMaximumClassId();
- }
+ {
+ return $specificModel.getMaximumClassId();
+ }
public int getMaxMethodId(int classId)
- {
- return _factories[classId].length - 1;
- }
-
+ {
+ return _factories[classId].length - 1;
+ }
+
#foreach( $amqpClass in $specificModel.getClassList() )
@@ -154,12 +153,12 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth
#set( $amqpClassNameFirstCharU = $amqpClassNameFirstChar.toUpperCase() )
#set( $amqpClassNameUpperCamel = "$amqpClassNameFirstCharU$amqpClass.getName().substring(1)" )
-
+
#foreach( $amqpMethod in $amqpClass.getMethodList() )
#set( $amqpMethodNameFirstChar = $amqpMethod.getName().substring(0,1) )
#set( $amqpMethodNameFirstCharU = $amqpMethodNameFirstChar.toUpperCase() )
#set( $amqpMethodNameUpperCamel = "$amqpMethodNameFirstCharU$amqpMethod.getName().substring(1)" )
- public ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body create${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body(
+ public ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body create${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}Body(
#foreach( $field in $amqpMethod.FieldList )
#if( $velocityCount == $amqpMethod.getFieldList().size() )
final $field.NativeType $field.Name
@@ -167,9 +166,9 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth
final $field.NativeType $field.Name,
#end
#end
- )
+ )
{
- return new ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl(
+ return new ${amqpClassNameUpperCamel}${amqpMethodNameUpperCamel}BodyImpl(
#foreach( $field in $amqpMethod.FieldList )
#if( $velocityCount == $amqpMethod.getFieldList().size() )
$field.Name
@@ -177,18 +176,18 @@ public class MethodRegistry_$version.getMajor()_$version.getMinor() extends Meth
$field.Name,
#end
#end
- );
+ );
}
-#end
-
+#end
+
#end
-
-
+
+
public ProtocolVersionMethodConverter getProtocolVersionMethodConverter()
{
return _protocolVersionConverter;
- }
+ }
}
diff --git a/java/ivy.xml b/java/ivy.xml
deleted file mode 100644
index 1399db5248..0000000000
--- a/java/ivy.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
-
- <info organisation="org/apache" module="qpid" revision="0.13"/>
-
- <publications xmlns:e="urn:ant.apache.org:ivy-extras">
- <artifact name="qpid-client" type="pom" ext="pom"/>
- <artifact name="qpid-client" type="pom.asc" ext="pom.asc"/>
- <artifact name="qpid-client" type="jar" ext="jar"/>
- <artifact name="qpid-client" type="jar.asc" ext="jar.asc"/>
- <artifact name="qpid-client" type="source" ext="jar" e:classifier="sources"/>
- <artifact name="qpid-client" type="source.asc" ext="jar.asc" e:classifier="sources"/>
- <artifact name="qpid-common" type="pom" ext="pom"/>
- <artifact name="qpid-common" type="pom.asc" ext="pom.asc"/>
- <artifact name="qpid-common" type="jar" ext="jar"/>
- <artifact name="qpid-common" type="jar.asc" ext="jar.asc"/>
- <artifact name="qpid-common" type="source" ext="jar" e:classifier="sources"/>
- <artifact name="qpid-common" type="source.asc" ext="jar.asc" e:classifier="sources"/>
- </publications>
-
- <dependencies/>
-</ivy-module>
diff --git a/java/ivysettings-nexus.xml b/java/ivysettings-nexus.xml
deleted file mode 100644
index 1d9c393e23..0000000000
--- a/java/ivysettings-nexus.xml
+++ /dev/null
@@ -1,30 +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.
--->
-<ivysettings>
- <credentials host="${nexus.host}" realm="Sonatype Nexus Repository Manager" username="${nexus.user}" passwd="${nexus.password}"/>
- <caches defaultCacheDir="${user.home}/.ivy2/cache"/>
- <resolvers>
- <ibiblio name="public" m2compatible="true"/>
- <url name="nexus">
- <artifact pattern="${nexus.upload.url}/[organisation]/[module]/[artifact]/[revision]/[artifact]-[revision](-[classifier]).[ext]" />
- </url>
- </resolvers>
- <modules>
- <module organisation="${nexus.organisation}" name="qpid" resolver="nexus"/>
- </modules>
- <settings defaultResolver="public"/>
-</ivysettings>
diff --git a/java/lib/backport-util-concurrent-2.2.jar b/java/lib/backport-util-concurrent-2.2.jar
new file mode 100644
index 0000000000..20a16877bd
--- /dev/null
+++ b/java/lib/backport-util-concurrent-2.2.jar
Binary files differ
diff --git a/java/lib/bdbstore/README.txt b/java/lib/bdbstore/README.txt
deleted file mode 100644
index 80adb199bf..0000000000
--- a/java/lib/bdbstore/README.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-The BDB JE jar must be downloaded into this directory in order to allow the optional bdbstore module to be built against it.
-
-*NOTE* The BDB JE library is licensed under the Sleepycat Licence [1], which is not compatible with the Apache Lience v2.0. As a result, the BDB JE library is not distributed with the project, and the optional bdbstore module is not compiled by default.
-
-The jar file may be downloaded by either:
-
- Seperately running the following command from the qpid/java/bdbstore dir: ant download-bdb
-
- OR
-
- Adding -Ddownload-bdb=true to your regular build command
-
-
-[1] http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-086837.html
diff --git a/java/lib/commons-pool-1.4.jar b/java/lib/commons-pool-1.4.jar
new file mode 100644
index 0000000000..d6bc185450
--- /dev/null
+++ b/java/lib/commons-pool-1.4.jar
Binary files differ
diff --git a/java/lib/core-3.1.1.jar b/java/lib/core-3.1.1.jar
new file mode 100644
index 0000000000..ae0b635867
--- /dev/null
+++ b/java/lib/core-3.1.1.jar
Binary files differ
diff --git a/java/lib/geronimo-servlet_2.5_spec-1.2.jar b/java/lib/geronimo-servlet_2.5_spec-1.2.jar
new file mode 100644
index 0000000000..00a2010036
--- /dev/null
+++ b/java/lib/geronimo-servlet_2.5_spec-1.2.jar
Binary files differ
diff --git a/java/lib/ivy/README.txt b/java/lib/ivy/README.txt
deleted file mode 100644
index f8a01f39b4..0000000000
--- a/java/lib/ivy/README.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Folder used to store Ivy libs for use in publishing Maven artifacts.
-
-Ivy must be downloaded and extracted into this directory if it is not available in the Ant lib dir.
-
-File may be downloaded in 2 ways:
-1. By running the following command from the qpid/java dir:
- ant -buildfile upload.xml download-ivy
-2. Manually download and extract via http://ant.apache.org/ivy.
-
-Note for method 1 you may also have to set proxy server settings in advance, eg:
-export ANT_OPTS="-Dhttp.proxyHost=<hostname> -Dhttp.proxyPort=<port>"
diff --git a/java/lib/javassist.jar b/java/lib/javassist.jar
new file mode 100644
index 0000000000..a6bde77812
--- /dev/null
+++ b/java/lib/javassist.jar
Binary files differ
diff --git a/java/lib/jline-0.9.94.jar b/java/lib/jline-0.9.94.jar
new file mode 100644
index 0000000000..dafca7c46e
--- /dev/null
+++ b/java/lib/jline-0.9.94.jar
Binary files differ
diff --git a/java/lib/jsp-2.1.jar b/java/lib/jsp-2.1.jar
new file mode 100644
index 0000000000..bfdb566c13
--- /dev/null
+++ b/java/lib/jsp-2.1.jar
Binary files differ
diff --git a/java/lib/jsp-api-2.1.jar b/java/lib/jsp-api-2.1.jar
new file mode 100644
index 0000000000..ac3a7a8f7e
--- /dev/null
+++ b/java/lib/jsp-api-2.1.jar
Binary files differ
diff --git a/java/lib/junit-4.4.jar b/java/lib/junit-4.4.jar
new file mode 100644
index 0000000000..649b0b327f
--- /dev/null
+++ b/java/lib/junit-4.4.jar
Binary files differ
diff --git a/java/lib/mina-core-1.0.1.jar b/java/lib/mina-core-1.0.1.jar
new file mode 100755
index 0000000000..f12067aa90
--- /dev/null
+++ b/java/lib/mina-core-1.0.1.jar
Binary files differ
diff --git a/java/lib/mina-filter-ssl-1.0.1.jar b/java/lib/mina-filter-ssl-1.0.1.jar
new file mode 100755
index 0000000000..53738e6498
--- /dev/null
+++ b/java/lib/mina-filter-ssl-1.0.1.jar
Binary files differ
diff --git a/java/lib/muse-core-2.2.0.jar b/java/lib/muse-core-2.2.0.jar
new file mode 100644
index 0000000000..674ec26f58
--- /dev/null
+++ b/java/lib/muse-core-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-platform-mini-2.2.0.jar b/java/lib/muse-platform-mini-2.2.0.jar
new file mode 100644
index 0000000000..1782083231
--- /dev/null
+++ b/java/lib/muse-platform-mini-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-util-2.2.0.jar b/java/lib/muse-util-2.2.0.jar
new file mode 100644
index 0000000000..8bb7348180
--- /dev/null
+++ b/java/lib/muse-util-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-util-qname-2.2.0.jar b/java/lib/muse-util-qname-2.2.0.jar
new file mode 100644
index 0000000000..af0c76ece4
--- /dev/null
+++ b/java/lib/muse-util-qname-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-util-xml-2.2.0.jar b/java/lib/muse-util-xml-2.2.0.jar
new file mode 100644
index 0000000000..016b303c62
--- /dev/null
+++ b/java/lib/muse-util-xml-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsa-soap-2.2.0.jar b/java/lib/muse-wsa-soap-2.2.0.jar
new file mode 100644
index 0000000000..f83322beac
--- /dev/null
+++ b/java/lib/muse-wsa-soap-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-muws-adv-api-2.2.0.jar b/java/lib/muse-wsdm-muws-adv-api-2.2.0.jar
new file mode 100644
index 0000000000..ba3bf4aa40
--- /dev/null
+++ b/java/lib/muse-wsdm-muws-adv-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-muws-adv-impl-2.2.0.jar b/java/lib/muse-wsdm-muws-adv-impl-2.2.0.jar
new file mode 100644
index 0000000000..780a20f474
--- /dev/null
+++ b/java/lib/muse-wsdm-muws-adv-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-muws-api-2.2.0.jar b/java/lib/muse-wsdm-muws-api-2.2.0.jar
new file mode 100644
index 0000000000..2a0cab200a
--- /dev/null
+++ b/java/lib/muse-wsdm-muws-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-muws-impl-2.2.0.jar b/java/lib/muse-wsdm-muws-impl-2.2.0.jar
new file mode 100644
index 0000000000..a9954bb27e
--- /dev/null
+++ b/java/lib/muse-wsdm-muws-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-wef-api-2.2.0.jar b/java/lib/muse-wsdm-wef-api-2.2.0.jar
new file mode 100644
index 0000000000..e9206b2eb3
--- /dev/null
+++ b/java/lib/muse-wsdm-wef-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsdm-wef-impl-2.2.0.jar b/java/lib/muse-wsdm-wef-impl-2.2.0.jar
new file mode 100644
index 0000000000..12856123b1
--- /dev/null
+++ b/java/lib/muse-wsdm-wef-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsn-api-2.2.0.jar b/java/lib/muse-wsn-api-2.2.0.jar
new file mode 100644
index 0000000000..72b70a043d
--- /dev/null
+++ b/java/lib/muse-wsn-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsn-impl-2.2.0.jar b/java/lib/muse-wsn-impl-2.2.0.jar
new file mode 100644
index 0000000000..615f2a5f62
--- /dev/null
+++ b/java/lib/muse-wsn-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsrf-api-2.2.0.jar b/java/lib/muse-wsrf-api-2.2.0.jar
new file mode 100644
index 0000000000..efa36e9fbc
--- /dev/null
+++ b/java/lib/muse-wsrf-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsrf-impl-2.2.0.jar b/java/lib/muse-wsrf-impl-2.2.0.jar
new file mode 100644
index 0000000000..a19b1e7149
--- /dev/null
+++ b/java/lib/muse-wsrf-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsrf-rmd-2.2.0.jar b/java/lib/muse-wsrf-rmd-2.2.0.jar
new file mode 100644
index 0000000000..e03676cad8
--- /dev/null
+++ b/java/lib/muse-wsrf-rmd-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsx-api-2.2.0.jar b/java/lib/muse-wsx-api-2.2.0.jar
new file mode 100644
index 0000000000..1533d8dc59
--- /dev/null
+++ b/java/lib/muse-wsx-api-2.2.0.jar
Binary files differ
diff --git a/java/lib/muse-wsx-impl-2.2.0.jar b/java/lib/muse-wsx-impl-2.2.0.jar
new file mode 100644
index 0000000000..9ce78ef0b7
--- /dev/null
+++ b/java/lib/muse-wsx-impl-2.2.0.jar
Binary files differ
diff --git a/java/lib/poms/backport-util-concurrent-2.2.xml b/java/lib/poms/backport-util-concurrent-2.2.xml
new file mode 100644
index 0000000000..6df4cfca40
--- /dev/null
+++ b/java/lib/poms/backport-util-concurrent-2.2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.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.
+-->
+<dep>
+ <groupId>backport-util-concurrent</groupId>
+ <artifactId>backport-util-concurrent</artifactId>
+ <version>2.2</version>
+</dep>
diff --git a/java/lib/poms/mina-core-1.0.1.xml b/java/lib/poms/mina-core-1.0.1.xml
new file mode 100644
index 0000000000..87fb96999f
--- /dev/null
+++ b/java/lib/poms/mina-core-1.0.1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.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.
+-->
+<dep>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
+ <version>1.0.1</version>
+</dep>
diff --git a/java/lib/poms/mina-filter-ssl-1.0.1.xml b/java/lib/poms/mina-filter-ssl-1.0.1.xml
new file mode 100644
index 0000000000..ae41d7ed63
--- /dev/null
+++ b/java/lib/poms/mina-filter-ssl-1.0.1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.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.
+-->
+<dep>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-filter-ssl</artifactId>
+ <version>1.0.1</version>
+</dep>
diff --git a/java/lib/start.jar b/java/lib/start.jar
new file mode 100644
index 0000000000..63685df7cc
--- /dev/null
+++ b/java/lib/start.jar
Binary files differ
diff --git a/java/lib/wsdl4j-1.6.1.jar b/java/lib/wsdl4j-1.6.1.jar
new file mode 100644
index 0000000000..67a35fcbaa
--- /dev/null
+++ b/java/lib/wsdl4j-1.6.1.jar
Binary files differ
diff --git a/java/lib/xercesImpl-2.8.1.jar b/java/lib/xercesImpl-2.8.1.jar
new file mode 100644
index 0000000000..3b351f6e2b
--- /dev/null
+++ b/java/lib/xercesImpl-2.8.1.jar
Binary files differ
diff --git a/java/lib/xml-apis-1.3.03.jar b/java/lib/xml-apis-1.3.03.jar
new file mode 100644
index 0000000000..b338fb6693
--- /dev/null
+++ b/java/lib/xml-apis-1.3.03.jar
Binary files differ
diff --git a/java/management/agent/build.xml b/java/management/agent/build.xml
new file mode 100644
index 0000000000..a410c74c1f
--- /dev/null
+++ b/java/management/agent/build.xml
@@ -0,0 +1,27 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<project name="QMF Agent" default="build">
+
+ <property name="module.depends" value="common client"/>
+
+ <import file="../../module.xml"/>
+
+</project>
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/Agent.java b/java/management/agent/src/main/java/org/apache/qpid/agent/Agent.java
new file mode 100644
index 0000000000..b1a4a8c93e
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/Agent.java
@@ -0,0 +1,706 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.jms.BytesMessage;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.binding.BindingContext;
+import org.apache.qpid.agent.binding.BindingUtils;
+import org.apache.qpid.agent.binding.ClassBinding;
+import org.apache.qpid.agent.binding.BindingException;
+import org.apache.qpid.agent.binding.MethodBinding;
+import org.apache.qpid.agent.binding.ParameterBinding;
+import org.apache.qpid.agent.binding.PropertyBinding;
+import org.apache.qpid.agent.binding.TypeBinding;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * The main class for interacting with the QMF bus. Objects which are to be
+ * managed can be registered with the agent, as can classes to be exposed via
+ * the schema.
+ */
+public class Agent implements MessageListener
+{
+ // The following are settings to configure the Agent
+ protected AMQConnection connection;
+ protected boolean sessionTransacted = false;
+ protected int acknowledgeMode = Session.AUTO_ACKNOWLEDGE;
+ protected String label;
+ protected UUID systemId;
+ // this list holds the objects until the agent is started
+ protected List managedObjects = new ArrayList();
+ protected List registeredClasses = new ArrayList();
+ // The following instance variables are not
+ // able to be set by the end user.
+ protected Session session;
+ protected MessageProducer prod;
+ protected MessageConsumer cons;
+ protected Queue reply;
+ protected BindingContext bctx = new BindingContext();
+ protected Map<Long, ManagedObject> objects = new Hashtable<Long, ManagedObject>();
+ protected long bbank;
+ protected long abank;
+ protected static final Log log = LogFactory.getLog(Agent.class);
+ protected volatile boolean inside = false;
+ protected ClassLoader classLoader = null;
+
+ public Agent()
+ {
+ systemId = UUID.randomUUID();
+ log.debug(String.format("Agent with uid %s created", systemId
+ .toString()));
+ }
+
+ public Agent(String label, UUID systemId)
+ {
+ this.systemId = systemId;
+ this.label = label;
+ log.debug(String.format("Agent with name %s and uid %s created", label,
+ systemId.toString()));
+ }
+
+ public void register(ManagedObject managedObject)
+ {
+ Class managedClass = managedObject.getObjectClass();
+ long id = managedObject.getId();
+ ClassBinding cb = bctx.register(managedClass);
+ managedObject.setManagedClassName(cb.getName());
+ managedObject.setManagedPackageName(cb.getPackage());
+ log.debug(String.format(
+ "Added managed object id '%d' for package '%s' class '%s'", id,
+ managedObject.getManagedPackageName(), managedObject
+ .getManagedClassName()));
+ objects.put(id, managedObject);
+ managedObjects.add(managedObject);
+ }
+
+ public void registerClass(Class cls)
+ {
+ bctx.register(cls);
+ if (!registeredClasses.contains(cls))
+ {
+ registeredClasses.add(cls);
+ }
+ }
+
+ /**
+ * Stops the agents connection to the bus
+ */
+ public void stop()
+ {
+ try
+ {
+ cons.close();
+ prod.close();
+ connection.stop();
+ connection.close();
+ session.close();
+ } catch (JMSException e)
+ {
+ log.error("Exception:", e);
+ }
+ }
+
+ /**
+ * Starts up the agent. Many bean containers may call this by default which
+ * aids in deployment
+ */
+ public void start()
+ {
+ log.debug(String.format("Agent with uid %s and name %s starting",
+ systemId.toString(), label));
+ for (Object clsName : registeredClasses.toArray())
+ {
+ try
+ {
+ Class cls = null;
+ if (String.class.isAssignableFrom(clsName.getClass()))
+ {
+ cls = getClass(clsName.toString());
+ } else
+ {
+ cls = (Class) clsName;
+ }
+ this.registerClass(cls);
+ } catch (Exception e)
+ {
+ log.error("Could not register class " + clsName);
+ }
+ }
+ for (Object obj : managedObjects.toArray())
+ {
+ this.register((ManagedObject) obj);
+ }
+ try
+ {
+ session = connection.createSession(sessionTransacted,
+ acknowledgeMode);
+ reply = session
+ .createQueue(String
+ .format(
+ "direct://amq.direct//%s-%s?exclusive='True'&autodelete='True'",
+ label, systemId));
+ cons = session.createConsumer(reply);
+ cons.setMessageListener(this);
+ prod = session.createProducer(null);
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ attachRequest(label, systemId);
+ try
+ {
+ connection.start();
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ }
+
+ /**
+ * Send an event object to the bus
+ */
+ public void raiseEvent(Object value, EventSeverity sev)
+ {
+ log.debug(String.format("Sending event of class %s with Severity %s",
+ value.getClass(), sev.ordinal()));
+ BBEncoder enc = this.init('e');
+ ClassBinding cb = bctx.getClassBinding(value.getClass());
+ String pkg = cb.getPackage();
+ String cls = cb.getName();
+ enc.writeStr8(pkg);
+ enc.writeStr8(cls);
+ enc.writeBin128(cb.getSchemaHash());
+ long now = System.currentTimeMillis() * 1000000;
+ enc.writeInt64(now);
+ enc.writeUint8((short) sev.ordinal());
+ for (PropertyBinding p : cb.getProperties())
+ {
+ p.getType().encode(enc, BindingUtils.get(p, value));
+ }
+ send(
+ String.format("console.event.%d.%d.%s.%s", bbank, abank, pkg,
+ cls), enc);
+ }
+
+ public void onMessage(Message message)
+ {
+ if (inside)
+ {
+ new Throwable().printStackTrace();
+ }
+ inside = true;
+ Decoder dec = readBody(message);
+ Destination replyTo;
+ try
+ {
+ replyTo = message.getJMSReplyTo();
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ byte[] magic = dec.readBytes(3);
+ if (magic[0] != 'A' || magic[1] != 'M' || magic[2] != '2')
+ {
+ throw new AgentException("bad magic: " + new String(magic));
+ }
+ short op = dec.readUint8();
+ long seq = dec.readUint32();
+ log.debug("Message recieved: " + (char) op);
+ switch (op)
+ {
+ case 'a':
+ this.handleAgentAttach(seq, replyTo, dec);
+ break;
+ case 'G':
+ this.handleGetQuery(seq, replyTo, dec);
+ break;
+ case 'M':
+ this.handleMethodRequest(seq, replyTo, dec);
+ break;
+ case 'S':
+ this.handleSchemaRequest(seq, replyTo, dec);
+ break;
+ case 'x':
+ // TODO
+ break;
+ default:
+ throw new IllegalArgumentException("opcode: " + ((char) op));
+ }
+ inside = false;
+ }
+
+ protected ClassBinding getClassBinding(ManagedObject mobj)
+ {
+ return bctx.getClassBinding(mobj.getObjectClass());
+ }
+
+ private byte[] ensure(int capacity, byte[] body, int size)
+ {
+ if (capacity > body.length)
+ {
+ byte[] copy = new byte[capacity];
+ System.arraycopy(body, 0, copy, 0, size);
+ body = copy;
+ }
+ return body;
+ }
+
+ private Decoder readBody(Message message)
+ {
+ BytesMessage msg = (BytesMessage) message;
+ BBDecoder dec = new BBDecoder();
+ byte[] buf = new byte[1024];
+ byte[] body = new byte[1024];
+ int size = 0;
+ int n;
+ try
+ {
+ while ((n = msg.readBytes(buf)) > 0)
+ {
+ body = ensure(size + n, body, size);
+ System.arraycopy(buf, 0, body, size, n);
+ size += n;
+ }
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ dec.init(ByteBuffer.wrap(body, 0, size));
+ return dec;
+ }
+
+ protected void handleAgentAttach(long seq, Destination replyTo, Decoder dec)
+ {
+ log.debug("Agent Attach Message");
+ bbank = dec.readUint32();
+ abank = dec.readUint32();
+ try
+ {
+ MessageConsumer mc = session
+ .createConsumer(session
+ .createQueue(String
+ .format(
+ "management://qpid.management//%s-%s?routingkey='agent.%d.%d'&exclusive='True'&autodelete='True'",
+ label, systemId, bbank, abank)));
+ mc.setMessageListener(this);
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ for (String packageName : bctx.getPackages())
+ {
+ packageIndication(packageName);
+ }
+ for (ClassBinding cb : bctx.getAllBindings())
+ {
+ classIndication(cb);
+ }
+ for (ManagedObject mo : objects.values())
+ {
+ content('i', seq, null, mo);
+ }
+ }
+
+ protected void handleMethodRequest(long seq, Destination replyTo,
+ Decoder dec)
+ {
+ dec.readUint64(); // first part of object-id
+ long id = dec.readUint64();
+ ManagedObject mo = objects.get(id);
+ if (mo == null)
+ {
+ methodResponse(seq, replyTo, 1, String.format(
+ "no such object: 0x%x", id));
+ } else
+ {
+ dec.readStr8(); // pkg
+ dec.readStr8(); // cls
+ dec.readBin128(); // hash
+ String mname = dec.readStr8();
+ ClassBinding cls = getClassBinding(mo);
+ MethodBinding method = cls.getMethod(mname);
+ if (method == null)
+ {
+ methodResponse(seq, replyTo, 2, String.format(
+ "no such method: %s", mname));
+ } else
+ {
+ log.trace("Handle method: " + method.getName());
+ List<ParameterBinding> params = method.getInParameters();
+ Object[] args = new Object[params.size()];
+ int idx = 0;
+ for (ParameterBinding p : params)
+ {
+ TypeBinding typeBinding = p.getType();
+ log
+ .trace(String
+ .format(
+ "Decoding parameter with type %s ref package %s ref class %s ",
+ typeBinding.getCode(), typeBinding
+ .getRefPackage(),
+ typeBinding.getRefClass()));
+ args[idx++] = typeBinding.decode(dec);
+ log.trace("Done");
+ }
+ try
+ {
+ Object[] result = mo.invoke(method, args);
+ methodResponse(seq, replyTo, 0, null, method, result);
+ } catch (BindingException ex)
+ {
+ log
+ .error(
+ String
+ .format(
+ "An exception occured invoking method %s. Stack trace sent to console.",
+ method.getName()), ex);
+ StringWriter str = new StringWriter();
+ PrintWriter writer = new PrintWriter(str);
+ ex.printStackTrace(writer);
+ writer.flush();
+ methodResponse(seq, replyTo, 7, str.toString());
+ }
+ log.trace("Done with method: " + method.getName());
+ }
+ }
+ }
+
+ protected void handleGetQuery(long seq, Destination replyTo, Decoder dec)
+ {
+ Map<String, Object> data = dec.readMap();
+ if (data.containsKey("_objectid"))
+ {
+ long objId = (Long) data.get("_objectid");
+ log.debug("Get Request message for object id " + objId);
+ ManagedObject mo = objects.get(objId);
+ if (mo == null)
+ {
+ methodResponse(seq, replyTo, 1, String.format(
+ "no such object: 0x%x", objId));
+ } else
+ {
+ content('g', seq, replyTo, mo);
+ }
+ } else if (data.containsKey("_class"))
+ {
+ String className = (String) data.get("_class");
+ String packageName = (String) data.get("_package");
+ log.debug(String.format(
+ "Get Request message for package '%s' class '%s'",
+ packageName, className));
+ for (ManagedObject mo : objects.values())
+ {
+ if (mo.getManagedClassName().equals(className))
+ {
+ if ((packageName == null) || packageName.equals("")
+ || packageName.equals(mo.getManagedPackageName()))
+ {
+ content('g', seq, replyTo, mo);
+ }
+ }
+ }
+ } else
+ {
+ for (ManagedObject mo : objects.values())
+ {
+ content('g', seq, replyTo, mo);
+ }
+ }
+ complete(seq, replyTo);
+ }
+
+ protected void handleSchemaRequest(long seq, Destination replyTo,
+ Decoder dec)
+ {
+ String pkg = dec.readStr8();
+ String cls = dec.readStr8();
+ log.debug(String.format(
+ "SchemaRequest message for package '%s' class '%s'", pkg, cls));
+ ClassBinding cb = bctx.getClassBinding(pkg, cls);
+ if (cb == null)
+ {
+ throw new AgentException("no such class: " + pkg + ", " + cls);
+ }
+ schemaResponse(seq, cb);
+ }
+
+ protected BBEncoder init(char opcode)
+ {
+ return init(opcode, 0);
+ }
+
+ protected BBEncoder init(char opcode, long sequence)
+ {
+ BBEncoder enc = new BBEncoder(1024);
+ enc.init();
+ enc.writeUint8((short) 'A');
+ enc.writeUint8((short) 'M');
+ enc.writeUint8((short) '2');
+ enc.writeUint8((short) opcode);
+ enc.writeUint32(sequence);
+ return enc;
+ }
+
+ protected void send(BBEncoder enc)
+ {
+ send("broker", enc);
+ }
+
+ protected void send(Destination dest, BBEncoder enc)
+ {
+ try
+ {
+ byte[] buf = new byte[1024];
+ BytesMessage msg = session.createBytesMessage();
+ ByteBuffer slice = enc.segment();
+ while (slice.hasRemaining())
+ {
+ int n = Math.min(buf.length, slice.remaining());
+ slice.get(buf, 0, n);
+ msg.writeBytes(buf, 0, n);
+ }
+ msg.setJMSReplyTo(reply);
+ // ???: I assume this is thread safe.
+ prod.send(dest, msg);
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ }
+
+ protected void send(String routingKey, BBEncoder enc)
+ {
+ try
+ {
+ send(session
+ .createQueue("management://qpid.management//?routingkey='"
+ + routingKey + "'"), enc);
+ } catch (JMSException e)
+ {
+ throw new AgentException(e);
+ }
+ }
+
+ protected void attachRequest(String label, UUID systemId)
+ {
+ BBEncoder enc = init('A');
+ enc.writeStr8(label);
+ enc.writeUuid(systemId);
+ enc.writeUint32(0);
+ enc.writeUint32(0);
+ send(enc);
+ }
+
+ protected void packageIndication(String pkg)
+ {
+ BBEncoder enc = init('p');
+ enc.writeStr8(pkg);
+ send(enc);
+ }
+
+ protected void classIndication(ClassBinding cb)
+ {
+ BBEncoder enc = init('q');
+ enc.writeUint8(cb.getKind());
+ enc.writeStr8(cb.getPackage());
+ enc.writeStr8(cb.getName());
+ enc.writeBin128(cb.getSchemaHash()); // schema hash?
+ send(enc);
+ }
+
+ protected void schemaResponse(long seq, ClassBinding cb)
+ {
+ BBEncoder enc = init('s', seq);
+ cb.encode(enc);
+ send(enc);
+ }
+
+ protected void content(char c, long seq, Destination dest, ManagedObject mo)
+ {
+ BBEncoder enc = init(c, seq);
+ ClassBinding cb = getClassBinding(mo);
+ String pkg = cb.getPackage();
+ String cls = cb.getName();
+ enc.writeStr8(pkg);
+ enc.writeStr8(cls);
+ enc.writeBin128(cb.getSchemaHash());
+ long now = System.currentTimeMillis() * 1000000;
+ enc.writeUint64(now);
+ enc.writeUint64(now);
+ enc.writeUint64(0);
+ enc.writeUint64(0x0000FFFFFFFFFFFFL & ((bbank << 28) | abank));
+ enc.writeUint64(mo.getId());
+ for (PropertyBinding p : cb.getProperties())
+ {
+ p.getType().encode(enc, mo.get(p));
+ }
+ if (dest == null)
+ {
+ send(String.format("console.obj.%d.%d.%s.%s", bbank, abank, pkg,
+ cls), enc);
+ } else
+ {
+ send(dest, enc);
+ }
+ }
+
+ protected void complete(long seq, Destination dest)
+ {
+ BBEncoder enc = init('z', seq);
+ enc.writeUint32(0);
+ enc.writeStr8("");
+ send(dest, enc);
+ }
+
+ protected void methodResponse(long seq, Destination dest, int status,
+ String text)
+ {
+ methodResponse(seq, dest, status, text, null, null);
+ }
+
+ protected void methodResponse(long seq, Destination dest, int status,
+ String text, MethodBinding method, Object[] result)
+ {
+ BBEncoder enc = init('m', seq);
+ enc.writeUint32(status);
+ enc.writeStr16(text == null ? "" : text);
+ if (method != null)
+ {
+ int idx = 0;
+ for (ParameterBinding p : method.getOutParameters())
+ {
+ p.getType().encode(enc, result[idx++]);
+ }
+ }
+ send(dest, enc);
+ }
+
+ protected Class getClass(String className)
+ {
+ try
+ {
+ if (classLoader != null)
+ {
+ return classLoader.loadClass(className);
+ } else
+ {
+ return Class.forName(className);
+ }
+ } catch (ClassNotFoundException e)
+ {
+ throw new AgentException(String.format(
+ "No class named %s was found", className), e);
+ }
+ }
+
+ public String getLabel()
+ {
+ return label;
+ }
+
+ public void setLabel(String label)
+ {
+ this.label = label;
+ }
+
+ public AMQConnection getConnection()
+ {
+ return connection;
+ }
+
+ public void setConnection(AMQConnection connection)
+ {
+ this.connection = connection;
+ }
+
+ public boolean isSessionTransacted()
+ {
+ return sessionTransacted;
+ }
+
+ public void setSessionTransacted(boolean sessionTransacted)
+ {
+ this.sessionTransacted = sessionTransacted;
+ }
+
+ public void setManagedObjects(List objectList)
+ {
+ this.managedObjects = objectList;
+ }
+
+ public List getManagedObjects()
+ {
+ return managedObjects;
+ }
+
+ public void setRegisteredClasses(List objectList)
+ {
+ this.registeredClasses = objectList;
+ }
+
+ public List getRegisteredClasses()
+ {
+ return this.registeredClasses;
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ String broker = args[0];
+ String name = args[1];
+ String url = String.format(
+ "amqp://guest:guest@/?brokerlist='tcp://%s'", broker);
+ AMQConnection conn = new AMQConnection(url);
+ Agent agent = new Agent(name, UUID.randomUUID());
+ agent.setConnection(conn);
+ for (int i = 2; i < args.length; i++)
+ {
+ Class<?> cls = Class.forName(args[i]);
+ agent.register(new ManagedPOJO(cls.newInstance()));
+ }
+ agent.start();
+ while (true)
+ {
+ Thread.sleep(1000);
+ }
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/AgentException.java b/java/management/agent/src/main/java/org/apache/qpid/agent/AgentException.java
new file mode 100644
index 0000000000..410cad2d8c
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/AgentException.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.agent;
+
+/**
+ * AgentException
+ *
+ */
+public class AgentException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public AgentException(String msg)
+ {
+ super(msg);
+ }
+
+ public AgentException(Throwable t)
+ {
+ super(t);
+ }
+
+ public AgentException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/EventSeverity.java b/java/management/agent/src/main/java/org/apache/qpid/agent/EventSeverity.java
new file mode 100644
index 0000000000..28735286c4
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/EventSeverity.java
@@ -0,0 +1,27 @@
+package org.apache.qpid.agent;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+public enum EventSeverity
+{
+ EMERGENCY, ALERT, CRIT, ERROR, WARN, NOTICE, INFO, DEBUG
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedEJB.java b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedEJB.java
new file mode 100644
index 0000000000..60efb1e284
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedEJB.java
@@ -0,0 +1,138 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.agent;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.binding.BindingUtils;
+import org.apache.qpid.agent.binding.MethodBinding;
+import org.apache.qpid.agent.binding.PropertyBinding;
+
+/**
+ * Wrapper classe for adding EJBS which are to be managed by the QMF Agent. The
+ * jndi location and the public interface to exposed are used to generate the
+ * schema.
+ */
+public class ManagedEJB extends ManagedObjectBase
+{
+ private Log log = LogFactory.getLog(ManagedEJB.class);
+ protected String className;
+ protected String jndiLocation;
+ protected ClassLoader classLoader;
+
+ protected Object getEJB()
+ {
+ ClassLoader previousCL = Thread.currentThread().getContextClassLoader();
+ try
+ {
+ if (classLoader != null)
+ {
+ Thread.currentThread().setContextClassLoader(classLoader);
+ }
+ InitialContext ctx = new InitialContext();
+ return ctx.lookup(jndiLocation);
+ } catch (NamingException e)
+ {
+ throw new AgentException("Error looking up EJB at " + jndiLocation,
+ e);
+ } finally
+ {
+ Thread.currentThread().setContextClassLoader(previousCL);
+ }
+ }
+
+ @Override
+ public Object get(PropertyBinding property)
+ {
+ return BindingUtils.get(property, this.getEJB());
+ }
+
+ @Override
+ public long getId()
+ {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public Class getObjectClass()
+ {
+ try
+ {
+ if (classLoader != null)
+ {
+ log.debug("Using the classloader");
+ return classLoader.loadClass(className);
+ } else
+ {
+ return Class.forName(className);
+ }
+ } catch (ClassNotFoundException e)
+ {
+ throw new AgentException(String.format(
+ "No class named %s was found", className), e);
+ }
+ }
+
+ @Override
+ public Object[] invoke(MethodBinding method, Object... args)
+ {
+ return BindingUtils.invoke(method, this.getEJB(), args);
+ }
+
+ @Override
+ public void set(PropertyBinding property, Object value)
+ {
+ BindingUtils.set(property, value, this.getEJB());
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public void setClassName(String className)
+ {
+ this.className = className;
+ }
+
+ public String getJndiLocation()
+ {
+ return jndiLocation;
+ }
+
+ public void setJndiLocation(String jndiLocation)
+ {
+ this.jndiLocation = jndiLocation;
+ }
+
+ public ClassLoader getClassLoader()
+ {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader cloader)
+ {
+ this.classLoader = cloader;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObject.java b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObject.java
new file mode 100644
index 0000000000..aa3bbf3894
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObject.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import org.apache.qpid.agent.binding.MethodBinding;
+import org.apache.qpid.agent.binding.PropertyBinding;
+
+/**
+ * Objects which are to be managed and controlled by the QMF Agent.
+ */
+public interface ManagedObject
+{
+ public abstract long getId();
+
+ public abstract Class getObjectClass();
+
+ public abstract Object get(PropertyBinding property);
+
+ public abstract void set(PropertyBinding property, Object value);
+
+ public abstract Object[] invoke(MethodBinding method, Object... args);
+
+ public abstract String getName();
+
+ public abstract void setName(String name);
+
+ public String getManagedClassName();
+
+ public String getManagedPackageName();
+
+ public void setManagedClassName(String aName);
+
+ public void setManagedPackageName(String aName);
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObjectBase.java b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObjectBase.java
new file mode 100644
index 0000000000..51789ae11f
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedObjectBase.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.agent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.binding.MethodBinding;
+import org.apache.qpid.agent.binding.PropertyBinding;
+
+public abstract class ManagedObjectBase implements ManagedObject
+{
+ private static Log log = LogFactory.getLog(ManagedObjectBase.class);
+ protected String name;
+ protected String managedClassName;
+ protected String managedPackageName;
+
+ public abstract long getId();
+
+ public abstract Object get(PropertyBinding property);
+
+ public abstract void set(PropertyBinding property, Object value);
+
+ public abstract Object[] invoke(MethodBinding method, Object... args);
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getManagedClassName()
+ {
+ return managedClassName;
+ }
+
+ public void setManagedClassName(String managedClassName)
+ {
+ this.managedClassName = managedClassName;
+ }
+
+ public String getManagedPackageName()
+ {
+ return managedPackageName;
+ }
+
+ public void setManagedPackageName(String managedPackageName)
+ {
+ this.managedPackageName = managedPackageName;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedPOJO.java b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedPOJO.java
new file mode 100644
index 0000000000..94d9b9d0a8
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/ManagedPOJO.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.binding.BindingUtils;
+import org.apache.qpid.agent.binding.MethodBinding;
+import org.apache.qpid.agent.binding.PropertyBinding;
+
+/**
+ * Wrapper classe for adding POJOS which are to be managed by the QMF Agent.
+ */
+public class ManagedPOJO extends ManagedObjectBase implements ManagedObject
+{
+ private Log log = LogFactory.getLog(ManagedPOJO.class);
+ private Object managed;
+
+ public ManagedPOJO()
+ {
+ super();
+ }
+
+ public ManagedPOJO(Object managed)
+ {
+ super();
+ this.setManaged(managed);
+ }
+
+ @Override
+ public long getId()
+ {
+ if (managed == null)
+ {
+ throw new AgentException("The managed object is null");
+ }
+ return System.identityHashCode(managed);
+ }
+
+ public Class getObjectClass()
+ {
+ return managed.getClass();
+ }
+
+ public Object getManaged()
+ {
+ return managed;
+ }
+
+ public void setManaged(Object managed)
+ {
+ this.managed = managed;
+ }
+
+ @Override
+ public Object get(PropertyBinding property)
+ {
+ return BindingUtils.get(property, managed);
+ }
+
+ @Override
+ public Object[] invoke(MethodBinding method, Object... args)
+ {
+ return BindingUtils.invoke(method, managed, args);
+ }
+
+ @Override
+ public void set(PropertyBinding property, Object value)
+ {
+ BindingUtils.set(property, value, managed);
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFAgent.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFAgent.java
new file mode 100644
index 0000000000..b9fcf40fc1
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFAgent.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Target(ElementType.FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFAgent
+{
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFEvent.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFEvent.java
new file mode 100644
index 0000000000..314f2a7e68
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFEvent.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Tells the QMF Agent that this object will be passed as a QMF event. This will
+ * cause only properties to be sent across the wire.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFEvent
+{
+ String eventName();
+
+ String packageName();
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFHide.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFHide.java
new file mode 100644
index 0000000000..db6cb0412f
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFHide.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Causes the property which is annotated to not be added to the QMF schema when
+ * it is built.
+ */
+@Target(ElementType.METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFHide
+{
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFObject.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFObject.java
new file mode 100644
index 0000000000..7d1713cdbe
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFObject.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Tells the QMF Agent that this object will be a managed object. This will
+ * allow users to query for it, as well as invoke methods on it.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFObject
+{
+ String className();
+
+ String packageName();
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFProperty.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFProperty.java
new file mode 100644
index 0000000000..f309fa95b5
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFProperty.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Controls the QMF schema which is generated for this property.
+ */
+@Target(ElementType.FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFProperty
+{
+ boolean optional() default false;
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFSeeAlso.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFSeeAlso.java
new file mode 100644
index 0000000000..bb9b87805d
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFSeeAlso.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Augements the schema generation process to look for known subclasses of a
+ * type. Modeled after the JAXB @XMLSeeAlso.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFSeeAlso
+{
+ Class[] value();
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFType.java b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFType.java
new file mode 100644
index 0000000000..8da1e15124
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/annotations/QMFType.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Tells the QMF Agent that this object will be a type only This will cause only
+ * properties to be sent across the wire.
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+@Documented
+public @interface QMFType
+{
+ String className();
+
+ String packageName();
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingContext.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingContext.java
new file mode 100644
index 0000000000..a60178e8b9
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingContext.java
@@ -0,0 +1,213 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.annotations.QMFEvent;
+import org.apache.qpid.agent.annotations.QMFObject;
+import org.apache.qpid.agent.annotations.QMFSeeAlso;
+import org.apache.qpid.agent.annotations.QMFType;
+
+/**
+ * Contains the mappings from java classes to QMF schema and back. There is one
+ * context per agent, and it contains all the metadata.
+ */
+public class BindingContext
+{
+ private static Log log = LogFactory.getLog(BindingContext.class);
+ private Map<Key, ClassBinding> classes = new Hashtable<Key, ClassBinding>();
+ private ArrayList<String> packages = new ArrayList<String>();
+
+ static class Key
+ {
+ String packageName = "";
+ String className = "";
+ boolean object = false;
+
+ @Override
+ public int hashCode()
+ {
+ return (packageName + "." + className).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return (obj instanceof Key
+ && (((Key) obj).packageName.equals(packageName)) && (((Key) obj).className
+ .equals(className)));
+ }
+ }
+
+ public BindingContext()
+ {
+ Key key = new Key();
+ key.className = "Object";
+ key.packageName = "org.apache.qmf";
+ key.object = false;
+ ClassBinding cb = new ClassBinding("org.apache.qmf", "Object",
+ Object.class, false, this);
+ classes.put(key, cb);
+ packages.add("org.apache.qmf");
+ }
+
+ public ClassBinding getClassBinding(Class clazz)
+ {
+ return classes.get(getClassKey(clazz));
+ }
+
+ public ClassBinding getClassBinding(String packageName, String className)
+ {
+ Key key = new Key();
+ key.packageName = packageName;
+ key.className = className;
+ return classes.get(key);
+ }
+
+ public ClassBinding register(Class cls)
+ {
+ String name = cls.getName();
+ ClassBinding cb = getClassBinding(cls);
+ if (cb == null)
+ {
+ Key key = getClassKey(cls);
+ // Create and store the internal representations
+ if (cls.isEnum())
+ {
+ cb = new EnumBinding(key.packageName, key.className, cls,
+ key.object, this);
+ } else
+ {
+ cb = new ClassBinding(key.packageName, key.className, cls,
+ key.object, this);
+ }
+ log.debug(String.format(
+ "Added class binding '%s' in package %s for class %s'",
+ key.className, key.packageName, cls.getCanonicalName()));
+ classes.put(key, cb);
+ if (!packages.contains(key.packageName))
+ {
+ packages.add(key.packageName);
+ }
+ // Parse the methods after adding the class to avoid recursion
+ cb.parse();
+ // See if there are other classes which should be looked at
+ QMFSeeAlso seeAlso = (QMFSeeAlso) cls
+ .getAnnotation(QMFSeeAlso.class);
+ if (seeAlso != null)
+ {
+ for (Class seeAlsoCls : seeAlso.value())
+ {
+ this.register(seeAlsoCls);
+ }
+ }
+ }
+ return cb;
+ }
+
+ public TypeBinding getTypeBinding(Class cls)
+ {
+ // Look for a built in type
+ TypeBinding type = QMFTypeBinding.forClass(cls);
+ // Have we seen it before?
+ if (type == null)
+ {
+ type = this.getClassBinding(cls);
+ }
+ if ((type == null) && List.class.isAssignableFrom(cls))
+ {
+ type = new ListBinding(this, cls);
+ }
+ if ((type == null) && Map.class.isAssignableFrom(cls))
+ {
+ type = new MapBinding(this, cls);
+ }
+ // Add it, but since we have not seen it before do not expose methods
+ if (type == null)
+ {
+ type = this.register(cls);
+ }
+ return type;
+ }
+
+ // FIXME: Need to store these keys off so we dont create alot of objects
+ protected Key getClassKey(Class cls)
+ {
+ Key key = new Key();
+ QMFObject objAnnotation = (QMFObject) cls
+ .getAnnotation(QMFObject.class);
+ if (objAnnotation != null)
+ {
+ key.className = objAnnotation.className();
+ key.packageName = objAnnotation.packageName();
+ key.object = true;
+ } else
+ {
+ QMFType typeAnnotation = (QMFType) cls.getAnnotation(QMFType.class);
+ if (typeAnnotation != null)
+ {
+ key.className = typeAnnotation.className();
+ key.packageName = typeAnnotation.packageName();
+ } else
+ {
+ QMFEvent eventAnnotation = (QMFEvent) cls
+ .getAnnotation(QMFEvent.class);
+ if (eventAnnotation != null)
+ {
+ key.className = eventAnnotation.eventName();
+ key.packageName = eventAnnotation.packageName();
+ } else
+ {
+ // If this is Object, we return the fake
+ // object value
+ if (cls == Object.class)
+ {
+ key.className = "Object";
+ key.packageName = "org.apache.qmf";
+ } else
+ {
+ String name = cls.getName();
+ int lastDot = name.lastIndexOf('.');
+ key.className = name.substring(lastDot + 1);
+ key.packageName = name.substring(0, lastDot);
+ }
+ }
+ }
+ }
+ return key;
+ }
+
+ public ArrayList<String> getPackages()
+ {
+ return packages;
+ }
+
+ public Collection<ClassBinding> getAllBindings()
+ {
+ return classes.values();
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingException.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingException.java
new file mode 100644
index 0000000000..f8e436290c
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingException.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+/**
+ * ManagedException
+ *
+ */
+public class BindingException extends RuntimeException
+{
+ private static final long serialVersionUID = -7350845525748113340L;
+
+ public BindingException(Throwable t)
+ {
+ super(t);
+ }
+
+ public BindingException()
+ {
+ super();
+ }
+
+ public BindingException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public BindingException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingUtils.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingUtils.java
new file mode 100644
index 0000000000..14f3fda0f1
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/BindingUtils.java
@@ -0,0 +1,137 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class BindingUtils
+{
+ private static Log log = LogFactory.getLog(BindingUtils.class);
+
+ public static Object get(PropertyBinding property, Object managed)
+ {
+ String name = property.getName();
+ return get(name, managed);
+ }
+
+ public static void set(PropertyBinding property, Object value,
+ Object managed)
+ {
+ String name = property.getName();
+ TypeBinding type = property.getType();
+ try
+ {
+ Method meth = managed.getClass().getMethod(accessor("set", name),
+ type.getJavaClass());
+ meth.invoke(managed, value);
+ } catch (NoSuchMethodException e)
+ {
+ throw new BindingException(e);
+ } catch (IllegalAccessException e)
+ {
+ throw new BindingException(e);
+ } catch (InvocationTargetException e)
+ {
+ throw new BindingException(e.getTargetException());
+ }
+ }
+
+ public static Object[] invoke(MethodBinding method, Object managed,
+ Object... args)
+ {
+ log.debug(String.format("Invoking %s on %s", method.getName(), managed
+ .getClass()));
+ List<ParameterBinding> in = method.getInParameters();
+ List<ParameterBinding> out = method.getOutParameters();
+ Class<?>[] classes = new Class<?>[in.size()];
+ int idx = 0;
+ for (ParameterBinding p : in)
+ {
+ classes[idx++] = p.getType().getJavaClass();
+ }
+ Object result;
+ try
+ {
+ Method meth = managed.getClass().getMethod(method.getName(),
+ classes);
+ result = meth.invoke(managed, args);
+ } catch (NoSuchMethodException e)
+ {
+ throw new BindingException(e);
+ } catch (IllegalAccessException e)
+ {
+ throw new BindingException(e);
+ } catch (InvocationTargetException e)
+ {
+ throw new BindingException(e.getTargetException());
+ }
+ Object[] results = new Object[out.size()];
+ // XXX: need better way to distinguish this case
+ if (out.size() == 1 && out.get(0).getName().equals("result"))
+ {
+ results[0] = result;
+ } else
+ {
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i] = get(out.get(i).getName(), result);
+ }
+ }
+ return results;
+ }
+
+ public static String accessor(String pfx, String property)
+ {
+ return pfx + Character.toUpperCase(property.charAt(0))
+ + property.substring(1);
+ }
+
+ public static Object get(String name, Object obj)
+ {
+ Object returnValue = null;
+ try
+ {
+ BeanInfo info = Introspector.getBeanInfo(obj.getClass());
+ PropertyDescriptor[] pds = info.getPropertyDescriptors();
+ for (PropertyDescriptor pd : pds)
+ {
+ if (pd.getName().equals(name))
+ {
+ Method getMethod = pd.getReadMethod();
+ returnValue = getMethod.invoke(obj);
+ break;
+ }
+ }
+ } catch (Exception e)
+ {
+ throw new BindingException(e);
+ }
+ return returnValue;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ClassBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ClassBinding.java
new file mode 100644
index 0000000000..469939a52f
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ClassBinding.java
@@ -0,0 +1,601 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.annotations.QMFEvent;
+import org.apache.qpid.agent.annotations.QMFObject;
+import org.apache.qpid.agent.annotations.QMFProperty;
+import org.apache.qpid.agent.annotations.QMFSeeAlso;
+import org.apache.qpid.agent.annotations.QMFType;
+import org.apache.qpid.agent.annotations.QMFHide;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Binding information from a custom java class to a QMF schema
+ */
+public class ClassBinding implements TypeBinding
+{
+ private static final Log log = LogFactory.getLog(ClassBinding.class);
+
+ private static enum MethodType
+ {
+ READ_ONLY, READ_WRITE, METHOD, IGNORE
+ }
+
+ protected boolean exposeBehaviour = true;
+ protected String pkg;
+ protected BindingContext bctx;
+ protected String name;
+ protected ArrayList<PropertyBinding> properties = new ArrayList<PropertyBinding>();
+ protected ArrayList<MethodBinding> methods = new ArrayList<MethodBinding>();
+ protected Map<String, MethodBinding> methodsByName = new HashMap<String, MethodBinding>();
+ protected Class javaClass;
+ protected short kind = 1;
+ protected byte hash[] = null;
+ protected ClassBinding superType = null;
+
+ public ClassBinding(String pkg, String name, Class cls,
+ boolean exposeBehaviour, BindingContext bctx)
+ {
+ this.pkg = pkg;
+ this.name = name;
+ this.bctx = bctx;
+ this.javaClass = cls;
+ this.exposeBehaviour = exposeBehaviour;
+ }
+
+ protected MethodType classify(Class<?> cls, Method m)
+ {
+ String name = m.getName();
+ MethodType returnValue = MethodType.METHOD;
+ String propPrefixes[] =
+ { "get", "is" };
+ for (String prefix : propPrefixes)
+ {
+ if (name.startsWith(prefix) && m.getParameterTypes().length == 0)
+ {
+ try
+ {
+ Class<?> type = m.getReturnType();
+ Method setter = cls.getMethod("set"
+ + name.substring(prefix.length()), type);
+ returnValue = MethodType.READ_WRITE;
+ } catch (NoSuchMethodException e)
+ {
+ returnValue = MethodType.READ_ONLY;
+ }
+ break;
+ }
+ }
+ return returnValue;
+ }
+
+ protected String property(Method m)
+ {
+ String name = m.getName();
+ String propPrefixes[] =
+ { "get", "is" };
+ for (String prefix : propPrefixes)
+ {
+ if (name.startsWith(prefix) && m.getParameterTypes().length == 0)
+ {
+ String sfx = name.substring(prefix.length());
+ return Character.toLowerCase(sfx.charAt(0)) + sfx.substring(1);
+ }
+ }
+ // If we got here, it is n invalid property
+ throw new IllegalArgumentException("" + m);
+ }
+
+ protected ArrayList<Method> getMethods(Class cls)
+ {
+ ArrayList returnValue = new ArrayList();
+ ArrayList nameList = new ArrayList();
+ if ((cls != null) && (!cls.equals(Object.class)))
+ {
+ for (Method m : cls.getDeclaredMethods())
+ {
+ if (m.getAnnotation(QMFHide.class) == null)
+ // && (!Modifier.isAbstract(m.getModifiers())))
+ {
+ returnValue.add(m);
+ nameList.add(m.getName());
+ }
+ }
+ // Look at the superclass, if it is also a
+ // QMF object then stop.
+ if (!this.hasQMFSupertype(cls))
+ {
+ for (Method m : this.getMethods(cls.getSuperclass()))
+ {
+ if (!nameList.contains(m.getName()))
+ {
+ returnValue.add(m);
+ nameList.add(m.getName());
+ }
+ }
+ }
+ }
+ return returnValue;
+ }
+
+ protected boolean hasQMFSupertype(Class cls)
+ {
+ boolean returnValue = false;
+ Class superType = cls.getSuperclass();
+ if (superType != null)
+ {
+ if ((superType.getAnnotation(QMFObject.class) != null)
+ || (superType.getAnnotation(QMFType.class) != null)
+ || (superType.getAnnotation(QMFSeeAlso.class) != null)
+ || (superType.getAnnotation(QMFEvent.class) != null))
+ {
+ returnValue = true;
+ }
+ }
+ return returnValue;
+ }
+
+ protected boolean isOptional(Method m, TypeBinding type)
+ {
+ boolean returnValue = false;
+ // Look for the annotaiton first
+ QMFProperty ann = m.getAnnotation(QMFProperty.class);
+ if (ann != null)
+ {
+ returnValue = ann.optional();
+ } else
+ {
+ returnValue = type.optionalDefault();
+ }
+ return returnValue;
+ }
+
+ public ClassBinding parse()
+ {
+ log.debug(String.format(
+ "Parsing class binding '%s' for package '%s' from class %s",
+ name, pkg, javaClass.getName()));
+ for (Method m : this.getMethods(javaClass))
+ {
+ String mname = m.getName();
+ Class<?> type = m.getReturnType();
+ switch (classify(javaClass, m))
+ {
+ case READ_ONLY:
+ TypeBinding tb = bctx.getTypeBinding(type);
+ boolean optional = isOptional(m, tb);
+ properties.add(new PropertyBinding(property(m), tb,
+ PropertyBinding.READ_ONLY, optional));
+ break;
+ case READ_WRITE:
+ TypeBinding tbnd = bctx.getTypeBinding(type);
+ boolean opt = isOptional(m, tbnd);
+ properties.add(new PropertyBinding(property(m), tbnd,
+ PropertyBinding.READ_WRITE, opt));
+ break;
+ case METHOD:
+ // Only expose methods if told to
+ if (exposeBehaviour)
+ {
+ List<ParameterBinding> params = new ArrayList<ParameterBinding>();
+ int arg = 0;
+ for (Class pcls : m.getParameterTypes())
+ {
+ params.add(new ParameterBinding("arg" + arg++, bctx
+ .getTypeBinding(pcls), true, false));
+ }
+ if (type != void.class)
+ {
+ params.add(new ParameterBinding("result", bctx
+ .getTypeBinding(type), false, true));
+ }
+ methods.add(new MethodBinding(mname, params));
+ }
+ break;
+ case IGNORE:
+ break;
+ }
+ }
+ for (MethodBinding m : methods)
+ {
+ methodsByName.put(m.getName(), m);
+ }
+ QMFEvent eventAnnotation = (QMFEvent) javaClass
+ .getAnnotation(QMFEvent.class);
+ if (eventAnnotation != null)
+ {
+ kind = 2; // Event Type
+ }
+ // if (this.hasQMFSupertype(javaClass)) {
+ if ((javaClass.getSuperclass() != Object.class)
+ && (javaClass.getSuperclass() != null))
+ {
+ superType = bctx.register(javaClass.getSuperclass());
+ }
+ return this;
+ }
+
+ public String getPackage()
+ {
+ return pkg;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public List<PropertyBinding> getProperties()
+ {
+ return properties;
+ }
+
+ public List<PropertyBinding> getAllProperties()
+ {
+ if (this.superType == null)
+ {
+ return properties;
+ } else
+ {
+ List<PropertyBinding> newList = new ArrayList<PropertyBinding>(
+ properties);
+ for (PropertyBinding p : superType.getAllProperties())
+ {
+ if (!newList.contains(p))
+ {
+ newList.add(p);
+ }
+ }
+ return newList;
+ }
+ }
+
+ public List<MethodBinding> getMethods()
+ {
+ return methods;
+ }
+
+ public MethodBinding getMethod(String name)
+ {
+ return methodsByName.get(name);
+ }
+
+ // Use this format
+ // bytes value
+ // 0-3 package name
+ // 4-7 class name
+ // 8-11 property signature hash
+ // 12-15 method signature hash
+ // FIXME: Hash codes seem to mess things up
+ public byte[] getSchemaHash()
+ {
+ if (null == hash)
+ {
+ hash = new byte[16];
+ StringBuilder blder = new StringBuilder();
+ int packageHash = pkg.hashCode();
+ int classHash = name.hashCode();
+ int propertyHash = 0;
+ int methodHash = 0;
+ for (PropertyBinding p : properties)
+ {
+ blder.append(p.getName()).append(":").append(
+ p.getType().getCode()).append(":")
+ .append(p.getAccess()).append(":").append(
+ p.isOptional());
+ }
+ propertyHash = blder.toString().hashCode();
+ blder = new StringBuilder();
+ for (MethodBinding m : methods)
+ {
+ blder.append(m.getName());
+ for (ParameterBinding p : m.getParameters())
+ {
+ String direction = p.isIn() ? "in" : "out";
+ blder.append(":").append(p.getName()).append(":").append(
+ direction).append(":")
+ .append(p.getType().getCode());
+ }
+ }
+ methodHash = blder.toString().hashCode();
+ hash[0] = (byte) (packageHash >> 24);
+ hash[1] = (byte) (packageHash >> 16);
+ hash[2] = (byte) (packageHash >> 8);
+ hash[3] = (byte) (packageHash);
+ hash[4] = (byte) (classHash >> 24);
+ hash[5] = (byte) (classHash >> 16);
+ hash[6] = (byte) (classHash >> 8);
+ hash[7] = (byte) (classHash);
+ hash[8] = (byte) (propertyHash >> 24);
+ hash[9] = (byte) (propertyHash >> 16);
+ hash[10] = (byte) (propertyHash >> 8);
+ hash[11] = (byte) (propertyHash);
+ hash[12] = (byte) (methodHash >> 24);
+ hash[13] = (byte) (methodHash >> 16);
+ hash[14] = (byte) (methodHash >> 8);
+ hash[15] = (byte) (methodHash);
+ }
+ return hash;
+ }
+
+ public void encode(Encoder enc)
+ {
+ log.debug(String.format("encoding %s %s with superclass %s", this
+ .getRefClass(), this.getRefPackage(), superType));
+ enc.writeUint8(kind); // kind
+ enc.writeStr8(pkg);
+ enc.writeStr8(name);
+ enc.writeBin128(this.getSchemaHash()); // schema hash
+ // Send true (1) if we have a super-type
+ //if (superType == null)
+ //{
+ // enc.writeUint8((short) 0);
+ //} else
+ //{
+ // enc.writeUint8((short) 1);
+ //}
+ enc.writeUint16(properties.size());
+ // Events do not have the method size sent
+ if (kind == 1)
+ {
+ enc.writeUint16(0);
+ enc.writeUint16(methods.size());
+ }
+ // Add the super type information if we have it
+ //if (superType != null)
+ //{
+ // enc.writeStr8(superType.pkg);
+ // enc.writeStr8(superType.name);
+ // enc.writeBin128(superType.getSchemaHash()); // schema hash
+ //}
+ for (PropertyBinding p : properties)
+ {
+ log.trace("encoding property " + p.getName());
+ p.encode(enc);
+ }
+ for (MethodBinding m : methods)
+ {
+ m.encode(enc);
+ }
+ }
+
+ // Type Binding functions
+ public short getCode()
+ {
+ return (short) 20;
+ }
+
+ public Class<?> getJavaClass()
+ {
+ return javaClass;
+ }
+
+ public Object decode(Decoder dec)
+ {
+ // FIXME This only works with POJOs
+ short typeCode = dec.readUint8();
+ log.trace("Type code: " + typeCode);
+ if (typeCode == 20)
+ {
+ String packageName = dec.readStr8();
+ String className = dec.readStr8();
+ log
+ .debug(String
+ .format(
+ "Decoding an object for package %s class %s with bindings for %s %s",
+ packageName, className, this.pkg, this.name));
+ byte schemaHash[] = dec.readBin128();
+ // Check to see that this is me, and not a subclass
+ if (packageName.equals(this.pkg) && className.equals(this.name))
+ {
+ return decodeWithNoHeaders(dec);
+ } else
+ {
+ ClassBinding mcls = bctx
+ .getClassBinding(packageName, className);
+ return mcls.decodeWithNoHeaders(dec);
+ }
+ } else
+ {
+ TypeBinding tb = QMFTypeBinding.getType(typeCode);
+ return tb.decode(dec);
+ }
+ }
+
+ protected Object decodeWithNoHeaders(Decoder dec)
+ {
+ Object instance = null;
+ try
+ {
+ log.trace("Creating a new instance of " + this.javaClass.getName());
+ instance = this.javaClass.newInstance();
+ } catch (Exception e)
+ {
+ log.error("Could not instantiate object of class"
+ + this.javaClass.getName());
+ throw new BindingException(e);
+ }
+ List<String> excludes = this.processPresenceMasks(dec);
+ for (PropertyBinding p : getAllProperties())
+ {
+ if (!excludes.contains(p.getName()))
+ {
+ Object value = p.getType().decode(dec);
+ BindingUtils.set(p, value, instance);
+ }
+ }
+ return instance;
+ }
+
+ protected List<String> processPresenceMasks(Decoder dec)
+ {
+ List<String> excludes = new ArrayList<String>();
+ short bit = 0;
+ short mask = 0;
+ for (PropertyBinding prop : properties)
+ {
+ if (prop.isOptional())
+ {
+ if (bit == 0)
+ {
+ mask = dec.readUint8();
+ bit = 1;
+ }
+ if ((mask & bit) == 0)
+ {
+ log.trace("Going in exclude " + prop.getName());
+ excludes.add(prop.getName());
+ }
+ bit *= 2;
+ if (bit == 256)
+ {
+ bit = 0;
+ }
+ }
+ }
+ return excludes;
+ }
+
+ public void encode(Encoder enc, Object value)
+ {
+ // if the object is null, assume this is the
+ // correct class
+ if (value == null || (value.getClass().equals(this.javaClass)))
+ {
+ String pkg = getPackage();
+ String cls = getName();
+ log.debug(String.format("Encoding class %s:%s", pkg, cls));
+ enc.writeUint8(this.getCode());
+ enc.writeStr8(pkg);
+ enc.writeStr8(cls);
+ enc.writeBin128(this.getSchemaHash());
+ short bit = 0;
+ short mask = 0;
+ if (value != null)
+ {
+ // Encode the property presence masks first.
+ // if this is not an event
+ if (!isEvent())
+ {
+ for (PropertyBinding p : getAllProperties())
+ {
+ if (p.isOptional())
+ {
+ Object pValue = BindingUtils.get(p, value);
+ if (bit == 0)
+ bit = 1;
+ if (pValue != null)
+ {
+ mask |= bit;
+ }
+ if (bit == 128)
+ {
+ enc.writeUint8(mask);
+ bit = 0;
+ mask = 0;
+ } else
+ {
+ bit = (short) (bit << 1);
+ }
+ }
+ }
+ if (bit != 0)
+ {
+ enc.writeUint8(mask);
+ }
+ }
+ // Now put the actual properties
+ for (PropertyBinding p : getAllProperties())
+ {
+ Object pValue = BindingUtils.get(p, value);
+ if (!p.isOptional() || !(pValue == null))
+ {
+ log.trace(String.format("Encoding property %s", p
+ .getName()));
+ p.getType().encode(enc, pValue);
+ }
+ }
+ }
+ log.debug(String.format("Done with %s:%s", pkg, cls));
+ } else
+ {
+ TypeBinding tb = bctx.getTypeBinding(value.getClass());
+ if (tb == null)
+ {
+ throw new BindingException(String.format(
+ "No class named %s defined for this context ", value
+ .getClass()));
+ } else
+ {
+ if (tb.isNative())
+ {
+ enc.writeUint8(tb.getCode());
+ }
+ tb.encode(enc, value);
+ }
+ }
+ }
+
+ public boolean isNative()
+ {
+ return false;
+ }
+
+ public boolean optionalDefault()
+ {
+ return true;
+ }
+
+ public String getRefClass()
+ {
+ return this.name;
+ }
+
+ public String getRefPackage()
+ {
+ return this.pkg;
+ }
+
+ public short getKind()
+ {
+ return kind;
+ }
+
+ public boolean isEvent()
+ {
+ return kind == 2;
+ }
+
+ public void setKind(short kind)
+ {
+ this.kind = kind;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/EnumBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/EnumBinding.java
new file mode 100644
index 0000000000..dcb619b736
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/EnumBinding.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Binding information from a java enum to a QMF schema
+ */
+public class EnumBinding extends ClassBinding
+{
+ private static Log log = LogFactory.getLog(EnumBinding.class);
+
+ public EnumBinding(String pkg, String name, Class cls,
+ boolean exposeBehaviour, BindingContext bctx)
+ {
+ super(pkg, name, cls, exposeBehaviour, bctx);
+ }
+
+ @Override
+ public void encode(Encoder enc)
+ {
+ enc.writeUint8((short) 1); // kind
+ enc.writeStr8(pkg);
+ enc.writeStr8(name);
+ enc.writeBin128(new byte[16]); // schema hash
+ // FIXME Is there a way to send the valid types?
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ if (value != null)
+ {
+ enc.writeStr16(value.toString());
+ } else
+ {
+ enc.writeStr16("");
+ }
+ }
+
+ @Override
+ public Object decode(Decoder dec)
+ {
+ // FIXME This only works with POJOs
+ Object instance = null;
+ String value = null;
+ try
+ {
+ value = dec.readStr16();
+ if ((value != null) && (!value.isEmpty()))
+ {
+ instance = Enum.valueOf((Class<Enum>) this.getJavaClass(),
+ value);
+ }
+ } catch (Exception e)
+ {
+ log.error(String.format(
+ "Could not create an enum of type %s with value %s",
+ this.javaClass.getName(), value));
+ throw new BindingException(e);
+ }
+ return instance;
+ }
+
+ // Make this look like a String
+ @Override
+ public short getCode()
+ {
+ return (short) 7;
+ }
+
+ @Override
+ public EnumBinding parse()
+ {
+ log.debug(String.format(
+ "Parsing enum binding '%s' for package '%s' from class %s",
+ name, pkg, javaClass.getName()));
+ return this;
+ }
+
+ @Override
+ public boolean optionalDefault()
+ {
+ return false;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ListBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ListBinding.java
new file mode 100644
index 0000000000..a3658a812c
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ListBinding.java
@@ -0,0 +1,131 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Binding information from a java list to a QMF schema.
+ */
+public class ListBinding implements TypeBinding
+{
+ private static Log log = LogFactory.getLog(ListBinding.class);
+ protected BindingContext bctx;
+ protected Class javaClass;
+
+ public ListBinding(BindingContext bctx, Class javaClass)
+ {
+ this.bctx = bctx;
+ this.javaClass = javaClass;
+ }
+
+ public void encode(Encoder enc, Object value)
+ {
+ List list = (List) value;
+ BBEncoder newEncoder = new BBEncoder(10);
+ if (list != null)
+ {
+ newEncoder.writeUint32(list.size());
+ for (Object obj : list)
+ {
+ TypeBinding type = bctx.getTypeBinding(obj.getClass());
+ newEncoder.writeUint8(type.getCode());
+ type.encode(newEncoder, obj);
+ }
+ } else
+ {
+ newEncoder.writeUint32(0);
+ }
+ enc.writeVbin32(newEncoder.buffer().array());
+ }
+
+ public Object decode(Decoder dec)
+ {
+ List list = null;
+ try
+ {
+ list = (List) javaClass.newInstance();
+ } catch (Exception e)
+ {
+ throw new BindingException(
+ "Could not create a List implementation for "
+ + javaClass.getName(), e);
+ }
+ BBDecoder newDecoder = new BBDecoder();
+ newDecoder.init(ByteBuffer.wrap(dec.readVbin32()));
+ long count = newDecoder.readUint32();
+ while (count > 0)
+ {
+ short typeCode = newDecoder.readUint8();
+ TypeBinding type = QMFTypeBinding.getType(typeCode);
+ if (type == null)
+ {
+ type = bctx.getTypeBinding(Object.class);
+ }
+ list.add(type.decode(newDecoder));
+ count -= 1;
+ }
+ return list;
+ }
+
+ // QMF List Type
+ public short getCode()
+ {
+ return (short) 21;
+ }
+
+ @Override
+ public Class<?> getJavaClass()
+ {
+ return javaClass;
+ }
+
+ @Override
+ public String getRefClass()
+ {
+ return null;
+ }
+
+ @Override
+ public String getRefPackage()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isNative()
+ {
+ return true;
+ }
+
+ public boolean optionalDefault()
+ {
+ return false;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MapBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MapBinding.java
new file mode 100644
index 0000000000..02d562a59a
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MapBinding.java
@@ -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.
+ *
+ */
+package org.apache.qpid.agent.binding;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Binding information from a java Map to a QMF schema.
+ */
+public class MapBinding implements TypeBinding
+{
+ private static Log log = LogFactory.getLog(MapBinding.class);
+ protected BindingContext bctx;
+ protected Class javaClass;
+
+ public MapBinding(BindingContext bctx, Class javaClass)
+ {
+ this.bctx = bctx;
+ this.javaClass = javaClass;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void encode(Encoder enc, Object value)
+ {
+ Map map = (Map) value;
+ enc.writeMap(map);
+ }
+
+ public Object decode(Decoder dec)
+ {
+ Map map = dec.readMap();
+ return map;
+ }
+
+ // QMF List Type
+ public short getCode()
+ {
+ return (short) 15;
+ }
+
+ @Override
+ public Class<?> getJavaClass()
+ {
+ return javaClass;
+ }
+
+ @Override
+ public String getRefClass()
+ {
+ return null;
+ }
+
+ @Override
+ public String getRefPackage()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isNative()
+ {
+ return true;
+ }
+
+ public boolean optionalDefault()
+ {
+ return false;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MethodBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MethodBinding.java
new file mode 100644
index 0000000000..fc05c7393a
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/MethodBinding.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.agent.binding;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Metadata for mapping a method to a QMF schema
+ */
+public class MethodBinding
+{
+ private final String name;
+ private final List<ParameterBinding> parameters;
+ private final List<ParameterBinding> inParameters = new ArrayList<ParameterBinding>();
+ private final List<ParameterBinding> outParameters = new ArrayList<ParameterBinding>();
+ private Log log = LogFactory.getLog(MethodBinding.class);
+
+ public MethodBinding(String name, List<ParameterBinding> parameters)
+ {
+ this.name = name;
+ this.parameters = parameters;
+ for (ParameterBinding p : parameters)
+ {
+ if (p.isIn())
+ {
+ inParameters.add(p);
+ }
+ if (p.isOut())
+ {
+ outParameters.add(p);
+ }
+ }
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public List<ParameterBinding> getParameters()
+ {
+ return parameters;
+ }
+
+ public List<ParameterBinding> getInParameters()
+ {
+ return inParameters;
+ }
+
+ public List<ParameterBinding> getOutParameters()
+ {
+ return outParameters;
+ }
+
+ void encode(Encoder enc)
+ {
+ Map map = new HashMap();
+ map.put("name", name);
+ map.put("argCount", parameters.size());
+ enc.writeMap(map);
+ for (ParameterBinding p : parameters)
+ {
+ p.encode(enc);
+ }
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ParameterBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ParameterBinding.java
new file mode 100644
index 0000000000..7362976e0e
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/ParameterBinding.java
@@ -0,0 +1,121 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Metadata for mapping a method argument to a QMF schema
+ */
+public class ParameterBinding
+{
+ private final String name;
+ private final TypeBinding type;
+ private final boolean in;
+ private final boolean out;
+
+ public ParameterBinding(String name, TypeBinding type, boolean in,
+ boolean out)
+ {
+ this.name = name;
+ this.type = type;
+ this.in = in;
+ this.out = out;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public TypeBinding getType()
+ {
+ return type;
+ }
+
+ public boolean isIn()
+ {
+ return in;
+ }
+
+ public boolean isOut()
+ {
+ return out;
+ }
+
+ void encode(Encoder enc)
+ {
+ Map map = new HashMap();
+ map.put("name", name);
+ map.put("type", type.getCode());
+ map.put("dir", (in ? "I" : "") + (out ? "O" : ""));
+ if (!type.isNative())
+ {
+ map.put("refClass", type.getRefClass());
+ map.put("refPackage", type.getRefPackage());
+ }
+ enc.writeMap(map);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (in ? 1231 : 1237);
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + (out ? 1231 : 1237);
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ParameterBinding other = (ParameterBinding) obj;
+ if (in != other.in)
+ return false;
+ if (name == null)
+ {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (out != other.out)
+ return false;
+ if (type == null)
+ {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ return true;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/PropertyBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/PropertyBinding.java
new file mode 100644
index 0000000000..604d66c818
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/PropertyBinding.java
@@ -0,0 +1,131 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Metadata for mapping a java property (getter/setter) to a QMF schema
+ */
+public class PropertyBinding
+{
+ private static Log log = LogFactory.getLog(PropertyBinding.class);
+ public final static int READ_CREATE = 1;
+ public final static int READ_WRITE = 2;
+ public final static int READ_ONLY = 3;
+ private String name;
+ private TypeBinding type;
+ private int accessType;
+ private boolean optional;
+
+ public PropertyBinding(String name, TypeBinding type, int accessType,
+ boolean optional)
+ {
+ this.name = name;
+ this.type = type;
+ this.accessType = accessType;
+ this.optional = optional;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + accessType;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PropertyBinding other = (PropertyBinding) obj;
+ if (accessType != other.accessType)
+ return false;
+ if (name == null)
+ {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (type == null)
+ {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ return true;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public TypeBinding getType()
+ {
+ return type;
+ }
+
+ public int getAccess()
+ {
+ return accessType;
+ }
+
+ public boolean isIndex()
+ {
+ return false;
+ }
+
+ public boolean isOptional()
+ {
+ return optional;
+ }
+
+ void encode(Encoder enc)
+ {
+ Map map = new HashMap();
+ map.put("name", name);
+ map.put("type", type.getCode());
+ map.put("access", getAccess());
+ map.put("index", isIndex() ? 1 : 0);
+ map.put("optional", isOptional() ? 1 : 0);
+ if (!type.isNative())
+ {
+ map.put("refClass", type.getRefClass());
+ map.put("refPackage", type.getRefPackage());
+ }
+ enc.writeMap(map);
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/QMFTypeBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/QMFTypeBinding.java
new file mode 100644
index 0000000000..11ccf1b1a7
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/QMFTypeBinding.java
@@ -0,0 +1,465 @@
+/*
+ *
+ * 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 org.apache.qpid.agent.binding;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Basic type mappings for QMF schema
+ */
+public abstract class QMFTypeBinding implements TypeBinding
+{
+ private static final Map<Class<?>, QMFTypeBinding> TYPES = new HashMap<Class<?>, QMFTypeBinding>();
+ private static final Map<Short, QMFTypeBinding> TYPES_BY_CODE = new HashMap<Short, QMFTypeBinding>();
+ static
+ {
+ new QMFTypeBinding(null, (short) 1)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Short.valueOf(dec.readUint8());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeUint8(((Number) value).shortValue());
+ }
+ };
+ new QMFTypeBinding(null, (short) 2)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Integer.valueOf(dec.readUint16());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeUint16(((Number) value).intValue());
+ }
+ };
+ new QMFTypeBinding(null, (short) 3)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Long.valueOf(dec.readUint32());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeUint32(((Number) value).longValue());
+ }
+ };
+ new QMFTypeBinding(null, (short) 4)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Long.valueOf(dec.readUint64());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeUint64(((Number) value).longValue());
+ }
+ };
+ new QMFTypeBinding(null, (short) 6) // short string
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readStr8();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ if (null == value)
+ value = "";
+ enc.writeStr8((String) value);
+ }
+ };
+ new QMFTypeBinding(String.class, (short) 7) // long string
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readStr16();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ if (null == value)
+ value = "";
+ enc.writeStr16((String) value);
+ }
+ };
+ new QMFTypeBinding(Date.class, (short) 8)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return new Date(dec.readDatetime());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeDatetime(((Date) value).getTime());
+ }
+ };
+ new QMFTypeBinding(Boolean.class, (short) 11)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Boolean.valueOf(dec.readUint8() != 0);
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ if (((Boolean) value).booleanValue())
+ {
+ enc.writeUint8((short) 1);
+ } else
+ {
+ enc.writeUint8((short) 0);
+ }
+ }
+
+ @Override
+ public short[] alternateTypes()
+ {
+ short[] types =
+ { 5 };
+ return types;
+ }
+ };
+ new QMFTypeBinding(boolean.class, (short) 11)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readUint8() != 0;
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ if (((Boolean) value).booleanValue())
+ {
+ enc.writeUint8((short) 1);
+ } else
+ {
+ enc.writeUint8((short) 0);
+ }
+ }
+ };
+ new QMFTypeBinding(Float.class, (short) 12)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Float.valueOf(dec.readFloat());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeFloat(((Number) value).floatValue());
+ }
+ };
+ new QMFTypeBinding(float.class, (short) 12)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readFloat();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeFloat(((Number) value).floatValue());
+ }
+ };
+ new QMFTypeBinding(Double.class, (short) 13)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Double.valueOf(dec.readDouble());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeDouble(((Number) value).doubleValue());
+ }
+ };
+ new QMFTypeBinding(double.class, (short) 13)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readDouble();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeDouble(((Number) value).doubleValue());
+ }
+ };
+ new QMFTypeBinding(UUID.class, (short) 14)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readUuid();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeUuid((UUID) value);
+ }
+ };
+ new QMFTypeBinding(byte.class, (short) 16)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readInt8();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt8(((Number) value).byteValue());
+ }
+ };
+ new QMFTypeBinding(Short.class, (short) 17)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Short.valueOf(dec.readInt16());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt16(((Number) value).shortValue());
+ }
+ };
+ new QMFTypeBinding(short.class, (short) 17)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readInt16();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt16(((Number) value).shortValue());
+ }
+ };
+ new QMFTypeBinding(Integer.class, (short) 18)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Integer.valueOf(dec.readInt32());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt32(((Number) value).intValue());
+ }
+ };
+ new QMFTypeBinding(int.class, (short) 18)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readInt32();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt32(((Number) value).intValue());
+ }
+ };
+ new QMFTypeBinding(Long.class, (short) 19)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return Long.valueOf(dec.readInt64());
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt64(((Number) value).longValue());
+ }
+ };
+ new QMFTypeBinding(long.class, (short) 19)
+ {
+ @Override
+ public Object decode(Decoder dec)
+ {
+ return dec.readInt64();
+ }
+
+ @Override
+ public void encode(Encoder enc, Object value)
+ {
+ enc.writeInt64(((Number) value).longValue());
+ }
+ };
+ }
+
+ public static final QMFTypeBinding forClass(Class<?> cls)
+ {
+ QMFTypeBinding t = TYPES.get(cls);
+ return t;
+ }
+
+ public static final boolean isBound(Class<?> cls)
+ {
+ return TYPES.containsKey(cls);
+ }
+
+ public static QMFTypeBinding getType(short code)
+ {
+ return TYPES_BY_CODE.get(code);
+ }
+
+ private final Class<?> cls;
+ private final short code;
+
+ private QMFTypeBinding(Class<?> cls, short code)
+ {
+ this.cls = cls;
+ this.code = code;
+ if (cls != null)
+ {
+ TYPES.put(cls, this);
+ }
+ TYPES_BY_CODE.put(code, this);
+ for (short type : this.alternateTypes())
+ {
+ TYPES_BY_CODE.put(type, this);
+ }
+ }
+
+ public Class<?> getJavaClass()
+ {
+ return cls;
+ }
+
+ public short getCode()
+ {
+ return code;
+ }
+
+ public boolean isNative()
+ {
+ return true;
+ }
+
+ public boolean optionalDefault()
+ {
+ return false;
+ }
+
+ public String getRefClass()
+ {
+ return null;
+ }
+
+ public String getRefPackage()
+ {
+ return null;
+ }
+
+ public abstract Object decode(Decoder dec);
+
+ public abstract void encode(Encoder enc, Object value);
+
+ public short[] alternateTypes()
+ {
+ short[] types =
+ {};
+ return types;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((cls == null) ? 0 : cls.hashCode());
+ result = prime * result + code;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ QMFTypeBinding other = (QMFTypeBinding) obj;
+ if (cls == null)
+ {
+ if (other.cls != null)
+ return false;
+ } else if (!cls.equals(other.cls))
+ return false;
+ if (code != other.code)
+ return false;
+ return true;
+ }
+}
diff --git a/java/management/agent/src/main/java/org/apache/qpid/agent/binding/TypeBinding.java b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/TypeBinding.java
new file mode 100644
index 0000000000..97ec943bfd
--- /dev/null
+++ b/java/management/agent/src/main/java/org/apache/qpid/agent/binding/TypeBinding.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.agent.binding;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Binding between Java Type and QMF type
+ */
+public interface TypeBinding
+{
+ public Object decode(Decoder dec);
+
+ public void encode(Encoder enc, Object value);
+
+ public Class<?> getJavaClass();
+
+ public short getCode();
+
+ public boolean isNative();
+
+ public String getRefClass();
+
+ public String getRefPackage();
+
+ public boolean optionalDefault();
+}
diff --git a/java/management/agent/src/test/java/org/apache/qpid/agent/Crumpet.java b/java/management/agent/src/test/java/org/apache/qpid/agent/Crumpet.java
new file mode 100644
index 0000000000..67095c809b
--- /dev/null
+++ b/java/management/agent/src/test/java/org/apache/qpid/agent/Crumpet.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import java.util.ArrayList;
+
+import org.apache.qpid.agent.annotations.QMFSeeAlso;
+import org.apache.qpid.agent.annotations.QMFType;
+
+/**
+ * Crumpet
+ *
+ */
+@QMFType(className = "Crumpet", packageName = "org.apache.test")
+@QMFSeeAlso(
+{ Pikelet.class })
+public class Crumpet
+{
+ private String foo = "fooValue";
+ private String bar = "barValue";
+ private ArrayList<String> ingredients = new ArrayList<String>();
+
+ public String getFoo()
+ {
+ return foo;
+ }
+
+ public void setFoo(String foo)
+ {
+ this.foo = foo;
+ }
+
+ public String getBar()
+ {
+ return bar;
+ }
+
+ public void setBar(String bar)
+ {
+ this.bar = bar;
+ }
+
+ public ArrayList<String> getIngredients()
+ {
+ return ingredients;
+ }
+
+ public void setIngredients(ArrayList<String> ingredients)
+ {
+ this.ingredients = ingredients;
+ }
+}
diff --git a/java/management/agent/src/test/java/org/apache/qpid/agent/Muppet.java b/java/management/agent/src/test/java/org/apache/qpid/agent/Muppet.java
new file mode 100644
index 0000000000..f039ab9baa
--- /dev/null
+++ b/java/management/agent/src/test/java/org/apache/qpid/agent/Muppet.java
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.qpid.agent.annotations.QMFObject;
+
+@QMFObject(className = "Muppet", packageName = "org.apache.test")
+public class Muppet extends Puppet
+{
+ private Log log = LogFactory.getLog(Muppet.class);
+
+ public String getSomething()
+ {
+ return "something";
+ }
+
+ public void doSomething(String str)
+ {
+ log.debug(String.format("doSomething: %s", str));
+ }
+
+ public String returnSomething()
+ {
+ log.debug("returning something");
+ return "asdf";
+ }
+
+ public Crumpet gimmieCrumpet(String asdf, int n, float f, Map foo)
+ {
+ log.debug(String
+ .format("mmm, crumpet: %s, %s, %s, %s", asdf, n, f, foo));
+ Crumpet crumpet = new Crumpet();
+ crumpet.getIngredients().add("Butter");
+ crumpet.getIngredients().add("Salt");
+ crumpet.getIngredients().add("Flour");
+ return crumpet;
+ }
+
+ public Crumpet gimmieCrumpet2()
+ {
+ Pikelet pik = new Pikelet();
+ pik.getIngredients().add("Butter");
+ pik.getIngredients().add("Salt");
+ pik.getIngredients().add("Eggs");
+ pik.getCrumpets().put("Crumpet1",
+ this.gimmieCrumpet("2121", 1, 1, null));
+ return pik;
+ }
+
+ public List gimmeLotsOfCrumpets()
+ {
+ log.debug("Asking for lots of Crumpets");
+ ArrayList<Crumpet> returnValue = new ArrayList<Crumpet>();
+ Crumpet crumpet = new Crumpet();
+ crumpet.getIngredients().add("Chocolate");
+ returnValue.add(crumpet);
+ crumpet = new Crumpet();
+ crumpet.getIngredients().add("Pecans");
+ returnValue.add(crumpet);
+ crumpet = new Pikelet();
+ crumpet.getIngredients().add("Poached Eggs");
+ returnValue.add(crumpet);
+ return returnValue;
+ }
+
+ public int divideByZero()
+ {
+ return 1 / 0;
+ }
+
+ public Crumpet takeCrumpet(Crumpet newCrumpet)
+ {
+ log.debug(String.format("I gots me a crumpet: foo: '%s' bar: '%s'",
+ newCrumpet.getFoo(), newCrumpet.getBar()));
+ log.debug("My crumpet's class is " + newCrumpet.getClass().getName());
+ for (String ingredient : newCrumpet.getIngredients())
+ {
+ log.debug("My crumpet is made of " + ingredient);
+ }
+ return newCrumpet;
+ }
+
+ public Object takeSomething(Object obj)
+ {
+ log.debug(String.format("I gots me a something: '%s'", obj.getClass()
+ .getName()));
+ return obj;
+ }
+}
diff --git a/java/management/agent/src/test/java/org/apache/qpid/agent/Pikelet.java b/java/management/agent/src/test/java/org/apache/qpid/agent/Pikelet.java
new file mode 100644
index 0000000000..f820fa6258
--- /dev/null
+++ b/java/management/agent/src/test/java/org/apache/qpid/agent/Pikelet.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+import java.util.HashMap;
+
+import org.apache.qpid.agent.annotations.QMFType;
+
+@QMFType(className = "Pikelet", packageName = "org.apache.test")
+public class Pikelet extends Crumpet
+{
+ protected String shape;
+ HashMap<String, Crumpet> crumpets = new HashMap<String, Crumpet>();
+
+ public String getShape()
+ {
+ return shape;
+ }
+
+ public void setShape(String shape)
+ {
+ this.shape = shape;
+ }
+
+ public HashMap<String, Crumpet> getCrumpets()
+ {
+ return crumpets;
+ }
+
+ public void setCrumpets(HashMap<String, Crumpet> crumpets)
+ {
+ this.crumpets = crumpets;
+ }
+}
diff --git a/java/management/agent/src/test/java/org/apache/qpid/agent/Puppet.java b/java/management/agent/src/test/java/org/apache/qpid/agent/Puppet.java
new file mode 100644
index 0000000000..bfd34840f8
--- /dev/null
+++ b/java/management/agent/src/test/java/org/apache/qpid/agent/Puppet.java
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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 org.apache.qpid.agent;
+
+public class Puppet
+{
+ public int countStrings()
+ {
+ return 4;
+ }
+}
diff --git a/java/management/client/README.txt b/java/management/client/README.txt
new file mode 100644
index 0000000000..ecd61da75e
--- /dev/null
+++ b/java/management/client/README.txt
@@ -0,0 +1,42 @@
+QMan - Qpid JMX & WS-DM Management Bridge
+---------------------------------------------------------
+
+Documentation
+--------------
+All of our user documentation for QMan module can be accessed on our wiki at:
+
+http://cwiki.apache.org/qpid/qman-qpid-management-bridge.html
+
+This includes a Getting Started and User Guide as well as detailed developer documentation.
+However, here's a VERY quick guide to running QMan, once you have installed it somewhere !
+
+Running
+------------------
+
+Once you installed QMan, under the root folder you should have the following structure
+
+- bin (folder) : contains startup & shutdown scripts;
+- app (folder) : contains the web application module;
+- etc (folder) : contains configuration files;
+- examples (folder) : contains examples (and a nested README as well)
+- lib (folder) : contains dependency libraries;
+- log (folder) : this is the default log folder.
+
+To run QMan,
+
+1) edit the $QMAN_HOME/etc/qman-config.xml file and configure broker connection data (host,port, username, etc...)
+2) under the $QMAN_HOME/bin directory run :
+
+> ./qman-wsdm-start.sh
+
+now, under $QMAN_HOME/log directory you should see two files :
+
+1) server.log : contains web server log messages;
+2) qman.log : contains qman log messages;
+
+Administration
+-----------------------
+
+After QMan has been started successfully you can browse its administration console pointing your browser to :
+
+http://<host>:<port>/qman/console
diff --git a/java/management/client/bin/qman-jmx.cmd b/java/management/client/bin/qman-jmx.cmd
new file mode 100644
index 0000000000..c04241494d
--- /dev/null
+++ b/java/management/client/bin/qman-jmx.cmd
@@ -0,0 +1,78 @@
+@echo off
+
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements. See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership. The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License. You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied. See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+
+@rem *************************************************************************
+@rem This script is used to initialize environment to start QMan JMX Adapter.
+@rem It uses several environment variables described below.
+@rem You can edit this file according to your environment or (reccommended) set their
+@rem values outside this script.
+@rem
+@rem It sets (or retrieve from the environment if defined) the following variables:
+@rem
+@rem QMAN_HOME - The home directory of your QMan installation.
+@rem JAVA_HOME - Location of the version of Java runtime used to start QMan.
+@rem QMAN_CONFIG_FILE - Location of the QMan configuration file.
+@rem **************************************************************************
+
+cls
+
+:CHECK JVM
+set JAVA=%JAVA_HOME%\bin\java
+set JAVA_OPTS=-Xms128m -Xmx512m
+
+if not "%JAVA_HOME%" == "" goto CONFIGURE AND START
+
+set JAVA=java
+
+echo.
+echo WARNING : JAVA_HOME is not set so unexpected results may occur.
+echo Please set JAVA_HOME to the directory of your local JDK / JRE to avoid this message.
+
+:CONFIGURE AND START
+
+if "%QMAN_HOME%" == "" SET QMAN_HOME=..
+if "%QMAN_CONFIG_FILE%" == "" SET QMAN_CONFIG_FILE=%QMAN_HOME%\etc\qman-config.xml
+
+SET QMAN_LIBS=%QMAN_HOME%\lib
+SET QMAN_CLASSPATH=%QMAN_HOME%\etc
+
+setlocal ENABLEDELAYEDEXPANSION
+
+FOR /R %QMAN_LIBS% %%G IN (*.jar) DO set QMAN_CLASSPATH=!QMAN_CLASSPATH!;%%G
+
+:START
+echo ===============================================================================
+echo.
+echo QMan JMX Bridge Bootstrap Environment
+echo --------------------------------------------------
+echo.
+echo QMan HOME : %QMAN_HOME%
+echo.
+echo Java executable : %JAVA%
+echo.
+echo Java Opts : %JAVA_OPTS%
+echo.
+echo Configuration file : %QMAN_CONFIG_FILE%
+echo.
+echo Bootstrap classpath : %QMAN_CLASSPATH%
+echo.
+echo ===============================================================================
+echo.
+
+"%JAVA%" %JAVA_OPTS% -Dcom.sun.management.jmxremote -Dqman-config=%QMAN_CONFIG_FILE% -classpath "%QMAN_CLASSPATH%" org.apache.qpid.management.domain.services.QMan \ No newline at end of file
diff --git a/java/management/client/bin/qman-jmx.sh b/java/management/client/bin/qman-jmx.sh
new file mode 100644
index 0000000000..1003117128
--- /dev/null
+++ b/java/management/client/bin/qman-jmx.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# *************************************************************************
+# This script is used to initialize environment to start QMan JMX Adapter.
+# It uses several environment variables described below.
+# You can edit this file according to your environment or (reccommended) set their
+# values outside this script.
+#
+# It sets (or retrieve from the environment if defined) the following variables:
+#
+# QMAN_HOME - The home directory of your QMan installation.
+# JAVA_HOME - Location of the version of Java runtime used to start QMan.
+# QMAN_CONFIG_FILE - Location of the QMan configuration file.
+# **************************************************************************
+
+clear
+
+JAVA=$JAVA_HOME/bin/java
+JAVA_OPTS="-Xms128m -Xmx512m"
+
+if [ "$JAVA_HOME" = "" ] ; then
+ echo "JAVA_HOME is not set. Unexpected results may occur."
+ echo "Set JAVA_HOME to the directory of your local JDK to avoid this message."
+ JAVA=java
+fi
+
+if [ "$QMAN_HOME" = "" ] ; then
+ QMAN_HOME=..
+fi
+
+if [ "$QMAN_CONFIG_FILE" = "" ] ; then
+ QMAN_CONFIG_FILE=$QMAN_HOME/etc/qman-config.xml
+fi
+
+if [ "$QMAN_LIBS" = "" ] ; then
+ QMAN_LIBS=$QMAN_HOME/lib
+fi
+QMAN_CLASSPATH=`find $QMAN_LIBS | tr '\n' ":"`
+QMAN_CLASSPATH=$QMAN_HOME/etc:$QMAN_CLASSPATH
+
+echo "==============================================================================="
+echo ""
+echo "QMan JMX Bridge Bootstrap Environment"
+echo "--------------------------------------------------"
+echo ""
+echo "QMan HOME : $QMAN_HOME"
+echo ""
+echo "Java executable : $JAVA"
+echo ""
+echo "Java Opts : $JAVA_OPTS"
+echo ""
+echo "Configuration file : $QMAN_CONFIG_FILE"
+echo ""
+echo "Bootstrap classpath : $QMAN_CLASSPATH"
+echo ""
+echo "==============================================================================="
+echo ""
+
+"$JAVA" $JAVA_OPTS -cp $QMAN_CLASSPATH -Dcom.sun.management.jmxremote -Dqman-config=$QMAN_CONFIG_FILE org.apache.qpid.management.domain.services.QMan
diff --git a/java/management/client/bin/qman-wsdm-start.cmd b/java/management/client/bin/qman-wsdm-start.cmd
new file mode 100644
index 0000000000..ec8321c6b8
--- /dev/null
+++ b/java/management/client/bin/qman-wsdm-start.cmd
@@ -0,0 +1,88 @@
+@echo off
+
+@rem Licensed to the Apache Software Foundation (ASF) under one
+@rem or more contributor license agreements. See the NOTICE file
+@rem distributed with this work for additional information
+@rem regarding copyright ownership. The ASF licenses this file
+@rem to you under the Apache License, Version 2.0 (the
+@rem "License"); you may not use this file except in compliance
+@rem with the License. You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing,
+@rem software distributed under the License is distributed on an
+@rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@rem KIND, either express or implied. See the License for the
+@rem specific language governing permissions and limitations
+@rem under the License.
+
+@rem *************************************************************************
+@rem This script is used to initialize environment to start QMan WS-DM Adapter.
+@rem It uses several environment variables described below.
+@rem You can edit this file according to your environment or (reccommended) set their
+@rem values outside this script.
+@rem
+@rem It sets (or retrieve from the environment if defined) the following variables:
+@rem
+@rem QMAN_HOME - The home directory of your QMan installation.
+@rem JAVA_HOME - Location of the version of Java runtime used to start QMan.
+@rem QMAN_WSDM_ADAPTER_PORT - The TCP port that QMan will use to listen for incoming connections.
+@rem QMAN_WSDM_ADAPTER_HOST - The IP address or DNS name QMan will use to listen for incoming connections
+@rem QMAN_CONFIG_FILE - Location of the QMan configuration file.
+@rem **************************************************************************
+
+set JAVA=%JAVA_HOME%\bin\java
+set JAVA_OPTS=-Xms128m -Xmx512m
+SET CLASSPATH=
+
+if not "%JAVA_HOME%" == "" goto CONFIGURE AND START
+set JAVA=java
+
+echo JAVA_HOME is not set. Unexpected results may occur.
+echo Set JAVA_HOME to the directory of your local JDK to avoid this message.
+
+:CONFIGURE AND START
+
+if "%QMAN_HOME%" == "" SET QMAN_HOME=..
+if "%QMAN_WSDM_ADAPTER_PORT%" == "" SET QMAN_WSDM_ADAPTER_PORT=8080
+if "%QMAN_WSDM_ADAPTER_HOST%" == "" SET QMAN_WSDM_ADAPTER_HOST=%COMPUTERNAME%
+if "%QMAN_CONFIG_FILE%" == "" SET QMAN_CONFIG_FILE=%QMAN_HOME%\etc\qman-config.xml
+
+SET ADMIN_PORT=8079
+SET ADMIN_KEY=gazzax
+SET QMAN_LIBS=%QMAN_HOME%\lib
+SET JETTY_CONFIG_FILE=%QMAN_HOME%\etc\jetty.xml
+
+SET CLASSPATH=%QMAN_HOME%\etc
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\start.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\jetty-6.1.14.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\jetty-util-6.1.14.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\geronimo-servlet_2.5_spec-1.2.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\slf4j-api-1.6.1.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\slf4j-log4j12-1.6.1.jar
+SET CLASSPATH=%CLASSPATH%;%QMAN_LIBS%\log4j-1.2.12.jar
+
+echo ===============================================================================
+echo.
+echo QMan WS-DM Bridge Bootstrap Environment
+echo ------------------------------------------------------
+echo.
+echo QMan HOME: %QMAN_HOME%
+echo.
+echo Java executable : %JAVA%
+echo.
+echo QMan configuration file : %QMAN_CONFIG_FILE%
+echo.
+echo Web Server configuration file : %JETTY_CONFIG_FILE%
+echo.
+echo Web Server HTTP port : %QMAN_WSDM_ADAPTER_PORT%
+echo.
+echo Web Server Admin port : %ADMIN_PORT%
+echo.
+echo Bootstrap classpath : %CLASSPATH%
+echo.
+echo ===============================================================================
+echo.
+
+%JAVA% -cp %CLASSPATH% -DQMAN_HOME=%QMAN_HOME% -Djetty.home=%QMAN_HOME% -Dqman.host=%QMAN_WSDM_ADAPTER_HOST% -Dqman.port=%QMAN_WSDM_ADAPTER_PORT% -DSTOP.PORT=%ADMIN_PORT% -DSTOP.KEY=%ADMIN_KEY% -Dqman-config=%QMAN_CONFIG_FILE% org.mortbay.start.Main %JETTY_CONFIG_FILE%
diff --git a/java/management/client/bin/qman-wsdm-start.sh b/java/management/client/bin/qman-wsdm-start.sh
new file mode 100644
index 0000000000..0024890527
--- /dev/null
+++ b/java/management/client/bin/qman-wsdm-start.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# *************************************************************************
+# This script is used to initialize environment to start QMan WS-DM Adapter.
+# It uses several environment variables described below.
+# You can edit this file according to your environment or (reccommended) set their
+# values outside this script.
+#
+# It sets (or retrieve from the environment if defined) the following variables:
+#
+# QMAN_HOME - The home directory of your QMan installation.
+# JAVA_HOME - Location of the version of Java runtime used to start QMan.
+# QMAN_WSDM_ADAPTER_PORT - The TCP port that QMan will use to listen for incoming connections.
+# QMAN_WSDM_ADAPTER_HOST - The IP address or DNS name QMan will use to listen for incoming connections
+# QMAN_CONFIG_FILE - Location of the QMan configuration file.
+# **************************************************************************
+
+JAVA=$JAVA_HOME/bin/java
+JAVA_OPTS="-Xms128m -Xmx512m"
+
+if [ "$JAVA_HOME" = "" ] ; then
+ echo "JAVA_HOME is not set. Unexpected results may occur."
+ echo "Set JAVA_HOME to the directory of your local JDK to avoid this message."
+ JAVA=java
+fi
+if [ "$QMAN_HOME" = "" ] ; then
+ QMAN_HOME=..
+fi
+if [ "$QMAN_WSDM_ADAPTER_PORT" = "" ] ; then
+ QMAN_WSDM_ADAPTER_PORT=8080
+fi
+if [ "$QMAN_WSDM_ADAPTER_HOST" = "" ] ; then
+ QMAN_WSDM_ADAPTER_HOST=$HOSTNAME
+fi
+if [ "$QMAN_CONFIG_FILE" = "" ] ; then
+ QMAN_CONFIG_FILE=$QMAN_HOME/etc/qman-config.xml
+fi
+
+ADMIN_PORT=8079
+ADMIN_KEY=gazzax
+QMAN_LIBS=$QMAN_HOME/lib
+JETTY_CONFIG_FILE=$QMAN_HOME/etc/jetty.xml
+
+QMAN_CLASSPATH=$QMAN_HOME/etc:$QMAN_LIBS/start.jar:$QMAN_LIBS/jetty-6.1.14.jar:$QMAN_LIBS/jetty-util-6.1.14.jar:$QMAN_LIBS/geronimo-servlet_2.5_spec-1.2.jar:$QMAN_LIBS/slf4j-api-1.6.1.jar:$QMAN_LIBS/slf4j-log4j12-1.6.1.jar:$QMAN_LIBS/log4j-1.2.12.jar
+
+echo "==============================================================================="
+echo""
+echo "QMan WS-DM Bridge Bootstrap Environment"
+echo "------------------------------------------------------"
+echo""
+echo "QMan HOME: $QMAN_HOME"
+echo""
+echo "Java executable : $JAVA"
+echo""
+echo "Java Opts : $JAVA_OPTS"
+echo""
+echo "Configuration file : $QMAN_CONFIG_FILE"
+echo""
+echo "Web Server Configuration File : $JETTY_CONFIG_FILE"
+echo""
+echo "Web Server HTTP port : $QMAN_WSDM_ADAPTER_PORT"
+echo""
+echo "Web Server HTTP host : $QMAN_WSDM_ADAPTER_HOST"
+echo""
+echo "Web Server Admin port : $ADMIN_PORT"
+echo""
+echo "Bootstrap classpath : $QMAN_CLASSPATH"
+echo""
+echo "==============================================================================="
+echo""
+
+"$JAVA" $JAVA_OPTS -cp $QMAN_CLASSPATH -DQMAN_HOME=$QMAN_HOME -Djetty.home=$QMAN_HOME -Dqman.host=$QMAN_WSDM_ADAPTER_HOST -Dqman.port=$QMAN_WSDM_ADAPTER_PORT -DSTOP.PORT=$ADMIN_PORT -DSTOP.KEY=$ADMIN_KEY -Dqman-config=$QMAN_CONFIG_FILE org.mortbay.start.Main $JETTY_CONFIG_FILE
diff --git a/java/management/client/bin/qman-wsdm-stop.cmd b/java/management/client/bin/qman-wsdm-stop.cmd
new file mode 100644
index 0000000000..6449c70227
--- /dev/null
+++ b/java/management/client/bin/qman-wsdm-stop.cmd
@@ -0,0 +1,37 @@
+@echo off
+
+rem Licensed to the Apache Software Foundation (ASF) under one
+rem or more contributor license agreements. See the NOTICE file
+rem distributed with this work for additional information
+rem regarding copyright ownership. The ASF licenses this file
+rem to you under the Apache License, Version 2.0 (the
+rem "License"); you may not use this file except in compliance
+rem with the License. You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing,
+rem software distributed under the License is distributed on an
+rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem KIND, either express or implied. See the License for the
+rem specific language governing permissions and limitations
+rem under the License.
+
+set JAVA=%JAVA_HOME%\bin\java
+
+if not "%JAVA_HOME%" == "" goto CONFIGURE AND START
+
+set JAVA=java
+
+echo JAVA_HOME is not set. Unexpected results may occur.
+echo Set JAVA_HOME to the directory of your local JDK to avoid this message.
+
+:CONFIGURE AND START
+
+if "%QMAN_HOME%" == "" SET QMAN_HOME=..
+SET ADMIN_PORT=8079
+SET ADMIN_KEY=gazzax
+
+"%JAVA%" -DSTOP.PORT=%ADMIN_PORT% -DSTOP.KEY=%ADMIN_KEY% -jar %QMAN_HOME%\lib\start.jar --stop
+
+echo QMan WS-DM Adapter shut down successfully. \ No newline at end of file
diff --git a/java/management/client/bin/qman-wsdm-stop.sh b/java/management/client/bin/qman-wsdm-stop.sh
new file mode 100644
index 0000000000..0de9a995ef
--- /dev/null
+++ b/java/management/client/bin/qman-wsdm-stop.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+JAVA=$JAVA_HOME/bin/java
+
+if [ "$JAVA_HOME" = "" ] ; then
+ echo "JAVA_HOME is not set. Unexpected results may occur."
+ echo "Set JAVA_HOME to the directory of your local JDK to avoid this message."
+ JAVA=java
+fi
+
+if [ "$QMAN_HOME" = "" ] ; then
+ QMAN_HOME=..
+fi
+
+ADMIN_PORT=8079
+ADMIN_KEY=gazzax
+
+"$JAVA" -DSTOP.PORT=$ADMIN_PORT -DSTOP.KEY=$ADMIN_KEY -jar $QMAN_HOME/lib/start.jar --stop
+
+echo "QMan WS-DM Adapter shut down successfully." \ No newline at end of file
diff --git a/java/management/client/build.xml b/java/management/client/build.xml
new file mode 100644
index 0000000000..415840f70d
--- /dev/null
+++ b/java/management/client/build.xml
@@ -0,0 +1,213 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<project name="QMan - Qpid JMX / WS-DM Adapter" default="build">
+
+ <property name="module.depends" value="client common"/>
+ <property name="module.test.depends" value="client common"/>
+
+ <import file="../../module.xml"/>
+
+ <property name="build.root" value="${module.build}"/>
+ <property name="web.module" value="${module.build}${file.separator}wsdm-module"/>
+ <property name="web-inf.folder" value="${web.module}${file.separator}WEB-INF"/>
+ <property name="classes.folder" value="${web-inf.folder}${file.separator}classes"/>
+ <property name="examples.folder" value="${module.build}${file.separator}examples"/>
+
+ <target name="release-bin-other">
+ <mkdir dir="${module.release}${file.separator}log"/>
+ <mkdir dir="${module.release}${file.separator}examples"/>
+ <mkdir dir="${module.release}${file.separator}examples${file.separator}sample_messages"/>
+
+ </target>
+
+ <target name="release-bin" depends="release-bin-tasks"/>
+
+ <target name="resources-release" description="copy resources into module release">
+ <copy todir="${module.release}" failonerror="false" flatten="true">
+ <fileset dir="${resources}" excludes="META-INF">
+ <exclude name="META-INF"/>
+ <exclude name="README.txt"/>
+ </fileset>
+ <fileset file="${module.build}${file.separator}README.txt"/>
+ </copy>
+ </target>
+
+ <target name="libs-release" description="copy dependencies into module release">
+ <copy todir="${module.release}${file.separator}" failonerror="true" verbose="true">
+ <fileset dir="${build}" casesensitive="yes" includes="${module.libs}">
+ <not><filename name="**/*javassist*"/></not>
+ <not><filename name="**/*xml-api*"/></not>
+ <not><filename name="**/*xerces*"/></not>
+ <not><filename name="**/*xalan*"/></not>
+ <not><filename name="**/*wsdl*"/></not>
+ <not><filename name="**/*muse*"/></not>
+ <not><filename name="**/*jsp*"/></not>
+ <not><filename name="**/*core-3.1.1.jar*"/></not>
+ </fileset>
+ </copy>
+ <copy todir="${module.release}${file.separator}lib" failonerror="true">
+ <fileset file="${module.jar}"/>
+ <fileset dir="${build.lib}" includes="${module.depends.jars}"/>
+ </copy>
+ <mkdir dir="${module.release}${file.separator}app${file.separator}qman"/>
+ <copy todir="${module.release}${file.separator}app${file.separator}qman" failonerror="true">
+ <fileset dir="${web.module}" includes="*/**"/>
+ </copy>
+ <mkdir dir="${module.release}${file.separator}examples"/>
+ <copy todir="${module.release}${file.separator}examples">
+ <fileset dir="${examples.folder}"/>
+ </copy>
+ </target>
+
+ <target name="prepare-wsdm-module">
+ <mkdir dir="${web.module}"/>
+ <mkdir dir="${web-inf.folder}"/>
+ <mkdir dir="${classes.folder}"/>
+ <copy file=".${file.separator}web.xml" todir="${web-inf.folder}" verbose="false"/>
+ <copy todir="${classes.folder}" verbose="false">
+ <fileset dir="${module.classes}">
+ <include name="wsdl/**"/>
+ <include name="muse.xml"/>
+ <include name="router-entries/**"/>
+ </fileset>
+ </copy>
+ <copy todir="${web-inf.folder}">
+ <fileset dir="${build}" includes="${module.libs}">
+ <exclude name="lib/jetty*.jar"/>
+ <exclude name="lib/start*.jar"/>
+ </fileset>
+ </copy>
+ <copy todir="${web-inf.folder}${file.separator}lib">
+ <fileset dir="${build}/lib">
+ <include name="qpid-client-*.jar"/>
+ <include name="qpid-common-*.jar"/>
+ <include name="qpid-management-client-*.jar"/>
+ <exclude name="qpid-client-example*.jar"/>
+ <exclude name="qpid-client-tests*.jar"/>
+ <exclude name="qpid-common-tests*.jar"/>
+ <exclude name="qpid-management-client-tests*.jar"/>
+ </fileset>
+ </copy>
+ <copy todir="${web.module}">
+ <fileset dir="${module.src}${file.separator}..${file.separator}..${file.separator}..${file.separator}console">
+ <include name="*/**"/>
+ </fileset>
+ </copy>
+ </target>
+ <target name="jar.manifest" depends="compile" if="module.manifest">
+ <jar destfile="${module.jar}" manifest="${module.manifest}">
+ <fileset dir="${module.classes}" casesensitive="yes">
+ <include name="**/**"/>
+ <exclude name="wsdl/**"/>
+ <exclude name="muse.xml"/>
+ <exclude name="router-entries/**"/>
+ </fileset>
+ </jar>
+ </target>
+ <target name="jar.nomanifest" depends="compile" unless="module.manifest">
+ <jar destfile="${module.jar}">
+ <metainf dir="${project.root}${file.separator}resources/" />
+ <fileset dir="${module.classes}" casesensitive="yes">
+ <include name="**/**"/>
+ <exclude name="wsdl/**"/>
+ <exclude name="muse.xml"/>
+ <exclude name="router-entries/**"/>
+ </fileset>
+ </jar>
+ </target>
+ <target name="postbuild" depends="prepare-wsdm-module,copy-examples-to-build,copy-README-to-build" description="Build WS-DM module"/>
+
+ <path id="module.test.path">
+ <pathelement path="${module.test.classes}" />
+ <path refid="module.test.libs"/>
+ <fileset dir="${build}/lib">
+ <include name="qpid-client-*.jar"/>
+ <include name="qpid-common-*.jar"/>
+ <include name="qpid-management-client-*.jar"/>
+ <exclude name="qpid-client-example*.jar"/>
+ <exclude name="qpid-client-tests*.jar"/>
+ <exclude name="qpid-common-tests*.jar"/>
+ <exclude name="qpid-management-client-tests*.jar"/>
+ </fileset>
+ </path>
+
+ <target name="copy-README-to-build">
+ <copy todir="${module.build}">
+ <fileset dir="${module.src}${file.separator}..${file.separator}..${file.separator}..">
+ <include name="README.txt"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="copy-examples-to-build">
+ <mkdir dir="${examples.folder}${file.separator}src"/>
+ <mkdir dir="${examples.folder}${file.separator}sample_messages"/>
+ <copy todir="${examples.folder}">
+ <fileset dir="${module.src}${file.separator}..${file.separator}..${file.separator}example">
+ <include name="README.txt"/>
+ </fileset>
+ </copy>
+ <copy todir="${examples.folder}${file.separator}src">
+ <fileset dir="${module.src}${file.separator}..${file.separator}..${file.separator}example">
+ <include name="**/*.java"/>
+ <exclude name="**/*.out.*"/>
+ </fileset>
+ </copy>
+ <copy todir="${examples.folder}${file.separator}sample_messages">
+ <fileset dir="${module.src}${file.separator}..${file.separator}..${file.separator}example" >
+ <exclude name="**/*.java"/>
+ <exclude name="**/README.txt"/>
+ <include name="**/*.out.*"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="test" depends="build,compile-tests" if="module.test.src.exists" unless="${dontruntest}" description="execute unit tests">
+ <delete file="${module.failed}"/>
+ <echo message="Using profile:${profile}" level="info"/>
+ <junit fork="${test.fork}" maxmemory="1024M" reloading="no"
+ haltonfailure="${haltonfailure}" haltonerror="${haltonerror}"
+ failureproperty="test.failures" printsummary="on" timeout="600000" >
+
+ <jvmarg value="${jvm.args}"/>
+ <sysproperty key="qman.war" value="${web.module}"/>
+
+ <formatter type="plain"/>
+ <formatter type="xml"/>
+
+ <classpath refid="module.test.path"/>
+
+ <batchtest fork="${test.fork}" todir="${module.results}">
+ <fileset dir="${module.test.src}" excludes="${module.test.excludes}">
+ <include name="**/${test}.java"/>
+ </fileset>
+ </batchtest>
+ </junit>
+ <antcall target="touch-failed"/>
+ <condition property="failed">
+ <and>
+ <isfalse value="${test.failures.ignore}"/>
+ <available file="${module.failed}"/>
+ </and>
+ </condition>
+ <fail if="failed" message="TEST SUITE FAILED"/>
+ </target>
+</project>
diff --git a/java/management/client/console/brokers_management.jsp b/java/management/client/console/brokers_management.jsp
new file mode 100644
index 0000000000..f307006ac1
--- /dev/null
+++ b/java/management/client/console/brokers_management.jsp
@@ -0,0 +1,209 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.List"%>
+<%@page import="java.util.*"%>
+<%@page import="java.net.URI"%>
+<%@page import="javax.xml.namespace.QName"%>
+<%@page import="org.w3c.dom.Element"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Brokers Management"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top">
+ <fieldset>
+ <legend>Connected Brokers</legend>
+ <table width="100%" cellspacing="1">
+ <tr>
+ <th nowrap="nowrap" align="center">Host</th>
+ <th nowrap="nowrap" align="center" >Port</th>
+ <th nowrap="nowrap" align="center">Virtual Host</th>
+ <th nowrap="nowrap" align="center">Username</th>
+ <th nowrap="nowrap" align="center">Initial Pool Capacity</th>
+ <th nowrap="nowrap" align="center">Max Pool Capacity</th>
+ <th nowrap="nowrap" align="center">Max Wait Timeout</th>
+ </tr>
+ <c:forEach var="broker" items="${model}" varStatus="rowCounter">
+ <c:choose>
+ <c:when test="${rowCounter.count % 2 == 0}">
+ <c:set var="bgcolor" scope="page" value="EAEAEA"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" scope="page" value="FFFFFF"/>
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.host}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.port}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.virtualHost}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.username}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.initialPoolCapacity}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.maxPoolCapacity}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${broker.maxWaitTimeout}"/></td>
+ </tr>
+ </c:forEach>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <form name="form" action="<%=request.getContextPath()%>/brokers_management" method="post">
+ <fieldset>
+ <legend>New Broker Connection Data</legend>
+ <table>
+ <tr>
+ <td>
+ Host :
+ </td>
+ <td>
+ <input type="text" name="host"/>
+ </td>
+ <td style="font-size: x-small;">
+ The hostname where the broker is running.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Port :
+ </td>
+ <td>
+ <input type="text" name="port"/>
+ </td>
+ <td style="font-size: x-small;">
+ The port number where the broker is running.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Virtual Host :
+ </td>
+ <td>
+ <input type="text" name="virtualHost"/>
+ </td>
+ <td style="font-size: x-small;">
+ The virtual host name.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Username :
+ </td>
+ <td>
+ <input type="text" name="username"/>
+ </td>
+ <td style="font-size: x-small;">
+ The username used for estabilish connection with broker.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Password :
+ </td>
+ <td>
+ <input type="text" name="password"/>
+ </td>
+ <td style="font-size: x-small;">
+ The password used for estabilish connection with broker.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Initial Pool Capacity :
+ </td>
+ <td>
+ <input type="text" name="initialCapacity"/>
+ </td>
+ <td style="font-size: x-small;">
+ The number of connections that must be immediately opened.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Max Pool Capacity :
+ </td>
+ <td>
+ <input type="text" name="maxCapacity"/>
+ </td>
+ <td style="font-size: x-small;">
+ The maximum number of open connections.
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Max Wait Timeout :
+ </td>
+ <td>
+ <input type="text" name="maxWaitTimeout"/>
+ </td>
+ <td style="font-size: x-small;">
+ The maximum amount of time that a client will wait for obtaining a connection.
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3" align="center">
+ <input type="submit" value="Connect"/>
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </form>
+ </tr>
+ <tr>
+ <td nowrap style="font-size: x-small; font-weight: bold; color=red;">
+ <ul>
+ <c:forEach var="errorMessage" items="${errors}">
+ <li><span style="font-size: medium; font-weight: bold; color:red;">${errorMessage}</span></li>
+ </c:forEach>
+ </ul>
+ </td>
+ </tr>
+
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/console.jsp b/java/management/client/console/console.jsp
new file mode 100644
index 0000000000..d1a207fe32
--- /dev/null
+++ b/java/management/client/console/console.jsp
@@ -0,0 +1,122 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="System Overview"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div class="panel" align="justify" style="height:500px; overflow-y:auto;">
+ <span class="bodytext">
+ <table width="100%" border="0">
+ <tr>
+ <td valign="top" nowrap align="center">
+ <fieldset>
+ <legend>QMan</legend>
+ <table cellspacing="2">
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold;" align="center">Version</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.version}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Version Name</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.versionName}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Start Date</td></tr>
+ <tr>
+ <td style="font-size: xx-small;" align="center">
+ <fmt:formatDate
+ value="${requestScope.model.startDate}"
+ pattern="MM/dd/yyyy hh:mm:ss"/>
+ </td>
+ </tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Host</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.host}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Port</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.port}</td></tr>
+ </table>
+ </fieldset>
+ <fieldset>
+ <legend>Operating System</legend>
+ <table cellspacing="2">
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold;" align="center">Name</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.osName}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Version</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.osVersion}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Arch</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.archName}</td></tr>
+ <tr><td><br /></td></tr>
+ <tr><td style="color: #006633; font-size: xx-small; font-weight:bold" align="center">Processors</td></tr>
+ <tr><td style="font-size: xx-small;" align="center">${requestScope.model.processors}</td></tr>
+ </table>
+ </fieldset>
+ </td>
+ <td valign="top">
+ <fieldset>
+ <legend>JVM Environment</legend>
+ <table cellspacing="5">
+ <tr>
+ <td valign="top">
+ <h4 style="color: #006633; font-size: xx-small">Boot Classpath :
+ <p/>
+ <c:forEach var="entry" items="${model.bootClasspath}">
+ <c:out value="${entry}"/>;
+ <br/>
+ </c:forEach>
+ </h4>
+ </td>
+ <td valign="top">
+ <h4 style="color: #006633; font-size: xx-small">
+ Input Arguments :
+ <p/>
+ <c:forEach var="argument" items="${model.inputArguments}">
+ <c:out value="${argument}"/>;
+ <br/>
+ </c:forEach>
+ </h4>
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/error_page.jsp b/java/management/client/console/error_page.jsp
new file mode 100644
index 0000000000..73d2f9edc3
--- /dev/null
+++ b/java/management/client/console/error_page.jsp
@@ -0,0 +1,59 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Error Page"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div class="panel" align="justify" style="height:500px; overflow-y:auto;">
+ <span class="bodytext">
+ <table width="100%">
+ <tr><td nowrap style="font-weight: bold;">
+ We are not able to satify your request because an error has happened.
+ <br>Message : ${errorMessage}
+ </td></tr>
+ <tr><td nowrap style="font-size: xx-small; font-weight: bold;">
+ <c:forEach var="stackTrace" items="${exception.stackTrace}">
+ ${stackTrace}
+ <br>
+ </c:forEach>
+ </td></tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/fragments/header.jsp b/java/management/client/console/fragments/header.jsp
new file mode 100644
index 0000000000..b401fee7a0
--- /dev/null
+++ b/java/management/client/console/fragments/header.jsp
@@ -0,0 +1,36 @@
+<!--
+
+ 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.
+
+-->
+
+<div id="header" align="center">
+ <div id="pagetitle">
+ <div id="asf-header" align="left">
+ <table width="100%">
+ <tr>
+ <td align="left"><img src="images/qpid-logo.png" height="100" width="200" /></td>
+ <td align="right"><img src="images/asf-logo.png" height="69" width="225" /></td>
+ </tr>
+ </table>
+ </div>
+ <div id="title" class="titletext" align="right">
+ <span class="bluetitle"><%=request.getParameter("title")%></span>
+ </div>
+ </div>
+</div>
diff --git a/java/management/client/console/fragments/menu.jsp b/java/management/client/console/fragments/menu.jsp
new file mode 100644
index 0000000000..6924fd5d43
--- /dev/null
+++ b/java/management/client/console/fragments/menu.jsp
@@ -0,0 +1,31 @@
+<!--
+
+ 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.
+
+-->
+
+<div id="menu" align="center">
+ <div id="linksmenu" align="left">
+ <a href="<%=request.getContextPath()%>/console"> &nbsp; &gt; System Overview</a>
+ <a href="<%=request.getContextPath()%>/brokers_management">&nbsp; &gt; Brokers Management</a>
+ <a href="<%=request.getContextPath()%>/resources_management">&nbsp; &gt; Resources Management</a>
+ <a>&nbsp; &gt; Subscriptions Management</a>
+ <a>&nbsp; &gt; System Health</a>
+ <a href="<%=request.getContextPath()%>/logging_configuration">&nbsp; &gt; Logging Configuration</a>
+ </div>
+</div>
diff --git a/java/management/client/console/images/asf-logo.png b/java/management/client/console/images/asf-logo.png
new file mode 100644
index 0000000000..d824fab768
--- /dev/null
+++ b/java/management/client/console/images/asf-logo.png
Binary files differ
diff --git a/java/management/client/console/images/menu.gif b/java/management/client/console/images/menu.gif
new file mode 100644
index 0000000000..9946e8e231
--- /dev/null
+++ b/java/management/client/console/images/menu.gif
Binary files differ
diff --git a/java/management/client/console/images/menuleft.gif b/java/management/client/console/images/menuleft.gif
new file mode 100644
index 0000000000..f986ecfc27
--- /dev/null
+++ b/java/management/client/console/images/menuleft.gif
Binary files differ
diff --git a/java/management/client/console/images/menuright.gif b/java/management/client/console/images/menuright.gif
new file mode 100644
index 0000000000..afdd8bd04b
--- /dev/null
+++ b/java/management/client/console/images/menuright.gif
Binary files differ
diff --git a/java/management/client/console/images/qpid-logo.png b/java/management/client/console/images/qpid-logo.png
new file mode 100644
index 0000000000..5f4ccc3081
--- /dev/null
+++ b/java/management/client/console/images/qpid-logo.png
Binary files differ
diff --git a/java/management/client/console/images/style.css b/java/management/client/console/images/style.css
new file mode 100644
index 0000000000..a32682fa2f
--- /dev/null
+++ b/java/management/client/console/images/style.css
@@ -0,0 +1,202 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+body
+{
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+}
+
+tr th {
+ padding: 4px 8px 4px 8px;
+ background: #5E7796;
+ border: 1px solid #CCC;
+ color:#b8ce83;
+ font-size: smaller;
+}
+
+fieldset
+{
+ font-size: xx-small;
+}
+
+#header
+{
+ width:1024px;
+}
+
+#content
+{
+ width:1024px;
+}
+
+#contenttext
+{
+ float:left; width:824px;
+ background-color:#FFFFFF;
+ border-left:solid 1px #999999; border-right:solid 1px #999999;
+ border-bottom:solid 1px #999999; border-top:dotted 1px #CCCCCC;
+ min-height:360px;
+}
+
+#asf-header
+{
+ float:left;
+ width:1007px;
+ height:110px;
+ background-color:#FFFFFF;
+ border-right:solid 1px #999999;
+ border-left:solid 1px #999999;
+}
+
+#pagetitle
+{
+ position:relative;
+ float:left;
+ width:1024px;
+ height:110px;
+ background-color:#FFFFFF;
+}
+
+#title
+{
+ position:absolute;
+ right:20px;
+ bottom:0px;
+ width:1008px;
+}
+
+#menu
+{
+ float:left; width: 190px; margin: 0 0 0 -7px;
+}
+
+.panel{
+ padding:12px;
+ margin: 5px;
+ padding:10px;
+}
+
+.bodytext {
+ font: 0.7em Tahoma, sans-serif;
+ color: #666666;
+}
+
+.titletext {
+ font: 0.7em Tahoma, sans-serif;
+ font-size:36px;
+ font-weight:bold;
+ color: #CCCCCC;
+}
+
+.orangelogotext {
+ font: 0.7em Tahoma, sans-serif;
+ font-size:36px;
+ font-weight:bold;
+ color:#FF9900;
+}
+.orangetitle {
+ font: 0.7em Tahoma, sans-serif;
+ font-size:24px;
+ font-weight:bold;
+ color:#FF9900;
+}
+
+.bluetitle {
+ font: 0.7em Tahoma, sans-serif;
+ font-size:24px;
+ font-weight:bold;
+ color:#369;
+}
+
+#linksmenu a{
+ float:right;
+ width:183px;
+ height:20px;
+ background-color:#5E7796;
+ border-left:solid 1px #FFFFFF;
+ border-bottom:solid 1px #FFFFFF;
+ font: 0.7em Tahoma, sans-serif;
+ font-size: 11px;
+ font-weight:bold;
+ color: #FFFFFF;
+ text-decoration:none;
+ padding-top:5px;
+}
+#linksmenu a:hover
+{
+ background-color:#336;
+}
+
+
+#wsdmmenu
+{
+ float:left;
+ position: relative;
+ width: 600px;
+ font-size:75%;
+ margin: 0 0 0px 5px;
+ line-height:normal;
+}
+
+#wsdmmenu ul
+{
+ margin:0;
+ padding:0px 0px 0 0px;
+ list-style: none;
+}
+
+#wsdmmenu li
+{
+ display:inline;
+ margin:0;
+ padding:0;
+}
+
+#wsdmmenu a {
+ float:left;
+ background: url(menuleft.gif) no-repeat left top;
+ margin:0;
+ padding:0 0 0 4px;
+ text-decoration:none;
+}
+
+#wsdmmenu a span {
+ float:left;
+ display:block;
+ background: url(menuright.gif) no-repeat right top;
+ padding:5px 15px 4px 6px;
+ color:#888;
+}
+
+#wsdmmenu a span {float:none;}
+
+#wsdmmenu a:hover
+{
+ background-position:0% -42px;
+}
+
+#wsdmmenu a:hover span
+{
+ background-position:100% -42px;
+}
diff --git a/java/management/client/console/jmx_perspective.jsp b/java/management/client/console/jmx_perspective.jsp
new file mode 100644
index 0000000000..5d276a0edc
--- /dev/null
+++ b/java/management/client/console/jmx_perspective.jsp
@@ -0,0 +1,157 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.List"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resource Management - JMX Perspective"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=${resourceId}"><span>JMX</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>WS-DM</span></a></li>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top" colspan="2">
+ <fieldset>
+ <legend>ObjectName</legend>
+ <ul>
+ <c:forEach var="property" items="${nameAttributes}">
+ <li>
+ <c:out value="${property}"/>
+ </li>
+ </c:forEach>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <fieldset>
+ <legend>Attributes</legend>
+ <table width="100%" cellspacing="1">
+ <tr>
+ <th>Name</th>
+ <th>Type</th>
+ <th>Value</th>
+ <th>Access</th>
+ </tr>
+ <c:forEach var="attribute" items="${metadata.attributes}" varStatus="rowCounter">
+ <c:choose>
+ <c:when test="${rowCounter.count % 2 == 0}">
+ <c:set var="bgcolor" scope="page" value="EAEAEA"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" scope="page" value="FFFFFF"/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${attribute.writable}">
+ <c:set var="access" scope="page" value="RW"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="access" scope="page" value="RO"/>
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${attribute.name}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${attribute.type}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${attributes[attribute.name]}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${access}"/></td>
+ </tr>
+ </c:forEach>
+ </table>
+ </fieldset>
+ </td>
+ <td valign="top">
+ <fieldset>
+ <legend>Operations</legend>
+ <table width="100%" cellspacing="0">
+ <tr>
+ <th>Name</th>
+ <th>Arguments</th>
+ </tr>
+
+ <c:forEach var="operation" items="${metadata.operations}" varStatus="rowCounter">
+ <c:choose>
+ <c:when test="${rowCounter.count % 2 == 0}">
+ <c:set var="bgcolor" scope="page" value="EAEAEA"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" scope="page" value="FFFFFF"/>
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${operation.name}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ <ul>
+ <c:forEach var="argument" items="${operation.signature}">
+ <li>
+ <c:out value="${argument.name}"/> (<c:out value="${argument.type}"/>)
+ </li>
+ </c:forEach>
+ </ul>
+ </td>
+ </tr>
+ </c:forEach>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+
+
+
+
+
+
+
+
+
+
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/logging_configuration.jsp b/java/management/client/console/logging_configuration.jsp
new file mode 100644
index 0000000000..89f10567fa
--- /dev/null
+++ b/java/management/client/console/logging_configuration.jsp
@@ -0,0 +1,241 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Logging Configuration"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div class="panel" align="justify" style="height:500px; overflow-y:auto;">
+ <span class="bodytext">
+ <form method="post" name="form" action="<%=request.getContextPath() %>/logging_configuration">
+ <table>
+ <tr>
+ <td>
+ <fieldset>
+ <legend>WSDL & RDM Debugger</legend>
+ <table>
+ <tr>
+ <td>
+ <c:choose>
+ <c:when test="${wsdlDebugEnabled}">
+ <c:set var="checked" scope="page" value="checked"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="checked" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <input type="checkbox" ${checked} name="wsdlDebugEnabled" />
+ </td>
+ <td nowrap style="font-size: x-small;">
+ When this flag is checked all WSDL and RMD messages are written on log file (or console depending on your configuration.)
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <fieldset>
+ <legend>SOAP Messages Debugger</legend>
+ <table>
+
+ <tr>
+ <td>
+ <c:choose>
+ <c:when test="${soapDebugEnabled}">
+ <c:set var="checked" scope="page" value="checked"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="checked" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <input ${checked} type="checkbox" name="soapDebugEnabled"/>
+ </td>
+ <td nowrap style="font-size: x-small;">
+ When this flag is checked all SOAP messages (requests & responses) are written on log file (or console depending on your configuration.)
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <fieldset>
+ <legend>QMan Logger Level</legend>
+ <table>
+ <tr>
+ <td>
+ <c:choose>
+ <c:when test="${qmanLogLevel == 'DEBUG'}">
+ <c:set var="qmanDebug" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="qmanDebug" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${qmanLogLevel == 'INFO'}">
+ <c:set var="qmanInfo" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="qmanInfo" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${qmanLogLevel == 'WARN'}">
+ <c:set var="qmanWarn" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="qmanWarn" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${qmanLogLevel == 'ERROR'}">
+ <c:set var="qmanError" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="qmanError" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${qmanLogLevel == 'FATAL'}">
+ <c:set var="qmanFatal" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="qmanFatal" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+
+ <select name="qmanLogLevel">
+ <option ${qmanDebug} value="DEBUG">DEBUG</option>
+ <option ${qmanWarn} value="WARN">WARNING</option>
+ <option ${qmanInfo} value="INFO">INFO</option>
+ <option ${qmanError} value="ERROR">ERROR</option>
+ <option ${qmanFatal} value="FATAL">FATAL</option>
+ </select>
+ </td>
+ <td nowrap style="font-size: x-small;">
+ This is the current priority level set for QMan module (and sub-modules). Note that a WARNING level is recomended in production.
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <fieldset>
+ <legend>Web Server Logger Level</legend>
+ <table>
+
+ <tr>
+ <td>
+ <c:choose>
+ <c:when test="${webServerLogLevel == 'DEBUG'}">
+ <c:set var="webServerDebug" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="webServerDebug" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${webServerLogLevel == 'INFO'}">
+ <c:set var="webServerInfo" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="webServerInfo" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${webServerLogLevel == 'WARN'}">
+ <c:set var="webServerWarn" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="webServerWarn" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${webServerLogLevel == 'ERROR'}">
+ <c:set var="webServerError" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="webServerError" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${webServerLogLevel == 'FATAL'}">
+ <c:set var="webServerFatal" scope="page" value="selected='true'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="webServerFatal" scope="page" value=""/>
+ </c:otherwise>
+ </c:choose>
+
+ <select name="webServerLogLevel">
+ <option ${webServerDebug} value="DEBUG" >DEBUG</option>
+ <option ${webServerWarn} value="WARN">WARNING</option>
+ <option ${webServerInfo} value="INFO">INFO</option>
+ <option ${webServerError} value="ERROR">ERROR</option>
+ <option ${webServerFatak} value="FATAL">FATAL</option>
+ </select>
+ </td>
+ <td nowrap style="font-size: x-small; ">
+ This is the current priority level set for QMan module (and sub-modules). Note that a WARNING level is recomended in production.
+ </td>
+ </tr>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <input type="submit" value="Submit" title="Submit"/>
+ </td>
+ </tr>
+ </table>
+ <br/></br>
+ <span style="fony-size: medium; color: red; font-weight: bold">Note that in general a DEBUG level is not reccommended in production (especially for WSDL and SOAP debugger).</span>
+ </form>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/resources_management.jsp b/java/management/client/console/resources_management.jsp
new file mode 100644
index 0000000000..4a6f9efed6
--- /dev/null
+++ b/java/management/client/console/resources_management.jsp
@@ -0,0 +1,105 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.List"%>
+
+<%
+ BrokerModel model = (BrokerModel) request.getAttribute("model");
+%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resources Management"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <% if (model != null) {%>
+ <li><a href="#"><span>${model.id}</span></a></li>
+ <%} %>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify" style="height:500px; overflow-y:auto;">
+ <span class="bodytext">
+ <table width="100%" border="0" cellpadding="1" cellspacing="2">
+<%
+ if (model != null ){
+ Set<String> categoryNames = model.getCategoryNames();
+ for(String categoryName : categoryNames)
+ {
+ List<ObjectName> categoryObjects = model.getCategory(categoryName);
+%>
+ <tr>
+ <td valign="top" nowrap align="left">
+ <fieldset>
+ <legend><%=categoryName%></legend>
+ <h4 style="color: #006633; font-size: xx-small">
+ <ul>
+ <%
+ for (ObjectName objectName : categoryObjects)
+ {%>
+
+ <li>
+ <a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=<%=objectName%>">
+ <%=objectName.getKeyProperty(Names.OBJECT_ID)%>
+ </a>
+ </li>
+ <%
+ }
+ %>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+<%
+ }
+ } else {
+%>
+<table><tr>
+<td nowrap style="font-weight: bold;" >Sorry, but it seems that QMan is not connected with any broker...</td>
+</tr>
+</table>
+<%
+ }
+%>
+ </table>
+ </span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/tbd.jsp b/java/management/client/console/tbd.jsp
new file mode 100644
index 0000000000..3c1c87a7b0
--- /dev/null
+++ b/java/management/client/console/tbd.jsp
@@ -0,0 +1,48 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="TBD"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div class="panel" align="justify" style="height:500px; overflow-y:auto;">
+ <span class="bodytext">
+ Sorry, this feature is not yet available!
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/wsdm_operations_perspective.jsp b/java/management/client/console/wsdm_operations_perspective.jsp
new file mode 100644
index 0000000000..50f67c4492
--- /dev/null
+++ b/java/management/client/console/wsdm_operations_perspective.jsp
@@ -0,0 +1,174 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.*"%>
+<%
+ Map<String,String> java2Xml = new HashMap<String,String>();
+java2Xml.put(UUID.class.getName(),"qman:uuid");
+java2Xml.put(Long.class.getName(),"xsd:long");
+java2Xml.put(long.class.getName(),"xsd:long");
+java2Xml.put(Boolean.class.getName(),"xsd:boolean");
+java2Xml.put(boolean.class.getName(),"xsd:boolean");
+java2Xml.put(Double.class.getName(),"xsd:double");
+java2Xml.put(double.class.getName(),"xsd:double");
+java2Xml.put(Float.class.getName(),"xsd:float");
+java2Xml.put(float.class.getName(),"xsd:float");
+java2Xml.put(Integer.class.getName(),"xsd:integer");
+java2Xml.put(int.class.getName(),"xsd:integer");
+java2Xml.put(Short.class.getName(),"xsd:short");
+java2Xml.put(short.class.getName(),"xsd:short");
+java2Xml.put(String.class.getName(),"xsd:string");
+java2Xml.put(URI.class.getName(),"xsd:anyURI");
+java2Xml.put(Date.class.getName(),"xsd:dateTime");
+java2Xml.put(QName.class.getName(),"xsd:QName");
+java2Xml.put(Element.class.getName(),"xsd:element");
+java2Xml.put(byte[].class.getName(),"xsd:base64Binary");
+java2Xml.put(Long[].class.getName(),"qman:arrayOfLong");
+java2Xml.put(long[].class.getName(),"qman:arrayOfLong");
+java2Xml.put(Boolean[].class.getName(),"qman:arrayOfBoolean");
+java2Xml.put(boolean[].class.getName(),"qman:arrayOfBoolean");
+java2Xml.put(Double[].class.getName(),"qman:arrayOfDouble");
+java2Xml.put(double[].class.getName(),"qman:arrayOfDouble");
+java2Xml.put(Float[].class.getName(),"qman:arrayOfFloat");
+java2Xml.put(float[].class.getName(),"qman:arrayOfFloat");
+java2Xml.put(Integer[].class.getName(),"qman:arrayOfInteger");
+java2Xml.put(int[].class.getName(),"qman:arrayOfInteger");
+java2Xml.put(Short[].class.getName(),"qman:arrayOfShort");
+java2Xml.put(short[].class.getName(),"qman:arrayOfShort");
+java2Xml.put(String[].class.getName(),"qman:arrayOfString");
+java2Xml.put(URI[].class.getName(),"qman:arrayOfURI");
+java2Xml.put(Date[].class.getName(),"qman:arrayOfDate");
+java2Xml.put(Map.class.getName(),"qman:map");
+java2Xml.put(HashMap.class.getName(),"qman:map");
+
+pageContext.setAttribute("types",java2Xml);
+%>
+<%@page import="java.net.URI"%>
+<%@page import="javax.xml.namespace.QName"%>
+<%@page import="org.w3c.dom.Element"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resource Management - WS-DM Operations Perspective"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=${resourceId}"><span>JMX</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?wsresourceId=${resourceId}"><span>WS-DM</span></a></li>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top" colspan="2">
+ <fieldset>
+ <legend>Resource ID</legend>
+ <ul>
+ <c:forEach var="property" items="${nameAttributes}">
+ <li>
+ <c:out value="${property}"/>
+ </li>
+ </c:forEach>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div id="wsdmmenu" align="left" style="font-size: small;">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>Properties</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_operations_perspective?resourceId=${resourceId}""><span>Operations</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_wsdl_perspective?resourceId=${resourceId}""><span>WSDL</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_rmd_perspective?resourceId=${resourceId}""><span>RDM</span></a></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <fieldset>
+ <legend>Attributes</legend>
+ <table width="100%" cellspacing="1">
+ <tr>
+ <th nowrap="nowrap" align="center">Name</th>
+ <th nowrap="nowrap" align="center">Arguments</th>
+ <th nowrap="nowrap" align="center">Faults</th>
+ </tr>
+ <c:forEach var="operation" items="${metadata.operations}" varStatus="rowCounter">
+ <c:choose>
+ <c:when test="${rowCounter.count % 2 == 0}">
+ <c:set var="bgcolor" scope="page" value="EAEAEA"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" scope="page" value="FFFFFF"/>
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${operation.name}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ <ul>
+ <c:forEach var="argument" items="${operation.signature}">
+ <li>
+ <c:out value="${argument.name}"/> (<c:out value="${types[argument.type]}"/>)
+ </li>
+ </c:forEach>
+ </ul>
+ </td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ <ul>
+ <li>qman:EntityInstanceNotFoundFault</li>
+ <li>qman:OperationInvocationFault</li>
+ <li>qman:QManFault</li>
+ </ul>
+ </td>
+ </tr>
+ </c:forEach>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/wsdm_properties_perspective.jsp b/java/management/client/console/wsdm_properties_perspective.jsp
new file mode 100644
index 0000000000..7769abc71c
--- /dev/null
+++ b/java/management/client/console/wsdm_properties_perspective.jsp
@@ -0,0 +1,218 @@
+<!--
+
+ 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.
+
+-->
+
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.List"%>
+<%@page import="java.util.*"%>
+
+<%
+ Map<String,String> java2Xml = new HashMap<String,String>();
+java2Xml.put(UUID.class.getName(),"qman:uuid");
+java2Xml.put(Long.class.getName(),"xsd:long");
+java2Xml.put(long.class.getName(),"xsd:long");
+java2Xml.put(Boolean.class.getName(),"xsd:boolean");
+java2Xml.put(boolean.class.getName(),"xsd:boolean");
+java2Xml.put(Double.class.getName(),"xsd:double");
+java2Xml.put(double.class.getName(),"xsd:double");
+java2Xml.put(Float.class.getName(),"xsd:float");
+java2Xml.put(float.class.getName(),"xsd:float");
+java2Xml.put(Integer.class.getName(),"xsd:integer");
+java2Xml.put(int.class.getName(),"xsd:integer");
+java2Xml.put(Short.class.getName(),"xsd:short");
+java2Xml.put(short.class.getName(),"xsd:short");
+java2Xml.put(String.class.getName(),"xsd:string");
+java2Xml.put(URI.class.getName(),"xsd:anyURI");
+java2Xml.put(Date.class.getName(),"xsd:dateTime");
+java2Xml.put(QName.class.getName(),"xsd:QName");
+java2Xml.put(Element.class.getName(),"xsd:element");
+java2Xml.put(byte[].class.getName(),"xsd:base64Binary");
+java2Xml.put(Long[].class.getName(),"qman:arrayOfLong");
+java2Xml.put(long[].class.getName(),"qman:arrayOfLong");
+java2Xml.put(Boolean[].class.getName(),"qman:arrayOfBoolean");
+java2Xml.put(boolean[].class.getName(),"qman:arrayOfBoolean");
+java2Xml.put(Double[].class.getName(),"qman:arrayOfDouble");
+java2Xml.put(double[].class.getName(),"qman:arrayOfDouble");
+java2Xml.put(Float[].class.getName(),"qman:arrayOfFloat");
+java2Xml.put(float[].class.getName(),"qman:arrayOfFloat");
+java2Xml.put(Integer[].class.getName(),"qman:arrayOfInteger");
+java2Xml.put(int[].class.getName(),"qman:arrayOfInteger");
+java2Xml.put(Short[].class.getName(),"qman:arrayOfShort");
+java2Xml.put(short[].class.getName(),"qman:arrayOfShort");
+java2Xml.put(String[].class.getName(),"qman:arrayOfString");
+java2Xml.put(URI[].class.getName(),"qman:arrayOfURI");
+java2Xml.put(Date[].class.getName(),"qman:arrayOfDate");
+java2Xml.put(Map.class.getName(),"qman:map");
+java2Xml.put(HashMap.class.getName(),"qman:map");
+
+pageContext.setAttribute("types",java2Xml);
+%>
+<%@page import="java.net.URI"%>
+<%@page import="javax.xml.namespace.QName"%>
+<%@page import="org.w3c.dom.Element"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resource Management - WS-DM Properties Perspective"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=${resourceId}"><span>JMX</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>WS-DM</span></a></li>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top" colspan="2">
+ <fieldset>
+ <legend>Resource ID</legend>
+ <ul>
+ <c:forEach var="property" items="${nameAttributes}">
+ <li>
+ <c:out value="${property}"/>
+ </li>
+ </c:forEach>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div id="wsdmmenu" align="left" style="font-size: small;">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>Properties</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_operations_perspective?resourceId=${resourceId}""><span>Operations</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_wsdl_perspective?resourceId=${resourceId}""><span>WSDL</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_rmd_perspective?resourceId=${resourceId}""><span>RDM</span></a></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <fieldset>
+ <legend>Attributes</legend>
+ <table width="100%" cellspacing="1">
+ <tr>
+ <th nowrap="nowrap" align="center">Name</th>
+ <th nowrap="nowrap" align="center" >Type</th>
+ <th nowrap="nowrap" align="center">Value</th>
+ <th nowrap="nowrap" align="center">Mutable</th>
+ <th nowrap="nowrap" align="center">Access</th>
+ <th nowrap="nowrap" align="center">Valid Values</th>
+ <th nowrap="nowrap" align="center">Static Values</th>
+ <th nowrap="nowrap" align="center">Initial Values</th>
+ </tr>
+ <c:forEach var="attribute" items="${metadata.attributes}" varStatus="rowCounter">
+ <c:choose>
+ <c:when test="${rowCounter.count % 2 == 0}">
+ <c:set var="bgcolor" scope="page" value="EAEAEA"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" scope="page" value="FFFFFF"/>
+ </c:otherwise>
+ </c:choose>
+ <c:choose>
+ <c:when test="${attribute.writable}">
+ <c:set var="access" scope="page" value="RW"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="access" scope="page" value="RO"/>
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${attribute.name}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${types[attribute.type]}"/></td>
+ <td style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${attributes[attribute.name]}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ &radic;
+ <%--
+ <c:out value="${attribute.mutable}"/>
+ --%>
+ </td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}"><c:out value="${access}"/></td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ N.A.
+<%--
+ <ul>
+ <c:forEach var="value" items="${attribute.validValues}">
+ <li>
+ <c:out value="${value}"/>
+ </li>
+ </c:forEach>
+ </ul>
+--%>
+ </td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ N.A.
+<%--
+ <ul>
+ <c:forEach var="value" items="${attribute.staticValues}">
+ <li>
+ <c:out value="${value}"/>
+ </li>
+ </c:forEach>
+ </ul>
+--%>
+ </td>
+ <td nowrap style="font-size: xx-small; font-weight: bold;" bgcolor="${bgcolor}">
+ N.A.
+<%--
+ <ul>
+ <c:forEach var="value" items="${attribute.initialValues}">
+ <li>
+ <c:out value="${value}"/>
+ </li>
+ </c:forEach>
+ </ul>
+--%>
+ </td>
+ </tr>
+ </c:forEach>
+ </table>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/wsdm_rmd_perspective.jsp b/java/management/client/console/wsdm_rmd_perspective.jsp
new file mode 100644
index 0000000000..083732668b
--- /dev/null
+++ b/java/management/client/console/wsdm_rmd_perspective.jsp
@@ -0,0 +1,99 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix="c"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x"%>
+
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.*"%>
+<%@page import="java.net.URI"%>
+<%@page import="javax.xml.namespace.QName"%>
+<%@page import="org.w3c.dom.Element"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resource Management - WS-DM RMD Perspective"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=${resourceId}"><span>JMX</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?wsresourceId=${resourceId}"><span>WS-DM</span></a></li>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top" colspan="2">
+ <fieldset>
+ <legend>Resource ID</legend>
+ <ul>
+ <c:forEach var="property" items="${nameAttributes}">
+ <li>
+ <c:out value="${property}"/>
+ </li>
+ </c:forEach>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div id="wsdmmenu" align="left" style="font-size: small;">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>Properties</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_operations_perspective?resourceId=${resourceId}""><span>Operations</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_wsdl_perspective?resourceId=${resourceId}""><span>WSDL</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_rmd_perspective?resourceId=${resourceId}""><span>RDM</span></a></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div class="panel" align="left" style="height:500px; width=200px; overflow-y:auto; font-size: smaller; font-weight:bold;">
+ <pre> <c:out value="${rmd}" /> </pre>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/console/wsdm_wsdl_perspective.jsp b/java/management/client/console/wsdm_wsdl_perspective.jsp
new file mode 100644
index 0000000000..0674c51a97
--- /dev/null
+++ b/java/management/client/console/wsdm_wsdl_perspective.jsp
@@ -0,0 +1,99 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix="c"%>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x"%>
+
+<%@page import="org.apache.qpid.management.web.action.BrokerModel"%>
+<%@page import="java.util.Set"%>
+<%@page import="javax.management.ObjectName"%>
+<%@page import="org.apache.qpid.management.Names"%>
+<%@page import="java.util.*"%>
+<%@page import="java.net.URI"%>
+<%@page import="javax.xml.namespace.QName"%>
+<%@page import="org.w3c.dom.Element"%>
+<html>
+ <head>
+ <link rel="stylesheet" href="<%=request.getContextPath()%>/images/style.css" type="text/css" />
+ <title>QMan Administration Console</title>
+ </head>
+ <body>
+ <div id="page" align="center">
+ <jsp:include page="/fragments/header.jsp">
+ <jsp:param name="title" value="Resource Management - WS-DM WSDL Perspective"/>
+ </jsp:include>
+
+ <div id="content" align="center">
+ <jsp:include page="/fragments/menu.jsp"/>
+
+ <div id="contenttext">
+ <div id="wsdmmenu" align="left">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/jmx_perspective?resourceId=${resourceId}"><span>JMX</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>WS-DM</span></a></li>
+ </ul>
+ </div>
+ <br />
+ <div class="panel" align="justify">
+ <span class="bodytext">
+ <table width="100%">
+ <tr>
+ <td valign="top" colspan="2">
+ <fieldset>
+ <legend>Resource ID</legend>
+ <ul>
+ <c:forEach var="property" items="${nameAttributes}">
+ <li style="color : black;">
+ <c:out value="${property}"/>
+ </li>
+ </c:forEach>
+ </ul>
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div id="wsdmmenu" align="left" style="font-size: small;">
+ <ul>
+ <li><a href="<%=request.getContextPath()%>/wsdm_properties_perspective?resourceId=${resourceId}"><span>Properties</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_operations_perspective?resourceId=${resourceId}""><span>Operations</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_wsdl_perspective?resourceId=${resourceId}""><span>WSDL</span></a></li>
+ <li><a href="<%=request.getContextPath()%>/wsdm_rmd_perspective?resourceId=${resourceId}""><span>RDM</span></a></li>
+ </ul>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <div class="panel" align="left" style="height:500px; width=200px; overflow-y:auto; font-size: smaller; font-weight:bold;">
+ <pre> <c:out value="${wsdl}" /> </pre>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/java/management/client/doc/man/qman-jmx b/java/management/client/doc/man/qman-jmx
new file mode 100644
index 0000000000..064c00eae5
--- /dev/null
+++ b/java/management/client/doc/man/qman-jmx
@@ -0,0 +1,17 @@
+.TH qman-jmx
+.SH NAME
+qman-jmx is a Management bridge that exposes one (or several) Qpid broker domain model as MBeans that are accessible through the Java Management Extensions (JMX). Once you run qman you need to start a JMX Console such as JConsole to browse the MBeans exposed by Q-Man.
+.SH SYNOPSIS
+qman
+.SH DESCRIPTION
+For more information on customizing qman-jmx for your own environment please read http://cwiki.apache.org/confluence/display/qpid/Qman+Tool
+.SH Configuration
+.SS Classpath
+By default qman jars will be loaded from /usr/share/java. If you want to load from an alternative location you could specify it using QPID_LIB_PATH var.
+.SS Config file
+qman can be configured to connect to one or more brokers at startup by adding brokers in
+.I /etc/qman-config.xml
+If you want to load qman with qman-config.xml from a different location, you can specify it using QPID_CONFIG_FILE var.
+.SS log4j configuration
+qman expects qman.log4j file to be in the classpath. By default it will be put in
+.I /usr/share/java
diff --git a/java/management/client/etc/jetty.xml b/java/management/client/etc/jetty.xml
new file mode 100644
index 0000000000..975053a518
--- /dev/null
+++ b/java/management/client/etc/jetty.xml
@@ -0,0 +1,47 @@
+<?xml version="1.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.
+
+-->
+
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+<Configure id="Server" class="org.mortbay.jetty.Server">
+ <Set name="StopAtShutdown">true</Set>
+ <Set name="Connectors">
+ <Array type="org.mortbay.jetty.Connector">
+ <Item>
+ <New
+ class="org.mortbay.jetty.nio.SelectChannelConnector">
+ <Set name="port">
+ <SystemProperty name="qman.port" default="8080" />
+ </Set>
+ <Set name="host">
+ <SystemProperty name="qman.host" default="localhost" />
+ </Set>
+ </New>
+ </Item>
+ </Array>
+ </Set>
+ <Set name="handler">
+ <New class="org.mortbay.jetty.webapp.WebAppContext">
+ <Set name="contextPath">/qman</Set>
+ <Set name="war"><SystemProperty name="QMAN_HOME" default=".." />/app/qman</Set>
+ </New>
+ </Set>
+</Configure>
diff --git a/java/management/client/etc/qman-config.xml b/java/management/client/etc/qman-config.xml
new file mode 100644
index 0000000000..cdc840e967
--- /dev/null
+++ b/java/management/client/etc/qman-config.xml
@@ -0,0 +1,68 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<configuration>
+
+<!--
+Default configuration for QMan has no broker settings;
+that is, there's no broker configured at startup.
+If you want to connect with a running broker when QMan starts up,
+you can do that uncommenting and editing the template reported below.
+-->
+<!-- <brokers>
+ <broker>
+ <host>localhost</host>
+ <port>5672</port>
+ <virtual-host>test</virtual-host>
+ <user>guest</user>
+ <password>guest</password>
+ <max-pool-capacity>4</max-pool-capacity>
+ <initial-pool-capacity>0</initial-pool-capacity>
+ <max-wait-timeout>-1</max-wait-timeout>
+ </broker>
+ <broker>
+ <host>localhost</host>
+ <port>5672</port>
+ <virtual-host>test</virtual-host>
+ <user>guest</user>
+ <password>guest</password>
+ <max-pool-capacity>4</max-pool-capacity>
+ <initial-pool-capacity>0</initial-pool-capacity>
+ <max-wait-timeout>-1</max-wait-timeout>
+ </broker>
+ </brokers>
+ -->
+ <!-- Internal worked manager configuration-->
+ <work-manager>
+ <!-- The size of the worker thread pool -->
+ <pool-capacity>5</pool-capacity>
+
+ <!-- Maximum size of the worker thread pool -->
+ <max-pool-capacity>15</max-pool-capacity>
+
+ <!--
+ when the current number of threads is greater than
+ the pool-capacity, this is the maximum time that excess threads
+ can be in an idle state (without any task assigned) before terminating.
+ The value is expressed is milliseconds.
+ -->
+ <keep-alive-time>5000</keep-alive-time>
+ </work-manager>
+</configuration>
diff --git a/java/management/client/etc/qman-config.xsd b/java/management/client/etc/qman-config.xsd
new file mode 100644
index 0000000000..38282c63d1
--- /dev/null
+++ b/java/management/client/etc/qman-config.xsd
@@ -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.
+ -
+-->
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:element name="broker">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="host" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="port" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="virtual-host" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="user" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="password" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="max-pool-capacity" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="initial-pool-capacity" minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="max-wait-timeout" minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="brokers">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="broker" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="configuration">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="brokers" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="host" type="xsd:string"/>
+ <xsd:element name="initial-pool-capacity" type="xsd:integer"/>
+ <xsd:element name="max-pool-capacity" type="xsd:integer"/>
+ <xsd:element name="max-wait-timeout" type="xsd:integer"/>
+ <xsd:element name="password" type="xsd:string"/>
+ <xsd:element name="port" type="xsd:integer"/>
+ <xsd:element name="user" type="xsd:string"/>
+ <xsd:element name="virtual-host"type="xsd:string"/>
+
+</schema> \ No newline at end of file
diff --git a/java/management/client/etc/qman.log4j b/java/management/client/etc/qman.log4j
new file mode 100644
index 0000000000..bf6f940a6c
--- /dev/null
+++ b/java/management/client/etc/qman.log4j
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+log4j.rootLogger=${root.logging.level}
+
+log4j.logger.org.apache.qpid=ERROR, console
+log4j.additivity.org.apache.qpid=false
+
+log4j.logger.org.apache.qpid.management.client=DEBUG, console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.Threshold=error
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
diff --git a/java/management/client/src/example/ConnectWithBroker.out.ok b/java/management/client/src/example/ConnectWithBroker.out.ok
new file mode 100644
index 0000000000..33af477b98
--- /dev/null
+++ b/java/management/client/src/example/ConnectWithBroker.out.ok
@@ -0,0 +1,81 @@
+ ConnectWithBrokerExample
+-------------------------------------------------------------------
+
+This example shows how to connect QMan with a broker using
+the adapter interface.
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://amqp.apache.org/qpid/management/qman/Connect</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:48bf9a1b-f814-7391-b5cf-d163de4ac068</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <qman:Connect xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <qman:host>sofia.gazzax.com</qman:host>
+ <qman:port>5672</qman:port>
+ <qman:username>test</qman:username>
+ <qman:password>a.gazzarini</qman:password>
+ <qman:virtualHost>p1ssw9rd</qman:virtualHost>
+ <qman:initialPoolCapacity>1</qman:initialPoolCapacity>
+ <qman:maxPoolCapacity>4</qman:maxPoolCapacity>
+ <qman:maxWaitTimeout>2000</qman:maxWaitTimeout>
+ </qman:Connect>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/fault</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:220bfe54-d5f4-4a04-794c-0f5d99a64567</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:48bf9a1b-f814-7391-b5cf-d163de4ac068</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://romagazzarini:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <soap:Fault>
+ <soap:Code xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <soap:Value>qman:QMan</soap:Value>
+ </soap:Code>
+ <soap:Reason>
+ <soap:Text>Unable to connect with the requested broker. Underlying exception message was null</soap:Text>
+ </soap:Reason>
+ <soap:Detail>
+ <qman:OperationInvocationFault xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrf-bf:Timestamp xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2">2009-02-17T10:37:08+01:00</wsrf-bf:Timestamp>
+ <wsrf-bf:OriginatorReference xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2">
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing"/>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/adapter</wsa:Address>
+ </wsrf-bf:OriginatorReference>
+ <qman:host>sofia.gazzax.com</qman:host>
+ <qman:port>5672</qman:port>
+ <qman:username>test</qman:username>
+ <qman:virtualHost>p1ssw9rd</qman:virtualHost>
+ </qman:OperationInvocationFault>
+ </soap:Detail>
+ </soap:Fault>
+ </soap:Body>
+</soap:Envelope>
+
+-----------------------EXAMPLE FAILURE-----------
+Not well-defined exception was detected while
+running the example.
+org.apache.muse.ws.addressing.soap.SoapFault: Unable to connect with the requested broker. Underlying exception message was null
+ at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:298)
+ at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:232)
+ at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:211)
+ at org.apache.qpid.management.example.ConnectWithBrokerExample.executeExample(ConnectWithBrokerExample.java:146)
+ at org.apache.qpid.management.example.ConnectWithBrokerExample.execute(ConnectWithBrokerExample.java:97)
+ at org.apache.qpid.management.example.ConnectWithBrokerExample.main(ConnectWithBrokerExample.java:201)
+--------------------------------------------------------
diff --git a/java/management/client/src/example/GetMultipleResourceProperties.out.ok b/java/management/client/src/example/GetMultipleResourceProperties.out.ok
new file mode 100644
index 0000000000..005841488d
--- /dev/null
+++ b/java/management/client/src/example/GetMultipleResourceProperties.out.ok
@@ -0,0 +1,262 @@
+ GetMultipleResourcePropertiesExample
+-------------------------------------------------------------------
+
+This example shows how to get properties from a
+WS-Resource using one request.
+First of all a request is send to WS-DM in order to get
+all registered WS-Resources.
+If the returned list is not empty then a GetMetadataRequest
+to the first child.
+The result metadata descriptor contains all property names of
+the target WS-Resource.
+Those names are then used for retrieving the corresponding values
+using the GetMultipleResourceProperties request.
+
+-------------------------------------------------------------------
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:1a72feb1-7d76-1014-66d7-cd03aeff3525</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:783956b1-4de7-f4b6-5421-536f5f310b9a</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:1a72feb1-7d76-1014-66d7-cd03aeff3525</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-sg:Entry xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">
+ <wsrf-sg:ServiceGroupEntryEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/ServiceGroupEntry</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <muse-wsa:ResourceId xmlns:muse-wsa="http://ws.apache.org/muse/addressing">uuid:b220e2bd-0370-da4e-fc71-5e283954d319</muse-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:ServiceGroupEntryEPR>
+ <wsrf-sg:MemberServiceEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:MemberServiceEPR>
+ <wsrf-sg:Content/>
+ </wsrf-sg:Entry>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:588288c9-8bb7-04e9-e7bf-7be1e2fe41fb</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://docs.oasis-open.org/wsrf/rmd-1</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:77c5520b-d450-5a8a-7e2b-22a1079392f2</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:588288c9-8bb7-04e9-e7bf-7be1e2fe41fb</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsrmd:MetadataDescriptor
+ interface="qman:QManWsResourcePortType"
+ name="QManWsResourceMetadata"
+ wsdlLocation="http://docs.oasis-open.org/wsrf/rmd-1 QManWsResource.wsdl"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:MgmtPubInterval" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Name" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:TerminationTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable"
+ name="qman:MsgTotalEnqueues" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Arguments" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:VhostRef" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:CurrentTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:ExpireTime" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Durable" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:ConsumerCount" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:Type" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ </wsrmd:MetadataDescriptor>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:783fc044-58a9-e780-a2ba-5b2ac0454985</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetMultipleResourceProperties xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MgmtPubInterval</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Name</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MsgTotalEnqueues</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Arguments</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:VhostRef</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:ExpireTime</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Durable</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:ConsumerCount</wsrf-rp:ResourceProperty>
+ <wsrf-rp:ResourceProperty xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Type</wsrf-rp:ResourceProperty>
+ </wsrf-rp:GetMultipleResourceProperties>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:9a2d76dd-52ba-ac7c-74cf-4acd99708529</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:783fc044-58a9-e780-a2ba-5b2ac0454985</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetMultipleResourcePropertiesResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:MgmtPubInterval xmlns:qman="http://amqp.apache.org/qpid/management/qman">32767</qman:MgmtPubInterval>
+ <qman:Name xmlns:qman="http://amqp.apache.org/qpid/management/qman">Initial Name</qman:Name>
+ <qman:MsgTotalEnqueues xmlns:qman="http://amqp.apache.org/qpid/management/qman">9223372036854775797</qman:MsgTotalEnqueues>
+ <qman:Arguments
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <qman:entry>
+ <qman:key>Key3</qman:key>
+ <qman:value xsi:type="xsd:integer">2147483647</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key4</qman:key>
+ <qman:value xsi:type="xsd:float">3.4028235E38</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key1</qman:key>
+ <qman:value xsi:type="xsd:string">aStringValue</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key2</qman:key>
+ <qman:value xsi:type="xsd:long">-9223372036854775808</qman:value>
+ </qman:entry>
+ </qman:Arguments>
+ <qman:VhostRef xmlns:qman="http://amqp.apache.org/qpid/management/qman">2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b</qman:VhostRef>
+ <qman:ExpireTime xmlns:qman="http://amqp.apache.org/qpid/management/qman">9223372036854775807</qman:ExpireTime>
+ <qman:Durable xmlns:qman="http://amqp.apache.org/qpid/management/qman">true</qman:Durable>
+ <qman:ConsumerCount xmlns:qman="http://amqp.apache.org/qpid/management/qman">-2147483638</qman:ConsumerCount>
+ </wsrf-rp:GetMultipleResourcePropertiesResponse>
+ </soap:Body>
+</soap:Envelope> \ No newline at end of file
diff --git a/java/management/client/src/example/GetQManResourceMembers.out.ko b/java/management/client/src/example/GetQManResourceMembers.out.ko
new file mode 100644
index 0000000000..d6b733e430
--- /dev/null
+++ b/java/management/client/src/example/GetQManResourceMembers.out.ko
@@ -0,0 +1,54 @@
+ GetQManResourceMembersExample Example
+-------------------------------------------------------------------
+
+This example shows the usage of WS-DM
+GetResourcePropertyRequest / Response on a
+Group service.
+The target resource is the WS-DM Adapter itself
+and the requested property is "ws-rp:Entry".
+WS-DM Adapter is a special WS-Resource (is a Group)
+that acts as the main entry point for retrieving
+all other managed resources.
+So clients that want to deal with QMan WS-Resources
+must first get resource identifiers sending
+a GetResourcePropertyRequest to WS-DM Adapter
+with "ws-rp:Entry" as target target property.
+
+-------------------------------------------------------------------
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://192.38.73.2:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:796bab33-ed59-3432-4e2c-1fadde465a25</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+-----------------------EXAMPLE FAILURE----------------------
+org.apache.muse.ws.addressing.soap.SoapFault: No route to host: connect
+ at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:298)
+ at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:254)
+ at org.apache.muse.ws.resource.remote.WsResourceClient.getResourceProperty(WsResourceClient.java:138)
+ at org.apache.muse.ws.resource.sg.remote.ServiceGroupClient.getMembers(ServiceGroupClient.java:110)
+ at org.apache.qpid.management.example.GetQManResourceMembersExample.execute(GetQManResourceMembersExample.java:61)
+ at org.apache.qpid.management.example.GetQManResourceMembersExample.main(GetQManResourceMembersExample.java:133)
+
+
+#########################################################################################
+
+WARNING! Unable to run this sample : port number must be a number.
+-------------------------------------------------------------
+Expected command line args for this sample are :
+
+1) host : ip or host name where QMan is running.
+2) port : port number where QMan is running.
+------------------------------------------------------------ \ No newline at end of file
diff --git a/java/management/client/src/example/GetQManResourceMembers.out.ok b/java/management/client/src/example/GetQManResourceMembers.out.ok
new file mode 100644
index 0000000000..dd75e1e490
--- /dev/null
+++ b/java/management/client/src/example/GetQManResourceMembers.out.ok
@@ -0,0 +1,55 @@
+ GetQManResourceMembersExample Example
+-------------------------------------------------------------------
+
+This example shows the usage of WS-DM
+GetResourcePropertyRequest / Response on a
+Group service.
+The target resource is the WS-DM Adapter itself
+and the requested property is "ws-rp:Entry".
+WS-DM Adapter is a special WS-Resource (is a Group)
+that acts as the main entry point for retrieving
+all other managed resources.
+So clients that want to deal with QMan WS-Resources
+must first get resource identifiers sending
+a GetResourcePropertyRequest to WS-DM Adapter
+with "ws-rp:Entry" as target target property.
+
+-------------------------------------------------------------------
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:024c678b-1fab-cb6a-0992-30027817fb92</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:90b0e421-6467-a72e-a8f4-cdedb80460b6</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:024c678b-1fab-cb6a-0992-30027817fb92</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://romagazzarini:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+--------------------------------------------------------------------------
+QMan has at the moment 0 registered resources.
+-------------------------------------------------------------------------- \ No newline at end of file
diff --git a/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok b/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok
new file mode 100644
index 0000000000..a259259228
--- /dev/null
+++ b/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok
@@ -0,0 +1,188 @@
+ GetResourceMetadataDescriptorExample
+-------------------------------------------------------------------
+
+The example shows how to get metadata from a
+WS-Resource.
+A QMan WS-Resource has different kinds of metadata.
+(see below)
+User who wants to receive metadata of a WS-Resource
+must send a GetMetadataRequesta specifying the
+associated dialect.
+Supported metadata that could be requested are :
+
+- WSDL : in this case dialect is "http://schemas.xmlsoap.org/wsdl/";
+- RDM (Resource Metadata Descriptor) : in this case dialect is "http://docs.oasis-open.org/wsrf/rmd-1 ".
+
+Note that this examples focuses on RDM Metadata only;
+another one is dedicated to WSDL.
+-------------------------------------------------------------------
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:cdcf747a-e5fc-3762-1748-87cc2eefb18b</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:1d0d091b-8867-d765-7cc8-4898851cd783</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:cdcf747a-e5fc-3762-1748-87cc2eefb18b</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-sg:Entry xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">
+ <wsrf-sg:ServiceGroupEntryEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/ServiceGroupEntry</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <muse-wsa:ResourceId xmlns:muse-wsa="http://ws.apache.org/muse/addressing">uuid:3a2ee31e-49ed-e30a-c985-0fe49c182a75</muse-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:ServiceGroupEntryEPR>
+ <wsrf-sg:MemberServiceEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:MemberServiceEPR>
+ <wsrf-sg:Content/>
+ </wsrf-sg:Entry>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ba2435fc-9172-69d8-f4be-34f7f45b26ff</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://docs.oasis-open.org/wsrf/rmd-1</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ceb6eb90-4910-01a9-c138-6029e6bb0836</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ba2435fc-9172-69d8-f4be-34f7f45b26ff</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsrmd:MetadataDescriptor
+ interface="qman:QManWsResourcePortType"
+ name="QManWsResourceMetadata"
+ wsdlLocation="http://docs.oasis-open.org/wsrf/rmd-1 QManWsResource.wsdl"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:MgmtPubInterval" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Name" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:TerminationTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable"
+ name="qman:MsgTotalEnqueues" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Arguments" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:VhostRef" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:CurrentTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:ExpireTime" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Durable" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:ConsumerCount" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:Type" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ </wsrmd:MetadataDescriptor>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope> \ No newline at end of file
diff --git a/java/management/client/src/example/GetResourcePropertyDocument.out.ok b/java/management/client/src/example/GetResourcePropertyDocument.out.ok
new file mode 100644
index 0000000000..9d6312f2f3
--- /dev/null
+++ b/java/management/client/src/example/GetResourcePropertyDocument.out.ok
@@ -0,0 +1,138 @@
+ GetResourcePropertyDocument
+-------------------------------------------------------------------
+
+This example shows how to get the whole property
+document from a WS-Resource.
+Resource property document represents a particular
+composed structural view of the resource properties
+of the WS-Resource.
+First of all a request is send to WS-DM in order to get
+all registered WS-Resources.
+the target WS-Resource.
+If the returned list is not empty then a
+GetResourcePropertyDocumentRequest is sent to the first child.
+
+-------------------------------------------------------------------
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:50aa09f5-44e7-8bd3-7f24-49b8f0b9bf0d</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:f71342ad-2185-fdb3-393a-e9a98305effd</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:50aa09f5-44e7-8bd3-7f24-49b8f0b9bf0d</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-sg:Entry xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">
+ <wsrf-sg:ServiceGroupEntryEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/ServiceGroupEntry</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <muse-wsa:ResourceId xmlns:muse-wsa="http://ws.apache.org/muse/addressing">uuid:b220e2bd-0370-da4e-fc71-5e283954d319</muse-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:ServiceGroupEntryEPR>
+ <wsrf-sg:MemberServiceEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:MemberServiceEPR>
+ <wsrf-sg:Content/>
+ </wsrf-sg:Entry>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e035946b-c3f5-1b24-e94a-61c674ce07b9</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyDocument xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:dafe12e4-c0a9-f872-cf1e-2a41bc291b2e</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e035946b-c3f5-1b24-e94a-61c674ce07b9</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyDocumentResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:QManWsResourceProperties xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <qman:MgmtPubInterval>32767</qman:MgmtPubInterval>
+ <wsrf-rp:QueryExpressionDialect>http://www.w3.org/TR/1999/REC-xpath-19991116</wsrf-rp:QueryExpressionDialect>
+ <qman:Name>Initial Name</qman:Name>
+ <wsrf-rl:TerminationTime xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"/>
+ <qman:MsgTotalEnqueues>9223372036854775797</qman:MsgTotalEnqueues>
+ <qman:Arguments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <qman:entry>
+ <qman:key>Key3</qman:key>
+ <qman:value xsi:type="xsd:integer">2147483647</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key4</qman:key>
+ <qman:value xsi:type="xsd:float">3.4028235E38</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key1</qman:key>
+ <qman:value xsi:type="xsd:string">aStringValue</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key2</qman:key>
+ <qman:value xsi:type="xsd:long">-9223372036854775808</qman:value>
+ </qman:entry>
+ </qman:Arguments>
+ <qman:VhostRef>2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b</qman:VhostRef>
+ <wsrf-rl:CurrentTime xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2">1232956293823</wsrf-rl:CurrentTime>
+ <qman:ExpireTime>9223372036854775807</qman:ExpireTime>
+ <qman:Durable>true</qman:Durable>
+ <qman:ConsumerCount>-2147483638</qman:ConsumerCount>
+ </qman:QManWsResourceProperties>
+ </wsrf-rp:GetResourcePropertyDocumentResponse>
+ </soap:Body>
+</soap:Envelope> \ No newline at end of file
diff --git a/java/management/client/src/example/GetResourcePropertyRequest.out.ok b/java/management/client/src/example/GetResourcePropertyRequest.out.ok
new file mode 100644
index 0000000000..4fa0ab3b8d
--- /dev/null
+++ b/java/management/client/src/example/GetResourcePropertyRequest.out.ok
@@ -0,0 +1,588 @@
+ GetResourcePropertyExample
+-------------------------------------------------------------------
+
+This example shows how to get the property value
+from a WS-Resource.
+First of all a request is send to WS-DM in order to get
+all registered WS-Resources.
+If the returned list is not empty then a GetMetadataRequest
+to the first child.
+The result metadata descriptor contains all properties of
+the target WS-Resource.
+For each of them a GetResourcePropertyRequest is sent
+ in order to get its value.
+
+-------------------------------------------------------------------
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e581b9cb-04a9-a87f-7763-dcf227ed7f8b</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:27bab9a7-89aa-16a1-966b-c0aa19d3b352</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e581b9cb-04a9-a87f-7763-dcf227ed7f8b</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-sg:Entry xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">
+ <wsrf-sg:ServiceGroupEntryEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/ServiceGroupEntry</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <muse-wsa:ResourceId xmlns:muse-wsa="http://ws.apache.org/muse/addressing">uuid:b220e2bd-0370-da4e-fc71-5e283954d319</muse-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:ServiceGroupEntryEPR>
+ <wsrf-sg:MemberServiceEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:MemberServiceEPR>
+ <wsrf-sg:Content/>
+ </wsrf-sg:Entry>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:c5efae22-bc2f-ccdd-477c-621d4e49cd77</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://docs.oasis-open.org/wsrf/rmd-1</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:4d933676-fb60-3fae-d7b9-39324a8661fc</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:c5efae22-bc2f-ccdd-477c-621d4e49cd77</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsrmd:MetadataDescriptor
+ interface="qman:QManWsResourcePortType"
+ name="QManWsResourceMetadata"
+ wsdlLocation="http://docs.oasis-open.org/wsrf/rmd-1 QManWsResource.wsdl"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:MgmtPubInterval" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Name" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:TerminationTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable"
+ name="qman:MsgTotalEnqueues" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Arguments" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:VhostRef" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:CurrentTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:ExpireTime" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Durable" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:ConsumerCount" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:Type" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ </wsrmd:MetadataDescriptor>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:83c13239-3e37-853d-776d-3dac2729117b</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MgmtPubInterval</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0beb3927-6420-9877-f163-4288ea1560da</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:83c13239-3e37-853d-776d-3dac2729117b</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:MgmtPubInterval xmlns:qman="http://amqp.apache.org/qpid/management/qman">32767</qman:MgmtPubInterval>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:30b678da-f1fa-8120-7660-9eb86ebb76b7</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Name</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:8343b104-1a82-212a-c84a-460cbc223327</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:30b678da-f1fa-8120-7660-9eb86ebb76b7</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:Name xmlns:qman="http://amqp.apache.org/qpid/management/qman">Initial Name</qman:Name>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:795eaebd-dd48-75b0-18b3-a7e3c1fd4d5a</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MsgTotalEnqueues</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:b6b91fd1-762b-3ae4-76c3-fe206c93b76d</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:795eaebd-dd48-75b0-18b3-a7e3c1fd4d5a</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:MsgTotalEnqueues xmlns:qman="http://amqp.apache.org/qpid/management/qman">9223372036854775797</qman:MsgTotalEnqueues>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:f57f0179-a31b-8607-668b-c2602838c363</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Arguments</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:fc07cbe4-a19a-6374-c985-49fa525d3e90</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:f57f0179-a31b-8607-668b-c2602838c363</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:Arguments
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <qman:entry>
+ <qman:key>Key3</qman:key>
+ <qman:value xsi:type="xsd:integer">2147483647</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key4</qman:key>
+ <qman:value xsi:type="xsd:float">3.4028235E38</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key1</qman:key>
+ <qman:value xsi:type="xsd:string">aStringValue</qman:value>
+ </qman:entry>
+ <qman:entry>
+ <qman:key>Key2</qman:key>
+ <qman:value xsi:type="xsd:long">-9223372036854775808</qman:value>
+ </qman:entry>
+ </qman:Arguments>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:5d735040-95d1-7c87-7ac9-b4a5700e0ab9</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:VhostRef</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:cdfe639c-357b-d55b-fe7d-4a203d46465c</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:5d735040-95d1-7c87-7ac9-b4a5700e0ab9</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:VhostRef xmlns:qman="http://amqp.apache.org/qpid/management/qman">2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b</qman:VhostRef>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e3fde856-57f5-a96f-a382-5e0f4206a6fe</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:ExpireTime</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:fa290c54-bac1-62d6-701e-3b8ec2eaf817</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:e3fde856-57f5-a96f-a382-5e0f4206a6fe</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:ExpireTime xmlns:qman="http://amqp.apache.org/qpid/management/qman">9223372036854775807</qman:ExpireTime>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:092dd5d9-c443-428c-813c-13428058b08c</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Durable</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:1053800e-345c-abed-e352-f524c1d24afa</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:092dd5d9-c443-428c-813c-13428058b08c</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:Durable xmlns:qman="http://amqp.apache.org/qpid/management/qman">true</qman:Durable>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:bc291be9-b1d1-f668-f3c5-29647e78d6bf</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:ConsumerCount</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:7467dddf-033e-f540-241f-76ce81c0ebeb</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:bc291be9-b1d1-f668-f3c5-29647e78d6bf</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:ConsumerCount xmlns:qman="http://amqp.apache.org/qpid/management/qman">-2147483638</qman:ConsumerCount>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:92783239-777c-27fa-cec2-ee3afecf5c32</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Type</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:af8168b4-6c13-c736-b521-f2b410541dd0</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:92783239-777c-27fa-cec2-ee3afecf5c32</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope> \ No newline at end of file
diff --git a/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources b/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources
new file mode 100644
index 0000000000..6e727261f9
--- /dev/null
+++ b/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources
@@ -0,0 +1,58 @@
+ GetWSDLMetadataExample
+-------------------------------------------------------------------
+
+This example shows the usage of WS-DM
+GetResourcePropertyRequest / Response on a
+Group service.
+The target resource is the WS-DM Adapter itself
+and the requested property is "ws-rp:Entry".
+WS-DM Adapter is a special WS-Resource (is a Group)
+that acts as the main entry point for retrieving
+all other managed resources.
+So clients that want to deal with QMan WS-Resources
+must first get resource identifiers sending
+a GetResourcePropertyRequest to WS-DM Adapter
+with "ws-rp:Entry" as target target property.
+
+-------------------------------------------------------------------
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:7f801eff-c528-91e8-33eb-3d1dd164bce7</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:86a34968-38aa-83e8-47dd-8e86ffd8ac06</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:7f801eff-c528-91e8-33eb-3d1dd164bce7</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+----------------------------WARNING---------------------------
+Cannot proceed with the example... it seems
+that there are no managed WS-Resources on QMan.
+Please check QMan in order to see that it is really
+connected with a broker.
+-------------------------------------------------------------------
diff --git a/java/management/client/src/example/GetWsdlMetadata.out.ok b/java/management/client/src/example/GetWsdlMetadata.out.ok
new file mode 100644
index 0000000000..16a4c1e07e
--- /dev/null
+++ b/java/management/client/src/example/GetWsdlMetadata.out.ok
@@ -0,0 +1,1968 @@
+ GetWSDLMetadataExample
+-------------------------------------------------------------------
+
+This example shows the usage of WS-DM
+GetResourcePropertyRequest / Response on a
+Group service.
+The target resource is the WS-DM Adapter itself
+and the requested property is "ws-rp:Entry".
+WS-DM Adapter is a special WS-Resource (is a Group)
+that acts as the main entry point for retrieving
+all other managed resources.
+So clients that want to deal with QMan WS-Resources
+must first get resource identifiers sending
+a GetResourcePropertyRequest to WS-DM Adapter
+with "ws-rp:Entry" as target target property.
+
+-------------------------------------------------------------------
+
+Type enter to proceed.
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ec4d0c03-3174-e39d-4a36-8f109056865b</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">wsrf-sg:Entry</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0f47d614-565e-5360-8dcc-ea8e4771e4dd</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ec4d0c03-3174-e39d-4a36-8f109056865b</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-sg:Entry xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2">
+ <wsrf-sg:ServiceGroupEntryEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/ServiceGroupEntry</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <muse-wsa:ResourceId xmlns:muse-wsa="http://ws.apache.org/muse/addressing">uuid:1d01b4ee-7d23-3a30-342e-62fc49984fe6</muse-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:ServiceGroupEntryEPR>
+ <wsrf-sg:MemberServiceEPR>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsrf-sg:MemberServiceEPR>
+ <wsrf-sg:Content/>
+ </wsrf-sg:Entry>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0cdb5112-09e0-ac39-06ba-393843f06e42</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://schemas.xmlsoap.org/wsdl/</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:980617c8-e3a0-ebf1-8f5a-2b43d3d6d416</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0cdb5112-09e0-ac39-06ba-393843f06e42</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsdl:definitions name="QManWsResource"
+ targetNamespace="http://amqp.apache.org/qpid/management/qman"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <wsdl:types>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://www.w3.org/2005/08/addressing"
+ xmlns:tns="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="EndpointReference"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:element name="Address" type="tns:AttributedURIType"/>
+ <xs:element minOccurs="0"
+ name="ReferenceParameters" type="tns:ReferenceParametersType"/>
+ <xs:element minOccurs="0" ref="tns:Metadata"/>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:complexType mixed="false"
+ name="ReferenceParametersType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="Metadata"
+ type="tns:MetadataType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="MetadataType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="MessageID"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="RelatesTo"
+ type="tns:RelatesToType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="RelatesToType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute
+ default="http://www.w3.org/2005/08/addressing/reply"
+ name="RelationshipType"
+ type="tns:RelationshipTypeOpenEnum" use="optional"/>
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType
+ name="RelationshipTypeOpenEnum" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:union memberTypes="tns:RelationshipType xs:anyURI"/>
+ </xs:simpleType>
+ <xs:simpleType name="RelationshipType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:restriction base="xs:anyURI">
+ <xs:enumeration value="http://www.w3.org/2005/08/addressing/reply"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="ReplyTo"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="From"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="FaultTo"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="To"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Action"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:attribute name="IsReferenceParameter"
+ type="xs:boolean" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:simpleType name="FaultCodesOpenEnumType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:union memberTypes="tns:FaultCodesType xs:QName"/>
+ </xs:simpleType>
+ <xs:simpleType name="FaultCodesType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:restriction base="xs:QName">
+ <xs:enumeration value="tns:InvalidAddressingHeader"/>
+ <xs:enumeration value="tns:InvalidAddress"/>
+ <xs:enumeration value="tns:InvalidEPR"/>
+ <xs:enumeration value="tns:InvalidCardinality"/>
+ <xs:enumeration value="tns:MissingAddressInEPR"/>
+ <xs:enumeration value="tns:DuplicateMessageID"/>
+ <xs:enumeration value="tns:ActionMismatch"/>
+ <xs:enumeration value="tns:MessageAddressingHeaderRequired"/>
+ <xs:enumeration value="tns:DestinationUnreachable"/>
+ <xs:enumeration value="tns:ActionNotSupported"/>
+ <xs:enumeration value="tns:EndpointUnavailable"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="RetryAfter"
+ type="tns:AttributedUnsignedLongType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedUnsignedLongType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:unsignedLong">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:element name="ProblemHeaderQName"
+ type="tns:AttributedQNameType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedQNameType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:QName">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:element name="ProblemHeader"
+ type="tns:AttributedAnyType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedAnyType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="1" minOccurs="1"
+ namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="ProblemIRI"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="ProblemAction"
+ type="tns:ProblemActionType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="ProblemActionType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="tns:Action"/>
+ <xs:element minOccurs="0"
+ name="SoapAction" type="xs:anyURI"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified"
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:tns="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import
+ namespace="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="GetMetadata" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="tns:Dialect"/>
+ <xs:element minOccurs="0" ref="tns:Identifier"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Dialect" type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Identifier"
+ type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Metadata" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="tns:MetadataSection"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MetadataSection" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:choice>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ <xs:element ref="tns:MetadataReference"/>
+ <xs:element ref="tns:Location"/>
+ </xs:choice>
+ <xs:attribute name="Dialect"
+ type="xs:anyURI" use="required"/>
+ <xs:attribute name="Identifier" type="xs:anyURI"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MetadataReference"
+ type="wsa:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Location" type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType name="AnyXmlType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##any" processContents="lax"/>
+ </xs:complexType>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="CurrentTime">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="TerminationTime" nillable="true">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ScheduledResourceTerminationRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rl:CurrentTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rl:TerminationTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Destroy">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="DestroyResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:complexType name="ResourceNotDestroyedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="ResourceNotDestroyedFault" type="wsrf-rl:ResourceNotDestroyedFaultType"/>
+ <xsd:element name="SetTerminationTime">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element
+ name="RequestedTerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element
+ name="RequestedLifetimeDuration" type="xsd:duration"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SetTerminationTimeResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ name="NewTerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element name="CurrentTime" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="UnableToSetTerminationTimeFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToSetTerminationTimeFault" type="wsrf-rl:UnableToSetTerminationTimeFaultType"/>
+ <xsd:complexType name="TerminationTimeChangeRejectedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="TerminationTimeChangeRejectedFault" type="wsrf-rl:TerminationTimeChangeRejectedFaultType"/>
+ <xsd:element name="TerminationNotification">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1"
+ name="TerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="TerminationReason" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="QueryExpressionDialect" type="xsd:anyURI"/>
+ <xsd:element name="QueryExpressionRPDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrf-rp:QueryExpressionDialect"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:attribute name="ResourceProperties" type="xsd:QName"/>
+ <xsd:complexType name="ResourcePropertyValueChangeNotificationType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="OldValues" nillable="true">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" name="NewValues" nillable="true">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="ResourcePropertyValueChangeNotification" type="wsrf-rp:ResourcePropertyValueChangeNotificationType"/>
+ <xsd:complexType mixed="true" name="QueryExpressionType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="0" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI"/>
+ </xsd:complexType>
+ <xsd:element name="QueryExpression" type="wsrf-rp:QueryExpressionType"/>
+ <xsd:element name="GetResourcePropertyDocument">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="GetResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="GetResourceProperty" type="xsd:QName"/>
+ <xsd:element name="GetResourcePropertyResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="InvalidResourcePropertyQNameFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InvalidResourcePropertyQNameFault" type="wsrf-rp:InvalidResourcePropertyQNameFaultType"/>
+ <xsd:element name="GetMultipleResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="1"
+ name="ResourceProperty" type="xsd:QName"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="GetMultipleResourcePropertiesResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PutResourcePropertyDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PutResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="ResourcePropertyChangeFailureType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="CurrentValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="RequestedValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="Restored" type="xsd:boolean"/>
+ </xsd:complexType>
+ <xsd:complexType name="UnableToPutResourcePropertyDocumentFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToPutResourcePropertyDocumentFault" type="wsrf-rp:UnableToPutResourcePropertyDocumentFaultType"/>
+ <xsd:complexType name="InsertType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Insert" type="wsrf-rp:InsertType"/>
+ <xsd:complexType name="UpdateType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Update" type="wsrf-rp:UpdateType"/>
+ <xsd:complexType name="DeleteType">
+ <xsd:attribute name="ResourceProperty"
+ type="xsd:QName" use="required"/>
+ </xsd:complexType>
+ <xsd:element name="Delete" type="wsrf-rp:DeleteType"/>
+ <xsd:element name="SetResourceProperties">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="1">
+ <xsd:element ref="wsrf-rp:Insert"/>
+ <xsd:element ref="wsrf-rp:Update"/>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SetResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:complexType name="InvalidModificationFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidModificationFault" type="wsrf-rp:InvalidModificationFaultType"/>
+ <xsd:complexType name="UnableToModifyResourcePropertyFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToModifyResourcePropertyFault" type="wsrf-rp:UnableToModifyResourcePropertyFaultType"/>
+ <xsd:complexType name="SetResourcePropertyRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="SetResourcePropertyRequestFailedFault" type="wsrf-rp:SetResourcePropertyRequestFailedFaultType"/>
+ <xsd:complexType name="InsertResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InsertResourcePropertiesRequestFailedFault" type="wsrf-rp:InsertResourcePropertiesRequestFailedFaultType"/>
+ <xsd:complexType name="UpdateResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UpdateResourcePropertiesRequestFailedFault" type="wsrf-rp:UpdateResourcePropertiesRequestFailedFaultType"/>
+ <xsd:complexType name="DeleteResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="DeleteResourcePropertiesRequestFailedFault" type="wsrf-rp:DeleteResourcePropertiesRequestFailedFaultType"/>
+ <xsd:element name="InsertResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Insert"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="InsertResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="UpdateResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Update"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="UpdateResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="DeleteResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="DeleteResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="QueryResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rp:QueryExpression"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="QueryResourcePropertiesResponse">
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:restriction base="xsd:anyType">
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:restriction>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="UnknownQueryExpressionDialectFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnknownQueryExpressionDialectFault" type="wsrf-rp:UnknownQueryExpressionDialectFaultType"/>
+ <xsd:complexType name="InvalidQueryExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InvalidQueryExpressionFault" type="wsrf-rp:InvalidQueryExpressionFaultType"/>
+ <xsd:complexType name="QueryEvaluationErrorFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="QueryEvaluationErrorFault" type="wsrf-rp:QueryEvaluationErrorFaultType"/>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:complexType name="ResourceUnknownFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnknownFault" type="wsrf-r:ResourceUnknownFaultType"/>
+ <xsd:complexType name="ResourceUnavailableFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnavailableFault" type="wsrf-r:ResourceUnavailableFaultType"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2"/>
+ <xsd:import namespace="http://www.w3.org/2005/08/addressing"/>
+ <xsd:simpleType name="PairsOfURIType">
+ <xsd:list itemType="xsd:anyURI"/>
+ </xsd:simpleType>
+ <xsd:attribute name="Descriptor" type="xsd:QName"/>
+ <xsd:attribute name="DescriptorLocation" type="xsd:anyURI"/>
+ <xsd:complexType mixed="true" name="DocumentationType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ <xsd:complexType name="DocumentedType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="DefinitionsType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrmd:MetadataDescriptor"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute
+ name="targetNamespace"
+ type="xsd:anyURI" use="required"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="Definitions" type="wsrmd:DefinitionsType">
+ <xsd:key name="MetadataDescriptor">
+ <xsd:annotation>
+ <xsd:documentation>
+ To form a QName, the name of any MetadataDescriptor must be
+ unique within a Definitions element.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:selector xpath="wsrmd:MetadataDescriptor"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ </xsd:element>
+ <xsd:complexType name="MetadataDescriptorType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrmd:Property"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:NCName" use="required"/>
+ <xsd:attribute name="interface"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute
+ name="wsdlLocation" type="wsrmd:PairsOfURIType"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="MetadataDescriptor" type="wsrmd:MetadataDescriptorType"/>
+ <xsd:complexType name="PropertyType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:choice>
+ <xsd:element
+ maxOccurs="1"
+ minOccurs="0" ref="wsrmd:ValidValues"/>
+ <xsd:element
+ maxOccurs="1"
+ minOccurs="0" ref="wsrmd:ValidValueRange"/>
+ </xsd:choice>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" ref="wsrmd:StaticValues"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute name="mutability" type="wsrmd:MutabilityType"/>
+ <xsd:attribute
+ name="modifiability" type="wsrmd:ModifiabilityType"/>
+ <xsd:attribute default="false"
+ name="subscribability" type="xsd:boolean"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="Property" type="wsrmd:PropertyType"/>
+ <xsd:simpleType name="MutabilityType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="constant"/>
+ <xsd:enumeration value="appendable"/>
+ <xsd:enumeration value="mutable"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ModifiabilityType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="read-only"/>
+ <xsd:enumeration value="read-write"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:complexType mixed="true" name="ValidValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="ValidValues" type="wsrmd:ValidValuesType"/>
+ <xsd:complexType mixed="true" name="ValidValueRangeType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="lowerBound" type="xsd:anySimpleType"/>
+ <xsd:attribute name="upperBound" type="xsd:anySimpleType"/>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="ValidValueRange" type="wsrmd:ValidValueRangeType"/>
+ <xsd:complexType mixed="true" name="StaticValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="StaticValues" type="wsrmd:StaticValuesType"/>
+ <xsd:complexType mixed="true" name="InitialValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="InitialValues" type="wsrmd:InitialValuesType"/>
+ <xsd:complexType name="MetadataDescriptorReferenceType">
+ <xsd:complexContent>
+ <xsd:extension base="wsa:EndpointReferenceType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="MetadataDescriptorReference" type="wsrmd:MetadataDescriptorReferenceType"/>
+ <xsd:element name="MetadataResourceRP" type="wsrmd:DefinitionsType"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://amqp.apache.org/qpid/management/qman">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rl-2"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="QManWsResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rl:CurrentTime"/>
+ <xsd:element ref="wsrf-rl:TerminationTime"/>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrf-rp:QueryExpressionDialect"/>
+ <xsd:element ref="qman:Name"/>
+ <xsd:element ref="qman:Type"/>
+ <xsd:element ref="qman:Arguments"/>
+ <xsd:element ref="qman:VhostRef"/>
+ <xsd:element ref="qman:Durable"/>
+ <xsd:element ref="qman:MsgTotalEnqueues"/>
+ <xsd:element ref="qman:ConsumerCount"/>
+ <xsd:element ref="qman:ExpireTime"/>
+ <xsd:element ref="qman:MgmtPubInterval"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="QManFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MethodInvocationFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="EntityInstanceNotFoundFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MalformedEntityNameFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NoSuchAttributeFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="result">
+ <xsd:sequence>
+ <xsd:element name="statusCode" type="xsd:long"/>
+ <xsd:element name="statusText" type="xsd:string"/>
+ <xsd:complexType name="outputParameters">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" name="entry">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:name
+ name="key" type="xsd:string"/>
+ <xsd:element
+ name="value" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:complexType>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Name" type="xsd:string"/>
+ <xsd:element name="Type" type="xsd:string"/>
+ <xsd:complexType name="map">
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded"
+ minOccurs="0" name="entry">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="key" type="xsd:string"/>
+ <xsd:element
+ name="value" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Arguments" type="qman:map"/>
+ <xsd:complexType name="uuid">
+ <xsd:sequence>
+ <xsd:element name="uuid" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="VhostRef" type="qman:uuid"/>
+ <xsd:element name="Durable" type="xsd:boolean"/>
+ <xsd:element name="MsgTotalEnqueues" type="xsd:long"/>
+ <xsd:element name="ConsumerCount" type="xsd:integer"/>
+ <xsd:element name="ExpireTime" type="xsd:dateTime"/>
+ <xsd:element name="MgmtPubInterval" type="xsd:short"/>
+ <xsd:element
+ name="echoWithSimpleTypesRequest" type="qman:echoWithSimpleTypesRequest"/>
+ <xsd:element
+ name="echoWithSimpleTypesResponse" type="qman:echoWithSimpleTypesResponse"/>
+ <xsd:complexType name="echoWithSimpleTypesRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="xsd:long"/>
+ <xsd:element name="p2" type="xsd:boolean"/>
+ <xsd:element name="p3" type="xsd:double"/>
+ <xsd:element name="p4" type="xsd:float"/>
+ <xsd:element name="p5" type="xsd:integer"/>
+ <xsd:element name="p6" type="xsd:short"/>
+ <xsd:element name="p7" type="xsd:string"/>
+ <xsd:element name="p8" type="xsd:anyURI"/>
+ <xsd:element name="p9" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypesResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithArraysRequest" type="qman:echoWithArraysRequest"/>
+ <xsd:element name="echoWithArraysResponse" type="qman:echoWithArraysResponse"/>
+ <xsd:complexType name="arrayOfLong">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:long"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfBoolean">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDouble">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:double"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfFloat">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:float"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfInteger">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:integer"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfShort">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:short"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfString">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfURI">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:anyURI"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDate">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithArraysRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfLong"/>
+ <xsd:element name="p2" type="qman:arrayOfBoolean"/>
+ <xsd:element name="p3" type="qman:arrayOfDouble"/>
+ <xsd:element name="p4" type="qman:arrayOfFloat"/>
+ <xsd:element name="p5" type="qman:arrayOfInteger"/>
+ <xsd:element name="p6" type="qman:arrayOfShort"/>
+ <xsd:element name="p7" type="qman:arrayOfString"/>
+ <xsd:element name="p8" type="qman:arrayOfURI"/>
+ <xsd:element name="p9" type="qman:arrayOfDate"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithArraysResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="echoWithSimpleTypeArraysRequest" type="qman:echoWithSimpleTypeArraysRequest"/>
+ <xsd:element
+ name="echoWithSimpleTypeArraysResponse" type="qman:echoWithSimpleTypeArraysResponse"/>
+ <xsd:complexType name="arrayOfLong">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:long"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfBoolean">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDouble">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:double"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfFloat">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:float"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfInt">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:integer"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfShort">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:short"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypeArraysRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfLong"/>
+ <xsd:element name="p2" type="qman:arrayOfBoolean"/>
+ <xsd:element name="p3" type="qman:arrayOfDouble"/>
+ <xsd:element name="p4" type="qman:arrayOfFloat"/>
+ <xsd:element name="p5" type="qman:arrayOfInt"/>
+ <xsd:element name="p6" type="qman:arrayOfShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypeArraysResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithByteArrayRequest" type="qman:echoWithByteArrayRequest"/>
+ <xsd:element
+ name="echoWithByteArrayResponse" type="qman:echoWithByteArrayResponse"/>
+ <xsd:complexType name="arrayOfByte">
+ <xsd:sequence>
+ <xsd:element name="entry" type=""/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithByteArrayRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfByte"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithByteArrayResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="voidWithoutArgumentsRequest" type="qman:voidWithoutArgumentsRequest"/>
+ <xsd:element
+ name="voidWithoutArgumentsResponse" type="qman:voidWithoutArgumentsResponse"/>
+ <xsd:complexType name="voidWithoutArgumentsRequest">
+ <xsd:sequence/>
+ </xsd:complexType>
+ <xsd:complexType name="voidWithoutArgumentsResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="throwsExceptionRequest" type="qman:throwsExceptionRequest"/>
+ <xsd:element name="throwsExceptionResponse" type="qman:throwsExceptionResponse"/>
+ <xsd:complexType name="throwsExceptionRequest">
+ <xsd:sequence/>
+ </xsd:complexType>
+ <xsd:complexType name="throwsExceptionResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithUUIDRequest" type="qman:echoWithUUIDRequest"/>
+ <xsd:element name="echoWithUUIDResponse" type="qman:echoWithUUIDResponse"/>
+ <xsd:complexType name="echoWithUUIDRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:uuid"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithUUIDResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithMapRequest" type="qman:echoWithMapRequest"/>
+ <xsd:element name="echoWithMapResponse" type="qman:echoWithMapResponse"/>
+ <xsd:complexType name="echoWithMapRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:map"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithMapResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://www.w3.org/2005/08/addressing"/>
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace">
+ <xsd:annotation>
+ <xsd:documentation>
+ Get access to the xml: attribute groups for xml:lang as declared on 'schema'
+ and 'documentation' below
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:import>
+ <xsd:element name="BaseFault" type="wsrf-bf:BaseFaultType"/>
+ <xsd:complexType name="BaseFaultType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" name="Timestamp" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="Originator" type="wsa:EndpointReferenceType"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="ErrorCode">
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:extension base="xsd:anyType">
+ <xsd:attribute
+ name="dialect"
+ type="xsd:anyURI" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="unbounded"
+ minOccurs="0" name="Description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute
+ ref="xml:lang" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="FaultCause">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1"
+ minOccurs="1"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ </xsd:schema>
+ <xs:schema
+ targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xml:lang="en" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:attribute name="lang" type="xs:language"/>
+ <xs:attribute default="preserve" name="space">
+ <xs:simpleType>
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="base" type="xs:anyURI"/>
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ </xs:attributeGroup>
+ </xs:schema>
+ </wsdl:types>
+ <wsdl:message name="GetMetadataMsg">
+ <wsdl:part element="wsx:GetMetadata" name="GetMetadataMsg"/>
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMsg">
+ <wsdl:part element="wsx:Metadata" name="GetMetadataResponseMsg"/>
+ </wsdl:message>
+ <wsdl:message name="DestroyRequest">
+ <wsdl:part element="wsrf-rl:Destroy" name="DestroyRequest"/>
+ </wsdl:message>
+ <wsdl:message name="DestroyResponse">
+ <wsdl:part element="wsrf-rl:DestroyResponse" name="DestroyResponse"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceNotDestroyedFault">
+ <wsdl:part
+ element="wsrf-rl:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part element="wsrf-r:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part
+ element="wsrf-r:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetTerminationTimeRequest">
+ <wsdl:part element="wsrf-rl:SetTerminationTime" name="SetTerminationTimeRequest"/>
+ </wsdl:message>
+ <wsdl:message name="SetTerminationTimeResponse">
+ <wsdl:part
+ element="wsrf-rl:SetTerminationTimeResponse" name="SetTerminationTimeResponse"/>
+ </wsdl:message>
+ <wsdl:message name="UnableToSetTerminationTimeFault">
+ <wsdl:part
+ element="wsrf-rl:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault"/>
+ </wsdl:message>
+ <wsdl:message name="TerminationTimeChangeRejectedFault">
+ <wsdl:part
+ element="wsrf-rl:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyDocument" name="GetResourcePropertyDocumentRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyDocumentResponse" name="GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part element="wsrf-rp:GetResourceProperty" name="GetResourcePropertyRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyResponse" name="GetResourcePropertyResponse"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:GetMultipleResourceProperties" name="GetMultipleResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:GetMultipleResourcePropertiesResponse" name="GetMultipleResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:QueryResourceProperties" name="QueryResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:QueryResourcePropertiesResponse" name="QueryResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <wsdl:part
+ element="wsrf-rp:UnknownQueryExpressionDialectFault" name="UnknownQueryExpressionDialectFault"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidQueryExpressionFault" name="InvalidQueryExpressionFault"/>
+ </wsdl:message>
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <wsdl:part
+ element="wsrf-rp:QueryEvaluationErrorFault" name="QueryEvaluationErrorFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:SetResourceProperties" name="SetResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:SetResourcePropertiesResponse" name="SetResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidModificationFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidModificationFault" name="InvalidModificationFault"/>
+ </wsdl:message>
+ <wsdl:message name="UnableToModifyResourcePropertyFault">
+ <wsdl:part
+ element="wsrf-rp:UnableToModifyResourcePropertyFault" name="UnableToModifyResourcePropertyFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertyRequestFailedFault">
+ <wsdl:part
+ element="wsrf-rp:SetResourcePropertyRequestFailedFault" name="SetResourcePropertyRequestFailedFault"/>
+ </wsdl:message>
+ <wsdl:portType name="QManWsResourcePortType"
+ wsrf-rp:ResourceProperties="qman:QManWsResourceProperties"
+ wsrmd:Descriptor="QManWsResourceMetadata" wsrmd:DescriptorLocation="QManWsResource.rmd">
+ <wsdl:operation name="GetMetadata">
+ <wsdl:input message="qman:GetMetadataMsg"
+ name="GetMetadataMsg" wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"/>
+ <wsdl:output
+ message="qman:GetMetadataResponseMsg"
+ name="GetMetadataResponseMsg" wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="Destroy">
+ <wsdl:input message="qman:DestroyRequest"
+ name="DestroyRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyRequest"/>
+ <wsdl:output message="qman:DestroyResponse"
+ name="DestroyResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyResponse"/>
+ <wsdl:fault
+ message="qman:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl:input
+ message="qman:SetTerminationTimeRequest"
+ name="SetTerminationTimeRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeRequest"/>
+ <wsdl:output
+ message="qman:SetTerminationTimeResponse"
+ name="SetTerminationTimeResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeResponse"/>
+ <wsdl:fault
+ message="qman:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input
+ message="qman:GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"/>
+ <wsdl:output
+ message="qman:GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input
+ message="qman:GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"/>
+ <wsdl:output
+ message="qman:GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input
+ message="qman:GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input
+ message="qman:QueryResourcePropertiesRequest"
+ name="QueryResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:QueryResourcePropertiesResponse"
+ name="QueryResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:UnknownQueryExpressionDialectFault" name="UnknownQueryExpressionDialectFault"/>
+ <wsdl:fault
+ message="qman:InvalidQueryExpressionFault" name="InvalidQueryExpressionFault"/>
+ <wsdl:fault
+ message="qman:QueryEvaluationErrorFault" name="QueryEvaluationErrorFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl:input
+ message="qman:SetResourcePropertiesRequest"
+ name="SetResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:SetResourcePropertiesResponse"
+ name="SetResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidModificationFault" name="InvalidModificationFault"/>
+ <wsdl:fault
+ message="qman:UnableToModifyResourcePropertyFault" name="UnableToModifyResourcePropertyFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ <wsdl:fault
+ message="qman:SetResourcePropertyRequestFailedFault" name="SetResourcePropertyRequestFailedFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypes">
+ <wsdl:input
+ message="qman:echoWithSimpleTypesRequestMessage"
+ name="echoWithSimpleTypesRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypes"/>
+ <wsdl:output
+ message="qman:echoWithSimpleTypesResponseMessage"
+ name="echoWithSimpleTypesResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypesResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithArrays">
+ <wsdl:input
+ message="qman:echoWithArraysRequestMessage"
+ name="echoWithArraysRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithArrays"/>
+ <wsdl:output
+ message="qman:echoWithArraysResponseMessage"
+ name="echoWithArraysResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithArraysResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypeArrays">
+ <wsdl:input
+ message="qman:echoWithSimpleTypeArraysRequestMessage"
+ name="echoWithSimpleTypeArraysRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArrays"/>
+ <wsdl:output
+ message="qman:echoWithSimpleTypeArraysResponseMessage"
+ name="echoWithSimpleTypeArraysResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArraysResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithByteArray">
+ <wsdl:input
+ message="qman:echoWithByteArrayRequestMessage"
+ name="echoWithByteArrayRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithByteArray"/>
+ <wsdl:output
+ message="qman:echoWithByteArrayResponseMessage"
+ name="echoWithByteArrayResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithByteArrayResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="voidWithoutArguments">
+ <wsdl:input
+ message="qman:voidWithoutArgumentsRequestMessage"
+ name="voidWithoutArgumentsRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/voidWithoutArguments"/>
+ <wsdl:output
+ message="qman:voidWithoutArgumentsResponseMessage"
+ name="voidWithoutArgumentsResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/voidWithoutArgumentsResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="throwsException">
+ <wsdl:input
+ message="qman:throwsExceptionRequestMessage"
+ name="throwsExceptionRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/throwsException"/>
+ <wsdl:output
+ message="qman:throwsExceptionResponseMessage"
+ name="throwsExceptionResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/throwsExceptionResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithUUID">
+ <wsdl:input
+ message="qman:echoWithUUIDRequestMessage"
+ name="echoWithUUIDRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithUUID"/>
+ <wsdl:output
+ message="qman:echoWithUUIDResponseMessage"
+ name="echoWithUUIDResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithUUIDResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithMap">
+ <wsdl:input
+ message="qman:echoWithMapRequestMessage"
+ name="echoWithMapRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithMap"/>
+ <wsdl:output
+ message="qman:echoWithMapResponseMessage"
+ name="echoWithMapResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithMapResponse"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="QManWsResourceBinding" type="qman:QManWsResourcePortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata"/>
+ <wsdl:input>
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="Destroy">
+ <wsdl-soap:operation soapAction="Destroy"/>
+ <wsdl:input name="DestroyRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="DestroyResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceNotDestroyedFault">
+ <wsdl-soap:fault
+ name="ResourceNotDestroyedFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl-soap:operation soapAction="SetTerminationTime"/>
+ <wsdl:input name="SetTerminationTimeRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="SetTerminationTimeResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="UnableToSetTerminationTimeFault">
+ <wsdl-soap:fault
+ name="UnableToSetTerminationTimeFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="TerminationTimeChangeRejectedFault">
+ <wsdl-soap:fault
+ name="TerminationTimeChangeRejectedFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl-soap:operation soapAction="QueryResourceProperties"/>
+ <wsdl:input name="QueryResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="QueryResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault">
+ <wsdl-soap:fault
+ name="UnknownQueryExpressionDialectFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidQueryExpressionFault">
+ <wsdl-soap:fault
+ name="InvalidQueryExpressionFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="QueryEvaluationErrorFault">
+ <wsdl-soap:fault
+ name="QueryEvaluationErrorFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl-soap:operation soapAction="http://oasis.org/SetResourceProperties"/>
+ <wsdl:input name="SetResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="SetResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidModificationFault">
+ <wsdl-soap:fault
+ name="InvalidModificationFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnableToModifyResourcePropertyFault">
+ <wsdl-soap:fault
+ name="UnableToModifyResourcePropertyFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="SetResourcePropertyRequestFailedFault">
+ <wsdl-soap:fault
+ name="SetResourcePropertyRequestFailedFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="http://ws.apache.org/muse/test/wsrf/GetMetadata"/>
+ <wsdl:input name="GetMetadataMsg">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetMetadataResponseMsg">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypes">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypes"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithArrays">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithArrays"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypeArrays">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArrays"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithByteArray">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithByteArray"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="voidWithoutArguments">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/voidWithoutArguments"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="throwsException">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/throwsException"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithUUID">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithUUID"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithMap">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithMap"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="QManWsResourceService">
+ <wsdl:port binding="qman:QManWsResourceBinding" name="QManWsResourcePort">
+ <wsdl-soap:address location="http://romagazzarini:8080/qman/services/QManWsResource"/>
+ </wsdl:port>
+ </wsdl:service>
+ <message name="echoWithSimpleTypesRequestMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypesRequest" name="echoWithSimpleTypesRequest"/>
+ </message>
+ <wsdl:message name="echoWithSimpleTypesResponseMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypesResponse" name="echoWithSimpleTypesResponse"/>
+ </wsdl:message>
+ <message name="echoWithArraysRequestMessage">
+ <wsdl:part element="qman:echoWithArraysRequest" name="echoWithArraysRequest"/>
+ </message>
+ <wsdl:message name="echoWithArraysResponseMessage">
+ <wsdl:part element="qman:echoWithArraysResponse" name="echoWithArraysResponse"/>
+ </wsdl:message>
+ <message name="echoWithSimpleTypeArraysRequestMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypeArraysRequest" name="echoWithSimpleTypeArraysRequest"/>
+ </message>
+ <wsdl:message name="echoWithSimpleTypeArraysResponseMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypeArraysResponse" name="echoWithSimpleTypeArraysResponse"/>
+ </wsdl:message>
+ <message name="echoWithByteArrayRequestMessage">
+ <wsdl:part
+ element="qman:echoWithByteArrayRequest" name="echoWithByteArrayRequest"/>
+ </message>
+ <wsdl:message name="echoWithByteArrayResponseMessage">
+ <wsdl:part
+ element="qman:echoWithByteArrayResponse" name="echoWithByteArrayResponse"/>
+ </wsdl:message>
+ <message name="voidWithoutArgumentsRequestMessage">
+ <wsdl:part
+ element="qman:voidWithoutArgumentsRequest" name="voidWithoutArgumentsRequest"/>
+ </message>
+ <wsdl:message name="voidWithoutArgumentsResponseMessage">
+ <wsdl:part
+ element="qman:voidWithoutArgumentsResponse" name="voidWithoutArgumentsResponse"/>
+ </wsdl:message>
+ <message name="throwsExceptionRequestMessage">
+ <wsdl:part element="qman:throwsExceptionRequest" name="throwsExceptionRequest"/>
+ </message>
+ <wsdl:message name="throwsExceptionResponseMessage">
+ <wsdl:part
+ element="qman:throwsExceptionResponse" name="throwsExceptionResponse"/>
+ </wsdl:message>
+ <message name="echoWithUUIDRequestMessage">
+ <wsdl:part element="qman:echoWithUUIDRequest" name="echoWithUUIDRequest"/>
+ </message>
+ <wsdl:message name="echoWithUUIDResponseMessage">
+ <wsdl:part element="qman:echoWithUUIDResponse" name="echoWithUUIDResponse"/>
+ </wsdl:message>
+ <message name="echoWithMapRequestMessage">
+ <wsdl:part element="qman:echoWithMapRequest" name="echoWithMapRequest"/>
+ </message>
+ <wsdl:message name="echoWithMapResponseMessage">
+ <wsdl:part element="qman:echoWithMapResponse" name="echoWithMapResponse"/>
+ </wsdl:message>
+ </wsdl:definitions>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope> \ No newline at end of file
diff --git a/java/management/client/src/example/PauseAndResumeSubscription.out.ok b/java/management/client/src/example/PauseAndResumeSubscription.out.ok
new file mode 100644
index 0000000000..8a98e1d0b7
--- /dev/null
+++ b/java/management/client/src/example/PauseAndResumeSubscription.out.ok
@@ -0,0 +1,133 @@
+This example is demonstrating a WS-Notification scenario
+when (for simplicity) QMan is at the same time consumer
+and producer.
+
+Specifically the example shows how a requestor can create,
+pause and resume a subscription.
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/adapter</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:485cc87c-660e-de43-e8fa-4ad5fffa95a6</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsnt:Subscribe xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2">
+ <wsnt:ConsumerReference>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/consumer</wsa:Address>
+ </wsnt:ConsumerReference>
+ </wsnt:Subscribe>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0ee610d1-e211-95c6-a498-e1084a610c44</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:485cc87c-660e-de43-e8fa-4ad5fffa95a6</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://romagazzarini:8080/qman/services/adapter</wsa:Address>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsnt:SubscribeResponse xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2">
+ <wsnt:SubscriptionReference>
+ <wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/SubscriptionManager</wsa:Address>
+ <wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <qman-wsa:ResourceId xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">282f28e6-4396-4000-a19d-87a03978e8a0</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsnt:SubscriptionReference>
+ <wsnt:CurrentTime>2009-02-27T13:51:56+01:00</wsnt:CurrentTime>
+ </wsnt:SubscribeResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/SubscriptionManager</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:35cc80af-84ac-2456-3e1f-edc2a7f60970</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">282f28e6-4396-4000-a19d-87a03978e8a0</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsnt:PauseSubscription xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:bb53d38a-428c-3d90-cc45-29d5cb27a8df</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:35cc80af-84ac-2456-3e1f-edc2a7f60970</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://romagazzarini:8080/qman/services/SubscriptionManager</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">282f28e6-4396-4000-a19d-87a03978e8a0</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <muse-op:PauseSubscriptionResponse xmlns:muse-op="http://docs.oasis-open.org/wsn/b-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://romagazzarini:8080/qman/services/SubscriptionManager</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:bfb48615-905a-e472-a9ca-5483fa592f60</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">282f28e6-4396-4000-a19d-87a03978e8a0</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsnt:ResumeSubscription xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:aab4cf18-3cc0-30c4-7036-009e26bb3213</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:bfb48615-905a-e472-a9ca-5483fa592f60</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://romagazzarini:8080/qman/services/SubscriptionManager</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">282f28e6-4396-4000-a19d-87a03978e8a0</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <muse-op:ResumeSubscriptionResponse xmlns:muse-op="http://docs.oasis-open.org/wsn/b-2"/>
+ </soap:Body>
+</soap:Envelope>
+
diff --git a/java/management/client/src/example/README.txt b/java/management/client/src/example/README.txt
new file mode 100644
index 0000000000..5365a416e5
--- /dev/null
+++ b/java/management/client/src/example/README.txt
@@ -0,0 +1,69 @@
+*** QMan WS-DM examples ***
+
+1) DESCRIPTION
+This set of examples shows QMan WS-DM interface capabilities.
+Each example is articulated in the following way.
+First the name of the example class with a brief description about that is printed out. For example :
+
+ GetWSDLMetadataExample
+-------------------------------------------------------------------
+
+This example shows the usage of WS-DM
+GetResourcePropertyRequest / Response on a
+Group service.
+The target resource is the WS-DM Adapter itself
+and the requested property is "ws-rp:Entry".
+WS-DM Adapter is a special WS-Resource (is a Group)
+that acts as the main entry point for retrieving
+all other managed resources.
+So clients that want to deal with QMan WS-Resources
+must first get resource identifiers sending
+a GetResourcePropertyRequest to WS-DM Adapter
+with "ws-rp:Entry" as target target property.
+
+-------------------------------------------------------------------
+
+Type enter to proceed.
+
+When you're ready type enter to proceed. Now the example runs and all the exchanged
+SOAP messages are printed out on the screen.
+If you want, we shipped (under sample_messages folder) several files containing those messages.
+
+A general note concerning examples...they are all written using java language so what you see is the
+"java" usage of WS-DM client API.
+The most important thing that you should keep in mind is that what is expected (on QMan side) is a SOAP WS-DM
+compliant message so on top of that you don't need to use those java API but feel free to produce those messages
+in your preferred way (by hand or using another programming language).
+
+Another thing : the examples contain a lot of code duplication because each of them is took as independent as possible.
+The general idea is that you open an example source file and in the executeExample(...) method you should have a quick
+idea of how things are working.
+Also, as mentioned before, we provided, under the sample_messages folder, the messages that are part of each example conversation.
+Remember : these messages are important, not the way / language you use to produce them.
+
+2) HOW TO RUN
+
+2.1) Java
+You need JDK 1.5 or higher in order to run and / or compile the examples.
+
+2.2) Dependencies
+You need to set / update the CLASSPATH environment variable with libraries found under $QMAN_HOME/app/qman/WEB-INF/lib.
+After that you should be able to run one the shipped examples:
+
+> java org.apache.qpid.management.example.GetMultipleResourcePropertiesExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.GetQManResourceMembersExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.GetResourceMetadataDescriptorExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.GetResourcePropertyDocumentExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.GetResourcePropertyExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.GetWSDLMetadataExample <qman_host> <qman_port>
+> java org.apache.qpid.management.example.SetResourcePropertyExample <qman_host> <qman_port>
+
+Where
+<qman_host> is the host (ip or hostname) where QMan is running;
+<qman_port> is the port number where QMan is running;
+
+2.3) Qpid
+You must have a running C++ broker with management enabled.
+
+2.4) QMan
+You must have QMan WS-DM up, running and connected with the broker above. \ No newline at end of file
diff --git a/java/management/client/src/example/SetResourcePropertiesRequest.out.ok b/java/management/client/src/example/SetResourcePropertiesRequest.out.ok
new file mode 100644
index 0000000000..1f346afa4e
--- /dev/null
+++ b/java/management/client/src/example/SetResourcePropertiesRequest.out.ok
@@ -0,0 +1,2316 @@
+ SetResourcePropertyExample
+-------------------------------------------------------------------
+
+This example shows how to change the state of a WS-Resource.
+That means a SetResourcePropertyRequest is sent to that
+WS-Resource.
+First of all a request is send to WS-DM in order to get all
+registered WS-Resources.
+If the returned list is not empty then two GetMetadataRequests
+(one for WSDL and one for RDM) are sent to the first child.
+The result metadata descriptors are used for determine :
+
+1) WS-Resource property names;
+2) Modifiability (read-only, read-write
+3) Datatype;
+-------------------------------------------------------------------
+
+So a SetResourcePropertyRequest can be sent in order
+to change the WS-Resource state.
+The example is looking for a property that has one of the
+following datatype :
+
+1) String (xsd:string)
+2) Long (xsd:long)
+3) Integer (xsd:integer or xsd:int)
+4) Double (xsd:double)
+5) Float (xsd:float)
+6) Short (xsd:short)
+
+After the update / insert request has been sent, a
+GetResourcePropertiesRequest is made again
+in order to see if the state has changed correctly.
+
+Type enter to proceed...
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:d026718c-2724-d3bf-fd5b-3c6bf4cd5a8c</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://docs.oasis-open.org/wsrf/rmd-1</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:dba8d7ab-83a6-16e1-03cc-48edc672a325</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:d026718c-2724-d3bf-fd5b-3c6bf4cd5a8c</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsrmd:MetadataDescriptor
+ interface="qman:QManWsResourcePortType"
+ name="QManWsResourceMetadata"
+ wsdlLocation="http://docs.oasis-open.org/wsrf/rmd-1 QManWsResource.wsdl"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:MgmtPubInterval" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Name" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:TerminationTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable"
+ name="qman:MsgTotalEnqueues" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Arguments" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:VhostRef" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="wsrl:CurrentTime" xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:ExpireTime" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:Durable" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-only"
+ mutability="mutable" name="qman:ConsumerCount" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ <wsrmd:Property modifiability="read-write"
+ mutability="mutable" name="qman:Type" xmlns:qman="http://amqp.apache.org/qpid/management/qman">
+ <wsrmd:ValidValues/>
+ <wsrmd:StaticValues/>
+ <wsrmd:InitialValues/>
+ </wsrmd:Property>
+ </wsrmd:MetadataDescriptor>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:11581af1-04af-05cd-7215-103cad6a316c</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <qman:GetMetadata xmlns:qman="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <qman:Dialect>http://schemas.xmlsoap.org/wsdl/</qman:Dialect>
+ </qman:GetMetadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:785964d4-9a81-784f-d68a-60de63223094</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:11581af1-04af-05cd-7215-103cad6a316c</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsx:Metadata xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <wsx:MetadataSection>
+ <wsdl:definitions name="QManWsResource"
+ targetNamespace="http://amqp.apache.org/qpid/management/qman"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <wsdl:types>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://www.w3.org/2005/08/addressing"
+ xmlns:tns="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="EndpointReference"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:element name="Address" type="tns:AttributedURIType"/>
+ <xs:element minOccurs="0"
+ name="ReferenceParameters" type="tns:ReferenceParametersType"/>
+ <xs:element minOccurs="0" ref="tns:Metadata"/>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:complexType mixed="false"
+ name="ReferenceParametersType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="Metadata"
+ type="tns:MetadataType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="MetadataType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="MessageID"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="RelatesTo"
+ type="tns:RelatesToType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="RelatesToType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute
+ default="http://www.w3.org/2005/08/addressing/reply"
+ name="RelationshipType"
+ type="tns:RelationshipTypeOpenEnum" use="optional"/>
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType
+ name="RelationshipTypeOpenEnum" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:union memberTypes="tns:RelationshipType xs:anyURI"/>
+ </xs:simpleType>
+ <xs:simpleType name="RelationshipType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:restriction base="xs:anyURI">
+ <xs:enumeration value="http://www.w3.org/2005/08/addressing/reply"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="ReplyTo"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="From"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="FaultTo"
+ type="tns:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="To"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Action"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:attribute name="IsReferenceParameter"
+ type="xs:boolean" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:simpleType name="FaultCodesOpenEnumType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:union memberTypes="tns:FaultCodesType xs:QName"/>
+ </xs:simpleType>
+ <xs:simpleType name="FaultCodesType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:restriction base="xs:QName">
+ <xs:enumeration value="tns:InvalidAddressingHeader"/>
+ <xs:enumeration value="tns:InvalidAddress"/>
+ <xs:enumeration value="tns:InvalidEPR"/>
+ <xs:enumeration value="tns:InvalidCardinality"/>
+ <xs:enumeration value="tns:MissingAddressInEPR"/>
+ <xs:enumeration value="tns:DuplicateMessageID"/>
+ <xs:enumeration value="tns:ActionMismatch"/>
+ <xs:enumeration value="tns:MessageAddressingHeaderRequired"/>
+ <xs:enumeration value="tns:DestinationUnreachable"/>
+ <xs:enumeration value="tns:ActionNotSupported"/>
+ <xs:enumeration value="tns:EndpointUnavailable"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="RetryAfter"
+ type="tns:AttributedUnsignedLongType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedUnsignedLongType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:unsignedLong">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:element name="ProblemHeaderQName"
+ type="tns:AttributedQNameType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedQNameType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:simpleContent>
+ <xs:extension base="xs:QName">
+ <xs:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:element name="ProblemHeader"
+ type="tns:AttributedAnyType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="AttributedAnyType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any maxOccurs="1" minOccurs="1"
+ namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:element name="ProblemIRI"
+ type="tns:AttributedURIType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="ProblemAction"
+ type="tns:ProblemActionType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType mixed="false"
+ name="ProblemActionType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="tns:Action"/>
+ <xs:element minOccurs="0"
+ name="SoapAction" type="xs:anyURI"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified"
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:tns="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import
+ namespace="http://www.w3.org/2005/08/addressing" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="GetMetadata" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="tns:Dialect"/>
+ <xs:element minOccurs="0" ref="tns:Identifier"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Dialect" type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Identifier"
+ type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Metadata" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="tns:MetadataSection"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MetadataSection" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType>
+ <xs:choice>
+ <xs:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ <xs:element ref="tns:MetadataReference"/>
+ <xs:element ref="tns:Location"/>
+ </xs:choice>
+ <xs:attribute name="Dialect"
+ type="xs:anyURI" use="required"/>
+ <xs:attribute name="Identifier" type="xs:anyURI"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="MetadataReference"
+ type="wsa:EndpointReferenceType" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:element name="Location" type="xs:anyURI" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
+ <xs:complexType name="AnyXmlType" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##any" processContents="lax"/>
+ </xs:complexType>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="CurrentTime">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="TerminationTime" nillable="true">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ScheduledResourceTerminationRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rl:CurrentTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rl:TerminationTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Destroy">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="DestroyResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:complexType name="ResourceNotDestroyedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="ResourceNotDestroyedFault" type="wsrf-rl:ResourceNotDestroyedFaultType"/>
+ <xsd:element name="SetTerminationTime">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element
+ name="RequestedTerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element
+ name="RequestedLifetimeDuration" type="xsd:duration"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SetTerminationTimeResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ name="NewTerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element name="CurrentTime" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="UnableToSetTerminationTimeFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToSetTerminationTimeFault" type="wsrf-rl:UnableToSetTerminationTimeFaultType"/>
+ <xsd:complexType name="TerminationTimeChangeRejectedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="TerminationTimeChangeRejectedFault" type="wsrf-rl:TerminationTimeChangeRejectedFaultType"/>
+ <xsd:element name="TerminationNotification">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1"
+ name="TerminationTime"
+ nillable="true" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="TerminationReason" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="QueryExpressionDialect" type="xsd:anyURI"/>
+ <xsd:element name="QueryExpressionRPDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrf-rp:QueryExpressionDialect"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:attribute name="ResourceProperties" type="xsd:QName"/>
+ <xsd:complexType name="ResourcePropertyValueChangeNotificationType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="OldValues" nillable="true">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" name="NewValues" nillable="true">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="ResourcePropertyValueChangeNotification" type="wsrf-rp:ResourcePropertyValueChangeNotificationType"/>
+ <xsd:complexType mixed="true" name="QueryExpressionType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="0" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI"/>
+ </xsd:complexType>
+ <xsd:element name="QueryExpression" type="wsrf-rp:QueryExpressionType"/>
+ <xsd:element name="GetResourcePropertyDocument">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="GetResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="GetResourceProperty" type="xsd:QName"/>
+ <xsd:element name="GetResourcePropertyResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="InvalidResourcePropertyQNameFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InvalidResourcePropertyQNameFault" type="wsrf-rp:InvalidResourcePropertyQNameFaultType"/>
+ <xsd:element name="GetMultipleResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="1"
+ name="ResourceProperty" type="xsd:QName"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="GetMultipleResourcePropertiesResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PutResourcePropertyDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="PutResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="ResourcePropertyChangeFailureType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="CurrentValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="RequestedValue">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="Restored" type="xsd:boolean"/>
+ </xsd:complexType>
+ <xsd:complexType name="UnableToPutResourcePropertyDocumentFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToPutResourcePropertyDocumentFault" type="wsrf-rp:UnableToPutResourcePropertyDocumentFaultType"/>
+ <xsd:complexType name="InsertType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Insert" type="wsrf-rp:InsertType"/>
+ <xsd:complexType name="UpdateType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Update" type="wsrf-rp:UpdateType"/>
+ <xsd:complexType name="DeleteType">
+ <xsd:attribute name="ResourceProperty"
+ type="xsd:QName" use="required"/>
+ </xsd:complexType>
+ <xsd:element name="Delete" type="wsrf-rp:DeleteType"/>
+ <xsd:element name="SetResourceProperties">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="1">
+ <xsd:element ref="wsrf-rp:Insert"/>
+ <xsd:element ref="wsrf-rp:Update"/>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SetResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:complexType name="InvalidModificationFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidModificationFault" type="wsrf-rp:InvalidModificationFaultType"/>
+ <xsd:complexType name="UnableToModifyResourcePropertyFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnableToModifyResourcePropertyFault" type="wsrf-rp:UnableToModifyResourcePropertyFaultType"/>
+ <xsd:complexType name="SetResourcePropertyRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="SetResourcePropertyRequestFailedFault" type="wsrf-rp:SetResourcePropertyRequestFailedFaultType"/>
+ <xsd:complexType name="InsertResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InsertResourcePropertiesRequestFailedFault" type="wsrf-rp:InsertResourcePropertiesRequestFailedFaultType"/>
+ <xsd:complexType name="UpdateResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UpdateResourcePropertiesRequestFailedFault" type="wsrf-rp:UpdateResourcePropertiesRequestFailedFaultType"/>
+ <xsd:complexType name="DeleteResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element
+ name="ResourcePropertyChangeFailure" type="wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="DeleteResourcePropertiesRequestFailedFault" type="wsrf-rp:DeleteResourcePropertiesRequestFailedFaultType"/>
+ <xsd:element name="InsertResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Insert"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="InsertResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="UpdateResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Update"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="UpdateResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="DeleteResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="DeleteResourcePropertiesResponse">
+ <xsd:complexType/>
+ </xsd:element>
+ <xsd:element name="QueryResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" ref="wsrf-rp:QueryExpression"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="QueryResourcePropertiesResponse">
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:restriction base="xsd:anyType">
+ <xsd:sequence>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="1" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:restriction>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="UnknownQueryExpressionDialectFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UnknownQueryExpressionDialectFault" type="wsrf-rp:UnknownQueryExpressionDialectFaultType"/>
+ <xsd:complexType name="InvalidQueryExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="InvalidQueryExpressionFault" type="wsrf-rp:InvalidQueryExpressionFaultType"/>
+ <xsd:complexType name="QueryEvaluationErrorFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="QueryEvaluationErrorFault" type="wsrf-rp:QueryEvaluationErrorFaultType"/>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:complexType name="ResourceUnknownFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnknownFault" type="wsrf-r:ResourceUnknownFaultType"/>
+ <xsd:complexType name="ResourceUnavailableFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnavailableFault" type="wsrf-r:ResourceUnavailableFaultType"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2"/>
+ <xsd:import namespace="http://www.w3.org/2005/08/addressing"/>
+ <xsd:simpleType name="PairsOfURIType">
+ <xsd:list itemType="xsd:anyURI"/>
+ </xsd:simpleType>
+ <xsd:attribute name="Descriptor" type="xsd:QName"/>
+ <xsd:attribute name="DescriptorLocation" type="xsd:anyURI"/>
+ <xsd:complexType mixed="true" name="DocumentationType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0" namespace="##any" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ <xsd:complexType name="DocumentedType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="DefinitionsType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrmd:MetadataDescriptor"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute
+ name="targetNamespace"
+ type="xsd:anyURI" use="required"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="Definitions" type="wsrmd:DefinitionsType">
+ <xsd:key name="MetadataDescriptor">
+ <xsd:annotation>
+ <xsd:documentation>
+ To form a QName, the name of any MetadataDescriptor must be
+ unique within a Definitions element.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:selector xpath="wsrmd:MetadataDescriptor"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ </xsd:element>
+ <xsd:complexType name="MetadataDescriptorType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrmd:Property"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:NCName" use="required"/>
+ <xsd:attribute name="interface"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute
+ name="wsdlLocation" type="wsrmd:PairsOfURIType"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="MetadataDescriptor" type="wsrmd:MetadataDescriptorType"/>
+ <xsd:complexType name="PropertyType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:choice>
+ <xsd:element
+ maxOccurs="1"
+ minOccurs="0" ref="wsrmd:ValidValues"/>
+ <xsd:element
+ maxOccurs="1"
+ minOccurs="0" ref="wsrmd:ValidValueRange"/>
+ </xsd:choice>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" ref="wsrmd:StaticValues"/>
+ <xsd:any
+ maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute name="mutability" type="wsrmd:MutabilityType"/>
+ <xsd:attribute
+ name="modifiability" type="wsrmd:ModifiabilityType"/>
+ <xsd:attribute default="false"
+ name="subscribability" type="xsd:boolean"/>
+ <xsd:anyAttribute
+ namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="Property" type="wsrmd:PropertyType"/>
+ <xsd:simpleType name="MutabilityType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="constant"/>
+ <xsd:enumeration value="appendable"/>
+ <xsd:enumeration value="mutable"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="ModifiabilityType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="read-only"/>
+ <xsd:enumeration value="read-write"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:complexType mixed="true" name="ValidValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="ValidValues" type="wsrmd:ValidValuesType"/>
+ <xsd:complexType mixed="true" name="ValidValueRangeType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="lowerBound" type="xsd:anySimpleType"/>
+ <xsd:attribute name="upperBound" type="xsd:anySimpleType"/>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="ValidValueRange" type="wsrmd:ValidValueRangeType"/>
+ <xsd:complexType mixed="true" name="StaticValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="StaticValues" type="wsrmd:StaticValuesType"/>
+ <xsd:complexType mixed="true" name="InitialValuesType">
+ <xsd:sequence>
+ <xsd:element maxOccurs="1"
+ minOccurs="0"
+ name="documentation" type="wsrmd:DocumentationType"/>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ <xsd:element name="InitialValues" type="wsrmd:InitialValuesType"/>
+ <xsd:complexType name="MetadataDescriptorReferenceType">
+ <xsd:complexContent>
+ <xsd:extension base="wsa:EndpointReferenceType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="MetadataDescriptorReference" type="wsrmd:MetadataDescriptorReferenceType"/>
+ <xsd:element name="MetadataResourceRP" type="wsrmd:DefinitionsType"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://amqp.apache.org/qpid/management/qman">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rl-2"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"/>
+ <xsd:element name="QManWsResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rl:CurrentTime"/>
+ <xsd:element ref="wsrf-rl:TerminationTime"/>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" ref="wsrf-rp:QueryExpressionDialect"/>
+ <xsd:element ref="qman:Name"/>
+ <xsd:element ref="qman:Type"/>
+ <xsd:element ref="qman:Arguments"/>
+ <xsd:element ref="qman:VhostRef"/>
+ <xsd:element ref="qman:Durable"/>
+ <xsd:element ref="qman:MsgTotalEnqueues"/>
+ <xsd:element ref="qman:ConsumerCount"/>
+ <xsd:element ref="qman:ExpireTime"/>
+ <xsd:element ref="qman:MgmtPubInterval"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="QManFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MethodInvocationFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="EntityInstanceNotFoundFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MalformedEntityNameFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NoSuchAttributeFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="result">
+ <xsd:sequence>
+ <xsd:element name="statusCode" type="xsd:long"/>
+ <xsd:element name="statusText" type="xsd:string"/>
+ <xsd:complexType name="outputParameters">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element
+ maxOccurs="unbounded"
+ minOccurs="0" name="entry">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:name
+ name="key" type="xsd:string"/>
+ <xsd:element
+ name="value" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:complexType>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Name" type="xsd:string"/>
+ <xsd:element name="Type" type="xsd:string"/>
+ <xsd:complexType name="map">
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded"
+ minOccurs="0" name="entry">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="key" type="xsd:string"/>
+ <xsd:element
+ name="value" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Arguments" type="qman:map"/>
+ <xsd:complexType name="uuid">
+ <xsd:sequence>
+ <xsd:element name="uuid" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="VhostRef" type="qman:uuid"/>
+ <xsd:element name="Durable" type="xsd:boolean"/>
+ <xsd:element name="MsgTotalEnqueues" type="xsd:long"/>
+ <xsd:element name="ConsumerCount" type="xsd:integer"/>
+ <xsd:element name="ExpireTime" type="xsd:dateTime"/>
+ <xsd:element name="MgmtPubInterval" type="xsd:short"/>
+ <xsd:element
+ name="echoWithSimpleTypesRequest" type="qman:echoWithSimpleTypesRequest"/>
+ <xsd:element
+ name="echoWithSimpleTypesResponse" type="qman:echoWithSimpleTypesResponse"/>
+ <xsd:complexType name="echoWithSimpleTypesRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="xsd:long"/>
+ <xsd:element name="p2" type="xsd:boolean"/>
+ <xsd:element name="p3" type="xsd:double"/>
+ <xsd:element name="p4" type="xsd:float"/>
+ <xsd:element name="p5" type="xsd:integer"/>
+ <xsd:element name="p6" type="xsd:short"/>
+ <xsd:element name="p7" type="xsd:string"/>
+ <xsd:element name="p8" type="xsd:anyURI"/>
+ <xsd:element name="p9" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypesResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithArraysRequest" type="qman:echoWithArraysRequest"/>
+ <xsd:element name="echoWithArraysResponse" type="qman:echoWithArraysResponse"/>
+ <xsd:complexType name="arrayOfLong">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:long"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfBoolean">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDouble">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:double"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfFloat">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:float"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfInteger">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:integer"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfShort">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:short"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfString">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfURI">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:anyURI"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDate">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:dateTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithArraysRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfLong"/>
+ <xsd:element name="p2" type="qman:arrayOfBoolean"/>
+ <xsd:element name="p3" type="qman:arrayOfDouble"/>
+ <xsd:element name="p4" type="qman:arrayOfFloat"/>
+ <xsd:element name="p5" type="qman:arrayOfInteger"/>
+ <xsd:element name="p6" type="qman:arrayOfShort"/>
+ <xsd:element name="p7" type="qman:arrayOfString"/>
+ <xsd:element name="p8" type="qman:arrayOfURI"/>
+ <xsd:element name="p9" type="qman:arrayOfDate"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithArraysResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="echoWithSimpleTypeArraysRequest" type="qman:echoWithSimpleTypeArraysRequest"/>
+ <xsd:element
+ name="echoWithSimpleTypeArraysResponse" type="qman:echoWithSimpleTypeArraysResponse"/>
+ <xsd:complexType name="arrayOfLong">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:long"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfBoolean">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:boolean"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfDouble">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:double"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfFloat">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:float"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfInt">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:integer"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="arrayOfShort">
+ <xsd:sequence>
+ <xsd:element name="entry" type="xsd:short"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypeArraysRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfLong"/>
+ <xsd:element name="p2" type="qman:arrayOfBoolean"/>
+ <xsd:element name="p3" type="qman:arrayOfDouble"/>
+ <xsd:element name="p4" type="qman:arrayOfFloat"/>
+ <xsd:element name="p5" type="qman:arrayOfInt"/>
+ <xsd:element name="p6" type="qman:arrayOfShort"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithSimpleTypeArraysResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithByteArrayRequest" type="qman:echoWithByteArrayRequest"/>
+ <xsd:element
+ name="echoWithByteArrayResponse" type="qman:echoWithByteArrayResponse"/>
+ <xsd:complexType name="arrayOfByte">
+ <xsd:sequence>
+ <xsd:element name="entry" type=""/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithByteArrayRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:arrayOfByte"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithByteArrayResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element
+ name="voidWithoutArgumentsRequest" type="qman:voidWithoutArgumentsRequest"/>
+ <xsd:element
+ name="voidWithoutArgumentsResponse" type="qman:voidWithoutArgumentsResponse"/>
+ <xsd:complexType name="voidWithoutArgumentsRequest">
+ <xsd:sequence/>
+ </xsd:complexType>
+ <xsd:complexType name="voidWithoutArgumentsResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="throwsExceptionRequest" type="qman:throwsExceptionRequest"/>
+ <xsd:element name="throwsExceptionResponse" type="qman:throwsExceptionResponse"/>
+ <xsd:complexType name="throwsExceptionRequest">
+ <xsd:sequence/>
+ </xsd:complexType>
+ <xsd:complexType name="throwsExceptionResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithUUIDRequest" type="qman:echoWithUUIDRequest"/>
+ <xsd:element name="echoWithUUIDResponse" type="qman:echoWithUUIDResponse"/>
+ <xsd:complexType name="echoWithUUIDRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:uuid"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithUUIDResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="echoWithMapRequest" type="qman:echoWithMapRequest"/>
+ <xsd:element name="echoWithMapResponse" type="qman:echoWithMapResponse"/>
+ <xsd:complexType name="echoWithMapRequest">
+ <xsd:sequence>
+ <xsd:element name="p1" type="qman:map"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="echoWithMapResponse">
+ <xsd:sequence>
+ <xsd:element name="result" type="qman:result"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:schema>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <xsd:import namespace="http://www.w3.org/2005/08/addressing"/>
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace">
+ <xsd:annotation>
+ <xsd:documentation>
+ Get access to the xml: attribute groups for xml:lang as declared on 'schema'
+ and 'documentation' below
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:import>
+ <xsd:element name="BaseFault" type="wsrf-bf:BaseFaultType"/>
+ <xsd:complexType name="BaseFaultType">
+ <xsd:sequence>
+ <xsd:any maxOccurs="unbounded"
+ minOccurs="0"
+ namespace="##other" processContents="lax"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="1" name="Timestamp" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="Originator" type="wsa:EndpointReferenceType"/>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="ErrorCode">
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:extension base="xsd:anyType">
+ <xsd:attribute
+ name="dialect"
+ type="xsd:anyURI" use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="unbounded"
+ minOccurs="0" name="Description">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute
+ ref="xml:lang" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element maxOccurs="1"
+ minOccurs="0" name="FaultCause">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any maxOccurs="1"
+ minOccurs="1"
+ namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+ </xsd:schema>
+ <xs:schema
+ targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xml:lang="en" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:attribute name="lang" type="xs:language"/>
+ <xs:attribute default="preserve" name="space">
+ <xs:simpleType>
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="base" type="xs:anyURI"/>
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ </xs:attributeGroup>
+ </xs:schema>
+ </wsdl:types>
+ <wsdl:message name="GetMetadataMsg">
+ <wsdl:part element="wsx:GetMetadata" name="GetMetadataMsg"/>
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMsg">
+ <wsdl:part element="wsx:Metadata" name="GetMetadataResponseMsg"/>
+ </wsdl:message>
+ <wsdl:message name="DestroyRequest">
+ <wsdl:part element="wsrf-rl:Destroy" name="DestroyRequest"/>
+ </wsdl:message>
+ <wsdl:message name="DestroyResponse">
+ <wsdl:part element="wsrf-rl:DestroyResponse" name="DestroyResponse"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceNotDestroyedFault">
+ <wsdl:part
+ element="wsrf-rl:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part element="wsrf-r:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part
+ element="wsrf-r:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetTerminationTimeRequest">
+ <wsdl:part element="wsrf-rl:SetTerminationTime" name="SetTerminationTimeRequest"/>
+ </wsdl:message>
+ <wsdl:message name="SetTerminationTimeResponse">
+ <wsdl:part
+ element="wsrf-rl:SetTerminationTimeResponse" name="SetTerminationTimeResponse"/>
+ </wsdl:message>
+ <wsdl:message name="UnableToSetTerminationTimeFault">
+ <wsdl:part
+ element="wsrf-rl:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault"/>
+ </wsdl:message>
+ <wsdl:message name="TerminationTimeChangeRejectedFault">
+ <wsdl:part
+ element="wsrf-rl:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyDocument" name="GetResourcePropertyDocumentRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyDocumentResponse" name="GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part element="wsrf-rp:GetResourceProperty" name="GetResourcePropertyRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part
+ element="wsrf-rp:GetResourcePropertyResponse" name="GetResourcePropertyResponse"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:GetMultipleResourceProperties" name="GetMultipleResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:GetMultipleResourcePropertiesResponse" name="GetMultipleResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:QueryResourceProperties" name="QueryResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:QueryResourcePropertiesResponse" name="QueryResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <wsdl:part
+ element="wsrf-rp:UnknownQueryExpressionDialectFault" name="UnknownQueryExpressionDialectFault"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidQueryExpressionFault" name="InvalidQueryExpressionFault"/>
+ </wsdl:message>
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <wsdl:part
+ element="wsrf-rp:QueryEvaluationErrorFault" name="QueryEvaluationErrorFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesRequest">
+ <wsdl:part
+ element="wsrf-rp:SetResourceProperties" name="SetResourcePropertiesRequest"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesResponse">
+ <wsdl:part
+ element="wsrf-rp:SetResourcePropertiesResponse" name="SetResourcePropertiesResponse"/>
+ </wsdl:message>
+ <wsdl:message name="InvalidModificationFault">
+ <wsdl:part
+ element="wsrf-rp:InvalidModificationFault" name="InvalidModificationFault"/>
+ </wsdl:message>
+ <wsdl:message name="UnableToModifyResourcePropertyFault">
+ <wsdl:part
+ element="wsrf-rp:UnableToModifyResourcePropertyFault" name="UnableToModifyResourcePropertyFault"/>
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertyRequestFailedFault">
+ <wsdl:part
+ element="wsrf-rp:SetResourcePropertyRequestFailedFault" name="SetResourcePropertyRequestFailedFault"/>
+ </wsdl:message>
+ <wsdl:portType name="QManWsResourcePortType"
+ wsrf-rp:ResourceProperties="qman:QManWsResourceProperties"
+ wsrmd:Descriptor="QManWsResourceMetadata" wsrmd:DescriptorLocation="QManWsResource.rmd">
+ <wsdl:operation name="GetMetadata">
+ <wsdl:input message="qman:GetMetadataMsg"
+ name="GetMetadataMsg" wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"/>
+ <wsdl:output
+ message="qman:GetMetadataResponseMsg"
+ name="GetMetadataResponseMsg" wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="Destroy">
+ <wsdl:input message="qman:DestroyRequest"
+ name="DestroyRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyRequest"/>
+ <wsdl:output message="qman:DestroyResponse"
+ name="DestroyResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyResponse"/>
+ <wsdl:fault
+ message="qman:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl:input
+ message="qman:SetTerminationTimeRequest"
+ name="SetTerminationTimeRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeRequest"/>
+ <wsdl:output
+ message="qman:SetTerminationTimeResponse"
+ name="SetTerminationTimeResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeResponse"/>
+ <wsdl:fault
+ message="qman:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input
+ message="qman:GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"/>
+ <wsdl:output
+ message="qman:GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input
+ message="qman:GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"/>
+ <wsdl:output
+ message="qman:GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input
+ message="qman:GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input
+ message="qman:QueryResourcePropertiesRequest"
+ name="QueryResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:QueryResourcePropertiesResponse"
+ name="QueryResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:UnknownQueryExpressionDialectFault" name="UnknownQueryExpressionDialectFault"/>
+ <wsdl:fault
+ message="qman:InvalidQueryExpressionFault" name="InvalidQueryExpressionFault"/>
+ <wsdl:fault
+ message="qman:QueryEvaluationErrorFault" name="QueryEvaluationErrorFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl:input
+ message="qman:SetResourcePropertiesRequest"
+ name="SetResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"/>
+ <wsdl:output
+ message="qman:SetResourcePropertiesResponse"
+ name="SetResourcePropertiesResponse" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse"/>
+ <wsdl:fault
+ message="qman:ResourceUnknownFault" name="ResourceUnknownFault"/>
+ <wsdl:fault
+ message="qman:ResourceUnavailableFault" name="ResourceUnavailableFault"/>
+ <wsdl:fault
+ message="qman:InvalidModificationFault" name="InvalidModificationFault"/>
+ <wsdl:fault
+ message="qman:UnableToModifyResourcePropertyFault" name="UnableToModifyResourcePropertyFault"/>
+ <wsdl:fault
+ message="qman:InvalidResourcePropertyQNameFault" name="InvalidResourcePropertyQNameFault"/>
+ <wsdl:fault
+ message="qman:SetResourcePropertyRequestFailedFault" name="SetResourcePropertyRequestFailedFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypes">
+ <wsdl:input
+ message="qman:echoWithSimpleTypesRequestMessage"
+ name="echoWithSimpleTypesRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypes"/>
+ <wsdl:output
+ message="qman:echoWithSimpleTypesResponseMessage"
+ name="echoWithSimpleTypesResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypesResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithArrays">
+ <wsdl:input
+ message="qman:echoWithArraysRequestMessage"
+ name="echoWithArraysRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithArrays"/>
+ <wsdl:output
+ message="qman:echoWithArraysResponseMessage"
+ name="echoWithArraysResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithArraysResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypeArrays">
+ <wsdl:input
+ message="qman:echoWithSimpleTypeArraysRequestMessage"
+ name="echoWithSimpleTypeArraysRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArrays"/>
+ <wsdl:output
+ message="qman:echoWithSimpleTypeArraysResponseMessage"
+ name="echoWithSimpleTypeArraysResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArraysResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithByteArray">
+ <wsdl:input
+ message="qman:echoWithByteArrayRequestMessage"
+ name="echoWithByteArrayRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithByteArray"/>
+ <wsdl:output
+ message="qman:echoWithByteArrayResponseMessage"
+ name="echoWithByteArrayResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithByteArrayResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="voidWithoutArguments">
+ <wsdl:input
+ message="qman:voidWithoutArgumentsRequestMessage"
+ name="voidWithoutArgumentsRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/voidWithoutArguments"/>
+ <wsdl:output
+ message="qman:voidWithoutArgumentsResponseMessage"
+ name="voidWithoutArgumentsResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/voidWithoutArgumentsResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="throwsException">
+ <wsdl:input
+ message="qman:throwsExceptionRequestMessage"
+ name="throwsExceptionRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/throwsException"/>
+ <wsdl:output
+ message="qman:throwsExceptionResponseMessage"
+ name="throwsExceptionResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/throwsExceptionResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithUUID">
+ <wsdl:input
+ message="qman:echoWithUUIDRequestMessage"
+ name="echoWithUUIDRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithUUID"/>
+ <wsdl:output
+ message="qman:echoWithUUIDResponseMessage"
+ name="echoWithUUIDResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithUUIDResponse"/>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithMap">
+ <wsdl:input
+ message="qman:echoWithMapRequestMessage"
+ name="echoWithMapRequest" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithMap"/>
+ <wsdl:output
+ message="qman:echoWithMapResponseMessage"
+ name="echoWithMapResponse" wsa:action="http://amqp.apache.org/qpid/management/qman/echoWithMapResponse"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="QManWsResourceBinding" type="qman:QManWsResourcePortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata"/>
+ <wsdl:input>
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="Destroy">
+ <wsdl-soap:operation soapAction="Destroy"/>
+ <wsdl:input name="DestroyRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="DestroyResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceNotDestroyedFault">
+ <wsdl-soap:fault
+ name="ResourceNotDestroyedFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl-soap:operation soapAction="SetTerminationTime"/>
+ <wsdl:input name="SetTerminationTimeRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="SetTerminationTimeResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="UnableToSetTerminationTimeFault">
+ <wsdl-soap:fault
+ name="UnableToSetTerminationTimeFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="TerminationTimeChangeRejectedFault">
+ <wsdl-soap:fault
+ name="TerminationTimeChangeRejectedFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl-soap:operation soapAction="QueryResourceProperties"/>
+ <wsdl:input name="QueryResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="QueryResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault">
+ <wsdl-soap:fault
+ name="UnknownQueryExpressionDialectFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidQueryExpressionFault">
+ <wsdl-soap:fault
+ name="InvalidQueryExpressionFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="QueryEvaluationErrorFault">
+ <wsdl-soap:fault
+ name="QueryEvaluationErrorFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl-soap:operation soapAction="http://oasis.org/SetResourceProperties"/>
+ <wsdl:input name="SetResourcePropertiesRequest">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="SetResourcePropertiesResponse">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ name="ResourceUnknownFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ name="ResourceUnavailableFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidModificationFault">
+ <wsdl-soap:fault
+ name="InvalidModificationFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnableToModifyResourcePropertyFault">
+ <wsdl-soap:fault
+ name="UnableToModifyResourcePropertyFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ name="InvalidResourcePropertyQNameFault" use="literal"/>
+ </wsdl:fault>
+ <wsdl:fault name="SetResourcePropertyRequestFailedFault">
+ <wsdl-soap:fault
+ name="SetResourcePropertyRequestFailedFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="http://ws.apache.org/muse/test/wsrf/GetMetadata"/>
+ <wsdl:input name="GetMetadataMsg">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="GetMetadataResponseMsg">
+ <wsdl-soap:body
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypes">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypes"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithArrays">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithArrays"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithSimpleTypeArrays">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithSimpleTypeArrays"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithByteArray">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithByteArray"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="voidWithoutArguments">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/voidWithoutArguments"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="throwsException">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/throwsException"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithUUID">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithUUID"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="echoWithMap">
+ <wsdl-soap:operation soapAction="http://amqp.apache.org/qpid/management/qman/echoWithMap"/>
+ <wsdl:input>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="QManWsResourceService">
+ <wsdl:port binding="qman:QManWsResourceBinding" name="QManWsResourcePort">
+ <wsdl-soap:address location="http://romagazzarini:8080/qman/services/QManWsResource"/>
+ </wsdl:port>
+ </wsdl:service>
+ <message name="echoWithSimpleTypesRequestMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypesRequest" name="echoWithSimpleTypesRequest"/>
+ </message>
+ <wsdl:message name="echoWithSimpleTypesResponseMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypesResponse" name="echoWithSimpleTypesResponse"/>
+ </wsdl:message>
+ <message name="echoWithArraysRequestMessage">
+ <wsdl:part element="qman:echoWithArraysRequest" name="echoWithArraysRequest"/>
+ </message>
+ <wsdl:message name="echoWithArraysResponseMessage">
+ <wsdl:part element="qman:echoWithArraysResponse" name="echoWithArraysResponse"/>
+ </wsdl:message>
+ <message name="echoWithSimpleTypeArraysRequestMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypeArraysRequest" name="echoWithSimpleTypeArraysRequest"/>
+ </message>
+ <wsdl:message name="echoWithSimpleTypeArraysResponseMessage">
+ <wsdl:part
+ element="qman:echoWithSimpleTypeArraysResponse" name="echoWithSimpleTypeArraysResponse"/>
+ </wsdl:message>
+ <message name="echoWithByteArrayRequestMessage">
+ <wsdl:part
+ element="qman:echoWithByteArrayRequest" name="echoWithByteArrayRequest"/>
+ </message>
+ <wsdl:message name="echoWithByteArrayResponseMessage">
+ <wsdl:part
+ element="qman:echoWithByteArrayResponse" name="echoWithByteArrayResponse"/>
+ </wsdl:message>
+ <message name="voidWithoutArgumentsRequestMessage">
+ <wsdl:part
+ element="qman:voidWithoutArgumentsRequest" name="voidWithoutArgumentsRequest"/>
+ </message>
+ <wsdl:message name="voidWithoutArgumentsResponseMessage">
+ <wsdl:part
+ element="qman:voidWithoutArgumentsResponse" name="voidWithoutArgumentsResponse"/>
+ </wsdl:message>
+ <message name="throwsExceptionRequestMessage">
+ <wsdl:part element="qman:throwsExceptionRequest" name="throwsExceptionRequest"/>
+ </message>
+ <wsdl:message name="throwsExceptionResponseMessage">
+ <wsdl:part
+ element="qman:throwsExceptionResponse" name="throwsExceptionResponse"/>
+ </wsdl:message>
+ <message name="echoWithUUIDRequestMessage">
+ <wsdl:part element="qman:echoWithUUIDRequest" name="echoWithUUIDRequest"/>
+ </message>
+ <wsdl:message name="echoWithUUIDResponseMessage">
+ <wsdl:part element="qman:echoWithUUIDResponse" name="echoWithUUIDResponse"/>
+ </wsdl:message>
+ <message name="echoWithMapRequestMessage">
+ <wsdl:part element="qman:echoWithMapRequest" name="echoWithMapRequest"/>
+ </message>
+ <wsdl:message name="echoWithMapResponseMessage">
+ <wsdl:part element="qman:echoWithMapResponse" name="echoWithMapResponse"/>
+ </wsdl:message>
+ </wsdl:definitions>
+ </wsx:MetadataSection>
+ </wsx:Metadata>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:103f564f-7008-8456-042f-095a092444f9</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MgmtPubInterval</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:b78625a8-af2f-b542-8001-d7e81d3de1c9</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:103f564f-7008-8456-042f-095a092444f9</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:MgmtPubInterval xmlns:qman="http://amqp.apache.org/qpid/management/qman">32767</qman:MgmtPubInterval>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0b80a9ca-9e02-1d6b-c0e0-8ceb8560ee6e</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:SetResourceProperties xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-rp:Update>
+ <qman:MgmtPubInterval xmlns:qman="http://amqp.apache.org/qpid/management/qman">12</qman:MgmtPubInterval>
+ </wsrf-rp:Update>
+ </wsrf-rp:SetResourceProperties>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:ae67ff51-e1c1-f2c3-5243-d54905f3907b</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0b80a9ca-9e02-1d6b-c0e0-8ceb8560ee6e</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:SetResourcePropertiesResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0dca61e4-072f-3091-0f38-9a967f14666a</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:MgmtPubInterval</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:84399474-c5b1-8738-f410-fd86face1599</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0dca61e4-072f-3091-0f38-9a967f14666a</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:MgmtPubInterval xmlns:qman="http://amqp.apache.org/qpid/management/qman">12</qman:MgmtPubInterval>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+----------------------------------------------------------------------------------
+Resource has been correctly updated.
+----------------------------------------------------------------------------------
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:8be37e48-b3a5-0e4a-aea3-eda3aad58418</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Type</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:b92c8851-d071-204f-6506-3706694cf32e</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:8be37e48-b3a5-0e4a-aea3-eda3aad58418</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:7917abf6-5c85-7e25-4515-b7f60cd32c39</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:SetResourceProperties xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <wsrf-rp:Insert>
+ <qman:Type xmlns:qman="http://amqp.apache.org/qpid/management/qman">This is a string.</qman:Type>
+ </wsrf-rp:Insert>
+ </wsrf-rp:SetResourceProperties>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:0b895a1f-39e5-8739-d9d7-390c5f2eb445</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:7917abf6-5c85-7e25-4515-b7f60cd32c39</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:SetResourcePropertiesResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"/>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (outgoing):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost:8080/qman/services/QManWsResource</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:930f39a4-0114-03bd-9921-105579fb4213</wsa:MessageID>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://www.w3.org/2005/08/addressing/role/anonymous</wsa:Address>
+ </wsa:From>
+ <qman-wsa:ResourceId
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ wsa:IsReferenceParameter="true" xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourceProperty
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2" xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:Type</wsrf-rp:GetResourceProperty>
+ </soap:Body>
+</soap:Envelope>
+
+[CLIENT TRACE] SOAP envelope contents (incoming):
+
+<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
+ <soap:Header>
+ <wsa:To xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/role/anonymous</wsa:To>
+ <wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse</wsa:Action>
+ <wsa:MessageID xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:3d3f04ab-3171-da69-08b5-2e74927ee981</wsa:MessageID>
+ <wsa:RelatesTo RelationshipType="wsa:Reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">uuid:930f39a4-0114-03bd-9921-105579fb4213</wsa:RelatesTo>
+ <wsa:From xmlns:wsa="http://www.w3.org/2005/08/addressing">
+ <wsa:Address>http://localhost:8080/qman/services/QManWsResource</wsa:Address>
+ <wsa:ReferenceParameters>
+ <qman-wsa:ResourceId wsa:IsReferenceParameter="true"
+ xmlns:qman-wsa="http://amqp.apache.org/qpid/management/qman/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid</qman-wsa:ResourceId>
+ </wsa:ReferenceParameters>
+ </wsa:From>
+ </soap:Header>
+ <soap:Body>
+ <wsrf-rp:GetResourcePropertyResponse xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2">
+ <qman:Type xmlns:qman="http://amqp.apache.org/qpid/management/qman">This is a string.</qman:Type>
+ </wsrf-rp:GetResourcePropertyResponse>
+ </soap:Body>
+</soap:Envelope>
+
+----------------------------------------------------------------------------------
+Resource has been correctly updated.
+----------------------------------------------------------------------------------
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java b/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java
new file mode 100644
index 0000000000..ffa96635a8
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+
+/**
+ * Common interface for all QMan related examples.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class AbstractQManExample
+{
+ final static String LINE_SEPARATOR = System.getProperty("line.separator","\n");
+ protected final static String PREFIX = "qman";
+
+ /**
+ * Prints out the expected command line of this sample and after that exits.
+ */
+ static void printUsageAndExit(String reason)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WARNING! Unable to run this sample : ")
+ .append(reason)
+ .append(LINE_SEPARATOR)
+ .append("-------------------------------------------------------------")
+ .append(LINE_SEPARATOR)
+ .append("Expected command line args for this sample are :")
+ .append(LINE_SEPARATOR)
+ .append(LINE_SEPARATOR)
+ .append("1) host : ip or host name where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("2) port : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("------------------------------------------------------------");
+ System.out.println(builder);
+ System.exit(1);
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ abstract void printOutExampleDescription();
+
+ /**
+ * Executes this example.
+ * Note that this is just a template method used to avoid code duplication
+ * (printOutExampleDescription() line) so in order to see how the example
+ * works you should have a look at the concrete implementation of
+ * executeExample(String host, int port).
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ */
+ void execute(String [] arguments)
+ {
+ if (arguments.length != 2){
+ printUsageAndExit("invalid command line was given.");
+ }
+
+ try
+ {
+ // 1) Parses command line arguments...
+ String host = arguments[0];
+ int port = Integer.parseInt(arguments[1]);
+
+ printOutExampleDescription();
+
+ waitForUserInput("Type enter to proceed...");
+
+ executeExample(host, port);
+
+ } catch(NumberFormatException exception)
+ {
+ printUsageAndExit("port number must be a number.");
+ } catch(Exception exception)
+ {
+ System.out.println("-----------------------EXAMPLE FAILURE-----------");
+ System.out.println("Not well-defined exception was detected while");
+ System.out.println("running the example.");
+ exception.printStackTrace(System.out);
+ System.out.println("--------------------------------------------------------");
+ }
+ }
+
+ protected void waitForUserInput(String message) throws IOException {
+ System.out.println(message);
+ System.in.read();
+ }
+
+ /**
+ * Each concrete implementor must define here how the example works.
+ * So, on top of that, user who wants to see how to use a specific feature
+ * should have a look at the concrete implementation of this method..
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception{};
+
+ /**
+ * Returns the endpoint reference of the adapter service.
+ *
+ * @param host ip or host name where the service is running.
+ * @param port the port number of the server where the service is running.
+ * @return the endpoint reference of the adapter service.
+ */
+ EndpointReference getAdapterEndpointReference(String host, int port)
+ {
+ URI address = URI.create(
+ "http://"+
+ host+
+ ":"+
+ port+
+ "/qman/services/adapter");
+ return new EndpointReference(address);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java b/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java
new file mode 100644
index 0000000000..153f0f66d5
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java
@@ -0,0 +1,240 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+
+/**
+ * This example shows how to connect QMan with a broker using the adapter interface.
+ * As you can see the interface is very simple and requests you the following parameters :
+ *
+ * <ul>
+ * <li>hostname : the host (hostname or ip) where the broker is running;</li>
+ * <li>port : the port number of the running broker;</li>
+ * <li>virtual host : the name of the virtual host;</li>
+ * <li>username : the username that will be used for estabilshing connection.</li>
+ * <li>password : the password that will be used for estabilshing connection.</li>
+ * <li>initial pool capacity : the initial size of broker connection pool. </li>
+ * <li>maximum pool capacity : the max allowed size of broker connection pool.</li>
+ * <li>maximum wait timeout : the max wait timeout for retrieving connections.</li>
+ * </ul>
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConnectWithBrokerExample extends AbstractQManExample
+{
+
+ /**
+ * Executes the connect example.
+ * Although not specified explicitly, the input array MUST contains in the following order :
+ *
+ * <ul>
+ * <li>host : the hostname where QMan is running;</li>
+ * <li>port : the port number where QMan is running;</li>
+ * <li>qpid host : the host name where QPid is running;</li>
+ * <li>qpid port : the port number where Qpid is running;</li>
+ * <li>virtual host : the virtual host name;</li>
+ * <li>username : the username that will be used for estabilshing connection.</li>
+ * <li>password : the password that will be used for estabilshing connection.</li>
+ * <li>initial pool capacity : the initial size of broker connection pool. </li>
+ * <li>maximum pool capacity : the max allowed size of broker connection pool.</li>
+ * <li>maximum wait timeout : the max wait timeout for retrieving connections.</li>
+ * </ul>
+ *
+ * Note that this example differs from the others (and therefore is overriding the execute() method) because
+ * in this case we are not using the "standard" WSRF interface but instead an additional custom
+ * "operation" on a WS-Resource.
+ *
+ * @param arguments the commadn line arguments.
+ */
+ void execute(String [] arguments)
+ {
+ if (arguments.length != 10){
+ printUsageAndExit("invalid command line was given.");
+ }
+
+ try
+ {
+ // 1) Parses command line arguments...
+ String host = arguments[0];
+ int port = Integer.parseInt(arguments[1]);
+ String qpidHost = arguments[2];
+ int qpidPort = Integer.parseInt(arguments[3]);
+ String virtualHost = arguments[4];
+ String username = arguments[5];
+ String password = arguments[6];
+ int initPoolCapacity = Integer.parseInt(arguments[7]);
+ int maxPoolCapacity = Integer.parseInt(arguments[8]);
+ long maxWaitTimeout = Long.parseLong(arguments[9]);
+
+ printOutExampleDescription();
+
+ waitForUserInput("Type enter to proceed...");
+
+ executeExample(
+ host,
+ port,
+ qpidHost,
+ qpidPort,
+ virtualHost,
+ username,
+ password,
+ initPoolCapacity,
+ maxPoolCapacity,
+ maxWaitTimeout);
+
+ } catch(NumberFormatException exception)
+ {
+ printUsageAndExit("Unable to run the example. Please ensure that all numeric values are correctly supplied.");
+ } catch(Exception exception)
+ {
+ System.out.println("-----------------------EXAMPLE FAILURE-----------");
+ System.out.println("Not well-defined exception was detected while");
+ System.out.println("running the example.");
+ exception.printStackTrace(System.out);
+ System.out.println("--------------------------------------------------------");
+ }
+ }
+
+ /**
+ * Connects QMan with a broker.
+ *
+ *@param host the hostname where QMan is running;
+ *@param port the port number where QMan is running;
+ *@param qpidHost the host name where QPid is running;
+ *@param qpidPort the port number where Qpid is running;
+ *@param virtualHost the virtual host name;
+ *@param username the username that will be used for estabilshing connection.
+ *@param password the password that will be used for estabilshing connection.
+ *@param initPoolCapacity the initial size of broker connection pool.
+ *@param maxPoolCapacity the max allowed size of broker connection pool.
+ *@param maxWaitTimeout the max wait timeout for retrieving connections.
+ *
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port, String qpidHost, int qpidPort, String virtualHost, String username, String password, int initPoolCapacity, int maxPoolCapacity, long maxWaitTimeout) throws Exception
+ {
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+ WsResourceClient adapterClient = new WsResourceClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 2) Creates the Adapter service client...
+ adapterClient.invoke(
+ getProxyHandler(),
+ new Object[]{
+ qpidHost,
+ qpidPort,
+ username,
+ password,
+ virtualHost,
+ initPoolCapacity,
+ maxPoolCapacity,
+ maxWaitTimeout});
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows how to connect QMan with a broker using");
+ System.out.println("the adapter interface.");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler getProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://amqp.apache.org/qpid/management/qman/Connect");
+ handler.setRequestName(new QName("http://amqp.apache.org/qpid/management/qman", "Connect", PREFIX));
+ handler.setRequestParameterNames(new QName[]{
+ new QName("http://amqp.apache.org/qpid/management/qman", "host", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "port", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "username", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "password", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "virtualHost", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "initialPoolCapacity", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "maxPoolCapacity", PREFIX),
+ new QName("http://amqp.apache.org/qpid/management/qman", "maxWaitTimeout", PREFIX)});
+ handler.setResponseName(new QName("http://amqp.apache.org/qpid/management/qman", "ConnectResponse", PREFIX));
+ handler.setReturnType(null);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new ConnectWithBrokerExample().execute(arguments);
+ }
+
+ static void printUsageAndExit(String reason)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append("WARNING! Unable to run this sample : ")
+ .append(reason)
+ .append(LINE_SEPARATOR)
+ .append("-------------------------------------------------------------")
+ .append(LINE_SEPARATOR)
+ .append("Expected command line args for this sample are :")
+ .append(LINE_SEPARATOR)
+ .append(LINE_SEPARATOR)
+ .append("1) host : ip or host name where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("2) port : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("3) qpid host : port number where Qpid is running.")
+ .append(LINE_SEPARATOR)
+ .append("4) qpid port : port number where Qpid is running.")
+ .append(LINE_SEPARATOR)
+ .append("5) virtual host : virtual host name.")
+ .append(LINE_SEPARATOR)
+ .append("6) username : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("7) password : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("8) initial pool capacity : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("9) max pool capacity : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+ .append("10) max wait timeout : port number where QMan is running.")
+ .append(LINE_SEPARATOR)
+
+ .append("------------------------------------------------------------");
+ System.out.println(builder);
+ System.exit(1);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java b/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java
new file mode 100644
index 0000000000..42587d78ff
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java
@@ -0,0 +1,293 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import java.net.URI;
+import java.util.Date;
+
+import org.apache.muse.util.xml.XPathUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.notification.impl.FilterCollection;
+import org.apache.muse.ws.notification.impl.MessagePatternFilter;
+import org.apache.muse.ws.notification.impl.ProducerPropertiesFilter;
+import org.apache.muse.ws.notification.impl.TopicFilter;
+import org.apache.muse.ws.notification.remote.NotificationProducerClient;
+import org.apache.qpid.management.Names;
+
+/**
+ * This example is demonstrating a WS-Notification scenario
+ * when (for simplicity) QMan is at the same time consumer
+ * and producer.
+ *
+ * Basically we have (on producer side) two topics : one for
+ * lifecycle events of object instance (objects created & removed)
+ * and another one for lifecycle of event (events created).
+ *
+ * On consumer side there are many options that you can use in
+ * order to made a sunscription :
+ *
+ * <ul>
+ * <li>you could be an observer of all messages (all topics);</li>
+ * <li>you could be an observer of one specific topic;</li>
+ * <li>
+ * you could be an observer of all messages that match
+ * a condition expressed in XPath;
+ * </li>
+ * </ul>
+ *
+ * All those options are provided with or withour a termination time.
+ * A subscription with a termination time will have a predefined expiry
+ * date while if there's no termination the subscription will never expire.
+ *
+ * @author Andrea Gazzarini
+ *
+ */
+public class ConsumerAndProducerExample extends AbstractQManExample
+{
+ @Override
+ void executeExample(String host, int port) throws Exception
+ {
+ // This is QMan...
+ URI producerURI = URI.create("http://"+host+":"+port+"/qman/services/adapter");
+
+ // ...and this is QMan too! Note that it has an hidden consumer capability that is used in
+ // order to run successfully this example...
+ URI consumerURI = URI.create("http://"+host+":"+port+"/qman/services/consumer");
+
+ EndpointReference producerEPR = new EndpointReference(producerURI);
+ EndpointReference consumerEPR = new EndpointReference(consumerURI);
+
+ // Example 1 : all messages on all topics without termination time.
+ subscribeAllMessagesWithoutTerminationTime(producerEPR,consumerEPR);
+
+ // Example 2 : all messages on all topics with termination time.
+ subscribeAllMessagesWithTerminationTime(producerEPR,consumerEPR);
+
+ // Example 3: Topic filter without termination time.
+ topicSubscriptionWithoutTerminationTime(producerEPR,consumerEPR);
+
+ // Example 4: Topic filter with termination time.
+ topicSubscriptionWithTerminationTime(producerEPR,consumerEPR);
+
+ // Example 5: a MessageFilter is installed in order to listen only for connection events
+ // (connections created or removed). The subscription never expire.
+ allMessagesWithMessageFilterWithoutTerminationTime(producerEPR,consumerEPR);
+
+ // Example 6: a MessageFilter is installed in order to listen only for connection events
+ // (connections created or removed). The subscription will expire in 10 seconds.
+ allMessagesWithMessageFilterAndTerminationTime(producerEPR,consumerEPR);
+
+ // Example 7 : a subscription with more than one filter.
+ complexSubscription(producerEPR, consumerEPR);
+ }
+
+ /**
+ * Makes a subscription on all topics / all messages without an expiry date.
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void subscribeAllMessagesWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ null, // Filter, if null that means "all messages"
+ null); // Termination Time : if null the subscription will never expire.
+ }
+
+ /**
+ * Makes a subscription on all topics / all messages with 10 seconds as termination time.
+ * The subscription will expire after 10 seconds.
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void subscribeAllMessagesWithTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ null, // Filter, if null that means "all messages"
+ new Date(System.currentTimeMillis() + 10000)); // Termination Time
+ }
+
+ /**
+ * Makes a subscription on a specifc topic without an expiry date.
+ * Only messages published on the given topic will be delivered to the given consumer.
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void topicSubscriptionWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ TopicFilter filter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME);
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ filter, // Topic Filter
+ null); // Termination Time : if null the subscription will never expire.
+ }
+
+ /**
+ * Makes a subscription on a specifc topic with an expiry date.
+ * Only messages published on the given topic will be delivered to the given consumer.
+ * The subscription will end after 10 seconds
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void topicSubscriptionWithTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ TopicFilter filter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME);
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ filter, // Topic Filter
+ new Date(System.currentTimeMillis() + 10000)); // Termination Time
+ }
+
+ /**
+ * Makes a subscription on all topics with a message filter without an expiry date.
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void allMessagesWithMessageFilterWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ // Applying this filter will result in a subscription that wll be notified only when a "connection"
+ // object is created or removed
+ MessagePatternFilter filter= new MessagePatternFilter(
+ "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath)
+ XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ filter, // Message Filter
+ null); // Termination Time : if null the subscription will never expire.
+ }
+
+ /**
+ * Makes a subscription on all topics with a message filter and an expiry date.
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void allMessagesWithMessageFilterAndTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ // Applying this filter will result in a subscription that wll be notified only when a "connection"
+ // object is created or removed
+ MessagePatternFilter filter= new MessagePatternFilter(
+ "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath)
+ XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ filter, // Message Filter
+ new Date(System.currentTimeMillis() + 10000)); // Termination Time
+ }
+
+ /**
+ * Makes a subscription on a specifc topic with an expiry date.
+ * Only messages published on the given topic will be delivered to the given consumer.
+ * The subscription will end after 10 seconds
+ *
+ * @param producer the producer endpoint reference.
+ * @param consumer the consumer endpoint reference .
+ * @throws SoapFault when the subscription cannot be made.
+ */
+ private void complexSubscription(EndpointReference producer, EndpointReference consumer) throws SoapFault
+ {
+ NotificationProducerClient producerClient = new NotificationProducerClient(producer);
+ producerClient.setTrace(true);
+
+ FilterCollection filter = new FilterCollection();
+
+ TopicFilter topicFilter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME);
+ MessagePatternFilter messageFilter= new MessagePatternFilter(
+ "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath)
+ XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0
+
+ ProducerPropertiesFilter producerFilter = new ProducerPropertiesFilter(
+ "boolean(/*/MgtPubInterval > 100 and /*/MsgTotalEnqueues > 56272)",
+ XPathUtils.NAMESPACE_URI);
+
+ filter.addFilter(topicFilter);
+ filter.addFilter(messageFilter);
+ filter.addFilter(producerFilter);
+
+ producerClient.subscribe(
+ consumer, // Consumer Endpoint reference
+ filter, // Topic Filter
+ new Date(System.currentTimeMillis() + 10000)); // Termination Time
+ }
+
+ @Override
+ void printOutExampleDescription()
+ {
+ System.out.println("This example is demonstrating a WS-Notification scenario ");
+ System.out.println("when (for simplicity) QMan is at the same time consumer ");
+ System.out.println("and producer.");
+ System.out.println();
+ System.out.println("Basically we have (on producer side) two topics : one for");
+ System.out.println("lifecycle events of object instance (objects created & removed) ");
+ System.out.println("and another one for lifecycle of event (events created).");
+ System.out.println();
+ System.out.println("On consumer side there are many options that you can use in");
+ System.out.println("order to made a sunscription :");
+ System.out.println();
+ System.out.println("- you could be an observer of all messages (all topics);");
+ System.out.println("- you could be an observer of one specific topic;");
+ System.out.println("- you could be an observer of all messages that match a condition expressed in XPath;");
+ System.out.println();
+ System.out.println("All those options are provided with or withour a termination time.");
+ System.out.println("A subscription with a termination time will have a predefined expiry");
+ System.out.println("date while if there's no termination the subscription will never expire.");
+ }
+
+ public static void main(String[] args)
+ {
+ new ConsumerAndProducerExample().execute(new String[]{"localhost","8080"});
+ }
+}
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java
new file mode 100644
index 0000000000..413222a79d
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java
@@ -0,0 +1,179 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to get properties from a WS-Resource using one request.
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then a GetMetadataRequest is sent to the
+ * first child.
+ * The result metadata descriptor contains all properties names of the target WS-Resource.
+ * Those names are then used for retrieving the corresponding values.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetMultipleResourcePropertiesExample extends AbstractQManExample
+{
+
+ /**
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then a GetMetadataRequest is sent to the
+ * first child.
+ * The result metadata descriptor contains all properties names of the target WS-Resource.
+ * Those names are then used for retrieving the corresponding values.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) Creates a proxy handler for service invocation.
+ ProxyHandler metadataProxyHandler = createProxyHandler();
+
+ // 5) ..and invokes the GetMetadata on the first member.
+ WsResourceClient wsResourceClient = resources[0];
+ wsResourceClient.setTrace(true);
+
+ // Dialect is RDM for this example
+ String dialect = "http://docs.oasis-open.org/wsrf/rmd-1";
+ Object [] inputParameters = {dialect};
+
+ // RDM is the first element of the returned array.
+ // The first element is a wsx:Metadata containing all resource properties.
+ Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters);
+ Element resourceMetadataDescriptor = metadata[0];
+
+ // 6) using XPath navigates xml in order to get the list of all properties.
+ Element [] properties = XmlUtils.findInSubTree(
+ resourceMetadataDescriptor,
+ new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd"));
+ List<QName> names = new ArrayList<QName>();
+
+ for (Element property : properties)
+ {
+
+ String attributeName = property.getAttribute("name"); // = qman:<Attribute Name>
+
+ // For this example we are only interested on qman namespace related properties...
+ if (attributeName.startsWith("qman"))
+ {
+ String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = <Attribute Name>
+
+ names.add(new QName(
+ "http://amqp.apache.org/qpid/management/qman",
+ attributeNameWithoutPrefix,
+ "qman"));
+ }
+ }
+
+ QName [] qnames = names.toArray(new QName[names.size()]);
+
+ // 7) Send a GetMultipleResourcePropertiesRequest.
+ // We do nothing with the returned value(s) because it / they
+ // has / have already printed out (wsResourceClient.setTrace(true))
+ @SuppressWarnings("unused")
+ Element [] values = wsResourceClient.getMultipleResourceProperties(qnames);
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows how to get properties from a");
+ System.out.println("WS-Resource using one request. ");
+ System.out.println("First of all a request is send to WS-DM in order to get");
+ System.out.println("all registered WS-Resources.");
+ System.out.println("If the returned list is not empty then a GetMetadataRequest");
+ System.out.println("to the first child.");
+ System.out.println("The result metadata descriptor contains all property names of");
+ System.out.println("the target WS-Resource.");
+ System.out.println("Those names are then used for retrieving the corresponding values");
+ System.out.println("using the GetMultipleResourceProperties request.");
+ System.out.println();
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler createProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX));
+ handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)});
+ handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX));
+ handler.setReturnType(Element[].class);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetMultipleResourcePropertiesExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java
new file mode 100644
index 0000000000..f74a44ab57
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+
+/**
+ * An example demonstrating the usage of GetResourcePropertyRequest/Response on
+ * the WS-DM Adapter.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetQManResourceMembersExample extends AbstractQManExample
+{
+ /**
+ * Looks for memebers of QMan group requesting ws-rp:Entry property to
+ * WS-DM Adapter resource service.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference serviceEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(serviceEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Invokes the service.
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ String result = (resources.length != 0)
+ ? ("QMan has at the moment "+resources.length+" registered resources.")
+ : "It seems that there are no managed resource on QMan side...";
+
+ System.out.println("--------------------------------------------------------------------------");
+ System.out.println(result);
+ System.out.println("--------------------------------------------------------------------------");
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows the usage of WS-DM ");
+ System.out.println("GetResourcePropertyRequest / Response on a ");
+ System.out.println("Group service.");
+ System.out.println("The target resource is the WS-DM Adapter itself ");
+ System.out.println("and the requested property is \"wsrf-sg:Entry\".");
+ System.out.println("WS-DM Adapter is a special WS-Resource (is a Group)");
+ System.out.println("that acts as the main entry point for retrieving");
+ System.out.println("all other managed resources.");
+ System.out.println("So clients that want to deal with QMan WS-Resources");
+ System.out.println("must first get resource identifiers sending");
+ System.out.println("a GetResourcePropertyRequest to WS-DM Adapter ");
+ System.out.println("with \"wsrf-sg:Entry\" as target target property.");
+ System.out.println();
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetQManResourceMembersExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java
new file mode 100644
index 0000000000..84befc01e4
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java
@@ -0,0 +1,156 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to get metadata from a WS-Resource.
+ * The service supports different kinds of metadata.
+ * User who wants to receive metadata of a WS-Resource must
+ * send a GetMetadataRequesta specifying the requested dialect.
+ *
+ * Supported metadata that could be requested are
+ *
+ * <ul>
+ * <li>
+ * WSDL : requested using "http://schemas.xmlsoap.org/wsdl/" as dialect..
+ * <li>
+ * <li>
+ * RDM (Resource Metadata Descriptor) : requested using "http://docs.oasis-open.org/wsrf/rmd-1 "as dialect.
+ * </li>
+ * </ul>
+ *
+ * Note that this example focuses on RDM Metadata only; another example is dedicated to WSDL.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetResourceMetadataDescriptorExample extends AbstractQManExample
+{
+
+ /**
+ * First, sends a request to WS-DM Adapter in order to get the list of managed resources.
+ * If the list is not empty, then takes the first member and sends it a GetMetadataRequest
+ * in order to get its RDM.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) Creates a proxy handler for service invocation.
+ ProxyHandler metadataProxyHandler = createProxyHandler();
+
+ // 5) ..and invokes the GetMetadata on the first member.
+ WsResourceClient firstMember = resources[0];
+ firstMember.setTrace(true);
+
+ // Dialect is RDM for this example
+ String dialect = "http://docs.oasis-open.org/wsrf/rmd-1";
+ Object [] inputParameters = {dialect};
+
+ // WSDL is the first element of the returned array. We don't need to print out it here
+ // because at this point it should have been already printed out (line 96 : firstMember.setTrace(true))
+ @SuppressWarnings("unused")
+ Element [] metadata = (Element[]) firstMember.invoke(metadataProxyHandler, inputParameters);
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("The example shows how to get metadata from a");
+ System.out.println("WS-Resource.");
+ System.out.println("A QMan WS-Resource has different kinds of metadata.");
+ System.out.println("(see below)");
+ System.out.println("User who wants to receive metadata of a WS-Resource");
+ System.out.println("must send a GetMetadataRequesta specifying the");
+ System.out.println("associated dialect.");
+ System.out.println("Supported metadata that could be requested are : ");
+ System.out.println();
+ System.out.println("- WSDL : in this case dialect is \"http://schemas.xmlsoap.org/wsdl/\";");
+ System.out.println("- RDM (Resource Metadata Descriptor) : in this case dialect is \"http://docs.oasis-open.org/wsrf/rmd-1 \".");
+ System.out.println();
+ System.out.println("Note that this examples focuses on RDM Metadata only;");
+ System.out.println("another one is dedicated to WSDL.");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler createProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX));
+ handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)});
+ handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX));
+ handler.setReturnType(Element[].class);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetResourceMetadataDescriptorExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java
new file mode 100644
index 0000000000..56ce81358d
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java
@@ -0,0 +1,111 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.example;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to get the whole property document from a WS-Resource.
+ * Resource property document represents a particular composed structural view of
+ * the resource properties of the WS-Resource.
+ * Let's say that It is a way to get all-in-once the state of the WS-Resource.
+ *
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then a GetResourcePropertyDocumentRequest is
+ * sent to the first child.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetResourcePropertyDocumentExample extends AbstractQManExample
+{
+
+ /**
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then a GetResourcePropertyDocumentRequest is
+ * sent to the first child.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) ..and invokes the GetMetadata on the first member.
+ WsResourceClient wsResourceClient = resources[0];
+ wsResourceClient.setTrace(true);
+
+ @SuppressWarnings("unused")
+ Element resourcePropertyDocument = wsResourceClient.getResourcePropertyDocument();
+ }
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows how to get the whole property");
+ System.out.println("document from a WS-Resource.");
+ System.out.println("Resource property document represents a particular ");
+ System.out.println("composed structural view of the resource properties");
+ System.out.println("of the WS-Resource.");
+ System.out.println("First of all a request is send to WS-DM in order to get");
+ System.out.println("all registered WS-Resources.");
+ System.out.println("the target WS-Resource.");
+ System.out.println("If the returned list is not empty then a");
+ System.out.println("GetResourcePropertyDocumentRequest is sent to the first child.");
+ System.out.println();
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetResourcePropertyDocumentExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java
new file mode 100644
index 0000000000..28ed1c7925
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java
@@ -0,0 +1,172 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to get the property value from a WS-Resource.
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then a GetMetadataRequest is sent to the
+ * first child.
+ * The result metadata descriptor contains all properties of the target WS-Resource.
+ * For each of them a GetResourcePropertyRequest is sent in order to get its value.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetResourcePropertyExample extends AbstractQManExample
+{
+
+ /**
+ * First, sends a request to WS-DM Adapter in order to get the list of managed resources.
+ * If the list is not empty, then takes the first member and sends it a GetMetadataRequest
+ * in order to get its WSDL.
+ * After that, for each property contained in ResourceMetadataDescriptorm (RDM) a
+ * GetResourcePropertyRequest is sent in order to get its value.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) Creates a proxy handler for service invocation.
+ ProxyHandler metadataProxyHandler = createProxyHandler();
+
+ // 5) ..and invokes the GetMetadata on the first member.
+ WsResourceClient wsResourceClient = resources[0];
+ wsResourceClient.setTrace(true);
+
+ // Dialect is RDM for this example
+ String dialect = "http://docs.oasis-open.org/wsrf/rmd-1";
+ Object [] inputParameters = {dialect};
+
+ // RDM is the first element of the returned array.
+ // The first element is a wsx:Metadata containing all resource properties.
+ Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters);
+ Element resourceMetadataDescriptor = metadata[0];
+
+ // 6) using XPath navigates xml in order to get the list of all properties.
+ Element [] properties = XmlUtils.findInSubTree(
+ resourceMetadataDescriptor,
+ new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd"));
+
+ for (Element property : properties)
+ {
+
+ String attributeName = property.getAttribute("name"); // = qman:<Attribute Name>
+
+ // For this example we are only interested on qman namespace related properties...
+ if (attributeName.startsWith("qman"))
+ {
+ String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = <Attribute Name>
+
+ // 7) Send a GetResourcePropertyRequest for the given attribute.
+ // We do nothing with the returned value(s) because it / they
+ // has / have already printed out (wsResourceClient.setTrace(true))
+ @SuppressWarnings("unused")
+ Element [] values = wsResourceClient.getResourceProperty(
+ new QName(
+ "http://amqp.apache.org/qpid/management/qman",
+ attributeNameWithoutPrefix,
+ "qman"));
+ }
+ }
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows how to get the property value");
+ System.out.println("from a WS-Resource.");
+ System.out.println("First of all a request is send to WS-DM in order to get");
+ System.out.println("all registered WS-Resources.");
+ System.out.println("If the returned list is not empty then a GetMetadataRequest");
+ System.out.println("to the first child.");
+ System.out.println("The result metadata descriptor contains all properties of");
+ System.out.println("the target WS-Resource.");
+ System.out.println("For each of them a GetResourcePropertyRequest is sent");
+ System.out.println(" in order to get its value.");
+ System.out.println();
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler createProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX));
+ handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)});
+ handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX));
+ handler.setReturnType(Element[].class);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetResourcePropertyExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java
new file mode 100644
index 0000000000..ecda6e8fb1
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java
@@ -0,0 +1,156 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to get metadata from a WS-Resource.
+ * The service supports different kinds of metadata.
+ * User who wants to receive metadata of a WS-Resource must
+ * send a GetMetadataRequesta specifying the requested dialect.
+ *
+ * Supported metadata that could be requested are
+ *
+ * <ul>
+ * <li>
+ * WSDL : requested using "http://schemas.xmlsoap.org/wsdl/" as dialect..
+ * <li>
+ * <li>
+ * RDM (Resource Metadata Descriptor) : requested using "http://docs.oasis-open.org/wsrf/rmd-1 "as dialect.
+ * </li>
+ * </ul>
+ *
+ * Note that this example focuses on WSDL Metadata only; another example is dedicated to RDM.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetWSDLMetadataExample extends AbstractQManExample
+{
+
+ /**
+ * First, sends a request to WS-DM Adapter in order to get the list of managed resources.
+ * If the list is not empty, then takes the first member and sends it a GetMetadataRequest
+ * in order to get its WSDL.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(true);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) Creates a proxy handler for service invocation.
+ ProxyHandler metadataProxyHandler = createProxyHandler();
+
+ // 5) ..and invokes the GetMetadata on the first member.
+ WsResourceClient firstMember = resources[0];
+ firstMember.setTrace(true);
+
+ // Dialect is WSDL for this example
+ String dialect = "http://schemas.xmlsoap.org/wsdl/";
+ Object [] inputParameters = {dialect};
+
+ // WSDL is the first element of the returned array. We don't need to print out it here
+ // because at this point it should have been already printed out (line 96 : firstMember.setTrace(true))
+ @SuppressWarnings("unused")
+ Element [] metadata = (Element[]) firstMember.invoke(metadataProxyHandler, inputParameters);
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("The example shows how to get metadata from a");
+ System.out.println("WS-Resource.");
+ System.out.println("A QMan WS-Resource has different kinds of metadata.");
+ System.out.println("(see below)");
+ System.out.println("User who wants to receive metadata of a WS-Resource");
+ System.out.println("must send a GetMetadataRequesta specifying the");
+ System.out.println("associated dialect.");
+ System.out.println("Supported metadata that could be requested are : ");
+ System.out.println();
+ System.out.println("- WSDL : in this case dialect is \"http://schemas.xmlsoap.org/wsdl/\";");
+ System.out.println("- RDM (Resource Metadata Descriptor) : in this case dialect is \"http://docs.oasis-open.org/wsrf/rmd-1 \".");
+ System.out.println();
+ System.out.println("Note that this examples focuses on WSDL Metadata only;");
+ System.out.println("another one is dedicated to RDM.");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler createProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX));
+ handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)});
+ handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX));
+ handler.setReturnType(Element[].class);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new GetWSDLMetadataExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java b/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java
new file mode 100644
index 0000000000..01a27a16f9
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import java.net.URI;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.notification.remote.NotificationProducerClient;
+import org.apache.muse.ws.notification.remote.SubscriptionClient;
+
+/**
+ * This example is demonstrating a WS-Notification scenario
+ * when (for simplicity) QMan is at the same time consumer
+ * and producer.
+ *
+ * Specifically the example shows how a requestor can create, pause and resume
+ * a subscription.
+ *
+ * @author Andrea Gazzarini
+ *
+ */
+public class PausableSubscriptionExample extends AbstractQManExample
+{
+ @Override
+ void executeExample(String host, int port) throws Exception
+ {
+ // This is QMan...
+ URI producerURI = URI.create("http://"+host+":"+port+"/qman/services/adapter");
+
+ // ...and this is QMan too! Note that it has an hidden consumer capability that is used in
+ // order to run successfully this example...
+ URI consumerURI = URI.create("http://"+host+":"+port+"/qman/services/consumer");
+
+ EndpointReference producerEPR = new EndpointReference(producerURI);
+ EndpointReference consumerEPR = new EndpointReference(consumerURI);
+
+ NotificationProducerClient producerClient = new NotificationProducerClient(producerEPR);
+ producerClient.setTrace(true);
+
+ // 1) Creates a subscription and gets the corresponding reference.
+ SubscriptionClient subscriptionClient = producerClient.subscribe(
+ consumerEPR, // Consumer Endpoint reference
+ null, // Filter, if null that means "all messages"
+ null); // Termination Time : if null the subscription will never expire.
+ subscriptionClient.setTrace(true);
+
+
+ // 2) Pauses the subscription.
+ subscriptionClient.pauseSubscription();
+
+ // 3) Resumes the subscription.
+ subscriptionClient.resumeSubscription();
+ }
+
+ @Override
+ void printOutExampleDescription()
+ {
+ System.out.println("This example is demonstrating a WS-Notification scenario ");
+ System.out.println("when (for simplicity) QMan is at the same time consumer ");
+ System.out.println("and producer.");
+ System.out.println();
+ System.out.println("Specifically the example shows how a requestor can create,");
+ System.out.println("pause and resume a subscription.");
+ }
+
+ public static void main(String[] args)
+ {
+ new PausableSubscriptionExample().execute(new String[]{"romagazzarini","8080"});
+ }
+}
diff --git a/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java b/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java
new file mode 100644
index 0000000000..8aed3101ff
--- /dev/null
+++ b/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java
@@ -0,0 +1,306 @@
+/*
+ *
+ * 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 org.apache.qpid.management.example;
+
+import java.lang.reflect.Array;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.w3c.dom.Element;
+
+/**
+ * This example shows how to change the state of a WS-Resource. That means
+ * a SetResourcePropertyRequest is sent to that WS-Resource.
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then two GetMetadataRequests are sent to the
+ * first child (one for WSDL and one for RDM).
+ * The result metadata descriptors are the used to determine :
+ *
+ * <br> What are names of WS-Resouce properties
+ * <br> Their modifiability (read-only or read-write)
+ * <br> Their type
+ *
+ * So a SetResourcePropertyRequest can be sent in order to change the WS-Resource state.
+ * The example is looking for a property that has one of the following datatype :
+ *
+ * <ul>
+ * <li>String</li>
+ * <li>Long</li>
+ * <li>Integer</li>
+ * <li>Short</li>
+ * <li>Double</li>
+ * <li>Float</li>
+ * </ul>
+ *
+ * After the update / insert request has been sent, a GetResourcePropertiesRequest is made
+ * again in order to see if the state has changed correctly.
+ *
+ * @author Andrea Gazzarini
+ */
+public class SetResourcePropertyExample extends AbstractQManExample
+{
+ /**
+ * First of all a request is send to WS-DM in order to get all registered WS-Resources.
+ * If the returned list is not empty then two GetMetadataRequests are sent to the
+ * first child (one for WSDL and one for RDM).
+ * The result metadata descriptors are the used to determine :
+ *
+ * <br> What are names of WS-Resouce properties
+ * <br> Their modifiability (read-only or read-write)
+ * <br> Their type
+ *
+ * So a SetResourcePropertyRequest can be sent in order to change the WS-Resource state.
+ * The example is looking for a property that has one of the following datatype :
+ *
+ * <ul>
+ * <li>String</li>
+ * <li>Long</li>
+ * <li>Integer</li>
+ * <li>Short</li>
+ * <li>Double</li>
+ * <li>Float</li>
+ * </ul>
+ *
+ * After the update / insert request has been sent, a GetResourcePropertiesRequest is made
+ * again in order to see if the state has changed correctly.
+ *
+ * @param host the host where QMan is running.
+ * @param port the port where QMan is running.
+ * @throws Exception when the example fails (not at application level).
+ */
+ void executeExample(String host, int port) throws Exception
+ {
+ // 1) Creates an endpoint reference of the adapter service...
+ EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port);
+
+ // 2) Creates the Adapter service client...
+ ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference);
+ adapterClient.setTrace(false);
+
+ // 3) Retrieves the all registered members (QMan WS-Resources)
+ WsResourceClient [] resources = adapterClient.getMembers();
+
+ // Sanity check : we cannot proceed if there are no WS-Resources.
+ if (resources.length == 0)
+ {
+ System.out.println("----------------------------WARNING---------------------------");
+ System.out.println("Cannot proceed with the example... it seems");
+ System.out.println("that there are no managed WS-Resources on QMan.");
+ System.out.println("Please check QMan in order to see that it is really");
+ System.out.println("connected with a broker.");
+ System.out.println("-------------------------------------------------------------------");
+ System.exit(0);
+ }
+
+ // 4) Creates a proxy handler for service invocation.
+ ProxyHandler metadataProxyHandler = createProxyHandler();
+
+ // 5) ..and invokes the GetMetadata on the first member.
+ WsResourceClient wsResourceClient = resources[0];
+ wsResourceClient.setTrace(true);
+
+ // Resource Metadata Descriptor
+ String dialect = "http://docs.oasis-open.org/wsrf/rmd-1";
+ Object [] inputParameters = {dialect};
+
+ // RDM is the first element of the returned array.
+ // The first element is a wsx:Metadata containing all resource properties.
+ Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters);
+ Element resourceMetadataDescriptor = metadata[0];
+
+ // 6) Now we need WSDL in order to catch datatypes
+ dialect = "http://schemas.xmlsoap.org/wsdl/";
+ inputParameters = new Object[]{dialect};
+ metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters);
+ Element wsdl = metadata[0];
+
+ //7) Defines sample values used for update property.
+ Map<String, Object> sampleValues = new HashMap<String, Object>();
+ sampleValues.put("xsd:string","This is a string.");
+ sampleValues.put("xsd:integer",new Integer(12345));
+ sampleValues.put("xsd:int",new Integer(54321));
+ sampleValues.put("xsd:long",new Integer(12345));
+ sampleValues.put("xsd:double",new Double(12345.6d));
+ sampleValues.put("xsd:float",new Float(123.4f));
+ sampleValues.put("xsd:short",new Short((short)12));
+
+ // 8) using XPath navigates xml in order to get the list of all properties.
+ Element [] properties = XmlUtils.findInSubTree(
+ resourceMetadataDescriptor,
+ new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd"));
+
+ Element [] wsdlElements = XmlUtils.findInSubTree(
+ wsdl,
+ new QName("http://www.w3.org/2001/XMLSchema","element","xsd"));
+
+ // Did we find at least one writable property?
+ boolean atLeastOnePropertyHasBeenFound = false;
+
+ for (Element property : properties)
+ {
+ // Sanity check : if the property is read-only then proceed with next
+ // property.
+ if (!"read-write".equals(property.getAttribute("modifiability")))
+ {
+ continue;
+ }
+
+ String attributeName = property.getAttribute("name"); // = qman:<Attribute Name>
+
+ // For this example we are only interested on qman namespace related properties...
+ if (attributeName.startsWith("qman"))
+ {
+ String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = <Attribute Name>
+
+ for (Element wsdlElement : wsdlElements)
+ {
+ String name = wsdlElement.getAttribute("name");
+ String type = wsdlElement.getAttribute("type");
+ if ((name != null) && (attributeNameWithoutPrefix.equals(name)) && (type != null))
+ {
+ Object newValue = sampleValues.get(type);
+ if (newValue != null)
+ {
+ atLeastOnePropertyHasBeenFound = true;
+
+ inputParameters = new Object[] {newValue};
+
+ // 9) Makes a GetResourcePropertiesRequest in order to get the current value.
+ QName propertyQName = new QName(
+ "http://amqp.apache.org/qpid/management/qman",
+ name,
+ "qman");
+
+ // The returned value is really an array because property shoudl be a multi-value property.
+ // So in order to get its value we need to extract the first value.
+ Object currentValue = wsResourceClient.getPropertyAsObject(propertyQName,newValue.getClass());
+
+ // 10a) If the property is not set (value is null) then an "Insert" request must be sent.
+ if (currentValue == null || Array.getLength(currentValue) == 0)
+ {
+ wsResourceClient.insertResourceProperty(propertyQName,inputParameters);
+ }
+ // 10b) If the property is not null then an "Update" request must be sent.
+ else
+ {
+ wsResourceClient.updateResourceProperty(propertyQName,inputParameters);
+ }
+
+ // 11) Let's query again the resource using GetResourceProperties in order to ensure the
+ // previous property has been properly updated.
+ currentValue = wsResourceClient.getPropertyAsObject(propertyQName,newValue.getClass());
+
+ String resultMessage = (newValue.equals(Array.get(currentValue, 0)))
+ ? "Resource has been correctly updated."
+ : "Something was wrong : resource seems not to be properly updated.";
+
+ System.out.println("----------------------------------------------------------------------------------");
+ System.out.println(resultMessage);
+ System.out.println("----------------------------------------------------------------------------------");
+
+ // Let's stop...one property is enough for this example :)
+ break;
+ }
+ }
+ }
+ if (!atLeastOnePropertyHasBeenFound)
+ {
+ System.out.println("----------------------------------------------------------------------------------");
+ System.out.println("WARNING : This example wasn't able to run because no writable ");
+ System.out.println("property has been found on the target WS-Resource.");
+ System.out.println("----------------------------------------------------------------------------------");
+ }
+ }
+ }
+ }
+
+ /**
+ * Prints out a description of this example.
+ */
+ void printOutExampleDescription()
+ {
+ System.out.println(" "+getClass().getSimpleName()+" ");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("This example shows how to change the state of a WS-Resource.");
+ System.out.println("That means a SetResourcePropertyRequest is sent to that");
+ System.out.println("WS-Resource.");
+ System.out.println("First of all a request is send to WS-DM in order to get all");
+ System.out.println("registered WS-Resources.");
+ System.out.println("If the returned list is not empty then two GetMetadataRequests");
+ System.out.println("(one for WSDL and one for RDM) are sent to the first child.");
+ System.out.println("The result metadata descriptors are used for determine :");
+ System.out.println();
+ System.out.println("1) WS-Resource property names;");
+ System.out.println("2) Modifiability (read-only, read-write");
+ System.out.println("3) Datatype;");
+ System.out.println("-------------------------------------------------------------------");
+ System.out.println();
+ System.out.println("So a SetResourcePropertyRequest can be sent in order");
+ System.out.println("to change the WS-Resource state.");
+ System.out.println("The example is looking for a property that has one of the");
+ System.out.println("following datatype :");
+ System.out.println();
+ System.out.println("1) String (xsd:string)");
+ System.out.println("2) Long (xsd:long)");
+ System.out.println("3) Integer (xsd:integer or xsd:int)");
+ System.out.println("4) Double (xsd:double)");
+ System.out.println("5) Float (xsd:float)");
+ System.out.println("6) Short (xsd:short)");
+ System.out.println();
+ System.out.println("After the update / insert request has been sent, a ");
+ System.out.println("GetResourcePropertiesRequest is made again");
+ System.out.println("in order to see if the state has changed correctly.");
+ System.out.println();
+ }
+
+ /**
+ * A proxy handler is a module needed in order to make a capability
+ * service invocation.
+ * It contains logic to serialize and deserialize request, response, input and
+ * output parameters during a web service invocation.
+ *
+ * @return a proxy handler.
+ */
+ private ProxyHandler createProxyHandler()
+ {
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX));
+ handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)});
+ handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX));
+ handler.setReturnType(Element[].class);
+ return handler;
+ }
+
+ public static void main(String[] arguments)
+ {
+ new SetResourcePropertyExample().execute(arguments);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/muse.xml b/java/management/client/src/main/java/muse.xml
new file mode 100644
index 0000000000..29a1c02e0c
--- /dev/null
+++ b/java/management/client/src/main/java/muse.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<muse xmlns="http://ws.apache.org/muse/descriptor"
+ xmlns:wsrf-sgw="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://ws.apache.org/muse/descriptor muse-descriptor.xsd">
+ <custom-serializer>
+ <java-serializable-type>java.lang.Object</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer</java-serializer-class>
+ </custom-serializer>
+ <custom-serializer>
+ <java-serializable-type>java.util.Map</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.MapSerializer</java-serializer-class>
+ </custom-serializer>
+ <custom-serializer>
+ <java-serializable-type>java.util.HashMap</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.MapSerializer</java-serializer-class>
+ </custom-serializer>
+ <custom-serializer>
+ <java-serializable-type>java.util.UUID</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.UUIDSerializer</java-serializer-class>
+ </custom-serializer>
+ <custom-serializer>
+ <java-serializable-type>org.apache.qpid.management.wsdm.capabilities.Result</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.InvocationResultSerializer</java-serializer-class>
+ </custom-serializer>
+ <custom-serializer>
+ <java-serializable-type>java.util.Date</java-serializable-type>
+ <java-serializer-class>org.apache.qpid.management.wsdm.muse.serializer.DateSerializer</java-serializer-class>
+ </custom-serializer>
+ <router>
+ <java-router-class>org.apache.muse.ws.resource.impl.WsResourceRouter</java-router-class>
+ <logging>
+ <log-file>log/muse.log</log-file>
+ <log-level>SEVERE</log-level>
+ </logging>
+ <persistence>
+ <java-persistence-class>org.apache.muse.core.routing.RouterFilePersistence</java-persistence-class>
+ <persistence-location>router-entries</persistence-location>
+ </persistence>
+ </router>
+ <resource-type use-router-persistence="true">
+ <context-path>consumer</context-path>
+ <wsdl>
+ <wsdl-file>wsdl/WS-BaseNotification-1_3.wsdl</wsdl-file>
+ <wsdl-port-type xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2">wsntw:NotificationConsumer</wsdl-port-type>
+ </wsdl>
+ <java-id-factory-class>org.apache.qpid.management.wsdm.common.QManResourceIdFactory</java-id-factory-class>
+ <java-resource-class>org.apache.muse.core.SimpleResource</java-resource-class>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer</capability-uri>
+ <java-capability-class>org.apache.muse.ws.notification.impl.SimpleNotificationConsumer</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://amqp.apache.org/qpid/management/qman/consumer</capability-uri>
+ <java-capability-class>org.apache.qpid.management.wsdm.capabilities.ConsumerCapability</java-capability-class>
+ </capability>
+ </resource-type>
+ <resource-type>
+ <context-path>SubscriptionManager</context-path>
+ <wsdl>
+ <wsdl-file>wsdl/WS-BaseNotification-1_3.wsdl</wsdl-file>
+ <wsdl-port-type xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2">wsntw:SubscriptionManager</wsdl-port-type>
+ </wsdl>
+ <java-id-factory-class>org.apache.qpid.management.wsdm.common.QManResourceIdFactory</java-id-factory-class>
+ <java-resource-class>org.apache.muse.ws.resource.impl.SimpleWsResource</java-resource-class>
+ <capability>
+ <capability-uri>http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</capability-uri>
+ <java-capability-class>org.apache.muse.ws.metadata.impl.SimpleMetadataExchange</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Get</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager</capability-uri>
+ <java-capability-class>org.apache.muse.ws.notification.impl.SimpleSubscriptionManager</java-capability-class>
+ <init-param>
+ <param-name>trace-notifications</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.lifetime.impl.SimpleImmediateTermination</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.lifetime.impl.SimpleScheduledTermination</java-capability-class>
+ </capability>
+ <init-param>
+ <param-name>validate-wsrp-schema</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ </resource-type>
+ <resource-type use-router-persistence="true">
+ <context-path>adapter</context-path>
+ <wsdl>
+ <wsdl-file>wsdl/QManAdapter.wsdl</wsdl-file>
+ <wsdl-port-type xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:QManAdapterPortType</wsdl-port-type>
+ </wsdl>
+ <java-id-factory-class>org.apache.qpid.management.wsdm.common.QManResourceIdFactory</java-id-factory-class>
+ <java-resource-class>org.apache.muse.ws.resource.impl.SimpleWsResource</java-resource-class>
+ <capability>
+ <capability-uri >http://amqp.apache.org/qpid/management/qman</capability-uri>
+ <java-capability-class>org.apache.qpid.management.wsdm.capabilities.QManAdapterCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</capability-uri>
+ <java-capability-class>org.apache.muse.ws.metadata.impl.SimpleMetadataExchange</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Get</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Query</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.query.impl.SimpleQueryCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/sgw-2/ServiceGroup</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.sg.impl.SimpleServiceGroup</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsn/bw-2/NotificationProducer</capability-uri>
+ <java-capability-class>org.apache.muse.ws.notification.impl.SimpleNotificationProducer</java-capability-class>
+ </capability>
+ <init-param>
+ <param-name>validate-wsrp-schema</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ </resource-type>
+ <resource-type>
+ <context-path>QManWsResource</context-path>
+ <wsdl>
+ <!-- Note that this is not a complete WSDL. It is just a base template where resource specific capabilities wll be added. -->
+ <wsdl-file>wsdl/QManWsResource.wsdl</wsdl-file>
+ <wsdl-port-type xmlns:qman="http://amqp.apache.org/qpid/management/qman">qman:QManWsResourcePortType</wsdl-port-type>
+ </wsdl>
+ <java-id-factory-class>org.apache.qpid.management.wsdm.common.ObjectNameIdFactory</java-id-factory-class>
+ <java-resource-class>org.apache.qpid.management.wsdm.muse.resources.QManWsResource</java-resource-class>
+ <capability>
+ <capability-uri>http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</capability-uri>
+ <java-capability-class>org.apache.qpid.management.wsdm.capabilities.QManMetadataExchangeCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Get</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Query</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.query.impl.SimpleQueryCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Set</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.set.impl.SimpleSetCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Put</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.set.impl.SimpleSetCapability</java-capability-class>
+ </capability>
+ </resource-type>
+ <resource-type>
+ <context-path>ServiceGroupEntry</context-path>
+ <wsdl>
+ <wsdl-file>/wsdl/WS-ServiceGroupEntry-1_2.wsdl</wsdl-file>
+ <wsdl-port-type>wsrf-sgw:ServiceGroupEntryPortType</wsdl-port-type>
+ </wsdl>
+ <java-id-factory-class>org.apache.qpid.management.wsdm.common.QManResourceIdFactory</java-id-factory-class>
+ <java-resource-class>org.apache.muse.ws.resource.impl.SimpleWsResource</java-resource-class>
+ <capability>
+ <capability-uri>http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata</capability-uri>
+ <java-capability-class>org.apache.muse.ws.metadata.impl.SimpleMetadataExchange</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/rpw-2/Get</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability</java-capability-class>
+ </capability>
+ <capability>
+ <capability-uri>http://docs.oasis-open.org/wsrf/sgw-2/ServiceGroupEntry</capability-uri>
+ <java-capability-class>org.apache.muse.ws.resource.sg.impl.SimpleEntry</java-capability-class>
+ </capability>
+ <init-param>
+ <param-name>validate-wsrp-schema</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ </resource-type>
+</muse>
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Messages.java b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java
new file mode 100644
index 0000000000..4f84128fb3
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java
@@ -0,0 +1,175 @@
+/*
+*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.management;
+
+/**
+ * Enumerative interfaces containing all QMan messages.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface Messages
+{
+ // MESSAGES
+ String EVENT_SEVERITY_ATTRIBUTE_DESCRIPTION = "Severity level for this event.";
+ String EVENT_TIMESTAMP_ATTRIBUTE_DESCRIPTION = "Current timestamp of this event.";
+ String ACTION_NOT_SUPPORTED="Action %s not supported by resource %s.";
+
+ // INFO
+ String QMAN_000001_STARTING_QMAN = "<QMAN-000001> : Starting Q-Man...";
+ String QMAN_000002_READING_CONFIGURATION = "<QMAN-000002> : Reading Q-Man configuration...";
+ String QMAN_000003_CREATING_MANAGEMENT_CLIENTS = "<QMAN-000003> : Creating management client(s)...";
+ String QMAN_000004_MANAGEMENT_CLIENT_CONNECTED = "<QMAN-000004> : Management client for broker %s successfully connected.";
+ String QMAN_000005_TYPE_MAPPING_CONFIGURED = "<QMAN-000005> : Type mapping : code = %s associated to %s (validator class is %s)";
+ String QMAN_000006_ACCESS_MODE_MAPPING_CONFIGURED = "<QMAN-000006> : Access Mode mapping : code = %s associated to %s";
+ String QMAN_000007_MANAGEMENT_HANDLER_MAPPING_CONFIGURED = "<QMAN-000007> : Management Queue Message Handler Mapping : opcode = %s associated with %s";
+ String QMAN_000008_METHOD_REPLY_HANDLER_MAPPING_CONFIGURED = "<QMAN-000008> : Method-Reply Queue Message Handler Mapping : opcode = %s associated with %s";
+ String QMAN_000009_BROKER_DATA_CONFIGURED = "<QMAN-000009> : Broker configuration %s: %s";
+ String QMAN_000010_INCOMING_SCHEMA = "<QMAN-000010> : Incoming schema for %s::%s.%s";
+ String QMAN_000011_SHUTDOWN_INITIATED = "<QMAN-000011> : The shutdown sequence has been initiated for management client connected with broker %s";
+ String QMAN_000012_MANAGEMENT_CLIENT_SHUT_DOWN = "<QMAN-000012> : Management client connected with broker %s shut down successfully.";
+ String QMAN_000013_METHOD_REPLY_CONSUMER_INSTALLED = "<QMAN-000013> : Method-reply queue consumer has been successfully installed and bound on broker %s.";
+ String QMAN_000014_MANAGEMENT_CONSUMER_INSTALLED ="<QMAN-000014> : Management queue consumer has been successfully installed and bound on broker %s.";
+ String QMAN_000015_MANAGEMENT_QUEUE_DECLARED = "<QMAN-000015> : Management queue with name %s has been successfully declared and bound on broker %s.";
+ String QMAN_000016_METHOD_REPLY_QUEUE_DECLARED = "<QMAN-000016> : Method-reply queue with name %s has been successfully declared and bound on broker %s.";
+ String QMAN_000017_CONSUMER_HAS_BEEN_REMOVED = "<QMAN-000017> : Consumer %s has been removed from broker %s.";
+ String QMAN_000018_QUEUE_UNDECLARED = "<QMAN-000018> : Queue %s has been removed from broker %s.";
+ String QMAN_000019_QMAN_STARTED = "<QMAN-000019> : Q-Man open for e-business.";
+ String QMAN_000020_SHUTTING_DOWN_QMAN = "<QMAN-000020> : Shutting down Q-Man...";
+ String QMAN_000021_SHUT_DOWN = "<QMAN-000021> : Q-Man shut down.";
+ String QMAN_000022_NO_BROKER_CONFIGURED = "<QMAN-000022> : Q-Man has no configured broker : in order to connect with a running one use Q-Man Administration interface.";
+ String QMAN_000023_QMAN_REGISTERED_AS_MBEAN = "<QMAN-000023> : Q-Man service is now available on MBeanServer.";
+
+ String QMAN_000026_WSDM_ADAPTER_STARTS = "<QMAN-000026> : Initializing WS-DM Adapter Environment...";
+ String QMAN_000027_WSDM_ADAPTER_STARTED = "<QMAN-000027> : WS-DM Adapter ready for incoming requests.";
+ String QMAN_000028_TEST_MODULE_NOT_FOUND = "<QMAN-000028> : Qpid emulator not found. Test notifications are disabled.";
+ String QMAN_000029_DEFAULT_URI = "<QMAN-000029> : Default URI will be set to %s";
+ String QMAN_000030_RESOURCE_HAS_BEEN_CREATED = "<QMAN-000030> : New resource instance has been created and registered. Resource id is %s";
+ String QMAN_000031_RESOURCE_HAS_BEEN_REMOVED = "<QMAN-000031> : WS-Resource %s has been removed";
+ String QMAN_000032_EVENTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = "<QMAN-000032> : Events lifecycle topic has been created with name %s";
+ String QMAN_000033_OBJECTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = "<QMAN-000033> : Objects lifecycle topic has been created with name %s";
+ String QMAN_000034_UNCLASSIFIED_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = "<QMAN-000034> : Unclassified object types lifecycle topic has been created with name %s";
+ String QMAN_000035_WORK_MANAGER_POOL_SIZE = "<QMAN-000035> : Work Manager thread pool size : %s";
+ String QMAN_000036_WORK_MANAGER_MAX_POOL_SIZE = "<QMAN-000036> : Work Manager thread pool max size : %s";
+ String QMAN_000037_WORK_MANAGER_KEEP_ALIVE_TIME = "<QMAN-000035> : Work Manager keep alive time : %s";
+
+ // DEBUG
+ String QMAN_200001_INCOMING_MESSAGE_HAS_BEEN_RECEIVED = "<QMAN-200001> : New incoming message has been received. Message content is %s";
+ String QMAN_200002_OPCODE_HANDLER_ASSOCIATION = "<QMAN-200002> : \"%s\" opcode is associated to handler %s";
+ String QMAN_200003_MESSAGE_FORWARDING = "<QMAN-200003> : Incoming message with \"%s\" as opcode will be forwarded to %s for processing.";
+ String QMAN_200004_MANAGEMENT_QUEUE_NAME = "<QMAN-200004> : Management queue name : %s";
+ String QMAN_200005_METHOD_REPLY_QUEUE_NAME = "<QMAN-200005> : Method-reply queue name : %s";
+ String QMAN_200006_QPID_CONNECTION_RELEASED = "<QMAN-200006> : Connection %s returned to the pool.";
+ String QMAN_200007_TEST_CONNECTION_ON_RESERVE = "<QMAN-200007> : Test connection on reserve. Is valid? %s";
+ String QMAN_200008_CONNECTION_DESTROYED = "<QMAN-200008> : Connection has been destroyed.";
+ String QMAN_200009_CONNECTION_DESTROY_FAILURE = "<QMAN-200009> : Unable to destroy a connection object.";
+ String QMAN_200010_EVENT_MBEAN_REGISTERED = "<QMAN-200010> : Event instance %s::%s::%s successfully registered with MBean Server with name %s";
+ String QMAN_200011_OBJECT_MBEAN_REGISTERED = "<QMAN-200011> : Object instance %s::%s::%s:%s successfully registered with MBean Server with name %s";
+ String QMAN_200012_OBJECT_MBEAN_UNREGISTERED = "<QMAN-200012> : Object instance %s::%s::%s:%s successfully unregistered from MBean Server. Name was %s";
+ String QMAN_200013_ARGUMENT_VALUE_ENCODED = "<QMAN-200013> : Encoded value %S for argument %s. Type is %s";
+ String QMAN_200014_INCOMING_INSTRUMENTATION_DATA = "<QMAN-200014> : Incoming instrumentation data for %s::%s.%s.%s";
+ String QMAN_200015_INCOMING_CONFIGURATION_DATA = "<QMAN-200015> : Incoming configuration data for %s::%s.%s.%s";
+ String QMAN_200016_PROPERTY_DEFINITION_HAS_BEEN_BUILT = "<QMAN-200016> : Property definition for %s::%s.%s has been built.";
+ String QMAN_200017_STATISTIC_DEFINITION_HAS_BEEN_BUILT = "<QMAN-200017> : Statistic definition for %s::%s.%s has been built.";
+ String QMAN_200018_OPTIONAL_PROPERTIES_INFO = "<QMAN-200018> : Class %s::%s.%s has %s optional properties.";
+ String QMAN_200019_EVENT_ARGUMENT_DEFINITION_HAS_BEEN_BUILT = "<QMAN-200019> : Event argument definition for %s::%s.%s has been built.";
+ String QMAN_200020_ENTITY_DEFINITION_HAS_BEEN_BUILT = "<QMAN-200020> : Entity definition has been built (without schema) for %s::%s.%s";
+ String QMAN_200021_INCOMING_EVENT_DATA = "<QMAN-200021> : Incoming data for event %s::%s.%s";
+ String QMAN_200022_VALIDATOR_INSTALLED = "<QMAN-200022> : Validator %s for type %s successfully installed.";
+ String QMAN_200023_VALIDATOR_NOT_FOUND = "<QMAN-200023> : No validator was found for type %s. The default (empty) validator will be used.";
+ String QMAN_200024_MANAGEMENT_MESSAGE_HAS_BEEN_SENT = "<QMAN-200024> : Message has been sent to management exchange. Message content : %s";
+ String QMAN_200025_SUBSCRIPTION_DECLARED = "<QMAN-200025> : New subscription between queue %s and destination %s has been declared.";
+ String QMAN_200026_SUBSCRIPTION_REMOVED = "<QMAN-200026> : Subscription named %s has been removed from remote broker.";
+ String QMAN_200027_QUEUE_DECLARED = "<QMAN-200027> : New queue with name %s has been declared.";
+ String QMAN_200028_QUEUE_REMOVED= "<QMAN-200028> : New queue with name %s has been undeclared.";
+ String QMAN_200029_BINDING_DECLARED = "<QMAN-200029> : New binding with %s as routing key has been declared between queue %s and exchange %s.";
+ String QMAN_200030_BINDING_REMOVED = "<QMAN-200030> : Binding with %s as routing key has been removed between queue %s and exchange %s.";
+ String QMAN_200031_COMPOUND_MESSAGE_CONTAINS = "<QMAN-200031> : Incoming compound message contains %s message(s).";
+ String QMAN_200032_COMMAND_MESSAGE_ROUTING_KEY = "<QMAN-200032> : Command message routing key : %s";
+ String QMAN_200033_CAPABILITY_CLASS_HAS_BEEN_ADDED = "<QMAN-200033> : Capability has been added to this resource. Class is %s while URI is %s.";
+ String QMAN_200034_RMD_NAME = "<QMAN-200034> : Resource Metadata Descriptor name is %s.";
+ String QMAN_200035_RMD_PATH = "<QMAN-200035> : Resource Metadata Descriptor path is %s.";
+ String QMAN_200036_ADDITIONAL_RMD_PROPERTY = "<QMAN-200036> : Additional RMD property : %s";
+ String QMAN_200037_RMD = "<QMAN-200037> : Resource Metadata Descriptor : %s";
+ String QMAN_200038_WSRP = "<QMAN-200038> : WS Resource Properties fragment : %s";
+ String QMAN_200039_DEBUG_JMX_NOTIFICATION = "<QMAN-200039> : %s";
+ String QMAN_200040_WS_ARTIFACTS_CACHED = "<QMAN-200040> : WS Artifacts has been stored on cache with the following id : %s";
+ String QMAN_200041_INCOMING_OBJECT_NAME_AND_DERIVED_KEY = "<QMAN-200041> : Incoming object name : %s, derived search key : %s";
+ String QMAN_200042_REMOVING_RESOURCE = "<QMAN-200042> : WS-Resource %s is going to be removed";
+ String QMAN_200043_GENERATED_ACCESSOR_METHOD = "<QMAN-200043> : Generated accessor method for %s : %s";
+ String QMAN_200044_GENERATED_METHOD = "<QMAN-200044> : Generated method for %s : %s";
+
+ // WARNING
+ String QMAN_300001_MESSAGE_DISCARDED = "<QMAN-300001> : No handler has been configured for processing messages with \"%s\" as opcode. Message will be discarded.";
+ String QMAN_300002_UNKNOWN_SEQUENCE_NUMBER = "<QMAN-300002> : Unable to deal with incoming message because it contains a unknown sequence number (%s).";
+ String QMAN_300003_BROKER_ALREADY_CONNECTED = "<QMAN-300003> : Unable to enlist given broker connection data : QMan is already connected with broker %s";
+ String QMAN_300004_INVALID_CONFIGURATION_FILE = "<QMAN-300004> : The given configuration file (%s) is not valid (it doesn't exist or cannot be read)";
+ String QMAN_300005_QEMU_INITIALIZATION_FAILURE = "<QMAN-300005> : Unable to initialize QEmu module and therefore emulation won't be enabled...";
+
+ String QMAN_300006_OS_MBEAN_FAILURE = "<QMAN-300006> : Unable to retrieve Operating System properties. No values will be displayed for underlying Operation System.";
+ String QMAN_300007_RUNTIME_MBEAN_FAILURE = "<QMAN-300007> : Unable to retrieve Runtime Environment properties. No values will be displayed.";
+
+ // ERROR
+ String QMAN_100001_BAD_MAGIC_NUMBER_FAILURE = "<QMAN-100001> : Message processing failure : incoming message contains a bad magic number (%s) and therefore will be discaded.";
+ String QMAN_100002_MESSAGE_READ_FAILURE = "<QMAN-100002> : Message I/O failure : unable to read byte message content and therefore it will be discarded.";
+ String QMAN_100003_MESSAGE_PROCESS_FAILURE = "<QMAN-100003> : Message processing failure : unknown exception; see logs for more details.";
+ String QMAN_100004_HANDLER_INITIALIZATION_FAILURE = "<QMAN-100004> : Message handler configured for opcode %s thrown an exception in initialization and therefore will be discarded.";
+ String QMAN_100005_CLASS_SCHEMA_PROCESSING_FAILURE = "<QMAN-100005> : Q-Man was unable to process the schema response message.";
+ String QMAN_100006_EVENT_SCHEMA_PROCESSING_FAILURE = "<QMAN-100006> : Q-Man was unable to process the schema response message.";
+ String QMAN_100007_UNABLE_TO_CONNECT_WITH_BROKER = "<QMAN-100007> : Unable to connect with broker located on %s. This broker will be ignored.";
+
+
+ String QMAN_100010_METHOD_INVOCATION_RESULT_FAILURE = "<QMAN-100010> : an exception occurred while storing the result of a method invocation. Sequence number was %s";
+ String QMAN_100011_UNKNOWN_CLASS_KIND = "<QMAN-100011> : Unknwon class kind : %s).";
+ String QMAN_100012_SCHEMA_MESSAGE_PROCESSING_FAILURE = "<QMAN-100012> : Q-Man was unable to process the schema response message.";
+ String QMAN_100013_MBEAN_REGISTRATION_FAILURE = "<QMAN-100013> : Unable to unregister object instance %s.";
+ String QMAN_100014_ATTRIBUTE_DECODING_FAILURE = "<QMAN-100014> : Unable to decode value for attribute %s";
+ String QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST = "<QMAN-100015> : Unable to send a schema request schema for %s.%s";
+ String QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE = "<QMAN-100016> : Unable to decode value for %s::%s::%s";
+ String QMAN_100017_UNABLE_TO_CONNECT = "<QMAN-100017>: Cannot connect to broker %s on %s";
+ String QMAN_100018_UNABLE_TO_STARTUP_CORRECTLY = "<QMAN-100018> : Q-Man was unable to startup correctly : see logs for further details.";
+ String QMAN_100019_REQ_OR_RES_MALFORMED = "<QMAN-100019> : Unexpected exception occurred on WSDM adapter layer : probably request or response was malformed.";
+ String QMAN_100020_ACTION_NOT_SUPPORTED = "<QMAN-100020> : "+ACTION_NOT_SUPPORTED;
+ String QMAN_100021_RMD_BUID_FAILURE = "<QMAN-100021> : Unable to build RDM for resource %s.";
+
+ String QMAN_100023_BUILD_WS_ARTIFACTS_FAILURE = "<QMAN-100023> : Unable to build WS artifacts.";
+ String QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE = "<QMAN-100024> : Unable to instantiate generated capability class for %s.";
+ String QMAN_100025_WSRF_FAILURE = "<QMAN-100025> : Resource manager raised an exception while creating capability for %s.";
+ String QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE = "<QMAN-100026> : Exception occurred while replacing the placeholder soap address with resource actual location.";
+ String QMAN_100027_RESOURCE_SHUTDOWN_FAILURE = "<QMAN-100027> : Shutdown failure while destroying resource %s.";
+ String QMAN_100029_MALFORMED_RESOURCE_URI_FAILURE = "<QMAN-100029> : Unable to define URI for QMan resources using \"%s\". It violates RFC 2396";
+ String QMAN_100030_JMX_CORE_STARTUP_FAILURE = "<QMAN-100030> : QMan JMX core Unexpected failure while starting up.";
+ String QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED = "<QMAN-100031> : Bad request has been received on this WS-Resource : Initialization is not possible because the resource has already been initialized.";
+ String QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED = "<QMAN-100032> : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource hasn't yet been initialized.";
+ String QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN = "<QMAN-100033> : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource has already been shutdown.";
+ String QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND = "<QMAN-100034> : Unable to get via XPath the schema section in WSDL.";
+ String QMAN_100035_RESOURCE_CAPABILITY_INVOCATION_FAILURE = "<QMAN-100035> : Resource thrown a failure while invoking a capability operation.";
+ String QMAN_100036_TOPIC_DECLARATION_FAILURE = "<QMAN-100036> : WS-DM Adapter was unable to declare events and / or objects lifecycle topic(s). As conseguence of that, QMan won't be able to correctly emit lifecycle notifications.";
+
+ // NEW
+ String QMAN_100035_GET_ATTRIBUTE_FAILURE = "<QMAN-100035> : Get Attribute invocation failure for attribute %s, resource %s.";
+ String QMAN_100036_SET_ATTRIBUTE_FAILURE = "<QMAN-100036> : Set Attribute invocation failure for attribute %s, resource %s.";
+ String QMAN_100037_INVOKE_OPERATION_FAILURE = "<QMAN-100037> : Operation Invocation failure for operation.";
+ String QMAN_100038_UNABLE_TO_SEND_WS_NOTIFICATION = "<QMAN-100038> : Unable to send notification.";
+ String QMAN_100039_UNABLE_TO_CONFIGURE_PROPERLY_WORKER_MANAGER = "<QMAN-100039> : Unable to properly configure WorkManager. A malformed property (NaN) was given as input parameter.";
+ String QMAN_100040_UNABLE_TO_LOCATE_WSRP_PROPERTIES = "<QMAN-100040> : Unable to evaluate the WSRP XPath expression on resource WSDL.";
+
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Names.java b/java/management/client/src/main/java/org/apache/qpid/management/Names.java
new file mode 100644
index 0000000000..b60867d9ff
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/Names.java
@@ -0,0 +1,216 @@
+/*
+ *
+ * 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 org.apache.qpid.management;
+
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+/**
+ * Enumeration of literal strings to avoid code duplication.
+ */
+public abstract class Names
+{
+ public static final String MANAGEMENT_EXCHANGE = "qpid.management";
+ public static final String MANAGEMENT_ROUTING_KEY = "console.#";
+
+ public static final String MANAGEMENT_QUEUE_PREFIX = "management.";
+ public static final String METHOD_REPLY_QUEUE_PREFIX = "reply.";
+
+ public static final String AMQ_DIRECT_QUEUE = "amq.direct";
+ public static final String AGENT_ROUTING_KEY_PREFIX = "agent.";
+ public static final String AGENT_ROUTING_KEY = AGENT_ROUTING_KEY_PREFIX+"1.0";
+
+ public static final String APPLICATION_NAME ="Q-Man";
+
+ // Attributes
+ public static final String PACKAGE = "package";
+ public static final String CLASS = "class";
+ public static final String EVENT = "event";
+ public static final String OBJECT_ID="objectId";
+ public static final String BROKER_ID = "brokerId";
+ public static final String DOMAIN_NAME = "Q-MAN";
+
+ public static final String ARG_COUNT_PARAM_NAME = "argCount";
+ public static final String DEFAULT_PARAM_NAME ="default";
+
+ public static final String NUMBER_VALIDATOR = "org.apache.qpid.management.domain.model.QpidProperty$NumberValidator";
+ public static final String STRING_VALIDATOR = "org.apache.qpid.management.domain.model.QpidProperty$StringValidator";
+
+ public static final String QMAN_CONFIG_OPTION_NAME = "qman-config";
+
+ public static final String ADD_BROKER_OPERATION_NAME = "addBroker";
+
+ public static final String NOT_AVAILABLE = "N.A.";
+
+ public static final ObjectName QPID_EMULATOR_OBJECT_NAME;
+ static
+ {
+ try
+ {
+ QPID_EMULATOR_OBJECT_NAME = new ObjectName(
+ new StringBuilder()
+ .append(DOMAIN_NAME)
+ .append(':')
+ .append("Name=Qpid,Type=Emulator")
+ .toString());
+ } catch(Exception exception)
+ {
+ throw new ExceptionInInitializerError(exception);
+ }
+ }
+
+ public static final ObjectName QMAN_OBJECT_NAME;
+ static
+ {
+ try
+ {
+ QMAN_OBJECT_NAME = new ObjectName(
+ new StringBuilder()
+ .append(DOMAIN_NAME)
+ .append(':')
+ .append("Name=QMan,Type=Service")
+ .toString());
+ } catch(Exception exception)
+ {
+ throw new ExceptionInInitializerError(exception);
+ }
+ }
+
+ // WSDM Stuff
+ public static final String NAMESPACE_URI = "http://amqp.apache.org/qpid/management/qman";
+ public final static String PREFIX = "qman";
+
+ public static final String ADDRESSING_URI = "http://amqp.apache.org/qpid/management/qman/addressing";
+ public static final String ADDRESSING_PREFIX = "qman-wsa";
+
+ public static final QName RESOURCE_ID_QNAME = new QName(
+ ADDRESSING_URI,
+ "ResourceId",
+ ADDRESSING_PREFIX);
+
+ public static final QName RES_ID_QNAME = new QName(
+ NAMESPACE_URI,
+ "ResourceId",
+ PREFIX);
+
+ public static final QName RESOURCE_QNAME = new QName(
+ NAMESPACE_URI,
+ "Resource",
+ PREFIX);
+
+ public static final QName LIFECYCLE_EVENT_QNAME = new QName(
+ NAMESPACE_URI,
+ "LifeCycleEvent",
+ PREFIX);
+
+ public static final QName PACKAGE_NAME_QNAME = new QName(
+ NAMESPACE_URI,
+ "PackageName",
+ PREFIX);
+
+ public static final QName ENTITY_NAME_QNAME = new QName(
+ NAMESPACE_URI,
+ "Name",
+ PREFIX);
+
+ public static final String TIMEMILLIS_ATTRIBUTE_NAME="TimeMillis";
+
+ public final static String QMAN_RESOURCE_NAME = "QManWsResource";
+
+ public final static String VALIDATE_WSRP_PARAM = "validate-wsrp-schema";
+
+ public static final String WEB_APP_CLASSES_FOLDER = "/WEB-INF/classes";
+
+
+ public final static QName QMAN_RESOURCE_PORT_TYPE_NAME = new QName(
+ Names.NAMESPACE_URI,
+ "QManWsResourcePortType",
+ Names.PREFIX);
+
+ public final static QName QMAN_STATUS_TEXT_NAME = new QName(
+ Names.NAMESPACE_URI,
+ "Message",
+ Names.PREFIX);
+
+ public final static QName QMAN_STATUS_CODE_NAME = new QName(
+ Names.NAMESPACE_URI,
+ "ReturnCode",
+ Names.PREFIX);
+
+ public final static QName QMAN_STATUS_ATTRIBUTE_NAME= new QName(
+ Names.NAMESPACE_URI,
+ "AttributeName",
+ Names.PREFIX);
+
+ public final static QName OBJECTS_LIFECYLE_TOPIC_NAME= new QName(
+ Names.NAMESPACE_URI,
+ "ObjectsLifeCycleTopic",
+ Names.PREFIX);
+
+ public final static QName EVENTS_LIFECYLE_TOPIC_NAME= new QName(
+ Names.NAMESPACE_URI,
+ "EventsLifeCycleTopic",
+ Names.PREFIX);
+
+ public final static QName HOST_QNAME = new QName(
+ Names.NAMESPACE_URI,
+ "host",
+ Names.PREFIX);
+
+ public final static QName PORT_QNAME = new QName(
+ Names.NAMESPACE_URI,
+ "port",
+ Names.PREFIX);
+
+ public final static QName USERNAME_QNAME= new QName(
+ Names.NAMESPACE_URI,
+ "username",
+ Names.PREFIX);
+
+ public final static QName VIRTUAL_HOST_QNAME= new QName(
+ Names.NAMESPACE_URI,
+ "virtualHost",
+ Names.PREFIX);
+
+ public final static QName UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME= new QName(
+ Names.NAMESPACE_URI,
+ "UnclassifiedLifeCycleTopic",
+ Names.PREFIX);
+
+
+ public final static String NAME_ATTRIBUTE = "name";
+ public final static String MODIFIABILITY = "modifiability";
+ public final static String READ_WRITE = "read-write";
+ public final static String READ_ONLY = "read-only";
+ public final static String MUTABILITY = "mutability";
+ public final static String MUTABLE = "mutable";
+
+ public final static String ENTRY = "entry";
+ public final static String KEY = "key";
+ public final static String VALUE = "value";
+ public final static String TYPE = "type";
+ public final static String XSI_TYPE = "xsi:"+TYPE;
+
+ public final static String ADAPTER_HOST_PROPERTY_NAME = "qman.host";
+ public final static String ADAPTER_PORT_PROPERTY_NAME = "qman.port";
+
+
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java b/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java
new file mode 100644
index 0000000000..c1b1ceb5b4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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 org.apache.qpid.management;
+
+/**
+ * Protocol defined constants.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface Protocol
+{
+ String MAGIC_NUMBER = "AM2";
+
+ char SCHEMA_REQUEST_OPCODE = 'S';
+ char SCHEMA_RESPONSE_OPCODE = Character.toLowerCase(SCHEMA_REQUEST_OPCODE);
+
+ char OPERATION_INVOCATION_REQUEST_OPCODE = 'M';
+ char OPERATION_INVOCATION_RESPONSE_OPCODE = Character.toLowerCase(OPERATION_INVOCATION_REQUEST_OPCODE);
+
+ char INSTRUMENTATION_CONTENT_RESPONSE_OPCODE = 'i';
+ char CONFIGURATION_CONTENT_RESPONSE_OPCDE = 'c';
+ char EVENT_CONTENT_RESPONSE_OPCDE = 'e';
+ char INSTR_AND_CONFIG_CONTENT_RESPONSE_OPCODE = 'g';
+
+ char HEARTBEAT_INDICATION_RESPONSE_OPCODE = 'h';
+
+ int CLASS = 1;
+ int EVENT = 2;
+
+ String DEFAULT_QMAN_HOSTNAME = "localhost";
+ int DEFAULT_QMAN_PORT_NUMBER = 8080;
+
+ String DEFAULT_ENDPOINT_URI = "http://localhost:8080/qman/services/adapter";
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java
new file mode 100644
index 0000000000..f23bf9d25e
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java
@@ -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 org.apache.qpid.management.configuration;
+
+/**
+ * Thrown when an attempt is made in order to connect QMan with an already connected broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokerAlreadyConnectedException extends Exception {
+
+ private static final long serialVersionUID = -5082431738056504669L;
+
+ private BrokerConnectionData _connectionData;
+
+ /**
+ * Builds a new exception with the given data.
+ *
+ * @param connectionData the broker connection data.
+ */
+ public BrokerAlreadyConnectedException(BrokerConnectionData connectionData) {
+ this._connectionData = connectionData;
+ }
+
+ /**
+ * Returns the connection data of the connected broker.
+ *
+ * @return the connection data of the connected broker.
+ */
+ public BrokerConnectionData getBrokerConnectionData()
+ {
+ return _connectionData;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java
new file mode 100644
index 0000000000..a64659b17c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java
@@ -0,0 +1,280 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+/**
+ * Value object which is holding connection data for a specific broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokerConnectionData
+{
+ private String _host;
+ private int _port;
+ private String _virtualHost;
+ private String _username;
+ private String _password;
+ private int _maxPoolCapacity;
+ private int _initialPoolCapacity;
+ private long _maxWaitTimeout;
+
+ /**
+ * Builds a connection data with the given parameters.
+ *
+ * @param host the hostname where the broker is running.
+ * @param port the port where the broker is running.
+ * @param username the username for connecting with the broker.
+ * @param password the password for connecting with the broker.
+ * @param virtualHost the virtual host.
+ * @param initialPoolCapacity the number of connections that must be immediately opened.
+ * @param maxPoolCapacity the maximum number of opened connection.
+ * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection.
+ */
+ public BrokerConnectionData(
+ String host,
+ int port,
+ String virtualHost,
+ String username,
+ String password,
+ int initialPoolCapacity,
+ int maxPoolCapacity,
+ long waitTimeout) {
+
+ this._host = host;
+ this._port = port;
+ this._virtualHost = virtualHost;
+ this._username = username;
+ this._password = password;
+ _maxPoolCapacity = maxPoolCapacity;
+ _initialPoolCapacity = initialPoolCapacity;
+ _maxWaitTimeout = waitTimeout;
+ }
+
+ /**
+ * Builds a new empty broker connection data object.
+ */
+ BrokerConnectionData()
+ {
+ }
+
+ /**
+ * Sets the value of host property for this connection data.
+ *
+ * @param host the host name.
+ */
+ void setHost (String host)
+ {
+ this._host = host;
+ }
+
+ /**
+ * Sets the value of port property for this connection data.
+ *
+ * @param port the port.
+ */
+ void setPort (String port)
+ {
+ this._port = Integer.parseInt(port);
+ }
+
+ /**
+ * Sets the value of virtual host property for this connection data.
+ *
+ * @param virtualHost the virtual host.
+ */
+ void setVirtualHost (String virtualHost)
+ {
+ this._virtualHost = virtualHost;
+ }
+
+ /**
+ * Sets the value of username property for this connection data.
+ *
+ * @param username the username.
+ */
+ void setUsername(String username)
+ {
+ this._username = username;
+ }
+
+ /**
+ * Sets the value of password property for this connection data.
+ *
+ * @param password the password.
+ */
+ void setPassword(String password)
+ {
+ this._password = password;
+ }
+
+ /**
+ * Returns the value of the host property.
+ *
+ * @return the value of the host property.
+ */
+ public String getHost ()
+ {
+ return _host;
+ }
+
+ /**
+ * Returns the value of the port property.
+ *
+ * @return the value of the port property.
+ */
+ public int getPort ()
+ {
+ return _port;
+ }
+
+ /**
+ * Returns the value of the virtual host property.
+ *
+ * @return the value of the virtual host property.
+ */
+ public String getVirtualHost ()
+ {
+ return _virtualHost;
+ }
+
+ /**
+ * Returns the value of the username property.
+ *
+ * @return the value of the username property.
+ */
+ public String getUsername ()
+ {
+ return _username;
+ }
+
+ /**
+ * Returns the value of the password property.
+ *
+ * @return the value of the password property.
+ */
+ public String getPassword ()
+ {
+ return _password;
+ }
+
+ // sofia:5663@pippo/sung1
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder()
+ .append(_host)
+ .append(':')
+ .append(_port)
+ .append('@')
+ .append(_virtualHost)
+ .toString();
+ }
+
+ /**
+ * Sets the max number of allowed connections that can be opened.
+ *
+ * @param value the max number of allowed connections that can be opened.
+ * @throws NumberFormatException if the given value is not a valid integer.
+ */
+ public void setMaxPoolCapacity (String value)
+ {
+ _maxPoolCapacity = Integer.parseInt(value);
+ }
+
+ /**
+ * Sets the max wait timeout for retrieving an available connections from the pool.
+ *
+ * @param value the max wait timeout for retrieving an available connections from the pool..
+ * @throws NumberFormatException if the given value is not a valid long.
+ */
+ public void setMaxWaitTimeout (String value)
+ {
+ this._maxWaitTimeout = Long.parseLong(value);
+ }
+
+ /**
+ * Returns the max number of allowed connections that can be opened.
+ *
+ * @return the max number of allowed connections that can be opened.
+ */
+ public int getMaxPoolCapacity ()
+ {
+ return _maxPoolCapacity;
+ }
+
+ /**
+ * Returns the max wait timeout for retrieving an available connections from the pool.
+ *
+ * @return the max wait timeout for retrieving an available connections from the pool.
+ */
+ public long getMaxWaitTimeout ()
+ {
+ return _maxWaitTimeout;
+ }
+
+ /**
+ * Sets the initial connection pool capacity.
+ *
+ * @param capacity the initial connection pool capacity.
+ */
+ public void setInitialPoolCapacity (String capacity)
+ {
+ _initialPoolCapacity = Integer.parseInt(capacity);
+ }
+
+ /**
+ * Returns the initial connection pool capacity.
+ *
+ * @return the initial connection pool capacity.
+ */
+ public int getInitialPoolCapacity ()
+ {
+ return _initialPoolCapacity;
+ }
+
+ @Override
+ public boolean equals(Object object)
+ {
+ if(object instanceof BrokerConnectionData)
+ {
+ try
+ {
+ BrokerConnectionData connectionData = (BrokerConnectionData) object;
+ return (_host.equals(connectionData._host) )
+ && (_port == connectionData._port)
+ && (_virtualHost.equals(connectionData._virtualHost));
+ }
+ catch (Exception exception)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return _host.hashCode()+_port+_virtualHost.hashCode();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java
new file mode 100644
index 0000000000..39981dc7cb
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.UUID;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Parser used for building broker connection data settings.
+ * The corresponding section on the configuration file is :
+ *
+ <broker>
+ <host>192.168.148.131</host>
+ <port>5672</port>
+ <virtual-host>test</virtual-host>
+ <user>guest</user>
+ <password>guest</password>
+ <max-pool-capacity>4</max-pool-capacity>
+ <initial-pool-capacity>4</initial-pool-capacity>
+ <max-wait-timeout>-1</max-wait-timeout>
+ </broker>
+ *
+ * @author Andrea Gazzarini
+ */
+class BrokerConnectionDataParser implements IParser
+{
+ private final static Logger LOGGER = Logger.get(Configuration.class);
+ private BrokerConnectionData _connectionData = new BrokerConnectionData();
+ private String _currentValue;
+
+ /**
+ * Callback : the given value is the text content of the current node.
+ */
+ public void setCurrrentAttributeValue (String value)
+ {
+ this._currentValue = value;
+ }
+
+ /**
+ * Callback: each time the end of an element is reached this method is called.
+ * It's here that the built mapping is injected into the configuration.
+ * <broker>
+ <host>192.168.61.130</host>
+ <port>5673</port>
+ <virtual-host>test</virtual-host>
+ <user>andrea</user>
+ <password>andrea</password>
+ </broker>
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case HOST:
+ {
+ _connectionData.setHost(_currentValue);
+ break;
+ }
+ case PORT :
+ {
+ _connectionData.setPort(_currentValue);
+ break;
+ }
+ case VIRTUAL_HOST:
+ {
+ _connectionData.setVirtualHost(_currentValue);
+ break;
+ }
+ case USER :
+ {
+ _connectionData.setUsername(_currentValue);
+ break;
+ }
+ case MAX_POOL_CAPACITY:
+ {
+ _connectionData.setMaxPoolCapacity (_currentValue);
+ break;
+ }
+ case INITIAL_POOL_CAPACITY:
+ {
+ _connectionData.setInitialPoolCapacity(_currentValue);
+ break;
+ }
+ case MAX_WAIT_TIMEOUT:
+ {
+ _connectionData.setMaxWaitTimeout(_currentValue);
+ break;
+ }
+ case PASSWORD:
+ {
+ _connectionData.setPassword(_currentValue);
+ break;
+ }
+ case BROKER:
+ {
+ try
+ {
+ Configuration.getInstance().addBrokerConnectionData(getUUId(),_connectionData);
+ } catch(Exception exception)
+ {
+ LOGGER.error(exception, Messages.QMAN_100007_UNABLE_TO_CONNECT_WITH_BROKER, _connectionData);
+ }
+ _connectionData = new BrokerConnectionData();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Gets an uuid in order to associate current connection data with a broker.
+ * @return
+ */
+ UUID getUUId(){
+ return UUID.randomUUID();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java
new file mode 100644
index 0000000000..9294cf740e
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java
@@ -0,0 +1,42 @@
+/*
+*
+ * 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 org.apache.qpid.management.configuration;
+
+/**
+ * Thrown when a connection to a broker cannot be estabilished.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokerConnectionException extends Exception
+{
+ private static final long serialVersionUID = 8170112238862494025L;
+
+ /**
+ * Builds a new exception with the given cause.
+ *
+ * @param cause the exception cause.
+ */
+ BrokerConnectionException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java
new file mode 100644
index 0000000000..ab90ec294b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java
@@ -0,0 +1,485 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+import org.apache.qpid.management.domain.model.AccessMode;
+import org.apache.qpid.management.domain.model.type.AbsTime;
+import org.apache.qpid.management.domain.model.type.DeltaTime;
+import org.apache.qpid.management.domain.model.type.ObjectReference;
+import org.apache.qpid.management.domain.model.type.Str16;
+import org.apache.qpid.management.domain.model.type.Str8;
+import org.apache.qpid.management.domain.model.type.Type;
+import org.apache.qpid.management.domain.model.type.Uint16;
+import org.apache.qpid.management.domain.model.type.Uint32;
+import org.apache.qpid.management.domain.model.type.Uint64;
+import org.apache.qpid.management.domain.model.type.Uint8;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.ReplyTo;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid Management bridge configuration.
+ * Basically iy is a singleton that is holding all the configurtion data loaded at startup.
+ */
+public final class Configuration
+{
+ private final static Logger LOGGER = Logger.get(Configuration.class);
+ private static Configuration INSTANCE = new Configuration();
+
+ // Work Manager default settings
+ private int _poolSize = 5;
+ private int _maxPoolSize = 15;
+ private long _keepAliveTime = 5000;
+
+ Map<Integer, Type> _typeMappings = new HashMap<Integer,Type>();
+ Map<Integer,AccessMode> _accessModes = new HashMap<Integer, AccessMode>();
+ Map<Type,String> _validators = new HashMap<Type, String>();
+
+ Map<UUID,BrokerConnectionData> _brokerConnectionInfos = new HashMap<UUID, BrokerConnectionData>();
+
+ Map<Character, IMessageHandler> _managementQueueHandlers = new HashMap<Character, IMessageHandler>();
+ Map<Character, IMessageHandler> _methodReplyQueueHandlers = new HashMap<Character, IMessageHandler>();
+
+ private String _managementQueueName;
+ private String _methodReplyQueueName;
+
+ private Header _headerForCommandMessages;
+ private DeliveryProperties _deliveryProperties = new DeliveryProperties();
+ private MessageProperties _messageProperties = new MessageProperties();
+
+ // Private constructor.
+ private Configuration()
+ {
+ defineQueueNames();
+
+ createHeaderForCommandMessages();
+
+ addAccessModeMappings();
+
+ addTypeMappings();
+ }
+
+
+ /**
+ * Returns the singleton instance.
+ *
+ * @return the singleton instance.
+ */
+ public static Configuration getInstance ()
+ {
+ return INSTANCE;
+ }
+
+ /**
+ * Returns true if this configuration has at least
+ * one broker configured.
+ *
+ * @return true if this configuration has at least one
+ * broker configured.
+ */
+ public boolean hasOneOrMoreBrokersDefined()
+ {
+ return !_brokerConnectionInfos.isEmpty();
+ }
+
+ /**
+ * Returns the type associated to the given code.
+ *
+ * @param code the code used as search criteria.
+ * @return the type associated to the given code.
+ * @throws UnknownTypeCodeException when the given code is not associated to any type.
+ */
+ public Type getType(int code) throws UnknownTypeCodeException
+ {
+ Type result = _typeMappings.get(code);
+ if (result == null)
+ {
+ throw new UnknownTypeCodeException(code);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the access mode associated to the given code.
+ *
+ * @param code the code used as search criteria.
+ * @return the access mode associated to the given code.
+ * @throws UnknownAccessCodeException when the given code is not associated to any access mode.
+ */
+ public AccessMode getAccessMode(int code) throws UnknownAccessCodeException
+ {
+ AccessMode result = _accessModes.get(code);
+ if (result == null)
+ {
+ throw new UnknownAccessCodeException(code);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the validator class name associated to the given type.
+ *
+ * @param type the type.
+ * @return the validator class name associated to the given type.
+ */
+ public String getValidatorClassName (Type type)
+ {
+ return _validators.get(type);
+ }
+
+ /**
+ * Gets from this configuration the list of known broker (I mean, only their connection data).
+ *
+ * @return the list of known broker
+ */
+ public Set<Entry<UUID, BrokerConnectionData>> getConnectionInfos(){
+ return _brokerConnectionInfos.entrySet();
+ }
+
+ /**
+ * Gets from this configuration the connection data of the broker associated with the given id.
+ *
+ * @param brokerId the broker identifier.
+ * @return the connection data of the broker associated with the given id.
+ * @throws UnknownBrokerException when the given id is not associated with any broker.
+ */
+ public BrokerConnectionData getBrokerConnectionData (UUID brokerId) throws UnknownBrokerException
+ {
+ BrokerConnectionData connectionData = _brokerConnectionInfos.get(brokerId);
+ if (connectionData == null)
+ {
+ throw new UnknownBrokerException(brokerId);
+ }
+ return _brokerConnectionInfos.get(brokerId);
+ }
+
+ /**
+ * Returns the name of the management queue.
+ *
+ * @return the name of the management queue.
+ */
+ public String getManagementQueueName() {
+ return _managementQueueName;
+ }
+
+ /**
+ * Returns the name of the method-reply queue.
+ *
+ * @return the name of the method-reply queue.
+ */
+ public String getMethodReplyQueueName() {
+ return _methodReplyQueueName;
+ }
+
+ /**
+ * Returns a map containing all the configured management message handlers.
+ * A management message handler it is a basically a processor for a management queue incoming message associated
+ * with a specific opcode.
+ *
+ * @return a map containing all the configured management message handlers.
+ */
+ public Map<Character, IMessageHandler> getManagementQueueHandlers()
+ {
+ return _managementQueueHandlers;
+ }
+
+ /**
+ * Returns a map containing all the configured method-reply message handlers.
+ * A management message handler it is a basically a processor for a method-reply queue incoming message associated
+ * with a specific opcode.
+ *
+ * @return a map containing all the configured method-reply message handlers.
+ */
+ public Map<Character, IMessageHandler> getMethodReplyQueueHandlers()
+ {
+ return _methodReplyQueueHandlers;
+ }
+
+ /**
+ * Returns the message header used for sending command message on management queue.
+ *
+ * @return the message header used for sending command message on management queue.
+ */
+ public Header getCommandMessageHeader ()
+ {
+ return _headerForCommandMessages;
+ }
+
+ /**
+ * Returns the command message properties.
+ *
+ * @return the command message properties.
+ */
+ public MessageProperties getCommandMessageProperties ()
+ {
+ return _messageProperties;
+ }
+
+ /**
+ * Returns the command message delivery properties.
+ *
+ * @return the command message delivery properties.
+ */
+ public DeliveryProperties getCommandDeliveryProperties ()
+ {
+ return _deliveryProperties;
+ }
+
+ /**
+ * Adds a new type mapping to this configuration.
+ *
+ * @param code the code that will be associated with the declared type.
+ * @param type the type.
+ * @param vailidatorClassName the FQN of the validator class that will be
+ * associated with the given type.
+ */
+ void addTypeMapping(int code, Type type, String validatorClassName) {
+ _typeMappings.put(code, type);
+ _validators.put(type, validatorClassName);
+
+ LOGGER.info(
+ Messages.QMAN_000005_TYPE_MAPPING_CONFIGURED,
+ code,
+ type,
+ validatorClassName);
+ }
+
+
+ /**
+ * Adds a new type mapping to this configuration.
+ *
+ * @param code the code that will be associated with the declared type.
+ * @param type the type.
+ */
+ void addTypeMapping(int code, Type type) {
+ _typeMappings.put(code, type);
+
+ LOGGER.info(
+ Messages.QMAN_000005_TYPE_MAPPING_CONFIGURED,
+ code,
+ type,
+ "not configured for this type.");
+ }
+
+ /**
+ * Adds a new access mode mapping to this configuration.
+ *
+ * @param code the code that will be associated with the access mode,
+ * @param accessMode the accessMode.
+ */
+ void addAccessModeMapping(int code, AccessMode accessMode){
+ _accessModes.put(code, accessMode);
+
+ LOGGER.info(Messages.QMAN_000006_ACCESS_MODE_MAPPING_CONFIGURED, code,accessMode);
+ }
+
+ /**
+ * Adds a new management message handler to this configuration.
+ * The incoming mapping object will contains an opcode and the class (as a string) of the message handler that will be used
+ * for processing incoming messages with that opcode.
+ *
+ * @param mapping the message handler mapping.
+ */
+ void addManagementMessageHandlerMapping (MessageHandlerMapping mapping)
+ {
+ Character opcode = mapping.getOpcode();
+ IMessageHandler handler = mapping.getMessageHandler();
+ _managementQueueHandlers.put(opcode, handler);
+
+ LOGGER.info(Messages.QMAN_000007_MANAGEMENT_HANDLER_MAPPING_CONFIGURED, opcode,handler.getClass().getName());
+ }
+
+ /**
+ * Adds a new method-reply message handler to this configuration.
+ * The incoming mapping object will contains an opcode and the class (as a string) of the message handler that will be used
+ * for processing incoming messages with that opcode.
+ *
+ * @param mapping the message handler mapping.
+ */
+ void addMethodReplyMessageHandlerMapping (MessageHandlerMapping mapping)
+ {
+ Character opcode = mapping.getOpcode();
+ IMessageHandler handler = mapping.getMessageHandler();
+ _methodReplyQueueHandlers.put(opcode, handler);
+
+ LOGGER.info(Messages.QMAN_000008_METHOD_REPLY_HANDLER_MAPPING_CONFIGURED, opcode,handler.getClass().getName());
+ }
+
+ /**
+ * Adds to this configuration a new broker connection data.
+ *
+ * @param brokerId the broker identifier.
+ * @param connectionData the connection data.
+ * @throws BrokerAlreadyConnectedException when the broker is already connected.
+ * @throws BrokerConnectionException when a connection cannot be estabilished.
+ */
+ void addBrokerConnectionData (UUID brokerId, BrokerConnectionData connectionData) throws BrokerAlreadyConnectedException, BrokerConnectionException
+ {
+ if (_brokerConnectionInfos.containsValue(connectionData))
+ {
+ throw new BrokerAlreadyConnectedException(connectionData);
+ }
+
+ try
+ {
+ QpidDatasource.getInstance().addConnectionPool(brokerId, connectionData);
+ _brokerConnectionInfos.put(brokerId,connectionData);
+
+ LOGGER.info(Messages.QMAN_000009_BROKER_DATA_CONFIGURED,brokerId,connectionData);
+ } catch(Exception exception)
+ {
+ throw new BrokerConnectionException(exception);
+ }
+
+ }
+
+ /**
+ * Header for command messages is created once because it only contains static values.
+ */
+ private void createHeaderForCommandMessages ()
+ {
+ ReplyTo replyTo=new ReplyTo();
+ replyTo.setRoutingKey(_methodReplyQueueName);
+ _messageProperties.setReplyTo(replyTo);
+ _deliveryProperties.setRoutingKey(Names.AGENT_ROUTING_KEY);
+ _headerForCommandMessages = new Header(_deliveryProperties, _messageProperties);
+ }
+
+ /**
+ * Creates the name of the queues used by this service.
+ * This is done because if a broker should be managed by one or more management client, then each of them
+ * must have its own channels to communicate with.
+ */
+ private void defineQueueNames()
+ {
+ UUID uuid = UUID.randomUUID();
+ _managementQueueName = Names.MANAGEMENT_QUEUE_PREFIX+uuid;
+ _methodReplyQueueName = Names.METHOD_REPLY_QUEUE_PREFIX+uuid;
+
+ LOGGER.debug(Messages.QMAN_200004_MANAGEMENT_QUEUE_NAME,_managementQueueName);
+ LOGGER.debug(Messages.QMAN_200005_METHOD_REPLY_QUEUE_NAME,_methodReplyQueueName);
+ }
+
+ /**
+ * Returns the worker manager thread pool size.
+ *
+ * @return the worker manager thread pool size.
+ */
+ public int getWorkerManagerPoolSize()
+ {
+ return _poolSize;
+ }
+
+ /**
+ * Sets the size of the worker manager thread pool.
+ *
+ * @param poolSize the size of the worker manager thread pool.
+ */
+ void setWorkerManagerPoolSize(int poolSize)
+ {
+ this._poolSize = poolSize;
+ }
+
+ /**
+ * Returns the maximum size of the worker manager
+ * thread pool size.
+ *
+ * @return the max size of the worker manager thread pool.
+ */
+ public int getWorkerManagerMaxPoolSize()
+ {
+ return _maxPoolSize;
+ }
+
+ /**
+ * Sets the maximum size of the worker manager
+ * thread pool size.
+ *
+ * @param maxPoolSize the max size of the worker manager thread pool.
+ */
+ void setWorkerManagerMaxPoolSize(int maxPoolSize)
+ {
+ this._maxPoolSize = maxPoolSize;
+ }
+
+ /**
+ * Returns the max amount of time that an excess thread
+ * can be idle before purging from the pool.
+ *
+ * @return the max keep alive time.
+ */
+ public long getWorkerManagerKeepAliveTime()
+ {
+ return _keepAliveTime;
+ }
+
+ /**
+ * Sets the max amount of time that an excess thread
+ * can be idle before purging from the pool.
+ *
+ * @param keepAliveTime the max keep alive time.
+ */
+ void setWorkerManagerKeepAliveTime(long keepAliveTime)
+ {
+ this._keepAliveTime = keepAliveTime;
+ }
+
+ /**
+ * Configures access mode mappings.
+ * An access mode mapping is an association between a code and an access mode.
+ */
+ private void addAccessModeMappings() {
+ addAccessModeMapping(1,AccessMode.RC);
+ addAccessModeMapping(2,AccessMode.RW);
+ addAccessModeMapping(3,AccessMode.RO);
+ }
+
+ /**
+ * Configures type mappings.
+ * A type mapping is an association between a code and a management type.
+ */
+ private void addTypeMappings()
+ {
+ addTypeMapping(1,new Uint8(),Names.NUMBER_VALIDATOR);
+ addTypeMapping(2,new Uint16(),Names.NUMBER_VALIDATOR);
+ addTypeMapping(3,new Uint32(),Names.NUMBER_VALIDATOR);
+ addTypeMapping(4,new Uint64(),Names.NUMBER_VALIDATOR);
+ addTypeMapping(6,new Str8(),Names.STRING_VALIDATOR);
+ addTypeMapping(7,new Str16(),Names.STRING_VALIDATOR);
+ addTypeMapping(8,new AbsTime());
+ addTypeMapping(9,new DeltaTime());
+ addTypeMapping(10,new ObjectReference());
+ addTypeMapping(11,new org.apache.qpid.management.domain.model.type.Boolean());
+ addTypeMapping(14,new org.apache.qpid.management.domain.model.type.Uuid());
+ addTypeMapping(15,new org.apache.qpid.management.domain.model.type.Map());
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java
new file mode 100644
index 0000000000..6eed515e11
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+/**
+ * Thrown when a problem is encountered during building the configuration.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConfigurationException extends Exception
+{
+ private static final long serialVersionUID = 8238481177714286259L;
+
+ public ConfigurationException(String msg)
+ {
+ super(msg);
+ }
+
+ /**
+ * Builds a new ConfigurationException with the given cause.
+ *
+ * @param exception the exception cause.
+ */
+ public ConfigurationException(Exception exception)
+ {
+ super(exception);
+ }
+
+ public ConfigurationException(String msg,Exception exception)
+ {
+ super(msg,exception);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java
new file mode 100644
index 0000000000..fe44c6aff7
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java
@@ -0,0 +1,240 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.UUID;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.HeartBeatIndicationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler;
+import org.apache.qpid.transport.util.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Director used for coordinating the build process of configuration.
+ * This is the only component which has a read-write permission on Configuration object.
+ */
+public class Configurator extends DefaultHandler
+{
+ private final static Logger LOGGER = Logger.get(Configurator.class);
+
+ /**
+ * Default (empty) parser used when there's no need to process data (non relevant elements).
+ */
+ final static IParser DEFAULT_PARSER = new IParser() {
+
+ public void setCurrrentAttributeValue (String value)
+ {
+ }
+
+ public void setCurrentAttributeName (String name)
+ {
+ }
+ };
+
+ IParser _brokerConfigurationParser = new BrokerConnectionDataParser();
+ IParser _workerManagerConfigurationParser = new WorkerManagerConfigurationParser();
+ IParser _currentParser = DEFAULT_PARSER;
+
+ /**
+ * Delegates the processing to the current parser.
+ */
+ @Override
+ public void characters (char[] ch, int start, int length) throws SAXException
+ {
+ String value = new String(ch,start,length).trim();
+ if (value.length() != 0) {
+ _currentParser.setCurrrentAttributeValue(value);
+ }
+ }
+
+ /**
+ * Here is defined what parser needs to be used for processing the current data.
+ */
+ @Override
+ public void startElement (String uri, String localName, String name, Attributes attributes) throws SAXException
+ {
+ switch(Tag.get(name))
+ {
+ case BROKERS :
+ {
+ _currentParser = _brokerConfigurationParser;
+ break;
+ }
+ case WORK_MANAGER :
+ {
+ _currentParser = _workerManagerConfigurationParser;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void endElement (String uri, String localName, String name) throws SAXException
+ {
+ _currentParser.setCurrentAttributeName(name);
+ }
+
+ /**
+ * Builds whole configuration.
+ *
+ * @throws ConfigurationException when the build fails.
+ */
+ public void configure() throws ConfigurationException
+ {
+ BufferedReader reader = null;
+ try
+ {
+ String initialConfigFileName = System.getProperty(Names.QMAN_CONFIG_OPTION_NAME);
+ if (initialConfigFileName != null && initialConfigFileName.trim().length() != 0)
+ {
+ File initialConfigurationFile = new File(initialConfigFileName);
+ if (initialConfigurationFile.canRead())
+ {
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ reader = new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(initialConfigFileName)));
+ InputSource source = new InputSource(reader);
+ parser.parse(source, this);
+ } else {
+ LOGGER.warn(
+ Messages.QMAN_300004_INVALID_CONFIGURATION_FILE,
+ initialConfigFileName);
+ }
+ }
+
+ addMandatoryManagementMessageHandlers();
+ addMandatoryMethodReplyMessageHandlers();
+ } catch (Exception exception)
+ {
+ throw new ConfigurationException(exception);
+ } finally
+ {
+ try
+ {
+ reader.close();
+ } catch (Exception ignore)
+ {
+ }
+ }
+ }
+
+ /**
+ * Creates and return a value object (BrokerConnectionData) with the given parameters.
+ * Note that that object will be stored on configuration and it could be used to set a connection with the broker.
+ * This happens when the "initialPoolCapacity" is greater than 0 : in this case the caller is indicatinf that it wants to open
+ * one or more connections immediately at startup and therefore Q-Man will try to do that.
+ *
+ * @param host the hostname where the broker is running.
+ * @param port the port where the broker is running.
+ * @param username the username for connecting with the broker.
+ * @param password the password for connecting with the broker.
+ * @param virtualHost the virtual host.
+ * @param initialPoolCapacity the number of the connection that must be immediately opened.
+ * @param maxPoolCapacity the maximum number of opened connection.
+ * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection.
+ * @return the value object containing the data above.
+ * @throws BrokerAlreadyConnectedException when the broker is already connected.
+ * @throws BrokerConnectionException when a connection cannot be estabilished.
+ */
+ public BrokerConnectionData createAndReturnBrokerConnectionData(
+ UUID brokerId,
+ String host,
+ int port,
+ String username,
+ String password,
+ String virtualHost,
+ int initialPoolCapacity,
+ int maxPoolCapacity,
+ long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException
+ {
+ BrokerConnectionData data = new BrokerConnectionData(
+ host,
+ port,
+ virtualHost,
+ username,
+ password,
+ initialPoolCapacity,
+ maxPoolCapacity,
+ maxWaitTimeout);
+ Configuration.getInstance().addBrokerConnectionData(brokerId, data);
+ return data;
+ }
+
+ /**
+ * Configures the mandatory management message handlers.
+ */
+ void addMandatoryMethodReplyMessageHandlers ()
+ {
+ Configuration.getInstance().addMethodReplyMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.OPERATION_INVOCATION_RESPONSE_OPCODE,
+ new MethodResponseMessageHandler()));
+
+ Configuration.getInstance().addMethodReplyMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.SCHEMA_RESPONSE_OPCODE,
+ new SchemaResponseMessageHandler()));
+ }
+
+ /**
+ * Configures the mandatory management message handlers.
+ */
+ void addMandatoryManagementMessageHandlers ()
+ {
+ Configuration.getInstance().addManagementMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.INSTRUMENTATION_CONTENT_RESPONSE_OPCODE,
+ new InstrumentationMessageHandler()));
+
+ Configuration.getInstance().addManagementMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE,
+ new ConfigurationMessageHandler()));
+
+ Configuration.getInstance().addManagementMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.EVENT_CONTENT_RESPONSE_OPCDE,
+ new EventContentMessageHandler()));
+
+ Configuration.getInstance().addManagementMessageHandlerMapping(
+ new MessageHandlerMapping(
+ Protocol.HEARTBEAT_INDICATION_RESPONSE_OPCODE,
+ new HeartBeatIndicationMessageHandler()));
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java
new file mode 100644
index 0000000000..a221686765
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+/**
+ * Interface definition for configuration parser
+ * Concrete implementors are responsible for parsing a specific XML part of configuration data.
+ *
+ * @author Andrea Gazzarini
+ */
+interface IParser
+{
+ /**
+ * Main director callback : Sets the name of the current attribute.
+ *
+ * @param name the name of the current attribute.
+ */
+ void setCurrentAttributeName(String name);
+
+ /**
+ * Main director callback : sets the value of the current attribute.
+ *
+ * @param value the value of the current attribute.
+ */
+ void setCurrrentAttributeValue(String value);
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java
new file mode 100644
index 0000000000..b02fb789cc
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+
+/**
+ * Message Handler mapping used for associating an opcode with a message handler.
+ */
+class MessageHandlerMapping
+{
+ private final Character _opcode;
+ private final IMessageHandler _handler;
+
+ /**
+ * Builds a new mapping with the given opcode and handler class.
+ *
+ * @param opcode the opcode.
+ * @param handlerClass the handler class.
+ */
+ MessageHandlerMapping(Character opcode, IMessageHandler handler)
+ {
+ this._opcode = opcode;
+ this._handler = handler;
+ }
+
+ /**
+ * Returns the opcode of this mapping.
+ *
+ * @return the code of this mapping.
+ */
+ Character getOpcode ()
+ {
+ return _opcode;
+ }
+
+ /**
+ * Returns the message handler for this mapping.
+ *
+ * @return the message handler for this mapping.
+ */
+ IMessageHandler getMessageHandler()
+ {
+ return _handler;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java
new file mode 100644
index 0000000000..569a65a782
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java
@@ -0,0 +1,249 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.commons.pool.impl.GenericObjectPoolFactory;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionException;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid datasource.
+ * Basically it is a connection pool manager used for optimizing broker connections usage.
+ *
+ * @author Andrea Gazzarini
+ */
+public final class QpidDatasource
+{
+ private final static Logger LOGGER = Logger.get(QpidDatasource.class);
+
+ /**
+ * A connection decorator used for adding pool interaction behaviour to an existing connection.
+ *
+ * @author Andrea Gazzarini
+ */
+ class PooledConnection extends Connection
+ {
+ private final UUID _brokerId;
+ private boolean _valid;
+
+ /**
+ * Builds a new decorator with the given connection.
+ *
+ * @param brokerId the broker identifier.
+ */
+ private PooledConnection(UUID brokerId)
+ {
+ this._brokerId = brokerId;
+ _valid = true;
+ }
+
+ /**
+ * Returns true if the underlying connection is still valid and can be used.
+ *
+ * @return true if the underlying connection is still valid and can be used.
+ */
+ boolean isValid()
+ {
+ return _valid;
+ }
+
+ void reallyClose()
+ {
+ super.close();
+ }
+
+ /**
+ * Returns the connection to the pool. That is, marks this connections as available.
+ * After that, this connection will be available for further operations.
+ */
+ public void close()
+ {
+ try
+ {
+ pools.get(_brokerId).returnObject(this);
+
+ LOGGER.debug(Messages.QMAN_200006_QPID_CONNECTION_RELEASED, this);
+ }
+ catch (Exception e)
+ {
+ throw new ConnectionException(e);
+ }
+ }
+
+ public void exception(Throwable t)
+ {
+ //super.exception(t);
+ _valid = false;
+ }
+ }
+
+ /**
+ * This is the connection factory, that is, the factory used to manage the lifecycle (create, validate & destroy) of
+ * the broker connection(s).
+ *
+ * @author Andrea Gazzarini
+ */
+ class QpidConnectionFactory extends BasePoolableObjectFactory
+ {
+ private final BrokerConnectionData _connectionData;
+ private final UUID _brokerId;
+
+ /**
+ * Builds a new connection factory with the given parameters.
+ *
+ * @param brokerId the broker identifier.
+ * @param connectionData the connecton data.
+ */
+ private QpidConnectionFactory(UUID brokerId, BrokerConnectionData connectionData)
+ {
+ this._connectionData = connectionData;
+ this._brokerId = brokerId;
+ }
+
+ /**
+ * Creates a new underlying connection.
+ */
+ @Override
+ public Connection makeObject () throws Exception
+ {
+ PooledConnection connection = new PooledConnection(_brokerId);
+ connection.connect(
+ _connectionData.getHost(),
+ _connectionData.getPort(),
+ _connectionData.getVirtualHost(),
+ _connectionData.getUsername(),
+ _connectionData.getPassword(),
+ false);
+ return connection;
+ }
+
+ /**
+ * Validates the underlying connection.
+ */
+ @Override
+ public boolean validateObject (Object obj)
+ {
+ PooledConnection connection = (PooledConnection) obj;
+ boolean isValid = connection.isValid();
+
+ LOGGER.debug(Messages.QMAN_200007_TEST_CONNECTION_ON_RESERVE,isValid);
+
+ return isValid;
+ }
+
+ /**
+ * Closes the underlying connection.
+ */
+ @Override
+ public void destroyObject (Object obj) throws Exception
+ {
+ try
+ {
+ PooledConnection connection = (PooledConnection) obj;
+ connection.reallyClose();
+
+ LOGGER.debug(Messages.QMAN_200008_CONNECTION_DESTROYED);
+ } catch (Exception exception)
+ {
+ LOGGER.debug(exception, Messages.QMAN_200009_CONNECTION_DESTROY_FAILURE);
+ }
+ }
+ }
+
+ // Singleton instance.
+ private static QpidDatasource instance = new QpidDatasource();
+
+ // Each entry contains a connection pool for a specific broker.
+ private Map<UUID, ObjectPool> pools = new HashMap<UUID, ObjectPool>();
+
+ // Private constructor.
+ private QpidDatasource()
+ {
+ }
+
+ /**
+ * Gets an available connection from the pool of the given broker.
+ *
+ * @param brokerId the broker identifier.
+ * @return a valid connection to the broker associated with the given identifier.
+ */
+ public Connection getConnection(UUID brokerId) throws Exception
+ {
+ return (Connection) pools.get(brokerId).borrowObject();
+ }
+
+ /**
+ * Entry point method for retrieving the singleton instance of this datasource.
+ *
+ * @return the qpid datasource singleton instance.
+ */
+ public static QpidDatasource getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Adds a connection pool to this datasource.
+ *
+ * @param brokerId the broker identifier that will be associated with the new connection pool.
+ * @param connectionData the broker connection data.
+ * @throws Exception when the pool cannot be created.
+ */
+ void addConnectionPool(UUID brokerId,BrokerConnectionData connectionData) throws Exception
+ {
+ GenericObjectPoolFactory factory = new GenericObjectPoolFactory(
+ new QpidConnectionFactory(brokerId,connectionData),
+ connectionData.getMaxPoolCapacity(),
+ GenericObjectPool.WHEN_EXHAUSTED_BLOCK,
+ connectionData.getMaxWaitTimeout(),-1,
+ true,
+ false);
+
+ ObjectPool pool = factory.createPool();
+
+ // Open connections at startup according to initial capacity param value.
+ int howManyConnectionAtStartup = connectionData.getInitialPoolCapacity();
+ Object [] openStartupList = new Object[howManyConnectionAtStartup];
+
+ // Open...
+ for (int index = 0; index < howManyConnectionAtStartup; index++)
+ {
+ openStartupList[index] = pool.borrowObject();
+ }
+
+ // ...and immediately return them to pool. In this way the pooled connection has been opened.
+ for (int index = 0; index < howManyConnectionAtStartup; index++)
+ {
+ pool.returnObject(openStartupList[index]);
+ }
+
+ pools.put(brokerId,pool);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java
new file mode 100644
index 0000000000..c2b6e1e27d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java
@@ -0,0 +1,54 @@
+/*
+*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.management.configuration;
+
+/**
+ * Configuration Tag catalogue.
+ *
+ * @author Andrea Gazzarini
+ */
+public enum Tag {
+ CONFIGURATION { @Override public String toString() { return "configuration"; }},
+ BROKER { @Override public String toString() { return "broker"; }},
+ HOST { @Override public String toString() { return "host"; }},
+ PORT { @Override public String toString() { return "port"; }},
+ MAX_POOL_CAPACITY { @Override public String toString() { return "max-pool-capacity"; }},
+ MAX_WAIT_TIMEOUT { @Override public String toString() { return "max-wait-timeout"; }},
+ INITIAL_POOL_CAPACITY { @Override public String toString() { return "initial-pool-capacity"; }},
+ VIRTUAL_HOST { @Override public String toString() { return "virtual-host"; }},
+ USER { @Override public String toString() { return "user"; }},
+ PASSWORD { @Override public String toString() { return "password"; }},
+ BROKERS { @Override public String toString() { return "brokers"; }},
+ WORK_MANAGER { @Override public String toString() { return "work-manager"; }},
+ POOL_CAPACITY { @Override public String toString() { return "pool-capacity"; }},
+ KEEP_ALIVE_TIME { @Override public String toString() { return "keep-alive-time"; }};
+
+ /**
+ * Returns the enum entry associated to the given tag name.
+ *
+ * @param name the name of tag.
+ * @return the enum entry associated to the given tag name.
+ */
+ public static Tag get(String name) {
+ return valueOf(name.replaceAll("-", "_").toUpperCase());
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java
new file mode 100644
index 0000000000..b7f1c0a7ec
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java
@@ -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 org.apache.qpid.management.configuration;
+
+/**
+ * Thrown when no access mode is found in configuration associated to the given code.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UnknownAccessCodeException extends Exception
+{
+ private static final long serialVersionUID = 2350963503092509119L;
+ private final int _code;
+
+ /**
+ * Builds a new UnknownAccessCodeException with the given code.
+ *
+ * @param code the access code.
+ */
+ UnknownAccessCodeException(int code)
+ {
+ super(String.valueOf(code));
+ this._code = code;
+ }
+
+ /**
+ * Returns the unknown code.
+ *
+ * @return the unknown code.
+ */
+ public int getCode ()
+ {
+ return _code;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java
new file mode 100644
index 0000000000..5b08e09c24
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.configuration;
+
+import java.util.UUID;
+
+/**
+ * Thrown when someone requests connection data for an unknown broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UnknownBrokerException extends Exception
+{
+ private static final long serialVersionUID = 4965395428832158924L;
+
+ /**
+ * Builds a new UnknownBrokerException with the given broker id.
+ *
+ * @param brokerId the broker identifier.
+ */
+ UnknownBrokerException(UUID brokerId)
+ {
+ super(String.valueOf(brokerId));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java
new file mode 100644
index 0000000000..57005d21e5
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java
@@ -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 org.apache.qpid.management.configuration;
+
+/**
+ * Thrown when no type is found in configuration associated to the given code.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UnknownTypeCodeException extends Exception
+{
+ private static final long serialVersionUID = 5440934037645111591L;
+ private int _code;
+
+ /**
+ * Builds a new UnknownTypeCodeException with the given code.
+ *
+ * @param code the access code.
+ */
+ UnknownTypeCodeException(int code)
+ {
+ super(String.valueOf(code));
+ this._code = code;
+ }
+
+ /**
+ * Returns the unknown code.
+ *
+ * @return the unknown code.
+ */
+ public int getCode ()
+ {
+ return _code;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java
new file mode 100644
index 0000000000..4e68b54b12
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.UUID;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Parser used for building worker manager settings.
+ * The corresponding section of the configuration file is :
+ *
+ <work-manager>
+ <pool-capacity>5</pool-capacity>
+ <max-pool-capacity>15</max-pool-capacity>
+ <keep-alive-time>5000</keep-alive-time>
+ </work-manager>
+
+ *
+ * @author Andrea Gazzarini
+ */
+class WorkerManagerConfigurationParser implements IParser
+{
+ private final static Logger LOGGER = Logger.get(Configuration.class);
+ private String _currentValue;
+
+ private String _poolSizeAsString;
+ private String _maxPoolSizeAsString;
+ private String _keepAliveTimeAsString;
+
+ /**
+ * Callback : the given value is the text content of the current node.
+ */
+ public void setCurrrentAttributeValue (String value)
+ {
+ this._currentValue = value;
+ }
+
+ /**
+ * Callback: each time the end of an element is reached
+ * this method is called.
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case POOL_CAPACITY:
+ {
+ _poolSizeAsString = _currentValue.trim();
+ break;
+ }
+ case MAX_POOL_CAPACITY :
+ {
+ _maxPoolSizeAsString = _currentValue;
+ break;
+ }
+ case KEEP_ALIVE_TIME:
+ {
+ _keepAliveTimeAsString = _currentValue;
+ break;
+ }
+ case WORK_MANAGER:
+ {
+ Configuration configuration = Configuration.getInstance();
+ try
+ {
+ configuration.setWorkerManagerPoolSize(Integer.parseInt(_poolSizeAsString));
+ configuration.setWorkerManagerMaxPoolSize(Integer.parseInt(_maxPoolSizeAsString));
+ configuration.setWorkerManagerKeepAliveTime(Long.parseLong(_keepAliveTimeAsString));
+ } catch(Exception exception)
+ {
+ LOGGER.error(Messages.QMAN_100039_UNABLE_TO_CONFIGURE_PROPERLY_WORKER_MANAGER);
+ } finally {
+ LOGGER.info(Messages.QMAN_000035_WORK_MANAGER_POOL_SIZE,configuration.getWorkerManagerPoolSize());
+ LOGGER.info(Messages.QMAN_000036_WORK_MANAGER_MAX_POOL_SIZE,configuration.getWorkerManagerMaxPoolSize());
+ LOGGER.info(Messages.QMAN_000037_WORK_MANAGER_KEEP_ALIVE_TIME,configuration.getWorkerManagerKeepAliveTime());
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Gets an uuid in order to associate current connection data with a broker.
+ * @return
+ */
+ UUID getUUId(){
+ return UUID.randomUUID();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java
new file mode 100644
index 0000000000..798e835ff4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.handler.base;
+
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Base class for all message handlers.
+ * A message handler is an handler for a specific type of message.
+ * Message type is defined by the opcode.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class BaseMessageHandler implements IMessageHandler
+{
+ /**
+ * Logger used for logging.
+ */
+ protected final Logger _logger = Logger.get(getClass());
+
+ /**
+ * Managed broker domain model.
+ */
+ protected DomainModel _domainModel;
+
+ /**
+ * Sets the broker domain model.
+ *
+ * @param domainModel the broker domain model.
+ */
+ public void setDomainModel(DomainModel domainModel)
+ {
+ this._domainModel = domainModel;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java
new file mode 100644
index 0000000000..be000e9a05
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.base;
+
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * Base class for content indication message handlers.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class ContentIndicationMessageHandler extends BaseMessageHandler
+{
+ /**
+ * Processes the income message.
+ *
+ * @param decoder the decoder used to parse the message.
+ * @param sequenceNumber the sequence number of the message.
+ */
+ public final void process (Decoder decoder, int sequenceNumber)
+ {
+ String packageName = decoder.readStr8();
+ String className = decoder.readStr8();
+ Binary classHash = new Binary(decoder.readBin128());
+
+ long timeStampOfCurrentSample = decoder.readDatetime();
+ long timeObjectWasCreated = decoder.readDatetime();
+ long timeObjectWasDeleted = decoder.readDatetime();
+
+ Binary objectId = new Binary(decoder.readBin128());
+
+ if (objectHasBeenRemoved(timeObjectWasDeleted, timeStampOfCurrentSample))
+ {
+ removeObjectInstance(packageName,className,classHash,objectId);
+ } else
+ {
+ updateDomainModel(
+ packageName,
+ className,
+ classHash,
+ objectId,
+ timeStampOfCurrentSample,
+ timeObjectWasCreated,
+ timeObjectWasDeleted,
+ decoder.readReaminingBytes());
+ }
+ }
+
+ /**
+ * Removes an object instance from the domain model.
+ *
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param classHash the class hash.
+ * @param objectId the object identifier.
+ */
+ void removeObjectInstance(String packageName, String className,Binary classHash, Binary objectId)
+ {
+ _domainModel.removeObjectInstance(packageName,className,classHash,objectId);
+ }
+
+ /**
+ * Checks if the timestamps contained in the message indicate that the object has been removed.
+ *
+ * @param deletionTimestamp time object was deleted.
+ * @param now timestamp of the current message.
+ * @return true if the object has been removed, false otherwise.
+ */
+ boolean objectHasBeenRemoved(long deletionTimestamp, long now) {
+ return (deletionTimestamp != 0) && (now > deletionTimestamp);
+ }
+
+ /**
+ * Updates domain model with the incoming data.
+ * This is a template method that each concrete subclass must implement in order to update the domain model
+ * with the incoming data.
+ *
+ * @param packageName the name of the package.
+ * @param className the name of the class.
+ * @param objectId the object identifier.
+ * @param timeStampOfCurrentSample timestamp of current sample.
+ * @param timeObjectWasCreated time object was created.
+ * @param timeObjectWasDeleted time object was deleted.
+ * @param contentData object instance incoming data.
+ */
+ protected abstract void updateDomainModel(
+ String packageName,
+ String className,
+ Binary classHash,
+ Binary objectId,
+ long timeStampOfCurrentSample,
+ long timeObjectWasCreated,
+ long timeObjectWasDeleted,
+ byte []contentData );
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java
new file mode 100644
index 0000000000..c120334d30
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.base;
+
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * Interface definition for a processor able to deal with a specific message.
+ * The concrete implementor must define what has to be done with the supplied (incoming) stream and the sequence
+ * number.
+ *
+ * @author Andrea Gazzarini.
+ */
+public interface IMessageHandler
+{
+ /**
+ * Processes the (incoming) stream message.
+ * Note that the main controller (the component that is controlling this handler) has already read the magic number and
+ * the sequence number so here concrete implementors must start from that point (that is, just after the sequence
+ * number).
+ *
+ * @param decoder the stream decoder.
+ * @param sequenceNumber the sequence number of the message.
+ */
+ void process (Decoder decoder, int sequenceNumber);
+
+ /**
+ * Injects the domain model into this handler.
+ *
+ * @param domainModel the domain model.
+ */
+ void setDomainModel(DomainModel domainModel);
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java
new file mode 100644
index 0000000000..3158138172
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import org.apache.qpid.management.domain.handler.base.ContentIndicationMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Schema Response message handler.
+ * This handler is responsible to process 'c'(opcode) messages sent by the management broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConfigurationMessageHandler extends ContentIndicationMessageHandler
+{
+ /**
+ * Broker domain model is going to be updated with incoming configuration data.
+ *
+ * @param packageName the name of the package.
+ * @param className the name of the class.
+ * @param objectId the object identifier.
+ * @param timeStampOfCurrentSample the timestamp of incoming data.
+ * @param timeObjectWasCreated time object was created.
+ * @param timeObjectWasDeleted time object was deleted.
+ */
+ @Override
+ protected void updateDomainModel (
+ String packageName,
+ String className,
+ Binary classHash,
+ Binary objectId,
+ long timeStampOfCurrentSample,
+ long timeObjectWasCreated,
+ long timeObjectWasDeleted,
+ byte[] contentData)
+ {
+ _domainModel.addConfigurationRawData(packageName,className,classHash,objectId,contentData);
+ }
+ }
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java
new file mode 100644
index 0000000000..0a590d2836
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * Base class for content indication message handlers.
+ *
+ * @author Andrea Gazzarini
+ */
+public class EventContentMessageHandler extends BaseMessageHandler
+{
+ /**
+ * Processes the income message.
+ *
+ * @param decoder the decoder used to parse the message.
+ * @param sequenceNumber the sequence number of the message.
+ */
+ public final void process (Decoder decoder, int sequenceNumber)
+ {
+ String packageName = decoder.readStr8();
+ String eventName = decoder.readStr8();
+ Binary eventHash = new Binary(decoder.readBin128());
+ long timeStampOfCurrentSample = decoder.readDatetime();
+ int severity = decoder.readUint8();
+ byte[] argumentsData = decoder.readReaminingBytes();
+
+ _domainModel.addEventRawData(packageName, eventName, eventHash, argumentsData,timeStampOfCurrentSample,severity);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java
new file mode 100644
index 0000000000..08c4f1bc5d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java
@@ -0,0 +1,39 @@
+/*
+*
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * This is the handler responsible for processing the heartbeat indication response messages.
+ * At the moment it simply updates the last refresh update timestamp of the domain model.
+ *
+ * @author Andrea Gazzarini.
+ */
+public class HeartBeatIndicationMessageHandler extends BaseMessageHandler
+{
+ public void process(Decoder decoder, int sequenceNumber)
+ {
+ _domainModel.updateLastRefreshDate();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java
new file mode 100644
index 0000000000..4ce64dd339
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.util.EventListener;
+
+import org.apache.qpid.management.domain.model.InvocationEvent;
+
+/**
+ * Listener interface used to denote a component interested in method invocation events.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface IMethodInvocationListener extends EventListener
+{
+ /**
+ * An operation is going to be invoked on a specific object instance.
+ * This lets this listener to be informed about the imminent invocation.
+ *
+ * @param event the invocation event.
+ */
+ void operationIsGoingToBeInvoked(InvocationEvent event);
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java
new file mode 100644
index 0000000000..e86a44f829
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import org.apache.qpid.management.domain.handler.base.ContentIndicationMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Schema Response message handler.
+ * This handler is responsible to process 'i'(opcode) messages sent by the management broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class InstrumentationMessageHandler extends ContentIndicationMessageHandler
+{
+ /**
+ * Broker domain model is going to be updated with incoming instrumentation data.
+ *
+ * @param packageName the name of the package.
+ * @param className the name of the class.
+ * @param objectId the object identifier.
+ * @param timeStampOfCurrentSample the timestamp of incoming data.
+ * @param timeObjectWasCreated time object was created.
+ * @param timeObjectWasDeleted time object was deleted.
+ */
+ @Override
+ protected void updateDomainModel (
+ String packageName,
+ String className,
+ Binary classHash,
+ Binary objectId,
+ long timeStampOfCurrentSample,
+ long timeObjectWasCreated,
+ long timeObjectWasDeleted,
+ byte[] contentData)
+ {
+ _domainModel.addInstrumentationRawData(packageName,className,classHash,objectId,contentData);
+ }
+ }
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java
new file mode 100644
index 0000000000..019fce5a50
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java
@@ -0,0 +1,157 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.qpid.management.domain.services.MethodInvocationException;
+
+/**
+ * Value object used for storing an invocation method result.
+ * This is done in order to accomplish multiple return value requirement.
+ * As we know, it's not possible to do that only with method signature and therefore this value object / struct is used.
+ *
+ * @author Andrea Gazzarini
+ */
+public class InvocationResult implements Serializable
+{
+ private static final long serialVersionUID = 2062662997326399693L;
+
+ private final long _returnCode;
+ private final String _statusText;
+ private final byte [] _outputAndBidirectionalArgumentValues;
+ private Map<String, Object> _outputSection;
+
+ /**
+ * Builds an invocation result with the given status code and status text.
+ *
+ * @param statusCode the status code.
+ * @param statusText the status text.
+ */
+ InvocationResult(long statusCode, String statusText,byte [] outputAndBidirectionalArgumentValues)
+ {
+ this._returnCode = statusCode;
+ this._statusText = statusText;
+ this._outputAndBidirectionalArgumentValues = outputAndBidirectionalArgumentValues;
+ }
+
+ /**
+ * Checks if this result contains an error return code.
+ *
+ * @return true if this result object contains an error return code.
+ */
+ public boolean isException ()
+ {
+ return _returnCode != 0;
+ }
+
+ /**
+ * Simply throws a new MethodInvocationException.
+ * Usually this method is called in conjunction with the isException() method in order to raise an exception if
+ * the wrapped return code means that there was an error.
+ *
+ * @throws MethodInvocationException always.
+ */
+ public void createAndThrowException() throws MethodInvocationException
+ {
+ throw new MethodInvocationException(_returnCode, _statusText);
+ }
+
+ @Override
+ public String toString ()
+ {
+ StringBuilder builder = new StringBuilder()
+ .append("Status code : ")
+ .append(_returnCode)
+ .append(",")
+ .append("Status Text : ")
+ .append(_statusText);
+ if (_outputSection != null && !_outputSection.isEmpty())
+ {
+ builder.append(". Parameters : ");
+ for (Entry<String, Object> outputEntry : _outputSection.entrySet())
+ {
+ builder.append(outputEntry.getKey()).append('=').append(outputEntry.getValue());
+ builder.append(',');
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Returns the return code of this invocation result.
+ *
+ * @return the return code of this invocation result.
+ */
+ public long getReturnCode ()
+ {
+ return _returnCode;
+ }
+
+ /**
+ * Contains the status text of this invocation result.
+ *
+ * @return the status text of this invocation result.
+ */
+ public String getStatusText ()
+ {
+ return _statusText;
+ }
+
+ /**
+ * Returns the output and bidirectional argument values in raw format (byte [])
+ *
+ * @return the output and bidirectional argument values in raw format (byte [])
+ */
+ public byte [] getOutputAndBidirectionalArgumentValues()
+ {
+ return _outputAndBidirectionalArgumentValues;
+ }
+
+ /**
+ * Sets the output section (decoded) of this invocation result.
+ * When an incoming message arrives, the output section (output and bidirectional argument values) are
+ * initially stored in raw format.
+ * After that, their values need to be converted.
+ * The final result is a map containing (for each Output or Input/Output parameter) the name of the argument as key
+ * and its value as value.
+ *
+ * @param output a map containing outptu and bidirectional values (not in schema order).
+ */
+ public void setOutputSection (Map<String, Object> outputSection)
+ {
+ this._outputSection = outputSection;
+ }
+
+ /**
+ * Returns the output section of this invocation result.
+ * The output section consists in output and bidirectional argument values.
+ * Note that the order of the arguments is not guaranteed.
+ *
+ * @param outputSection the output section of this invocation result;
+ */
+ public Map<String, Object> getOutputSection ()
+ {
+ return _outputSection;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java
new file mode 100644
index 0000000000..bc6a77d804
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Simple transfer object used for holding method / event definition data.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MethodOrEventDataTransferObject
+{
+ private final Map<String, Object> _definition;
+ private List<Map<String, Object>> _argumentDefinitions;
+
+ /**
+ * Builds a new trasfer object with the given parameters.
+ *
+ * @param definition the method definition.
+ * @param argumentDefinitions the arguments definitions.
+ */
+ public MethodOrEventDataTransferObject(
+ Map<String, Object> definition,
+ List<Map<String, Object>> argumentDefinitions)
+ {
+ this._definition = definition;
+ this._argumentDefinitions = argumentDefinitions;
+ }
+
+ /**
+ * Returns the method definition.
+ *
+ * @return the method definition.
+ */
+ public Map<String, Object> getDefinition() {
+ return _definition;
+ }
+
+ /**
+ * Returns the arguemnts definitions.
+ *
+ * @return the arguemnts definitions.
+ */
+ public List<Map<String, Object>> getArgumentsDefinitions()
+ {
+ return _argumentDefinitions;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java
new file mode 100644
index 0000000000..9c99eb09aa
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.management.domain.model.InvocationEvent;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Message handler for method response messages.
+ * This handler is installed on domain model as a method invocation result listener.
+ * When a method is going to be invoked this listener is notified with the exchange channel that will be used between it and
+ * the event (method invocation) source object.
+ *
+ * @author Andrea Gazzarini
+ *
+ */
+public class MethodResponseMessageHandler extends BaseMessageHandler
+{
+ private final static Logger LOGGER = Logger.get(MethodResponseMessageHandler.class);
+
+ private Map<Integer, BlockingQueue<InvocationResult>> _exchangeChannels = new HashMap<Integer, BlockingQueue<InvocationResult>>();
+
+ /**
+ * This is the listener installed on domain model for method invocations.
+ */
+ private final IMethodInvocationListener methodInvocationListener = new IMethodInvocationListener()
+ {
+ /**
+ * Event source callback.
+ * A method is going to be invoked and this method lets this listener take the exchange channel that will be used
+ * with the event source for synchronous communication.
+ *
+ * @param event the operation invocation event.
+ */
+ public void operationIsGoingToBeInvoked (InvocationEvent event)
+ {
+ _exchangeChannels.put(event.getSequenceNumber(), event.getExchangeChannel());
+ }
+ };
+
+ /**
+ * Processes the incoming message.
+ *
+ * @param decoder the decoder used for parsing incoming data.
+ * @param sequenceNumber the sequence number of the incoming message.
+ */
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ InvocationResult result = new InvocationResult(decoder.readUint32(), decoder.readStr16(),decoder.readReaminingBytes());
+ BlockingQueue<InvocationResult> exchangeChannel = _exchangeChannels.remove(sequenceNumber);
+ if (exchangeChannel != null)
+ {
+ try
+ {
+ exchangeChannel.put(result);
+ } catch (InterruptedException exception)
+ {
+ LOGGER.error(exception,Messages.QMAN_100010_METHOD_INVOCATION_RESULT_FAILURE,sequenceNumber);
+ }
+ } else
+ {
+ LOGGER.warn(
+ "Unable to deal with incoming message because it contains a unknown sequence number (%s).",
+ sequenceNumber);
+ }
+ }
+
+ /**
+ * Sets the domain model on this handler.
+ * In addiction, this handler registers a method invocation listener on the domain model.
+ *
+ * @param domainModel the managed broker domain model.
+ */
+ @Override
+ public void setDomainModel (DomainModel domainModel)
+ {
+ super.setDomainModel(domainModel);
+ domainModel.setMethodInvocationListener(methodInvocationListener);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java
new file mode 100644
index 0000000000..8456b2f8ac
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java
@@ -0,0 +1,314 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.management.domain.services.MethodInvocationException;
+
+/**
+ * This is a sample entity used on QMan test case.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidDomainObject implements QpidDomainObjectMBean
+{
+ private UUID _vhostRef;
+ private String _name;
+ private Boolean _durable;
+ private Map<String, Object> _arguments;
+ private Long _msgTotalEnqueues;
+ private Integer _consumerCount;
+ private Short _mgmtPubInterval;
+ private Date _expireTime;
+ private String _type;
+ private byte [] _byteArray;
+
+ /**
+ * Builds a new QpidDomainObject with default values for
+ * its properties.
+ */
+ public QpidDomainObject()
+ {
+ _vhostRef = UUID.randomUUID();
+ _name = "Initial Name";
+ _durable = Boolean.TRUE;
+ _arguments = new HashMap<String, Object>();
+ _arguments.put("Key1", "aStringValue");
+ _arguments.put("Key2", Long.MIN_VALUE);
+ _arguments.put("Key3", Integer.MAX_VALUE);
+ _arguments.put("Key4", Double.MIN_VALUE);
+ _arguments.put("Key4", Float.MAX_VALUE);
+
+ _msgTotalEnqueues = Long.MAX_VALUE-10;
+ _consumerCount = Integer.MIN_VALUE+10;
+ _mgmtPubInterval = Short.MAX_VALUE;
+ _expireTime = new Date(Long.MAX_VALUE);
+ _byteArray = new byte[]{1,2,3,5,6,7,8,7,56};
+ }
+
+ /**
+ * A method that is throwing an exception, everytime.
+ *
+ * @throws Exception each time the method is called.
+ */
+ public void throwsException() throws Exception
+ {
+ throw new MethodInvocationException(-1,"KO");
+ }
+
+ /**
+ * Sample echo method that return an empty result object.
+ * That is, an object with only status code / text valorized
+ * (no output parameters).
+ *
+ * @return an empty result object.
+ */
+ public InvocationResult voidWithoutArguments()
+ {
+ return new InvocationResult(0,"OK,null",null);
+ }
+
+ /**
+ * Echo method that accepts and returns primitive type arrays.
+ *
+ * @param longs an array of long.
+ * @param booleans an array of boolean.
+ * @param doubles an array of double.
+ * @param floats an array of float.
+ * @param integers an array of int.
+ * @param shorts an array of short.
+ * @return a result object with the same input parameters (as output parameters).
+ */
+ public InvocationResult echoWithSimpleTypeArrays(
+ long [] longs,
+ boolean [] booleans,
+ double [] doubles,
+ float [] floats,
+ int [] integers,
+ short [] shorts)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put(long.class.getName(), longs);
+ outputParameters.put(boolean.class.getName(), booleans);
+ outputParameters.put(double.class.getName(), doubles);
+ outputParameters.put(float.class.getName(), floats);
+ outputParameters.put(int.class.getName(), integers);
+ outputParameters.put(short.class.getName(), shorts);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ /**
+ * Echo method that accepts and returns wrapper types.
+ *
+ * @param aLong a java.lang.Long
+ * @param aBoolean a java.lang.Boolean
+ * @param aDouble a java.lang.Double
+ * @param aFloat a java.lang.Float
+ * @param anInteger a java.lang.Integer
+ * @param aShort a java.lang.Short
+ * @param aString a java.lang.String
+ * @param anURI a java.net.URI
+ * @param aDate a java.util.Date
+ * @return a result object with the same given parameters (as output parameters)
+ */
+ public InvocationResult echoWithSimpleTypes(
+ Long aLong,
+ Boolean aBoolean,
+ Double aDouble,
+ Float aFloat,
+ Integer anInteger,
+ Short aShort,
+ String aString,
+ URI anURI,
+ Date aDate)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put("p1", aLong);
+ outputParameters.put("p2", aBoolean);
+ outputParameters.put("p3", aDouble);
+ outputParameters.put("p4", aFloat);
+ outputParameters.put("p5", anInteger);
+ outputParameters.put("p6", aShort);
+ outputParameters.put("p7", aString);
+ outputParameters.put("p8", anURI);
+ outputParameters.put("p9", aDate);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ /**
+ * Echo method that accepts and returns wrapper type arrays .
+ *
+ * @param longs an array of java.lang.Long
+ * @param booleans an array of java.lang.Boolean
+ * @param doubles an array of java.lang.Double
+ * @param floats an array of java.lang.Float
+ * @param integers an array of java.lang.Integer
+ * @param shorts an array of java.lang.Short
+ * @param strings an array of java.lang.String
+ * @param uris an array of java.net.URI
+ * @param dates an array of java.util.Date
+ * @return a result object with the same input parameters (as output parameters).
+ */
+ public InvocationResult echoWithArrays(
+ Long [] longs,
+ Boolean [] booleans,
+ Double [] doubles,
+ Float [] floats,
+ Integer [] integers,
+ Short [] shorts,
+ String [] strings,
+ URI [] uris,
+ Date [] dates)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put(Long.class.getName(), longs);
+ outputParameters.put(Boolean.class.getName(), booleans);
+ outputParameters.put(Double.class.getName(), doubles);
+ outputParameters.put(Float.class.getName(), floats);
+ outputParameters.put(Integer.class.getName(), integers);
+ outputParameters.put(Short.class.getName(), shorts);
+ outputParameters.put(String.class.getName(), strings);
+ outputParameters.put(URI.class.getName(), uris);
+ outputParameters.put(Date.class.getName(), dates);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ /**
+ * Echo method that accepts and returns a byte array.
+ *
+ * @param byteArray a byte array
+ * @return a result containing the input byte array (as output parameter)
+ */
+ public InvocationResult echoWithByteArray(byte [] byteArray)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put(byte[].class.getName(),byteArray);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ /**
+ * Echo method that accepts and returns an UUID.
+ *
+ * @param uuid a java.util.UUID.
+ * @return a result containing the input UUID (as output parameter)
+ */
+ public InvocationResult echoWithUUID(UUID uuid)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put("uuid",uuid);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ /**
+ * Echo method that accepts and returns a Map.
+ *
+ * @param map a java.util.Map.
+ * @return a result containing the input Map (as output parameter)
+ */
+ public InvocationResult echoWithMap(Map<String,Object> map)
+ {
+ InvocationResult result = new InvocationResult(0,"OK",null);
+ Map<String, Object> outputParameters = new HashMap<String, Object>();
+ outputParameters.put("map",map);
+ result.setOutputSection(outputParameters);
+ return result;
+ }
+
+ public UUID getVhostRef()
+ {
+ return _vhostRef;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public Boolean getDurable()
+ {
+ return _durable;
+ }
+
+ public Map<String, Object> getArguments()
+ {
+ return _arguments;
+ }
+
+ public Long getMsgTotalEnqueues()
+ {
+ return _msgTotalEnqueues;
+ }
+
+ public Integer getConsumerCount()
+ {
+ return _consumerCount;
+ }
+
+ public Date getExpireTime()
+ {
+ return _expireTime;
+ }
+
+ public Short getMgmtPubInterval()
+ {
+ return _mgmtPubInterval;
+ }
+
+ public void setExpireTime(Date expireTime)
+ {
+ this._expireTime = expireTime;
+ }
+
+ public void setMgmtPubInterval(Short value)
+ {
+ this._mgmtPubInterval = value;
+ }
+
+ public void setType(String type)
+ {
+ this._type = type;
+ }
+
+ public String getType()
+ {
+ return _type;
+ }
+
+ public byte[] getByteArray()
+ {
+ return _byteArray;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java
new file mode 100644
index 0000000000..da585a9f43
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java
@@ -0,0 +1,234 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Management interface for Qpid domain object.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface QpidDomainObjectMBean
+{
+ /**
+ * A method that is throwing an exception, everytime.
+ *
+ * @throws Exception each time the method is called.
+ */
+ void throwsException() throws Exception;
+
+ /**
+ * Sample echo method that return an empty result object.
+ * That is, an object with only status code / text valorized
+ * (no output parameters).
+ *
+ * @return an empty result object.
+ */
+ InvocationResult voidWithoutArguments();
+
+ /**
+ * Echo method that accepts and returns wrapper types.
+ *
+ * @param aLong a java.lang.Long
+ * @param aBoolean a java.lang.Boolean
+ * @param aDouble a java.lang.Double
+ * @param aFloat a java.lang.Float
+ * @param anInteger a java.lang.Integer
+ * @param aShort a java.lang.Short
+ * @param aString a java.lang.String
+ * @param anURI a java.net.URI
+ * @param aDate a java.util.Date
+ * @return a result object with the same given parameters (as output parameters)
+ */
+ InvocationResult echoWithSimpleTypes(
+ Long aLong,
+ Boolean aBoolean,
+ Double aDouble,
+ Float aFloat,
+ Integer anInteger,
+ Short aShort,
+ String aString,
+ URI anURI,
+ Date aDate);
+
+ /**
+ * Echo method that accepts and returns wrapper type arrays .
+ *
+ * @param longs an array of java.lang.Long
+ * @param booleans an array of java.lang.Boolean
+ * @param doubles an array of java.lang.Double
+ * @param floats an array of java.lang.Float
+ * @param integers an array of java.lang.Integer
+ * @param shorts an array of java.lang.Short
+ * @param strings an array of java.lang.String
+ * @param uris an array of java.net.URI
+ * @param dates an array of java.util.Date
+ * @return a result object with the same input parameters (as output parameters).
+ */
+ InvocationResult echoWithArrays(
+ Long [] longs,
+ Boolean [] booleans,
+ Double [] doubles,
+ Float [] floats,
+ Integer [] integers,
+ Short [] shorts,
+ String [] strings,
+ URI [] uris,
+ Date [] dates);
+
+ /**
+ * Echo method that accepts and returns primitive type arrays.
+ *
+ * @param longs an array of long.
+ * @param booleans an array of boolean.
+ * @param doubles an array of double.
+ * @param floats an array of float.
+ * @param integers an array of int.
+ * @param shorts an array of short.
+ * @return a result object with the same input parameters (as output parameters).
+ */
+ InvocationResult echoWithSimpleTypeArrays(
+ long [] longs,
+ boolean [] booleans,
+ double [] doubles,
+ float [] floats,
+ int [] integers,
+ short [] shorts);
+
+ /**
+ * Echo method that accepts and returns a byte array.
+ *
+ * @param byteArray a byte array
+ * @return a result containing the input byte array (as output parameter)
+ */
+ InvocationResult echoWithByteArray(byte [] byteArray);
+
+ /**
+ * Echo method that accepts and returns an UUID.
+ *
+ * @param uuid a java.util.UUID.
+ * @return a result containing the input UUID (as output parameter)
+ */
+ InvocationResult echoWithUUID(UUID uuid);
+
+ /**
+ * Echo method that accepts and returns a Map.
+ *
+ * @param map a java.util.Map.
+ * @return a result containing the input Map (as output parameter)
+ */
+ InvocationResult echoWithMap(Map<String,Object> map);
+
+ /**
+ * Returns the VHostRef property value.
+ *
+ * @return the VHostRef property value.
+ */
+ UUID getVhostRef();
+
+ /**
+ * Returns the name property value.
+ *
+ * @return the name property value.
+ */
+ String getName();
+
+ /**
+ * Returns the durable property value.
+ *
+ * @return the durable property value.
+ */
+ Boolean getDurable();
+
+ /**
+ * Returns the arguments property value.
+ *
+ * @return the arguments property value.
+ */
+ Map<String, Object> getArguments();
+
+ /**
+ * Returns the msgTotalEnqueues property value.
+ *
+ * @return the msgTotalEnqueues property value.
+ */
+ Long getMsgTotalEnqueues();
+
+ /**
+ * Returns the consumerCount property value.
+ *
+ * @return the consumerCount property value.
+ */
+ Integer getConsumerCount();
+
+ /**
+ * Returns the mgmtPubInterval property value.
+ *
+ * @return the mgmtPubInterval property value.
+ */
+ Short getMgmtPubInterval();
+
+ /**
+ * Sets the mgmtPubInterval property value.
+ *
+ * @param the mgmtPubInterval property value.
+ */
+ void setMgmtPubInterval(Short mgmtPubInterval);
+
+ /**
+ * Returns the expireTime property value.
+ *
+ * @return the expireTime property value.
+ */
+ Date getExpireTime();
+
+ /**
+ * Sets the expireTime property value.
+ *
+ * @return the expireTime property value.
+ */
+ void setExpireTime(Date expireTime);
+
+ /**
+ * Returns the type property value.
+ *
+ * @return the type property value.
+ */
+ void setType(String type);
+
+ /**
+ * Sets the type property value.
+ *
+ * @return the type property value.
+ */
+ String getType();
+
+// /**
+// * Returns the byteArray property value.
+// *
+// * @return the byteArray property value.
+// */
+// byte[] getByteArray();
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java
new file mode 100644
index 0000000000..4564acc9d0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java
@@ -0,0 +1,217 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * Schema Response message handler.
+ * This handler is responsible to process 'S'(opcode) messages sent by the management broker containing the full
+ * schema details for a class.
+ *
+ * @author Andrea Gazzarini
+ */
+public class SchemaResponseMessageHandler extends BaseMessageHandler
+{
+ /**
+ * Behavioural interface for classes that are responsible to deal with schema messages.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface IProcessor
+ {
+ /**
+ * Processes the incoming message using the given decoder.
+ *
+ * @param decoder the decoder used for dealing with incoming message.
+ */
+ void process(Decoder decoder);
+ }
+
+ /**
+ * Processor responsible to deal with class schema related messages.
+ */
+ final IProcessor _classSchemaProcessor = new IProcessor()
+ {
+ public void process(Decoder decoder)
+ {
+ try
+ {
+ String packageName = decoder.readStr8();
+ String className = decoder.readStr8();
+
+ Binary schemaHash = new Binary(decoder.readBin128());
+
+ int howManyProperties = decoder.readUint16();
+ int howManyStatistics = decoder.readUint16();
+ int howManyMethods = decoder.readUint16();
+
+ _domainModel.addSchema(
+ packageName,
+ className,
+ schemaHash,
+ getAttributes(decoder, howManyProperties),
+ getAttributes(decoder, howManyStatistics),
+ getMethods(decoder, howManyMethods));
+ } catch(Exception exception)
+ {
+ _logger.error(exception,Messages.QMAN_100005_CLASS_SCHEMA_PROCESSING_FAILURE);
+ }
+ }
+ };
+
+ /**
+ * Processor responsible to deal with class event related messages.
+ */
+ final IProcessor _eventSchemaProcessor = new IProcessor()
+ {
+ public void process(Decoder decoder)
+ {
+ try
+ {
+ String packageName = decoder.readStr8();
+ String className = decoder.readStr8();
+ Binary hash = new Binary(decoder.readBin128());
+ int howManyArguments = decoder.readUint16();
+
+ _domainModel.addEventSchema(
+ packageName,
+ className,
+ hash,
+ getAttributes(decoder, howManyArguments));
+ } catch(Exception exception)
+ {
+ _logger.error(exception,Messages.QMAN_100006_EVENT_SCHEMA_PROCESSING_FAILURE);
+ }
+ }
+ };
+
+ /**
+ * Processes an incoming schema response.
+ * This will be used for building the corresponding class definition.
+ *
+ * @param decoder the decoder used for parsing the incoming stream.
+ * @param sequenceNumber the sequence number of the incoming message.
+ */
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ try
+ {
+ int classKind = decoder.readUint8();
+ switch(classKind)
+ {
+ case Protocol.CLASS :
+ {
+ _classSchemaProcessor.process(decoder);
+ break;
+ }
+ case Protocol.EVENT :
+ {
+ _eventSchemaProcessor.process(decoder);
+ break;
+ }
+ default :
+ {
+ _logger.error(Messages.QMAN_100011_UNKNOWN_CLASS_KIND,classKind);
+ }
+ }
+ } catch(Exception exception)
+ {
+ _logger.error(exception,Messages.QMAN_100012_SCHEMA_MESSAGE_PROCESSING_FAILURE);
+ }
+ }
+
+ /**
+ * Reads from the incoming message stream the properties definitions.
+ *
+ * @param decoder the decoder used for decode incoming data.
+ * @param howManyProperties the number of properties to read.
+ * @return a list of maps. Each map contains a property definition.
+ */
+ List<Map<String, Object>> getAttributes(Decoder decoder,int howMany)
+ {
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(howMany);
+ for (int i = 0; i < howMany; i++ )
+ {
+ result.add(decoder.readMap());
+ }
+ return result;
+ }
+
+ /**
+ * Reads the methods definitions from the incoming message stream.
+ *
+ * @param decoder the decoder used for decode incoming data.
+ * @param howManyMethods the number of methods to read.
+ * @return a list method definitions.
+ */
+ List<MethodOrEventDataTransferObject> getMethods(Decoder decoder, int howManyMethods)
+ {
+ List<MethodOrEventDataTransferObject> result = new ArrayList<MethodOrEventDataTransferObject>(howManyMethods);
+ for (int i = 0; i < howManyMethods; i++)
+ {
+ Map<String,Object> method = decoder.readMap();
+ int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME);
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String,Object>>(howManyArguments);
+ for (int argIndex = 0; argIndex < howManyArguments; argIndex++)
+ {
+ arguments.add(decoder.readMap());
+ }
+ result.add(new MethodOrEventDataTransferObject(method,arguments));
+ }
+ return result;
+ }
+
+ /**
+ * Reads the events definitions from the incoming message stream.
+ *
+ * @param decoder the decoder used for decode incoming data.
+ * @param howManyEvents the number of events to read.
+ * @return a list event definitions.
+ */
+ List<MethodOrEventDataTransferObject> getEvents(Decoder decoder, int howManyEvents)
+ {
+ List<MethodOrEventDataTransferObject> result = new ArrayList<MethodOrEventDataTransferObject>(howManyEvents);
+ for (int i = 0; i < howManyEvents; i++)
+ {
+ Map<String,Object> method = decoder.readMap();
+ int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME);
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String,Object>>(howManyArguments);
+ for (int argIndex = 0; argIndex < howManyArguments; argIndex++)
+ {
+ arguments.add(decoder.readMap());
+ }
+ result.add(new MethodOrEventDataTransferObject(method,arguments));
+ }
+ return result;
+ }
+ }
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java
new file mode 100644
index 0000000000..6d1426c122
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Enumeration for Access modes.
+ *
+ * @author Andrea Gazzarini
+ */
+public enum AccessMode
+{
+ RC { @Override public String toString() { return "Read-Create"; }},
+ RO { @Override public String toString() { return "Read-Only"; }},
+ RW { @Override public String toString() { return "Read-Write"; }}
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java
new file mode 100644
index 0000000000..8166c35eb6
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Enumeration of allowed method argument direction codes.
+ *
+ * @author Andrea Gazzarini
+ */
+public enum Direction
+{
+ I{ @Override public String toString() { return "Input"; }},
+ O{ @Override public String toString() { return "Output"; }},
+ IO{ @Override public String toString() { return "Input-Output"; }};
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java
new file mode 100644
index 0000000000..5a0ebaf1f7
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java
@@ -0,0 +1,239 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Broker domain model.
+ * This is the local representation of a remote broker domain model.
+ *
+ * @author Andrea Gazzarini
+ */
+public class DomainModel
+{
+ private final UUID _id;
+
+ /** Here the known packages of the remote broker are stored. */
+ Map<String,QpidPackage> _packages = new HashMap<String, QpidPackage>();
+
+ private Date _lastRefreshDate = new Date();
+
+ private IMethodInvocationListener _methodInvocationListener;
+
+ /**
+ * Builds a new domain model with the given broker identifier.
+ *
+ * @param brokerId the broker identifier.
+ */
+ public DomainModel(UUID brokerId)
+ {
+ this._id = brokerId;
+ }
+
+ /**
+ * Returns the identifier of the broker associated with this domain model.
+ *
+ * @return the identifier of the broker associated with this domain model.
+ */
+ public UUID getBrokerId()
+ {
+ return _id;
+ }
+
+ /**
+ * Adds the specified schema to this domain model.
+ *
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param classHash the class schema hash.
+ * @param properties the class properties.
+ * @param statistics the class statistics.
+ * @param methods the class methods.
+ * @throws UnableToBuildFeatureException
+ */
+ public void addSchema(
+ String packageName,
+ String className,
+ Binary classHash,
+ List<Map<String, Object>> properties,
+ List<Map<String, Object>> statistics,
+ List<MethodOrEventDataTransferObject> methods) throws UnableToBuildFeatureException
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.addClassDefinition(className,classHash,properties,statistics,methods);
+ }
+
+ /**
+ * Updates the last refresh date.
+ */
+ public void updateLastRefreshDate()
+ {
+ this._lastRefreshDate = new Date();
+ }
+
+ /**
+ * Returns the last refresh date.
+ *
+ * @return the last refresh date.
+ */
+ public Date getLastRefreshDate()
+ {
+ return _lastRefreshDate;
+ }
+
+ /**
+ * Adds the specified schema to this domain model.
+ *
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param classHash the class schema hash.
+ * @param properties the class properties.
+ * @param statistics the class statistics.
+ * @param methods the class methods.
+ * @throws UnableToBuildFeatureException
+ */
+ public void addEventSchema(
+ String packageName,
+ String className,
+ Binary classHash,
+ List<Map<String, Object>> arguments) throws UnableToBuildFeatureException
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.addEventDefinition(className,classHash,arguments);
+ }
+
+ /**
+ * Gets the package with the specified name.
+ * Note that if the package doesn't exist a new one will be created and returned.
+ *
+ * @param packageName the name of the package.
+ * @return the package.
+ */
+ QpidPackage getPackageByName (String packageName)
+ {
+ QpidPackage qpidPackage = _packages.get(packageName);
+ if (qpidPackage == null)
+ {
+ qpidPackage = new QpidPackage(packageName,this);
+ _packages.put(packageName, qpidPackage);
+ }
+ return qpidPackage;
+ }
+
+ /**
+ * Returns true if a package with the specified name already exists on this domain model.
+ *
+ * @param packageName the name of the package.
+ * @return true if the package exists, false otherwise.
+ */
+ boolean containsPackage (String packageName)
+ {
+ return _packages.containsKey(packageName);
+ }
+
+ /**
+ * Adds the given instrumentation data (raw format) to this domain model.
+ * Note that this data is belonging to a specific object instance.
+ *
+ * @param packageName the name of the ower package.
+ * @param className the name of the owner class.
+ * @param classHash the schema hash for this class.
+ * @param objectId the object instance identifier.
+ * @param rawData the instrumentation data.
+ */
+ public void addInstrumentationRawData (String packageName, String className,Binary classHash, Binary objectId, byte[] rawData)
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.setObjectInstanceInstrumentationRawData(className,classHash,objectId,rawData);
+ }
+
+ public void addEventRawData (
+ String packageName,
+ String eventName,
+ Binary eventHash,
+ byte[] rawData,
+ long currentTimestamp,
+ int severity)
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.setEventInstanceRawData(eventName,eventHash,rawData,currentTimestamp,severity);
+ }
+
+ /**
+ * Adds the given configuration data (raw format) to this domain model.
+ * Note that this data is belonging to a specific object instance.
+ *
+ * @param packageName the name of the ower package.
+ * @param className the name of the owner class.
+ * @param classHash the schema hash for this class.
+ * @param objectId the object instance identifier.
+ * @param rawData the configuration data.
+ */
+ public void addConfigurationRawData (String packageName, String className, Binary classHash,Binary objectId, byte[] rawData)
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.setObjectInstanceConfigurationRawData(className,classHash,objectId,rawData);
+ }
+
+ /**
+ * Removes the object instance associated to the given parameters.
+ *
+ * @param packageName the owner package.
+ * @param className the class definition of the object instance.
+ * @param classHash the class hash
+ * @param objectId the object identifier.
+ */
+ public void removeObjectInstance (String packageName, String className, Binary classHash, Binary objectId)
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.removeObjectInstance(className, classHash, objectId);
+ }
+
+ /**
+ * Releases all the resources kept by domain model entitiies.
+ */
+ public void releaseResources()
+ {
+ for (QpidPackage qpidPackage : _packages.values())
+ {
+ qpidPackage.releaseResources();
+ }
+ }
+
+ public void setMethodInvocationListener(IMethodInvocationListener listener)
+ {
+ this._methodInvocationListener = listener;
+ }
+
+ IMethodInvocationListener getMethodInvocationListener ()
+ {
+ return _methodInvocationListener;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java
new file mode 100644
index 0000000000..1ede559145
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+/**
+ * Interface definition for attribute validators.
+ *
+ * @author Andrea Gazzarini
+ */
+interface IValidator
+{
+ /**
+ * Validates the given value according to the rules definied by this validator.
+ *
+ * @param value the value be checked.
+ *
+ * @throws ValidationException when the value is violating validator's rules.
+ */
+ void validate(Object value) throws ValidationException;
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java
new file mode 100644
index 0000000000..d84a018346
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+import java.util.EventObject;
+import java.util.concurrent.BlockingQueue;
+
+import org.apache.qpid.management.domain.handler.impl.InvocationResult;
+
+/**
+ * Operation invocation event.
+ * This encapsulates all the information that a method invocation listener needs to know about an operation which is
+ * going to be invoked.
+ *
+ * @author Andrea Gazzarini
+ */
+public class InvocationEvent extends EventObject
+{
+ private static final long serialVersionUID = 240229490753008597L;
+
+ private final int _sequenceNumber;
+ private final BlockingQueue<InvocationResult> _exchangeChannel;
+
+ /**
+ * Builds a new invocation event with the given data.
+ *
+ * @param source the event source.
+ * @param sequenceNumber the sequence number of the method invocation.
+ * @param exchangeChannel the exchange channel for synchronous communication.
+ */
+ InvocationEvent(Object source, int sequenceNumber, BlockingQueue<InvocationResult> exchangeChannel)
+ {
+ super(source);
+ this._sequenceNumber = sequenceNumber;
+ this._exchangeChannel = exchangeChannel;
+ }
+
+ /**
+ * Returns the sequence number that will be / has been used for method invocation.
+ *
+ * @return the sequence number that will be / has been used for method invocation.
+ */
+ public int getSequenceNumber()
+ {
+ return _sequenceNumber;
+ }
+
+ /**
+ * Returns the exchange channel that will be used between event source and event listener for synchronous
+ * communication.
+ *
+ * @return the exchange channel that will be used for synchronous communication.
+ */
+ public BlockingQueue<InvocationResult> getExchangeChannel()
+ {
+ return _exchangeChannel;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java
new file mode 100644
index 0000000000..657d7e6210
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java
@@ -0,0 +1,410 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.lang.management.ManagementFactory;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.model.QpidClass.QManManagedObject;
+import org.apache.qpid.management.domain.model.QpidEvent.QManManagedEvent;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.domain.services.QMan;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * A simple facade used to perform operations on Mbean server.
+ */
+public class JmxService
+{
+ private final static Logger LOGGER = Logger.get(JmxService.class);
+ MBeanServer _mxServer = ManagementFactory.getPlatformMBeanServer();
+
+ /**
+ * Registers QMan with the MBeanServer.
+ * After that QMan management interface will be JMX-exposed.
+ *
+ * @param qman QMan
+ * @throws MBeanException when some error occurs during registration.
+ */
+ public void registerQManService(QMan qman) throws MBeanException
+ {
+ if (!_mxServer.isRegistered(Names.QMAN_OBJECT_NAME))
+ {
+ try {
+ _mxServer.registerMBean(qman, Names.QMAN_OBJECT_NAME);
+ } catch (Exception exception) {
+ throw new MBeanException(exception);
+ }
+ }
+ }
+
+ /**
+ * Registers an event instance with MBean server.
+ *
+ * @param eventInstance the mben event instance
+ * @param brokerId the broker identifier.
+ * @param packageName the package name.
+ * @param eventClassName the event class name.
+ * @return the object name used for registration.
+ */
+ ObjectName registerEventInstance(
+ QManManagedEvent eventInstance,
+ UUID brokerId,
+ String packageName,
+ String eventClassName)
+ {
+ ObjectName name = createEventName(brokerId, packageName, eventClassName);
+ if (!_mxServer.isRegistered(name))
+ {
+ try
+ {
+ _mxServer.registerMBean(eventInstance, name);
+
+ LOGGER.debug(
+ Messages.QMAN_200010_EVENT_MBEAN_REGISTERED,
+ brokerId,
+ packageName,
+ eventClassName,
+ name);
+ } catch (Exception exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+ return name;
+}
+
+ /**
+ * Registers a pre-existing object instance as an MBean with the MBean
+ * server.
+ *
+ * @param instance the object instance.
+ * @param brokerId the broker identifier.
+ * @param packageName the name of the package containing this instance.
+ * @param className the name of the owner class of this instance.
+ * @param objectId the object instance identifier.
+ * @return the object name used for registration.
+ */
+ ObjectName registerObjectInstance(
+ QManManagedObject instance,
+ UUID brokerId,
+ String packageName,
+ String className,
+ Binary objectId)
+ {
+ ObjectName name = createObjectName(brokerId, packageName, className, objectId);
+ if (!_mxServer.isRegistered(name))
+ {
+ try
+ {
+ _mxServer.registerMBean(instance, name);
+
+ LOGGER.debug(
+ Messages.QMAN_200011_OBJECT_MBEAN_REGISTERED,
+ brokerId,
+ packageName,
+ className,
+ objectId,
+ name);
+ } catch (Exception exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Removes / unregisters a managed object instance from the MBean Server.
+ *
+ * @param brokerId the broker identifier.
+ * @param packageName the name of the package containing this instance.
+ * @param className the name of the owner class of this instance.
+ * @param objectId the object instance identifier.
+ * @return obejctName the obejct name used for deregistration.
+ */
+ ObjectName unregisterObjectInstance(
+ UUID brokerId,
+ String packageName,
+ String className,
+ Binary objectId)
+ {
+ ObjectName name = createObjectName(brokerId, packageName, className, objectId);
+ if (_mxServer.isRegistered(name))
+ {
+ try
+ {
+ _mxServer.unregisterMBean(name);
+
+ LOGGER.debug(
+ Messages.QMAN_200012_OBJECT_MBEAN_UNREGISTERED,
+ brokerId,
+ packageName,
+ className,
+ objectId,
+ name);
+ } catch (Exception exception)
+ {
+ LOGGER.error(exception,Messages.QMAN_100013_MBEAN_REGISTRATION_FAILURE,name);
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Removes (unregister) all events from MBean Server.
+ */
+ void unregisterEvents()
+ {
+ for (ObjectName name : getEventMBeans())
+ {
+ try
+ {
+ _mxServer.unregisterMBean(name);
+ } catch(Exception ignore)
+ {
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ Set<ObjectName> getEventMBeans()
+ {
+ return _mxServer.queryNames(createEventSearchName(),null);
+ }
+
+ /**
+ * Removes (unregister) all object instances from MBean Server.
+ */
+ @SuppressWarnings("unchecked")
+ void unregisterObjectInstances()
+ {
+ Set<ObjectName> names = _mxServer.queryNames(createObjectInstanceSearchName(),null);
+ for (ObjectName name : names)
+ {
+ try
+ {
+ _mxServer.unregisterMBean(name);
+ } catch(Exception ignore)
+ {
+ }
+ }
+ }
+
+ /**
+ * Factory method for ObjectNames.
+ *
+ * @param brokerId the broker identifier.
+ * @param packageName the name of the package containing this instance.
+ * @param className the name of the owner class of this instance.
+ * @param objectId the object instance identifier.
+ * @return the object name built according to the given parameters.
+ */
+ private ObjectName createObjectName(UUID brokerId, String packageName, String className, Binary objectId)
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(':')
+ .append(Names.BROKER_ID)
+ .append('=')
+ .append(brokerId)
+ .append(",type=Object,")
+ .append(Names.PACKAGE)
+ .append('=')
+ .append(packageName)
+ .append(',')
+ .append(Names.CLASS)
+ .append('=')
+ .append(className)
+ .append(',')
+ .append(Names.OBJECT_ID)
+ .append('=')
+ .append(objectId)
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ /**
+ * Creates an object name that will be used for searching all registered events.
+ *
+ * @return the object name that will be used for searching all registered events.
+ */
+ ObjectName createEventSearchName()
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(':')
+ .append('*')
+ .append(",type=Event")
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ /**
+ * Creates an object name that will be used for searching all registered events.
+ *
+ * @return the object name that will be used for searching all registered events.
+ */
+ ObjectName createClassDefinitionSearchName()
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(":Category=Schema,*")
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ /**
+ * Creates an object name that will be used for searching all registered object instances.
+ *
+ * @return the object name that will be used for searching all registered object instances.
+ */
+ private ObjectName createObjectInstanceSearchName()
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(':')
+ .append('*')
+ .append(",type=Object")
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ /**
+ * Factory method for ObjectNames.
+ *
+ * @param brokerId the broker identifier.
+ * @param packageName the name of the package containing this instance.
+ * @param className the name of the owner class of this instance.
+ * @return the object name built according to the given parameters.
+ */
+ private ObjectName createEventName(UUID brokerId, String packageName, String className)
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(':')
+ .append(Names.BROKER_ID)
+ .append('=')
+ .append(brokerId)
+ .append(",type=Event,")
+ .append(Names.PACKAGE)
+ .append('=')
+ .append(packageName)
+ .append(',')
+ .append(Names.CLASS)
+ .append('=')
+ .append(className)
+ .append(',')
+ .append(Names.OBJECT_ID)
+ .append('=')
+ .append(UUID.randomUUID())
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ ObjectName createEntityDefinitionName(String packageName, String className, String type)
+ {
+ String asString = new StringBuilder()
+ .append(Names.DOMAIN_NAME)
+ .append(':')
+ .append("Category=Schema,Type=")
+ .append(type)
+ .append(",package=")
+ .append(packageName)
+ .append(",name=")
+ .append(className)
+ .toString();
+ try
+ {
+ return new ObjectName(asString);
+ } catch (MalformedObjectNameException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ public void registerEntityDefinition(ObjectName name, QpidEntity entity,String packageName, String className)
+ {
+ try
+ {
+ if (!_mxServer.isRegistered(name))
+ _mxServer.registerMBean(entity, name);
+ _mxServer.addNotificationListener(name, Names.QMAN_OBJECT_NAME, null, null);
+ } catch(Exception exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void unregisterClassDefinitions()
+ {
+ Set<ObjectName> names = _mxServer.queryNames(createClassDefinitionSearchName(),null);
+ for (ObjectName name : names)
+ {
+ try
+ {
+ _mxServer.unregisterMBean(name);
+ } catch(Exception ignore)
+ {
+ }
+ }
+
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java
new file mode 100644
index 0000000000..160054059b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+import java.util.List;
+
+import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute;
+
+public class MissingFeatureAttributesException extends UnableToBuildFeatureException
+{
+ private static final long serialVersionUID = 671471705085787235L;
+
+ public MissingFeatureAttributesException(List<Attribute> missingAttributeList)
+ {
+ super(String.valueOf(missingAttributeList));
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java
new file mode 100644
index 0000000000..e126fcb8f5
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java
@@ -0,0 +1,123 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.transport.codec.Encoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * An argument is the formal definition of a parameter belonging to a specific method / operation.
+ */
+class QpidArgument extends QpidProperty
+{
+ private final static Logger LOGGER = Logger.get(QpidArgument.class);
+
+ private Object _defaultValue;
+
+ private Direction _direction;
+
+ /**
+ * Sets the direction of this argument.
+ *
+ * @param the direction of this argument.
+ */
+ public void setDirection(String code)
+ {
+ this._direction = Direction.valueOf(code);
+ }
+
+ /**
+ * Returns the direction of this argument.
+ *
+ * @return the direction of this argument.
+ */
+ public Direction getDirection()
+ {
+ return _direction;
+ }
+
+ /**
+ * Sets the default value of this argument.
+ *
+ * @param defaultValue the default value of this argument.
+ */
+ public void setDefaultValue(Object defaultValue)
+ {
+ this._defaultValue = defaultValue;
+ }
+
+ /**
+ * Returns the default value of this argument.
+ *
+ * @return the default value of this argument.
+ */
+ public Object getDefaultValue()
+ {
+ return _defaultValue;
+ }
+
+ /**
+ * Returns true if this is an Input argument.
+ *
+ * @return true if this is an Input argument.
+ */
+ public boolean isInput()
+ {
+ return _direction != Direction.O;
+ }
+
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder()
+ .append(getJavaType().getName())
+ .append(' ')
+ .append(_name)
+ .append("(")
+ .append(_direction)
+ .append(")")
+ .toString();
+ }
+
+ /**
+ * Encodes the given value according to this argument type & definition.
+ *
+ * @param value the value to be encoded.
+ * @param encoder the encoder.
+ */
+ public void encode(Object value,Encoder encoder)
+ {
+ _type.encode(value, encoder);
+ LOGGER.debug(Messages.QMAN_200013_ARGUMENT_VALUE_ENCODED,value,_name,_type);
+ }
+
+ /**
+ * Decodes the value for this argument according to its type & definition.
+ *
+ * @param decoder the decoder
+ * @return the decoded value of this argument.
+ */
+ public Object decode(org.apache.qpid.transport.codec.Decoder decoder)
+ {
+ return _type.decode(decoder);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java
new file mode 100644
index 0000000000..6712a14075
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.domain.model.type.Type;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Layer supertype for qpid properties and statistics.
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidAttribute extends QpidFeature
+{
+ private final static Logger LOGGER = Logger.get(QpidAttribute.class);
+
+ /** feature type */
+ protected Type _type;
+
+ /** feature unit */
+ protected String _unit;
+
+ /**
+ * Returns the units used for numeric values (i.e. seconds, bytes, etc.)
+ *
+ * @return the units used for numeric values (i.e. seconds, bytes, etc.)
+ */
+ String getUnit ()
+ {
+ return _unit;
+ }
+
+ /**
+ * Sets the unit for this property.
+ *
+ * @param unit the unit of this property.
+ */
+ void setUnit (String unit)
+ {
+ this._unit = unit;
+ }
+
+ /**
+ * Returns the java type (class) of this feature.
+ *
+ * @return the java type (class) of this feature.
+ */
+ Class<?> getJavaType ()
+ {
+ return _type.getJavaType();
+ }
+
+ /**
+ * Sets the type of this feature.
+ *
+ * @param type the type of this feature.
+ */
+ void setType (Type type)
+ {
+ this._type = type;
+ }
+
+ /**
+ * Gets the value of this feature according to its type definition.
+ *
+ * @param decoder the decoder used to extract the value.
+ * @return the value of this feature according to its type definition
+ */
+ Object decodeValue(Decoder decoder)
+ {
+ try {
+ return _type.decode(decoder);
+ } catch(RuntimeException exception)
+ {
+ LOGGER.error(exception,Messages.QMAN_100014_ATTRIBUTE_DECODING_FAILURE,this);
+ throw exception;
+ }
+ }
+
+ @Override
+ public String toString ()
+ {
+ return super.toString()+",type="+_type;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java
new file mode 100644
index 0000000000..667e600668
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java
@@ -0,0 +1,833 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Map.Entry;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener;
+import org.apache.qpid.management.domain.handler.impl.InvocationResult;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.domain.services.SequenceNumberGenerator;
+import org.apache.qpid.management.jmx.EntityLifecycleNotification;
+import org.apache.qpid.management.jmx.OperationHasBeenInvokedNotification;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid Class definition.
+ * A type definition for a manageable object.
+ * This class is also responsible to manage incoming obejct instance data (configuration & instrumentation).
+ * How can we handle data before schema is injected into this class? simply we must retain that data in raw format.
+ * This class has 3 states :
+ * 1) first state is when schema is not yet injected. In this case the incoming object data is retained as is (in raw format)
+ * and a schema request is sent;
+ * 2) second state is when schema has been requested but not yet injected. The incoming object data is still retained as is
+ * (in raw format)
+ * 3) third state is when schema is injected. Each injection of data will result in an update / create / delete of
+ * the corresponding object instance. In addition, the first time the state change, the old retained raw data is cnverted in
+ * object instance(s).
+ */
+class QpidClass extends QpidEntity implements QpidClassMBean
+{
+ /**
+ * State interface for this class definition.
+ * Each state is responsible to handle the injection of the data and / or schema.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface State
+ {
+ /**
+ * Adds configuration data for the object instance associated to the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the raw configuration data.
+ */
+ void addInstrumentationData (Binary objectId, byte[] rawData);
+
+ /**
+ * Adds instrumentation data for the object instance associated to the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the raw instrumentation data.
+ */
+ void addConfigurationData (Binary objectId, byte[] rawData);
+
+ /**
+ * Inject the schema into this class definition.
+ *
+ * @param propertyDefinitions
+ * @param statisticDefinitions
+ * @param methodDefinitions
+ * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException;
+ };
+
+ /**
+ * This is the initial state of every qpid class.
+ * The class definition instance is created but its schema has not been injected.
+ * Incoming configuration & instrumentation data will be stored in raw format because we don't know how to
+ * parse it until the schema arrives.
+ * In addition, this state is responsible (when data arrives) to request its schema.
+ */
+ final State _schemaNotRequested = new State() {
+
+ /**
+ * Stores the incoming data in raw format and request the schema for this class.
+ * After that a transition to the next state is made.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming configuration data.
+ */
+ public synchronized void addConfigurationData (Binary objectId, byte[] rawData)
+ {
+ try
+ {
+ requestSchema();
+ _state = _schemaRequestedButNotYetInjected;
+ } catch (Exception exception)
+ {
+ _logger.error(
+ exception,
+ Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST,
+ _parent.getName(),
+ _name);
+ } finally {
+ QManManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawConfigurationData.add(rawData);
+ }
+ }
+
+ /**
+ * Stores the incoming data in raw format and request the schema for this class.
+ * After that a transition to the next state is made.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming instrumentation data.
+ */
+ public synchronized void addInstrumentationData (Binary objectId, byte[] rawData)
+ {
+ try
+ {
+ requestSchema();
+ _state = _schemaRequestedButNotYetInjected;
+ } catch (Exception e)
+ {
+ _logger.error(
+ Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST,
+ _parent.getName(),
+ _name);
+ } finally {
+ QManManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawConfigurationData.add(rawData);
+ }
+ }
+
+ /**
+ * This method only throws an illegal state exception because when a schema arrives
+ * this state is no longer valid.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException
+ {
+ throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state.");
+ }
+ };
+
+ /**
+ * This is the first state of this class definition : the schema is not yet injected so each injection of object data will be
+ * retained in raw format.
+ */
+ final State _schemaRequestedButNotYetInjected = new State()
+ {
+ /**
+ * Stores the incoming data in raw format.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming configuration data.
+ */
+ public void addConfigurationData (Binary objectId, byte[] rawData)
+ {
+ QManManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawConfigurationData.add(rawData);
+ }
+
+ /**
+ * Stores the incoming data in raw format.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming instrumentation data.
+ */
+ public void addInstrumentationData (Binary objectId, byte[] rawData)
+ {
+ QManManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawInstrumentationData.add(rawData);
+ }
+
+ /**
+ * When a schema is injected into this defintiion the following should happen :
+ * 1) the incoming schema is parsed and the class definition is built;
+ * 2) the retained raw data is converted into object instance(s)
+ * 3) the internal state of this class changes;
+ *
+ * If someting is wrong during that process the schema is not built and the state don't change.
+ */
+ public synchronized void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException
+ {
+
+ MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[propertyDefinitions.size()+statisticDefinitions.size()];
+ MBeanOperationInfo [] operationsMetadata = new MBeanOperationInfo[methodDefinitions.size()];
+
+ buildAttributes(propertyDefinitions,statisticDefinitions,attributesMetadata);
+ buildMethods(methodDefinitions,operationsMetadata);
+
+ _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,operationsMetadata,null);
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.SCHEMA_INJECTED_NOTIFICATION_TYPE,
+ _parent.getName(),
+ _name,
+ Names.CLASS,
+ _objectName);
+
+ sendNotification(notification);
+
+ // Converting stored object instances into JMX MBean and removing raw instance data.
+ for (Entry<Binary, QManManagedObject> instanceEntry : _objectInstances.entrySet())
+ {
+ Binary objectId = instanceEntry.getKey();
+ QManManagedObject instance = instanceEntry.getValue();
+
+ for (Iterator<byte[]> iterator = instance._rawInstrumentationData.iterator(); iterator.hasNext();)
+ {
+ updateInstanceWithInstrumentationData(instance,iterator.next());
+ iterator.remove();
+ }
+
+ for (Iterator<byte[]> iterator = instance._rawConfigurationData.iterator(); iterator.hasNext();)
+ {
+ updateInstanceWithConfigurationData(instance, iterator.next());
+ iterator.remove();
+ }
+
+ registerMBean(instance,_parent.getOwnerId(),_parent.getName(),_name,objectId);
+ }
+ _state = _schemaInjected;
+
+ }
+ };
+
+ /**
+ * After a schema is built into this definition this is the current state of the class.
+ */
+ final State _schemaInjected = new State()
+ {
+ /**
+ * Updates the configuration state of the object instance associates with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the configuration data (raw format).
+ */
+ public void addConfigurationData (Binary objectId, byte[] rawData)
+ {
+ QManManagedObject instance = getObjectInstance(objectId,true);
+ updateInstanceWithConfigurationData(instance, rawData);
+ }
+
+ /**
+ * Updates the instrumentation state of the object instance associates with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the instrumentation data (raw format).
+ */
+ public void addInstrumentationData (Binary objectId, byte[] rawData)
+ {
+ QManManagedObject instance = getObjectInstance(objectId,true);
+ updateInstanceWithInstrumentationData(instance, rawData);
+ }
+
+ /**
+ * Never called when the class definition has this state.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException
+ {
+ throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state.");
+ }
+ };
+
+ /**
+ * MBean used for representing remote broker object instances.
+ * This is the core component of the QMan domain model
+ */
+ class QManManagedObject extends QManManagedEntity implements MBeanRegistration
+ {
+ private Binary _objectId;
+
+ // Arrays used for storing raw data before this mbean is registered to mbean server.
+ List<byte[]> _rawInstrumentationData = new ArrayList<byte[]>();
+ List<byte[]> _rawConfigurationData = new ArrayList<byte[]>();
+
+ /**
+ * Builds a new managed object with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ */
+ QManManagedObject(Binary objectId)
+ {
+ this._objectId = objectId;
+ }
+
+ /**
+ * Returns the value of the given attribute.s
+ *
+ * @throws AttributeNotFoundException when no attribute is found with the given name.
+ */
+ public Object getAttribute (String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException
+ {
+ if (attributeName == null)
+ {
+ throw new RuntimeOperationsException(new IllegalArgumentException("attribute name must not be null"));
+ }
+
+ if (_properties.containsKey(attributeName) || _statistics.containsKey(attributeName))
+ {
+ return _attributes.get(attributeName);
+ } else
+ {
+ throw new AttributeNotFoundException(attributeName);
+ }
+ }
+
+ /**
+ * Executes an operation on this object instance.
+ *
+ * @param actionName the name of the method.
+ * @param params the method parameters
+ * @param signature the method signature.
+ */
+ public Object invoke (String actionName, Object[] params, String[] signature) throws MBeanException,ReflectionException
+ {
+ OperationHasBeenInvokedNotification notification = null;
+ try
+ {
+ QpidMethod method = _methods.get(actionName);
+ if (method != null)
+ {
+ try
+ {
+ method.validate(params);
+ InvocationResult result = invokeMethod(_objectId, method, params);
+ notification = new OperationHasBeenInvokedNotification(actionName,params,signature,result);
+ return result;
+ } catch (Exception ex)
+ {
+ MBeanException exception = new MBeanException(ex);
+ notification = new OperationHasBeenInvokedNotification(actionName,params,signature,exception);
+ throw exception;
+ }
+ } else
+ {
+ ReflectionException exception = new ReflectionException(new NoSuchMethodException(actionName));
+ notification = new OperationHasBeenInvokedNotification(actionName,params,signature,exception);
+ throw exception;
+ }
+ } finally
+ {
+ sendNotification(notification);
+ }
+ }
+
+ /**
+ * Sets the value of the given attribute on this object instance.
+ *
+ * @param attribute contains the new value of the attribute.
+ * @throws AttributeNotFoundException when the given attribute is not found on this object instance.
+ * @throws InvalidAttributeValueException when the given value is violating one attribute invariant.
+ */
+ public void setAttribute (Attribute attribute) throws AttributeNotFoundException,
+ InvalidAttributeValueException, MBeanException, ReflectionException
+ {
+ QpidProperty property = _properties.get(attribute.getName());
+ try
+ {
+ property.validate(attribute.getValue());
+ } catch(ValidationException exception)
+ {
+ throw new InvalidAttributeValueException(exception.getMessage());
+ }
+ throw new RuntimeException("Not yet implemented.");
+ }
+
+ /**
+ * Sets the values of several attributes of this MBean.
+ *
+ * @param attributes a list of attributes: The identification of the attributes to be set and the values they are to be set to.
+ * @return The list of attributes that were set, with their new values.
+ */
+ public AttributeList setAttributes (AttributeList attributes)
+ {
+ throw new RuntimeException("Not yet implemented.");
+ }
+
+ /**
+ * MBean server callback after deregistration.
+ */
+ public void postDeregister ()
+ {
+ }
+
+ /**
+ * After the object is registered the raw data is set to null.
+ * This is done because we no longer need this data : it has already been
+ * injected into this object instance.
+ *
+ * @param registrationDone a flag indicating if the instance has been registered to mbean server.
+ */
+ public void postRegister (Boolean registrationDone)
+ {
+ if (registrationDone)
+ {
+ _rawConfigurationData = null;
+ _rawInstrumentationData = null;
+ }
+ }
+
+ /**
+ * MBean server callback before deregistration.
+ */
+ public void preDeregister () throws Exception
+ {
+ }
+
+ /**
+ * MBean server callback before registration.
+ */
+ public ObjectName preRegister (MBeanServer server, ObjectName name) throws Exception
+ {
+ return name;
+ }
+ }
+
+ Map<String, QpidProperty> _properties = new HashMap<String, QpidProperty>();
+ Map<String, QpidStatistic> _statistics = new HashMap<String, QpidStatistic>();
+ private Map<String, QpidMethod> _methods = new HashMap<String, QpidMethod>();
+
+ private List<QpidProperty> _schemaOrderedProperties = new ArrayList<QpidProperty>();
+ private List<QpidStatistic> _schemaOrderedStatistics= new ArrayList<QpidStatistic>();
+
+ private int _howManyPresenceBitMasks;
+ private BlockingQueue<InvocationResult> _exchangeChannelForMethodInvocations;
+ private final IMethodInvocationListener _methodInvocationListener;
+
+ Map<Binary, QManManagedObject> _objectInstances = new HashMap<Binary, QManManagedObject>();
+ State _state = _schemaNotRequested;;
+
+ private final static class Log
+ {
+ private final static Logger LOGGER = Logger.get(QpidClass.class);
+ final static void logMethodInvocationResult(InvocationResult result)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(String.valueOf(result));
+ }
+ }
+ }
+
+ /**
+ * Builds a new class with the given name and package as parent.
+ *
+ * @param className the name of the class.
+ * @param hash the class schema hash.
+ * @param parentPackage the parent of this class.
+ */
+ QpidClass(String className, Binary hash, QpidPackage parentPackage)
+ {
+ super(className,hash, parentPackage,Names.CLASS);
+ this._methodInvocationListener = _parent.getMethodInvocationListener();
+ this._exchangeChannelForMethodInvocations = new SynchronousQueue<InvocationResult>();
+ }
+
+ /**
+ * Adds the configuration data for the object instance associated to the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the raw configuration data.
+ */
+ void addInstrumentationData (Binary objectId, byte[] rawData)
+ {
+ _logger.debug(
+ Messages.QMAN_200014_INCOMING_INSTRUMENTATION_DATA,
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name,
+ objectId);
+ _state.addInstrumentationData(objectId, rawData);
+ }
+
+ /**
+ * Adds the instrumentation data for the object instance associated to the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the raw instrumentation data.
+ */
+ void addConfigurationData (Binary objectId, byte[] rawData)
+ {
+ _logger.debug(
+ Messages.QMAN_200015_INCOMING_CONFIGURATION_DATA,
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name,
+ objectId);
+ _state.addConfigurationData(objectId, rawData);
+ }
+
+ /**
+ * Sets the schema for this class definition.
+ * A schema is basically a metadata description of all properties, statistics, methods and events of this class.
+ *
+ * @param propertyDefinitions properties metadata.
+ * @param statisticDefinitions statistics metadata.
+ * @param methodDefinitions methods metadata.
+ * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema.
+ */
+ void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException
+ {
+ _logger.info(Messages.QMAN_000010_INCOMING_SCHEMA,_parent.getOwnerId(),_parent.getName(),_name);
+ _state.setSchema(propertyDefinitions, statisticDefinitions, methodDefinitions);
+ }
+
+ /**
+ * Internal method used for building attributes definitions.
+ *
+ * @param props the map contained in the properties schema.
+ * @param stats the map contained in the statistics schema.
+ * @param attributes the management metadata for attributes.
+ * @throws UnableToBuildFeatureException when it's not possibile to build one attribute definition.
+ */
+ void buildAttributes (
+ List<Map<String, Object>> props,
+ List<Map<String, Object>> stats,
+ MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException
+ {
+ int index = 0;
+ int howManyOptionalProperties = 0;
+
+ for (Map<String, Object> propertyDefinition : props)
+ {
+ QpidFeatureBuilder builder = QpidFeatureBuilder.createPropertyBuilder(propertyDefinition);
+ builder.build();
+
+ QpidProperty property = (QpidProperty) builder.getQpidFeature();
+
+ howManyOptionalProperties += (property.isOptional()) ? 1 : 0;
+
+ _properties.put(property.getName(),property);
+ _schemaOrderedProperties.add(property);
+ attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature();
+
+ _logger.debug(
+ Messages.QMAN_200016_PROPERTY_DEFINITION_HAS_BEEN_BUILT,
+ _parent.getName(),
+ _name,
+ property);
+ }
+
+ _howManyPresenceBitMasks = (int)Math.ceil((double)howManyOptionalProperties / 8);
+
+ _logger.debug(
+ Messages.QMAN_200018_OPTIONAL_PROPERTIES_INFO,
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name,
+ _howManyPresenceBitMasks);
+
+ for (Map<String, Object> statisticDefinition : stats)
+ {
+ QpidFeatureBuilder builder = QpidFeatureBuilder.createStatisticBuilder(statisticDefinition);
+ builder.build();
+ QpidStatistic statistic = (QpidStatistic) builder.getQpidFeature();
+
+ _statistics.put(statistic.getName(),statistic);
+ _schemaOrderedStatistics.add(statistic);
+ attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature();
+
+ _logger.debug(
+ Messages.QMAN_200017_STATISTIC_DEFINITION_HAS_BEEN_BUILT,
+ _parent.getName(),
+ _name,
+ statistic);
+ }
+ }
+
+ /**
+ * Returns the object instance associated to the given identifier.
+ * Note that if the identifier is not associated to any obejct instance, a new one will be created.
+ *
+ * @param objectId the object identifier.
+ * @param registration a flag indicating whenever the (new ) instance must be registered with MBean server.
+ * @return the object instance associated to the given identifier.
+ */
+ QManManagedObject getObjectInstance(Binary objectId, boolean registration)
+ {
+ QManManagedObject objectInstance = _objectInstances.get(objectId);
+ if (objectInstance == null)
+ {
+ objectInstance = new QManManagedObject(objectId);
+ _objectInstances.put(objectId, objectInstance);
+ if (registration)
+ {
+ registerMBean(objectInstance,_parent.getOwnerId(),_parent.getName(),_name,objectId);
+ }
+ }
+ return objectInstance;
+ }
+
+ /**
+ * Internal method used for building method defintiions.
+ *
+ * @param definitions the properties map contained in the incoming schema.
+ * @param operationsMetadata
+ * @throws UnableToBuildFeatureException when it's not possibile to build one or more definitions.
+ */
+ void buildMethods (List<MethodOrEventDataTransferObject> definitions, MBeanOperationInfo[] operationsMetadata) throws UnableToBuildFeatureException
+ {
+ int index = 0;
+ for (MethodOrEventDataTransferObject definition: definitions)
+ {
+ QpidFeatureBuilder builder = QpidFeatureBuilder.createMethodBuilder(definition);
+ builder.build();
+ operationsMetadata [index++]= (MBeanOperationInfo) builder.getManagementFeature();
+ QpidMethod method = (QpidMethod) builder.getQpidFeature();
+ _methods.put(method.getName(),method);
+ }
+ }
+
+ /**
+ * Header (opcode='M')
+ * ObjectId of target object (128 bits)
+ * Package name (str8)
+ * Class name (str8)
+ * Class hash (bin128)
+ * Method name (str8) [as defined in the schema]
+ * Now encode all input ("I") and i/o (IO) arguments in the order in which they are defined in the schema.
+ * (i.e. make one pass over the argument list and encode arguments that are either input or inptu/output).
+
+ * @param objectId
+ * @param method
+ * @param parameters
+ * @throws Exception
+ */
+ private InvocationResult invokeMethod(Binary objectId,QpidMethod method,Object [] parameters) throws Exception
+ {
+ try
+ {
+ _service.connect();
+
+ int sequenceNumber = SequenceNumberGenerator.getNextSequenceNumber();
+ _methodInvocationListener.operationIsGoingToBeInvoked(new InvocationEvent(this,sequenceNumber,_exchangeChannelForMethodInvocations));
+ _service.invoke(_parent.getName(), _name, _hash,objectId,parameters, method,sequenceNumber,objectId.getBankId(),objectId.getBrokerId());
+
+ InvocationResult result = _exchangeChannelForMethodInvocations.poll(5000,TimeUnit.MILLISECONDS);
+
+ if (result == null)
+ {
+ throw new TimeoutException();
+ }
+
+ Map<String, Object> output = method.decodeParameters(result.getOutputAndBidirectionalArgumentValues());
+ result.setOutputSection(output);
+
+ Log.logMethodInvocationResult(result);
+
+ if (result.isException())
+ {
+ result.createAndThrowException();
+ }
+ return result;
+ } finally
+ {
+ _service.close();
+ }
+ }
+
+ /**
+ * Updates the given obejct instance with the given incoming configuration data.
+ *
+ * @param instance the managed object instance.
+ * @param rawData the incoming configuration data which contains new values for instance properties.
+ */
+ void updateInstanceWithConfigurationData(QManManagedObject instance,byte [] rawData)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(rawData));
+
+ byte [] presenceBitMasks = decoder.readBytes(_howManyPresenceBitMasks);
+ for (QpidProperty property : _schemaOrderedProperties)
+ {
+ try {
+ Object value = property.decodeValue(decoder,presenceBitMasks);
+ instance.createOrReplaceAttributeValue(property.getName(),value);
+ } catch(Exception ignore) {
+ _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,property.getName());
+ }
+ }
+ }
+
+ /**
+ * Updates the given object instance with the given incoming instrumentation data.
+ *
+ * @param instance the managed object instance.
+ * @param rawData the incoming instrumentation data which contains new values for instance properties.
+ */
+ void updateInstanceWithInstrumentationData(QManManagedObject instance,byte [] rawData)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(rawData));
+
+ for (QpidStatistic statistic : _schemaOrderedStatistics)
+ {
+ try {
+ Object value = statistic.decodeValue(decoder);
+ instance.createOrReplaceAttributeValue(statistic.getName(),value);
+ } catch(Exception ignore) {
+ _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,statistic.getName());
+ }
+ }
+ }
+
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder()
+ .append(_parent.getOwnerId())
+ .append("::")
+ .append(_parent.getName())
+ .append('.')
+ .append(_name)
+ .toString();
+ }
+
+ /**
+ * Removes the object instance associated to the given identifier.
+ *
+ * @param objectId the object identifier.
+ */
+ void removeObjectInstance (Binary objectId)
+ {
+ QManManagedObject toBeRemoved = _objectInstances.remove(objectId);
+ if (toBeRemoved != null)
+ {
+ ObjectName objectName = JMX_SERVICE.unregisterObjectInstance(_parent.getOwnerId(),_parent.getName(),_name,toBeRemoved._objectId);
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE,
+ _parent.getName(),
+ _name,
+ Names.CLASS,
+ objectName);
+
+ sendNotification(notification);
+ }
+ }
+
+ /**
+ * Deregisters all the object instances and release all previously acquired resources.
+ */
+ void releaseResources ()
+ {
+ _objectInstances.clear();
+ JMX_SERVICE.unregisterObjectInstances();
+ JMX_SERVICE.unregisterClassDefinitions();
+ _service.close();
+ }
+
+ /**
+ * Compose method used for registering mbean instance.
+ *
+ * @param instance the mbean instance.
+ * @param brokerId the broker identifier.
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param objectId the object identifier.
+ */
+ private void registerMBean(
+ QManManagedObject instance,
+ UUID brokerId,
+ String packageName,
+ String className,
+ Binary objectId)
+ {
+ ObjectName objectName = JMX_SERVICE.registerObjectInstance(instance,_parent.getOwnerId(),_parent.getName(),_name,objectId);
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE,
+ packageName,
+ className,
+ Names.CLASS,
+ objectName);
+
+ sendNotification(notification);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java
new file mode 100644
index 0000000000..eeb4e0e2d8
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Management interface for Qpid entity class..
+ */
+public interface QpidClassMBean
+{
+ /**
+ * Retruns the name of the class.
+ *
+ * @return the name of the class.
+ */
+ String getName();
+
+ /**
+ * Returns the name of the package.
+ *
+ * @return the name of the package.
+ */
+ String getPackageName();
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java
new file mode 100644
index 0000000000..ea0acb5fd1
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java
@@ -0,0 +1,184 @@
+package org.apache.qpid.management.domain.model;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.DynamicMBean;
+import javax.management.MBeanInfo;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.domain.services.QpidService;
+import org.apache.qpid.management.jmx.EntityLifecycleNotification;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Layer supertype for QMan entities.
+ */
+public abstract class QpidEntity extends NotificationBroadcasterSupport
+{
+ /**
+ * Layer supertype for QMan managed bean entities.
+ */
+ abstract class QManManagedEntity implements DynamicMBean
+ {
+ // After mbean is registered with the MBean server this collection holds the mbean attribute values.
+ Map<String,Object> _attributes = new HashMap<String, Object>();
+
+ /**
+ * Creates or replace the given attribute.
+ * Note that this is not part of the management interface of this object instance and therefore will be accessible only
+ * from within this class.
+ * It is used to update directly the object attributes bypassing jmx interface.
+ *
+ * @param attributeName the name of the attribute.
+ * @param property newValue the new value of the attribute.
+ */
+ void createOrReplaceAttributeValue(String attributeName, Object newValue)
+ {
+ _attributes.put(attributeName, newValue);
+ }
+
+ /**
+ * Get the values of several attributes of the Dynamic MBean.
+ *
+ * @param attributes A list of the attributes to be retrieved.
+ *
+ * @return The list of attributes retrieved.
+ */
+ public AttributeList getAttributes (String[] attributes)
+ {
+ if (attributes == null)
+ {
+ throw new RuntimeOperationsException(new IllegalArgumentException("Attributes array must not be null"));
+ }
+
+ AttributeList result = new AttributeList(attributes.length);
+ for (int i = 0; i < attributes.length; i++)
+ {
+ String attributeName = attributes[i];
+ try
+ {
+ result.add(new Attribute(attributeName,getAttribute(attributeName)));
+ } catch(Exception exception)
+ {
+ // Already logged.
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns metadata for this object instance.
+ */
+ // Developer Note : note that this metadata is a member of the outer class definition : in that way we create
+ // that metadata only once and then it will be shared between all object instances (it's a readonly object)
+ public MBeanInfo getMBeanInfo ()
+ {
+ return _metadata;
+ }
+ };
+
+ final Logger _logger = Logger.get(getClass());
+ final static JmxService JMX_SERVICE = new JmxService();
+
+ final String _name;
+ final Binary _hash;
+
+ final QpidPackage _parent;
+ MBeanInfo _metadata;
+ final QpidService _service;
+
+ protected ObjectName _objectName;
+
+ private final String _type;
+
+ /**
+ * Builds a new class with the given name and package as parent.
+ *
+ * @param className the name of the class.
+ * @param hash the class schema hash.
+ * @param parentPackage the parent of this class.
+ */
+ QpidEntity(String className, Binary hash, QpidPackage parentPackage,String type)
+ {
+ this._name = className;
+ this._parent = parentPackage;
+ this._hash = hash;
+ this._type = type;
+ this._service = new QpidService(_parent.getOwnerId());
+
+ _logger.debug(
+ Messages.QMAN_200020_ENTITY_DEFINITION_HAS_BEEN_BUILT,
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name);
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String getPackageName()
+ {
+ return _parent.getName();
+ }
+
+ /**
+ * Internal method used to send a schema request for this entity.
+ *
+ * @throws Exception when the request cannot be sent.
+ */
+ void requestSchema() throws Exception
+ {
+
+ _objectName = JMX_SERVICE.createEntityDefinitionName(_parent.getName(), _name,_type);
+ JMX_SERVICE.registerEntityDefinition(_objectName,this,_parent.getName(),_name);
+
+ try
+ {
+ _service.connect();
+ _service.requestSchema(_parent.getName(), _name, _hash);
+ _service.sync();
+ } finally
+ {
+ _service.close();
+ }
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.SCHEMA_REQUESTED_NOTIFICATION_TYPE,
+ _parent.getName(),
+ _name,
+ Names.CLASS,
+ _objectName);
+ sendNotification(notification);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java
new file mode 100644
index 0000000000..31d8d01fc9
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java
@@ -0,0 +1,493 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.jmx.EntityLifecycleNotification;
+import org.apache.qpid.transport.codec.BBDecoder;
+
+/**
+ * Qpid event definition.
+ */
+class QpidEvent extends QpidEntity implements QpidEventMBean
+{
+
+ /**
+ * State interface for this event definition.
+ * Each state is responsible to handle the injection of the data and / or schema.
+ */
+ interface State
+ {
+ /**
+ * Adds the given data for the object instance associated to the given object identifier.
+ *
+ * @param rawData the raw configuration data.
+ */
+ void addNewEventData (byte[] rawData, long currentTimestamp, int severity);
+
+ /**
+ * Inject the schema into this class definition.
+ *
+ * @param propertyDefinitions
+ * @param statisticDefinitions
+ * @param methodDefinitions
+ * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition.
+ */
+ public void setSchema (List<Map<String, Object>> agumentDefinitions) throws UnableToBuildFeatureException;
+ };
+
+
+ /**
+ * This is the initial state of every qpid class.
+ * The class definition instance is created but its schema has not been injected.
+ * Incoming configuration & instrumentation data will be stored in raw format because we don't know how to
+ * parse it until the schema arrives.
+ * In addition, this state is responsible (when data arrives) to request its schema.
+ */
+ final State _schemaNotRequested = new State() {
+
+ /**
+ * Stores the incoming data in raw format and request the schema for this class.
+ * After that a transition to the next state is made.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming configuration data.
+ */
+ public synchronized void addNewEventData (byte[] rawData, long currentTimestamp, int severity)
+ {
+ try
+ {
+ requestSchema();
+ _state = _schemaRequestedButNotYetInjected;
+ } catch (Exception exception)
+ {
+ _logger.error(
+ exception,
+ Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST,
+ _parent.getName(),
+ _name);
+ } finally {
+ createEventInstance(rawData,currentTimestamp,severity);
+ }
+ }
+
+ /**
+ * This method only throws an illegal state exception because when a schema arrives
+ * this state is no longer valid.
+ */
+ public void setSchema (List<Map<String, Object>> agumentDefinitions) throws UnableToBuildFeatureException
+ {
+ throw new IllegalStateException("When a schema arrives it's not possible for this event to be in this state.");
+ }
+ };
+
+ /**
+ * This is the first state of this class definition : the schema is not yet injected so each injection of object data will be
+ * retained in raw format.
+ */
+ final State _schemaRequestedButNotYetInjected = new State()
+ {
+ /**
+ * Stores the incoming data in raw format and request the schema for this class.
+ * After that a transition to the next state is made.
+ *
+ * @param objectId the object instance identifier.
+ * @param rawData incoming configuration data.
+ */
+ public synchronized void addNewEventData (byte[] rawData,long currentTimestamp, int severity)
+ {
+ createEventInstance(rawData,currentTimestamp, severity);
+ }
+
+ /**
+ * When a schema is injected into this defintiion the following should happen :
+ * 1) the incoming schema is parsed and the class definition is built;
+ * 2) the retained raw data is converted into object instance(s)
+ * 3) the internal state of this class changes;
+ *
+ * If someting is wrong during that process the schema is not built and the state don't change.
+ */
+ public synchronized void setSchema (List<Map<String, Object>> argumentDefinitions) throws UnableToBuildFeatureException
+ {
+ MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[argumentDefinitions.size()+2];
+
+ buildArguments(argumentDefinitions, attributesMetadata);
+
+ _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,null,null);
+
+ // Converting stored object instances into JMX MBean and removing raw instance data.
+ for (QManManagedEvent instance : _eventInstances)
+ {
+ updateEventInstanceWithData(instance);
+ registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name);
+ }
+ _state = _schemaInjected;
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.SCHEMA_INJECTED_NOTIFICATION_TYPE,
+ _parent.getName(),
+ _name,
+ Names.EVENT,
+ _objectName);
+
+ sendNotification(notification);
+ }
+ };
+
+ /**
+ * After a schema is built into this definition this is the current state of the class.
+ */
+ final State _schemaInjected = new State()
+ {
+ /**
+ * Updates the configuration state of the object instance associates with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the configuration data (raw format).
+ */
+ public void addNewEventData (byte[] rawData,long currentTimestamp, int severity)
+ {
+ QManManagedEvent instance = createEventInstance(rawData,currentTimestamp, severity);
+ updateEventInstanceWithData(instance);
+ registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name);
+ }
+
+ /**
+ * Never called when the class definition has this state.
+ */
+ public void setSchema (List<Map<String, Object>> agumentDefinitions) throws UnableToBuildFeatureException
+ {
+ // N.A. : Schema is already injected.
+ }
+ };
+
+ /**
+ * MBean used for representing remote broker object instances.
+ * This is the core component of the QMan domain model
+ *
+ * @author Andrea Gazzarini
+ */
+ class QManManagedEvent extends QManManagedEntity
+ {
+
+
+ // Arrays used for storing raw data before this mbean is registered to mbean server.
+ final byte[] _rawEventData;
+ final long _timestamp;
+ final int _severity;
+
+ /**
+ * Builds a new managed object with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ */
+ private QManManagedEvent(byte [] data, long timestamp, int severity)
+ {
+ this._rawEventData = data;
+ this._timestamp = timestamp;
+ this._severity = severity;
+ _attributes.put(SEVERITY_ATTR_NAME, _severity);
+ _attributes.put(TIMESTAMP_ATTR_NAME, new Date(_timestamp));
+ }
+
+ /**
+ * Returns the value of the given attribute.s
+ *
+ * @throws AttributeNotFoundException when no attribute is found with the given name.
+ */
+ public Object getAttribute (String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException
+ {
+ if (attributeName == null)
+ {
+ throw new RuntimeOperationsException(new IllegalArgumentException("Attribute name must not be null."));
+ }
+
+ if (_arguments.containsKey(attributeName) || SEVERITY_ATTR_NAME.equals(attributeName) || TIMESTAMP_ATTR_NAME.equals(attributeName))
+ {
+ return _attributes.get(attributeName);
+ } else
+ {
+ throw new AttributeNotFoundException(attributeName);
+ }
+ }
+
+ /**
+ * Executes an operation on this object instance.
+ *
+ * @param actionName the name of the method.
+ * @param params the method parameters
+ * @param signature the method signature.
+ */
+ public Object invoke (String actionName, Object[] params, String[] signature) throws MBeanException,ReflectionException
+ {
+ throw new ReflectionException(new NoSuchMethodException(actionName));
+ }
+
+ /**
+ * Sets the value of the given attribute on this object instance.
+ *
+ * @param attribute contains the new value of the attribute.
+ * @throws AttributeNotFoundException when the given attribute is not found on this object instance.
+ * @throws InvalidAttributeValueException when the given value is violating one attribute invariant.
+ */
+ public void setAttribute (Attribute attribute) throws AttributeNotFoundException,
+ InvalidAttributeValueException, MBeanException, ReflectionException
+ {
+ throw new ReflectionException(new NoSuchMethodException());
+ }
+
+ /**
+ * Sets the values of several attributes of this MBean.
+ *
+ * @param attributes a list of attributes: The identification of the attributes to be set and the values they are to be set to.
+ * @return The list of attributes that were set, with their new values.
+ */
+ public AttributeList setAttributes (AttributeList attributes)
+ {
+ throw new RuntimeException();
+ }
+ }
+
+ final static String SEVERITY_ATTR_NAME = "Severity";
+ final static String TIMESTAMP_ATTR_NAME = "Date";
+
+ private List<QpidProperty> _schemaOrderedArguments = new ArrayList<QpidProperty>();
+
+ Map<String, QpidProperty> _arguments = new HashMap<String, QpidProperty>();
+ List<QManManagedEvent> _eventInstances = new LinkedList<QManManagedEvent>();
+ State _state = _schemaNotRequested;;
+
+ /**
+ * Builds a new class with the given name and package as parent.
+ *
+ * @param className the name of the class.
+ * @param hash the class schema hash.
+ * @param parentPackage the parent of this class.
+ */
+ QpidEvent(String eventClassName, Binary hash, QpidPackage parentPackage)
+ {
+ super(eventClassName,hash,parentPackage,Names.EVENT);
+ }
+
+ /**
+ * Adds the configuration data for the object instance associated to the given object identifier.
+ *
+ * @param objectId the object identifier.
+ * @param rawData the raw configuration data.
+ */
+ void addEventData (byte[] rawData, long currentTimestamp, int severity)
+ {
+ _logger.debug(
+ Messages.QMAN_200021_INCOMING_EVENT_DATA,
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name);
+ _state.addNewEventData(rawData, currentTimestamp, severity);
+ }
+
+ /**
+ * Sets the schema for this class definition.
+ * A schema is basically a metadata description of all properties, statistics, methods and events of this class.
+ *
+ * @param propertyDefinitions properties metadata.
+ * @param statisticDefinitions statistics metadata.
+ * @param methodDefinitions methods metadata.
+ * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema.
+ */
+ void setSchema (List<Map<String, Object>> argumentDefinitions) throws UnableToBuildFeatureException
+ {
+ _logger.info(Messages.QMAN_000010_INCOMING_SCHEMA,_parent.getOwnerId(),_parent.getName(),_name);
+ _state.setSchema(argumentDefinitions);
+ }
+
+ /**
+ * Internal method used for building attributes definitions.
+ *
+ * @param props the map contained in the properties schema.
+ * @param stats the map contained in the statistics schema.
+ * @param attributes the management metadata for attributes.
+ * @throws UnableToBuildFeatureException when it's not possibile to build one attribute definition.
+ */
+ void buildArguments (
+ List<Map<String, Object>> arguments,MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException
+ {
+ int index = 0;
+
+ for (Map<String, Object> argumentDefinition : arguments)
+ {
+ // Force metadata attributes. It is needed because arguments are "similar" to properties but they
+ // aren't properties and then they haven't optional, index and access metadata attributes
+ // (mandatory for build a property definition).
+ argumentDefinition.put(QpidFeatureBuilder.Attribute.optional.name(),0);
+ argumentDefinition.put(QpidFeatureBuilder.Attribute.index.name(),1);
+ argumentDefinition.put(QpidFeatureBuilder.Attribute.access.name(),3);
+
+ QpidFeatureBuilder builder = QpidFeatureBuilder.createPropertyBuilder(argumentDefinition);
+ builder.build();
+
+ QpidProperty argument = (QpidProperty) builder.getQpidFeature();
+
+ _arguments.put(argument.getName(),argument);
+ _schemaOrderedArguments.add(argument);
+ attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature();
+
+ _logger.debug(
+ Messages.QMAN_200019_EVENT_ARGUMENT_DEFINITION_HAS_BEEN_BUILT,
+ _parent.getName(),
+ _name,
+ argument);
+ }
+
+ attributes[index++] = new MBeanAttributeInfo(
+ SEVERITY_ATTR_NAME,
+ Integer.class.getName(),
+ Messages.EVENT_SEVERITY_ATTRIBUTE_DESCRIPTION,
+ true,
+ false,
+ false);
+
+ attributes[index++] = new MBeanAttributeInfo(
+ TIMESTAMP_ATTR_NAME,
+ Date.class.getName(),
+ Messages.EVENT_TIMESTAMP_ATTRIBUTE_DESCRIPTION,
+ true,
+ false,
+ false);
+ }
+
+ /**
+ * Returns the object instance associated to the given identifier.
+ * Note that if the identifier is not associated to any obejct instance, a new one will be created.
+ *
+ * @param objectId the object identifier.
+ * @param registration a flag indicating whenever the (new ) instance must be registered with MBean server.
+ * @return the object instance associated to the given identifier.
+ */
+ QManManagedEvent createEventInstance(byte [] data, long timestamp, int severity)
+ {
+ QManManagedEvent eventInstance = new QManManagedEvent(data, timestamp, severity);
+ _eventInstances.add(eventInstance);
+ return eventInstance;
+ }
+
+ /**
+ * Updates the given obejct instance with the given incoming configuration data.
+ *
+ * @param instance the managed object instance.
+ * @param rawData the incoming configuration data which contains new values for instance properties.
+ */
+ void updateEventInstanceWithData(QManManagedEvent instance)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(instance._rawEventData));
+
+ for (QpidProperty property : _schemaOrderedArguments)
+ {
+ try {
+ Object value = property.decodeValue(decoder);
+ instance.createOrReplaceAttributeValue(property.getName(),value);
+ } catch(Exception ignore) {
+ _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,property.getName());
+ }
+ }
+ }
+
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder()
+ .append(_parent.getOwnerId())
+ .append("::")
+ .append(_parent.getName())
+ .append(".")
+ .append(_name)
+ .toString();
+ }
+
+ /**
+ * Deregisters all the object instances and release all previously acquired resources.
+ */
+ void releaseResources ()
+ {
+ _eventInstances.clear();
+ JMX_SERVICE.unregisterEvents();
+ JMX_SERVICE.unregisterClassDefinitions();
+ _service.close();
+ }
+
+ /**
+ * Checks if this event definition contains event instance(s).
+ *
+ * @return true if there is one or more managed instances.
+ */
+ boolean hasNoInstances()
+ {
+ return _eventInstances.isEmpty();
+ }
+
+ /**
+ * Compose method used for registering an mbean (event) instance.
+ *
+ * @param instance the mbean event.
+ * @param brokerId the broker identifier.
+ * @param packageName the package name.
+ * @param eventClassName the event class name.
+ */
+ private void registerEventInstance(
+ QManManagedEvent instance,
+ UUID brokerId,
+ String packageName,
+ String eventClassName)
+ {
+ ObjectName objectName = JMX_SERVICE.registerEventInstance(instance,brokerId,packageName,eventClassName);
+
+ EntityLifecycleNotification notification = new EntityLifecycleNotification(
+ EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE,
+ packageName,
+ eventClassName,
+ Names.EVENT,
+ objectName);
+
+ sendNotification(notification);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java
new file mode 100644
index 0000000000..35ba62e02c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Management interface for Qpid entity class..
+ */
+public interface QpidEventMBean
+{
+ /**
+ * Retruns the name of the event.
+ *
+ * @return the name of the event.
+ */
+ String getName();
+
+ /**
+ * Returns the name of the package.
+ *
+ * @return the name of the package.
+ */
+ String getPackageName();
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java
new file mode 100644
index 0000000000..3262448bd4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+/**
+ * Layer Supertype for all qpid management features.
+ */
+abstract class QpidFeature
+{
+ /** The name of the feature. */
+ protected String _name;
+
+ /**
+ * The description of the feature.
+ */
+ protected String _description;
+
+ /**
+ * Returns the description of this feature.
+ *
+ * @return the description of this feature.
+ */
+ String getDescription ()
+ {
+ return _description;
+ }
+
+ /**
+ * Sets the description for this feature.
+ *
+ * @param description the description for this feature.
+ */
+ void setDescription (String description)
+ {
+ this._description = description;
+ }
+
+ /**
+ * Returns the name of the feature.
+ *
+ * @return the name of the feature.
+ */
+ public String getName ()
+ {
+ return _name;
+ }
+
+ /**
+ * Sets the name for this feature.
+ *
+ * @param name the name of this feature.
+ */
+ void setName (String name)
+ {
+ this._name = name;
+ }
+
+ /**
+ * Returns the name of the feature.
+ *
+ * @return the name of the feature.
+ */
+ @Override
+ public String toString ()
+ {
+ return _name;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java
new file mode 100644
index 0000000000..d0862c15ca
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java
@@ -0,0 +1,454 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanFeatureInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.configuration.UnknownTypeCodeException;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.Names;
+
+/**
+ * A builder used to parse incoming schema message and therefore to build a feature (property, statistic, method, event)
+ * definition.
+ * In order to set up the correct state for this builder, clients must create an instance of this class
+ * The product of the builder will be a QpidFeature and a JMX Managemtn feature used for describing that feature in a
+ * JMX environment. So, for example, for building a property definition client code should be :
+ *
+ * <br>- QpidFeatureBuilder builder = QpidFeature.createPropertyBuilder(...);
+ * <br>- builder.build();
+ * <br>- QpidProperty property = (QpidProperty) builder.getQpidFeature();
+ * <br>- MBeanAttributeInfo managementAttributeInfo = (MBeanAttributeInfo)builder.getManagementFeature();
+ *
+ * <br>N.B.: a builder instance is not supposed to be reused. One instance for one feature!
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidFeatureBuilder
+{
+
+ static enum Attribute {
+ name,type,access,index,optional,unit,min,max,maxlen,desc,dir,argCount;
+ };
+
+ private List<Attribute> _mandatoryAttributes = new ArrayList<Attribute>();
+
+ /**
+ * Builder state for this class.
+ * Each concrete implementor is a builder for a specific feature.
+ * using the appropriate factory method.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface State {
+ void build() throws UnableToBuildFeatureException;
+ }
+
+ /**
+ * Builder used for building property definition.
+ */
+ final State _propertyBuilder = new State() {
+
+ /**
+ * Builds a property definition as well a management attribute feature.
+ */
+ public void build () throws UnableToBuildFeatureException
+ {
+ QpidProperty property = new QpidProperty();
+ try {
+ int optionalIndex = 0;
+ for (Entry<String, Object> propertyAttribute : _featureDefinition.entrySet())
+ {
+ Attribute attribute = Attribute.valueOf(propertyAttribute.getKey());
+ switch(attribute)
+ {
+ case name :
+ {
+ property.setName(String.valueOf(propertyAttribute.getValue()));
+ break;
+ }
+ case access :
+ {
+ int code = (Integer)propertyAttribute.getValue();
+ property.setAccessMode(Configuration.getInstance().getAccessMode(code));
+ break;
+ }
+ case unit :
+ {
+ property.setUnit(String.valueOf(propertyAttribute.getValue()));
+ break;
+ }
+ case min :
+ {
+ property.setMinValue((Integer)propertyAttribute.getValue());
+ break;
+ }
+ case max :
+ {
+ property.setMaxValue((Integer)propertyAttribute.getValue());
+ break;
+ }
+ case maxlen :
+ {
+ property.setMaxLength((Integer)propertyAttribute.getValue());
+ break;
+ }
+ case desc :
+ {
+ property.setDescription(String.valueOf(propertyAttribute.getValue()));
+ break;
+ }
+ case type :
+ {
+ int code = (Integer) propertyAttribute.getValue();
+ property.setType(Configuration.getInstance().getType(code));
+ break;
+ }
+ case index :
+ {
+ break;
+ }
+ case optional :
+ {
+ int code = (Integer) propertyAttribute.getValue();
+ if (code == 1)
+ {
+ property.markAsOptional(optionalIndex);
+ optionalIndex++;
+ }
+ break;
+ }
+ }
+ _mandatoryAttributes.remove(attribute);
+ }
+ } catch(Exception exception)
+ {
+ throw new UnableToBuildFeatureException(exception,property.getName());
+ }
+
+ if (!_mandatoryAttributes.isEmpty())
+ {
+ throw new MissingFeatureAttributesException(_mandatoryAttributes);
+ }
+
+ _managementFeatureInfo = new MBeanAttributeInfo(
+ property.getName(),
+ property.getJavaType().getName(),
+ property.getDescription(),
+ true,
+ property.getAccessMode()==AccessMode.RW,
+ false);
+ _qpidFeature = property;
+ }
+ };
+
+ final State _statisticBuilder = new State()
+ {
+ public void build () throws UnableToBuildFeatureException
+ {
+ QpidStatistic statistic = new QpidStatistic();
+ try
+ {
+ for (Entry<String, Object> statisticAttribute : _featureDefinition.entrySet())
+ {
+ Attribute attribute = Attribute.valueOf(statisticAttribute.getKey());
+ switch(attribute)
+ {
+ case name :
+ {
+ statistic.setName(String.valueOf(statisticAttribute.getValue()));
+ break;
+ }
+ case unit :
+ {
+ statistic.setUnit(String.valueOf(statisticAttribute.getValue()));
+ break;
+ }
+ case desc :
+ {
+ statistic.setDescription(String.valueOf(statisticAttribute.getValue()));
+ break;
+ }
+ case type :
+ {
+ int code = (Integer) statisticAttribute.getValue();
+ statistic.setType(Configuration.getInstance().getType(code));
+ break;
+ }
+ }
+ _mandatoryAttributes.remove(attribute);
+ }
+ } catch(Exception exception)
+ {
+ throw new UnableToBuildFeatureException(exception,statistic.getName());
+ }
+
+ if (!_mandatoryAttributes.isEmpty())
+ {
+ throw new MissingFeatureAttributesException(_mandatoryAttributes);
+ }
+
+ _managementFeatureInfo = new MBeanAttributeInfo(
+ statistic.getName(),
+ statistic.getJavaType().getName(),
+ statistic.getDescription(),
+ true,
+ false,
+ false);
+ _qpidFeature = statistic;
+ }
+ };
+
+ /**
+ * Builder used for building a statistic definition.
+ */
+ final State _argumentBuilder = new State()
+ {
+ /**
+ * Builds a property definition as well a management attribute feature.
+ */
+ public void build () throws UnableToBuildFeatureException
+ {
+ QpidArgument argument = new QpidArgument();
+ for (Entry<String, Object> argumentAttribute : _featureDefinition.entrySet())
+ {
+ String key = argumentAttribute.getKey();
+ if (Names.DEFAULT_PARAM_NAME.equals(key))
+ {
+ argument.setDefaultValue(argumentAttribute.getValue());
+ } else {
+ Attribute attribute = Attribute.valueOf(key);
+ switch (attribute)
+ {
+ case name :
+ {
+ argument.setName((String)argumentAttribute.getValue());
+ break;
+ }
+ case desc :
+ {
+ argument.setDescription((String)argumentAttribute.getValue());
+ break;
+ }
+ case type :
+ {
+ try
+ {
+ argument.setType(Configuration.getInstance().getType((Integer)argumentAttribute.getValue()));
+ break;
+ } catch(UnknownTypeCodeException exception)
+ {
+ throw new UnableToBuildFeatureException(exception,argument.getName());
+ }
+ }
+ case dir :
+ {
+ argument.setDirection((String)argumentAttribute.getValue());
+ break;
+ }
+ case unit :
+ {
+ argument.setUnit((String)argumentAttribute.getValue());
+ break;
+
+ }
+ }
+ }
+ }
+
+ if (!_mandatoryAttributes.isEmpty())
+ {
+ throw new MissingFeatureAttributesException(_mandatoryAttributes);
+ }
+
+ _qpidFeature = argument;
+ _managementFeatureInfo = new MBeanParameterInfo(
+ argument.getName(),
+ argument.getJavaType().getName(),
+ argument.getDescription());
+ }
+ };
+
+ final State _methodBuilder = new State()
+ {
+ public void build () throws UnableToBuildFeatureException
+ {
+ Map<String,Object> definition = _methodOrEventDefinition.getDefinition();
+ String name = (String)definition.get(Attribute.name.name());
+ if (name == null)
+ {
+ throw new MissingFeatureAttributesException(_mandatoryAttributes);
+ }
+
+ QpidMethod method = new QpidMethod((String)definition.get(Attribute.name.name()),(String) definition.get(Attribute.desc.name()));
+
+ List<Map<String,Object>> args = _methodOrEventDefinition.getArgumentsDefinitions();
+
+ List<MBeanParameterInfo> signature = new LinkedList<MBeanParameterInfo>();
+
+ for (Map<String,Object> argumentDefinition : args)
+ {
+ QpidFeatureBuilder builder = QpidFeatureBuilder.createArgumentBuilder(argumentDefinition);
+ builder.build();
+
+ QpidArgument argument = (QpidArgument) builder.getQpidFeature();
+ method.addArgument(argument);
+ if (argument.isInput())
+ {
+ signature.add((MBeanParameterInfo) builder.getManagementFeature());
+ }
+ }
+
+ _qpidFeature = method;
+ _managementFeatureInfo = new MBeanOperationInfo(
+ method.getName(),
+ method.getDescription(),
+ (MBeanParameterInfo[])signature.toArray(new MBeanParameterInfo[signature.size()]),
+ void.class.getName(),
+ MBeanOperationInfo.ACTION);
+ }
+ };
+
+ final State _eventBuilder = new State()
+ {
+ public void build () throws UnableToBuildFeatureException
+ {
+ }
+ };
+
+ private MBeanFeatureInfo _managementFeatureInfo;
+ private QpidFeature _qpidFeature;
+ private final Map <String, Object> _featureDefinition;
+ private final MethodOrEventDataTransferObject _methodOrEventDefinition;
+ private State _state;
+
+ static QpidFeatureBuilder createPropertyBuilder(Map<String, Object> propertyDefinition)
+ {
+ QpidFeatureBuilder result = new QpidFeatureBuilder(propertyDefinition);
+ result._state = result._propertyBuilder;
+ result._mandatoryAttributes.add(Attribute.name);
+ result._mandatoryAttributes.add(Attribute.access);
+ result._mandatoryAttributes.add(Attribute.type);
+ result._mandatoryAttributes.add(Attribute.optional);
+ result._mandatoryAttributes.add(Attribute.index);
+ return result;
+ }
+
+ static QpidFeatureBuilder createStatisticBuilder(Map<String, Object> statisticDefinition)
+ {
+ QpidFeatureBuilder result = new QpidFeatureBuilder(statisticDefinition);
+ result._state = result._statisticBuilder;
+ result._mandatoryAttributes.add(Attribute.name);
+ result._mandatoryAttributes.add(Attribute.type);
+ return result;
+ }
+
+ static QpidFeatureBuilder createEventBuilder(Map<String, Object> eventDefinition)
+ {
+ QpidFeatureBuilder result = new QpidFeatureBuilder(eventDefinition);
+ result._state = result._eventBuilder;
+ return result;
+ }
+
+ static QpidFeatureBuilder createMethodBuilder(MethodOrEventDataTransferObject methodDefinition)
+ {
+ QpidFeatureBuilder result = new QpidFeatureBuilder(methodDefinition);
+ result._state = result._methodBuilder;
+ result._mandatoryAttributes.add(Attribute.name);
+ return result;
+ }
+
+ private static QpidFeatureBuilder createArgumentBuilder(Map<String, Object> argumentDefinition)
+ {
+ QpidFeatureBuilder result = new QpidFeatureBuilder(argumentDefinition);
+ result._state = result._argumentBuilder;
+ return result;
+ }
+
+
+ /**
+ * Builds new builder with the given data.
+ * This constructor is used for building properties, statistics and arguments.
+ *
+ * @param definition the feature definition data.
+ */
+ private QpidFeatureBuilder(Map<String, Object> definition)
+ {
+ this._featureDefinition = definition;
+ this._methodOrEventDefinition = null;
+ }
+
+ /**
+ * Builds new builder with the given data.
+ * This constructor is used for building properties, statistics and arguments.
+ *
+ * @param definition the feature definition data.
+ */
+ private QpidFeatureBuilder(MethodOrEventDataTransferObject definition)
+ {
+ this._featureDefinition = null;
+ this._methodOrEventDefinition = definition;
+ }
+
+ /**
+ * Returns the just built qpid feature.
+ *
+ * @return the qpid feature.
+ */
+ QpidFeature getQpidFeature()
+ {
+ return _qpidFeature;
+ }
+
+ /**
+ * Return the jmx metadata for the built feature.
+ *
+ * @return the jmx metadata for the built feature.
+ */
+ MBeanFeatureInfo getManagementFeature()
+ {
+ return _managementFeatureInfo;
+ }
+
+ void build() throws UnableToBuildFeatureException
+ {
+ try
+ {
+ _state.build();
+ } catch(UnableToBuildFeatureException exception)
+ {
+ throw exception;
+ } catch(Exception exception)
+ {
+ throw new UnableToBuildFeatureException(exception,"Feature name is not available for debugging.");
+ }
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java
new file mode 100644
index 0000000000..7824ecc9a4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+
+/**
+ * Qpid method definition.
+ * An entity describing an invocation that can be made on a managed object instance.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidMethod extends QpidFeature
+{
+ /** Argument list */
+ List<QpidArgument> arguments = new LinkedList<QpidArgument>();
+
+ /**
+ * Builds a new qpid method definition with the given name and description.
+ *
+ * @param name the method name.
+ * @param description the method description.
+ */
+ QpidMethod(String name, String description)
+ {
+ this._name = name;
+ this._description = description;
+ }
+
+ /**
+ * Adds an argument to this method.
+ *
+ * @param argument the new argument to be added.
+ */
+ void addArgument(QpidArgument argument)
+ {
+ arguments.add(argument);
+ }
+
+ /**
+ * Returns a string representation of this method.
+ * The result format is <method name>(argType1 argName1 (Direction), argType2 argName2 (Direction), etc...)
+ *
+ * @return a string representation of this method.
+ */
+ @Override
+ public String toString ()
+ {
+ StringBuilder builder = new StringBuilder()
+ .append(_name)
+ .append('(');
+
+ for (QpidArgument argument : arguments)
+ {
+ builder.append(argument).append(',');
+ }
+
+ builder.append(')');
+ return builder.toString();
+ }
+
+ /**
+ * Encodes the given parameter values according to this method arguments definitions.
+ * Note that only Input/Output and Input parameters are encoded.
+ *
+ * @param parameters the parameters values.
+ * @param encoder the encoder used for encoding.
+ */
+ public void encodeParameters (Object[] parameters, Encoder encoder)
+ {
+ int index = 0;
+ for (QpidArgument argument : arguments)
+ {
+ if (argument.getDirection() != Direction.O)
+ {
+ argument.encode(parameters[index++],encoder);
+ }
+ }
+ }
+
+ /**
+ * Decodes the given input raw according to this method arguments definitions.
+ * Note that only Input/Output and Output parameters are encoded.
+ *
+ * @param parameters the parameters values.
+ * @param encoder the encoder used for encoding.
+ */
+ public Map<String, Object> decodeParameters (byte [] values)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(ByteBuffer.wrap(values));
+ Map<String, Object> result = new HashMap<String, Object>();
+
+ for (QpidArgument argument : arguments)
+ {
+ if (argument.getDirection() != Direction.I)
+ {
+ result.put(argument.getName(),argument.decode(decoder));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Validates the given array of parameters against the constraint defined on this method's arguments.
+ *
+ * @param parameters the parameters (values) to be validated.
+ * @throws ValidationException when one of the supplied values is violating some constraint.
+ */
+ public void validate (Object[] parameters) throws ValidationException
+ {
+ int index = 0;
+ for (QpidArgument argument : arguments)
+ {
+ if (argument.getDirection() != Direction.O)
+ {
+ argument.validate(parameters[index++]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java
new file mode 100644
index 0000000000..c25a5d7d1c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java
@@ -0,0 +1,286 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Qpid package definition.
+ * A grouping of class definitions that are related to a single software component.
+ * The package concept is used to extend the management schema beyond just the QPID software components.
+ * The name is prefixed with "Qpid" for avoiding name conficts with java.lang.Package.
+ *
+ * @author Andrea Gazzarini
+ */
+final class QpidPackage
+{
+ /**
+ * Qpid class identity.
+ * Each qpid class is uniquely identifier by its name and schema-hash.
+ * The schema hash is an MD5 checksum of the schema for a class.
+ * It is there so we can support the case where two different versions of the same class are present at the same time.
+ *
+ * @author Andrea Gazzarini
+ */
+ class QpidClassIdentity {
+ final String name;
+ final Binary hash;
+
+ /**
+ * Builds a new class identity with the given name and hash.
+ *
+ * @param name the class name.
+ * @param hash is an MD5 checksum of the schema of this outer class.
+ */
+ QpidClassIdentity(String name,Binary hash) {
+ this.name = name;
+ this.hash = hash;
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return name.hashCode()+hash.hashCode();
+ }
+
+ @Override
+ public boolean equals (Object obj)
+ {
+ if(obj instanceof QpidClassIdentity)
+ {
+ QpidClassIdentity identity = (QpidClassIdentity) obj;
+ return name.equals(identity.name) && hash.equals(identity.hash);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ private String _name;
+ private DomainModel _parent;
+ private Map<QpidClassIdentity, QpidClass> _classes = new HashMap<QpidClassIdentity, QpidClass>();
+ private Map<QpidClassIdentity, QpidEvent> _events = new HashMap<QpidClassIdentity, QpidEvent>();
+
+ /**
+ * Builds a new package with the supplied name.
+ *
+ * @param name the name of the package.
+ */
+ QpidPackage(String name, DomainModel parent)
+ {
+ this._name = name;
+ this._parent = parent;
+ }
+
+ /**
+ * Returns the identifier of the broker which contains this package.
+ * @return
+ */
+ UUID getOwnerId()
+ {
+ return _parent.getBrokerId();
+ }
+
+ /**
+ * Returns the name of this package.
+ *
+ * @return the name of this package.
+ */
+ String getName ()
+ {
+ return _name;
+ }
+
+ /**
+ * Adds a class definition to this package.
+ * The class will be added only if its definition doesn't already exists.
+ *
+ * @param className the name of the class.
+ * @param classHash the class schema hash.
+ * @param properties the properties of the class.
+ * @param statistics the statistics of the class.
+ * @param methods the methods of the class.
+ * @param events the events of the class.
+ *
+ * @throws UnableToBuildFeatureException when the class definition cannot be built due to a feature build failure.
+ */
+ void addClassDefinition (
+ String className,
+ Binary classHash,
+ List<Map<String, Object>> properties,
+ List<Map<String, Object>> statistics,
+ List<MethodOrEventDataTransferObject> methods) throws UnableToBuildFeatureException
+ {
+ getQpidClass(className,classHash,true).setSchema(properties,statistics,methods);
+ }
+
+ void addEventDefinition (
+ String eventClassName,
+ Binary classHash,
+ List<Map<String, Object>> arguments) throws UnableToBuildFeatureException
+ {
+ getQpidEvent(eventClassName,classHash,true).setSchema(arguments);
+ }
+
+ /**
+ * Returns true if this package contains the given class definition.
+ *
+ * @param className the name of the class.
+ * @return true if this package contains the class definition, false otherwise.
+ */
+ boolean alreadyContainsClassDefinition (String className, Binary hash)
+ {
+ return _classes.containsKey(new QpidClassIdentity(className,hash));
+ }
+
+ /**
+ * Injects into a class the given object instance instrumentation data.
+ *
+ * @param className the of the class the injected object data belongs to.
+ * @param objectId the object identifier.
+ * @param rawData the instrumentation data (in raw format).
+ */
+ void setObjectInstanceInstrumentationRawData (String className, Binary classHash,Binary objectId, byte[] rawData)
+ {
+ getQpidClass(className, classHash,true).addInstrumentationData(objectId,rawData);
+ }
+
+ /**
+ * Injects into a class the given object instance configuration data.
+ *
+ * @param className the of the class the injected object data belongs to.
+ * @param objectId the object identifier.
+ * @param rawData the configuration data (in raw format).
+ */
+ void setObjectInstanceConfigurationRawData (String className,Binary classHash, Binary objectId, byte[] rawData)
+ {
+ getQpidClass(className,classHash,true).addConfigurationData(objectId,rawData);
+ }
+
+ void setEventInstanceRawData (String eventName,Binary eventHash, byte[] rawData,long currentTimestamp,int severity)
+ {
+ getQpidEvent(eventName,eventHash,true).addEventData(rawData, currentTimestamp, severity);
+ }
+
+ /**
+ * Returns the definition of the class with given name.
+ *
+ * @param className the name of the class.
+ * @param hash the class hash.
+ * @param store a flag indicating if a just created class must be stored or not.
+ * @return the definition of the class with given name.
+ */
+ QpidClass getQpidClass(String className, Binary hash, boolean store)
+ {
+ QpidClassIdentity identity = new QpidClassIdentity(className,hash);
+ QpidClass classDefinition = _classes.get(identity);
+ if (classDefinition == null)
+ {
+ classDefinition = new QpidClass(className, hash,this);
+ if (store)
+ {
+ _classes.put(identity,classDefinition);
+ }
+ }
+ return classDefinition;
+ }
+
+ /**
+ * Returns the definition of the class with given name.
+ *
+ * @param className the name of the class.
+ * @param hash the class hash.
+ * @param store a flag indicating if a just created class must be stored or not.
+ * @return the definition of the class with given name.
+ */
+ QpidEvent getQpidEvent(String className, Binary hash, boolean store)
+ {
+ QpidClassIdentity identity = new QpidClassIdentity(className,hash);
+ QpidEvent eventDefinition = _events.get(identity);
+ if (eventDefinition == null)
+ {
+ eventDefinition = new QpidEvent(className, hash,this);
+ if (store)
+ {
+ _events.put(identity,eventDefinition);
+ }
+ }
+ return eventDefinition;
+ }
+
+ /**
+ * Returns a string representation of this class.
+ * That is, this method returns the simple name (not FQN) of this class.
+ */
+ @Override
+ public String toString ()
+ {
+ return _name;
+ }
+
+ /**
+ * Removes the object instance associated to the given parameters.
+ *
+ * @param className the class definition of the object instance.
+ * @param classHash the class hash
+ * @param objectId the object identifier.
+ */
+ void removeObjectInstance (String className, Binary classHash, Binary objectId)
+ {
+ QpidClass qpidClass = getQpidClass(className,classHash,false);
+ qpidClass.removeObjectInstance(objectId);
+ }
+
+ /**
+ * Releases all previously acquired resources of this package.
+ */
+ void releaseResources ()
+ {
+ for (QpidClass qpidClass : _classes.values())
+ {
+ qpidClass.releaseResources();
+ }
+
+ for (QpidEvent qpidEvent: _events.values())
+ {
+ qpidEvent.releaseResources();
+ }
+ }
+
+ /**
+ * Returns the method invocation listener of the corresponing parent domain model.
+ *
+ * @return the method invocation listener of the corresponing parent domain model.
+ */
+ IMethodInvocationListener getMethodInvocationListener ()
+ {
+ return _parent.getMethodInvocationListener();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java
new file mode 100644
index 0000000000..089b00c71c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java
@@ -0,0 +1,295 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.lang.reflect.Constructor;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.domain.model.type.Type;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid property definition.
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidProperty extends QpidAttribute
+{
+ private final static Logger LOGGER = Logger.get(QpidProperty.class);
+
+ private final static int [] MASKS = {1,2,4,8,16,32,64,128};
+
+ /**
+ * Decoder interface used for decoding incomng values for this property.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface Decoder
+ {
+ Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks);
+ }
+
+ /**
+ * Decoder used for decoding incoming values for this optional property.
+ */
+ final Decoder _optionalPropertyDecoder = new Decoder() {
+
+ public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks)
+ {
+ return ((presenceBitMasks[_optionalIndex/8] & MASKS[_maskIndex]) != 0)
+ ? QpidProperty.this.decodeValue(decoder)
+ : null;
+ }
+ };
+
+ /**
+ * Decoder used for decoding incoming values for this mandatory property.
+ */
+ final Decoder _mandatoryPropertyDecoder = new Decoder() {
+
+ public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks)
+ {
+ return QpidProperty.this.decodeValue(decoder);
+ }
+ };
+
+
+ /**
+ * Null object used to perform a dummy validation.
+ * This is the default validator installed at creation time.
+ */
+ final static IValidator EMPTY_VALIDATOR = new IValidator()
+ {
+ public void validate (Object value) throws ValidationException
+ {
+ // Nothing to do here.
+ }
+ };
+
+ /**
+ * Validator responsible for validating strings.
+ * At the moment the only constraint that should be applied to a string feature is the "max length"
+ */
+ class StringValidator implements IValidator
+ {
+ public void validate (Object value) throws ValidationException
+ {
+ if ((_maxLength != Integer.MIN_VALUE) && (value != null)){
+ int length = value.toString().length();
+ if (length > _maxLength) {
+ throw new ValidationException(
+ ValidationException.MAX_LENGTH,
+ _maxLength,
+ _name,
+ length);
+ }
+ }
+ }
+ };
+
+ /**
+ * Validator responsible for validating numbers.
+ */
+ class NumberValidator implements IValidator
+ {
+ public void validate (Object value) throws ValidationException
+ {
+ if (value != null) {
+ double numericValue = ((Number)value).doubleValue();
+ if (_minValue != Integer.MIN_VALUE && numericValue < _minValue) {
+ throw new ValidationException(
+ ValidationException.MIN_VALUE,
+ _minValue,
+ _name,
+ numericValue);
+ }
+
+ if (_maxValue != Integer.MIN_VALUE && numericValue > _maxValue) {
+ throw new ValidationException(
+ ValidationException.MAX_VALUE,
+ _maxValue,
+ _name,
+ numericValue);
+ }
+ }
+ }
+ };
+
+ private AccessMode _accessMode;
+ private int _minValue = Integer.MIN_VALUE;
+ private int _maxValue = Integer.MIN_VALUE;
+ private int _maxLength = Integer.MIN_VALUE;
+
+ private int _optionalIndex;
+ private int _maskIndex;
+
+ Decoder _decoder = _mandatoryPropertyDecoder;
+
+ private IValidator _validator = EMPTY_VALIDATOR;
+
+ /**
+ * Validates the given value according to the current validator.
+ * It delegates the validation to the current installed validator.
+ *
+ * @param value the value of this qpid property.
+ * @throws ValidationException when the given value is violating the current validator constraints.
+ */
+ void validate(Object value) throws ValidationException {
+ _validator.validate(value);
+ }
+
+ /**
+ * Sets the type of this property.
+ * In addition this method tries to detect if a validator has been associated with the type.
+ * If no validator is found then the default validator will be used; that is : no validator will be performed on this
+ * property.
+ *
+ * @param type the type of this property.
+ */
+ void setType (Type type)
+ {
+ super.setType(type);
+ try {
+ Class<?> validatorClass = Class.forName(Configuration.getInstance().getValidatorClassName(type));
+ Constructor<?> validatorConstructor = validatorClass.getDeclaredConstructor(QpidProperty.class);
+ _validator = (IValidator) validatorConstructor.newInstance(this);
+ LOGGER.debug(Messages.QMAN_200022_VALIDATOR_INSTALLED ,validatorClass.getName(), type);
+ } catch(Exception exception) {
+ _validator = EMPTY_VALIDATOR;
+ LOGGER.debug(Messages.QMAN_200023_VALIDATOR_NOT_FOUND , type);
+ }
+ }
+
+ /**
+ * Gets the value of this property according to its type definition.
+ *
+ * @param decoder the decoder used to extract the value.
+ * @return the value of this feature according to its type definition
+ */
+ Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks)
+ {
+ return _decoder.decodeValue(decoder, presenceBitMasks);
+ }
+
+ /**
+ * Sets access mode for this property.
+ *
+ * @param accessMode the access mode for this property.
+ */
+ void setAccessMode (AccessMode accessMode)
+ {
+ this._accessMode = accessMode;
+ }
+
+ /**
+ * Gets the minimum allowed value for this property.
+ *
+ * @return the minimum allowed value for this property.
+ */
+ int getMinValue ()
+ {
+ return _minValue;
+ }
+
+ /**
+ * Sets the minimum allowed value for this property.
+ *
+ * @param minValue the minimum allowed value for this property.
+ */
+ void setMinValue (int minValue)
+ {
+ this._minValue = minValue;
+ }
+
+ /**
+ * Gets the maximum allowed value for this property.
+ *
+ * @return the maximum allowed value for this property.
+ */
+ int getMaxValue ()
+ {
+ return _maxValue;
+ }
+
+ /**
+ * Sets the masimum allowed value for this property.
+ *
+ * @param maxValue the maximum allowed value for this property.
+ */
+ void setMaxValue (int maxValue)
+ {
+ this._maxValue = maxValue;
+ }
+
+ /**
+ * Gets the max length value for this property.
+ *
+ * @return the max length value for this property.
+ */
+ int getMaxLength ()
+ {
+ return _maxLength;
+ }
+
+ /**
+ * Sets the max length value for this property.
+ *
+ * @param maxLength the max length value for this property.
+ */
+ void setMaxLength (int maxLength)
+ {
+ this._maxLength = maxLength;
+ }
+
+ /**
+ * Gets the description of this property.
+ *
+ * @return the description of this property.
+ */
+ AccessMode getAccessMode ()
+ {
+ return _accessMode;
+ }
+
+ /**
+ * Marks this property as optional.
+ *
+ * @param optional the optional attribute value for this property.
+ * @param index the index of this optional property
+ */
+ void markAsOptional (int index)
+ {
+ this._optionalIndex = index;
+ this._maskIndex = (_optionalIndex >= 8) ? _optionalIndex-8 : _optionalIndex;
+ _decoder = _optionalPropertyDecoder;
+ }
+
+ /**
+ * Returns true if this property is marked as optional.
+ *
+ * @return true if this property is marked as optional, false otherwise.
+ */
+ boolean isOptional ()
+ {
+ return _decoder == _optionalPropertyDecoder;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java
new file mode 100644
index 0000000000..37a652c098
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Qpid statistic definition.
+ *
+ * A statistic is a typed member of a class which represents an instrumentation attribute of the class.
+ * Statistics are always read-only in nature and tend to change rapidly.
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidStatistic extends QpidAttribute
+{
+ // EMPTY CLASS : Statistic metadata are all defined in superclasses.
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java
new file mode 100644
index 0000000000..fc4506779b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Thrown when a feature (property, statistic, method or event) definition cannot be built due to schema parsing errors.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UnableToBuildFeatureException extends Exception
+{
+ private static final long serialVersionUID = 5180111828887602836L;
+
+ /**
+ * Builds a new UnableToBuildFeatureException with the specified cause.
+ *
+ * @param exception the exception cause.
+ */
+ UnableToBuildFeatureException(Exception exception, String featureName)
+ {
+ super( (featureName != null) ? featureName : "Feature name is not available for debugging purposes." ,exception);
+ }
+
+ /**
+ * Builds a new UnableToBuildFeatureException with the specified message.
+ *
+ * @param message the detail message.
+ */
+ UnableToBuildFeatureException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java
new file mode 100644
index 0000000000..3b117e5b9d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+/**
+ * Thrown when an attempt is made in order to update / change the state of an object and a constraint on that state
+ * is violated.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ValidationException extends Exception
+{
+ private static final long serialVersionUID = -5218828669655586205L;
+
+ public final static String MAX_LENGTH = "Max Length";
+ public final static String MAX_VALUE = "Max Value";
+ public final static String MIN_VALUE = "Min Value";
+
+ private final String _featureName;
+ private final Object _featureValue;
+
+ private final Number _constraintValue;
+ private final String _constraintName;
+
+ /**
+ * Builds a new validation exception with the specified parameters.
+ *
+ * @param constraintName the name of the violated constraint.
+ * @param constraintValue the value of the violated constraint.
+ * @param featureName the name of the violating feature.
+ * @param featureValue the value of the violating feature.
+ */
+ ValidationException(String constraintName,Number constraintValue, String featureName,Object featureValue)
+ {
+ super(String.format(
+ "Property constraint violation : " +
+ "%s allowed for property %s is %s but received value was %s",
+ constraintName,
+ featureName,
+ constraintValue,
+ featureValue));
+ this._constraintName = constraintName;
+ this._constraintValue = constraintValue;
+ this._featureName = featureName;
+ this._featureValue = featureValue;
+ }
+
+ /**
+ * Returns the value of the violating feature.
+ *
+ * @return the value of the violating feature.
+ */
+ public Object getFeatureValue ()
+ {
+ return _featureValue;
+ }
+
+ /**
+ * Returns the name of the violating feature.
+ *
+ * @return the name of the violating feature.
+ */
+ public String getFeatureName()
+ {
+ return _featureName;
+ }
+
+ /**
+ * Returns the value of the violated constraint.
+ *
+ * @return the value of the violated constraint.
+ */
+ public Number getConstraintValue ()
+ {
+ return _constraintValue;
+ }
+
+ /**
+ * Returns the name of the violated constraint.
+ *
+ * @return the name of the violated constraint.
+ */
+ public String getConstraintName ()
+ {
+ return _constraintName;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java
new file mode 100644
index 0000000000..28f5f70c04
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class AbsTime extends Type
+{
+ public AbsTime()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readInt64();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeInt64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java
new file mode 100644
index 0000000000..95cb03b04b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java
@@ -0,0 +1,169 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.UUID;
+
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * It is a simple wrapper for a byte array (for example a 128bin).
+ * It is used to let QMan deal with an object instead of an array.
+ *
+ * @author Andrea Gazzarini
+ */
+public final class Binary implements Serializable
+{
+ private static final long serialVersionUID = -6865585077320637567L;
+
+ // Marker internal (empty) interface
+ private interface State extends Serializable{}
+
+ /**
+ * Internal state of this object used to denote the situation when the hashcode() method has never been called.
+ * After the hashcode has been computed this class switches the state of the outer object to the next state.
+ */
+ State hashCodeNotYetComputed = new State()
+ {
+ private static final long serialVersionUID = 221632033761266959L;
+
+ @Override
+ public int hashCode ()
+ {
+ hashCode = Arrays.hashCode(_bytes);
+ state = hashCodeAlreadyComputed;
+ return hashCode;
+ }
+ };
+
+ /**
+ * Internal state of this object used to denote the situation where the hashcode() method has already been computed.
+ * Simply it returns the just computed value for the hashcode.
+ */
+ State hashCodeAlreadyComputed = new State()
+ {
+ private static final long serialVersionUID = 221632033761266959L;
+
+ @Override
+ public int hashCode ()
+ {
+ return hashCode;
+ }
+ };
+
+ private final UUID uuid;
+ private final byte [] _bytes;
+ private long _first;
+ private int hashCode;
+
+ /** Current state (hashcode computation). */
+ State state = hashCodeNotYetComputed;
+
+ /**
+ * Builds a new binary with the given byte array.
+ *
+ * @param bytes the wrapped data.
+ */
+ public Binary(byte [] bytes)
+ {
+ this._bytes = bytes;
+ byte [] array = new byte [8];
+ System.arraycopy(_bytes, 0, array, 0, 8);
+ _first = unpack64(array);
+ uuid = UUID.randomUUID();
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return state.hashCode();
+ }
+
+ @Override
+ public boolean equals (Object obj)
+ {
+ if(obj instanceof Binary)
+ {
+ try
+ {
+ Binary binary = (Binary)obj;
+ return Arrays.equals(_bytes, binary._bytes);
+ } catch (Exception exception)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Encodes the content (wrapped byte array) of this instance using the given encoder.
+ *
+ * @param encoder the encoder used to encode instance content.
+ */
+ public void encode(Encoder encoder)
+ {
+ encoder.writeBin128(_bytes);
+ }
+
+ @Override
+ public String toString ()
+ {
+ return uuid.toString();
+ }
+
+ /**
+ * Returns the bank identifier derived from this object identifier.
+ *
+ * @return the bank identifier derived from this object identifier.
+ */
+ public long getBankId()
+ {
+ return _first & 0x000000000FFFFFFF;
+ }
+
+ /**
+ * Returns the broker identifier derived from this object identifier.
+ *
+ * @return the broker identifier derived from this object identifier.
+ */
+ public long getBrokerId()
+ {
+ return (_first & 281474708275200L) >> 28;
+ }
+
+ public final long unpack64(byte data[]) {
+ return (
+ ((long) (data[0] & 0xff) << 56) |
+ ((long)(data[1] & 0xff) << 48) |
+ ((long)(data[2] & 0xff) << 40) |
+ ((long)(data[3] & 0xff) << 32) |
+ ((long)(data[4] & 0xff) << 24) |
+ ((long)(data[5] & 0xff) << 16) |
+ ((long)(data[6] & 0xff) << 8) |
+ (long) data[7] & 0xff);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java
new file mode 100644
index 0000000000..c339b870ac
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Boolean extends Type
+{
+ public Boolean()
+ {
+ super(java.lang.Boolean.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return (decoder.readUint8() == 1);
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint8( ((java.lang.Boolean)value) ? (short)1 : 0 );
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java
new file mode 100644
index 0000000000..a788e2f8e1
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class DeltaTime extends Type
+{
+ public DeltaTime()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readUint64();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java
new file mode 100644
index 0000000000..d36af3d3df
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Double extends Type
+{
+ public Double()
+ {
+ super(java.lang.Double.class);
+ }
+
+ @Override
+ public Object decode(Decoder decoder)
+ {
+ return decoder.readDouble();
+ }
+
+ @Override
+ public void encode(Object value, Encoder encoder)
+ {
+ encoder.writeDouble((java.lang.Double)value);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java
new file mode 100644
index 0000000000..cb1f6e78a7
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Float extends Type
+{
+ public Float()
+ {
+ super(java.lang.Float.class);
+ }
+
+ @Override
+ public Object decode(Decoder decoder)
+ {
+ return decoder.readFloat();
+ }
+
+ @Override
+ public void encode(Object value, Encoder encoder)
+ {
+ encoder.writeFloat((java.lang.Float)value);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java
new file mode 100644
index 0000000000..f4685f0295
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Int16 extends Type
+{
+ public Int16()
+ {
+ super(Short.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readInt16();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeInt16((Short)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java
new file mode 100644
index 0000000000..ae5be90a2d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Int32 extends Type
+{
+ public Int32()
+ {
+ super(Integer.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readInt32();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeInt32((Integer)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java
new file mode 100644
index 0000000000..f76818344e
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Int64 extends Type
+{
+ public Int64()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readInt64();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeInt64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java
new file mode 100644
index 0000000000..6f7c3b24d0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Int8 extends Type
+{
+ public Int8()
+ {
+ super(Byte.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readInt8();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeInt8((Byte)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java
new file mode 100644
index 0000000000..ef5bc7a484
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Map extends Type
+{
+ public Map()
+ {
+ super(java.util.Map.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readMap();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeMap((java.util.Map<String, Object>)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java
new file mode 100644
index 0000000000..13e1b68d26
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class ObjectReference extends Type
+{
+ public ObjectReference()
+ {
+ super(byte[].class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readBin128();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ ((Binary)value).encode(encoder);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java
new file mode 100644
index 0000000000..42829ce176
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Str16 extends Type
+{
+ public Str16()
+ {
+ super(String.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readStr16();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeStr16((String)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java
new file mode 100644
index 0000000000..f9b747ce6d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Str8 extends Type
+{
+ public Str8()
+ {
+ super(String.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readStr8();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeStr8((String)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java
new file mode 100644
index 0000000000..7f92ec82b0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+/**
+ * Layer supertype for all management "types".
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class Type
+{
+ /** Java representation of this type. */
+ protected final Class<?> javaType;
+
+ /**
+ * Builds a new management type wiich wraps the given java type.
+ *
+ * @param javaType the java type.
+ */
+ Type(Class<?> javaType)
+ {
+ this.javaType = javaType;
+ }
+
+ /**
+ * Returns the wrapped java type.
+ *
+ * @return the wrapped java type.
+ */
+ public Class<?> getJavaType ()
+ {
+ return javaType;
+ }
+
+ /**
+ * Each concrete subclass must define here how to decode incoming data according.
+ *
+ * @param decoder the decoder used to extract data.
+ * @return the "typed" value.
+ *
+ */
+ public abstract Object decode(Decoder decoder);
+
+ /**
+ * Returns a string representation of this type.
+ *
+ * @return a string representation of this type.
+ */
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder(getClass().getName())
+ .append(" (wraps ")
+ .append(javaType.getName())
+ .append(')').toString();
+ }
+
+ /**
+ * Identity for types is based on wrapped java type identity.
+ */
+ @Override
+ public boolean equals (Object obj)
+ {
+ return (obj instanceof Type) && getJavaType() == ((Type)obj).getJavaType();
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return getJavaType().hashCode();
+ }
+
+ /**
+ * Encodes the given values according to this type definition.
+ *
+ * @param value the value to be encoded.
+ * @param encoder the encoder.
+ */
+ public abstract void encode (Object value,Encoder encoder);
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java
new file mode 100644
index 0000000000..2d3edd41ea
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Uint16 extends Type
+{
+ public Uint16()
+ {
+ super(Integer.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return new Integer(decoder.readUint16());
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint16((Integer)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java
new file mode 100644
index 0000000000..c5fb981bb0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Uint32 extends Type
+{
+ public Uint32()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return new Long(decoder.readUint32());
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint32((Long)value);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java
new file mode 100644
index 0000000000..9182f883bf
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Uint64 extends Type
+{
+ public Uint64()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return new Long(decoder.readUint64());
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java
new file mode 100644
index 0000000000..ab7e78856c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Uint8 extends Type
+{
+ public Uint8()
+ {
+ super(Short.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return new Short(decoder.readUint8());
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUint8((Short)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java
new file mode 100644
index 0000000000..1b3be954d6
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model.type;
+
+import java.util.UUID;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Uuid extends Type
+{
+ public Uuid()
+ {
+ super(UUID.class);
+ }
+
+ @Override
+ public Object decode (Decoder decoder)
+ {
+ return decoder.readUuid();
+ }
+
+ @Override
+ public void encode (Object value, Encoder encoder)
+ {
+ encoder.writeUuid((UUID)value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java
new file mode 100644
index 0000000000..fc9819fce4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java
@@ -0,0 +1,183 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Message listener used for processing incoming messages.
+ * So it is installed as a consumer on a specific channel and when a new message arrives:
+ *
+ * 1) Performs a sanity check on the message (magic number, sequence number)
+ * 2) Extracts the opcode and looks for one message handler associated with that opcode.
+ * 3) If a message handler is found the delegates the message processing; otherwise a log message is written to indicate
+ * that the message will be skipped.
+ *
+ * @author Andrea Gazzarini
+ */
+class BrokerMessageListener implements MessageListener
+{
+ private final static Logger LOGGER = Logger.get(BrokerMessageListener.class);
+
+ private static class Log
+ {
+ // Debugs the content of the incoming message.
+ static void debugIncomingMessage(ByteBuffer message)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(Messages.QMAN_200001_INCOMING_MESSAGE_HAS_BEEN_RECEIVED, Arrays.toString(message.array()));
+ }
+ }
+
+ // Debugs all the configured handlers.
+ static void debugConfiguredHandlers (Map<Character, IMessageHandler> _handlers)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ for (Entry<Character, IMessageHandler> entry : _handlers.entrySet())
+ {
+ LOGGER.debug(Messages.QMAN_200002_OPCODE_HANDLER_ASSOCIATION,entry.getKey(),entry.getValue());
+ }
+ }
+ }
+ }
+
+ Map<Character, IMessageHandler> _handlers = new HashMap<Character, IMessageHandler>();
+ private DomainModel _domainModel;
+
+ /**
+ * Builds a new message listener with the given broker domain model.
+ *
+ * @param model the managed broker domain model.
+ */
+ BrokerMessageListener(DomainModel model)
+ {
+ this._domainModel = model;
+ }
+
+ /**
+ * When a new message arrives this method is called.
+ * 1) Performs a sanity check on the message (magic number, sequence number)
+ * 2) Extracts the opcode and looks for one message handler associated with that opcode.
+ * 3) If a message handler is found the delegates the message processing; otherwise a log message is written to indicate
+ * that the message will be skipped.
+ *
+ * @param message the incoming message.
+ */
+ public void onMessage (Message compoundMessage)
+ {
+ try
+ {
+ MessageTokenizer tokenizer = new MessageTokenizer(compoundMessage);
+ while (tokenizer.hasMoreElements())
+ {
+ dispatch(tokenizer.nextElement());
+ }
+ } catch(IOException exception)
+ {
+ LOGGER.error(exception,Messages.QMAN_100002_MESSAGE_READ_FAILURE);
+ } catch(Exception exception)
+ {
+ LOGGER.error(exception,Messages.QMAN_100003_MESSAGE_PROCESS_FAILURE);
+ }
+ }
+
+ /**
+ * Configures a new handler with this listener.
+ * After that, each time a message arrives with the specified opcode, this handler will be responsible for
+ * processing.
+ * Note that calling this method will switch this listener to a WORKING state.
+ *
+ * @param opcode the operation code.
+ * @param handler the message handler.
+ */
+ void setHandlers(Map<Character, IMessageHandler> handlers)
+ {
+ for (Entry<Character, IMessageHandler> entry : handlers.entrySet())
+ {
+ char opcode = entry.getKey();
+ IMessageHandler handler = entry.getValue();
+ try
+ {
+ handler.setDomainModel(_domainModel);
+ _handlers.put(opcode, handler);
+ } catch (Exception exception) {
+ LOGGER.error(exception,
+ Messages.QMAN_100004_HANDLER_INITIALIZATION_FAILURE,
+ opcode);
+ }
+ }
+ }
+
+
+
+ /**
+ * Dispatches the given message to the appropriate handler.
+ *
+ * @param message
+ * the incoming message.
+ * @throws IOException
+ * when the message content cannot be read.
+ */
+ private void dispatch(Message message) throws IOException
+ {
+ ByteBuffer buffer = message.readData();
+
+ String magicNumber = new String(new byte[] {buffer.get(),buffer.get(),buffer.get()});
+ if (!Protocol.MAGIC_NUMBER.equals(magicNumber))
+ {
+ LOGGER.error(Messages.QMAN_100001_BAD_MAGIC_NUMBER_FAILURE,magicNumber);
+ return;
+ }
+
+ char opcode = (char)buffer.get();
+
+ IMessageHandler handler = _handlers.get(opcode);
+ if (handler != null)
+ {
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(buffer);
+
+ LOGGER.debug(Messages.QMAN_200003_MESSAGE_FORWARDING,opcode,handler);
+
+ handler.process(decoder,decoder.readSequenceNo());
+ } else
+ {
+ LOGGER.warn(Messages.QMAN_300001_MESSAGE_DISCARDED,opcode);
+ Log.debugConfiguredHandlers(_handlers);
+ }
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java
new file mode 100644
index 0000000000..a6f5ab90cc
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java
@@ -0,0 +1,249 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.util.UUID;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.BrokerConnectionData;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * This is the Object representation of a management client.
+ * According to specification : "A software component that is separate from the messaging broker, connected to the
+ * management broker via an AMQP connection, which allows any software component to be managed remotely by QPID."
+ *
+ * @author Andrea Gazzarini
+ */
+public final class ManagementClient
+{
+ private final static Logger LOGGER = Logger.get(ManagementClient.class);
+
+ private final String _managementQueueName;
+ private final String _methodReplyQueueName;
+
+ private DomainModel _domainModel;
+ private QpidService _service;
+
+ private final BrokerConnectionData _connectionData;
+
+ /**
+ * Builds a new <code>ManagementClient</code> with the given identifier and connection data.
+ *
+ * @param brokerId the broker identifier.
+ * @param connectionData the broker connection data (host, port, etc...)
+ */
+ ManagementClient(UUID brokerId,BrokerConnectionData connectionData)
+ {
+ _connectionData = connectionData;
+ _service = new QpidService(brokerId);
+ _domainModel = new DomainModel(brokerId);
+ _managementQueueName = Configuration.getInstance().getManagementQueueName();
+ _methodReplyQueueName = Configuration.getInstance().getMethodReplyQueueName();
+ }
+
+ @Override
+ public String toString()
+ {
+ return _connectionData.toString();
+ }
+
+ /**
+ * Returns the connection data associated with this management client.
+ *
+ * @return the connection data associated with this management client.
+ */
+ public BrokerConnectionData getBrokerConnectionData()
+ {
+ return _connectionData;
+ }
+
+ /**
+ * Establishing initial communication Between Client and Broker.
+ * According to specification :
+ * "Communication is established between the management client and management agent using normal AMQP procedures.
+ * The client creates a connection to the broker and then establishes a session with its corresponding channel.
+ * Two private queues are then declared.
+ * A management queue is declared and bound to the qpid.management exchange with "mgmt.#" as routing key; in that
+ * way all management-related messages sent to the exchange will be received by this client.
+ * When a client successfully binds to the qpid.management exchange, the management agent schedules a schema
+ * broadcast to be sent to the exchange.
+ * The agent will publish, via the exchange, a description of the schema for all manageable objects in its control. That
+ * schema is therefore received by this service and it will be part of service's domain model."
+ *
+ * @throws StartupFailureException when this management client cannot perform startup operations due to an error.
+ */
+ void estabilishFirstConnectionWithBroker() throws StartupFailureException{
+ try {
+ connectWithBroker();
+
+ createAndBindMethodReplyQueue();
+ createAndBindManagementQueue();
+
+ registerConsumerOnManagementQueue();
+ registerConsumerOnMethodReplyQueue();
+
+ synchronize();
+ } catch(Exception exception)
+ {
+ try {
+ _service.close();
+ } catch(Exception ignore)
+ {
+ }
+ throw new StartupFailureException(exception);
+ }
+ }
+
+ /**
+ * Shutdown procedure for this management client.
+ */
+ void shutdown ()
+ {
+ LOGGER.info(Messages.QMAN_000011_SHUTDOWN_INITIATED,_domainModel.getBrokerId());
+
+ removeMethodReplyConsumer();
+ destroyAndUnbingMethodReplyQueue();
+
+ removeManagementConsumer();
+ destroyAndUnbingManagementQueue();
+
+ _domainModel.releaseResources();
+
+ _service.close();
+
+ LOGGER.info(Messages.QMAN_000012_MANAGEMENT_CLIENT_SHUT_DOWN,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Registers a consumer (that is, a listener) on the method-reply queue.
+ */
+ private void registerConsumerOnMethodReplyQueue ()
+ {
+ BrokerMessageListener methodReplyChannelListener = new BrokerMessageListener(_domainModel);
+ methodReplyChannelListener.setHandlers(Configuration.getInstance().getMethodReplyQueueHandlers());
+ _service.createSubscription(_methodReplyQueueName, _methodReplyQueueName, methodReplyChannelListener);
+
+ LOGGER.info(Messages.QMAN_000013_METHOD_REPLY_CONSUMER_INSTALLED, _domainModel.getBrokerId());
+ }
+
+ /**
+ * Registers a consumer (listener) on the management queue.
+ */
+ private void registerConsumerOnManagementQueue ()
+ {
+ BrokerMessageListener managementChannelListener = new BrokerMessageListener(_domainModel);
+ managementChannelListener.setHandlers(Configuration.getInstance().getManagementQueueHandlers());
+ _service.createSubscription(_managementQueueName, _managementQueueName, managementChannelListener);
+
+ LOGGER.info(Messages.QMAN_000014_MANAGEMENT_CONSUMER_INSTALLED, _domainModel.getBrokerId());
+ }
+
+ /**
+ * Declares a management queue and bound it to the "qpid.management" exchange with "mgmt.#" as routing key;
+ */
+ private void createAndBindManagementQueue ()
+ {
+ _service.declareQueue(_managementQueueName);
+ _service.declareBinding(
+ _managementQueueName,
+ Names.MANAGEMENT_EXCHANGE,
+ Names.MANAGEMENT_ROUTING_KEY);
+
+ LOGGER.info(Messages.QMAN_000015_MANAGEMENT_QUEUE_DECLARED,_managementQueueName,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Declares a private queue for receiving method replies (after method invocations).
+ * This queue is bound to the amq.direct exchange using a routing key equal to the name of the queue.
+ */
+ private void createAndBindMethodReplyQueue ()
+ {
+ _service.declareQueue(_methodReplyQueueName);
+ _service.declareBinding(_methodReplyQueueName, Names.AMQ_DIRECT_QUEUE, _methodReplyQueueName);
+
+ LOGGER.info(Messages.QMAN_000016_METHOD_REPLY_QUEUE_DECLARED,_methodReplyQueueName, _domainModel.getBrokerId());
+ }
+
+ /**
+ * Removes the method-reply queue consumer.
+ */
+ private void removeMethodReplyConsumer()
+ {
+ _service.removeSubscription(_methodReplyQueueName);
+
+ LOGGER.info(Messages.QMAN_000017_CONSUMER_HAS_BEEN_REMOVED,_methodReplyQueueName,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Unbind the method reply queue and after that destroy it from remote broker.
+ */
+ private void destroyAndUnbingMethodReplyQueue()
+ {
+ _service.declareUnbinding(_methodReplyQueueName, Names.AMQ_DIRECT_QUEUE, _methodReplyQueueName);
+ _service.deleteQueue(_methodReplyQueueName);
+
+ LOGGER.info(Messages.QMAN_000018_QUEUE_UNDECLARED,_methodReplyQueueName,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Removes the management queue consumer.
+ */
+ private void removeManagementConsumer()
+ {
+ _service.removeSubscription(_managementQueueName);
+
+ LOGGER.info(Messages.QMAN_000017_CONSUMER_HAS_BEEN_REMOVED,_managementQueueName,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Unbind the management queue and after that destroy it from remote broker.
+ */
+ private void destroyAndUnbingManagementQueue()
+ {
+ _service.declareUnbinding(_managementQueueName, Names.MANAGEMENT_EXCHANGE, Names.MANAGEMENT_ROUTING_KEY);
+ _service.deleteQueue(_managementQueueName);
+
+ LOGGER.info(Messages.QMAN_000018_QUEUE_UNDECLARED, _managementQueueName,_domainModel.getBrokerId());
+ }
+
+ /**
+ * Connects this client with the broker.
+ *
+ * @throws QpidException when it's not possibile to connect with the broker.
+ */
+ private void connectWithBroker() throws Exception
+ {
+ _service.connect();
+ }
+
+ /**
+ * All the Management client commands are asynchronous.
+ * Synchronous behavior is achieved through invoking the sync method.
+ */
+ private void synchronize()
+ {
+ _service.sync();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java
new file mode 100644
index 0000000000..9275255517
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java
@@ -0,0 +1,152 @@
+/*
+*
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.nclient.util.ByteBufferMessage;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * The message tokenizer class allows a multi message listener to break a
+ * message into tokens where each token is itself a valid AMQP message.
+ *
+ * @author Andrea Gazzarini
+ * @see QPID-1368
+ */
+class MessageTokenizer implements Enumeration<Message>
+{
+ private final static Logger LOGGER = Logger.get(MessageTokenizer.class);
+
+ static byte [] MAGIC_NUMBER_BYTES;
+
+ private LinkedList<Message> _messages = new LinkedList<Message>();
+ private Iterator<Message> _iterator;
+
+ static
+ {
+ try
+ {
+ MAGIC_NUMBER_BYTES = Protocol.MAGIC_NUMBER.getBytes("UTF-8");
+ } catch(Exception exception)
+ {
+ throw new ExceptionInInitializerError(exception);
+ }
+ }
+
+ /**
+ * Builds a new Message tokenizer with the given message.
+ * Note that if the given message is not a "compound" message this tokenizer will producer only one token;
+ * That is, the token is a message equals to the given message.
+ *
+ * @param compoundMessage the compound message
+ * @throws IOException when it's not possible to read the given message content.
+ */
+ MessageTokenizer(Message compoundMessage) throws IOException
+ {
+ build(compoundMessage);
+ }
+
+ public boolean hasMoreElements()
+ {
+ return _iterator.hasNext();
+ }
+
+ public Message nextElement()
+ {
+ return _iterator.next();
+ }
+
+ /**
+ * Retruns the number of the tokens produced by this tokenizer.
+ *
+ * @return the number of the tokens produced by this tokenizer.
+ */
+ public int countTokens()
+ {
+ return _messages.size();
+ }
+
+ // Internal methods used for splitting the multi message byte array.
+ int indexOf(byte[] source, int startIndex)
+ {
+ int currentSourceIndex;
+ int currentExampleIndex;
+
+ if (startIndex + 3 > source.length)
+ return -1;
+
+ for (currentSourceIndex = startIndex; currentSourceIndex <= source.length - 3; currentSourceIndex++)
+ {
+ for (currentExampleIndex = 0; currentExampleIndex < 3; currentExampleIndex++)
+ {
+ if (source[currentSourceIndex + currentExampleIndex] != MAGIC_NUMBER_BYTES[currentExampleIndex])
+ break;
+ }
+
+ if (currentExampleIndex == 3)
+ return currentSourceIndex;
+ }
+ return -1;
+ }
+
+ // Internal method used for building the tokens.
+ private void build(Message compoundMessage) throws IOException
+ {
+ int startIndex = 0;
+ int indexOfMagicNumber = 0;
+
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(compoundMessage.readData());
+ byte [] source = decoder.readReaminingBytes();
+
+ int howManyTokens = 1;
+
+ while ((indexOfMagicNumber = indexOf(source, startIndex+1)) != -1)
+ {
+ addMessageToken(source, startIndex, (indexOfMagicNumber-startIndex));
+ startIndex = indexOfMagicNumber;
+ howManyTokens++;
+ }
+ addMessageToken(source, startIndex, (source.length-startIndex));
+ _iterator = _messages.iterator();
+
+ LOGGER.debug(Messages.QMAN_200031_COMPOUND_MESSAGE_CONTAINS,howManyTokens);
+ };
+
+ // Builds & adds a new "message" token
+ private void addMessageToken(byte [] source,int startIndex,int length) throws IOException
+ {
+ byte [] messageData = new byte[length];
+ System.arraycopy(source, startIndex, messageData, 0, messageData.length);
+ Message message = new ByteBufferMessage();
+ message.appendData(messageData);
+ _messages.add(message);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java
new file mode 100644
index 0000000000..26fd8eee24
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+public class MethodInvocationException extends Exception
+{
+ private static final long serialVersionUID = -7772343434879470351L;
+ private final long _returnCode;
+ private final String _statusText;
+
+ public MethodInvocationException(long code, String text)
+ {
+ this._returnCode = code;
+ this._statusText = text;
+ }
+
+ @Override
+ public String getMessage ()
+ {
+ return String.format("Return code : \"%s, reason : \"%s\"",_returnCode,_statusText);
+ }
+
+ public long getReturnCode ()
+ {
+ return _returnCode;
+ }
+
+ public String getStatusText ()
+ {
+ return _statusText;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java
new file mode 100644
index 0000000000..c4c0ce5e74
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java
@@ -0,0 +1,412 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.DynamicMBean;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+import javax.management.ReflectionException;
+
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.BrokerAlreadyConnectedException;
+import org.apache.qpid.management.configuration.BrokerConnectionData;
+import org.apache.qpid.management.configuration.BrokerConnectionException;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.model.JmxService;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Main entry point for starting Q-Man application.
+ */
+public class QMan extends NotificationBroadcasterSupport implements DynamicMBean, NotificationListener
+{
+ private final static Logger LOGGER = Logger.get(QMan.class);
+ private final List<ManagementClient> managementClients = new ArrayList<ManagementClient>();
+
+ private Configurator _configurator = new Configurator();
+ private ThreadPoolExecutor _workManager;
+
+ /**
+ * Starts QMan.
+ * @throws StartupFailureException when it's not possible to proceed with startup.
+ */
+ public void start() throws StartupFailureException
+ {
+ LOGGER.info(Messages.QMAN_000001_STARTING_QMAN);
+ LOGGER.info(Messages.QMAN_000002_READING_CONFIGURATION);
+
+ try
+ {
+ registerQManService();
+
+ _configurator.configure();
+
+ configureWorkManager();
+
+ LOGGER.info(Messages.QMAN_000019_QMAN_STARTED);
+ } catch(Exception exception) {
+ LOGGER.error(exception,Messages.QMAN_100018_UNABLE_TO_STARTUP_CORRECTLY );
+ throw new StartupFailureException(exception);
+ }
+ }
+
+ /**
+ * Connects Q-Man with a broker defined by the given parameter.
+ *
+ * @param host the hostname where the broker is running.
+ * @param port the port where the broker is running.
+ * @param username the username for connecting with the broker.
+ * @param password the password for connecting with the broker.
+ * @param virtualHost the virtual host.
+ * @param initialPoolCapacity the number of the connection that must be immediately opened.
+ * @param maxPoolCapacity the maximum number of opened connection.
+ * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection.
+ * @throws MBeanException when it's not possible to connect with the broker.
+ */
+ public void addBroker(
+ String host,
+ int port,
+ String username,
+ String password,
+ String virtualHost,
+ int initialPoolCapacity,
+ int maxPoolCapacity,
+ long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException
+ {
+ Configurator configurator = new Configurator();
+ try {
+ UUID brokerId = UUID.randomUUID();
+ BrokerConnectionData data = configurator.createAndReturnBrokerConnectionData(
+ brokerId,
+ host,
+ port,
+ username,
+ password,
+ virtualHost,
+ initialPoolCapacity,
+ maxPoolCapacity,
+ maxWaitTimeout);
+ createManagementClient(brokerId, data);
+ } catch (BrokerAlreadyConnectedException exception)
+ {
+ LOGGER.warn(Messages.QMAN_300003_BROKER_ALREADY_CONNECTED, exception.getBrokerConnectionData());
+ throw exception;
+ }
+ }
+
+ /**
+ * Stop Qman
+ */
+ public void stop()
+ {
+ LOGGER.info(Messages.QMAN_000020_SHUTTING_DOWN_QMAN);
+ try
+ {
+ for (ManagementClient client : managementClients)
+ {
+ client.shutdown();
+ }
+ } catch(Exception exception)
+ {
+ }
+ LOGGER.info(Messages.QMAN_000021_SHUT_DOWN);
+ }
+
+ /**
+ * Creates a management client using the given data.
+ *
+ * @param brokerId the broker identifier.
+ * @param data the broker connection data.
+ */
+ public void createManagementClient(UUID brokerId, BrokerConnectionData data)
+ {
+ try
+ {
+ ManagementClient client = new ManagementClient(brokerId,data);
+ client.estabilishFirstConnectionWithBroker();
+ managementClients.add(client);
+
+ LOGGER.info(Messages.QMAN_000004_MANAGEMENT_CLIENT_CONNECTED,brokerId);
+ } catch(StartupFailureException exception) {
+ LOGGER.error(exception, Messages.QMAN_100017_UNABLE_TO_CONNECT,brokerId,data);
+ }
+ }
+
+ /**
+ * Returns the list of management clients currently handled by QMan.
+ *
+ * @return the list of management clients currently handled by QMan.
+ */
+ public List<ManagementClient> getManagementClients()
+ {
+ return managementClients;
+ }
+
+ /**
+ * Injects the configurator on this QMan instance.
+ * That configutator later will be responsible to manage the configuration.
+ *
+ * @param configurator the configurator to be injected.
+ */
+ public void setConfigurator(Configurator configurator){
+ this._configurator = configurator;
+ }
+
+ /**
+ * Main method used for starting Q-Man.
+ *
+ * @param args the command line arguments.
+ */
+ public static void main (String[] args)
+ {
+ if (args.length == 1)
+ {
+ String logFileName = args[0];
+ DOMConfigurator.configureAndWatch(logFileName,5000);
+ }
+
+ final QMan qman = new QMan();
+
+ Thread hook = new Thread()
+ {
+ @Override
+ public void run ()
+ {
+ qman.stop();
+ }
+ };
+
+ Runtime.getRuntime().addShutdownHook(hook);
+ try
+ {
+ qman.start();
+
+ System.out.println("Type \"q\" to quit.");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ while ( !"q".equals(reader.readLine()) )
+ {
+
+ }
+ Runtime.getRuntime().removeShutdownHook(hook);
+ qman.stop();
+ System.exit(-1);
+ } catch (StartupFailureException exception)
+ {
+ qman.stop();
+ System.exit(-1);
+ } catch (IOException exception)
+ {
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * Not implemented for this MBean.
+ */
+ public Object getAttribute(String attribute)
+ {
+ return null;
+ }
+
+ /**
+ * Not implemented for this MBean.
+ */
+ public AttributeList getAttributes(String[] attributes)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the metadata for this MBean
+ *
+ * @return the metadata for this MBean
+ */
+ public MBeanInfo getMBeanInfo()
+ {
+ MBeanParameterInfo parameters [] = new MBeanParameterInfo[8];
+
+ parameters[0] = new MBeanParameterInfo(
+ "host",
+ String.class.getName(),
+ "The IP address or DNS name that Qpid Broker uses to listen for incoming connections.");
+ parameters[1] = new MBeanParameterInfo(
+ "port",
+ int.class.getName(),
+ "The port number that Qpid Broker uses to listen for incoming connections.");
+ parameters[2] = new MBeanParameterInfo(
+ "username",
+ String.class.getName(),
+ "The Qpid account name used in the physical connection.");
+ parameters[3] = new MBeanParameterInfo(
+ "password",
+ String.class.getName(),
+ "The Qpid account password used in the physical connection.");
+ parameters[4]= new MBeanParameterInfo(
+ "virtualHost",
+ String.class.getName(),
+ "The virtualHost name.");
+ parameters[5]= new MBeanParameterInfo(
+ "initialPoolCapacity",
+ int.class.getName(),
+ "The number of physical connections (between 0 and a positive 32-bit integer) to create when creating the (Qpid) connection pool.");
+ parameters[6]= new MBeanParameterInfo(
+ "maxPoolCapacity",
+ int.class.getName(),
+ "The maximum number of physical database connections (between 0 and a positive 32-bit integer) that the (Qpid) connection pool can contain. ");
+ parameters[7]= new MBeanParameterInfo(
+ "maxWaitTimeout",
+ long.class.getName(),
+ "The maximum amount of time to wait for an idle connection.A value of -1 indicates an illimted amount of time (i.e. forever)");
+
+ MBeanOperationInfo operation = new MBeanOperationInfo(
+ "addBroker",
+ "Connects QMan with a broker.",
+ parameters,
+ void.class.getName(),
+ MBeanOperationInfo.ACTION);
+
+ MBeanInfo mbean = new MBeanInfo(
+ QMan.class.getName(),
+ "QMan Management & Administration interface.",
+ null,
+ null,
+ new MBeanOperationInfo[]{operation},
+ null);
+
+ return mbean;
+ }
+
+ /**
+ * Invokes an operation on QMan (MBean).
+ *
+ * @param actionName the operation name.
+ * @param params the operation parameters.
+ * @param signature the operation signature.
+ * @return the result of the invocation (if the operation is not void);
+ * @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE> thrown by the MBean's invoked method.
+ * @exception ReflectionException Wraps a <CODE>java.lang.Exception</CODE> thrown while trying to invoke the method
+ */
+ public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException
+ {
+ if (Names.ADD_BROKER_OPERATION_NAME.equals(actionName))
+ {
+ try
+ {
+ addBroker(
+ (String)params[0],
+ (Integer)params[1],
+ (String)params[2],
+ (String)params[3],
+ (String)params[4],
+ (Integer)params[5],
+ (Integer)params[6],
+ (Long)params[7]);
+ } catch(Exception exception)
+ {
+ throw new MBeanException(exception);
+ }
+ } else
+ {
+ throw new ReflectionException(new NoSuchMethodException(actionName));
+ }
+ return null;
+ }
+
+ /**
+ * Not implemented for this MBean.
+ */
+ public void setAttribute(Attribute attribute)
+ {
+ }
+
+ /**
+ * Not implemented for this MBean.
+ */
+ public AttributeList setAttributes(AttributeList attributes)
+ {
+ return null;
+ }
+
+ /**
+ * Simply dispatches the incoming notification to registered listeners.
+ * Consider that the notification is sent asynchronously so the QMan current thread is not
+ * waiting for completion of receiver task.
+ *
+ * @param notification the incoming notification.
+ * @param handback the context associated to this notification.
+ */
+ public void handleNotification(final Notification notification, Object handback)
+ {
+ _workManager.execute(new Runnable(){
+ public void run()
+ {
+ sendNotification(notification);
+ }
+ });
+ }
+
+ /**
+ * Registers QMan as an MBean on MBeanServer.
+ *
+ * @throws MBeanException when it's not possible to proceeed with registration.
+ */
+ private void registerQManService() throws MBeanException
+ {
+ JmxService service = new JmxService();
+ service.registerQManService(this);
+
+ LOGGER.info(Messages.QMAN_000023_QMAN_REGISTERED_AS_MBEAN);
+ }
+
+ /**
+ * Configures work manager component.
+ */
+ private void configureWorkManager()
+ {
+ Configuration configuration = Configuration.getInstance();
+ _workManager = new ThreadPoolExecutor(
+ configuration.getWorkerManagerPoolSize(),
+ configuration.getWorkerManagerMaxPoolSize(),
+ configuration.getWorkerManagerKeepAliveTime(),
+ TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(30));
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java
new file mode 100644
index 0000000000..bd7d305184
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java
@@ -0,0 +1,361 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.QpidDatasource;
+import org.apache.qpid.management.domain.model.QpidMethod;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.messages.MethodInvocationRequestMessage;
+import org.apache.qpid.management.messages.SchemaRequestMessage;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageCreditUnit;
+import org.apache.qpid.transport.MessageTransfer;
+import org.apache.qpid.transport.Option;
+import org.apache.qpid.transport.Session;
+import org.apache.qpid.transport.SessionException;
+import org.apache.qpid.transport.SessionListener;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid Broker facade.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidService implements SessionListener
+{
+ private final static Logger LOGGER = Logger.get(QpidService.class);
+
+ private UUID _brokerId;
+ private Connection _connection;
+ private Session _session;
+ private Map<String,MessagePartListenerAdapter> _listeners;
+
+ /**
+ * Builds a new service with the given connection data.
+ *
+ * @param connectionData the connection data of the broker.
+ */
+ public QpidService(UUID brokerId)
+ {
+ this._brokerId = brokerId;
+ }
+
+ /**
+ * Estabilishes a connection with the broker.
+ *
+ * @throws QpidException in case of connection failure.
+ */
+ public void connect() throws Exception
+ {
+ _connection = QpidDatasource.getInstance().getConnection(_brokerId);
+ _listeners = new ConcurrentHashMap<String,MessagePartListenerAdapter>();
+ _session = _connection.createSession(0);
+ _session.setSessionListener(this);
+ }
+
+ public void opened(Session ssn) {}
+
+ public void resumed(Session ssn) {}
+
+ public void message(Session ssn, MessageTransfer xfr)
+ {
+ MessagePartListenerAdapter l = _listeners.get(xfr.getDestination());
+ if (l == null)
+ {
+ LOGGER.error("unhandled message: %s", xfr);
+ }
+ else
+ {
+ l.messageTransfer(xfr);
+ }
+ }
+
+
+ public void exception(Session ssn, SessionException exc)
+ {
+
+ }
+
+ public void closed(Session ssn) {}
+
+ /**
+ * All the previously entered outstanding commands are asynchronous.
+ * Synchronous behavior is achieved through invoking this method.
+ */
+ public void sync()
+ {
+ _session.sync();
+ }
+
+ /**
+ * Closes communication with broker.
+ */
+ public void close()
+ {
+ try
+ {
+ _session.close();
+ _session = null;
+ _listeners = null;
+ } catch (Exception e)
+ {
+ }
+ try
+ {
+ _connection.close();
+ _connection = null;
+ } catch (Exception e)
+ {
+ }
+ }
+
+ /**
+ * Associate a message listener with a destination therefore creating a new subscription.
+ *
+ * @param queueName The name of the queue that the subscriber is receiving messages from.
+ * @param destinationName the name of the destination, or delivery tag, for the subscriber.
+ * @param listener the listener for this destination.
+ *
+ * @see Session#messageSubscribe(String, String, short, short, org.apache.qpid.nclient.MessagePartListener, java.util.Map, org.apache.qpid.transport.Option...)
+ */
+ public void createSubscription(String queueName, String destinationName, MessageListener listener)
+ {
+ _listeners.put(destinationName, new MessagePartListenerAdapter(listener));
+ _session.messageSubscribe
+ (queueName,
+ destinationName,
+ MessageAcceptMode.NONE,
+ MessageAcquireMode.PRE_ACQUIRED,
+ null, 0, null);
+
+ _session.messageFlow(destinationName, MessageCreditUnit.BYTE, Session.UNLIMITED_CREDIT);
+ _session.messageFlow(destinationName, MessageCreditUnit.MESSAGE, Session.UNLIMITED_CREDIT);
+
+ LOGGER.debug(Messages.QMAN_200025_SUBSCRIPTION_DECLARED,queueName,destinationName);
+ }
+
+ /**
+ * Removes a previously declared consumer from the broker.
+ *
+ * @param destinationName the name of the destination, or delivery tag, for the subscriber.
+ * @see Session#messageCancel(String, Option...)
+ */
+ public void removeSubscription(String destinationName)
+ {
+ _session.messageCancel(destinationName);
+ LOGGER.debug(Messages.QMAN_200026_SUBSCRIPTION_REMOVED,destinationName);
+ }
+
+ /**
+ * Declares a queue on the broker with the given name.
+ *
+ * @param queueName the name of the declared queue.
+ * @see Session#queueDeclare(String, String, java.util.Map, Option...)
+ */
+ public void declareQueue(String queueName)
+ {
+ _session.queueDeclare(queueName, null, null);
+ LOGGER.debug(Messages.QMAN_200027_QUEUE_DECLARED,queueName);
+ }
+
+ /**
+ * Removes the queue with the given name from the broker.
+ *
+ * @param queueName the name of the queue.
+ * @see Session#queueDelete(String, Option...)
+ */
+ public void deleteQueue(String queueName)
+ {
+ _session.queueDelete(queueName);
+ LOGGER.debug(Messages.QMAN_200028_QUEUE_REMOVED,queueName);
+ }
+
+ /**
+ * Binds (on the broker) a queue with an exchange.
+ *
+ * @param queueName the name of the queue to bind.
+ * @param exchangeName the exchange name.
+ * @param routingKey the routing key used for the binding.
+ * @see Session#exchangeBind(String, String, String, java.util.Map, Option...)
+ */
+ public void declareBinding(String queueName, String exchangeName, String routingKey)
+ {
+ _session.exchangeBind(queueName, exchangeName, routingKey, null);
+ LOGGER.debug(Messages.QMAN_200029_BINDING_DECLARED,routingKey,queueName,exchangeName);
+ }
+
+ /**
+ * Removes a previously declare binding between an exchange and a queue.
+ *
+ * @param queueName the name of the queue.
+ * @param exchangeName the name of the exchange.
+ * @param routingKey the routing key used for binding.
+ */
+ public void declareUnbinding(String queueName, String exchangeName, String routingKey)
+ {
+ _session.exchangeUnbind(queueName, exchangeName, routingKey);
+ LOGGER.debug(Messages.QMAN_200030_BINDING_REMOVED,routingKey,queueName,exchangeName);
+ }
+
+ /**
+ * Sends a command message with the given data on the management queue.
+ *
+ * @param messageData the command message content.
+ */
+
+ /**
+ * Requests a schema for the given package.class.hash.
+ *
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param schemaHash the schema hash.
+ * @throws IOException when the schema request cannot be sent.
+ */
+ public void requestSchema(final String packageName, final String className, final Binary schemaHash) throws IOException
+ {
+ Message message = new SchemaRequestMessage()
+ {
+ @Override
+ protected String className ()
+ {
+ return className;
+ }
+
+ @Override
+ protected String packageName ()
+ {
+ return packageName;
+ }
+
+ @Override
+ protected Binary schemaHash ()
+ {
+ return schemaHash;
+ }
+ };
+
+ sendMessage(message);
+ }
+
+ /**
+ * Invokes an operation on a broker object instance.
+ *
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param schemaHash the schema hash of the corresponding class.
+ * @param objectId the object instance identifier.
+ * @param parameters the parameters for this invocation.
+ * @param method the method (definition) invoked.
+ * @param bankId the object bank identifier.
+ * @param brokerId the broker identifier.
+ * @return the sequence number used for this message.
+ * @throws MethodInvocationException when the invoked method returns an error code.
+ * @throws UnableToComplyException when it wasn't possibile to invoke the requested operation.
+ */
+ public void invoke(
+ final String packageName,
+ final String className,
+ final Binary schemaHash,
+ final Binary objectId,
+ final Object[] parameters,
+ final QpidMethod method,
+ final int sequenceNumber,
+ final long bankId,
+ final long brokerId) throws MethodInvocationException, UnableToComplyException
+ {
+ Message message = new MethodInvocationRequestMessage(bankId, brokerId)
+ {
+
+ @Override
+ protected int sequenceNumber ()
+ {
+ return sequenceNumber;
+ }
+
+ protected Binary objectId() {
+ return objectId;
+ }
+
+ protected String packageName()
+ {
+ return packageName;
+ }
+
+ protected String className()
+ {
+ return className;
+ }
+
+ @Override
+ protected QpidMethod method ()
+ {
+ return method;
+ }
+
+ @Override
+ protected Object[] parameters ()
+ {
+ return parameters;
+ }
+
+ @Override
+ protected Binary schemaHash ()
+ {
+ return schemaHash;
+ }
+ };
+
+ try {
+ sendMessage(message);
+ sync();
+ } catch(Exception exception) {
+ throw new UnableToComplyException(exception);
+ }
+ }
+
+ /**
+ * Sends a command message.
+ *
+ * @param message the command message.
+ * @throws IOException when the message cannot be sent.
+ */
+ public void sendMessage(Message message) throws IOException
+ {
+ _session.messageTransfer(
+ Names.MANAGEMENT_EXCHANGE,
+ MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ message.getHeader(),
+ message.readData());
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java
new file mode 100644
index 0000000000..e6d99971cd
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+/**
+ * Sequence number generator utility class.
+ *
+ * @author Andrea Gazzarini
+ */
+public class SequenceNumberGenerator
+{
+ private static int sequenceNumber;
+
+ /**
+ * Returns a valid sequence number.
+ *
+ * @return a sequence number.
+ */
+ public static synchronized int getNextSequenceNumber()
+ {
+ return sequenceNumber++;
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java
new file mode 100644
index 0000000000..9da8832624
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+/**
+ * Thrown in case of service startup failure.
+ * For example the configuration file couldn't be read because is not well-formed.
+ *
+ * @author Andrea Gazzarini.
+ */
+public class StartupFailureException extends Exception
+{
+ private static final long serialVersionUID = -4102037574602857703L;
+
+ /**
+ * Builds a new StartupFailureException with the given exception.
+ *
+ * @param exception the exception cause.
+ */
+ public StartupFailureException(Exception exception)
+ {
+ super(exception);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java
new file mode 100644
index 0000000000..2ab9a41e75
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+public class UnableToComplyException extends Exception
+{
+ public UnableToComplyException(Exception exception)
+ {
+ super(exception);
+ }
+
+ private static final long serialVersionUID = -3071434478559509435L;
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java b/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java
new file mode 100644
index 0000000000..d7f9d8d6f0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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 org.apache.qpid.management.jmx;
+
+import javax.management.Notification;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.services.SequenceNumberGenerator;
+
+/**
+ * Q-Man JMX entity lifecycle notification.
+ * A notification is sent to interested listener by Q-Man on the following scenarios :
+ *
+ * <br> - A schema (class / event) has been requested (Schema request);
+ * <br> - A schema (class / event) has been injected (Schema response);
+ * <br> - A schema cannot be parsed (probably it is malformed);
+ * <br> - An object instance has been created (Instrumentation / Configuration response);
+ * <br> - An event instance has been created (Instrumentation / Configuration response);
+ * <br> - An object instance has been removed (Instrumentation / Configuration response);
+ *
+ * @author Andrea Gazzarini
+ */
+public class EntityLifecycleNotification extends Notification
+{
+ private static final long serialVersionUID = -7755773156742412161L;
+
+ public static final String SCHEMA_INJECTED_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.entity.schema.injected";
+ public static final String SCHEMA_REQUESTED_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.entity.schema.requested";
+ public static final String MALFORMED_SCHEMA_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.error.schema";
+
+ public static final String INSTANCE_ADDED_NOTIFICATION_TYPE = "qman.lifecycle.entity.instance.created";
+ public static final String INSTANCE_REMOVED_NOTIFICATION_TYPE = "qman.lifecycle.entity.instance.removed";
+
+ private String _packageName = Names.NOT_AVAILABLE;
+ private String _className = Names.NOT_AVAILABLE;
+ private String _classKind = Names.NOT_AVAILABLE;
+
+ private ObjectName _objectName;
+
+ /**
+ * Builds a new notification with the given parameters.
+ *
+ * @param type the notification type.
+ * @param sequenceNumber the sequence number.
+ * @param packageName the package name.
+ * @param className the class name.
+ * @param classKind the class kind (i.e. class or event)
+ * @param objectName the object name of the affected mbean.
+ */
+ public EntityLifecycleNotification(
+ String type,
+ String packageName,
+ String className,
+ String classKind,
+ ObjectName objectName)
+ {
+ super(
+ type,
+ Names.APPLICATION_NAME,
+ SequenceNumberGenerator.getNextSequenceNumber());
+
+ this._className = className;
+ this._packageName = packageName;
+ this._classKind = classKind;
+ this._objectName = objectName;
+ }
+
+ /**
+ * Returns the package name of object contained in this notification.
+ *
+ * @return the package name of object contained in this notification.
+ */
+ public String getPackageName()
+ {
+ return _packageName;
+ }
+
+ /**
+ * Returns the class name of object contained in this notification.
+ *
+ * @return the class name of object contained in this notification.
+ */
+ public String getClassName()
+ {
+ return _className;
+ }
+
+ /**
+ * Returns the class kind of object contained in this notification.
+ *
+ * @return the class kind of object contained in this notification.
+ * @see Names#CLASS
+ * @see Names#EVENT
+ */
+ public String getClassKind()
+ {
+ return _classKind;
+ }
+
+ /**
+ * Returns the object name of object contained in this notification.
+ *
+ * @return the object name of object contained in this notification.
+ */
+ public ObjectName getObjectName()
+ {
+ return _objectName;
+ }
+
+ /**
+ * Returns a string representation of this notification.
+ *
+ * @return a string representation of this notification.
+ */
+ @Override
+ public String toString()
+ {
+ return new StringBuilder()
+ .append(getType())
+ .append(':')
+ .append(_packageName)
+ .append('.')
+ .append(_className)
+ .append('@')
+ .append(_objectName)
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java b/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java
new file mode 100644
index 0000000000..dec29c1b93
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java
@@ -0,0 +1,168 @@
+/*
+ *
+ * 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 org.apache.qpid.management.jmx;
+
+import javax.management.Notification;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.impl.InvocationResult;
+import org.apache.qpid.management.domain.services.SequenceNumberGenerator;
+
+/**
+ * Q-Man JMX method invocation notification.
+ * This kind of notification is sent to interested listener by Q-Man when
+ * a method has been invoked (Method invocation request)
+ *
+ * @author Andrea Gazzarini
+ */
+public class OperationHasBeenInvokedNotification extends Notification
+{
+ private static final long serialVersionUID = -7755773156742412161L;
+ public static final String NOTIFICATION_TYPE = "org.apache.qpid.management.operation.invoked";
+
+ private final String _operationName;
+ private final Object [] _parameters;
+ private final String [] _signature;
+ private final Exception _exception;
+ private final InvocationResult _result;
+
+ /**
+ * Builds a new notification with the given parameters.
+ *
+ * @param type the notification type.
+ * @param operationName the operation name.
+ * @param params the operation parameters.
+ * @param signature the operation signature.
+ * @param exception the exception raised by the invocation.
+ */
+ public OperationHasBeenInvokedNotification(
+ String operationName,
+ Object[] parameters,
+ String [] signature,
+ Exception exception)
+ {
+ super(
+ NOTIFICATION_TYPE,
+ Names.APPLICATION_NAME,
+ SequenceNumberGenerator.getNextSequenceNumber());
+
+ this._operationName= operationName;
+ this._parameters = parameters;
+ this._signature = signature;
+ this._result = null;
+ this._exception = exception;
+ }
+
+ /**
+ * Builds a new notification with the given parameters.
+ *
+ * @param type the notification type.
+ * @param operationName the operation name.
+ * @param params the operation parameters.
+ * @param signature the operation signature.
+ * @param objectName the target mbean object name.
+ * @param result the invocation result.
+ */
+ public OperationHasBeenInvokedNotification(
+ String operationName,
+ Object[] parameters,
+ String [] signature,
+ InvocationResult result)
+ {
+ super(
+ NOTIFICATION_TYPE,
+ Names.APPLICATION_NAME,
+ SequenceNumberGenerator.getNextSequenceNumber());
+
+ this._operationName= operationName;
+ this._parameters = parameters;
+ this._signature = signature;
+ this._result = result;
+ this._exception = null;
+ }
+
+ /**
+ * Returns the exception raised by this notification
+ * referred operation.
+ *
+ * @return the exception raised by this notification referred operation.
+ */
+ public Exception getException()
+ {
+ return _exception;
+ }
+
+ /**
+ * Returns the exception raised by this notification
+ * referred operation.
+ *
+ * @return the exception raised by this notification referred operation.
+ */
+ public InvocationResult getResult()
+ {
+ return _result;
+ }
+
+ /**
+ * Returns the operation name.
+ *
+ * @return the operation name.
+ */
+ public String getOperationName()
+ {
+ return _operationName;
+ }
+
+ /**
+ * Returns the parameters used in method invocation.
+ *
+ * @return the parameters used in method invocation.
+ */
+ public Object [] getParameters()
+ {
+ return _parameters;
+ }
+
+ /**
+ * Returns the signature of the invoked operation.
+ *
+ * @return the signature of the invoked operation.
+ */
+ public String [] getSignature()
+ {
+ return _signature;
+ }
+
+ /**
+ * Returns a string representation of this notification.
+ *
+ * @return a string representation of this notification.
+ */
+ @Override
+ public String toString()
+ {
+ return new StringBuilder()
+ .append(getType())
+ .append(':')
+ .append(_operationName)
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java
new file mode 100644
index 0000000000..2fa20fb456
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.messages;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.domain.services.SequenceNumberGenerator;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.codec.BBEncoder;
+
+/**
+ * Message implementation used for specific management purposes.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class ManagementMessage implements Message
+{
+ /**
+ * Strategy interface for building / getting data.
+ *
+ * @author Andrea Gazzarini
+ */
+ private interface IDataBuilderStrategy
+ {
+ ByteBuffer getData();
+ };
+
+ /**
+ * Strategy used for retrieving raw data from this message when it has been already encoded.
+ */
+ IDataBuilderStrategy READING = new IDataBuilderStrategy()
+ {
+ public ByteBuffer getData() {
+ return _data;
+ };
+ };
+
+ /**
+ * Strategy used for retrieving raw data from this message when it hasn't been already encoded.
+ */
+ IDataBuilderStrategy ACCUMULATING = new IDataBuilderStrategy()
+ {
+ public ByteBuffer getData() {
+ _codec.writeInt8((byte)opcode());
+ _codec.writeSequenceNo(sequenceNumber());
+
+ specificMessageEncoding();
+
+ _data =_codec.segment();
+ _reader = READING;
+ return _data;
+ }
+ };
+
+ protected BBEncoder _codec;
+ protected ByteBuffer _data;
+ private int _messageTransferId;
+ private IDataBuilderStrategy _reader = ACCUMULATING;
+
+ /**
+ * Builds an empty management message.
+ */
+ ManagementMessage()
+ {
+ _codec = new BBEncoder(100);
+ _codec.writeMagicNumber();
+ }
+
+ /**
+ * Returns the sequence number that will be used for this message.
+ *
+ * @return the sequence number that will be used for this message.
+ */
+ protected int sequenceNumber ()
+ {
+ return SequenceNumberGenerator.getNextSequenceNumber();
+ }
+
+ /**
+ * Returns the opcode that will be used for this message.
+ *
+ * @return the opcode that will be used for this message.
+ */
+ abstract char opcode ();
+
+ /**
+ * Returns the delivery properties of this message.
+ *
+ * @return the delivery properties of this message.
+ */
+ public DeliveryProperties getDeliveryProperties ()
+ {
+ return Configuration.getInstance().getCommandDeliveryProperties();
+ }
+
+ /**
+ * Returns the header of this message.
+ *
+ * @return the header of this message.
+ */
+ public Header getHeader ()
+ {
+ return Configuration.getInstance().getCommandMessageHeader();
+ }
+
+ /**
+ * Returns the messages header properties of this message.
+ *
+ * @return the message header properties of this message.
+ */
+ public MessageProperties getMessageProperties ()
+ {
+ return Configuration.getInstance().getCommandMessageProperties();
+ }
+
+ /**
+ * Returns the transfer Id of this message.
+ *
+ * @return the transfer Id of this message.
+ */
+ public int getMessageTransferId ()
+ {
+ return _messageTransferId;
+ }
+
+ /**
+ * Returns the encoded data of this message.
+ *
+ * @return the encoded data of this message.
+ */
+ public ByteBuffer readData () throws IOException
+ {
+ return _reader.getData();
+ }
+
+ /**
+ * Sets the header for this message.
+ *
+ * @param header the new message header.
+ */
+ public void setHeader (Header header)
+ {
+ // N.A. at the moment.
+ }
+
+ public void appendData (byte[] src) throws IOException
+ {
+ }
+
+ public void appendData (ByteBuffer src) throws IOException
+ {
+ }
+
+ public void clearData ()
+ {
+ }
+
+ public void readData (byte[] target) throws IOException
+ {
+ }
+
+ /**
+ * Concrete subclasses (message implementations) must define here their specific data encoding.
+ */
+ abstract void specificMessageEncoding();
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java
new file mode 100644
index 0000000000..99916085d6
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java
@@ -0,0 +1,161 @@
+/*
+ *
+ * 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 org.apache.qpid.management.messages;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.domain.model.QpidMethod;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.ReplyTo;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Abstract representation of a method invocation request message.
+ * Concrete subclasses must supply the values needed to build & encode the message.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class MethodInvocationRequestMessage extends ManagementMessage
+{
+ private final static Logger LOGGER = Logger.get(MethodInvocationRequestMessage.class);
+
+ private DeliveryProperties _deliveryProperties;
+ private MessageProperties _messageProperties;
+ private Header _header;
+
+ /**
+ * Builds a new method invocation request message with the given target identifiers.
+ *
+ * @param bankId the bank identifier.
+ * @param brokerId the broker identifier.
+ */
+ public MethodInvocationRequestMessage(long bankId, long brokerId)
+ {
+ ReplyTo replyTo=new ReplyTo();
+ replyTo.setRoutingKey(Configuration.getInstance().getMethodReplyQueueName());
+ _messageProperties = new MessageProperties();
+ _messageProperties.setReplyTo(replyTo);
+
+ String routingKey = String.format(Names.AGENT_ROUTING_KEY_PREFIX+"%s.%s", brokerId,bankId);
+
+ LOGGER.debug(Messages.QMAN_200032_COMMAND_MESSAGE_ROUTING_KEY, routingKey);
+
+ _deliveryProperties = new DeliveryProperties();
+ _deliveryProperties.setRoutingKey(routingKey);
+ _header = new Header(_deliveryProperties, _messageProperties);
+ }
+
+ @Override
+ char opcode ()
+ {
+ return Protocol.OPERATION_INVOCATION_REQUEST_OPCODE;
+ }
+
+ /**
+ * Returns the package name.
+ *
+ * @return the package name.
+ */
+ protected abstract String packageName();
+
+ /**
+ * Returns the class name.
+ *
+ * @return the class name.
+ */
+ protected abstract String className();
+
+ /**
+ * Returns the schema hash.
+ *
+ * @return the schema hash.
+ */
+ protected abstract Binary schemaHash();
+
+ /**
+ * Returns the object identifier.
+ *
+ * @return the object identifier.
+ */
+ protected abstract Binary objectId();
+
+ /**
+ * Returns the method to be invoked.
+ *
+ * @return the method to be invoked.
+ */
+ protected abstract QpidMethod method();
+
+ /**
+ * Returns the parameters used for method invocation.
+ *
+ * @return the parameters used for method invocation.
+ */
+ protected abstract Object[] parameters();
+
+ /**
+ * Returns the delivery properties of this message.
+ *
+ * @return the delivery properties of this message.
+ */
+ public DeliveryProperties getDeliveryProperties ()
+ {
+ return _deliveryProperties;
+ }
+
+ /**
+ * Returns the header of this message.
+ *
+ * @return the header of this message.
+ */
+ public Header getHeader ()
+ {
+ return _header;
+ }
+
+ /**
+ * Returns the messages header properties of this message.
+ *
+ * @return the message header properties of this message.
+ */
+ public MessageProperties getMessageProperties ()
+ {
+ return _messageProperties;
+ }
+
+ @Override
+ void specificMessageEncoding ()
+ {
+ objectId().encode(_codec);
+ _codec.writeStr8(packageName());
+ _codec.writeStr8(className());
+ schemaHash().encode(_codec);
+
+ QpidMethod method = method();
+ _codec.writeStr8(method.getName());
+ method.encodeParameters(parameters(), _codec);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java
new file mode 100644
index 0000000000..9df1733649
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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 org.apache.qpid.management.messages;
+
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Abstract representation of a schema request message.
+ * Concrete subclasses must supply the values needed to build & encode the message.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class SchemaRequestMessage extends ManagementMessage
+{
+ @Override
+ char opcode ()
+ {
+ return Protocol.SCHEMA_REQUEST_OPCODE;
+ }
+
+ /**
+ * Returns the package name.
+ *
+ * @return the package name.
+ */
+ protected abstract String packageName();
+
+ /**
+ * Returns the class name.
+ *
+ * @return the class name.
+ */
+ protected abstract String className();
+
+ /**
+ * Returns the schema hash.
+ *
+ * @return the schema hash.
+ */
+ protected abstract Binary schemaHash();
+
+ @Override
+ final void specificMessageEncoding ()
+ {
+ _codec.writeStr8(packageName());
+ _codec.writeStr8(className());
+ schemaHash().encode(_codec);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java
new file mode 100644
index 0000000000..8f73098e20
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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 org.apache.qpid.management.servlet;
+
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.muse.core.platform.mini.MiniServlet;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.BrokerConnectionData;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.domain.services.QMan;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * When QMan is started and a configuration file is given
+ * (via system property) with initial broker connection data(s),
+ * this servlet simply sends connect command(s) to QMan in order
+ * to estabilish the connection(s) to the requested broker(s).
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConnectQManToBroker extends MiniServlet
+{
+ private static final long serialVersionUID = 6149614872902682208L;
+ private final static Logger LOGGER = Logger.get(ConnectQManToBroker.class);
+
+ /**
+ * Send one or more initial "connect" command(s) to QMan in order
+ * to estabilish a connection with broker found on the configuration file..
+ * Note that this is done only if that configuration file is given (via system
+ * property) and it is valid.
+ */
+ public void init()
+ {
+ Configuration configuration = Configuration.getInstance();
+ if (configuration.hasOneOrMoreBrokersDefined())
+ {
+ QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME);
+
+ LOGGER.info(Messages.QMAN_000003_CREATING_MANAGEMENT_CLIENTS);
+ for (Entry<UUID, BrokerConnectionData> entry : Configuration.getInstance().getConnectionInfos())
+ {
+ qman.createManagementClient(entry.getKey(), entry.getValue());
+ }
+ } else
+ {
+ LOGGER.info(Messages.QMAN_000022_NO_BROKER_CONFIGURED);
+ }
+ }
+
+ /**
+ * This is a startup module only so an override of the default servlet
+ * behaviour must be done in order to prevent incoming http
+ * requests processing.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException each time this method is called.
+ */
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException
+ {
+ throw new ServletException();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java
new file mode 100644
index 0000000000..edd6804e68
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.servlet;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.services.QMan;
+import org.apache.qpid.management.domain.services.StartupFailureException;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * QMan JMX lifecycle manager.
+ * Provides lifecycle management of QMan JMX core including startup and shutdown.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QManLifeCycleManager implements ServletContextListener
+{
+ private final static Logger LOGGER = Logger.get(QManLifeCycleManager.class);
+
+ /**
+ * Starts QMan JMX Core.
+ *
+ * @param event the application context event.
+ */
+ public void contextInitialized(ServletContextEvent event)
+ {
+ try
+ {
+ QMan qman = new QMan();
+ qman.start();
+ event.getServletContext().setAttribute(
+ Names.APPLICATION_NAME,
+ qman);
+ } catch (StartupFailureException exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100030_JMX_CORE_STARTUP_FAILURE);
+ }
+ }
+
+ /**
+ * Sutdown QMan JMX Core.
+ *
+ * @param event the application context event.
+ */
+ public void contextDestroyed(ServletContextEvent event)
+ {
+ ServletContext context = event.getServletContext();
+
+ QMan qman = (QMan) context.getAttribute(Names.APPLICATION_NAME);
+ qman.stop();
+
+ context.removeAttribute(Names.APPLICATION_NAME);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java
new file mode 100644
index 0000000000..c6fcde08c4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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 org.apache.qpid.management.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterIsolationLayer;
+import org.apache.qpid.qman.debug.XmlDebugger;
+import org.apache.qpid.transport.util.Logger;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * QMan Adapter facade.
+ * This is the main requestor entry point of the WS-DM connector / adapter.
+ * All WSDM requests will be handled (at higher level) by this servlet.
+ *
+ * @author Andrea Gazzarini
+ */
+public class WSDMAdapter extends HttpServlet
+{
+ private static final long serialVersionUID = 6149614872902682208L;
+ private final static Logger LOGGER = Logger.get(WSDMAdapter.class);
+ private WSDMAdapterIsolationLayer _isolationLayer;
+
+ @Override
+ public void init() throws ServletException {
+ LOGGER.debug(Messages.QMAN_000026_WSDM_ADAPTER_STARTS);
+
+ _isolationLayer = new WSDMAdapterIsolationLayer(getServletContext());
+ _isolationLayer.initialize();
+
+ LOGGER.debug(Messages.QMAN_000027_WSDM_ADAPTER_STARTED);
+
+ }
+
+ /**
+ * Accepts http requests containing a soap envelope (request) and therefore
+ * acts as the main entry point of whole WS process.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException in case of application failure.
+ * @throws IOException in case of generic I/O failure.
+ */
+ @Override
+ protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
+ {
+ PrintWriter writer = response.getWriter();
+
+ Document soapEnvelopeRequest = null;
+ String soapEnvelopeResposeAsString = null;
+
+ try
+ {
+ soapEnvelopeRequest = XmlUtils.createDocument(request.getInputStream());
+
+ Document soapEnvelopeResponse = _isolationLayer.handleRequest(soapEnvelopeRequest);
+ soapEnvelopeResposeAsString = XmlUtils.toString(soapEnvelopeResponse,false,true);
+
+ response.setContentType("text/xml");
+
+ writer.write(soapEnvelopeResposeAsString);
+ } catch (SAXException exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100019_REQ_OR_RES_MALFORMED);
+ throw new ServletException(exception);
+ } finally {
+ writer.flush();
+
+ XmlDebugger.debug(soapEnvelopeRequest);
+ try {
+ XmlDebugger.debug(soapEnvelopeResposeAsString);
+ } catch(Exception exception) {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100019_REQ_OR_RES_MALFORMED);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java
new file mode 100644
index 0000000000..09b7309b96
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Names;
+
+/**
+ * Value Object encapsulating a broker management domain model.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokerModel
+{
+ private Map<String, List<ObjectName>> _objectsByType = new HashMap<String, List<ObjectName>>();
+ private String _id;
+
+ /**
+ * Adds a new object to this domain model.
+ *
+ * @param name the object name of the JMX entity.
+ */
+ void addObject(ObjectName name)
+ {
+ String packageName = name.getKeyProperty(Names.PACKAGE);
+ String className = name.getKeyProperty(Names.CLASS);
+ if (className != null)
+ {
+ String fqn = packageName+"."+className;
+
+ List<ObjectName> objects = _objectsByType.get(fqn);
+ if (objects == null)
+ {
+ objects = new ArrayList<ObjectName>();
+ _objectsByType.put(fqn,objects);
+ }
+ objects.add(name);
+ }
+ }
+
+ /**
+ * Gets the identifier of the owner of this model.
+ *
+ * @return the identifier of the owner of this model.
+ */
+ public String getId()
+ {
+ return _id;
+ }
+
+ /**
+ * Sets the identifier of the owner of this model.
+ *
+ * @param id the identifier of the owner of this model.
+ */
+ public void setId(String id)
+ {
+ this._id = id;
+ }
+
+ public Set<String> getCategoryNames()
+ {
+ return _objectsByType.keySet();
+ }
+
+ public List<ObjectName> getCategory(String name)
+ {
+ return _objectsByType.get(name);
+ }
+
+ public int getCategoryCount()
+ {
+ return _objectsByType.keySet().size();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java
new file mode 100644
index 0000000000..509c86c08b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.BrokerAlreadyConnectedException;
+import org.apache.qpid.management.configuration.BrokerConnectionData;
+import org.apache.qpid.management.configuration.BrokerConnectionException;
+import org.apache.qpid.management.domain.services.ManagementClient;
+import org.apache.qpid.management.domain.services.QMan;
+
+/**
+ * This controller is responsible to :
+ *
+ * <ul>
+ * <li> prepare data for the page that is showing all connected brokers.</li>.
+ * </li> connect QMan with a broker on demand.
+ * </ul>
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokersManagementAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ /**
+ * Retrieves all connected brokers (their connection data) and prepare the model that
+ * is then forwarded to the appropriate view page.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException in case of failure while forwarding to the view component.
+ * @throws IOException in case of failure while forwarding to the view component.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME);
+ List<ManagementClient> managementClients = qman.getManagementClients();
+
+ List<BrokerConnectionData> brokers = new ArrayList<BrokerConnectionData>(managementClients.size());
+
+ if (!managementClients.isEmpty())
+ {
+ for (ManagementClient managementClient : managementClients)
+ {
+ brokers.add(managementClient.getBrokerConnectionData());
+ }
+ request.setAttribute("model", brokers);
+ }
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ /**
+ * Connects QMan with a new broker and forwards to
+ * the brokers list view page.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException in case of failure while forwarding to the view component.
+ * @throws IOException in case of failure while forwarding to the view component.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME);
+
+ String host = request.getParameter("host");
+ String portString = request.getParameter("port");
+ String virtualHost = request.getParameter("virtualHost");
+ String username = request.getParameter("username");
+ String password = request.getParameter("password");
+
+ String initialCapacityString = request.getParameter("initialCapacity");
+ String maxCapacityString = request.getParameter("maxCapacity");
+ String maxWaitTimeoutString = request.getParameter("maxWaitTimeout");
+
+ List<String> errors = new LinkedList<String>();
+ int port = 0;
+ int initialPoolCapacity = 0;
+ int maxPoolCapacity = 0;
+ long maxWaitTimeout = 0;
+
+ if(host== null || host.trim().length()==0)
+ {
+ errors.add("Invalid value for \"host\" attribute. Must be not null.");
+ }
+
+ if(virtualHost == null || virtualHost.trim().length()==0)
+ {
+ errors.add("Invalid value for \"virtualHost\" attribute. Must be not null.");
+ }
+
+ try
+ {
+ port = Integer.parseInt(portString);
+ } catch(Exception exception)
+ {
+ errors.add("Invalid value for \"port\" attribute. Must be not null and must be a number.");
+ }
+
+ try
+ {
+ initialPoolCapacity = Integer.parseInt(initialCapacityString);
+ } catch(Exception exception)
+ {
+ errors.add("Invalid value for \"Initial Pool Capacity\" attribute. Must be not null and must be a number.");
+ }
+
+ try
+ {
+ maxPoolCapacity = Integer.parseInt(maxCapacityString);
+ } catch(Exception exception)
+ {
+ errors.add("Invalid value for \"Max Pool Capacity\" attribute. Must be not null and must be a number.");
+ }
+
+ try
+ {
+ maxWaitTimeout = Long.parseLong(maxWaitTimeoutString);
+ } catch(Exception exception)
+ {
+ errors.add("Invalid value for \"Max Wait Timeout\" attribute. Must be not null and must be a number.");
+ }
+
+ request.setAttribute("errors", errors);
+
+ if (errors.isEmpty())
+ {
+ qman.addBroker(
+ host,
+ port,
+ username,
+ password,
+ virtualHost,
+ initialPoolCapacity,
+ maxPoolCapacity,
+ maxWaitTimeout);
+ }
+ doGet(request, response);
+ }catch(BrokerAlreadyConnectedException exception)
+ {
+ request.setAttribute("errorMessage","Supplied data refers to an already connected broker...");
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp");
+ dispatcher.forward(request,response);
+ }
+ catch(BrokerConnectionException exception)
+ {
+ request.setAttribute("errorMessage","Unable to connect with the requested broker...");
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java
new file mode 100644
index 0000000000..ee098882f1
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.util.Date;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * This action is the controller responsible to prepare data for the home
+ * page (System Overview) of QMan admin console.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConsoleAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ private static final Logger LOGGER = Logger.get(ConsoleAction.class);
+
+ private Date _startDate;
+
+ /**
+ * Initializes this controller.
+ * Simply it computes the start date of the application.
+ */
+ @Override
+ public void init()
+ {
+ _startDate = new Date();
+ }
+
+ /**
+ * Prepares data for System Overview admin console page and forward that data to that page.
+ *
+ * @throws ServletException when this controller is not able to forward to the appropriate view page.
+ * @throws IOException when this controller is not able to forward to the appropriate view page.
+ */
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ ConsoleModel model = new ConsoleModel();
+ model.setVersion("1.0");
+ model.setVersionName("Sofia");
+ model.setStartDate(_startDate);
+ model.setHost(System.getProperty(Names.ADAPTER_HOST_PROPERTY_NAME, "localhost"));
+ model.setPort(Integer.parseInt(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME, "8080")));
+
+ try
+ {
+ OperatingSystemMXBean operatingSystem = ManagementFactory.getOperatingSystemMXBean();
+ model.setOsName(operatingSystem.getName());
+ model.setProcessors(operatingSystem.getAvailableProcessors());
+ model.setOsVersion(operatingSystem.getVersion());
+ model.setArchName(operatingSystem.getArch());
+ } catch(Exception exception)
+ {
+ LOGGER.warn(exception,Messages.QMAN_300006_OS_MBEAN_FAILURE);
+ model.setOsName("N.A.");
+ model.setProcessors(null);
+ model.setOsVersion("N.A.");
+ model.setArchName("N.A.");
+ }
+
+ try
+ {
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+
+ String bootClasspath = runtime.getBootClassPath();
+ model.setBootClasspath(bootClasspath.split(File.pathSeparator));
+
+ String classpath = runtime.getClassPath();
+ model.setClasspath(classpath.split(File.pathSeparator));
+
+ model.setInputArguments(runtime.getInputArguments().toArray(new String[]{}));
+ } catch(Exception exception)
+ {
+ LOGGER.warn(exception,Messages.QMAN_300007_RUNTIME_MBEAN_FAILURE);
+ }
+
+ request.setAttribute("model", model);
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/console.jsp");
+ dispatcher.forward(request,response);
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java
new file mode 100644
index 0000000000..ac0e1d2bbd
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java
@@ -0,0 +1,158 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.web.action;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Console Model.
+ * It is a simple Data Transfer Object encapsulating all information about QMan
+ * console (System Overview)
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConsoleModel implements Serializable
+{
+ private static final long serialVersionUID = -7676132151242738376L;
+ private String _version;
+ private String _versionName;
+ private Date _startDate;
+ private String _host;
+ private int _port;
+
+ private String _osName;
+ private String _osVersion;
+ private String _archName;
+ private Integer _processors;
+
+ private String [] _bootClasspath;
+ private String [] _classpath;
+ private String [] _inputArguments;
+ private String [] _systemProperties;
+
+ public String getVersion()
+ {
+ return _version;
+ }
+ public void setVersion(String version)
+ {
+ this._version = version;
+ }
+ public String getVersionName()
+ {
+ return _versionName;
+ }
+ public void setVersionName(String versionName)
+ {
+ this._versionName = versionName;
+ }
+ public Date getStartDate()
+ {
+ return _startDate;
+ }
+ public void setStartDate(Date startDate)
+ {
+ this._startDate = startDate;
+ }
+ public String getHost()
+ {
+ return _host;
+ }
+ public void setHost(String host)
+ {
+ this._host = host;
+ }
+ public int getPort()
+ {
+ return _port;
+ }
+ public void setPort(int port)
+ {
+ this._port = port;
+ }
+ public String getOsName()
+ {
+ return _osName;
+ }
+ public void setOsName(String osName)
+ {
+ this._osName = osName;
+ }
+ public String getOsVersion()
+ {
+ return _osVersion;
+ }
+ public void setOsVersion(String osVersion)
+ {
+ this._osVersion = osVersion;
+ }
+ public String getArchName()
+ {
+ return _archName;
+ }
+ public void setArchName(String archName)
+ {
+ this._archName = archName;
+ }
+ public Integer getProcessors()
+ {
+ return _processors;
+ }
+ public void setProcessors(Integer processors)
+ {
+ this._processors = processors;
+ }
+ public List<String> getBootClasspath()
+ {
+ return Arrays.asList(_bootClasspath);
+ }
+ public void setBootClasspath(String [] bootClasspath)
+ {
+ this._bootClasspath = bootClasspath;
+ }
+ public String [] getClasspath()
+ {
+ return _classpath;
+ }
+ public void setClasspath(String [] classpath)
+ {
+ this._classpath = classpath;
+ }
+ public String [] getInputArguments()
+ {
+ return _inputArguments;
+ }
+ public void setInputArguments(String [] inputArguments)
+ {
+ this._inputArguments = inputArguments;
+ }
+ public String [] getSystemProperties()
+ {
+ return _systemProperties;
+ }
+ public void setSystemProperties(String [] systemProperties)
+ {
+ this._systemProperties = systemProperties;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java
new file mode 100644
index 0000000000..59777cc9c8
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This controller is responsible to provide a jmx perspective of a specific resource.
+ * That means that this controller is querying the Platform MBean server in order to
+ * get metadata for the requested mbean.
+ *
+ * After that metadata will be forwarded to the appropriate view page and therefore
+ * will be shown on the Admin console.
+ *
+ * @author Andrea Gazzarini
+ */
+public class JmxPerspectiveAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ /**
+ * Adapter interface for converting objects on html strings.
+ *
+ * @author Andrea Gazzarini.
+ */
+ interface JavaToHtmlAdapter
+ {
+ /**
+ * Returns an HTML string representation of the given object.
+ *
+ * @param javaObject the object that needs to be converted.
+ * @return an html string containing value of the given object.
+ */
+ String toHtml(Object javaObject);
+ }
+
+ /**
+ * Adapter implementation for Map (and subclasses).
+ */
+ private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter()
+ {
+ @SuppressWarnings("unchecked")
+ public String toHtml(Object javaObject)
+ {
+ Map<String,Object> value = (Map<String, Object>) javaObject;
+
+ // Sanity check : if the map is empty or null there's no need to
+ // do any convertion
+ if (value == null || value.isEmpty())
+ {
+ return "(empty)";
+ }
+
+ StringBuilder builder = new StringBuilder("<ul>");
+ for (Entry<String, Object> entry : value.entrySet())
+ {
+ builder
+ .append("<li>")
+ .append(entry.getKey())
+ .append(" = ")
+ .append(entry.getValue());
+ }
+ builder.append("</ul>");
+ return builder.toString();
+ }
+ };
+
+ private Map<String, JavaToHtmlAdapter> _adapters = new HashMap<String, JavaToHtmlAdapter>();
+
+ @Override
+ public void init() throws ServletException
+ {
+ _adapters.put(Map.class.getName(), mapAdapter);
+ _adapters.put(HashMap.class.getName(),mapAdapter);
+ _adapters.put(Properties.class.getName(),mapAdapter);
+ _adapters.put(Hashtable.class.getName(),mapAdapter);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ String resourceId = null;
+ try
+ {
+ resourceId = request.getParameter("resourceId");
+
+ ObjectName objectName = new ObjectName(resourceId);
+ String [] keyProperties = objectName.getKeyPropertyListString().split(",");
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ MBeanInfo metadata = server.getMBeanInfo(objectName);
+
+ Map<String, String> attributes = getAttributes(server, objectName,metadata.getAttributes());
+
+ request.setAttribute("resourceId", objectName);
+ request.setAttribute("metadata",metadata);
+ request.setAttribute("nameAttributes",keyProperties);
+ request.setAttribute("attributes",attributes);
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/jmx_perspective.jsp");
+ dispatcher.forward(request,response);
+ } catch(MalformedObjectNameException exception)
+ {
+ request.setAttribute("errorMessage","Malformed Resource ID : supplied value is "+resourceId);
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+
+ }
+ catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ /**
+ * Starting from an mbean metadata, this method retrieves all the attributes
+ * from the corresponding MBean Server.
+ *
+ * @param server the mbean server where the target mbean is registered.
+ * @param name the name of the target mbean.
+ * @param metadata the metadata of mbean.
+ * @return a map containing all attributes of the given mbean.
+ * @throws Exception when it's not possible to retrieve attributes.
+ */
+ private Map<String, String> getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception
+ {
+ Map<String,String> result = new HashMap<String, String>(metadata.length);
+ for (MBeanAttributeInfo attribute : metadata)
+ {
+ Object value = server.getAttribute(name, attribute.getName());
+ result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value));
+ }
+ return result;
+ }
+
+ /**
+ * Converts the given attribute value in a html string format.
+ *
+ * @param type the java type of the given attribute value.
+ * @param value the attribute value.
+ * @return a html string format of the given value.
+ */
+ private String getAdaptedValue(String type, Object value)
+ {
+ JavaToHtmlAdapter adapter = _adapters.get(type);
+ return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java
new file mode 100644
index 0000000000..aefd4ca8dd
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.qpid.qman.debug.WsdlDebugger;
+import org.apache.qpid.qman.debug.XmlDebugger;
+
+/**
+ * Logging configuration controller.
+ * Accepts input parameters from admin console and configure the underlying
+ * logging subsystem at runtime.
+ *
+ * @author Andrea Gazzarini
+ */
+public class LoggingConfigurationAction extends HttpServlet
+{
+ private static final long serialVersionUID = 633352305870632824L;
+
+ private final static String WSDL_DEBUG_ENABLED_PARAM = "wsdlDebugEnabled";
+ private final static String SOAP_DEBUG_ENABLED_PARAM = "soapDebugEnabled";
+ private final static String WEB_SERVER_LOG_LEVEL_PARAM = "webServerLogLevel";
+ private final static String QMAN_LOG_LEVEL_PARAM = "qmanLogLevel";
+
+ private final static String WEB_SERVER_PACKAGE = "org.mortbay";
+ private final static String QMAN_PACKAGE = "org.qpid.apache.management";
+
+ /**
+ * Retrieves current logging configuration and forward those data to the logging configuration view page.
+ * In this way that page will be able to display the current logging settings.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException when this controller is not able to forward to the appropriate view page.
+ * @throws IOException when this controller is not able to forward to the appropriate view page.
+ */
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ Level messageDebuggerLogLevel = Logger.getLogger(XmlDebugger.class).getEffectiveLevel();
+ Level wsdlDebuggerLogLevel = Logger.getLogger(WsdlDebugger.class).getEffectiveLevel();
+ Level webServerLogLevel = Logger.getLogger(WEB_SERVER_PACKAGE).getEffectiveLevel();
+ Level qmanLogLevel = Logger.getLogger(QMAN_PACKAGE).getEffectiveLevel();
+
+ request.setAttribute(WSDL_DEBUG_ENABLED_PARAM,wsdlDebuggerLogLevel.equals(Level.DEBUG));
+ request.setAttribute(SOAP_DEBUG_ENABLED_PARAM,messageDebuggerLogLevel.equals(Level.DEBUG));
+ request.setAttribute(WEB_SERVER_LOG_LEVEL_PARAM,webServerLogLevel);
+ request.setAttribute(QMAN_LOG_LEVEL_PARAM,qmanLogLevel);
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/logging_configuration.jsp");
+ dispatcher.forward(request, response);
+ }
+
+ /**
+ * Accepts user data coming from admin console and use it for configure the underlying logging
+ * subsystem.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException when this controller is not able to forward to the appropriate view page.
+ * @throws IOException when this controller is not able to forward to the appropriate view page.
+ */
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ String wsdlDebugEnabled = request.getParameter(WSDL_DEBUG_ENABLED_PARAM);
+ String soapDebugEnabled = request.getParameter(SOAP_DEBUG_ENABLED_PARAM);
+
+ String qmanLevel = request.getParameter(QMAN_LOG_LEVEL_PARAM);
+ String serverLevel = request.getParameter(WEB_SERVER_LOG_LEVEL_PARAM);
+
+ Logger.getLogger(WEB_SERVER_PACKAGE).setLevel(Level.toLevel(serverLevel));
+ Logger.getLogger(QMAN_PACKAGE).setLevel(Level.toLevel(qmanLevel));
+
+ Logger.getLogger(WsdlDebugger.class).setLevel(
+ "on".equals(wsdlDebugEnabled)
+ ? Level.DEBUG
+ : Level.INFO);
+
+ Logger.getLogger(XmlDebugger.class).setLevel(
+ "on".equals(soapDebugEnabled)
+ ? Level.DEBUG
+ : Level.INFO);
+
+ doGet(request, response);
+ }
+}
+ \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java
new file mode 100644
index 0000000000..f1a55be6bf
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.services.ManagementClient;
+import org.apache.qpid.management.domain.services.QMan;
+
+/**
+ * This controller retrieves from QMan all the registered resources and organize
+ * that data in a model that is then forwarded to the appropriate view page.
+ *
+ * TODO : In the corresponding view page only one broker is displayed.
+ * A query should be made on QMan mbean in order to retrieve all connected broker and therefore
+ * a model for each of them should be created.
+ * In the corresponding weg page there should be a "tab" for each broker. Each tab should show only
+ * the objects belonging to that broker.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ResourcesManagementAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME);
+ List<ManagementClient> managementClient = qman.getManagementClients();
+
+ if (!managementClient.isEmpty())
+ {
+ BrokerModel model = new BrokerModel();
+ model.setId(managementClient.toString());
+
+ MBeanServer mxServer = ManagementFactory.getPlatformMBeanServer();
+ Set<ObjectName> objectNames = mxServer.queryNames(new ObjectName("Q-MAN:*"), null);
+ for (ObjectName objectName : objectNames)
+ {
+ model.addObject(objectName);
+ }
+
+ request.setAttribute("model", model);
+ }
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/resources_management.jsp");
+ dispatcher.forward(request,response);
+ } catch(MalformedObjectNameException exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java
new file mode 100644
index 0000000000..ca5b3285b0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+/**
+ * This controller is responsible to retirve operations metadata from a WS-Resource.
+ * That metadat will be forwarded and used by the corresponding view page.
+ *
+ * TODO : This is not really showing WS metadata. Insted JMX metadata is used here.
+ *
+ * @author Andrea Gazzarini
+ *
+ */
+public class WsdmOperationsPerspectiveAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ private ProxyHandler proxyHandler;
+
+ interface JavaToHtmlAdapter
+ {
+ String toHtml(Object javaObject);
+ }
+
+ private URI resourceUri;
+
+ private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter()
+ {
+ @SuppressWarnings("unchecked")
+ public String toHtml(Object javaObject)
+ {
+ Map<String,Object> value = (Map<String, Object>) javaObject;
+
+ if (value == null || value.isEmpty())
+ {
+ return "(empty)";
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("<ul>");
+ for (Entry<String, Object> entry : value.entrySet())
+ {
+ builder
+ .append("<li>")
+ .append(entry.getKey())
+ .append(" = ")
+ .append(entry.getValue());
+ }
+ builder.append("</ul>");
+ return builder.toString();
+ }
+ };
+
+ private Map<String, JavaToHtmlAdapter> adapters = new HashMap<String, JavaToHtmlAdapter>();
+
+ @Override
+ public void init() throws ServletException
+ {
+ adapters.put(Map.class.getName(), mapAdapter);
+ adapters.put(HashMap.class.getName(),mapAdapter);
+ adapters.put(Properties.class.getName(),mapAdapter);
+ adapters.put(Hashtable.class.getName(),mapAdapter);
+
+ proxyHandler = new ReflectionProxyHandler();
+ proxyHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ proxyHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", Names.PREFIX));
+ proxyHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", Names.PREFIX)});
+ proxyHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", Names.PREFIX));
+ proxyHandler.setReturnType(Element[].class);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ String resourceId = request.getParameter("resourceId");
+ ObjectName objectName = new ObjectName(resourceId);
+ String wsdmResourceId = objectName.getKeyProperty(Names.OBJECT_ID);
+
+ EndpointReference resourceEndpointReference = new EndpointReference(getURI(request));
+ resourceEndpointReference.addParameter(
+ Names.RESOURCE_ID_QNAME,
+ wsdmResourceId);
+
+// WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference);
+// Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0];
+// Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0];
+
+ String [] keyProperties = objectName.getKeyPropertyListString().split(",");
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ MBeanInfo metadata = server.getMBeanInfo(objectName);
+
+ Map<String, String> attributes = getAttributes(server, objectName,metadata.getAttributes());
+
+ request.setAttribute("resourceId", resourceId);
+ request.setAttribute("metadata",metadata);
+ request.setAttribute("nameAttributes",keyProperties);
+ request.setAttribute("attributes",attributes);
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_operations_perspective.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ private URI getURI(HttpServletRequest request)
+ {
+ if (resourceUri == null)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append(request.getProtocol())
+ .append("//")
+ .append(request.getServerName())
+ .append(":")
+ .append(request.getServerPort())
+ .append("/qman/services/QManWsResource");
+ resourceUri = URI.create(builder.toString());
+ }
+ return resourceUri;
+ }
+
+ private Map<String, String> getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception
+ {
+ Map<String,String> result = new HashMap<String, String>(metadata.length);
+ for (MBeanAttributeInfo attribute : metadata)
+ {
+ Object value = server.getAttribute(name, attribute.getName());
+ result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value));
+ }
+ return result;
+ }
+
+ private String getAdaptedValue(String type, Object value)
+ {
+ JavaToHtmlAdapter adapter = adapters.get(type);
+ return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java
new file mode 100644
index 0000000000..e3a8eb50d7
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+public class WsdmPropertiesPerspectiveAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+
+ private ProxyHandler proxyHandler;
+
+ interface JavaToHtmlAdapter
+ {
+ String toHtml(Object javaObject);
+ }
+
+ private URI resourceUri;
+
+ private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter()
+ {
+ @SuppressWarnings("unchecked")
+ public String toHtml(Object javaObject)
+ {
+ Map<String,Object> value = (Map<String, Object>) javaObject;
+
+ if (value == null || value.isEmpty())
+ {
+ return "(empty)";
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("<ul>");
+ for (Entry<String, Object> entry : value.entrySet())
+ {
+ builder
+ .append("<li>")
+ .append(entry.getKey())
+ .append(" = ")
+ .append(entry.getValue());
+ }
+ builder.append("</ul>");
+ return builder.toString();
+ }
+ };
+
+ private Map<String, JavaToHtmlAdapter> adapters = new HashMap<String, JavaToHtmlAdapter>();
+
+ @Override
+ public void init() throws ServletException
+ {
+ adapters.put(Map.class.getName(), mapAdapter);
+ adapters.put(HashMap.class.getName(),mapAdapter);
+ adapters.put(Properties.class.getName(),mapAdapter);
+ adapters.put(Hashtable.class.getName(),mapAdapter);
+
+ proxyHandler = new ReflectionProxyHandler();
+ proxyHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ proxyHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", Names.PREFIX));
+ proxyHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", Names.PREFIX)});
+ proxyHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", Names.PREFIX));
+ proxyHandler.setReturnType(Element[].class);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ String resourceId = request.getParameter("resourceId");
+ ObjectName objectName = new ObjectName(resourceId);
+
+ String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID);
+
+ EndpointReference resourceEndpointReference = new EndpointReference(getURI(request));
+ resourceEndpointReference.addParameter(
+ Names.RESOURCE_ID_QNAME,
+ wsresourceid);
+
+// WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference);
+// Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0];
+// Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0];
+
+ String [] keyProperties = objectName.getKeyPropertyListString().split(",");
+
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ MBeanInfo metadata = server.getMBeanInfo(objectName);
+
+ Map<String, String> attributes = getAttributes(server, objectName,metadata.getAttributes());
+
+ request.setAttribute("resourceId", resourceId);
+ request.setAttribute("metadata",metadata);
+ request.setAttribute("nameAttributes",keyProperties);
+ request.setAttribute("attributes",attributes);
+
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_properties_perspective.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ private URI getURI(HttpServletRequest request)
+ {
+ if (resourceUri == null)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append(request.getProtocol())
+ .append("//")
+ .append(request.getServerName())
+ .append(":")
+ .append(request.getServerPort())
+ .append("/qman/services/QManWsResource");
+ resourceUri = URI.create(builder.toString());
+ }
+ return resourceUri;
+ }
+
+ private Map<String, String> getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception
+ {
+ Map<String,String> result = new HashMap<String, String>(metadata.length);
+ for (MBeanAttributeInfo attribute : metadata)
+ {
+ Object value = server.getAttribute(name, attribute.getName());
+ result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value));
+ }
+ return result;
+ }
+
+ private String getAdaptedValue(String type, Object value)
+ {
+ JavaToHtmlAdapter adapter = adapters.get(type);
+ return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java
new file mode 100644
index 0000000000..b4c488e97c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java
@@ -0,0 +1,139 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.net.URI;
+
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.metadata.WsxConstants;
+import org.apache.muse.ws.resource.metadata.WsrmdConstants;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+public class WsdmRmdPerspectiveAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+ private static final Object [] RMD_DIALECT = new Object[]{WsrmdConstants.NAMESPACE_URI};
+
+ private ProxyHandler proxyHandler;
+
+ private URI resourceUri;
+
+ @Override
+ public void init() throws ServletException
+ {
+ proxyHandler = new ReflectionProxyHandler();
+ proxyHandler.setAction(WsxConstants.GET_METADATA_URI);
+ proxyHandler.setRequestName(WsxConstants.GET_METADATA_QNAME);
+ proxyHandler.setRequestParameterNames(new QName[]{
+ new QName(
+ WsxConstants.NAMESPACE_URI,
+ WsxConstants.DIALECT,
+ WsxConstants.PREFIX)});
+ proxyHandler.setResponseName(WsxConstants.METADATA_QNAME);
+ proxyHandler.setReturnType(Element[].class);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ String resourceId = request.getParameter("resourceId");
+ ObjectName objectName = new ObjectName(resourceId);
+
+ String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID);
+ EndpointReference resourceEndpointReference = new EndpointReference(getURI(request));
+
+ resourceEndpointReference.addParameter(
+ Names.RESOURCE_ID_QNAME,
+ wsresourceid);
+
+ WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference);
+ Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0];
+
+// NodeList nodelist = wsdl.getChildNodes();
+// Element definitions = null;
+// for (int i = 0; i < nodelist.getLength(); i++)
+// {
+// Node node = nodelist.item(i);
+// switch (node.getNodeType())
+// {
+// case Node.ELEMENT_NODE:
+// {
+// Element element = (Element) node;
+// if (element.getNodeName().indexOf("definitions") != -1)
+// {
+// definitions = element;
+// break;
+// }
+// }
+// }
+// }
+
+ String output = XmlUtils.toString(rmd);
+
+ String [] keyProperties = objectName.getKeyPropertyListString().split(",");
+
+ request.setAttribute("resourceId", resourceId);
+ request.setAttribute("nameAttributes",keyProperties);
+ request.setAttribute("rmd",output);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_rmd_perspective.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ private URI getURI(HttpServletRequest request)
+ {
+ if (resourceUri == null)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("http://")
+ .append(request.getServerName())
+ .append(":")
+ .append(request.getServerPort())
+ .append("/qman/services/QManWsResource");
+ resourceUri = URI.create(builder.toString());
+ }
+ return resourceUri;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java
new file mode 100644
index 0000000000..77a5237037
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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 org.apache.qpid.management.web.action;
+
+import java.io.IOException;
+import java.net.URI;
+
+import javax.management.ObjectName;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.metadata.WsxConstants;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class WsdmWsdlPerspectiveAction extends HttpServlet
+{
+ private static final long serialVersionUID = -2411413147821629363L;
+ private static final Object [] WSDL_DIALECT = new Object[]{WsxConstants.WSDL_DIALECT};
+
+ private ProxyHandler proxyHandler;
+
+ private URI resourceUri;
+
+ @Override
+ public void init() throws ServletException
+ {
+ proxyHandler = new ReflectionProxyHandler();
+ proxyHandler.setAction(WsxConstants.GET_METADATA_URI);
+ proxyHandler.setRequestName(WsxConstants.GET_METADATA_QNAME);
+ proxyHandler.setRequestParameterNames(new QName[]{
+ new QName(
+ WsxConstants.NAMESPACE_URI,
+ WsxConstants.DIALECT,
+ WsxConstants.PREFIX)});
+ proxyHandler.setResponseName(WsxConstants.METADATA_QNAME);
+ proxyHandler.setReturnType(Element[].class);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ String resourceId = request.getParameter("resourceId");
+ ObjectName objectName = new ObjectName(resourceId);
+
+ String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID);
+ EndpointReference resourceEndpointReference = new EndpointReference(getURI(request));
+
+ resourceEndpointReference.addParameter(
+ Names.RESOURCE_ID_QNAME,
+ wsresourceid);
+
+ WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference);
+ Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0];
+
+ NodeList nodelist = wsdl.getChildNodes();
+ Element definitions = null;
+ for (int i = 0; i < nodelist.getLength(); i++)
+ {
+ Node node = nodelist.item(i);
+ switch (node.getNodeType())
+ {
+ case Node.ELEMENT_NODE:
+ {
+ Element element = (Element) node;
+ if (element.getNodeName().indexOf("definitions") != -1)
+ {
+ definitions = element;
+ break;
+ }
+ }
+ }
+ }
+
+ String output = XmlUtils.toString(definitions);
+
+ String [] keyProperties = objectName.getKeyPropertyListString().split(",");
+
+ request.setAttribute("resourceId", resourceId);
+ request.setAttribute("nameAttributes",keyProperties);
+ request.setAttribute("wsdl",output);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_wsdl_perspective.jsp");
+ dispatcher.forward(request,response);
+ } catch(Exception exception)
+ {
+ request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
+ request.setAttribute("exception",exception);
+ RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
+ dispatcher.forward(request,response);
+ }
+ }
+
+ private URI getURI(HttpServletRequest request)
+ {
+ if (resourceUri == null)
+ {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("http://")
+ .append(request.getServerName())
+ .append(":")
+ .append(request.getServerPort())
+ .append("/qman/services/QManWsResource");
+ resourceUri = URI.create(builder.toString());
+ }
+ return resourceUri;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java
new file mode 100644
index 0000000000..79a387e80c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java
@@ -0,0 +1,130 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.impl.QpidDomainObject;
+import org.apache.qpid.management.domain.handler.impl.QpidDomainObjectMBean;
+import org.apache.qpid.management.jmx.EntityLifecycleNotification;
+
+/**
+ * QEmu is basically an instance creator that is installed separately
+ * as part of QMan test cases & examples.
+ * Reason for that is to emulate object creation (queues, exchanges, etc...)
+ * without having Qpid broker connected and therefore controlling the
+ * total number of the instances that are created.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QEmu extends NotificationBroadcasterSupport implements QEmuMBean, MBeanRegistration{
+
+ private MBeanServer _mxServer;
+ private final static String PACKAGE_NAME= "org.apache.qpid";
+ private final static String QUEUE = "queue";
+
+ /**
+ * Unregisters a Queue MBean with MBeanServer.
+ *
+ * @param objectName the name of the MBean that must unregistered.
+ * @throws Exception when the creation or the registration fails.
+ */
+ public void unregister(ObjectName objectName) throws Exception
+ {
+ _mxServer.unregisterMBean(objectName);
+
+ sendNotification(
+ EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE,
+ objectName);
+ }
+
+ /**
+ * Creates and registers a Queue MBean with MBeanServer.
+ *
+ * @param objectName the name of the queue MBean.
+ * @throws Exception when the creation or the registration fails.
+ */
+ public void createQueue(ObjectName objectName) throws Exception
+ {
+ QpidDomainObjectMBean queue = new QpidDomainObject();
+ _mxServer.registerMBean(queue, objectName);
+
+ sendNotification(
+ EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE,
+ objectName);
+ }
+
+ /**
+ * Sends a notification about a lifecycle event of the mbean associated
+ * with the given object.
+ *
+ * @param type the event (notification) type.
+ * @param name the name of the event source.
+ */
+ private void sendNotification(String type,ObjectName name)
+ {
+ sendNotification(
+ new EntityLifecycleNotification(
+ type,
+ PACKAGE_NAME,
+ QUEUE,
+ Names.CLASS,
+ name));
+ }
+
+ /**
+ * Not implemented for this class.
+ */
+ public void postDeregister()
+ {
+ // N.A.
+ }
+
+ /**
+ * Not implemented for this class.
+ */
+ public void postRegister(Boolean registrationDone)
+ {
+ // N.A.
+ }
+
+ /**
+ * Not implemented for this class.
+ */
+ public void preDeregister()
+ {
+ // N.A.
+ }
+
+ /**
+ * MBean server callback.
+ * Stores the value of the owner MBeanServer.
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ {
+ this._mxServer = server;
+ return name;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java
new file mode 100644
index 0000000000..47aa4ea681
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm;
+
+import java.lang.management.ManagementFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * QPid Emulator Initializer.
+ * This component is basically responsible to create and initialize
+ * an emulator module used for simulate object instances creation.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QEmuInitializer extends HttpServlet
+{
+ private static final long serialVersionUID = 6149614872902682208L;
+ private final static Logger LOGGER = Logger.get(QEmuInitializer.class);
+
+ /**
+ * QEmu initialization method.
+ *
+ * @throws ServletException when the module cannot be initialized.
+ */
+ public void init() throws ServletException
+ {
+ try
+ {
+ ManagementFactory.getPlatformMBeanServer().registerMBean(
+ new QEmu(),
+ Names.QPID_EMULATOR_OBJECT_NAME);
+ } catch(Exception exception)
+ {
+ LOGGER.warn(
+ exception,
+ Messages.QMAN_300005_QEMU_INITIALIZATION_FAILURE);
+ throw new ServletException(exception);
+ }
+ }
+
+ /**
+ * This is a startup module only so an override of the
+ * default servlet behaviour must be done in order to
+ * prevent incoming http requests processing.
+ *
+ * @param request the http request.
+ * @param response the http response.
+ * @throws ServletException each time this method is called.
+ */
+ @Override
+ public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException
+ {
+ throw new ServletException();
+ }
+
+ /**
+ * Unregister QPid emulator.
+ */
+ public void destroy()
+ {
+ try
+ {
+ ManagementFactory.getPlatformMBeanServer().unregisterMBean(
+ Names.QPID_EMULATOR_OBJECT_NAME);
+ } catch (Exception exception)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java
new file mode 100644
index 0000000000..f22e7ff12d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java
@@ -0,0 +1,48 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm;
+
+import javax.management.ObjectName;
+
+/**
+ * Management interface for QEmu.
+ *
+ * @author Andrea Gazzarini
+ * @see QEmu
+ */
+public interface QEmuMBean
+{
+ /**
+ * Creates and registers a Queue MBean with MBeanServer.
+ *
+ * @param objectName the name of the queue MBean.
+ * @throws Exception when the creation or the registration fails.
+ */
+ void createQueue(ObjectName name) throws Exception;
+
+ /**
+ * Unregisters a Queue MBean with MBeanServer.
+ *
+ * @param objectName the name of the MBean that must unregistered.
+ * @throws Exception when the creation or the registration fails.
+ */
+ void unregister(ObjectName name) throws Exception;
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java
new file mode 100644
index 0000000000..eef70b5544
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import javax.management.ObjectName;
+
+/**
+ * Thrown when the artifacts related to a specific resource cannot be built.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ArtifactsNotAvailableException extends Exception
+{
+ private static final long serialVersionUID = -9010460152421791926L;
+
+ private final WsArtifacts _artifacts;
+ private final ObjectName _objectName;
+
+ /**
+ * Builds a new exception with the given arguments.
+ *
+ * @param artifacts the artifacts built.
+ * @param cause the exception cause.
+ * @param objectName the object name of the corresponding JMX entity.
+ */
+ public ArtifactsNotAvailableException(
+ WsArtifacts artifacts,
+ Throwable cause,
+ ObjectName objectName)
+ {
+ super(cause);
+ this._artifacts = artifacts;
+ this._objectName = objectName;
+ }
+
+ /**
+ * Returns a message that indicates which artifacts were built.
+ *
+ * @return a message that indicates which artifacts were built.
+ */
+ @Override
+ public String getMessage()
+ {
+ StringBuilder builder = new StringBuilder();
+ if (_artifacts == null)
+ {
+ return super.getMessage();
+ }
+
+ builder.append("Built artifacts for ")
+ .append(_objectName)
+ .append(" : ")
+ .append( (_artifacts.getWsdl() != null) ? "WSDL," : "")
+ .append( (_artifacts.getCapabilityClass() != null) ? "Capability Class," : "")
+ .append( (_artifacts.getResourceMetadataDescriptor() != null) ? "Resource Metadata Descriptor," : "");
+ return builder.toString();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java
new file mode 100644
index 0000000000..f3c8077d46
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+/**
+ * Thrown when a WSRF artifact (either WSDL or capability) cannot be built.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BuilderException extends Exception
+{
+ private static final long serialVersionUID = -8267818907567906262L;
+
+ /**
+ * Builds a new exception with the given cause.
+ *
+ * @param cause the exception cause.
+ */
+ public BuilderException(Exception cause)
+ {
+ super(cause);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java
new file mode 100644
index 0000000000..59a5801505
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+public interface Constants
+{
+ String WSRP_PROPERTIES_XPATH = "/wsdl:definitions/wsdl:types/xsd:schema[" +
+ "@targetNamespace='http://amqp.apache.org/qpid/management/qman']" +
+ "/xsd:element[@name='QManWsResourceProperties']/xsd:complexType/xsd:sequence";
+
+ String SERVICE_LOCATION_XPATH = "/wsdl:definitions/wsdl:service/wsdl:port/wsdl-soap:address/@location";
+ String QMAN_SCHEMA_XPATH = "/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://amqp.apache.org/qpid/management/qman']";
+
+ String MIN_OCCURS = "minOccurs";
+ String REF_ATTRIBUTE = "ref";
+ String NAME_ATTRIBUTE = "name";
+ String TYPE_ATTRIBUTE ="type";
+
+ QName XSD_ELEMENT_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"element","xsd");
+ QName XSD_COMPLEX_TYPE_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"complexType","xsd");
+ QName XSD_SEQUENCE_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"sequence","xsd");
+
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java
new file mode 100644
index 0000000000..bde98092a0
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import org.apache.muse.core.AbstractCapability;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.notification.NotificationConsumer;
+import org.apache.muse.ws.notification.NotificationMessage;
+import org.apache.muse.ws.notification.NotificationMessageListener;
+import org.apache.muse.ws.notification.WsnConstants;
+
+/**
+ * WS-Notifications consumer capability.
+ * At the moment QMan is not a consumer of itself so this capability is here only
+ * for test purposes.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ConsumerCapability extends AbstractCapability implements NotificationMessageListener
+{
+ /**
+ * Initializes this capability and register itself as message listener.
+ *
+ * @throws SoapFault when the initialization fails.
+ */
+ public void initializeCompleted() throws SoapFault
+ {
+ super.initializeCompleted();
+
+ NotificationConsumer wsn = (NotificationConsumer)getResource().getCapability(WsnConstants.CONSUMER_URI);
+ wsn.addMessageListener(this);
+ }
+
+ /**
+ * Returns true if this consumer can accepts the message.
+ *
+ * @return true;
+ */
+ public boolean accepts(NotificationMessage message)
+ {
+ return true;
+ }
+
+ /**
+ * On Message callback.
+ */
+ public void process(NotificationMessage message)
+ {
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java
new file mode 100644
index 0000000000..370cf3086d
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectName;
+
+import org.apache.muse.core.Environment;
+
+/**
+ * Dummy capability builder used for avoid duplicated builds for the
+ * same class.
+ * Basically it acts likes a Null Object when the target capability class has been
+ * already built.
+ *
+ * @author Andrea Gazzarini
+ */
+public class DummyCapabilityBuilder implements IArtifactBuilder
+{
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void begin(ObjectName objectName)
+ {
+ }
+
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void endAttributes()
+ {
+ }
+
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void endOperations()
+ {
+ }
+
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void onAttribute(MBeanAttributeInfo attributeMetadata)
+ {
+ }
+
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void onOperation(MBeanOperationInfo operationMetadata)
+ {
+ }
+
+ /**
+ * Director callback.
+ * Do nothing here (see class comments above.)
+ */
+ public void setEnvironment(Environment environment)
+ {
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java
new file mode 100644
index 0000000000..70b9b0e009
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectName;
+
+import org.apache.muse.core.Environment;
+
+/**
+ * Defines behaviour needed by WS-DM artifact builders.
+ * Each concrete implementor must provide its own parser
+ * implementation of the given JMX data.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface IArtifactBuilder
+{
+ /**
+ * The build process begin and the given parameter is the
+ * object name of the corresponding JMX entity.
+ *
+ * @throws BuilderException when the initialization fails.
+ */
+ void begin(ObjectName objectName) throws BuilderException;
+
+ /**
+ * Processes an attribute (its metadata) of the current MBean.
+ *
+ * @param attributeMetadata the attribute metadata.
+ * @throws BuilderException when the builder cannot parse the given metadata.
+ */
+ void onAttribute(MBeanAttributeInfo attributeMetadata) throws BuilderException;
+
+ /**
+ * Processes an operation (its metadata) of the current MBean.
+ *
+ * @param operationMetadata the operation metadata.
+ * @throws BuilderException when the builder cannot parse the given metadata.
+ */
+ void onOperation(MBeanOperationInfo operationMetadata) throws BuilderException;
+
+ /**
+ * Ends of the attributes section.
+ *
+ * @throws BuilderException when the builder encounter a problem during this phase..
+ */
+ void endAttributes() throws BuilderException;
+
+ /**
+ * Ends of the operations section.
+ *
+ * @throws BuilderException when the builder encounter a problem during this phase..
+ */
+ void endOperations() throws BuilderException;
+
+ /**
+ * Injects the adapter enviroment on this builder.
+ *
+ * @param environment the adapter environment.
+ */
+ void setEnvironment(Environment environment);
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java
new file mode 100644
index 0000000000..37ecc0c031
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java
@@ -0,0 +1,219 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.Attribute;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.muse.ws.resource.impl.AbstractWsResourceCapability;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.domain.handler.impl.InvocationResult;
+import org.apache.qpid.management.domain.services.MethodInvocationException;
+import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault;
+import org.apache.qpid.management.wsdm.common.MethodInvocationFault;
+import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault;
+import org.apache.qpid.management.wsdm.common.QManFault;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Abstract capability used for centralize common
+ * behaviour of the QMan resource(s) related capabilities.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class MBeanCapability extends AbstractWsResourceCapability
+{
+ private static final Logger LOGGER = Logger.get(MBeanCapability.class);
+
+ protected final MBeanServer _mxServer;
+ protected ObjectName _objectName;
+
+ /**
+ * Builds a new capability related to the given object name.
+ *
+ * @param objectName the name of the target object of this capability.
+ */
+ public MBeanCapability()
+ {
+ _mxServer = ManagementFactory.getPlatformMBeanServer();
+ }
+
+ /**
+ * Injects on this capability the object name of the target mbean.
+ *
+ * @param objectName the object name of the target mbean.
+ */
+ void setResourceObjectName(ObjectName objectName)
+ {
+ this._objectName = objectName;
+ }
+
+ /**
+ * Returns the attribute value of a QMan managed object instance.
+ *
+ * @param attributeName the name of the attribute to be requested.
+ * @return the value for the requested attribute.
+ * @throws NoSuchAttributeFault when the requested attribute cannot be found
+ * on the given entity instance.
+ * @throws EntityInstanceNotFoundFault when the requested entity instance cannot
+ * be found.
+ * @throws QManFault in case of internal system failure.
+ */
+ Object getAttribute(String attributeName) throws NoSuchAttributeFault, EntityInstanceNotFoundFault, QManFault
+ {
+ try
+ {
+ return _mxServer.getAttribute(_objectName, attributeName);
+ } catch (AttributeNotFoundException exception)
+ {
+ throw new NoSuchAttributeFault(
+ getWsResource().getEndpointReference(),
+ attributeName);
+ } catch (InstanceNotFoundException exception)
+ {
+ throw new EntityInstanceNotFoundFault(
+ getWsResource().getEndpointReference(),
+ _objectName);
+ } catch (Exception exception)
+ {
+ LOGGER.error(
+ Messages.QMAN_100035_GET_ATTRIBUTE_FAILURE,
+ attributeName,
+ _objectName);
+ throw new QManFault(
+ getWsResource().getEndpointReference(),
+ exception);
+ }
+ }
+
+ /**
+ * Sets the value for the given attribute on this MBean (proxy).
+ *
+ * @param objectName
+ * the object name of the target instance (excluding the domain
+ * name).
+ * @param attributeName
+ * the name of the attribute to be requested.
+ * @param value
+ * the value for the requested attribute.
+ * @throws NoSuchAttributeFault
+ * when the requested attribute cannot be found on the given
+ * entity instance.
+ * @throws EntityInstanceNotFoundFault
+ * when the requested entity instance cannot be found.
+ * @throws QManFault
+ * in case of internal system failure.
+ */
+ void setAttribute(String attributeName, Object value) throws NoSuchAttributeFault, EntityInstanceNotFoundFault, QManFault
+ {
+ try
+ {
+ _mxServer.setAttribute(_objectName, new Attribute(attributeName,value));
+ } catch (AttributeNotFoundException exception)
+ {
+ throw new NoSuchAttributeFault(
+ getWsResource().getEndpointReference(),
+ attributeName);
+ } catch (InstanceNotFoundException exception)
+ {
+ throw new EntityInstanceNotFoundFault(
+ getWsResource().getEndpointReference(),
+ _objectName);
+ } catch (Exception exception)
+ {
+ LOGGER.error(
+ Messages.QMAN_100036_SET_ATTRIBUTE_FAILURE,
+ attributeName,
+ _objectName);
+ throw new QManFault(
+ getWsResource().getEndpointReference(),
+ exception);
+ }
+ }
+
+ /**
+ * Invokes the requested operation on target JMX resource.
+ *
+ * @param operationName the name of the operation to be invoked.
+ * @param params parameters used for operation invocation.
+ * @param signature the operation / method signature.
+ * @throws EntityInstanceNotFoundFault
+ * when the target MBean doesn't exist on Management server.
+ * @throws MethodInvocationFault
+ * when the invocation of the requested operation raises an exception.
+ * @throws QManFault
+ * in case of not-well known failure.
+ */
+ Result invoke(String operationName, Object [] params, String [] signature) throws EntityInstanceNotFoundFault, MethodInvocationFault,QManFault
+ {
+ try
+ {
+ InvocationResult output = (InvocationResult) _mxServer
+ .invoke(
+ _objectName,
+ operationName,
+ params,
+ signature);
+
+ return new Result(output.getOutputSection());
+
+ } catch (InstanceNotFoundException exception)
+ {
+ throw new EntityInstanceNotFoundFault(
+ getWsResource().getEndpointReference(),
+ _objectName);
+ } catch (MBeanException exception)
+ {
+ if (exception.getTargetException() instanceof MethodInvocationException)
+ {
+ MethodInvocationException failure = (MethodInvocationException) exception.getTargetException();
+ throw new MethodInvocationFault(
+ getWsResource().getEndpointReference(),
+ operationName,
+ failure.getStatusText(),
+ failure.getReturnCode());
+ } else {
+ LOGGER.error(
+ Messages.QMAN_100037_INVOKE_OPERATION_FAILURE,
+ operationName,
+ _objectName);
+ throw new QManFault(
+ getWsResource().getEndpointReference(),
+ exception);
+ }
+ }catch(Exception exception)
+ {
+ LOGGER.error(
+ Messages.QMAN_100037_INVOKE_OPERATION_FAILURE,
+ operationName,
+ _objectName);
+ throw new QManFault(
+ getWsResource().getEndpointReference(),
+ exception);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java
new file mode 100644
index 0000000000..ea67bdf9e1
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java
@@ -0,0 +1,549 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import javassist.CannotCompileException;
+import javassist.ClassClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewMethod;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.Environment;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault;
+import org.apache.qpid.management.wsdm.common.MethodInvocationFault;
+import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault;
+import org.apache.qpid.management.wsdm.common.QManFault;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Builder for capability class that will implements the interface
+ * and the behaviour of the underlying JMX Entity.
+ * The product of this builder (capability class) will be used for create a new instance
+ * of the corresponding capability. It will be the "adapter" between WS-Resource and
+ * JMX MBean.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MBeanCapabilityBuilder implements IArtifactBuilder{
+
+ private final static String GET_PROPERTY_NAMES_METHOD_COMMON_PART = "public QName[] getPropertyNames() { return ";
+ private final static String GET_PROPERTY_NAMES_METHOD_WITH_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" PROPERTIES;}";
+ private final static String GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" new QName[0];}";
+ private final static Logger LOGGER = Logger.get(MBeanCapabilityBuilder.class);
+
+ /**
+ * Handler interface definining operation needed to be
+ * peformed (by a concrete implementor) when the "endAttributes"
+ * director callback happens.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface EndAttributesHandler {
+
+ /**
+ * Concrete implementor must define in this method what
+ * needs to be done when the corresponding director callback
+ * happens (@see {@link MBeanCapabilityBuilder#endAttributes()}
+ *
+ * @throws BuilderException when a failure is raised inside the concrete implementation.
+ */
+ void endAttributes() throws BuilderException;
+ };
+
+ /**
+ * This is the concrete implementation of the internal interface EndAttributesHandler
+ * that is activated when this builder detects the presence of at least one property on the
+ * capability class.
+ */
+ final EndAttributesHandler _atLeastThereIsOneProperty = new EndAttributesHandler() {
+
+ /**
+ * Creates the QName array instance member and the corresponding
+ * accessor getPropertyNames().
+ *
+ * @throws BuilderException when the member above cannot be added to the capability class.
+ */
+ public void endAttributes() throws BuilderException
+ {
+ try
+ {
+ _properties.deleteCharAt(_properties.length()-1);
+ _properties.append("};");
+
+ CtField properties = CtField.make(_properties.toString(), _capabilityClassDefinition);
+
+ _capabilityClassDefinition.addField(properties);
+
+ CtMethod getPropertyNames = CtNewMethod.make(
+ GET_PROPERTY_NAMES_METHOD_WITH_ARRAY,
+ _capabilityClassDefinition);
+ _capabilityClassDefinition.addMethod(getPropertyNames);
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+ };
+
+ /**
+ * This is the concrete implementation of the internal interface EndAttributesHandler
+ * that is activated when this builder detects that there are no properties defined for
+ * the capability class.
+ */
+ final EndAttributesHandler _noPropertyHasBeenDefined= new EndAttributesHandler()
+ {
+ /**
+ * Creates the getPropertyNames() that simply returns an empty QName array.
+ *
+ * @throws BuilderException when the member above cannot be added to the capability class.
+ */
+ public void endAttributes() throws BuilderException
+ {
+ try
+ {
+ CtMethod getPropertyNames = CtNewMethod.make(
+ GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY,
+ _capabilityClassDefinition);
+ _capabilityClassDefinition.addMethod(getPropertyNames);
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+ };
+
+ /**
+ * This is the active state for this builder when the requested class has never been
+ * built.
+ */
+ IArtifactBuilder _classNotAvailable = new IArtifactBuilder()
+ {
+
+ /**
+ * Build process begins.
+ * The given object name is used to build a minimal definition of the product class.
+ *
+ * @param objectName the name of the JMX entity.
+ * @throws BuilderException when the initial definiton of the capability cannot be created.
+ */
+ public void begin(ObjectName objectName) throws BuilderException
+ {
+ String className = objectName.getKeyProperty(Names.CLASS);
+ ClassPool pool = ClassPool.getDefault();
+ pool.insertClassPath(new ClassClassPath(MBeanCapabilityBuilder.class));
+ pool.importPackage(QName.class.getPackage().getName());
+ pool.importPackage(ObjectName.class.getPackage().getName());
+ pool.importPackage(QManFault.class.getPackage().getName());
+ pool.importPackage(Names.class.getPackage().getName());
+ pool.importPackage(Result.class.getPackage().getName());
+ pool.importPackage(NoSuchAttributeFault.class.getPackage().getName());
+ pool.importPackage(EntityInstanceNotFoundFault.class.getPackage().getName());
+ pool.importPackage(MethodInvocationFault.class.getPackage().getName());
+
+ _capabilityClassDefinition = pool.makeClass("org.apache.qpid.management.wsdm.capabilities."+className);
+ try
+ {
+ _capabilityClassDefinition.setSuperclass(pool.get(MBeanCapability.class.getName()));
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+
+ /**
+ * Director callback.
+ * All attributes have been notified.
+ *
+ * This builder is using this callback in order to create the initial
+ * properties QNames declaration.
+ *
+ */
+ public void endAttributes() throws BuilderException
+ {
+ _endAttributeHandler.endAttributes();
+ }
+
+ @SuppressWarnings("unchecked")
+ public void endOperations() throws BuilderException
+ {
+ try
+ {
+ _capabilityClass = _capabilityClassDefinition.toClass(
+ QManAdapterCapability.class.getClassLoader(),
+ QManAdapterCapability.class.getProtectionDomain());
+ } catch (Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+
+ /**
+ * Director callback.
+ * Attrbute metadata notification. With this callback the director informs this builder that the
+ * currently processed MBean has an attribute with the given metadata.
+ * This builder uses this information in order to add a property and the corresponding accessors
+ * to the capability class that is going to be built.
+ *
+ * @throws BuilderException bytecode manipulation / creation failure.
+ */
+ public void onAttribute(MBeanAttributeInfo attribute) throws BuilderException
+ {
+ String name = attribute.getName();
+ String type = attribute.getType();
+
+ try
+ {
+ type = Class.forName(type).getCanonicalName();
+
+ addPropertyMemberInstance(type, name);
+
+ String nameForAccessors = getNameForAccessors(name);
+
+ if (attribute.isReadable())
+ {
+ String accessor = generateGetter(type, nameForAccessors,name);
+ CtMethod getter = CtNewMethod.make(accessor,_capabilityClassDefinition);
+ _capabilityClassDefinition.addMethod(getter);
+ appendToPropertiesArray(name);
+
+ LOGGER.debug(
+ Messages.QMAN_200043_GENERATED_ACCESSOR_METHOD,
+ _objectName,
+ accessor);
+ }
+
+ if (attribute.isWritable())
+ {
+ String accessor = generateSetter(type, nameForAccessors,name);
+ CtMethod setter = CtNewMethod.make(accessor,_capabilityClassDefinition);
+ _capabilityClassDefinition.addMethod(setter);
+
+ LOGGER.debug(
+ Messages.QMAN_200043_GENERATED_ACCESSOR_METHOD,
+ _objectName,
+ accessor);
+ }
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+
+ public void onOperation(MBeanOperationInfo operation) throws BuilderException
+ {
+ StringBuilder method = new StringBuilder();
+ try
+ {
+ method
+ .append("public Result ")
+ .append(operation.getName())
+ .append("( ");
+
+ for (MBeanParameterInfo parameter: operation.getSignature())
+ {
+ method
+ .append(Class.forName(parameter.getType()).getCanonicalName())
+ .append(' ')
+ .append(parameter.getName())
+ .append(',');
+ }
+
+ method.deleteCharAt(method.length()-1);
+ method.append(") throws EntityInstanceNotFoundFault, MethodInvocationFault,QManFault { return invoke(")
+ .append("\"").append(operation.getName()).append("\"")
+ .append(", new Object[]{ ");
+
+ for (MBeanParameterInfo parameter: operation.getSignature())
+ {
+ method.append(parameter.getName())
+ .append(',');
+ }
+
+ method.deleteCharAt(method.length()-1);
+ method.append("}, new String[]{ ");
+
+ for (MBeanParameterInfo parameter: operation.getSignature())
+ {
+ method
+ .append("\"")
+ .append(parameter.getType())
+ .append("\",");
+ }
+ method.deleteCharAt(method.length()-1);
+ method.append("}); }");
+
+ String methodAsString = method.toString();
+ methodAsString = methodAsString.replace("new Object[]{}","null");
+ methodAsString = methodAsString.replace("new String[]{}","null");
+
+ CtMethod definition = CtNewMethod.make(methodAsString,_capabilityClassDefinition);
+ _capabilityClassDefinition.addMethod(definition);
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ } finally {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(
+ Messages.QMAN_200044_GENERATED_METHOD,
+ _objectName,
+ method.toString());
+ }
+ }
+ }
+
+ public void setEnvironment(Environment environment)
+ {
+ // Nothing to do here...
+ }
+ };
+
+ StringBuilder _properties = new StringBuilder("private static final QName[] PROPERTIES = new QName[]{ ");
+ private Class<MBeanCapability> _capabilityClass;
+ CtClass _capabilityClassDefinition;
+ EndAttributesHandler _endAttributeHandler = _noPropertyHasBeenDefined;
+
+ private ObjectName _objectName;
+
+ IArtifactBuilder _state;
+
+ /**
+ * Director callback.
+ * Attrbute metadata notification. With this callback the director informs this builder that the
+ * currently processed MBean has an attribute with the given metadata.
+ * This builder uses this information in order to add a property and the corresponding accessors
+ * to the capability class that is going to be built.
+ *
+ * @throws BuilderException bytecode manipulation / creation failure.
+ */
+ public void onAttribute(MBeanAttributeInfo attribute) throws BuilderException
+ {
+ _state.onAttribute(attribute);
+ }
+
+ /**
+ * First callback : this method is called at the begin of the director process.
+ * Contains builder initialization code.
+ *
+ * @param objectName the name of the target JMX entity of this capability.
+ * @throws BuilderException when the initialization fails.
+ */
+ @SuppressWarnings("unchecked")
+ public void begin(ObjectName objectName) throws BuilderException
+ {
+ try
+ {
+ this._objectName = objectName;
+ String className = objectName.getKeyProperty(Names.CLASS);
+ _capabilityClass = (Class<MBeanCapability>) Class.forName("org.apache.qpid.management.wsdm.capabilities."+className);
+ _state = new DummyCapabilityBuilder();
+ } catch (ClassNotFoundException exception)
+ {
+ _state = _classNotAvailable;
+ }
+
+ _state.begin(objectName);
+ }
+
+ /**
+ * Director callback.
+ * Operation metadata notification. With this callback the director informs this builder that the
+ * currently processed MBean has an operation with the given metadata.
+ * This builder uses this information in order to add a method to the capability class that is
+ * going to be built.
+ *
+ * For example, let's suppose that an operation like that is detected on the MBean :
+ *
+ * public void purge(int request)
+ *
+ * then the capability will be enrichied with the following method :
+ *
+ * public void purge(int request) throws QManFault {
+ * invoke(
+ * "purge",
+ * new Object[]{request},
+ * new String[]{int.class.getName()});
+ * }
+ *
+ * @throws BuilderException bytecode manipulation / creation failure.
+ */
+ public void onOperation(MBeanOperationInfo operation) throws BuilderException
+ {
+ _state.onOperation(operation);
+ }
+
+ /**
+ * Returns the capability class (the product of this builder).
+ *
+ * @return the capability class (the product of this builder).
+ */
+ Class<MBeanCapability> getCapabilityClass()
+ {
+ return _capabilityClass;
+ }
+
+ /**
+ * Determines what needs to be done when all attributes
+ * metadata has been notified to this builder.
+ * Capability class must have an array member with all defined
+ * properties and a getter method that returns it.
+ * In this method those two members are declared (obviously only
+ * if this capability has at least one property).
+ *
+ * @throws BuilderException when something fails during this phase.
+ */
+ public void endAttributes() throws BuilderException
+ {
+ _state.endAttributes();
+ }
+
+ /**
+ * Director callback.
+ * This method is notified when all operations metadata has been
+ * notified to this builder.
+ * This is the place where the capability class is created, defined and loaded by the JVM.
+ *
+ * @throws BuilderException issues on this method are basically class loading related.
+ */
+ @SuppressWarnings("unchecked")
+ public void endOperations() throws BuilderException
+ {
+ _state.endOperations();
+ }
+
+ /**
+ * Injects the module environment on this builder.
+ *
+ * @param environment the module environment.
+ */
+ public void setEnvironment(Environment environment)
+ {
+ // Nothing to do here...
+ }
+
+ /**
+ * Generates the get accessor method for the given property.
+ *
+ * @param type the type of the property.
+ * @param name the name of the property with the first letter capitalized.
+ * @param plainName the plain name of the property.
+ * @return the getter method (as a string).
+ */
+ String generateGetter(String type, String name,String plainName)
+ {
+ return new StringBuilder()
+ .append("public ")
+ .append(type)
+ .append(' ')
+ .append("get")
+ .append(name)
+ .append("() throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { return (")
+ .append(type)
+ .append(") getAttribute(\"")
+ .append(plainName)
+ .append("\"); }")
+ .toString();
+ }
+
+ /**
+ * Generates the set accessor method for the given property.
+ *
+ * @param type the type of the property.
+ * @param name the name of the property with the first letter capitalized.
+ * @param plainName the plain name of the property.
+ * @return the setter method (as a string).
+ */
+ String generateSetter(String type, String name, String plainName)
+ {
+ return new StringBuilder()
+ .append("public void ")
+ .append("set")
+ .append(name)
+ .append("(")
+ .append(type)
+ .append(" newValue) throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault {")
+ .append(" setAttribute(\"")
+ .append(plainName)
+ .append("\", newValue); }")
+ .toString();
+ }
+
+ /**
+ * Appends the given attribute name to the properties array declared as an
+ * instance member of the capability class.
+ *
+ * @param attributeName the name of the attribute.
+ */
+ private void appendToPropertiesArray(String attributeName)
+ {
+ _properties.append("new QName(Names.NAMESPACE_URI, \"")
+ .append(attributeName)
+ .append("\", Names.PREFIX),");
+
+ _endAttributeHandler = _atLeastThereIsOneProperty;
+ }
+
+ /**
+ * Adds a new property member instance to the capability class.
+ *
+ * @param type the type of the property.
+ * @param name the name of the property.
+ * @throws CannotCompileException when the property cannot be added.
+ */
+ private void addPropertyMemberInstance(String type, String name) throws CannotCompileException
+ {
+ StringBuilder buffer = new StringBuilder()
+ .append("private ")
+ .append(type)
+ .append(' ')
+ .append(name)
+ .append(';');
+
+ CtField field= CtField.make(buffer.toString(),_capabilityClassDefinition);
+ _capabilityClassDefinition.addField(field);
+ }
+
+ /**
+ * Returns a name that will be used in accessor methods.
+ * That name will differ from the given one because the first letter will be capitalized.
+ * For example, if the given name is "name" the return value will be "Name".
+ *
+ * @param name the plain name of the attribute.
+ * @return a capitalized version of the given name to be used in accessors.
+ */
+ String getNameForAccessors(String name)
+ {
+ return
+ Character.toUpperCase(name.charAt(0)) +
+ name.substring(1);
+ }
+
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java
new file mode 100644
index 0000000000..414f37a746
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java
@@ -0,0 +1,557 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.AbstractCapability;
+import org.apache.muse.core.Resource;
+import org.apache.muse.core.ResourceManager;
+import org.apache.muse.core.routing.MessageHandler;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.notification.NotificationProducer;
+import org.apache.muse.ws.notification.WsnConstants;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.jmx.EntityLifecycleNotification;
+import org.apache.qpid.management.wsdm.common.ThreadSessionManager;
+import org.apache.qpid.management.wsdm.common.UnableToConnectWithBrokerFault;
+import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterEnvironment;
+import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer;
+import org.apache.qpid.management.wsdm.notifications.LifeCycleEvent;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * QMan Adapter capability.
+ * Basically it acts as a lifecycle manager of all ws resource that correspond to entities on JMX side.
+ *
+ * @author Andrea Gazzarini
+*/
+@SuppressWarnings("serial")
+public class QManAdapterCapability extends AbstractCapability
+{
+ private final static Logger LOGGER = Logger.get(QManAdapterCapability.class);
+
+ private MBeanServer _mxServer;
+ private WsArtifactsFactory _artifactsFactory;
+ private URI _resourceURI;
+ private NotificationProducer _publisherCapability;
+ private ThreadPoolExecutor _workManager;
+ private Map<String, QName> _lifeCycleTopics = new HashMap<String, QName>();
+
+ /**
+ * Runnable wrapper used for sending asynchronous
+ * notifications.
+ *
+ * @author Andrea Gazzarini
+ */
+ private final class AsynchNotificationTask implements Runnable
+ {
+ private final QName topicName;
+ private final LifeCycleEvent event;
+
+ AsynchNotificationTask(QName tName, LifeCycleEvent evt)
+ {
+ topicName = tName;
+ event = evt;
+ }
+
+ public void run()
+ {
+ try
+ {
+ _publisherCapability.publish(topicName,event);
+ } catch (SoapFault exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100038_UNABLE_TO_SEND_WS_NOTIFICATION);
+ }
+ }
+ };
+
+ /**
+ * NotificationFilter for "create" only events.
+ */
+ private final NotificationFilter _filterForNewInstances = new NotificationFilter(){
+
+ /**
+ * Returns true when the notification is related to a creation of a new instance.
+ *
+ * @return true when the notification is related to a creation of a new instance.
+ */
+ public boolean isNotificationEnabled(Notification notification)
+ {
+ return EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE.equals(notification.getType());
+ }
+
+ };
+
+ /**
+ * NotificationFilter for "remove" only events.
+ */
+ private final NotificationFilter _filterForRemovedInstances = new NotificationFilter(){
+
+ /**
+ * Returns true when the notification is related to a deletion of an existing instance.
+ *
+ * @return true when the notification is related to a deletion of an existing instance.
+ */
+ public boolean isNotificationEnabled(Notification notification)
+ {
+ return EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE.equals(notification.getType());
+ }
+ };
+
+ /**
+ * This listener handles "create" mbean events and therefore provides procedure to create and initialize
+ * corresponding ws resources.
+ */
+ private final NotificationListener _listenerForNewInstances = new NotificationListener()
+ {
+ /**
+ * Handles JMX "create" notification type.
+ *
+ * @param notification the entity lifecycle notification.
+ * @param data user data associated with the incoming notifiication : it is not used at the moment.
+ */
+ public void handleNotification(Notification notification, Object data)
+ {
+ ObjectName eventSourceName = null;
+ try
+ {
+ EntityLifecycleNotification lifecycleNotification = (EntityLifecycleNotification) notification;
+ eventSourceName = lifecycleNotification.getObjectName();
+
+ ThreadSessionManager.getInstance().getSession().setObjectName(eventSourceName);
+
+ LOGGER.debug(Messages.QMAN_200039_DEBUG_JMX_NOTIFICATION, notification);
+
+ ResourceManager resourceManager = getResource().getResourceManager();
+ Resource resource = resourceManager.createResource(Names.QMAN_RESOURCE_NAME);
+
+ WsArtifacts artifacts = _artifactsFactory.getArtifactsFor(resource,eventSourceName);
+ MBeanCapability capability = _artifactsFactory.createCapability(
+ artifacts.getCapabilityClass(),
+ eventSourceName);
+
+ ThreadSessionManager.getInstance().getSession().setWsdlDocument(artifacts.getWsdl());
+ ThreadSessionManager.getInstance().getSession().setResourceMetadataDescriptor(artifacts.getResourceMetadataDescriptor());
+
+ resource.setWsdlPortType(Names.QMAN_RESOURCE_PORT_TYPE_NAME);
+ capability.setCapabilityURI(Names.NAMESPACE_URI+"/"+capability.getClass().getSimpleName());
+ capability.setMessageHandlers(createMessageHandlers(capability));
+
+ resource.addCapability(capability);
+ resource.initialize();
+ resourceManager.addResource(resource.getEndpointReference(), resource);
+
+ LOGGER.info(
+ Messages.QMAN_000030_RESOURCE_HAS_BEEN_CREATED,
+ eventSourceName);
+
+ AsynchNotificationTask asynchNotificationTask = new AsynchNotificationTask(
+ getTopicName(lifecycleNotification.getClassKind()),
+ LifeCycleEvent.newCreateEvent(
+ eventSourceName.getKeyProperty(Names.OBJECT_ID),
+ lifecycleNotification.getPackageName(),
+ lifecycleNotification.getClassName()));
+
+ _workManager.execute(asynchNotificationTask);
+
+ } catch (ArtifactsNotAvailableException exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100023_BUILD_WS_ARTIFACTS_FAILURE);
+ } catch (IllegalAccessException exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE,
+ eventSourceName);
+ } catch (InstantiationException exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE,
+ eventSourceName);
+ } catch (SoapFault exception)
+ {
+ LOGGER.error(
+ exception,Messages.QMAN_100025_WSRF_FAILURE,
+ eventSourceName);
+ } catch (Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100025_WSRF_FAILURE,
+ eventSourceName);
+ }
+ }
+ };
+
+ /**
+ * This listener handles "remove" mbean events and therefore provides procedure to shutdown and remove
+ * corresponding ws resources.
+ */
+ private final NotificationListener _listenerForRemovedInstances = new NotificationListener()
+ {
+ /**
+ * Handles JMX "remove" notification type.
+ *
+ * @param notification the entity lifecycle notification.
+ * @param data user data associated with the incoming notifiication : it is not used at the moment.
+ */
+ public void handleNotification(Notification notification, Object data)
+ {
+ EntityLifecycleNotification lifecycleNotification = (EntityLifecycleNotification) notification;
+ ObjectName eventSourceName = lifecycleNotification.getObjectName();
+
+ LOGGER.debug(Messages.QMAN_200042_REMOVING_RESOURCE, eventSourceName);
+
+ EndpointReference endpointPointReference = new EndpointReference(_resourceURI);
+ endpointPointReference.addParameter(
+ Names.RESOURCE_ID_QNAME,
+ eventSourceName.getKeyProperty(Names.OBJECT_ID));
+
+ ResourceManager resourceManager = getResource().getResourceManager();
+ try
+ {
+ Resource resource = resourceManager.getResource(endpointPointReference);
+ resource.shutdown();
+
+ LOGGER.info(
+ Messages.QMAN_000031_RESOURCE_HAS_BEEN_REMOVED,
+ eventSourceName);
+
+ AsynchNotificationTask asynchNotificationTask = new AsynchNotificationTask(
+ getTopicName(lifecycleNotification.getClassKind()),
+ LifeCycleEvent.newRemoveEvent(
+ eventSourceName.getKeyProperty(Names.OBJECT_ID),
+ lifecycleNotification.getPackageName(),
+ lifecycleNotification.getClassName()));
+
+ _workManager.execute(asynchNotificationTask);
+
+ }
+ catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100027_RESOURCE_SHUTDOWN_FAILURE,
+ eventSourceName);
+ }
+ }
+ };
+
+ /**
+ * Initializes this capability.
+ *
+ * @throws SoapFault when the initialization fails..
+ */
+ @Override
+ public void initialize() throws SoapFault
+ {
+ super.initialize();
+
+ registerByteArraySerializer();
+
+ createLifeCycleTopics();
+
+ initializeWorkManager();
+
+ createQManResourceURI();
+
+ _mxServer = ManagementFactory.getPlatformMBeanServer();
+ _artifactsFactory = new WsArtifactsFactory(getEnvironment(),_mxServer);
+
+ registerQManLifecycleListeners();
+ }
+
+ /**
+ * Connects QMan with a broker with the given connection data.
+ *
+ * @param host the host where the broker is running.
+ * @param port the port number where the broker is running.
+ * @param username username for estabilshing connection.
+ * @param password password for estabilshing connection.
+ * @param virtualHost the virtualHost name.
+ * @param initialPoolCapacity the initial size of broker connection pool.
+ * @param maxPoolCapacity the max allowed size of broker connection pool.
+ * @param maxWaitTimeout the max wait timeout for retrieving connections.
+ * @throws SoapFault when the connection with broker cannot be estabilished.
+ */
+ @SuppressWarnings("unchecked")
+ public void connect(
+ String host,
+ int port,
+ String username,
+ String password,
+ String virtualHost,
+ int initialPoolCapacity,
+ int maxPoolCapacity,
+ long maxWaitTimeout) throws SoapFault
+ {
+ try
+ {
+ _mxServer.invoke(
+ Names.QMAN_OBJECT_NAME,
+ "addBroker",
+ new Object[]{host,port,username,password,virtualHost,initialPoolCapacity,maxPoolCapacity,maxWaitTimeout},
+ new String[]{
+ String.class.getName(),
+ int.class.getName(),
+ String.class.getName(),
+ String.class.getName(),
+ String.class.getName(),
+ int.class.getName(),
+ int.class.getName(),
+ long.class.getName()});
+ } catch(Exception exception)
+ {
+ LOGGER.error(Messages.QMAN_100017_UNABLE_TO_CONNECT,host,port);
+ throw new UnableToConnectWithBrokerFault(
+ getResource().getEndpointReference(),
+ host,
+ port,
+ username,
+ virtualHost,
+ exception.getMessage());
+ }
+ }
+
+ /**
+ * Creates the message handlers for the given capability.
+ *
+ * @param capability the QMan capability.
+ * @return a collection with message handlers for the given capability.
+ */
+ protected Collection<MessageHandler> createMessageHandlers(MBeanCapability capability)
+ {
+ Collection<MessageHandler> handlers = new ArrayList<MessageHandler>();
+
+ for (Method method : capability.getClass().getDeclaredMethods())
+ {
+ String name = method.getName();
+
+ QName requestName = new QName(
+ Names.NAMESPACE_URI,
+ name,
+ Names.PREFIX);
+
+ QName returnValueName = new QName(
+ Names.NAMESPACE_URI,
+ name+"Response",
+ Names.PREFIX);
+
+ String actionURI = Names.NAMESPACE_URI+"/"+name;
+
+ MessageHandler handler = new QManMessageHandler(
+ actionURI,
+ requestName,
+ returnValueName);
+
+ handler.setMethod(method);
+ handlers.add(handler);
+ }
+ return handlers;
+ }
+
+ /**
+ * Returns the publisher capability associated with the owner resource.
+ *
+ * @return the publisher capability associated with the owner resource.
+ */
+ NotificationProducer getPublisherCapability()
+ {
+ return (NotificationProducer) getResource().getCapability(WsnConstants.PRODUCER_URI);
+ }
+
+ /**
+ * Creates events & objects lifecycle topic that will be used to publish lifecycle event
+ * messages..
+ */
+ void createLifeCycleTopics()
+ {
+ try
+ {
+ _publisherCapability = getPublisherCapability();
+
+ _publisherCapability.addTopic(Names.EVENTS_LIFECYLE_TOPIC_NAME);
+ _lifeCycleTopics.put(Names.EVENT,Names.EVENTS_LIFECYLE_TOPIC_NAME);
+
+ LOGGER.info(
+ Messages.QMAN_000032_EVENTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED,
+ Names.OBJECTS_LIFECYLE_TOPIC_NAME);
+
+ _publisherCapability.addTopic(Names.OBJECTS_LIFECYLE_TOPIC_NAME);
+ _lifeCycleTopics.put(Names.CLASS,Names.OBJECTS_LIFECYLE_TOPIC_NAME);
+
+ LOGGER.info(
+ Messages.QMAN_000033_OBJECTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED,
+ Names.OBJECTS_LIFECYLE_TOPIC_NAME);
+
+ _publisherCapability.addTopic(Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME);
+ LOGGER.info(
+ Messages.QMAN_000034_UNCLASSIFIED_LIFECYCLE_TOPIC_HAS_BEEN_CREATED,
+ Names.OBJECTS_LIFECYLE_TOPIC_NAME);
+ } catch(Exception exception)
+ {
+ LOGGER.error(exception, Messages.QMAN_100036_TOPIC_DECLARATION_FAILURE);
+ }
+ }
+
+ /**
+ * Starting from an object type (i.e. event or class) returns the name of the
+ * corresponding topic where the lifecycle message must be published.
+ * Note that if the given object type is unknown then the "Unclassified Object Types" topic
+ * will be returned (and therefore the message will be published there).
+ *
+ * @param objectType the type of the object.
+ * @return the name of the topic associated with the given object type.
+ */
+ QName getTopicName(String objectType)
+ {
+ QName topicName = _lifeCycleTopics.get(objectType);
+ return (topicName != null)
+ ? topicName
+ : Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME;
+ }
+
+ /**
+ * Workaround : it seems that is not possibile to declare a serializer
+ * for a byte array using muse descriptor...
+ * What is the stringified name of the class?
+ * byte[].getClass().getName() is [B but is not working (ClassNotFound).
+ * So, at the end, this is hard-coded here!
+ */
+ private void registerByteArraySerializer()
+ {
+ SerializerRegistry.getInstance().registerSerializer(
+ byte[].class,
+ new ByteArraySerializer());
+ }
+
+ /**
+ * Creates the URI that will be later used to identify a QMan WS-Resource.
+ * Note that the resources that will be created are identified also with their resource id.
+ * Briefly we could say that this is the soap:address of the WS-Resource definition.
+ *
+ * @throws SoapFault when the URI cannot be built (probably it is malformed).
+ */
+ private void createQManResourceURI() throws SoapFault
+ {
+ WSDMAdapterEnvironment environment = (WSDMAdapterEnvironment) getEnvironment();
+ String resourceURI = environment.getDefaultURIPrefix()+Names.QMAN_RESOURCE_NAME;
+ try
+ {
+ _resourceURI = URI.create(resourceURI);
+
+ } catch(IllegalArgumentException exception)
+ {
+ LOGGER.info(
+ exception,
+ Messages.QMAN_100029_MALFORMED_RESOURCE_URI_FAILURE,
+ resourceURI);
+ throw new SoapFault(exception);
+ }
+ }
+
+ /**
+ * Initializes the work manager used for asynchronous notifications.
+ */
+ private void initializeWorkManager()
+ {
+ Configuration configuration = Configuration.getInstance();
+ _workManager = new ThreadPoolExecutor(
+ configuration.getWorkerManagerPoolSize(),
+ configuration.getWorkerManagerMaxPoolSize(),
+ configuration.getWorkerManagerKeepAliveTime(),
+ TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(30));
+ }
+
+ /**
+ * This adapter capability needs to be an event listener of QMan JMX core
+ * in order to detect relevant lifecycle events and therefore create WS artifacts & notification(s).
+ *
+ * @throws SoapFault when it's not possible to register event listener : is QMan running?
+ */
+ @SuppressWarnings("serial")
+ private void registerQManLifecycleListeners() throws SoapFault
+ {
+ try
+ {
+ _mxServer.addNotificationListener(
+ Names.QMAN_OBJECT_NAME,
+ _listenerForNewInstances,
+ _filterForNewInstances,
+ null);
+
+ _mxServer.addNotificationListener(
+ Names.QMAN_OBJECT_NAME,
+ _listenerForRemovedInstances,
+ _filterForRemovedInstances,
+ null);
+
+ try
+ {
+ _mxServer.addNotificationListener(
+ Names.QPID_EMULATOR_OBJECT_NAME,
+ _listenerForNewInstances,
+ _filterForNewInstances, null);
+
+ _mxServer.addNotificationListener(
+ Names.QPID_EMULATOR_OBJECT_NAME,
+ _listenerForRemovedInstances,
+ _filterForRemovedInstances, null);
+
+ } catch (Exception exception)
+ {
+ LOGGER.info(Messages.QMAN_000028_TEST_MODULE_NOT_FOUND);
+ }
+ } catch(InstanceNotFoundException exception)
+ {
+ throw new SoapFault(exception);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java
new file mode 100644
index 0000000000..95f54ef5b5
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.reflect.Method;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.routing.ReflectionMessageHandler;
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer;
+import org.w3c.dom.Element;
+
+/**
+ * JMXConnectionListener_example custom implementation of Muse message handler to properly deal with
+ * byte arrays.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QManMessageHandler extends ReflectionMessageHandler
+{
+
+ /**
+ * Builds a new message handler with the given arguments.
+ *
+ * @param actionURI the action URI.
+ * @param requestQName the qname of the incoming request.
+ * @param returnValueName the qname of the result value.
+ */
+ public QManMessageHandler(String actionURI, QName requestQName,
+ QName returnValueName)
+ {
+ super(actionURI, requestQName, returnValueName);
+ }
+
+ /**
+ * Transforms the given xml element in the corresponding
+ * object representation.
+ *
+ * @throws SoapFaul when unmarshal operation fails.
+ */
+ @SuppressWarnings("unchecked")
+ public Object[] fromXML(Element xml) throws SoapFault
+ {
+ Method method = getMethod();
+
+ if (xml == null )
+ {
+ return EMPTY_REQUEST;
+ }
+
+ Class[] parameters = method.getParameterTypes();
+ Object[] objects = new Object[parameters.length];
+
+ Element[] elements = XmlUtils.getAllElements(xml);
+
+ if (parameters.length == 1 && elements.length == 0)
+ {
+ elements = new Element[]{ xml };
+ }
+
+ if (elements.length != parameters.length)
+ {
+ throw new SoapFault("IncorrectParams");
+ }
+
+ SerializerRegistry registry = SerializerRegistry.getInstance();
+
+ for (int i = 0; i < elements.length; ++i)
+ {
+ Class clazz = parameters[i];
+ if (clazz == byte[].class)
+ {
+ objects[i] = new ByteArraySerializer().fromXML(elements[i]);
+ } else
+ {
+ Serializer ser = registry.getSerializer(parameters[i]);
+ objects[i] = ser.fromXML(elements[i]);
+ }
+ }
+ return objects;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java
new file mode 100644
index 0000000000..d6255d0bed
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java
@@ -0,0 +1,99 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.metadata.WsxConstants;
+import org.apache.muse.ws.resource.WsResource;
+import org.apache.muse.ws.resource.metadata.MetadataDescriptor;
+import org.apache.muse.ws.resource.metadata.WsrmdConstants;
+import org.apache.muse.ws.resource.metadata.ext.WsrfMetadataExchange;
+import org.apache.muse.ws.wsdl.WsdlUtils;
+import org.apache.qpid.management.wsdm.muse.resources.QManWsResource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * QMan resource metadata exchange.
+ * We cannot resuse the preexisting classes directly because the wsdl of the service instance
+ * is retrieved using a file path.
+ * Since the owner resource (QManWsResource) is dynamic (I mean, its interface is dynamic), the corresponding
+ * WSDL cannot defined at compile time but needs some changes when the resource is created.
+ * As part of that, the WSDL template found under wsdl folder is modified with the additional properties of the given
+ * resource. The metadata exchange capability must include those properties too.
+ *
+ * Note that this capability is appliable only to a QManWsResource.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QManMetadataExchangeCapability extends WsrfMetadataExchange
+{
+ /**
+ * Returns the WSDL associated with the owner of this capability.
+ *
+ * @return the WSDL associated with the owner of this capability.
+ */
+ @Override
+ protected Element getWSDL()
+ {
+ QManWsResource resource = (QManWsResource) getResource();
+
+ Document wsdlDoc = resource.getWsdl();
+ Element wsdl = XmlUtils.getFirstElement(wsdlDoc);
+
+ WsdlUtils.removeWsdlReferences(wsdl);
+ WsdlUtils.removeSchemaReferences(wsdl);
+
+ return wsdl;
+ }
+
+ /**
+ * Returns the resource metadata descriptor associated with the owenr
+ * resource of thi capability.
+ *
+ * @return the resource metadata descriptor.
+ */
+ protected Element getResourceMetadataDescriptor()
+ {
+ WsResource resource = (WsResource)getResource();
+ MetadataDescriptor metadataDescriptor = resource.getPropertyCollection().getMetadata();
+ return metadataDescriptor.toXML();
+ }
+
+ public Element[] getMetadata(String dialect)
+ {
+ if (dialect == null)
+ {
+ return new Element[]{
+ getResourceMetadataDescriptor(),
+ getWSDL()};
+ } else {
+ if (WsrmdConstants.NAMESPACE_URI.equals(dialect))
+ {
+ return new Element[]{getResourceMetadataDescriptor()};
+ } else if (WsxConstants.WSDL_DIALECT.equals(dialect))
+ {
+ return new Element[]{getWSDL()};
+ }
+ }
+ return super.getMetadata(dialect);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java
new file mode 100644
index 0000000000..a00d2665ae
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.util.*;
+
+/**
+ * Data Transfer Object that encapsulates the result of a method invocation.
+ * This is the object that will be marshalled in XML and will contain the result of a method
+ * invocation (status code & text).
+ *
+ * @author Andrea Gazzarini
+ */
+public final class Result
+{
+ private final Map<String,Object> _outputParameters;
+
+ /**
+ * Builds a new result DTO with the given parameters.
+ *
+ * @param statusCode the return code.
+ * @param statusText the status message.
+ * @param outputParameters the output parameters.
+ */
+ public Result(Map<String, Object> outputParameters)
+ {
+ this._outputParameters = outputParameters;
+ }
+
+ /**
+ * Returns the output parameterss.
+ *
+ * @return the output parameterss.
+ */
+ public Map<String, Object> getOutputParameters()
+ {
+ return _outputParameters;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java
new file mode 100644
index 0000000000..c1678eb43f
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectName;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.resource.metadata.WsrmdConstants;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.qman.debug.WsdlDebugger;
+import org.w3c.dom.Element;
+
+/**
+ * Resource Metadata Descriptor Builder.
+ * It is used for build the metadata descriptor for properties of the
+ * incoming jmx object.
+ *
+ * @author Andrea Gazzarini
+ */
+class RmdBuilder implements IArtifactBuilder
+{
+ private List<Element> _metadataDescriptor = new ArrayList<Element>();
+
+ ObjectName _objectName;
+
+ /**
+ * Nothing to be done here on this builder.
+ * Simply logs a message indicating the target object name.
+ *
+ * @param objectName the jmx name of the object that is going to be processed.
+ */
+ public void begin(ObjectName objectName)
+ {
+ this._objectName = objectName;
+ }
+
+ /**
+ * Nothing to be done here on this builder.
+ *
+ * @throws BuilderException never.
+ */
+ public void endAttributes()
+ {
+ // N.A. for this builder.
+ }
+
+ /**
+ * Nothing to be done here on this builder.
+ *
+ * @throws BuilderException never.
+ */
+ public void endOperations()
+ {
+ // N.A. for this builder.
+ }
+
+ /**
+ * Process a single attribute metadata.
+ * An attribute (that is, a property) represented by the corresponding incoming
+ * attribute metadata will generate an wsrmd:Property xml element with the constraints
+ * (initial values, static values, allowed values) contained on the metadata.
+ *
+ * @param attributeMetadata the attribute (jmx) metadata.
+ */
+ public void onAttribute(MBeanAttributeInfo attributeMetadata)
+ {
+ Element property = XmlUtils.createElement(WsrmdConstants.PROPERTY_QNAME);
+ property.setAttribute(Names.NAME_ATTRIBUTE, Names.PREFIX+":"+attributeMetadata.getName());
+ property.setAttribute(Names.MODIFIABILITY,
+ attributeMetadata.isWritable()
+ ? Names.READ_WRITE
+ : Names.READ_ONLY);
+ property.setAttribute(Names.MUTABILITY,Names.MUTABLE);
+
+ WsdlDebugger.debug(_objectName, property);
+
+ _metadataDescriptor.add(property);
+ }
+
+ /**
+ * Nothing to be done here on this builder.
+ *
+ * @throws BuilderException never.
+ */
+ public void onOperation(MBeanOperationInfo operation)
+ {
+ // N.A. for this builder
+ }
+
+ /**
+ * Nothing to be done here on this builder.
+ *
+ * @throws BuilderException never.
+ */
+ public void setEnvironment(Environment environment)
+ {
+ // N.A. for this builder
+ }
+
+ /**
+ * Nothing to be done here on this builder.
+ *
+ * @throws BuilderException never.
+ */
+ public Element[] getResourceMetadataDescriptor()
+ {
+ Element [] properties = _metadataDescriptor.toArray(
+ new Element[_metadataDescriptor.size()]);
+ return properties;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java
new file mode 100644
index 0000000000..35a919c295
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java
@@ -0,0 +1,196 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ObjectName;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.core.Resource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Director used for coordinate the building process of WS-DM artifacts.
+ *
+ * @author Andrea Gazzarini
+ */
+final class WSDMArtifactsDirector
+{
+ private final ObjectName _eventSourceObjectName;
+ private final MBeanInfo _metadata;
+
+ private final MBeanCapabilityBuilder _capabilityBuilder;
+ private final WsdlBuilder _wsdlBuilder;
+ private final RmdBuilder _rmdBuilder;
+
+ /**
+ * Builds a new director with the given objectname and (jmx) metadata.
+ *
+ * @param eventSourceObjectName the object name of the event source mbean.
+ * @param metadata the jmx metadata of the corresponding mbean.
+ */
+ WSDMArtifactsDirector(ObjectName eventSourceObjectName, MBeanInfo metadata)
+ {
+ this._eventSourceObjectName = eventSourceObjectName;
+ this._metadata = metadata;
+
+ _wsdlBuilder = new WsdlBuilder();
+ _capabilityBuilder = new MBeanCapabilityBuilder();
+ _rmdBuilder = new RmdBuilder();
+ }
+
+ /**
+ * Starts the build process of this director.
+ * This method acts as a facade of the whole build process.
+ *
+ * @throws BuilderException when one step of the build process fails.
+ */
+ void direct() throws BuilderException
+ {
+ processObjectName();
+ processAttributes();
+ endAttributes();
+ processOperations();
+ endOperations();
+ }
+
+ /**
+ * Notifiies builder that all the operations metadata have been transmitted.
+ *
+ * @throws BuilderException when one builder raises an exception during this operation.
+ */
+ private void endOperations() throws BuilderException
+ {
+ _capabilityBuilder.endOperations();
+ _wsdlBuilder.endOperations();
+ _rmdBuilder.endOperations();
+ }
+
+ /**
+ * Notifiies builder that all the attributes metadata have been transmitted.
+ *
+ * @throws BuilderException when one builder raises an exception during this operation.
+ */
+ private void endAttributes() throws BuilderException
+ {
+ _capabilityBuilder.endAttributes();
+ _wsdlBuilder.endAttributes();
+ _rmdBuilder.endAttributes();
+ }
+
+ /**
+ * Injects event source object name on all builders.
+ *
+ * @throws BuilderException when one builder raises an exception during this operation.
+ */
+ void processObjectName() throws BuilderException
+ {
+ _capabilityBuilder.begin(_eventSourceObjectName);
+ _wsdlBuilder.begin(_eventSourceObjectName);
+ _rmdBuilder.begin(_eventSourceObjectName);
+ }
+
+ /**
+ * Injects attributes metadata on all builders.
+ *
+ * @throws BuilderException when one builder raises an exception during this operation.
+ */
+ void processAttributes() throws BuilderException
+ {
+ for (MBeanAttributeInfo attribute : _metadata.getAttributes())
+ {
+ _capabilityBuilder.onAttribute(attribute);
+ _wsdlBuilder.onAttribute(attribute);
+ _rmdBuilder.onAttribute(attribute);
+ }
+ }
+
+ /**
+ * Injects operations metadata on all builders.
+ *
+ * @throws BuilderException when one builder raises an exception during this operation.
+ */
+ void processOperations() throws BuilderException
+ {
+ for (MBeanOperationInfo operation : _metadata.getOperations())
+ {
+ _capabilityBuilder.onOperation(operation);
+ _wsdlBuilder.onOperation(operation);
+ }
+ }
+
+ /**
+ * Returns the capabilty class.
+ *
+ * @return the capability class.
+ */
+ Class<MBeanCapability> getCapabilityClass()
+ {
+ return _capabilityBuilder.getCapabilityClass();
+ }
+
+ /**
+ * Returns the wsdl.
+ *
+ * @return the wsdl.
+ */
+ Document getWsdl()
+ {
+ return _wsdlBuilder.getWsdl();
+ }
+
+ /**
+ * Returns the resource metadata descriptor containing metadata (rules, constraints, etc)
+ * for the current resource.
+ * The returned object is an array of Element and each of them maps a resource property.
+ *
+ * @return the resource metadata descriptor (as an array of Element).
+ */
+ Element [] getResourceMetadataDescriptor()
+ {
+ return _rmdBuilder.getResourceMetadataDescriptor();
+ }
+
+ /**
+ * Injects the environment on this director.
+ *
+ * @param environment the QMan environment.
+ */
+ void setEnvironment(Environment environment)
+ {
+ _wsdlBuilder.setEnvironment(environment);
+ _capabilityBuilder.setEnvironment(environment);
+ _rmdBuilder.setEnvironment(environment);
+ }
+
+ /**
+ * Injectcs the ws resource on this director.
+ *
+ * @param resource the ws resource.
+ */
+ public void setResource(Resource resource)
+ {
+ _wsdlBuilder.setWsdlPath(resource.getWsdlPath());
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java
new file mode 100644
index 0000000000..ac4636b9c9
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Web Service Artifacts.
+ * Basically it acts as a container for all artifacts built when a new WS-Resource is created.
+ * With WS artifacts we mean :
+ *
+ * <ul>
+ * <li>Capability class (which encapsulate the WS-DM capability concern)</li>
+ * <li>WS Resource Metadata Descriptor (RMD)</li>
+ * <li>Web Service Description (WSDL)</li>
+ * </ul>
+ *
+ * @author Andrea Gazzarini
+ */
+class WsArtifacts {
+
+ private final Class<MBeanCapability>_capabilityClass;
+ private final Element[] _resourceMetadataDescriptor;
+ private final Document _wsdl;
+
+ /**
+ * Builds a new artifacts container with the given artifacts.
+ *
+ * @param capabilityClass the capability class.
+ * @param resourceMetadataDescriptor the resource metadata descriptor.
+ * @param wsdl the wsdl.
+ */
+ public WsArtifacts(
+ Class<MBeanCapability> capabilityClass,
+ Element[] resourceMetadataDescriptor,
+ Document wsdl)
+ {
+ this._capabilityClass = capabilityClass;
+ this._resourceMetadataDescriptor = resourceMetadataDescriptor;
+ this._wsdl = wsdl;
+ }
+
+ /**
+ * Returns the capability class.
+ *
+ * @return the capability class.
+ */
+ Class<MBeanCapability> getCapabilityClass()
+ {
+ return _capabilityClass;
+ }
+
+ /**
+ * Returns the resource metadata descriptor.
+ * It is not a whole document but each property metadata is described in a
+ * separated element so the returned object is an array of elements.
+ *
+ * @return the resource metadata descriptor.
+ */
+ Element[] getResourceMetadataDescriptor()
+ {
+ return _resourceMetadataDescriptor;
+ }
+
+ /**
+ * Returns the web service description.
+ *
+ * @return the web service description (WSDL).
+ */
+ Document getWsdl()
+ {
+ return _wsdl;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java
new file mode 100644
index 0000000000..94505d28f7
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java
@@ -0,0 +1,140 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.core.Resource;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Manager for all WS-* related artifacts.
+ * Basically it is a factory ehnanced with a _cache mechanism so each created resource
+ * (WSDL, capability class, descriptor) is created and its reference is returned when requested
+ * again.
+ *
+ * @author Andrea Gazzarini
+ */
+class WsArtifactsFactory
+{
+ private final static Logger LOGGER = Logger.get(WsArtifactsFactory.class);
+
+ private final MBeanServer _mxServer;
+ private final Environment _environment;
+ private Map<ObjectName, WsArtifacts> _cache;
+
+ /**
+ * Builds a new factory with the given environment and mbean server.
+ *
+ * @param environment the builder environment.
+ * @param mxServer the management server.
+ */
+ public WsArtifactsFactory(Environment environment, MBeanServer mxServer)
+ {
+ this._environment = environment;
+ this._mxServer = mxServer;
+ this._cache = new HashMap<ObjectName, WsArtifacts>();
+ }
+
+ /**
+ * Returns the WS artifacts corresponding with the given resource.
+ *
+ * @param resource the WS resource.
+ * @param objectName the resource identifier (name).
+ * @return the WS artifacts corresponding with the given resource.
+ * @throws ArtifactsNotAvailableException when some problem occurs during artifacts generation.
+ */
+ @SuppressWarnings("unchecked")
+ WsArtifacts getArtifactsFor(Resource resource, ObjectName objectName) throws ArtifactsNotAvailableException
+ {
+ WsArtifacts result = null;
+ try
+ {
+ Hashtable<String, String> keyProperties = objectName.getKeyPropertyList();
+ keyProperties.remove(Names.NAME_ATTRIBUTE);
+ keyProperties.remove(Names.OBJECT_ID);
+
+ ObjectName searchKey = ObjectName.getInstance(objectName.getDomain(),keyProperties);
+
+ LOGGER.debug(
+ Messages.QMAN_200041_INCOMING_OBJECT_NAME_AND_DERIVED_KEY,
+ objectName,
+ searchKey);
+
+ result = _cache.get(searchKey);
+ if (result == null)
+ {
+ MBeanInfo metadata = _mxServer.getMBeanInfo(objectName);
+
+ WSDMArtifactsDirector director = new WSDMArtifactsDirector(objectName,metadata);
+ director.setEnvironment(_environment);
+ director.setResource(resource);
+ director.direct();
+
+ result = new WsArtifacts(
+ director.getCapabilityClass(),
+ director.getResourceMetadataDescriptor(),
+ director.getWsdl());
+
+ _cache.put(searchKey, result);
+
+ LOGGER.debug(
+ Messages.QMAN_200040_WS_ARTIFACTS_CACHED,
+ searchKey);
+ }
+
+ return result;
+ } catch(Exception exception)
+ {
+ throw new ArtifactsNotAvailableException(
+ result,
+ exception,
+ objectName);
+ }
+ }
+
+ /**
+ * Utility method for create concrete instance of the given capability class.
+ *
+ * @param capabilityClass the capability class.
+ * @param objectName the object name that will act as the target for this capability invocations.
+ * @return an initialized instance of the given capability class.
+ * @throws InstantiationException when the class cannot be instantiated.
+ * @throws IllegalAccessException when this method does not have access to
+ * the definition of the capability class.
+ */
+ MBeanCapability createCapability(Class<MBeanCapability> capabilityClass, ObjectName objectName)
+ throws InstantiationException, IllegalAccessException
+ {
+ MBeanCapability capability = capabilityClass.newInstance();
+ capability.setResourceObjectName(objectName);
+ return capability;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java
new file mode 100644
index 0000000000..6bfccda1ce
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java
@@ -0,0 +1,460 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
+import javax.xml.transform.TransformerException;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.util.ReflectUtils;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.wsdl.WsdlUtils;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterEnvironment;
+import org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer;
+import org.apache.qpid.qman.debug.WsdlDebugger;
+import org.apache.qpid.transport.util.Logger;
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+/**
+ * TO BE IMPROVED USING JAXB!!
+ *
+ * @author Andrea Gazzarini
+ */
+class WsdlBuilder implements IArtifactBuilder,Constants {
+
+ private final static Logger LOGGER = Logger.get(WsdlBuilder.class);
+
+ private WSDMAdapterEnvironment _environment;
+ private Document _document;
+ private Element schema;
+ private Element _wsrpProperties;
+ private ObjectSerializer _serializer;
+ private ObjectName _objectName;
+ private Map<String, String> arrayTypesAlreadyDeclared = new HashMap<String, String>();
+
+ private Element _arrayComplexType;
+ private Element _nestedArrayType;
+
+ /**
+ * For each attibute the corresponding xml type definition must be inserted on the QMan
+ * schema related section.
+ * After that, a reference to that definition must be declared on the wsrp element .
+ *
+ * @param attributeMetadata the attribute metadata.
+ * @throws BuilderException only if this builder wasn't able to get a reference (via XPath)
+ * to QMan schema section.
+ */
+ public void onAttribute(MBeanAttributeInfo attributeMetadata) throws BuilderException
+ {
+ try
+ {
+ String attributeName = attributeMetadata.getName();
+ schema.appendChild(defineSchemaFor(attributeMetadata.getType(), attributeName));
+
+ Element propertyRef= XmlUtils.createElement(_document, XSD_ELEMENT_QNAME);
+ propertyRef.setAttribute(MIN_OCCURS, "0");
+ propertyRef.setAttribute(
+ REF_ATTRIBUTE,
+ Names.PREFIX+":"+attributeName);
+
+ _wsrpProperties.appendChild(propertyRef);
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Element defineSchemaFor(String type, String attributeName) throws Exception
+ {
+ Element propertyDeclaration = XmlUtils.createElement(_document, XSD_ELEMENT_QNAME);
+ String xmlType = null;
+ if (type.equals(Map.class.getName()))
+ {
+ xmlType="qman:map";
+ } else if (UUID.class.getName().equals(type))
+ {
+ xmlType = "qman:uuid";
+ } else if (type.startsWith("["))
+ {
+ Class arrayClass = Class.forName(type);
+ Class clazz = ReflectUtils.getClassFromArrayClass(arrayClass);
+ String arrayType = arrayClass.getSimpleName().replace("[]", "").trim();
+ arrayType = Character.toUpperCase(arrayType.charAt(0))+arrayType.substring(1);
+ if (!arrayTypesAlreadyDeclared.containsKey(type))
+ {
+ _arrayComplexType.setAttribute(NAME_ATTRIBUTE, "arrayOf"+arrayType);
+ _nestedArrayType.setAttribute(TYPE_ATTRIBUTE, _serializer.getXmlType(clazz));
+ schema.appendChild(_arrayComplexType);
+ arrayTypesAlreadyDeclared.put(type, arrayType);
+ }
+ xmlType = "qman:arrayOf"+arrayTypesAlreadyDeclared.get(type);
+ }
+ else
+ {
+ xmlType = _serializer.getXmlType(Class.forName(type));
+ }
+ propertyDeclaration.setAttribute(NAME_ATTRIBUTE,attributeName);
+ propertyDeclaration.setAttribute(TYPE_ATTRIBUTE, xmlType);
+ return propertyDeclaration;
+ }
+
+ /**
+ * Initializes this builder.
+ *
+ * @param objectName the name of the current JMX entity.
+ * @throws BuilderException when it's not possible to proceed with the initialization.
+ */
+ public void begin(ObjectName objectName) throws BuilderException
+ {
+ this._objectName = objectName;
+ this._serializer = (ObjectSerializer) SerializerRegistry.getInstance().getSerializer(Object.class);
+
+ createWsrpPropertiesElement();
+
+ createReusableArrayComplextType();
+
+ replaceDummyServiceLocationOnWsdl();
+
+ createSchemaElement();
+ }
+
+ public void onOperation(MBeanOperationInfo operationMetadata) throws BuilderException
+ {
+ // SCHEMA SECTION
+ /*
+ <xs:element name='purgeRequest' type='qman:purgeRequest' />
+
+ <xs:element name='purgeResponse' type='qman:purgeResponse' />
+
+ <xs:complexType name='purgeRequest'>
+ <xs:sequence>
+ <xs:element name='arg0' type='xs:int' />
+ <xs:element minOccurs='0' name='arg1' type='qman:hashMap' />
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:element name='hashMap'>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs='unbounded' minOccurs='0' name='entry'>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs='0' name='key' type='xs:string'/>
+ <xs:element minOccurs='0' name='value' type='xs:anyType'/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name='purgeResponse'>
+ <xs:sequence />
+ </xs:complexType>
+ */
+
+ try
+ {
+ // <xsd:element xmlns="" name="purgeRequest" type="qman:purgeRequest"/>
+
+ Element methodRequestElement= _document.createElement("xsd:element");
+ String methodNameRequest = operationMetadata.getName()+"Request";
+ methodRequestElement.setAttribute("name", methodNameRequest);
+ methodRequestElement.setAttribute("type", "qman:"+methodNameRequest);
+
+ // <xs:element name='purgeResponse' type='qman:purgeResponse' />
+// Element methodResponseElement= _document.createElement("xsd:element");
+ String methodNameResponse= operationMetadata.getName()+"Response";
+// methodResponseElement.setAttribute("name", methodNameResponse);
+// methodResponseElement.setAttribute("type", "qman:result");//+methodNameResponse);
+
+ schema.appendChild(methodRequestElement);
+// schema.appendChild(methodResponseElement);
+
+ /*
+ <xs:complexType name='purgeRequest'>
+ <xs:sequence>
+ <xs:element name='arg0' type='xs:int' />
+ <xs:element minOccurs='0' name='arg1' type='qman:hashMap' />
+ </xs:sequence>
+ </xs:complexType>
+
+ */
+
+ Element methodNameRequestComplexType = _document.createElement("xsd:complexType");
+ methodNameRequestComplexType.setAttribute("name", methodNameRequest);
+ Element methodNameRequestComplexTypeSequence = _document.createElement("xsd:sequence");
+
+ for(MBeanParameterInfo parameter : operationMetadata.getSignature())
+ {
+ methodNameRequestComplexTypeSequence.appendChild(defineSchemaFor(parameter.getType(), parameter.getName()));
+ }
+
+ methodNameRequestComplexType.appendChild(methodNameRequestComplexTypeSequence);
+ schema.appendChild(methodNameRequestComplexType);
+
+ /*
+ <message name="purgeResponseMessage">
+ <part element='qman:purgeResponse' name='purgeResponse'></part>
+ </message>
+
+ <message name='purgeRequestMessage'>
+ <part element="qman:purgeRequest" name='purgeRequest'></part>
+ </message>
+ */
+ Element definitions = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions");
+
+ String requestMessageName = methodNameRequest+"Message";
+ String responseMessageName = methodNameResponse+"Message";
+
+ Element requestMessage = _document.createElement("message");
+ requestMessage.setAttribute("name", requestMessageName);
+ Element requestPart = _document.createElement("wsdl:part");
+ requestPart.setAttribute("element", "qman:"+methodNameRequest);
+ requestPart.setAttribute("name", methodNameRequest);
+ requestMessage.appendChild(requestPart);
+
+ Element responseMessage = _document.createElement("wsdl:message");
+ responseMessage.setAttribute("name", responseMessageName);
+ Element responsePart = _document.createElement("wsdl:part");
+ responsePart.setAttribute("element", "qman:result");//+methodNameResponse);
+ responsePart.setAttribute("name", methodNameResponse);
+ responseMessage.appendChild(responsePart);
+
+ definitions.appendChild(requestMessage);
+ definitions.appendChild(responseMessage);
+
+
+ /*
+ <operation name='purge'>
+ <input message="qman:purgeRequestMessage">
+ </input>
+ <output message='qman:purgeResponseMessage'>
+ </output>
+ </operation>
+ */
+ Element portType = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:portType");
+ Element operation = _document.createElement("wsdl:operation");
+ operation.setAttribute("name", operationMetadata.getName());
+
+ Element input = _document.createElement("wsdl:input");
+ input.setAttribute("message", "qman:"+requestMessageName);
+ input.setAttribute("name", methodNameRequest);
+ input.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+operationMetadata.getName());
+
+ //name="SetResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"/>
+
+ operation.appendChild(input);
+
+ Element output = _document.createElement("wsdl:output");
+ output.setAttribute("message", "qman:"+responseMessageName);
+ output.setAttribute("name", methodNameResponse);
+ output.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+methodNameResponse);
+
+ operation.appendChild(output);
+
+ portType.appendChild(operation);
+
+ /*
+ <operation name='purge'>
+ <soap:operation soapAction='purge' />
+ <input>
+ <soap:body use='literal' />
+ </input>
+ <output>
+ <soap:body use='literal' />
+ </output>
+ </operation>
+ */
+ Element binding = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:binding");
+ Element bindingOperation = _document.createElement("wsdl:operation");
+ bindingOperation.setAttribute("name", operationMetadata.getName());
+
+ Element soapOperation = _document.createElement("wsdl-soap:operation");
+ soapOperation.setAttribute("soapAction", Names.NAMESPACE_URI+"/"+operationMetadata.getName());
+
+ Element bindingInput = _document.createElement("wsdl:input");
+ Element bodyIn = _document.createElement("wsdl-soap:body");
+ bodyIn.setAttribute("use", "literal");
+
+ Element bindingOutput = _document.createElement("wsdl:output");
+ Element bodyOut = _document.createElement("wsdl-soap:body");
+ bodyOut.setAttribute("use", "literal");
+
+ bindingOutput.appendChild(bodyOut);
+ bindingInput.appendChild(bodyIn);
+
+ bindingOperation.appendChild(soapOperation);
+ bindingOperation.appendChild(bindingInput);
+ bindingOperation.appendChild(bindingOutput);
+
+ binding.appendChild(bindingOperation);
+ } catch(Exception exception)
+ {
+ throw new BuilderException(exception);
+ }
+ }
+
+ /**
+ * Director callback : all attributes have been notified.
+ * Nothing to do here.
+ */
+ public void endAttributes()
+ {
+ // N.A.
+ }
+
+ /**
+ * Director callback : all operations have been notified.
+ * Nothing to do here.
+ */
+ public void endOperations()
+ {
+ // N.A.
+ }
+
+ /**
+ * Returns the WSDL built by this builder.
+ *
+ * @return the WSDL built by this builder.
+ */
+ public Document getWsdl()
+ {
+ WsdlDebugger.debug(_objectName,_document);
+ return _document;
+ }
+
+ /**
+ * Injects the application context environment
+ * on this builder.
+ *
+ * @param environment the application context environment.
+ */
+ public void setEnvironment(Environment environment)
+ {
+ this._environment = (WSDMAdapterEnvironment)environment;
+ }
+
+ /**
+ * Injects the path of the wsdl document.
+ *
+ * @param wsdlPath the path of the wsdl document.
+ */
+ public void setWsdlPath(String wsdlPath)
+ {
+ _document = WsdlUtils.createWSDL(_environment, wsdlPath, true);
+ }
+
+ /**
+ * Create a reference to the WSRP properties element.
+ *
+ * @throws BuilderException in case of XPath evaluation problem.
+ */
+ private void createWsrpPropertiesElement() throws BuilderException
+ {
+ try
+ {
+ _wsrpProperties = (Element) XPathAPI.selectSingleNode(
+ _document,
+ WSRP_PROPERTIES_XPATH);
+ } catch (TransformerException exception)
+ {
+ LOGGER.error(Messages.QMAN_100040_UNABLE_TO_LOCATE_WSRP_PROPERTIES);
+ throw new BuilderException(exception);
+ }
+ }
+
+ /**
+ * Creates a template element that will be used for array
+ * type schema declaration(s).
+ */
+ private void createReusableArrayComplextType()
+ {
+ _arrayComplexType = XmlUtils.createElement(_document, XSD_COMPLEX_TYPE_QNAME);
+ Element sequence = XmlUtils.createElement(_document, XSD_SEQUENCE_QNAME);
+ _nestedArrayType = XmlUtils.createElement(_document, XSD_ELEMENT_QNAME);
+ _nestedArrayType.setAttribute(NAME_ATTRIBUTE, "entry");
+ sequence.appendChild(_nestedArrayType);
+ _arrayComplexType.appendChild(sequence);
+ }
+
+ private void createSchemaElement() throws BuilderException
+ {
+ try
+ {
+ schema = (Element) XPathAPI.selectSingleNode(
+ _document.getDocumentElement(),
+ QMAN_SCHEMA_XPATH);
+ } catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND);
+ throw new BuilderException(exception);
+ }
+ }
+
+ /**
+ * The template WSDL contains a dummy URL as service location that
+ * needs to be replaced with the real service address.
+ *
+ * @throws BuilderException when replacement fails (XPath problem).
+ */
+ private void replaceDummyServiceLocationOnWsdl() throws BuilderException
+ {
+ try
+ {
+ Attr location = (Attr) XPathAPI.selectSingleNode(
+ _document,
+ SERVICE_LOCATION_XPATH);
+
+ StringBuilder builder = new StringBuilder("http://")
+ .append(InetAddress.getLocalHost().getHostName())
+ .append(':')
+ .append(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME,"8080"))
+ .append('/')
+ .append(_environment.getContextPath())
+ .append('/')
+ .append("services/QManWsResource");
+ location.setValue(builder.toString());
+ } catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE);
+ throw new BuilderException(exception);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java
new file mode 100644
index 0000000000..116d74727a
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+
+/**
+ * Thrown when some operation has been requested on an entity and the entity hasn't been found
+ * on the managed domain.
+ *
+ * @author Andrea Gazzarini
+ */
+public class EntityInstanceNotFoundFault extends QManFault
+{
+ private static final long serialVersionUID = -3772811863214553615L;
+
+ private final static QName EXCEPTION_QNAME = new QName(
+ Names.NAMESPACE_URI,
+ "EntityInstanceNotFoundFault",
+ Names.PREFIX);
+
+ /**
+ * Builds a new exception with the given endpoint reference and the object name of the entity
+ * that wasn't found.
+ *
+ * @param endpointReference the origin endpoint reference of this exception.
+ * @param targetEntityName the object name of the not found entity.
+ */
+ public EntityInstanceNotFoundFault(EndpointReference endpointReference, ObjectName targetEntityName)
+ {
+ super(
+ endpointReference,
+ EXCEPTION_QNAME,
+ targetEntityName.getCanonicalName());
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java
new file mode 100644
index 0000000000..f24c2bfd46
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.common;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * This is the exception encapsulating the fault that will be thrown in case of
+ * method invocation failure.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MethodInvocationFault extends QManFault
+{
+ private static final long serialVersionUID = 5977379710882983474L;
+
+ private String _message;
+ private long _returnCode;
+
+ /**
+ * Builds a new exception with the given endpoint reference and method invocation exception.
+ * This constructor will be used when the invocation thrown the MethodInvocationException.
+ *
+ * @param endpointReference the endpoint reference.
+ * @param methodName the name of the method.
+ * @param message the explanatio message.
+ * @param returnCode the a mnemonic code associated with the failure.
+ */
+ public MethodInvocationFault(
+ EndpointReference endpointReference,
+ String methodName,
+ String message,
+ long returnCode)
+ {
+ super(
+ endpointReference,
+ new QName(
+ Names.NAMESPACE_URI,
+ "OperationInvocationFault",
+ Names.PREFIX),
+ String.format("OPERATION \"%s\" FAILURE. See detail section for further details.",methodName));
+ this._message = message;
+ this._returnCode = returnCode;
+ }
+
+ @Override
+ public Element getDetail()
+ {
+ Element detail = super.getDetail();
+ Document owner = detail.getOwnerDocument();
+ detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_TEXT_NAME,_message));
+ detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_CODE_NAME,_returnCode));
+ return detail;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java
new file mode 100644
index 0000000000..e9f37f8afb
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * This is the exception encapsulating the fault that will be thrown when a requested
+ * attribute is not found on the target ws resource.
+ *
+ * @author Andrea Gazzarini
+ */
+public class NoSuchAttributeFault extends QManFault
+{
+ private static final long serialVersionUID = 5977379710882983474L;
+
+ private String _attributeName;
+
+ /**
+ * Builds a new exception with the given endpoint reference, JMX object name
+ * and attribute that hasn't been found.
+ *
+ * @param endpointReference the endpoint reference.
+ * @param attributeName the name of the attribute that hasn't been found.
+ */
+ public NoSuchAttributeFault(EndpointReference endpointReference, String attributeName)
+ {
+ super(
+ endpointReference,
+ new QName(
+ Names.NAMESPACE_URI,
+ "NoSuchAttributeFault",
+ Names.PREFIX),
+ "Attribute not found on this WS-Resource.");
+ _attributeName = attributeName;
+ }
+
+ @Override
+ public Element getDetail()
+ {
+ Element detail = super.getDetail();
+ Document owner = detail.getOwnerDocument();
+ detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_ATTRIBUTE_NAME,_attributeName));
+ return detail;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java
new file mode 100644
index 0000000000..eb7eee9547
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.routing.ResourceIdFactory;
+import org.apache.qpid.management.Names;
+
+/**
+ * ResourceIdFactory implementation that is using an objectName as
+ * resource identifier.
+ * This is done in order to make a relationship between an MBean (which is part of the
+ * JMX core domain model) and a WS-Resource (the same entity as is represented on WS-DM adapter side).
+ *
+ * @author Andrea Gazzarini
+ */
+public class ObjectNameIdFactory implements ResourceIdFactory
+{
+ /**
+ * Returns the name of the identifier element.
+ *
+ * @return the name of the identifier element.
+ */
+ public QName getIdentifierName()
+ {
+ return Names.RESOURCE_ID_QNAME;
+ }
+
+ /**
+ * Returns the object name used as a resource identifier.
+ * Developer note : this factory is highly coupled with ThreadSessionManager stuff because
+ * the object name that will be used as identifier is supposed to be in the thread session.
+ *
+ * @return the object name used as a resource identifier.
+ */
+ public String getNextIdentifier()
+ {
+ ObjectName objectName = ThreadSessionManager.getInstance().getSession().getObjectName();
+ return objectName.getKeyProperty(Names.OBJECT_ID);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java
new file mode 100644
index 0000000000..0a52c2ba65
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.common;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.basefaults.BaseFault;
+import org.apache.qpid.management.Names;
+
+/**
+ * Base class for QMan thrown faults.
+ * This should be thrown to denote a situation where a not-well cause could be determined.
+ */
+public class QManFault extends BaseFault
+{
+ private static final long serialVersionUID = 5977379710882983474L;
+ private final static QName SERVICE = new QName(
+ Names.NAMESPACE_URI,
+ "QMan",
+ Names.PREFIX);
+
+ private final static QName EXCEPTION_QNAME = new QName(
+ Names.NAMESPACE_URI,
+ "QManFault",
+ Names.PREFIX);
+
+ /**
+ * Builds a new exception with the given endpoint reference and the exception cause.
+ *
+ * @param endpointReference the endpoint reference.
+ * @param cause the exception cause.
+ */
+ public QManFault(EndpointReference endpointReference, Exception cause)
+ {
+ super(EXCEPTION_QNAME,cause.getMessage());
+ setCode(SERVICE);
+ setOriginReference(endpointReference);
+ }
+
+ /**
+ * Builds a new exception with the given endpoint reference, qname and detail message.
+ *
+ * @param endpointReference the endpoint reference.
+ * @param qname the qname of this exception.
+ * @param message the detail message of this exception.
+ */
+ public QManFault(EndpointReference endpointReference, QName qname, String message)
+ {
+ super(qname,message);
+ setOriginReference(endpointReference);
+ setCode(SERVICE);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java
new file mode 100644
index 0000000000..1a34971c6a
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.routing.ResourceIdFactory;
+import org.apache.qpid.management.Names;
+
+/**
+ * A simple implementation of resource id factory that uses a UUID as resource
+ * identifier.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QManResourceIdFactory implements ResourceIdFactory
+{
+ /**
+ * Returns the identifier name for id element.
+ *
+ * @return the identifier name for id element.
+ */
+ public QName getIdentifierName()
+ {
+ return Names.RESOURCE_ID_QNAME;
+ }
+
+ /**
+ * Returns the next valid identifier.
+ *
+ * @return the next valid identifier.
+ */
+ public String getNextIdentifier()
+ {
+ return UUID.randomUUID().toString();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java
new file mode 100644
index 0000000000..588879b951
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+import javax.management.ObjectName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Thread-scoped session.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ThreadSession
+{
+ private ObjectName _objectName;
+ private Document _wsdl;
+ private Element [] _wsrmdProperties;
+
+ /**
+ * Empty constructor.
+ */
+ ThreadSession()
+ {
+ }
+
+ /**
+ * Gets the object name associated with this thread session.
+ *
+ * @return the object name associated with this thread session.
+ */
+ public ObjectName getObjectName()
+ {
+ return _objectName;
+ }
+
+ /**
+ * Sets the object name on this thread session.
+ *
+ * @param the object name of this thread session..
+ */
+ public void setObjectName(ObjectName objectName)
+ {
+ this._objectName = objectName;
+ }
+
+ /**
+ * Sets the WSDL document on this thread session.
+ *
+ * @param the WSDL document of this thread session..
+ */
+ public void setWsdlDocument(Document wsdlDoc)
+ {
+ this._wsdl = wsdlDoc;
+ }
+
+ /**
+ * Gets the WSDL document associated with this thread session.
+ *
+ * @return the WSDL document associated with this thread session.
+ */
+ public Document getWsdlDocument()
+ {
+ return _wsdl;
+ }
+
+ /**
+ * Gets the RDM elements associated with this thread session.
+ *
+ * @return the RDM elements associated with this thread session.
+ */
+ public Element[] getResourceMetadataDescriptor()
+ {
+ return _wsrmdProperties;
+ }
+
+ /**
+ * Sets the WSDL elements on this thread session.
+ *
+ * @param the WSDL elements of this thread session..
+ */
+ public void setResourceMetadataDescriptor(Element[] rmd)
+ {
+ this._wsrmdProperties = rmd;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java
new file mode 100644
index 0000000000..6a081bfec4
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.common;
+
+/**
+ * Thread session manager used to handle thread-scoped sessions.
+ *
+ * @author Andrea Gazzarini
+ */
+public final class ThreadSessionManager
+{
+ private static ThreadSessionManager instance = new ThreadSessionManager();
+
+ private ThreadLocal<ThreadSession> sessions;
+
+ /**
+ * Builds and initializes a new manager.
+ */
+ private ThreadSessionManager()
+ {
+ this.sessions = new ThreadLocal<ThreadSession>();
+ }
+
+ /**
+ * Returns the singleton instance of this manager.
+ *
+ * @return the singleton instance of this manager.
+ */
+ public static ThreadSessionManager getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Returns (or create and returns) the session associated with the
+ * current thread.
+ *
+ * @return the thread session.
+ */
+ public ThreadSession getSession()
+ {
+ ThreadSession session = (ThreadSession) sessions.get();
+ if (session == null)
+ {
+ session = new ThreadSession();
+ sessions.set(session);
+ }
+ return session;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java
new file mode 100644
index 0000000000..55365b4051
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.common;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * This is the exception encapsulating the fault that will be thrown in case of
+ * broker connection failure.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UnableToConnectWithBrokerFault extends QManFault
+{
+ private static final long serialVersionUID = 5977379710882983474L;
+
+ private String _host;
+ private int _port;
+ private String _username;
+ private String _virtualHostName;
+
+ /**
+ * Builds a new exception with the given endpoint reference and connection data.
+ *
+ * @param host the requested qpid host.
+ * @param port the requested qpid port.
+ * @param username the username used for estabilishing connection.
+ * @param virtualHostName the name of the target virtual host..
+ */
+ public UnableToConnectWithBrokerFault(
+ EndpointReference endpointReference,
+ String host,
+ int port,
+ String username,
+ String virtualHostName,
+ String message)
+ {
+ super(
+ endpointReference,
+ new QName(
+ Names.NAMESPACE_URI,
+ "UnableToConnectFault",
+ Names.PREFIX),
+ String.format("Unable to connect with the requested broker. Underlying exception message was %s",message));
+ this._host = host;
+ this._port = port;
+ this._username = username;
+ this._virtualHostName = virtualHostName;
+ }
+
+ @Override
+ public Element getDetail()
+ {
+ Element detail = super.getDetail();
+ Document owner = detail.getOwnerDocument();
+ detail.appendChild(XmlUtils.createElement(owner, Names.HOST_QNAME,_host));
+ detail.appendChild(XmlUtils.createElement(owner, Names.PORT_QNAME,_port));
+ detail.appendChild(XmlUtils.createElement(owner, Names.USERNAME_QNAME,_username));
+ detail.appendChild(XmlUtils.createElement(owner, Names.VIRTUAL_HOST_QNAME,_virtualHostName));
+ return detail;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java
new file mode 100644
index 0000000000..e4d0f25adc
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java
@@ -0,0 +1,118 @@
+package org.apache.qpid.management.wsdm.muse.engine;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import java.io.File;
+import java.net.URI;
+
+import javax.servlet.ServletContext;
+
+import org.apache.muse.core.AbstractEnvironment;
+import org.apache.muse.util.FileUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * QMan Adapter enviroment implementation.
+ *
+ * @author Andrea Gazzarini
+ */
+public class WSDMAdapterEnvironment extends AbstractEnvironment
+{
+ private final static Logger LOGGER = Logger.get(WSDMAdapterEnvironment.class);
+ private final File _realDirectory;
+ private final ServletContext _servletContext;
+
+ /**
+ * Builds a new qman environment with the given application context.
+ *
+ * @param servletContext the application context.
+ */
+ public WSDMAdapterEnvironment(ServletContext servletContext)
+ {
+ this._servletContext = servletContext;
+ String realDirectoryPath = servletContext.getRealPath(Names.WEB_APP_CLASSES_FOLDER);
+
+ _realDirectory = (realDirectoryPath != null)
+ ? new File(realDirectoryPath)
+ : FileUtils.CURRENT_DIR;
+
+ String defaultURI = getDefaultURIPrefix()+"adapter";
+ setDefaultURI(defaultURI);
+
+ LOGGER.info(Messages.QMAN_000029_DEFAULT_URI, defaultURI);
+ }
+
+ /**
+ * Returns the endpoint created starting by this application default URI.
+ *
+ * @return the endpoint created starting by this application default URI.
+ */
+ public EndpointReference getDeploymentEPR()
+ {
+ return new EndpointReference(URI.create(getDefaultURI()));
+ }
+
+ /**
+ * Returns the application classes folder.
+ *
+ * @return the application classes folder.
+ */
+ public File getRealDirectory()
+ {
+ return _realDirectory;
+ }
+
+ /**
+ * Returns the default endpoint reference URI.
+ *
+ * @return the default endpoint reference URI.
+ */
+ public String getDefaultURIPrefix()
+ {
+ return new StringBuilder()
+ .append("http://")
+ .append(System.getProperty(
+ Names.ADAPTER_HOST_PROPERTY_NAME,
+ Protocol.DEFAULT_QMAN_HOSTNAME))
+ .append(":")
+ .append(System.getProperty(
+ Names.ADAPTER_PORT_PROPERTY_NAME,
+ String.valueOf(Protocol.DEFAULT_QMAN_PORT_NUMBER)))
+ .append(_servletContext.getContextPath())
+ .append("/services/")
+ .toString();
+ }
+
+ /**
+ * Returns the context path name of QMan application.
+ *
+ * @return the context path name of QMan application.
+ */
+ public String getContextPath()
+ {
+ return _servletContext.getContextPath();
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java
new file mode 100644
index 0000000000..e9a74bf60c
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java
@@ -0,0 +1,57 @@
+package org.apache.qpid.management.wsdm.muse.engine;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+import javax.servlet.ServletContext;
+
+import org.apache.muse.core.Environment;
+import org.apache.muse.core.platform.mini.MiniIsolationLayer;
+
+/**
+ * QMan specific implementation of the Apache Muse isolation layer.
+ * If you are a Muse expert you were wondering why don't we use the muse default implementation...
+ * well,
+ *
+ * @author Andrea Gazzarini
+ */
+public class WSDMAdapterIsolationLayer extends MiniIsolationLayer
+{
+ /**
+ * Builds a new isolation layer with the given application context.
+ *
+ * @param initialContext the application context.
+ */
+ public WSDMAdapterIsolationLayer(ServletContext initialContext)
+ {
+ super(null, initialContext);
+ }
+
+ /**
+ * WSDMAdapterEnvironment factory method.
+ *
+ * @return the environment.
+ */
+ protected Environment createEnvironment()
+ {
+ return new WSDMAdapterEnvironment(getInitialContext());
+ }
+}
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java
new file mode 100644
index 0000000000..c16c156b73
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java
@@ -0,0 +1,762 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.muse.resources;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.Capability;
+import org.apache.muse.core.Environment;
+import org.apache.muse.core.ResourceManager;
+import org.apache.muse.core.routing.MessageHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.addressing.WsaConstants;
+import org.apache.muse.ws.addressing.soap.SoapConstants;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.addressing.soap.SoapUtils;
+import org.apache.muse.ws.resource.WsResource;
+import org.apache.muse.ws.resource.metadata.MetadataDescriptor;
+import org.apache.muse.ws.resource.metadata.WsrmdConstants;
+import org.apache.muse.ws.resource.metadata.impl.SimpleMetadataDescriptor;
+import org.apache.muse.ws.resource.metadata.impl.WsrmdUtils;
+import org.apache.muse.ws.resource.properties.ResourcePropertyCollection;
+import org.apache.muse.ws.resource.properties.impl.SimpleResourcePropertyCollection;
+import org.apache.muse.ws.resource.properties.impl.WsrpUtils;
+import org.apache.muse.ws.resource.properties.schema.ResourcePropertiesSchema;
+import org.apache.muse.ws.resource.properties.schema.impl.SimpleResourcePropertiesSchema;
+import org.apache.muse.ws.wsdl.WsdlUtils;
+import org.apache.qpid.management.Messages;
+import org.apache.qpid.management.wsdm.common.ThreadSessionManager;
+import org.apache.qpid.transport.util.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * QMan WS resource.
+ * We could say that this is a QMan manageable entity under the
+ * WS-DM perspective.
+ *
+ * @author Andrea Gazzarini
+ */
+@SuppressWarnings("unchecked")
+public class QManWsResource implements WsResource
+{
+ private final static Logger LOGGER = Logger.get(QManWsResource.class);
+
+ /**
+ * Internal state of this resource.
+ *
+ * @author Andrea Gazzarini
+ */
+ interface State
+ {
+ /**
+ * Provides initialization of this resource.
+ *
+ * @throws SoapFault when the initialization fails.
+ */
+ void initialize() throws SoapFault;
+
+ /**
+ * Returns true if this resource has been initialized.
+ *
+ * @return true if this resource has been initialized.
+ */
+ boolean hasBeenInitialized();
+
+ /**
+ * Returns true if this resource has been shutdown.
+ *
+ * @return true if this resource has been shutdown.
+ */
+ boolean hasBeenShutdown();
+
+ /**
+ * Shuts down this resource.
+ *
+ * @throws SoapFault when the shutdown procedure fails.
+ */
+ void shutdown() throws SoapFault;
+ }
+
+ private final State _hasBeenShutdown = new State()
+ {
+ /**
+ * Return false because this resource has been shutdown so therefore
+ * initialization occurred.
+ *
+ * @return true;
+ */
+ public boolean hasBeenInitialized()
+ {
+ return true;
+ }
+
+ /**
+ * Returns true because this state indicates that resource has been shutdown.
+ *
+ * @return true.
+ */
+ public boolean hasBeenShutdown()
+ {
+ return true;
+ }
+
+ /**
+ * Since this resource has been shutdown the initialization
+ * cannot be performed again.
+ * As conseguence of that this method throws an exception.
+ *
+ * @throws SoapFault each time this method is called.
+ */
+ public void initialize() throws SoapFault
+ {
+ LOGGER.error(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED);
+ throw new SoapFault(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED);
+ }
+
+ public void shutdown() throws SoapFault
+ {
+ LOGGER.error(Messages.QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN);
+ throw new SoapFault(Messages.QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN);
+ }
+ };
+
+ private final State _hasBeenInitialized = new State()
+ {
+ /**
+ * Returns true because this is the state where a resource is when it
+ * has been initialized.
+ *
+ * @return true.
+ */
+ public boolean hasBeenInitialized()
+ {
+ return true;
+ }
+
+ /**
+ * Returns false because this resource has been initialized but no shutdown request
+ * has been received.
+ *
+ * @return false.
+ */
+ public boolean hasBeenShutdown()
+ {
+ return false;
+ }
+
+ /**
+ * A resource in this state cannot be initialized again so if this method is called an
+ * exception is thrown.
+ *
+ * @throws SoapFault each time this method is called.
+ */
+ public void initialize() throws SoapFault
+ {
+ LOGGER.error(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED);
+ throw new SoapFault(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED);
+ }
+
+ /**
+ * Shuts down this resource.
+ *
+ * @throws SoapFault when the shutdown procedure fails.
+ */
+ public void shutdown() throws SoapFault
+ {
+ shutdownCapabilities();
+
+ ResourceManager manager = getResourceManager();
+
+ if (manager.getResource(_enpointReference) != null)
+ {
+ manager.removeResource(_enpointReference);
+ }
+
+ _currentState = _hasBeenShutdown;
+ }
+ };
+
+ /**
+ * The initial state of this resource.
+ * As the name suggests, it is not yet initialized.
+ */
+ private final State _notYetInitialized = new State()
+ {
+ /**
+ * Provides initialization of this resource.
+ *
+ * @throws SoapFault when the initialization fails.
+ */
+ public void initialize() throws SoapFault
+ {
+ _properties = new SimpleResourcePropertyCollection();
+ _wsdl = ThreadSessionManager.getInstance().getSession().getWsdlDocument();
+
+ ResourcePropertiesSchema schema = createPropertiesSchema(_wsdl);
+ _properties.setSchema(schema);
+
+ MetadataDescriptor metadata = createMetadataDescriptor(_wsdl);
+ _properties.setMetadata(metadata);
+
+ initializeCapabilities();
+
+ _properties.applyMetadata();
+
+ // Resource intialization completed : Let's make a state change.
+ _currentState = _hasBeenInitialized;
+ }
+
+ /**
+ * Shuts down this resource.
+ *
+ * @throws SoapFault when the shutdown procedure fails. */
+ public void shutdown() throws SoapFault
+ {
+ LOGGER.error(Messages.QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED);
+ throw new SoapFault(Messages.QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED);
+ }
+
+ /**
+ * Returns false because this state indicates that
+ * the resource has not yet been initialized.
+ *
+ * @return false;
+ */
+ public boolean hasBeenInitialized()
+ {
+ return false;
+ }
+
+ /**
+ * Returns false because the resource, when is in this state
+ * hasn't been initialized and as conseguence of that hasn't
+ * been shutdonm.
+ *
+ * @return false;
+ */
+ public boolean hasBeenShutdown()
+ {
+ return false;
+ }
+ };
+
+ private Map<String,Capability> _capabilitiesByAction = new HashMap<String, Capability>();
+ private Map<String, Capability> _capabilitiesByURI = new LinkedHashMap<String, Capability>();
+
+ private String _contextPath;
+ private Environment _environment;
+ private EndpointReference _enpointReference;
+
+ private State _currentState = _notYetInitialized;
+
+ private ResourceManager _resourceManager;
+ private ResourcePropertyCollection _properties;
+
+ private Map<String,String> _initParameters = Collections.EMPTY_MAP;
+
+ // Workaround : muse is using and hardcoded java.util.logging.Logger but we should use
+ // SLF4j so this is the original implementatation that won't never be used (on QMan classes)
+ private java.util.logging.Logger _logger;
+
+ private Document _wsdl;
+ private String _wsdlPath;
+ private QName _wsdlPortType;
+
+ /**
+ * Adds the given capability to this resource.
+ *
+ * @param capability the capability to be added.
+ */
+ public void addCapability(Capability capability)
+ {
+ capability.setResource(this);
+ capability.setLog(getLog());
+ capability.setEnvironment(getEnvironment());
+
+ String uri = capability.getCapabilityURI();
+ _capabilitiesByURI.put(uri, capability);
+
+ LOGGER.debug(
+ Messages.QMAN_200033_CAPABILITY_CLASS_HAS_BEEN_ADDED,
+ capability.getClass(),
+ uri);
+ }
+
+ /**
+ * Returns the capability associated with the given URI.
+ *
+ * @return the capability associated with the given URI.
+ */
+ public Capability getCapability(String capabilityURI)
+ {
+ return _capabilitiesByURI.get(capabilityURI);
+ }
+
+ /**
+ * Returns a collection with all registered capability URIs.
+ *
+ * @return a collection with all registered capability URIs.
+ */
+ public final Collection getCapabilityURIs()
+ {
+ return Collections.unmodifiableSet(_capabilitiesByURI.keySet());
+ }
+
+ /**
+ * Returns the context path of this resource.
+ *
+ * @return the context path of this resource.
+ */
+ public final String getContextPath()
+ {
+ return _contextPath;
+ }
+
+ /**
+ * Returns the endpoint reference of this resource.
+ *
+ * @return the endpoint reference of this resource.
+ */
+ public EndpointReference getEndpointReference()
+ {
+ return _enpointReference;
+ }
+
+ /**
+ * Returns the enviroment associated with this resource.
+ *
+ * @return the enviroment associated with this resource.
+ */
+ public final Environment getEnvironment()
+ {
+ return _environment;
+ }
+
+ /**
+ * Returns the initialization parameter of this resource associated with
+ * the given name.
+ *
+ * @param name the init parameter name.
+ * @return the initialization parameter associated with the given name.
+ */
+ public final String getInitializationParameter(String name)
+ {
+ return (String)getInitializationParameters().get(name);
+ }
+
+ /**
+ * Returns the map containing all init parameters of this resource.
+ *
+ * @return the map containing all init parameters of this resource.
+ */
+ public final Map<String,String> getInitializationParameters()
+ {
+ return _initParameters;
+ }
+
+ /**
+ * N.A. This resource uses QMan logging instead of plain java.util.logger
+ * implementation.
+ */
+ public final java.util.logging.Logger getLog()
+ {
+ return _logger;
+ }
+
+ /**
+ * Returns the resource manager associated with this resource.
+ *
+ * @return the resource manager associated with this resource.
+ */
+ public ResourceManager getResourceManager()
+ {
+ return _resourceManager;
+ }
+
+ /**
+ * Returns the wsdl (relative) path of this resource.
+ *
+ * @return the wsdl (relative) path of this resource.
+ */
+ public String getWsdlPath()
+ {
+ return _wsdlPath;
+ }
+
+ /**
+ * Returns the port type of this resource.
+ *
+ * @return the port type of this resource.
+ */
+ public final QName getWsdlPortType()
+ {
+ return _wsdlPortType;
+ }
+
+ /**
+ * Returns true if this resource has been initialized, false otherwise.
+ *
+ * @return true if this resource has been initialized, false otherwise.
+ */
+ public final boolean hasBeenInitialized()
+ {
+ return _currentState.hasBeenInitialized();
+ }
+
+ /**
+ * Returns true if this resource has been shutdown, false otherwise.
+ *
+ * @return true if this resource has been shutdown, false otherwise.
+ */
+ public final boolean hasBeenShutdown()
+ {
+ return _currentState.hasBeenShutdown();
+ }
+
+ /**
+ * Checks if a capability with the given URI is available for this resource.
+ *
+ * @return true if a capability with the given URI is available for this resource, false otherwise.
+ */
+ public final boolean hasCapability(String capabilityURI)
+ {
+ return getCapability(capabilityURI) != null;
+ }
+
+ /**
+ * Returns the collection containing all properties of this resource.
+ *
+ * @return the collection containing all properties of this resource.
+ */
+ public final ResourcePropertyCollection getPropertyCollection()
+ {
+ return _properties;
+ }
+
+ /**
+ * Return the WSDL document of this resource.
+ *
+ * @return the WSDL document of this resource.
+ */
+ public Document getWsdl()
+ {
+ return _wsdl;
+ }
+
+ /**
+ * Initializes this resources.
+ * Note that the what needs to be done depends on the current state of this
+ * resource.
+ *
+ * @throws SoapFault when the initialization fails.
+ */
+ public void initialize() throws SoapFault
+ {
+ _currentState.initialize();
+ }
+
+ /**
+ * Invokes the action specified in the given soap request on this resource.
+ *
+ * @param requestBody the SOAP body.
+ * @return the result of the invocation as org.w3c.dom.Element
+ */
+ public Element invoke(Element requestBody)
+ {
+ String action = _environment.getAddressingContext().getAction();
+ Capability capability = getCapabilityForAction(action);
+
+ // Sanity check : is there a capability for the given action?
+ if (capability == null)
+ {
+ SoapFault wsaFault = new SoapFault(
+ String.format(
+ Messages.ACTION_NOT_SUPPORTED,
+ action,getContextPath()));
+
+ wsaFault.setCode(SoapConstants.SENDER_QNAME);
+ wsaFault.setSubCode(WsaConstants.ACTION_NOT_SUPPORTED_FAULT_QNAME);
+
+ Element detail = XmlUtils.createElement(WsaConstants.PROBLEM_ACTION_QNAME);
+ XmlUtils.setElement(detail, WsaConstants.ACTION_QNAME, action);
+ wsaFault.setDetail(detail);
+
+ LOGGER.error(
+ Messages.QMAN_100020_ACTION_NOT_SUPPORTED,
+ action,
+ getContextPath());
+
+ return wsaFault.toXML();
+ }
+
+ MessageHandler handler = capability.getMessageHandler(action);
+ Method method = handler.getMethod();
+
+ try
+ {
+ Object[]parameters = handler.fromXML(requestBody);
+ Object result = method.invoke(capability, parameters);
+ return handler.toXML(result);
+ }
+ catch (Throwable throwable)
+ {
+ LOGGER.error(
+ throwable,
+ Messages.QMAN_100037_INVOKE_OPERATION_FAILURE);
+
+ SoapFault response = SoapUtils.convertToFault(
+ (throwable.getCause()!= null)
+ ? throwable.getCause()
+ : throwable);
+ return response.toXML();
+ }
+ }
+
+ /**
+ * Sets the context path of this resource.
+ *
+ * @param contextPath the context path of this resource.
+ */
+ public final void setContextPath(String contextPath)
+ {
+ _contextPath = contextPath;
+ }
+
+ /**
+ * Sets the endpoint reference of this resource.
+ *
+ * @param endpointReference the endpoint reference of this resource.
+ */
+ public final void setEndpointReference(EndpointReference endpointReference)
+ {
+ if (_enpointReference != null && hasBeenInitialized())
+ throw new RuntimeException(("ExistingResourceEPR"));
+
+ _enpointReference = endpointReference;
+ }
+
+ /**
+ * Sets the context environment of this resource.
+ *
+ * @param environment the context environment of this resource.
+ */
+ public final void setEnvironment(Environment environment)
+ {
+ _environment = environment;
+ }
+
+ /**
+ * Sets the initialization parameters of this resource.
+ *
+ * @param parameters the init parameters of this resource.
+ */
+ public final void setInitializationParameters(Map parameters)
+ {
+ _initParameters = (parameters != null)
+ ? parameters
+ : Collections.EMPTY_MAP;
+ }
+
+ /**
+ * N.A. for this resource. QMan logging mechanism is used for that.
+ */
+ public final void setLog(java.util.logging.Logger log)
+ {
+ _logger = log;
+ }
+
+ /**
+ * Sets the resource manager owner of this resource.
+ *
+ * @param manager the resource manager of this resource.
+ */
+ public void setResourceManager(ResourceManager manager)
+ {
+ _resourceManager = manager;
+ }
+
+ /**
+ * Sets the WSDL (relative) path of this resource.
+ *
+ * @param wsdlPath the WSDL (relative) path of this resource.
+ */
+ public final void setWsdlPath(String wsdlPath)
+ {
+ this._wsdlPath = wsdlPath;
+ }
+
+ /**
+ * Sets the port type of this resource.
+ *
+ * @param wsdlPortType the port type of this resource.
+ */
+ public final void setWsdlPortType(QName wsdlPortType)
+ {
+ _wsdlPortType = wsdlPortType;
+ }
+
+ /**
+ * Shutdown procedure for this resource.
+ *
+ * @throws SoapFault when the shutdown procedure fails.
+ */
+ public synchronized void shutdown() throws SoapFault
+ {
+ _currentState.shutdown();
+ }
+
+ /**
+ * Returns a string representation of this resource.
+ * Basically the resource endpoint reference (as a string) is returned.
+ *
+ * @return the resource endpoint reference (as a string) is returned.
+ */
+ public String toString()
+ {
+ return getEndpointReference().toString();
+ }
+
+ /**
+ * Initializes capabilities of this resource.
+ *
+ * @throws SoapFault when at least one capability fails to initialize.
+ */
+ private void initializeCapabilities() throws SoapFault
+ {
+ for (Entry<String, Capability> entry : _capabilitiesByURI.entrySet())
+ {
+ Capability capability = entry.getValue();
+ capability.initialize();
+
+ for (Object action : capability.getActions())
+ {
+ _capabilitiesByAction.put((String)action, capability);
+ }
+
+ capability.initializeCompleted();
+ }
+ }
+
+ /**
+ * Shutdown procedure for all registered capabilities of this resource.
+ *
+ * @throws SoapFault when at least one capability shutdown fails.
+ */
+ private void shutdownCapabilities() throws SoapFault
+ {
+ for (Entry<String,Capability> entry : _capabilitiesByURI.entrySet())
+ {
+ Capability capabilty = entry.getValue();
+ capabilty.prepareShutdown();
+ capabilty.shutdown();
+ }
+ }
+
+ /**
+ * Creates a metadata descriptor for this resource.
+ *
+ * @param wsdl the WSDL document.
+ * @return a metadata descriptor for this resource.
+ * @throws SoapFault when it's not possible build the descriptor.
+ */
+ private MetadataDescriptor createMetadataDescriptor(Document wsdl) throws SoapFault
+ {
+ try
+ {
+ Element portTypeXML = WsdlUtils.getPortType(wsdl, getWsdlPortType());
+
+ String rmdName = XmlUtils.getAttribute(
+ portTypeXML,
+ WsrmdConstants.DESCRIPTOR_ATTR_QNAME);
+
+ String rmdPath = XmlUtils.getAttribute(
+ portTypeXML,
+ WsrmdConstants.DESCRIPTOR_LOCATION_ATTR_QNAME);
+
+ LOGGER.debug(Messages.QMAN_200034_RMD_NAME, rmdName);
+ LOGGER.debug(Messages.QMAN_200035_RMD_PATH, rmdPath);
+
+ Environment env = getEnvironment();
+ String path = env.createRelativePath(getWsdlPath(), rmdPath);
+ Document rmdDoc = env.getDocument(path);
+
+ Element[] additionalProperties =
+ ThreadSessionManager
+ .getInstance()
+ .getSession()
+ .getResourceMetadataDescriptor();
+
+ Element metadataDescriptor = WsrmdUtils.getMetadataDescriptor(rmdDoc, rmdName);
+
+ for (Element element : additionalProperties)
+ {
+
+// rmdDoc.importNode(element, true);
+ Element adopted = (Element) rmdDoc.importNode(element,false);
+ metadataDescriptor.appendChild(adopted);
+ }
+
+ return new SimpleMetadataDescriptor(metadataDescriptor);
+ }
+ catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ Messages.QMAN_100021_RMD_BUID_FAILURE,
+ getContextPath());
+ throw new SoapFault(exception);
+ }
+ }
+
+ /**
+ * Returns the capability associated with the given action.
+ *
+ * @param action the wsa:action of the requested capability.
+ * @return the capability associated with the given action.
+ */
+ private Capability getCapabilityForAction(String action)
+ {
+ return (Capability)_capabilitiesByAction.get(action);
+ }
+
+ /**
+ * Creates a WSRP document representing schema properties for this resource.
+ *
+ * @param wsdl the DOM document holding the resource's WSDL.
+ * @return the WSRP document schema.
+ */
+ private ResourcePropertiesSchema createPropertiesSchema(Document wsdl)
+ {
+ QName wsrpName = WsrpUtils.getPropertiesName(wsdl, getWsdlPortType());
+ Element wsrpDoc = WsdlUtils.getElementDeclaration(wsdl, wsrpName);
+ return new SimpleResourcePropertiesSchema(wsrpName, wsrpDoc);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java
new file mode 100644
index 0000000000..a064542658
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm.muse.serializer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.xerces.impl.dv.util.Base64;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of Muse Serializer for byte array type.
+ *
+ * @author Andrea Gazzarini
+ */
+public class ByteArraySerializer implements Serializer {
+
+ /**
+ * Return a byte array representation of the given xml element.
+ *
+ * @param xml the element to unmarshal.
+ * @throws SoapFault when the unmarshalling fails.
+ */
+ public Object fromXML(Element xml) throws SoapFault
+ {
+ try
+ {
+ return Base64.decode(xml.getTextContent());
+ } catch (Exception exception)
+ {
+ throw new SoapFault(exception);
+ }
+ }
+
+ /**
+ * Returns the java type associated to this class.
+ *
+ * @return the java type associated to this class.
+ */
+ public Class<?> getSerializableType()
+ {
+ return byte[].class;
+ }
+
+ /**
+ * Return an xml representation of the given byte array with the given name.
+ *
+ * @param object the byte array to marshal.
+ * @param qname the qualified (xml) name of the object to use in xml representation.
+ * @return the xml representation of the byte array.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Element toXML(Object object, QName qname) throws SoapFault
+ {
+ Element element = XmlUtils.createElement(
+ qname,
+ Base64.encode((byte[]) object));
+ element.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
+ element.setAttribute("xsi:type","xsd:base64Binary");
+ return element;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java
new file mode 100644
index 0000000000..60350ccc31
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm.muse.serializer;
+
+import java.util.Date;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of Muse Serializer for Date type.
+ * Note that Muse already ships a serializer but the formatter used on that class
+ * is losing precision betweem marshal / unmarshal operations.
+ *
+ * @author Andrea Gazzarini
+ */
+public class DateSerializer implements Serializer
+{
+ /**
+ * Return a Date representation of the given xml element.
+ *
+ * @param xml the element to unmarshal.
+ * @throws SoapFault when the unmarshalling fails.
+ */
+ public Object fromXML(Element elementData) throws SoapFault
+ {
+ return new Date(Long.parseLong(elementData.getTextContent()));
+ }
+
+ /**
+ * Returns the java type associated to this class.
+ *
+ * @return the java type associated to this class.
+ */
+ public Class<?> getSerializableType()
+ {
+ return Date.class;
+ }
+
+ /**
+ * Return an xml representation of the given UUID with the given name.
+ *
+ * @param object the UUID to marshal.
+ * @param qname the qualified (xml) name of the object to use in xml representation.
+ * @return the xml representation of the UUID.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Element toXML(Object obj, QName qname) throws SoapFault
+ {
+ Date date = (Date) obj;
+ return XmlUtils.createElement(qname, String.valueOf(date.getTime()));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java
new file mode 100644
index 0000000000..b819d52ad1
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.muse.serializer;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.wsdm.capabilities.Result;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of Muse Serializer for Result type.
+ *
+ * @author Andrea Gazzarini
+ */
+public class InvocationResultSerializer implements Serializer
+{
+ private Serializer _mapSerializer = SerializerRegistry.getInstance().getSerializer(Map.class);
+
+ /**
+ * Return a UUID representation of the given xml element.
+ *
+ * @param xml the element to unmarshal.
+ * @throws SoapFault when the unmarshalling fails.
+ */
+ @SuppressWarnings("unchecked")
+ public Object fromXML(Element elementData) throws SoapFault
+ {
+ Element outputParameters = XmlUtils.getFirstElement(elementData);
+ return new Result((Map<String, Object>) _mapSerializer.fromXML(outputParameters));
+ }
+
+ /**
+ * Returns the java type associated to this class.
+ *
+ * @return the java type associated to this class.
+ */
+ public Class<?> getSerializableType()
+ {
+ return Result.class;
+ }
+
+ /**
+ * Return an xml representation of the given UUID with the given name.
+ *
+ * @param object the UUID to marshal.
+ * @param qname the qualified (xml) name of the object to use in xml representation.
+ * @return the xml representation of the UUID.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Element toXML(Object obj, QName qname) throws SoapFault
+ {
+ Result result = (Result) obj;
+ Element root = XmlUtils.createElement(qname);
+ if (result.getOutputParameters() != null)
+ {
+ Element outputSection = SerializerRegistry.getInstance().getSerializer(Map.class).toXML(result.getOutputParameters(), new QName("outputParameters"));
+ root.appendChild(outputSection);
+ }
+ return root;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java
new file mode 100644
index 0000000000..07e1dfdc56
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java
@@ -0,0 +1,134 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.muse.serializer;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of Muse Serializer for Map type.
+ *
+ * <amspam>
+ * <entry>
+ * <key>
+ * <value>
+ * </entry>
+ * </amsasm>
+ *
+ * @author Andrea Gazzarini
+ */
+public class MapSerializer implements Serializer
+{
+
+ ByteArraySerializer _byteArraySerializer = new ByteArraySerializer();
+ Serializer _objectSerializer = SerializerRegistry.getInstance().getSerializer(Object.class);
+ Serializer _stringSerializer = SerializerRegistry.getInstance().getSerializer(String.class);
+
+ /**
+ * Return a map representation of the given xml element.
+ *
+ * @param xml the element to unmarshal.
+ * @throws SoapFault when the unmarshalling fails.
+ */
+ public Object fromXML(Element xml) throws SoapFault
+ {
+ Map<Object,Object> result = new HashMap<Object,Object>();
+
+ if (xml != null)
+ {
+ Element[] children = XmlUtils.getAllElements(xml);
+ Serializer objectDeserializer = SerializerRegistry.getInstance().getSerializer(Object.class);
+
+ for (Element entry : children)
+ {
+ Element[] keysAndValues = XmlUtils.getAllElements(entry);
+ Object key = null;
+ Object value = null;
+ for (Element element : keysAndValues)
+ {
+ if (Names.KEY.equals(element.getLocalName()))
+ {
+ key = _stringSerializer.fromXML(element);
+ } else if (Names.VALUE.equals(element.getLocalName()))
+ {
+ value = objectDeserializer.fromXML(element);
+ }
+ }
+ result.put(key, value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the java type associated to this class.
+ *
+ * @return the java type associated to this class.
+ */
+ public Class<?> getSerializableType()
+ {
+ return Map.class;
+ }
+
+ /**
+ * Return an xml representation of the given Map with the given name.
+ *
+ * @param object the Map to marshal.
+ * @param qname the qualified (xml) name of the object to use in xml representation.
+ * @return the xml representation of the given Map.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Element toXML(Object obj, QName qname) throws SoapFault
+ {
+
+ Map<?, ?> data = (Map<?, ?>) obj;
+
+ QName entryQName = new QName(qname.getNamespaceURI(),Names.ENTRY,qname.getPrefix());
+ QName keyQName = new QName(qname.getNamespaceURI(),Names.KEY,qname.getPrefix());
+ QName valueQName = new QName(qname.getNamespaceURI(),Names.VALUE,qname.getPrefix());
+
+ Element root = XmlUtils.createElement(qname);
+ root.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
+ for (Entry<?, ?> mapEntry: data.entrySet())
+ {
+ Element entry = XmlUtils.createElement(entryQName);
+ entry.appendChild(_stringSerializer.toXML(mapEntry.getKey(), keyQName));
+ if (mapEntry.getValue().getClass() == byte[].class) {
+ entry.appendChild(_byteArraySerializer.toXML(mapEntry.getValue(), valueQName));
+ } else {
+ entry.appendChild(_objectSerializer.toXML(mapEntry.getValue(), valueQName));
+ }
+ root.appendChild(entry);
+ }
+ return root;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java
new file mode 100644
index 0000000000..ff0c69cdda
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java
@@ -0,0 +1,202 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.muse.serializer;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+/**
+ * Generic Serializer for objects.
+ * It is a general-purpose serializer used for encoding Object values.
+ */
+public class ObjectSerializer implements Serializer
+{
+ /**
+ * Mapping between xsd and java types.
+ */
+ private Map<String, Class<?>> xml2Java = new HashMap<String, Class<?>>();
+ {
+ xml2Java.put("xsd:long", Long.class);
+ xml2Java.put("xsd:boolean",Boolean.class);
+ xml2Java.put("xsd:double",Double.class);
+ xml2Java.put("xsd:float",Float.class);
+ xml2Java.put("xsd:integer",Integer.class);
+ xml2Java.put("xsd:int",Integer.class);
+ xml2Java.put("xsd:short",Short.class);
+ xml2Java.put("xsd:string",String.class);
+ xml2Java.put("xsd:anyURI",URI.class);
+ xml2Java.put("xsd:dateTime",Date.class);
+ xml2Java.put("xsd:QName",QName.class);
+ xml2Java.put("xsd:element",Element.class);
+ xml2Java.put("xsd:base64Binary",byte[].class);
+ xml2Java.put("qman:arrayOfLong",Long[].class);
+ xml2Java.put("qman:arrayOfBoolean",Boolean[].class);
+ xml2Java.put("qman:arrayOfDouble",Double[].class);
+ xml2Java.put("qman:arrayOfFloat",Float[].class);
+ xml2Java.put("qman:arrayOfInteger",Integer[].class);
+ xml2Java.put("qman:arrayOfShort",Short[].class);
+ xml2Java.put("qman:arrayOfString",String[].class);
+ xml2Java.put("qman:arrayOfURI",URI[].class);
+ xml2Java.put("qman:arrayOfDate",Date[].class);
+ xml2Java.put("qman:uuid",UUID.class);
+ xml2Java.put("qman:map",Map.class);
+ xml2Java.put("qman:map",HashMap.class);
+ }
+
+ private Map<Class<?>, String> java2Xml = new HashMap<Class<?>, String>();
+ {
+ java2Xml.put(UUID.class,"qman:uuid");
+ java2Xml.put(Long.class,"xsd:long");
+ java2Xml.put(long.class,"xsd:long");
+ java2Xml.put(Boolean.class,"xsd:boolean");
+ java2Xml.put(boolean.class,"xsd:boolean");
+ java2Xml.put(Double.class,"xsd:double");
+ java2Xml.put(double.class,"xsd:double");
+ java2Xml.put(Float.class,"xsd:float");
+ java2Xml.put(float.class,"xsd:float");
+ java2Xml.put(Integer.class,"xsd:integer");
+ java2Xml.put(int.class,"xsd:integer");
+ java2Xml.put(Short.class,"xsd:short");
+ java2Xml.put(short.class,"xsd:short");
+ java2Xml.put(String.class,"xsd:string");
+ java2Xml.put(URI.class,"xsd:anyURI");
+ java2Xml.put(Date.class,"xsd:dateTime");
+ java2Xml.put(QName.class,"xsd:QName");
+ java2Xml.put(Element.class,"xsd:element");
+ java2Xml.put(byte[].class,"xsd:base64Binary");
+ java2Xml.put(Long[].class,"qman:arrayOfLong");
+ java2Xml.put(long[].class,"qman:arrayOfLong");
+ java2Xml.put(Boolean[].class,"qman:arrayOfBoolean");
+ java2Xml.put(boolean[].class,"qman:arrayOfBoolean");
+ java2Xml.put(Double[].class,"qman:arrayOfDouble");
+ java2Xml.put(double[].class,"qman:arrayOfDouble");
+ java2Xml.put(Float[].class,"qman:arrayOfFloat");
+ java2Xml.put(float[].class,"qman:arrayOfFloat");
+ java2Xml.put(Integer[].class,"qman:arrayOfInteger");
+ java2Xml.put(int[].class,"qman:arrayOfInteger");
+ java2Xml.put(Short[].class,"qman:arrayOfShort");
+ java2Xml.put(short[].class,"qman:arrayOfShort");
+ java2Xml.put(String[].class,"qman:arrayOfString");
+ java2Xml.put(URI[].class,"qman:arrayOfURI");
+ java2Xml.put(Date[].class,"qman:arrayOfDate");
+ java2Xml.put(Map.class,"qman:map");
+ java2Xml.put(HashMap.class,"qman:map");
+ }
+
+ /**
+ * Converts the incoming element into the appropriate Java type.
+ * The method will fail if :
+ *
+ * <br>1) The element has no xsi:type attribute;
+ * <br>2) The xsi:type attribute has no corresponding java type on this serializer mappings.
+ *
+ * @param elementData the xml element containing data to be unmarshalled.l
+ * @return the java object as result of xml element unmarshalling.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Object fromXML(Element elementData) throws SoapFault
+ {
+ Attr typeAttribute = elementData.getAttributeNodeNS(
+ XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI,
+ Names.TYPE);
+
+ if (typeAttribute == null)
+ {
+ throw new SoapFault(
+ "No type attribute was found for the current element. " +
+ "If you are using this serializer, in order to unmarshal the" +
+ " opportune type the xsi:type must be specified.");
+ }
+
+ Class<?> clazz = xml2Java.get(typeAttribute.getValue());
+
+ if (clazz == null)
+ {
+ throw new SoapFault(
+ String.format(
+ "No corresponding class was found on this serializer mappings for xsi:type %s.",
+ typeAttribute));
+ }
+
+ if (clazz == byte[].class) {
+ return new ByteArraySerializer().fromXML(elementData);
+ }
+
+ return SerializerRegistry.getInstance().getSerializer(clazz).fromXML(elementData);
+ }
+
+ /**
+ * As this serializer is supposed to deal with generic object types, this method returns Object.class.
+ *
+ * @return Object.class
+ */
+ public Class<?> getSerializableType()
+ {
+ return Object.class;
+ }
+
+ /**
+ * Converts the given object (with the given qname) in XML format.
+ * This method fails if there's no corresponding xml type for the given runtime type of the input object.
+ *
+ * @param obj the object to be marshalled.
+ * @param qname the qualified name that will be used in encoding.
+ */
+ public Element toXML(Object obj, QName qname) throws SoapFault
+ {
+ Class<?> clazz = obj.getClass();
+
+ Element result = null;
+
+ if (clazz == byte[].class) {
+ result = new ByteArraySerializer().toXML(obj,qname);
+ }
+ else {
+ result = SerializerRegistry.getInstance().getSerializer(clazz).toXML(obj,qname);
+ }
+ result.setAttribute(Names.XSI_TYPE, java2Xml.get(clazz));
+ return result;
+ }
+
+ /**
+ * Returns the xml type associated with the given class.
+ *
+ * @param clazz the class.
+ * @return the xml type associated with the given class.
+ */
+ public String getXmlType(Class<?> clazz)
+ {
+ return java2Xml.get(clazz);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java
new file mode 100644
index 0000000000..408a8de6cf
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm.muse.serializer;
+
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.serializer.Serializer;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.w3c.dom.Element;
+
+/**
+ * Implementation of Muse Serializer for UUID type.
+ *
+ * @author Andrea Gazzarini
+ */
+public class UUIDSerializer implements Serializer
+{
+ /**
+ * Return a UUID representation of the given xml element.
+ *
+ * @param xml the element to unmarshal.
+ * @throws SoapFault when the unmarshalling fails.
+ */
+ public Object fromXML(Element elementData) throws SoapFault
+ {
+ return UUID.fromString(elementData.getTextContent());
+ }
+
+ /**
+ * Returns the java type associated to this class.
+ *
+ * @return the java type associated to this class.
+ */
+ public Class<?> getSerializableType()
+ {
+ return UUID.class;
+ }
+
+ /**
+ * Return an xml representation of the given UUID with the given name.
+ *
+ * @param object the UUID to marshal.
+ * @param qname the qualified (xml) name of the object to use in xml representation.
+ * @return the xml representation of the UUID.
+ * @throws SoapFault when the marshalling fails.
+ */
+ public Element toXML(Object obj, QName qname) throws SoapFault
+ {
+ return XmlUtils.createElement(qname, String.valueOf(obj));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java
new file mode 100644
index 0000000000..9284a62461
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java
@@ -0,0 +1,149 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.notifications;
+
+import org.apache.muse.util.xml.XmlSerializable;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Object representation of a QMan entity lifecycle event notification.
+ * Note that with entity we mean both object(s) and event(s).
+ *
+ * At the moment there are only two types of lifecycle events : CREATE and REMOVE.
+ * The first one if fired when a new instance (event or object) is created, while the second
+ * one is fired when an object instance (events are transient objects so they are not destroyed)
+ * is removed.
+ *
+ * Developer Note : The marshal & unmarshal ops could be handled using JAXB but
+ * we are not sure about the running environment (JAXB libs were included only
+ * starting from 1.6)
+ *
+ * This is the event XML representation :
+ *
+ * <LifecycleEvent Type="created" timemillis="">
+ <Resource>
+ <ResourceId>16038bd5-b62b-4e86-9833-7560ed57b474</id>
+ <Package>org.qpid.apache.broker</package>
+ <Name>session</name>
+ </Resource>
+ </lifecycle-event>
+
+ * @author Andrea Gazzarini
+ */
+public class LifeCycleEvent implements XmlSerializable
+{
+ private final String _resourceId;
+ private final String _packageName;
+ private final String _name;
+
+ private final LifeCycleEventType _type;
+
+ /**
+ * Builds a new event with the given data.
+ *
+ * @param resourceId resource identifier.
+ * @param packageName resource package name.
+ * @param name resource name.
+ * @param type event type.
+ */
+ private LifeCycleEvent(String resourceId, String packageName, String name, LifeCycleEventType type)
+ {
+ this._resourceId = resourceId;
+ this._packageName = packageName;
+ this._name = name;
+ this._type = type;
+ }
+
+ /**
+ * Factory method for a new "CREATE" event.
+ * Builds a new "CREATE" event with the given data.
+ *
+ * @param resourceId resource identifier.
+ * @param packageName resource package name.
+ * @param name resource name.
+ */
+ public static LifeCycleEvent newCreateEvent(String resourceId, String packageName, String name)
+ {
+ return new LifeCycleEvent(resourceId, packageName, name, LifeCycleEventType.CREATED);
+ }
+
+ /**
+ * Factory method for a new "REMOVE" event.
+ * Builds a new "REMOVE" event with the given data.
+ *
+ * @param resourceId resource identifier.
+ * @param packageName resource package name.
+ * @param name resource name.
+ */
+ public static LifeCycleEvent newRemoveEvent(String resourceId, String packageName, String name)
+ {
+ return new LifeCycleEvent(resourceId, packageName, name, LifeCycleEventType.REMOVED);
+ }
+
+ /**
+ * Returns an XML representation of this event.
+ *
+ * @return an XML representation of this event.
+ */
+ public Element toXML()
+ {
+ return toXML(XmlUtils.EMPTY_DOC);
+ }
+
+ /**
+ * Returns an XML representation of this event using the given
+ * input document as owner.
+ *
+ * @return an XML representation of this event.
+ */
+ public Element toXML(Document factory)
+ {
+ Element lifeCycleEvent = XmlUtils.createElement(factory, Names.LIFECYCLE_EVENT_QNAME);
+
+ lifeCycleEvent.setAttribute(
+ "Type",
+ _type.toString());
+
+ lifeCycleEvent.setAttribute(
+ Names.TIMEMILLIS_ATTRIBUTE_NAME,
+ String.valueOf(System.currentTimeMillis()));
+
+ Element resource = XmlUtils.createElement(factory, Names.RESOURCE_QNAME);
+ lifeCycleEvent.appendChild(resource);
+
+ Element id = XmlUtils.createElement(factory, Names.RES_ID_QNAME);
+ id.setTextContent(_resourceId);
+ resource.appendChild(id);
+
+ Element packageName = XmlUtils.createElement(factory, Names.PACKAGE_NAME_QNAME);
+ packageName.setTextContent(_packageName);
+ resource.appendChild(packageName);
+
+ Element name = XmlUtils.createElement(factory, Names.ENTITY_NAME_QNAME);
+ name.setTextContent(_name);
+ resource.appendChild(name);
+
+ return lifeCycleEvent;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java
new file mode 100644
index 0000000000..9ce7bfc743
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.notifications;
+
+/**
+ * Event type enumeration.
+ * Event type are used as part of event WS-Notifications in order to inform
+ * the interested listeners about the lifecycle of a QMan managed entity (object or event instance).
+ *
+ * @author Andrea Gazzarini
+ */
+public enum LifeCycleEventType
+{
+ CREATED,
+ REMOVED;
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java b/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java
new file mode 100644
index 0000000000..398a69817b
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 org.apache.qpid.qman.debug;
+
+import javax.management.ObjectName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.qpid.transport.util.Logger;
+import org.w3c.dom.Node;
+
+/**
+ * Utility class used for debbugging WSDL documents
+ *
+ * @author Andrea Gazzarini
+ */
+public class WsdlDebugger {
+ public final static Logger LOGGER = Logger.get(WsdlDebugger.class);
+
+ /**
+ * Prints out to log the given node.
+ *
+ * @param node the xml node to be printed out.
+ */
+ public static void debug(ObjectName resourceId, Node node)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(resourceId+" : "+XmlUtils.toString(node, false,true));
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java b/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java
new file mode 100644
index 0000000000..600bb51858
--- /dev/null
+++ b/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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 org.apache.qpid.qman.debug;
+
+import javax.management.ObjectName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.qpid.transport.util.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Utility class used for debbugging XML messages
+ *
+ * @author Andrea Gazzarini
+ */
+public class XmlDebugger {
+ public final static Logger LOGGER = Logger.get(XmlDebugger.class);
+
+ /**
+ * Prints out to log the given node.
+ *
+ * @param node the xml node to be printed out.
+ */
+ public static void debug(Node node)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(XmlUtils.toString(node, false,true));
+ }
+ }
+
+ /**
+ * Prints out to log the given node.
+ *
+ * @param node the xml node to be printed out.
+ */
+ public static void debug(ObjectName resourceId, Node node)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(resourceId+" : "+XmlUtils.toString(node, false,true));
+ }
+ }
+
+
+ /**
+ * Prints out to log the given element array.
+ *
+ * @param elements the element array to be printed out.
+ */
+ public static void debug(Element [] elements)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ StringBuilder builder = new StringBuilder();
+ for (Element element : elements) {
+ builder.append(XmlUtils.toString(element,false,true));
+ builder.append(System.getProperty("line.separator"));
+ }
+ LOGGER.debug(builder.toString());
+ }
+ }
+
+ /**
+ * Prints out to log the given node.
+ *
+ * @param node the xml node to be printed out.
+ */
+ public static void debug(String node)
+ {
+ LOGGER.debug(node);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml b/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml
new file mode 100644
index 0000000000..062791fa3f
--- /dev/null
+++ b/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing"/>
diff --git a/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml b/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml
new file mode 100644
index 0000000000..062791fa3f
--- /dev/null
+++ b/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<wsa:ReferenceParameters xmlns:wsa="http://www.w3.org/2005/08/addressing"/>
diff --git a/java/management/client/src/main/java/wsdl/QManAdapter.rmd b/java/management/client/src/main/java/wsdl/QManAdapter.rmd
new file mode 100644
index 0000000000..31e921a06b
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/QManAdapter.rmd
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<Definitions xmlns="http://docs.oasis-open.org/wsrf/rmd-1">
+ <MetadataDescriptor
+ xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wst="http://docs.oasis-open.org/wsn/t-1"
+ xmlns:muws1="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:muws2="http://docs.oasis-open.org/wsdm/muws2-2.xsd"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ name="WsDmAdapterMetadata"
+ interface="qman:QManAdapterPortType"
+ wsdlLocation="http://amqp.apache.org/qpid/management/qman QManAdapter.wsdl">
+ <Property name="wsrf-sg:MembershipContentRule" modifiability="read-only" mutability="mutable">
+ <StaticValues>
+ <wsrf-sg:MembershipContentRule MemberInterface="qman:QManWsResourcePortType"/>
+ </StaticValues>
+ </Property>
+ <Property name="wsrf-sg:Entry" modifiability="read-only" mutability="mutable" />
+ <Property name="wsrf-rp:QueryExpressionDialect" modifiability="read-only" mutability="constant" />
+ <Property name="wsnt:FixedTopicSet" modifiability="read-only" mutability="constant" />
+ <Property name="wst:TopicSet" modifiability="read-only" mutability="mutable" />
+ <Property name="wsnt:TopicExpression" modifiability="read-only" mutability="mutable" />
+ <Property name="wsnt:TopicExpressionDialect" modifiability="read-only" mutability="mutable" />
+ </MetadataDescriptor>
+</Definitions>
diff --git a/java/management/client/src/main/java/wsdl/QManAdapter.wsdl b/java/management/client/src/main/java/wsdl/QManAdapter.wsdl
new file mode 100644
index 0000000000..4b26862604
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/QManAdapter.wsdl
@@ -0,0 +1,694 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ targetNamespace="http://amqp.apache.org/qpid/management/qman"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2"
+ xmlns:wsrf-sgw="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
+ xmlns:wst="http://docs.oasis-open.org/wsn/t-1"
+ xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns:muws1="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:muws2="http://docs.oasis-open.org/wsdm/muws2-2.xsd"
+ name="QManAdapter" >
+ <wsdl:types>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsrf/bf-2">
+ <xsd:include schemaLocation="WS-BaseFaults-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:include schemaLocation="WS-ResourceProperties-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsrf/r-2">
+ <xsd:include schemaLocation="WS-Resource-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://www.w3.org/2005/08/addressing">
+ <xsd:include schemaLocation="WS-Addressing-2005_08.xsd"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <xsd:include schemaLocation="WS-MetadataExchange-2004_09.xsd"/>
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsrf/sg-2">
+ <xsd:include schemaLocation="WS-ServiceGroup-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsdm/muws1-2.xsd">
+ <xsd:include schemaLocation="WSDM-MUWS-Part1-1_1.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsdm/muws2-2.xsd">
+ <xsd:include schemaLocation="WSDM-MUWS-Part2-1_1.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsn/b-2">
+ <xsd:include schemaLocation="WS-BaseNotification-1_3.xsd" />
+ </xsd:schema>
+ <xsd:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wsn/t-1">
+ <xsd:include schemaLocation="WS-Topics-1_3.xsd" />
+ </xsd:schema>
+ <xsd:schema targetNamespace="http://amqp.apache.org/qpid/management/qman">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2" schemaLocation="WS-BaseFaults-1_2.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/sg-2" schemaLocation="WS-ServiceGroup-1_2.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2" schemaLocation="WS-ResourceProperties-1_2.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsn/b-2" schemaLocation="WS-BaseNotification-1_3.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsn/t-1" schemaLocation="WS-Topics-1_3.xsd"/>
+ <xsd:element name="WsDmAdapterResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-sg:Entry"/>
+ <xsd:element ref="wsrf-sg:MembershipContentRule"/>
+ <xsd:element ref="wsrf-rp:QueryExpressionDialect" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="wsnt:FixedTopicSet" />
+ <xsd:element ref="wst:TopicSet" minOccurs="0" />
+ <xsd:element ref="wsnt:TopicExpression" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="wsnt:TopicExpressionDialect" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="OperationInvocationFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="EntityInstanceNotFoundFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MalformedEntityNameFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NoSuchAttributeFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Connect">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="host" type="xsd:string" minOccurs="1" nillable="false"/>
+ <xsd:element name="port" type="xsd:integer" minOccurs="1" nillable="false"/>
+ <xsd:element name="username" type="xsd:string" minOccurs="1" nillable="false"/>
+ <xsd:element name="password" type="xsd:string" minOccurs="1" nillable="false"/>
+ <xsd:element name="virtualHost" type="xsd:string" minOccurs="1" nillable="false"/>
+ <xsd:element name="initialPoolCapacity" type="xsd:integer" minOccurs="1" nillable="false"/>
+ <xsd:element name="maxPoolCapacity" type="xsd:integer" minOccurs="1" nillable="false"/>
+ <xsd:element name="maxWaitTimeout" type="xsd:long" minOccurs="1" nillable="false"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ConnectResponse"/>
+ </xsd:schema>
+ </wsdl:types>
+
+ <wsdl:message name="SubscribeRequest">
+ <wsdl:part name="SubscribeRequest" element="wsnt:Subscribe" />
+ </wsdl:message>
+
+ <wsdl:message name="SubscribeResponse">
+ <wsdl:part name="SubscribeResponse"
+ element="wsnt:SubscribeResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="SubscribeCreationFailedFault">
+ <wsdl:part name="SubscribeCreationFailedFault"
+ element="wsnt:SubscribeCreationFailedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="TopicExpressionDialectUnknownFault">
+ <wsdl:part name="TopicExpressionDialectUnknownFault"
+ element="wsnt:TopicExpressionDialectUnknownFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidFilterFault">
+ <wsdl:part name="InvalidFilterFault"
+ element="wsnt:InvalidFilterFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidProducerPropertiesExpressionFault">
+ <wsdl:part name="InvalidProducerPropertiesExpressionFault"
+ element="wsnt:InvalidProducerPropertiesExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidMessageContentExpressionFault">
+ <wsdl:part name="InvalidMessageContentExpressionFault"
+ element="wsnt:InvalidMessageContentExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnrecognizedPolicyRequestFault">
+ <wsdl:part name="UnrecognizedPolicyRequestFault"
+ element="wsnt:UnrecognizedPolicyRequestFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnsupportedPolicyRequestFault">
+ <wsdl:part name="UnsupportedPolicyRequestFault"
+ element="wsnt:UnsupportedPolicyRequestFault" />
+ </wsdl:message>
+
+ <wsdl:message name="NotifyMessageNotSupportedFault">
+ <wsdl:part name="NotifyMessageNotSupportedFault"
+ element="wsnt:NotifyMessageNotSupportedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnacceptableInitialTerminationTimeFault">
+ <wsdl:part name="UnacceptableInitialTerminationTimeFault"
+ element="wsnt:UnacceptableInitialTerminationTimeFault" />
+ </wsdl:message>
+
+ <!-- ========== NotificationProducer::GetCurrentMessage ===========
+ GetCurrentMessage(topicExpression)
+ returns: a NotificationMessage (xsd:any)
+ -->
+ <wsdl:message name="GetCurrentMessageRequest">
+ <wsdl:part name="GetCurrentMessageRequest"
+ element="wsnt:GetCurrentMessage" />
+ </wsdl:message>
+
+ <wsdl:message name="GetCurrentMessageResponse">
+ <wsdl:part name="GetCurrentMessageResponse"
+ element="wsnt:GetCurrentMessageResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidTopicExpressionFault">
+ <wsdl:part name="InvalidTopicExpressionFault"
+ element="wsnt:InvalidTopicExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="TopicNotSupportedFault">
+ <wsdl:part name="TopicNotSupportedFault"
+ element="wsnt:TopicNotSupportedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="MultipleTopicsSpecifiedFault">
+ <wsdl:part name="MultipleTopicsSpecifiedFault"
+ element="wsnt:MultipleTopicsSpecifiedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="NoCurrentMessageOnTopicFault">
+ <wsdl:part name="NoCurrentMessageOnTopicFault"
+ element="wsnt:NoCurrentMessageOnTopicFault" />
+ </wsdl:message>
+
+
+
+ <wsdl:message name="OperationInvocationFaultMessage">
+ <wsdl:part name="OperationInvocationFault" element="qman:OperationInvocationFault" />
+ </wsdl:message>
+ <wsdl:message name="EntityInstanceNotFoundFaultMessage">
+ <wsdl:part name="EntityInstanceNotFound" element="qman:EntityInstanceNotFoundFault" />
+ </wsdl:message>
+ <wsdl:message name="MalformedEntityNameFaultMessage">
+ <wsdl:part name="MalformedEntityName" element="qman:MalformedEntityNameFault" />
+ </wsdl:message>
+ <wsdl:message name="NoSuchAttributeFaultMessage">
+ <wsdl:part name="NoSuchAttributeFault" element="qman:NoSuchAttributeFault" />
+ </wsdl:message>
+ <wsdl:message name="ConnectRequestMessage">
+ <wsdl:part name="ConnectRequest" element="qman:Connect" />
+ </wsdl:message>
+ <wsdl:message name="ConnectResponseMessage">
+ <wsdl:part name="ConnectResponse" element="qman:ConnectResponse" />
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part name="InvalidResourcePropertyQNameFault" element="wsrf-rp:InvalidResourcePropertyQNameFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part name="ResourceUnknownFault" element="wsrf-r:ResourceUnknownFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part name="ResourceUnavailableFault" element="wsrf-r:ResourceUnavailableFault" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part name="GetResourcePropertyDocumentRequest" element="wsrf-rp:GetResourcePropertyDocument"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part name="GetResourcePropertyDocumentResponse" element="wsrf-rp:GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part name="GetMultipleResourcePropertiesRequest" element="wsrf-rp:GetMultipleResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part name="GetMultipleResourcePropertiesResponse" element="wsrf-rp:GetMultipleResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part name="GetResourcePropertyRequest" element="wsrf-rp:GetResourceProperty" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part name="GetResourcePropertyResponse" element="wsrf-rp:GetResourcePropertyResponse" />
+ </wsdl:message>
+ <wsdl:message name="GetMetadataRequestMessage">
+ <wsdl:part name="GetMetadataMsg" element="wsx:GetMetadata" />
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMessage">
+ <wsdl:part name="GetMetadataResponseMsg" element="wsx:Metadata" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part name="QueryResourcePropertiesRequest" element="wsrf-rp:QueryResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part name="QueryResourcePropertiesResponse" element="wsrf-rp:QueryResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <wsdl:part name="UnknownQueryExpressionDialectFault" element="wsrf-rp:UnknownQueryExpressionDialectFault" />
+ </wsdl:message>
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <wsdl:part name="InvalidQueryExpressionFault" element="wsrf-rp:InvalidQueryExpressionFault" />
+ </wsdl:message>
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <wsdl:part name="QueryEvaluationErrorFault" element="wsrf-rp:QueryEvaluationErrorFault" />
+ </wsdl:message>
+ <wsdl:portType
+ name="QManAdapterPortType"
+ wsrf-rp:ResourceProperties="qman:WsDmAdapterResourceProperties"
+ wsrmd:Descriptor="WsDmAdapterMetadata" wsrmd:DescriptorLocation="QManAdapter.rmd">
+
+ <wsdl:operation name="Subscribe">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeRequest"
+ message="qman:SubscribeRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeResponse"
+ message="qman:SubscribeResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="qman:ResourceUnknownFault" />
+ <wsdl:fault name="InvalidFilterFault"
+ message="qman:InvalidFilterFault" />
+ <wsdl:fault name="TopicExpressionDialectUnknownFault"
+ message="qman:TopicExpressionDialectUnknownFault" />
+ <wsdl:fault name="InvalidTopicExpressionFault"
+ message="qman:InvalidTopicExpressionFault" />
+ <wsdl:fault name="TopicNotSupportedFault"
+ message="qman:TopicNotSupportedFault" />
+ <wsdl:fault name="InvalidProducerPropertiesExpressionFault"
+ message="qman:InvalidProducerPropertiesExpressionFault" />
+ <wsdl:fault name="InvalidMessageContentExpressionFault"
+ message="qman:InvalidMessageContentExpressionFault" />
+ <wsdl:fault name="UnacceptableInitialTerminationTimeFault"
+ message="qman:UnacceptableInitialTerminationTimeFault" />
+ <wsdl:fault name="UnrecognizedPolicyRequestFault"
+ message="qman:UnrecognizedPolicyRequestFault" />
+ <wsdl:fault name="UnsupportedPolicyRequestFault"
+ message="qman:UnsupportedPolicyRequestFault" />
+ <wsdl:fault name="NotifyMessageNotSupportedFault"
+ message="qman:NotifyMessageNotSupportedFault" />
+ <wsdl:fault name="SubscribeCreationFailedFault"
+ message="qman:SubscribeCreationFailedFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetCurrentMessage">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/GetCurrentMessageRequest"
+ message="qman:GetCurrentMessageRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/GetCurrentMessageResponse"
+ message="qman:GetCurrentMessageResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="qman:ResourceUnknownFault" />
+ <wsdl:fault name="TopicExpressionDialectUnknownFault"
+ message="qman:TopicExpressionDialectUnknownFault" />
+ <wsdl:fault name="InvalidTopicExpressionFault"
+ message="qman:InvalidTopicExpressionFault" />
+ <wsdl:fault name="TopicNotSupportedFault"
+ message="qman:TopicNotSupportedFault" />
+ <wsdl:fault name="NoCurrentMessageOnTopicFault"
+ message="qman:NoCurrentMessageOnTopicFault" />
+ <wsdl:fault name="MultipleTopicsSpecifiedFault"
+ message="qman:MultipleTopicsSpecifiedFault" />
+ </wsdl:operation>
+
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesRequest"
+ name="QueryResourcePropertiesRequest"
+ message="qman:QueryResourcePropertiesRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesResponse"
+ name="QueryResourcePropertiesResponse"
+ message="qman:QueryResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault" message="qman:UnknownQueryExpressionDialectFault"/>
+ <wsdl:fault name="InvalidQueryExpressionFault" message="qman:InvalidQueryExpressionFault"/>
+ <wsdl:fault name="QueryEvaluationErrorFault" message="qman:QueryEvaluationErrorFault" />
+ </wsdl:operation>
+ <wsdl:operation name="Connect">
+ <wsdl:documentation>
+ Connects QMan with a new broker.
+ </wsdl:documentation>
+ <wsdl:input
+ wsa:Action="http://amqp.apache.org/qpid/management/qman/Connect"
+ name="ConnectRequestInput"
+ message="qman:ConnectRequestMessage" />
+ <wsdl:output
+ wsa:Action="http://amqp.apache.org/qpid/management/qman/ConnectResponse"
+ name="ConnectResponseOutput"
+ message="qman:ConnectResponseMessage" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:documentation>
+ Returns an array containing values for the requested properties.
+ Note that using this method it's possibile to retrieve only the value of the QManService properties.
+ That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used.</wsdl:documentation>
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest"
+ message="qman:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse"
+ message="qman:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="qman:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:documentation>
+ Returns resource's entire WS-RP document, with the most up-to-date values of all properties. Note that using this method it's possibile to retrieve only the value of the QManService properties.
+ That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used.</wsdl:documentation>
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest"
+ message="qman:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse"
+ message="qman:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:documentation>
+ Returns the value of the given property. Note that using this method it's possibile to retrieve only the value of the QManService properties.
+ That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used.
+ </wsdl:documentation>
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest"
+ message="qman:GetResourcePropertyRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse"
+ message="qman:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="qman:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMetadata">
+ <wsdl:documentation>
+ Implementation of the WS-MetadataExchange GetMetadata port type. Note that the only supported metadata type (dialect) is WSDL.
+ </wsdl:documentation>
+ <wsdl:input
+ wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"
+ name="GetMetadataMsg"
+ message="qman:GetMetadataRequestMessage"/>
+ <wsdl:output
+ wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"
+ name="GetMetadataResponseMsg"
+ message="qman:GetMetadataResponseMessage"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="QManAdapterBinding" type="qman:QManAdapterPortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="Subscribe">
+ <wsdl-soap:operation
+ soapAction="http://ws.apache.org/muse/test/wsrf/Subscribe" />
+ <wsdl:input>
+ <wsdl-soap:body use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="ResourceUnknownFault" />
+ </wsdl:fault>
+ <wsdl:fault name="InvalidFilterFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="InvalidFilterFault" />
+ </wsdl:fault>
+ <wsdl:fault name="TopicExpressionDialectUnknownFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="TopicExpressionDialectUnknownFault" />
+ </wsdl:fault>
+ <wsdl:fault name="InvalidTopicExpressionFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="InvalidTopicExpressionFault" />
+ </wsdl:fault>
+ <wsdl:fault name="TopicNotSupportedFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="TopicNotSupportedFault" />
+ </wsdl:fault>
+ <wsdl:fault
+ name="InvalidProducerPropertiesExpressionFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="InvalidProducerPropertiesExpressionFault" />
+ </wsdl:fault>
+ <wsdl:fault name="InvalidMessageContentExpressionFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="InvalidMessageContentExpressionFault" />
+ </wsdl:fault>
+ <wsdl:fault
+ name="UnacceptableInitialTerminationTimeFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="UnacceptableInitialTerminationTimeFault" />
+ </wsdl:fault>
+ <wsdl:fault name="UnrecognizedPolicyRequestFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="UnrecognizedPolicyRequestFault" />
+ </wsdl:fault>
+ <wsdl:fault name="UnsupportedPolicyRequestFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="UnsupportedPolicyRequestFault" />
+ </wsdl:fault>
+ <wsdl:fault name="NotifyMessageNotSupportedFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="NotifyMessageNotSupportedFault" />
+ </wsdl:fault>
+ <wsdl:fault name="SubscribeCreationFailedFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="SubscribeCreationFailedFault" />
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetCurrentMessage">
+ <wsdl-soap:operation
+ soapAction="http://ws.apache.org/muse/test/wsrf/GetCurrentMessage" />
+ <wsdl:input>
+ <wsdl-soap:body use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="ResourceUnknownFault" />
+ </wsdl:fault>
+ <wsdl:fault name="TopicExpressionDialectUnknownFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="TopicExpressionDialectUnknownFault" />
+ </wsdl:fault>
+ <wsdl:fault name="InvalidTopicExpressionFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="InvalidTopicExpressionFault" />
+ </wsdl:fault>
+ <wsdl:fault name="TopicNotSupportedFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="TopicNotSupportedFault" />
+ </wsdl:fault>
+ <wsdl:fault name="NoCurrentMessageOnTopicFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="NoCurrentMessageOnTopicFault" />
+ </wsdl:fault>
+ <wsdl:fault name="MultipleTopicsSpecifiedFault">
+ <wsdl-soap:fault
+ namespace="http://ws.apache.org/muse/test/wsrf" use="encoded"
+ name="MultipleTopicsSpecifiedFault" />
+ </wsdl:fault>
+ </wsdl:operation>
+
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl-soap:operation soapAction="QueryResourceProperties"/>
+ <wsdl:input name="QueryResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output name="QueryResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="UnknownQueryExpressionDialectFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidQueryExpressionFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidQueryExpressionFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="QueryEvaluationErrorFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="QueryEvaluationErrorFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="Connect">
+ <wsdl-soap:operation soapAction="Connect" />
+ <wsdl:input>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata" />
+ <wsdl:input>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="QManAdapterService">
+ <wsdl:port name="QManAdapterPort" binding="qman:QManAdapterBinding">
+ <wsdl-soap:address location="http://romagazzarini:8080/qman/services/adapter"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/QManWsResource.rmd b/java/management/client/src/main/java/wsdl/QManWsResource.rmd
new file mode 100644
index 0000000000..c4944440e0
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/QManWsResource.rmd
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<Definitions xmlns="http://docs.oasis-open.org/wsrf/rmd-1" >
+ <MetadataDescriptor
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wst="http://docs.oasis-open.org/wsn/t-1"
+ xmlns:muws1="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:muws2="http://docs.oasis-open.org/wsdm/muws2-2.xsd"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ name="QManWsResourceMetadata"
+ interface="qman:QManWsResourcePortType"
+ wsdlLocation="http://ws.apache.org/muse/test/wsrf QManWsResource.wsdl" >
+ <Property name="wsrf-rp:QueryExpressionDialect" modifiability="read-only" mutability="constant" />
+ </MetadataDescriptor>
+
+</Definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/QManWsResource.wsdl b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl
new file mode 100644
index 0000000000..16169c9b78
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ targetNamespace="http://amqp.apache.org/qpid/management/qman"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ name="QManWsResource">
+ <wsdl:types>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://www.w3.org/2005/08/addressing">
+ <xsd:include schemaLocation="WS-Addressing-2005_08.xsd"/>
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <xsd:include schemaLocation="WS-MetadataExchange-2004_09.xsd"/>
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rl-2">
+ <xsd:include schemaLocation="WS-ResourceLifetime-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:include schemaLocation="WS-ResourceProperties-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2">
+ <xsd:include schemaLocation="WS-Resource-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rmd-1">
+ <xsd:include schemaLocation="WS-ResourceMetadataDescriptor-CD-01.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://amqp.apache.org/qpid/management/qman">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rl-2" schemaLocation="WS-ResourceLifetime-1_2.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rp-2" schemaLocation="WS-ResourceProperties-1_2.xsd"/>
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2" schemaLocation="WS-BaseFaults-1_2.xsd"/>
+ <xsd:element name="QManWsResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:QueryExpressionDialect" minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="QManFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MethodInvocationFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="EntityInstanceNotFoundFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MalformedEntityNameFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NoSuchAttributeFault">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="uuid">
+ <xsd:sequence>
+ <xsd:element name="uuid" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="map">
+ <xsd:sequence>
+ <xsd:element name="entry" minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="key" type="xsd:string"/>
+ <xsd:element name="value" type="xsd:anyType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="result">
+ <xsd:sequence>
+ <xsd:element name="outputParameters" type="qman:map"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ </xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="GetMetadataMsg">
+ <wsdl:part name="GetMetadataMsg" element="wsx:GetMetadata" />
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMsg">
+ <wsdl:part name="GetMetadataResponseMsg" element="wsx:Metadata" />
+ </wsdl:message>
+ <wsdl:message name="DestroyRequest">
+ <wsdl:part name="DestroyRequest" element="wsrf-rl:Destroy" />
+ </wsdl:message>
+ <wsdl:message name="DestroyResponse">
+ <wsdl:part name="DestroyResponse" element="wsrf-rl:DestroyResponse" />
+ </wsdl:message>
+ <wsdl:message name="ResourceNotDestroyedFault">
+ <wsdl:part name="ResourceNotDestroyedFault" element="wsrf-rl:ResourceNotDestroyedFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part name="ResourceUnknownFault" element="wsrf-r:ResourceUnknownFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part name="ResourceUnavailableFault" element="wsrf-r:ResourceUnavailableFault" />
+ </wsdl:message>
+ <wsdl:message name="UnableToPutResourcePropertyDocumentFault">
+ <wsdl:part name="UnableToPutResourcePropertyDocumentFault" element="wsrf-rp:UnableToPutResourcePropertyDocumentFault" />
+ </wsdl:message>
+ <wsdl:message name="PutResourcePropertyDocumentRequest">
+ <wsdl:part name="PutResourcePropertyDocumentRequest" element="wsrf-rp:PutResourcePropertyDocument"/>
+ </wsdl:message>
+ <wsdl:message name="PutResourcePropertyDocumentResponse">
+ <wsdl:part name="PutResourcePropertyDocumentResponse" element="wsrf-rp:PutResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part name="GetResourcePropertyDocumentRequest" element="wsrf-rp:GetResourcePropertyDocument"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part name="GetResourcePropertyDocumentResponse" element="wsrf-rp:GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part name="GetResourcePropertyRequest" element="wsrf-rp:GetResourceProperty" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part name="GetResourcePropertyResponse" element="wsrf-rp:GetResourcePropertyResponse" />
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part name="InvalidResourcePropertyQNameFault" element="wsrf-rp:InvalidResourcePropertyQNameFault" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part name="GetMultipleResourcePropertiesRequest" element="wsrf-rp:GetMultipleResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part name="GetMultipleResourcePropertiesResponse" element="wsrf-rp:GetMultipleResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part name="QueryResourcePropertiesRequest" element="wsrf-rp:QueryResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part name="QueryResourcePropertiesResponse" element="wsrf-rp:QueryResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <wsdl:part name="UnknownQueryExpressionDialectFault" element="wsrf-rp:UnknownQueryExpressionDialectFault" />
+ </wsdl:message>
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <wsdl:part name="InvalidQueryExpressionFault" element="wsrf-rp:InvalidQueryExpressionFault" />
+ </wsdl:message>
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <wsdl:part name="QueryEvaluationErrorFault" element="wsrf-rp:QueryEvaluationErrorFault" />
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesRequest">
+ <wsdl:part name="SetResourcePropertiesRequest" element="wsrf-rp:SetResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertiesResponse">
+ <wsdl:part name="SetResourcePropertiesResponse" element="wsrf-rp:SetResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="InvalidModificationFault">
+ <wsdl:part name="InvalidModificationFault" element="wsrf-rp:InvalidModificationFault" />
+ </wsdl:message>
+ <wsdl:message name="UnableToModifyResourcePropertyFault">
+ <wsdl:part name="UnableToModifyResourcePropertyFault" element="wsrf-rp:UnableToModifyResourcePropertyFault" />
+ </wsdl:message>
+ <wsdl:message name="SetResourcePropertyRequestFailedFault">
+ <wsdl:part name="SetResourcePropertyRequestFailedFault" element="wsrf-rp:SetResourcePropertyRequestFailedFault" />
+ </wsdl:message>
+ <wsdl:portType
+ name="QManWsResourcePortType"
+ wsrf-rp:ResourceProperties="qman:QManWsResourceProperties"
+ wsrmd:Descriptor="QManWsResourceMetadata"
+ wsrmd:DescriptorLocation="QManWsResource.rmd">
+ <wsdl:operation name="GetMetadata">
+ <wsdl:input
+ wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"
+ name="GetMetadataMsg"
+ message="qman:GetMetadataMsg"/>
+ <wsdl:output
+ wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"
+ name="GetMetadataResponseMsg"
+ message="qman:GetMetadataResponseMsg"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest"
+ message="qman:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse"
+ message="qman:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="PutResourcePropertyDocument">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/PutResourcePropertyDocument/PutResourcePropertyDocumentRequest"
+ name="PutResourcePropertyDocumentRequest"
+ message="qman:PutResourcePropertyDocumentRequest"/>
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/PutResourcePropertyDocument/PutResourcePropertyDocumentResponse"
+ name="PutResourcePropertyDocumentResponse"
+ message="qman:PutResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="UnableToPutResourcePropertyDocumentFault" message="qman:UnableToPutResourcePropertyDocumentFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest"
+ message="qman:GetResourcePropertyRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse"
+ message="qman:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="qman:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest"
+ message="qman:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse"
+ message="qman:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="qman:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesRequest"
+ name="QueryResourcePropertiesRequest"
+ message="qman:QueryResourcePropertiesRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesResponse"
+ name="QueryResourcePropertiesResponse"
+ message="qman:QueryResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault" message="qman:UnknownQueryExpressionDialectFault"/>
+ <wsdl:fault name="InvalidQueryExpressionFault" message="qman:InvalidQueryExpressionFault"/>
+ <wsdl:fault name="QueryEvaluationErrorFault" message="qman:QueryEvaluationErrorFault" />
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl:input
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"
+ name="SetResourcePropertiesRequest"
+ message="qman:SetResourcePropertiesRequest" />
+ <wsdl:output
+ wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse"
+ name="SetResourcePropertiesResponse"
+ message="qman:SetResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="qman:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="qman:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidModificationFault" message="qman:InvalidModificationFault" />
+ <wsdl:fault name="UnableToModifyResourcePropertyFault" message="qman:UnableToModifyResourcePropertyFault" />
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="qman:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="SetResourcePropertyRequestFailedFault" message="qman:SetResourcePropertyRequestFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="QManWsResourceBinding" type="qman:QManWsResourcePortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata" />
+ <wsdl:input>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="PutResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="PutResourcePropertyDocument"/>
+ <wsdl:input name="PutResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input>
+ <wsdl:output name="PutResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnableToPutResourcePropertyDocumentFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="UnableToPutResourcePropertyDocumentFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl-soap:operation soapAction="QueryResourceProperties"/>
+ <wsdl:input name="QueryResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="QueryResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="UnknownQueryExpressionDialectFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidQueryExpressionFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidQueryExpressionFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="QueryEvaluationErrorFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="QueryEvaluationErrorFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl-soap:operation soapAction="http://oasis.org/SetResourceProperties"/>
+ <wsdl:input name="SetResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="SetResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="literal"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidModificationFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidModificationFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnableToModifyResourcePropertyFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="UnableToModifyResourcePropertyFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="SetResourcePropertyRequestFailedFault">
+ <wsdl-soap:fault
+ use="literal"
+ name="SetResourcePropertyRequestFailedFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="QManWsResourceService">
+ <wsdl:port name="QManWsResourcePort" binding="qman:QManWsResourceBinding">
+ <wsdl-soap:address location="http://localhost:8080/qman/services/QManWsResource"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd b/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd
new file mode 100644
index 0000000000..ab38b1b7f2
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd
@@ -0,0 +1,181 @@
+<?xml version="1.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.
+
+-->
+
+
+<!-- Schema defined in the SOAP Version 1.2 Part 1 specification
+ Proposed Recommendation:
+ http://www.w3.org/TR/2003/PR-soap12-part1-20030507/
+ $Id: SOAP-Envelope-1_2.xsd,v 1.1 2006/05/07 19:09:15 danjemiolo Exp $
+
+ Copyright (C)2003 W3C(R) (MIT, ERCIM, Keio), All Rights Reserved.
+ W3C viability, trademark, document use and software licensing rules
+ apply.
+ http://www.w3.org/Consortium/Legal/
+
+ This document is governed by the W3C Software License [1] as
+ described in the FAQ [2].
+
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:tns="http://www.w3.org/2003/05/soap-envelope"
+ targetNamespace="http://www.w3.org/2003/05/soap-envelope"
+ elementFormDefault="qualified">
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="XML-Namespace-1998.xsd"/>
+
+ <!-- Envelope, header and body -->
+ <xs:element name="Envelope" type="tns:Envelope"/>
+ <xs:complexType name="Envelope">
+ <xs:sequence>
+ <xs:element ref="tns:Header" minOccurs="0"/>
+ <xs:element ref="tns:Body" minOccurs="1"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+
+ <xs:element name="Header" type="tns:Header"/>
+ <xs:complexType name="Header">
+ <xs:annotation>
+ <xs:documentation>
+ Elements replacing the wildcard MUST be namespace qualified, but can be in the targetNamespace
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+
+ <xs:element name="Body" type="tns:Body"/>
+ <xs:complexType name="Body">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+
+ <!-- Global Attributes. The following attributes are intended to be
+ usable via qualified attribute names on any complex type referencing
+ them. -->
+ <xs:attribute name="mustUnderstand" type="xs:boolean" default="0"/>
+ <xs:attribute name="relay" type="xs:boolean" default="0"/>
+ <xs:attribute name="role" type="xs:anyURI"/>
+
+ <!-- 'encodingStyle' indicates any canonicalization conventions
+ followed in the contents of the containing element. For example, the
+ value 'http://www.w3.org/2003/05/soap-encoding' indicates the pattern
+ described in the last call working draft of SOAP Version 1.2 Part 2:
+ Adjuncts -->
+
+ <xs:attribute name="encodingStyle" type="xs:anyURI"/>
+
+ <xs:element name="Fault" type="tns:Fault"/>
+ <xs:complexType name="Fault" final="extension">
+ <xs:annotation>
+ <xs:documentation>
+ Fault reporting structure
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="Code" type="tns:faultcode"/>
+ <xs:element name="Reason" type="tns:faultreason"/>
+ <xs:element name="Node" type="xs:anyURI" minOccurs="0"/>
+ <xs:element name="Role" type="xs:anyURI" minOccurs="0"/>
+ <xs:element name="Detail" type="tns:detail" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="faultreason">
+ <xs:sequence>
+ <xs:element name="Text" type="tns:reasontext"
+ minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="reasontext">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="xml:lang" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="faultcode">
+ <xs:sequence>
+ <xs:element name="Value"
+ type="tns:faultcodeEnum"/>
+ <xs:element name="Subcode"
+ type="tns:subcode"
+ minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:simpleType name="faultcodeEnum">
+ <xs:restriction base="xs:QName">
+ <xs:enumeration value="tns:DataEncodingUnknown"/>
+ <xs:enumeration value="tns:MustUnderstand"/>
+ <xs:enumeration value="tns:Receiver"/>
+ <xs:enumeration value="tns:Sender"/>
+ <xs:enumeration value="tns:VersionMismatch"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="subcode">
+ <xs:sequence>
+ <xs:element name="Value"
+ type="xs:QName"/>
+ <xs:element name="Subcode"
+ type="tns:subcode"
+ minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="detail">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+
+ <!-- Global element declaration and complex type definition for header entry returned due to a mustUnderstand fault -->
+ <xs:element name="NotUnderstood" type="tns:NotUnderstoodType"/>
+ <xs:complexType name="NotUnderstoodType">
+ <xs:attribute name="qname" type="xs:QName" use="required"/>
+ </xs:complexType>
+
+ <!-- Global element and associated types for managing version transition as described in Appendix A of the SOAP Version 1.2 Part 1 Last Call Working Draft -->
+ <xs:complexType name="SupportedEnvType">
+ <xs:attribute name="qname" type="xs:QName" use="required"/>
+ </xs:complexType>
+
+ <xs:element name="Upgrade" type="tns:UpgradeType"/>
+ <xs:complexType name="UpgradeType">
+ <xs:sequence>
+ <xs:element name="SupportedEnvelope" type="tns:SupportedEnvType" minOccurs="1" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+</xs:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd b/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd
new file mode 100644
index 0000000000..04b4a688b3
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<xs:schema
+ targetNamespace="http://www.w3.org/2005/08/addressing"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:tns="http://www.w3.org/2005/08/addressing"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <!-- Constructs from the WS-Addressing Core -->
+
+ <xs:element name="EndpointReference"
+ type="tns:EndpointReferenceType" />
+ <xs:complexType name="EndpointReferenceType" mixed="false">
+ <xs:sequence>
+ <xs:element name="Address" type="tns:AttributedURIType" />
+ <xs:element name="ReferenceParameters"
+ type="tns:ReferenceParametersType" minOccurs="0" />
+ <xs:element ref="tns:Metadata" minOccurs="0" />
+ <xs:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax" />
+ </xs:complexType>
+
+ <xs:complexType name="ReferenceParametersType" mixed="false">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax" />
+ </xs:complexType>
+
+ <xs:element name="Metadata" type="tns:MetadataType" />
+ <xs:complexType name="MetadataType" mixed="false">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax" />
+ </xs:complexType>
+
+ <xs:element name="MessageID" type="tns:AttributedURIType" />
+ <xs:element name="RelatesTo" type="tns:RelatesToType" />
+ <xs:complexType name="RelatesToType" mixed="false">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="RelationshipType"
+ type="tns:RelationshipTypeOpenEnum" use="optional"
+ default="http://www.w3.org/2005/08/addressing/reply" />
+ <xs:anyAttribute namespace="##other"
+ processContents="lax" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="RelationshipTypeOpenEnum">
+ <xs:union memberTypes="tns:RelationshipType xs:anyURI" />
+ </xs:simpleType>
+
+ <xs:simpleType name="RelationshipType">
+ <xs:restriction base="xs:anyURI">
+ <xs:enumeration
+ value="http://www.w3.org/2005/08/addressing/reply" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="ReplyTo" type="tns:EndpointReferenceType" />
+ <xs:element name="From" type="tns:EndpointReferenceType" />
+ <xs:element name="FaultTo" type="tns:EndpointReferenceType" />
+ <xs:element name="To" type="tns:AttributedURIType" />
+ <xs:element name="Action" type="tns:AttributedURIType" />
+
+ <xs:complexType name="AttributedURIType" mixed="false">
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:anyAttribute namespace="##other"
+ processContents="lax" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <!-- Constructs from the WS-Addressing SOAP binding -->
+
+ <xs:attribute name="IsReferenceParameter" type="xs:boolean" />
+
+ <xs:simpleType name="FaultCodesOpenEnumType">
+ <xs:union memberTypes="tns:FaultCodesType xs:QName" />
+ </xs:simpleType>
+
+ <xs:simpleType name="FaultCodesType">
+ <xs:restriction base="xs:QName">
+ <xs:enumeration value="tns:InvalidAddressingHeader" />
+ <xs:enumeration value="tns:InvalidAddress" />
+ <xs:enumeration value="tns:InvalidEPR" />
+ <xs:enumeration value="tns:InvalidCardinality" />
+ <xs:enumeration value="tns:MissingAddressInEPR" />
+ <xs:enumeration value="tns:DuplicateMessageID" />
+ <xs:enumeration value="tns:ActionMismatch" />
+ <xs:enumeration value="tns:MessageAddressingHeaderRequired" />
+ <xs:enumeration value="tns:DestinationUnreachable" />
+ <xs:enumeration value="tns:ActionNotSupported" />
+ <xs:enumeration value="tns:EndpointUnavailable" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="RetryAfter" type="tns:AttributedUnsignedLongType" />
+ <xs:complexType name="AttributedUnsignedLongType" mixed="false">
+ <xs:simpleContent>
+ <xs:extension base="xs:unsignedLong">
+ <xs:anyAttribute namespace="##other"
+ processContents="lax" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:element name="ProblemHeaderQName"
+ type="tns:AttributedQNameType" />
+ <xs:complexType name="AttributedQNameType" mixed="false">
+ <xs:simpleContent>
+ <xs:extension base="xs:QName">
+ <xs:anyAttribute namespace="##other"
+ processContents="lax" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:element name="ProblemHeader" type="tns:AttributedAnyType" />
+ <xs:complexType name="AttributedAnyType" mixed="false">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"
+ minOccurs="1" maxOccurs="1" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax" />
+ </xs:complexType>
+
+ <xs:element name="ProblemIRI" type="tns:AttributedURIType" />
+
+ <xs:element name="ProblemAction" type="tns:ProblemActionType" />
+ <xs:complexType name="ProblemActionType" mixed="false">
+ <xs:sequence>
+ <xs:element ref="tns:Action" minOccurs="0" />
+ <xs:element name="SoapAction" minOccurs="0"
+ type="xs:anyURI" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" processContents="lax" />
+ </xs:complexType>
+
+</xs:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd
new file mode 100644
index 0000000000..665797e486
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+-->
+
+<xsd:schema
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-bf=
+ "http://docs.oasis-open.org/wsrf/bf-2"
+ elementFormDefault="qualified" attributeFormDefault="unqualified"
+ targetNamespace=
+ "http://docs.oasis-open.org/wsrf/bf-2">
+ <xsd:import
+ namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd"/>
+
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="XML-Namespace-1998.xsd">
+ <xsd:annotation>
+ <xsd:documentation>
+ Get access to the xml: attribute groups for xml:lang as declared on 'schema'
+ and 'documentation' below
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:import>
+<!-- ====================== BaseFault Types ======================= -->
+
+ <xsd:element name="BaseFault" type="wsrf-bf:BaseFaultType"/>
+
+ <xsd:complexType name="BaseFaultType">
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="Timestamp" type="xsd:dateTime"
+ minOccurs="1" maxOccurs="1"/>
+ <xsd:element name="Originator" type="wsa:EndpointReferenceType"
+ minOccurs="0" maxOccurs="1"/>
+ <xsd:element name="ErrorCode"
+ minOccurs="0" maxOccurs="1">
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:extension base="xsd:anyType">
+ <xsd:attribute name="dialect" type="xsd:anyURI"
+ use="required"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="Description"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="FaultCause" minOccurs="0" maxOccurs="1">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+</xsd:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl
new file mode 100644
index 0000000000..d53bf60f3a
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2004-2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+<wsdl:definitions name="WS-BaseNotification"
+ targetNamespace="http://docs.oasis-open.org/wsn/bw-2"
+ xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2"
+ xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
+ xmlns:wsrf-rlw="http://docs.oasis-open.org/wsrf/rlw-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-rpw="http://docs.oasis-open.org/wsrf/rpw-2"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+
+<!-- ========================== Imports =========================== -->
+ <wsdl:import
+ namespace="http://docs.oasis-open.org/wsrf/rw-2"
+ location="WS-Resource-1_2.wsdl"/>
+
+ <wsdl:import
+ namespace="http://docs.oasis-open.org/wsrf/rlw-2"
+ location="WS-ResourceLifetime-1_2.wsdl"/>
+
+ <wsdl:import
+ namespace="http://docs.oasis-open.org/wsrf/rpw-2"
+ location="WS-ResourceProperties-1_2.wsdl"/>
+
+<!-- ===================== Types Definitions ====================== -->
+ <wsdl:types>
+ <xsd:schema>
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsn/b-2"
+ schemaLocation="WS-BaseNotification-1_3.xsd"/>
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/rp-2"
+ schemaLocation="WS-ResourceProperties-1_2.xsd"/>
+ </xsd:schema>
+ </wsdl:types>
+
+<!-- ================ NotificationConsumer::Notify ================
+ Notify(
+ NotificationMessage
+ (SubscriptionReference, TopicExpression, ProducerReference,
+ Message)*
+ returns: n/a (one way)
+-->
+ <wsdl:message name="Notify">
+ <wsdl:part name="Notify" element="wsnt:Notify"/>
+ </wsdl:message>
+
+<!-- ============== NotificationProducer::Subscribe ===============
+ Subscribe(
+ (ConsumerEndpointReference, [Filter], [SubscriptionPolicy],
+ [InitialTerminationTime])
+ returns: WS-Resource qualified EPR to a Subscription
+-->
+ <wsdl:message name="SubscribeRequest" >
+ <wsdl:part name="SubscribeRequest"
+ element="wsnt:Subscribe"/>
+ </wsdl:message>
+
+ <wsdl:message name="SubscribeResponse">
+ <wsdl:part name="SubscribeResponse"
+ element="wsnt:SubscribeResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="SubscribeCreationFailedFault">
+ <wsdl:part name="SubscribeCreationFailedFault"
+ element="wsnt:SubscribeCreationFailedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="TopicExpressionDialectUnknownFault">
+ <wsdl:part name="TopicExpressionDialectUnknownFault"
+ element="wsnt:TopicExpressionDialectUnknownFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidFilterFault">
+ <wsdl:part name="InvalidFilterFault"
+ element="wsnt:InvalidFilterFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidProducerPropertiesExpressionFault">
+ <wsdl:part name="InvalidProducerPropertiesExpressionFault"
+ element="wsnt:InvalidProducerPropertiesExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidMessageContentExpressionFault">
+ <wsdl:part name="InvalidMessageContentExpressionFault"
+ element="wsnt:InvalidMessageContentExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnrecognizedPolicyRequestFault">
+ <wsdl:part name="UnrecognizedPolicyRequestFault"
+ element="wsnt:UnrecognizedPolicyRequestFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnsupportedPolicyRequestFault">
+ <wsdl:part name="UnsupportedPolicyRequestFault"
+ element="wsnt:UnsupportedPolicyRequestFault" />
+ </wsdl:message>
+
+ <wsdl:message name="NotifyMessageNotSupportedFault">
+ <wsdl:part name="NotifyMessageNotSupportedFault"
+ element="wsnt:NotifyMessageNotSupportedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnacceptableInitialTerminationTimeFault">
+ <wsdl:part name="UnacceptableInitialTerminationTimeFault"
+ element="wsnt:UnacceptableInitialTerminationTimeFault"/>
+ </wsdl:message>
+
+<!-- ========== NotificationProducer::GetCurrentMessage ===========
+ GetCurrentMessage(topicExpression)
+ returns: a NotificationMessage (xsd:any)
+-->
+ <wsdl:message name="GetCurrentMessageRequest">
+ <wsdl:part name="GetCurrentMessageRequest"
+ element="wsnt:GetCurrentMessage"/>
+ </wsdl:message>
+
+ <wsdl:message name="GetCurrentMessageResponse">
+ <wsdl:part name="GetCurrentMessageResponse"
+ element="wsnt:GetCurrentMessageResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="InvalidTopicExpressionFault">
+ <wsdl:part name="InvalidTopicExpressionFault"
+ element="wsnt:InvalidTopicExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="TopicNotSupportedFault">
+ <wsdl:part name="TopicNotSupportedFault"
+ element="wsnt:TopicNotSupportedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="MultipleTopicsSpecifiedFault">
+ <wsdl:part name="MultipleTopicsSpecifiedFault"
+ element="wsnt:MultipleTopicsSpecifiedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="NoCurrentMessageOnTopicFault">
+ <wsdl:part name="NoCurrentMessageOnTopicFault"
+ element="wsnt:NoCurrentMessageOnTopicFault" />
+ </wsdl:message>
+
+<!-- ========== PullPoint::GetMessages ===========
+ GetMessages(MaximumNumber)
+ returns: NotificationMessage list
+-->
+ <wsdl:message name="GetMessagesRequest">
+ <wsdl:part name="GetMessagesRequest"
+ element="wsnt:GetMessages"/>
+ </wsdl:message>
+
+ <wsdl:message name="GetMessagesResponse">
+ <wsdl:part name="GetMessagesResponse"
+ element="wsnt:GetMessagesResponse"/>
+ </wsdl:message>
+
+<!-- ========== PullPoint::DestroyPullPoint ===========
+ DestroyPullPoint()
+ returns: void
+-->
+ <wsdl:message name="DestroyPullPointRequest">
+ <wsdl:part name="DestroyPullPointRequest"
+ element="wsnt:DestroyPullPoint"/>
+ </wsdl:message>
+
+ <wsdl:message name="DestroyPullPointResponse">
+ <wsdl:part name="DestroyPullPointResponse"
+ element="wsnt:DestroyPullPointResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnableToDestroyPullPointFault">
+ <wsdl:part name="UnableToDestroyPullPointFault"
+ element="wsnt:UnableToDestroyPullPointFault"/>
+ </wsdl:message>
+
+<!-- ========== PullPoint::CreatePullPoint ===========
+ CreatePullPoint()
+ returns: PullPoint (wsa:EndpointReference)
+-->
+ <wsdl:message name="CreatePullPointRequest">
+ <wsdl:part name="CreatePullPointRequest"
+ element="wsnt:CreatePullPoint"/>
+ </wsdl:message>
+
+ <wsdl:message name="CreatePullPointResponse">
+ <wsdl:part name="CreatePullPointResponse"
+ element="wsnt:CreatePullPointResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnableToCreatePullPointFault">
+ <wsdl:part name="UnableToCreatePullPointFault"
+ element="wsnt:UnableToCreatePullPointFault"/>
+ </wsdl:message>
+
+<!-- ================ SubscriptionManager::Renew ==================
+ Renew( Duration | AbsoluteTime)
+ returns: (New Termination Time [CurrentTime])
+-->
+ <wsdl:message name="RenewRequest">
+ <wsdl:part name="RenewRequest"
+ element="wsnt:Renew"/>
+ </wsdl:message>
+
+ <wsdl:message name="RenewResponse">
+ <wsdl:part name="RenewResponse"
+ element="wsnt:RenewResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnacceptableTerminationTimeFault">
+ <wsdl:part name="UnacceptableTerminationTimeFault"
+ element="wsnt:UnacceptableTerminationTimeFault" />
+ </wsdl:message>
+
+<!-- ============== SubscriptionManager::Unsubscribe ===============
+ Unsubscribe()
+ returns: empty
+-->
+ <wsdl:message name="UnsubscribeRequest">
+ <wsdl:part name="UnsubscribeRequest"
+ element="wsnt:Unsubscribe"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnsubscribeResponse">
+ <wsdl:part name="UnsubscribeResponse"
+ element="wsnt:UnsubscribeResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnableToDestroySubscriptionFault">
+ <wsdl:part name="UnableToDestroySubscriptionFault"
+ element="wsnt:UnableToDestroySubscriptionFault" />
+ </wsdl:message>
+
+<!-- ========== SubscriptionManager::PauseSubscription ============
+ PauseSubscription()
+ returns: empty
+-->
+ <wsdl:message name="PauseSubscriptionRequest">
+ <wsdl:part name="PauseSubscriptionRequest"
+ element="wsnt:PauseSubscription"/>
+ </wsdl:message>
+
+ <wsdl:message name="PauseSubscriptionResponse">
+ <wsdl:part name="PauseSubscriptionResponse"
+ element="wsnt:PauseSubscriptionResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="PauseFailedFault">
+ <wsdl:part name="PauseFailedFault"
+ element="wsnt:PauseFailedFault" />
+ </wsdl:message>
+
+<!-- ========= SubscriptionManager::ResumeSubscription ============
+ ResumeSubscription()
+ returns: empty
+-->
+ <wsdl:message name="ResumeSubscriptionRequest">
+ <wsdl:part name="ResumeSubscriptionRequest"
+ element="wsnt:ResumeSubscription"/>
+ </wsdl:message>
+
+ <wsdl:message name="ResumeSubscriptionResponse">
+ <wsdl:part name="ResumeSubscriptionResponse"
+ element="wsnt:ResumeSubscriptionResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="ResumeFailedFault">
+ <wsdl:part name="ResumeFailedFault"
+ element="wsnt:ResumeFailedFault" />
+ </wsdl:message>
+
+<!-- =================== PortType Definitions ===================== -->
+<!-- ========= NotificationConsumer PortType Definition =========== -->
+ <wsdl:portType name="NotificationConsumer">
+ <wsdl:operation name="Notify">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer/NotifyRequest" message="wsntw:Notify" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+<!-- ========= NotificationProducer PortType Definition =========== -->
+ <wsdl:portType name="NotificationProducer">
+ <wsdl:operation name="Subscribe">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeRequest"
+ message="wsntw:SubscribeRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeResponse"
+ message="wsntw:SubscribeResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="InvalidFilterFault"
+ message="wsntw:InvalidFilterFault"/>
+ <wsdl:fault name="TopicExpressionDialectUnknownFault"
+ message="wsntw:TopicExpressionDialectUnknownFault"/>
+ <wsdl:fault name="InvalidTopicExpressionFault"
+ message="wsntw:InvalidTopicExpressionFault" />
+ <wsdl:fault name="TopicNotSupportedFault"
+ message="wsntw:TopicNotSupportedFault" />
+ <wsdl:fault name="InvalidProducerPropertiesExpressionFault"
+ message="wsntw:InvalidProducerPropertiesExpressionFault"/>
+ <wsdl:fault name="InvalidMessageContentExpressionFault"
+ message="wsntw:InvalidMessageContentExpressionFault"/>
+ <wsdl:fault name="UnacceptableInitialTerminationTimeFault"
+ message="wsntw:UnacceptableInitialTerminationTimeFault"/>
+ <wsdl:fault name="UnrecognizedPolicyRequestFault"
+ message="wsntw:UnrecognizedPolicyRequestFault"/>
+ <wsdl:fault name="UnsupportedPolicyRequestFault"
+ message="wsntw:UnsupportedPolicyRequestFault"/>
+ <wsdl:fault name="NotifyMessageNotSupportedFault"
+ message="wsntw:NotifyMessageNotSupportedFault"/>
+ <wsdl:fault name="SubscribeCreationFailedFault"
+ message="wsntw:SubscribeCreationFailedFault"/>
+ </wsdl:operation>
+
+ <wsdl:operation name="GetCurrentMessage">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/GetCurrentMessageRequest"
+ message="wsntw:GetCurrentMessageRequest"/>
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/GetCurrentMessageResponse"
+ message="wsntw:GetCurrentMessageResponse"/>
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="TopicExpressionDialectUnknownFault"
+ message="wsntw:TopicExpressionDialectUnknownFault"/>
+ <wsdl:fault name="InvalidTopicExpressionFault"
+ message="wsntw:InvalidTopicExpressionFault" />
+ <wsdl:fault name="TopicNotSupportedFault"
+ message="wsntw:TopicNotSupportedFault" />
+ <wsdl:fault name="NoCurrentMessageOnTopicFault"
+ message="wsntw:NoCurrentMessageOnTopicFault" />
+ <wsdl:fault name="MultipleTopicsSpecifiedFault"
+ message="wsntw:MultipleTopicsSpecifiedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+<!-- ========== PullPoint PortType Definition ===================== -->
+ <wsdl:portType name="PullPoint">
+ <wsdl:operation name="GetMessages">
+ <wsdl:input name="GetMessagesRequest"
+ message="wsntw:GetMessagesRequest" />
+ <wsdl:output name="GetMessagesResponse"
+ message="wsntw:GetMessagesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault" />
+ </wsdl:operation>
+
+ <wsdl:operation name="Notify">
+ <wsdl:input message="wsntw:Notify"/>
+ </wsdl:operation>
+ </wsdl:portType>
+
+<!-- ========== CreatePullPoint PortType Definition =============== -->
+ <wsdl:portType name="CreatePullPoint">
+ <wsdl:operation name="CreatePullPoint">
+ <wsdl:input name="CreatePullPointRequest"
+ message="wsntw:CreatePullPointRequest" />
+ <wsdl:output name="CreatePullPointResponse"
+ message="wsntw:CreatePullPointResponse" />
+ <wsdl:fault name="UnableToCreatePullPointFault"
+ message="wsntw:UnableToCreatePullPointFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+<!-- ========== SubscriptionManager PortType Definition =========== -->
+ <wsdl:portType name="SubscriptionManager"
+ wsrf-rp:ResourceProperties="wsnt:SubscriptionManagerRP">
+
+ <wsdl:operation name="Destroy">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyRequest"
+ name="DestroyRequest" message="wsrf-rlw:DestroyRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination/DestroyResponse"
+ name="DestroyResponse" message="wsrf-rlw:DestroyResponse" />
+ <wsdl:fault name="ResourceNotDestroyedFault" message="wsrf-rlw:ResourceNotDestroyedFault" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeRequest"
+ name="SetTerminationTimeRequest" message="wsrf-rlw:SetTerminationTimeRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination/SetTerminationTimeResponse"
+ name="SetTerminationTimeResponse" message="wsrf-rlw:SetTerminationTimeResponse" />
+ <wsdl:fault name="UnableToSetTerminationTimeFault" message="wsrf-rlw:UnableToSetTerminationTimeFault" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="TerminationTimeChangeRejectedFault" message="wsrf-rlw:TerminationTimeChangeRejectedFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest" message="wsrf-rpw:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse" message="wsrf-rpw:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest" message="wsrf-rpw:GetResourcePropertyRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse" message="wsrf-rpw:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest" message="wsrf-rpw:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse" message="wsrf-rpw:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+
+<!-- </wsdl:portType>
+
+ <wsdl:portType name="PausableSubscriptionManager">
+-->
+ <!-- === PausableSubscriptionManager specific operations === -->
+ <wsdl:operation name="PauseSubscription">
+ <wsdl:input message="wsntw:PauseSubscriptionRequest" wsa:Action="http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionRequest"/>
+ <wsdl:output message="wsntw:PauseSubscriptionResponse" wsa:Action="http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionResponse"/>
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="PauseFailedFault"
+ message="wsntw:PauseFailedFault" />
+ </wsdl:operation>
+ <wsdl:operation name="ResumeSubscription">
+ <wsdl:input message="wsntw:ResumeSubscriptionRequest" wsa:Action="http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionRequest"/>
+ <wsdl:output message="wsntw:ResumeSubscriptionResponse" wsa:Action="http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionResponse"/>
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="ResumeFailedFault"
+ message="wsntw:ResumeFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+</wsdl:definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd
new file mode 100644
index 0000000000..9e10282759
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2004-2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+
+<xsd:schema
+ targetNamespace="http://docs.oasis-open.org/wsn/b-2"
+ xmlns="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
+xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+<!-- ======================== Imports ============================ -->
+
+ <xsd:import namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd"
+ />
+
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"
+ schemaLocation="WS-BaseFaults-1_2.xsd"
+ />
+
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rl-2"
+ schemaLocation="WS-ResourceLifetime-1_2.xsd"
+ />
+ <xsd:import namespace="http://docs.oasis-open.org/wsn/t-1"
+ schemaLocation="WS-Topics-1_3.xsd"
+ />
+
+<!-- ===================== Misc. Helper Types ===================== -->
+
+ <xsd:complexType name="QueryExpressionType" mixed="true">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1" processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI" use="required"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="TopicExpressionType" mixed="true">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1" processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI" use="required" />
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+
+ <xsd:complexType name="FilterType">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="SubscriptionPolicyType">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+<!-- =============== Resource Property Related =================== -->
+<!-- ======== Resource Properties for NotificationProducer ======== -->
+ <xsd:element name="TopicExpression" type="wsnt:TopicExpressionType"/>
+ <xsd:element name="FixedTopicSet" type="xsd:boolean" default="true"/>
+ <xsd:element name="TopicExpressionDialect" type="xsd:anyURI"/>
+
+ <xsd:element name="NotificationProducerRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsnt:TopicExpression"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="wsnt:FixedTopicSet"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:TopicExpressionDialect"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="wstop:TopicSet"
+ minOccurs="0" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ======== Resource Properties for SubscriptionManager ========= -->
+ <xsd:element name="ConsumerReference"
+ type="wsa:EndpointReferenceType" />
+ <xsd:element name="Filter" type="wsnt:FilterType" />
+ <xsd:element name="SubscriptionPolicy" type="wsnt:SubscriptionPolicyType" />
+
+
+ <xsd:element name="CreationTime" type="xsd:dateTime" />
+
+ <xsd:element name="SubscriptionManagerRP" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsnt:ConsumerReference"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element ref="wsnt:Filter"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:SubscriptionPolicy"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:CreationTime"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsrf-rl:CurrentTime"/>
+ <xsd:element ref="wsrf-rl:TerminationTime"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ================= Notification Metadata ===================== -->
+ <xsd:element name="SubscriptionReference"
+ type="wsa:EndpointReferenceType" />
+ <xsd:element name="Topic"
+ type="wsnt:TopicExpressionType" />
+ <xsd:element name="ProducerReference"
+ type="wsa:EndpointReferenceType" />
+
+<!-- ================== Message Helper Types ===================== -->
+ <xsd:complexType name="NotificationMessageHolderType" >
+ <xsd:sequence>
+ <xsd:element ref="wsnt:SubscriptionReference"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:Topic"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:ProducerReference"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element name="Message">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="lax"
+ minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="NotificationMessage"
+ type="wsnt:NotificationMessageHolderType"/>
+
+<!-- ========== Message Types for NotificationConsumer =========== -->
+ <xsd:element name="Notify" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsnt:NotificationMessage"
+ minOccurs="1" maxOccurs="unbounded" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ========== Message Types for NotificationProducer =========== -->
+
+ <xsd:simpleType name="AbsoluteOrRelativeTimeType">
+ <xsd:union memberTypes="xsd:dateTime xsd:duration" />
+ </xsd:simpleType>
+
+ <xsd:element name="CurrentTime" type="xsd:dateTime" />
+
+ <xsd:element name="TerminationTime"
+ nillable="true" type="xsd:dateTime" />
+
+ <xsd:element name="ProducerProperties"
+ type="wsnt:QueryExpressionType" />
+
+ <xsd:element name="MessageContent"
+ type="wsnt:QueryExpressionType" />
+
+ <xsd:element name="UseRaw"><xsd:complexType/></xsd:element>
+
+ <xsd:element name="Subscribe" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="ConsumerReference"
+ type="wsa:EndpointReferenceType"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element name="Filter"
+ type="wsnt:FilterType"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element name="InitialTerminationTime"
+ type="wsnt:AbsoluteOrRelativeTimeType"
+ nillable="true"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element name="SubscriptionPolicy"
+ minOccurs="0" maxOccurs="1">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="SubscribeResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="SubscriptionReference"
+ type="wsa:EndpointReferenceType"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element ref="wsnt:CurrentTime"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsnt:TerminationTime"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="GetCurrentMessage">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="Topic"
+ type="wsnt:TopicExpressionType" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="GetCurrentMessageResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="SubscribeCreationFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="SubscribeCreationFailedFault"
+ type="wsnt:SubscribeCreationFailedFaultType"/>
+
+ <xsd:complexType name="InvalidFilterFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="UnknownFilter" type="xsd:QName"
+ minOccurs="1" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidFilterFault"
+ type="wsnt:InvalidFilterFaultType"/>
+
+ <xsd:complexType name="TopicExpressionDialectUnknownFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="TopicExpressionDialectUnknownFault"
+ type="wsnt:TopicExpressionDialectUnknownFaultType"/>
+
+ <xsd:complexType name="InvalidTopicExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidTopicExpressionFault"
+ type="wsnt:InvalidTopicExpressionFaultType"/>
+
+ <xsd:complexType name="TopicNotSupportedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="TopicNotSupportedFault"
+ type="wsnt:TopicNotSupportedFaultType"/>
+
+ <xsd:complexType name="MultipleTopicsSpecifiedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="MultipleTopicsSpecifiedFault"
+ type="wsnt:MultipleTopicsSpecifiedFaultType"/>
+
+ <xsd:complexType name="InvalidProducerPropertiesExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidProducerPropertiesExpressionFault"
+ type="wsnt:InvalidProducerPropertiesExpressionFaultType"/>
+
+ <xsd:complexType name="InvalidMessageContentExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidMessageContentExpressionFault"
+ type="wsnt:InvalidMessageContentExpressionFaultType"/>
+
+ <xsd:complexType name="UnrecognizedPolicyRequestFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="UnrecognizedPolicy" type="xsd:QName"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnrecognizedPolicyRequestFault"
+ type="wsnt:UnrecognizedPolicyRequestFaultType"/>
+
+ <xsd:complexType name="UnsupportedPolicyRequestFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="UnsupportedPolicy" type="xsd:QName"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnsupportedPolicyRequestFault"
+ type="wsnt:UnsupportedPolicyRequestFaultType"/>
+
+ <xsd:complexType name="NotifyMessageNotSupportedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="NotifyMessageNotSupportedFault"
+ type="wsnt:NotifyMessageNotSupportedFaultType"/>
+
+ <xsd:complexType name="UnacceptableInitialTerminationTimeFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="MinimumTime" type="xsd:dateTime"/>
+ <xsd:element name="MaximumTime" type="xsd:dateTime"
+ minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnacceptableInitialTerminationTimeFault"
+ type="wsnt:UnacceptableInitialTerminationTimeFaultType"/>
+
+ <xsd:complexType name="NoCurrentMessageOnTopicFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="NoCurrentMessageOnTopicFault"
+ type="wsnt:NoCurrentMessageOnTopicFaultType"/>
+
+<!-- ======== Message Types for PullPoint ======================== -->
+ <xsd:element name="GetMessages">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="MaximumNumber"
+ type="xsd:nonNegativeInteger"/>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="GetMessagesResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsnt:NotificationMessage"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="DestroyPullPoint">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="DestroyPullPointResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="UnableToDestroyPullPointFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnableToDestroyPullPointFault"
+ type="wsnt:UnableToDestroyPullPointFaultType"/>
+
+<!-- ======== Message Types for Create PullPoint ================= -->
+ <xsd:element name="CreatePullPoint">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="CreatePullPointResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="PullPoint"
+ type="wsa:EndpointReferenceType"/>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="UnableToCreatePullPointFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnableToCreatePullPointFault"
+ type="wsnt:UnableToCreatePullPointFaultType"/>
+
+<!-- ======== Message Types for Base SubscriptionManager ========= -->
+ <xsd:element name="Renew">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="TerminationTime"
+ type="wsnt:AbsoluteOrRelativeTimeType"
+ nillable="true"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="RenewResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsnt:TerminationTime"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element ref="wsnt:CurrentTime"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="UnacceptableTerminationTimeFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="MinimumTime" type="xsd:dateTime"/>
+ <xsd:element name="MaximumTime" type="xsd:dateTime"
+ minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnacceptableTerminationTimeFault"
+ type="wsnt:UnacceptableTerminationTimeFaultType"/>
+
+ <xsd:element name="Unsubscribe">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="UnsubscribeResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="UnableToDestroySubscriptionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnableToDestroySubscriptionFault"
+ type="wsnt:UnableToDestroySubscriptionFaultType"/>
+
+<!-- ====== Message Types for Pausable SubscriptionManager ======= -->
+
+ <xsd:element name="PauseSubscription">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="PauseSubscriptionResponse" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="ResumeSubscription">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="ResumeSubscriptionResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="PauseFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="PauseFailedFault"
+ type="wsnt:PauseFailedFaultType"/>
+
+ <xsd:complexType name="ResumeFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResumeFailedFault"
+ type="wsnt:ResumeFailedFaultType"/>
+
+</xsd:schema> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd b/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd
new file mode 100644
index 0000000000..4cef35b510
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd
@@ -0,0 +1,134 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<!--
+(c) 2004 BEA Systems Inc., Computer Associates International, Inc.,
+International Business Machines Corporation, Microsoft Corporation,
+Inc., SAP AG, Sun Microsystems, and webMethods. All rights reserved.
+
+Permission to copy and display the WS-MetadataExchange Specification
+(the "Specification"), in any medium without fee or royalty is hereby
+granted, provided that you include the following on ALL copies of the
+Specification that you make:
+
+1. A link or URL to the Specification at this location.
+2. The copyright notice as shown in the Specification.
+
+BEA Systems, Computer Associates, IBM, Microsoft, SAP, Sun, and
+webMethods (collectively, the "Authors") each agree to grant you a
+license, under royalty-free and otherwise reasonable,
+non-discriminatory terms and conditions, to their respective essential
+patent claims that they deem necessary to implement the
+WS-MetadataExchange Specification.
+
+THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
+REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE
+SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
+IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY
+PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
+INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
+USE OR DISTRIBUTION OF THE SPECIFICATIONS.
+
+The name and trademarks of the Authors may NOT be used in any manner,
+including advertising or publicity pertaining to the Specifications or
+their contents without specific, written prior permission. Title to
+copyright in the Specifications will at all times remain with the
+Authors.
+
+No other rights are granted by implication, estoppel or otherwise.
+-->
+
+<xs:schema
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:tns="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" >
+
+ <xs:import
+ namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd" />
+
+ <!-- Get Metadata request -->
+ <xs:element name='GetMetadata' >
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref='tns:Dialect' minOccurs='0' />
+ <xs:element ref='tns:Identifier' minOccurs='0' />
+ </xs:sequence>
+ <xs:anyAttribute namespace='##other' processContents='lax' />
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name='Dialect' type='xs:anyURI' />
+ <xs:element name='Identifier' type='xs:anyURI' />
+
+ <!-- Get Metadata response -->
+ <xs:element name='Metadata' >
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref='tns:MetadataSection'
+ minOccurs='0'
+ maxOccurs='unbounded' />
+ </xs:sequence>
+ <xs:anyAttribute namespace='##other' processContents='lax' />
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name='MetadataSection' >
+ <xs:complexType>
+ <xs:choice>
+ <xs:any namespace='##other'
+ processContents='lax'
+ minOccurs='0'
+ maxOccurs='unbounded' />
+ <xs:element ref='tns:MetadataReference' />
+ <xs:element ref='tns:Location' />
+ </xs:choice>
+ <xs:attribute name='Dialect' type='xs:anyURI' use='required' />
+ <xs:attribute name='Identifier' type='xs:anyURI' />
+ <xs:anyAttribute namespace='##other' processContents='lax' />
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name='MetadataReference'
+ type='wsa:EndpointReferenceType' />
+
+ <xs:element name='Location'
+ type='xs:anyURI' />
+
+ <!-- count(/s:Envelope/s:Body/*) = 0 for Get request -->
+
+ <!-- Get Response returns xs:any -->
+
+ <xs:complexType name='AnyXmlType' >
+ <xs:sequence>
+ <xs:any namespace='##any' processContents='lax' />
+ </xs:sequence>
+ <xs:anyAttribute namespace='##any' processContents='lax' />
+ </xs:complexType>
+
+</xs:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl
new file mode 100644
index 0000000000..ed1c309211
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+
+<wsdl:definitions name="WS-Resource"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rw-2"
+>
+
+<!-- ===================== Types Definitions ====================== -->
+ <wsdl:types>
+ <xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rw-2"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/r-2"
+ schemaLocation="WS-Resource-1_2.xsd"
+ />
+
+ </xsd:schema>
+ </wsdl:types>
+
+<!-- ================= WS-Resource faults ========================= -->
+ <wsdl:message name="ResourceUnknownFault">
+ <part name="ResourceUnknownFault"
+ element="wsrf-r:ResourceUnknownFault" />
+ </wsdl:message>
+
+ <wsdl:message name="ResourceUnavailableFault">
+ <part name="ResourceUnavailableFault"
+ element="wsrf-r:ResourceUnavailableFault" />
+ </wsdl:message>
+
+</wsdl:definitions>
+
diff --git a/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd
new file mode 100644
index 0000000000..5d50284a33
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ elementFormDefault="qualified" attributeFormDefault="unqualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2"
+>
+
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/bf-2"
+ schemaLocation="WS-BaseFaults-1_2.xsd" />
+
+<!-- ====================== WS-Resource fault types ============= -->
+
+ <xsd:complexType name="ResourceUnknownFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnknownFault"
+ type="wsrf-r:ResourceUnknownFaultType"/>
+
+ <xsd:complexType name="ResourceUnavailableFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceUnavailableFault"
+ type="wsrf-r:ResourceUnavailableFaultType"/>
+</xsd:schema>
+
diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl
new file mode 100644
index 0000000000..adea5800fc
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+ OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+ Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+ The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+ This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+<wsdl:definitions name="WS-ResourceLifetime"
+targetNamespace="http://docs.oasis-open.org/wsrf/rlw-2"
+xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+xmlns:wsrf-rlw="http://docs.oasis-open.org/wsrf/rlw-2"
+xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
+xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
+
+ <wsdl:import namespace="http://docs.oasis-open.org/wsrf/rw-2"
+ location="WS-Resource-1_2.wsdl"/>
+ <wsdl:types>
+ <xsd:schema attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ xmlns="http://www.w3.org/2001/XMLSchema">
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/rl-2"
+ schemaLocation="WS-ResourceLifetime-1_2.xsd" />
+ </xsd:schema>
+ </wsdl:types>
+
+ <wsdl:message name="SetTerminationTimeRequest">
+ <wsdl:part element="wsrf-rl:SetTerminationTime" name="SetTerminationTimeRequest" />
+ </wsdl:message>
+ <wsdl:message name="SetTerminationTimeResponse">
+ <wsdl:part element="wsrf-rl:SetTerminationTimeResponse" name="SetTerminationTimeResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="DestroyRequest">
+ <wsdl:part element="wsrf-rl:Destroy" name="DestroyRequest" />
+ </wsdl:message>
+ <wsdl:message name="DestroyResponse">
+ <wsdl:part element="wsrf-rl:DestroyResponse" name="DestroyResponse" />
+ </wsdl:message>
+ <wsdl:message name="ResourceNotDestroyedFault">
+ <wsdl:part element="wsrf-rl:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnableToSetTerminationTimeFault">
+ <wsdl:part element="wsrf-rl:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault" />
+ </wsdl:message>
+ <wsdl:message name="TerminationTimeChangeRejectedFault">
+ <wsdl:part element="wsrf-rl:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault" />
+ </wsdl:message>
+ <wsdl:portType name="ImmediateResourceTermination">
+ <wsdl:operation name="Destroy">
+ <wsdl:input name="DestroyRequest" message="wsrf-rlw:DestroyRequest" />
+
+ <wsdl:output name="DestroyResponse" message="wsrf-rlw:DestroyResponse" />
+ <wsdl:fault message="wsrf-rlw:ResourceNotDestroyedFault" name="ResourceNotDestroyedFault" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:portType name="ScheduledResourceTermination"
+ wsrf-rp:ResourceProperties="wsrf-rl:ScheduledResourceTerminationRP">
+ <wsdl:operation name="SetTerminationTime">
+ <wsdl:input name="SetTerminationTimeRequest" message="wsrf-rlw:SetTerminationTimeRequest" />
+ <wsdl:output name="SetTerminationTimeResponse" message="wsrf-rlw:SetTerminationTimeResponse" />
+
+ <wsdl:fault message="wsrf-rlw:UnableToSetTerminationTimeFault" name="UnableToSetTerminationTimeFault" />
+ <wsdl:fault name="ResourceUnknownFault" message="wsrf-rw:ResourceUnknownFault" />
+ <wsdl:fault name="ResourceUnavailableFault" message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault message="wsrf-rlw:TerminationTimeChangeRejectedFault" name="TerminationTimeChangeRejectedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+</wsdl:definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd
new file mode 100644
index 0000000000..3338faf191
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+ OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+ Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+ The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+ This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+
+
+<xsd:schema
+xmlns="http://www.w3.org/2001/XMLSchema"
+xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+elementFormDefault="qualified" attributeFormDefault="unqualified"
+targetNamespace="http://docs.oasis-open.org/wsrf/rl-2">
+
+ <xsd:import namespace="http://docs.oasis-open.org/wsrf/bf-2"
+ schemaLocation="WS-BaseFaults-1_2.xsd" />
+ <!--
+ =============== Resource Property Related ===================
+ -->
+ <!--
+ ==== Resource Properties for ScheduledResourceTermination ====
+ -->
+
+ <xsd:element name="CurrentTime" >
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime" >
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="TerminationTime" nillable="true">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime" >
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- ==== Resource Properties for ScheduledResourceTermination ==== -->
+ <xsd:element name="ScheduledResourceTerminationRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="1" minOccurs="1" ref="wsrf-rl:CurrentTime" />
+ <xsd:element maxOccurs="1" minOccurs="1" ref="wsrf-rl:TerminationTime" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- ====== Message Types for ImmediateResourceTermination ======= -->
+ <xsd:element name="Destroy">
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:element name="DestroyResponse">
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:complexType name="ResourceNotDestroyedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType" />
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ResourceNotDestroyedFault" type="wsrf-rl:ResourceNotDestroyedFaultType" />
+ <!-- ====== Message Types for ScheduledResourceTermination ======= -->
+ <xsd:element name="SetTerminationTime">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element name="RequestedTerminationTime" nillable="true" type="xsd:dateTime" />
+ <xsd:element name="RequestedLifetimeDuration" type="xsd:duration" />
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="SetTerminationTimeResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="NewTerminationTime" nillable="true" type="xsd:dateTime" />
+ <xsd:element name="CurrentTime" type="xsd:dateTime" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="UnableToSetTerminationTimeFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType" />
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="UnableToSetTerminationTimeFault" type="wsrf-rl:UnableToSetTerminationTimeFaultType" />
+ <xsd:complexType name="TerminationTimeChangeRejectedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType" />
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="TerminationTimeChangeRejectedFault" type="wsrf-rl:TerminationTimeChangeRejectedFaultType" />
+
+
+ <!--
+ ============= Notification Message Related ==================
+ -->
+ <xsd:element name="TerminationNotification">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="TerminationTime" type="xsd:dateTime" minOccurs="1" maxOccurs="1" nillable="true" />
+ <xsd:element name="TerminationReason" type="xsd:anyType" minOccurs="0" maxOccurs="1" />
+ </xsd:sequence>
+
+ </xsd:complexType>
+ </xsd:element>
+
+
+</xsd:schema> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd
new file mode 100644
index 0000000000..2c5952264b
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd
@@ -0,0 +1,325 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005-2006). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+-->
+
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rmd-1"
+ xmlns:wsrmd="http://docs.oasis-open.org/wsrf/rmd-1"
+ elementFormDefault="qualified">
+
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/rp-2"
+ schemaLocation="WS-ResourceProperties-1_2.xsd" />
+
+ <xsd:import
+ namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd" />
+
+
+
+<!-- ======================== Utility Types ======================= -->
+ <xsd:simpleType name="PairsOfURIType">
+ <xsd:list itemType="xsd:anyURI" />
+ </xsd:simpleType>
+
+<!-- ================ PortType Attribute Extensions ================ -->
+ <xsd:attribute name="Descriptor" type="xsd:QName" />
+
+ <xsd:attribute name="DescriptorLocation" type="xsd:anyURI" />
+
+<!-- ================= Documentation Component ==================== -->
+ <xsd:complexType name="DocumentationType" mixed="true" >
+ <xsd:sequence>
+ <xsd:any namespace="##any"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:anyAttribute/>
+ </xsd:complexType>
+
+ <xsd:complexType name="DocumentedType">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wsrmd:DocumentationType"
+ minOccurs="0" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+<!-- ================== Definitions Component ===================== -->
+<!--
+ <Definitions
+ targetNamespace="xsd:anyURI"
+ {anyAttribute}* >
+
+ <documentation />?
+ <MetadataDescriptor /> *
+ {any}*
+
+</Definitions>
+ -->
+
+ <xsd:complexType name= "DefinitionsType" >
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element ref="wsrmd:MetadataDescriptor"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="targetNamespace"
+ type="xsd:anyURI" use="required"/>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="Definitions" type="wsrmd:DefinitionsType" >
+ <xsd:key name="MetadataDescriptor">
+ <xsd:annotation>
+ <xsd:documentation>
+ To form a QName, the name of any MetadataDescriptor must be
+ unique within a Definitions element.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:selector xpath="wsrmd:MetadataDescriptor" />
+ <xsd:field xpath="@name" />
+ </xsd:key>
+ </xsd:element>
+
+<!-- =============== MetadataDescriptor Component =================== -->
+<!--
+<MetadataDescriptor
+ name="xsd:NCName"
+ interface="xsd:QName"
+ wsdlLocation="list of xsd:anyURI"?
+ {anyAttribute}* >
+
+ <documentation />?
+ <Property /> *
+ {any}*
+
+</MetadataDescriptor>
+-->
+
+ <xsd:complexType name= "MetadataDescriptorType" >
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:element ref="wsrmd:Property"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:NCName" use="required"/>
+ <xsd:attribute name="interface"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute name="wsdlLocation"
+ type="wsrmd:PairsOfURIType" />
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="MetadataDescriptor"
+ type="wsrmd:MetadataDescriptorType" />
+
+<!-- ==================== Property Component ====================== -->
+<!--
+<Property
+ name="xsd:QName"
+ mutability="[constant|appendable|mutable]" ?
+ modifiability="[read-only|read-write]" ?
+ subscribability="xs:boolean" ?
+ {anyAttribute}* >
+
+ <documentation />?
+ [ <ValidValues> {any}* </ValidValues> |
+ <ValidValueRange lowerBound=’xsd:simpleType’
+ upperBound=’xsd:simpleType’>
+ </ValidValueRange> ] ?
+ <StaticValues> {any}* </StaticValues> ?
+
+ {any} *
+
+</Property>
+-->
+ <xsd:complexType name= "PropertyType" >
+ <xsd:complexContent>
+ <xsd:extension base="wsrmd:DocumentedType">
+ <xsd:sequence>
+ <xsd:choice>
+ <xsd:element ref="wsrmd:ValidValues"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element ref="wsrmd:ValidValueRange"
+ minOccurs="0" maxOccurs="1" />
+ </xsd:choice>
+ <xsd:element ref="wsrmd:StaticValues"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="name"
+ type="xsd:QName" use="required"/>
+ <xsd:attribute name="mutability"
+ type="wsrmd:MutabilityType" />
+ <xsd:attribute name="modifiability"
+ type="wsrmd:ModifiabilityType" />
+ <xsd:attribute name="subscribability" type="xsd:boolean" default="false" />
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="Property" type="wsrmd:PropertyType" />
+
+ <xsd:simpleType name="MutabilityType">
+ <xsd:restriction base="xsd:string" >
+ <xsd:enumeration value="constant" />
+ <xsd:enumeration value="appendable" />
+ <xsd:enumeration value="mutable" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="ModifiabilityType">
+ <xsd:restriction base="xsd:string" >
+ <xsd:enumeration value="read-only" />
+ <xsd:enumeration value="read-write" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+<!-- ================= Valid Values Component ===================== -->
+<!--
+<ValidValues
+ {anyAttribute}* >
+ <documentation />?
+ {any}*
+</ValidValues>
+-->
+ <xsd:complexType name= "ValidValuesType" mixed="true">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wsrmd:DocumentationType"
+ minOccurs="0" maxOccurs="1" />
+
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:element name="ValidValues" type="wsrmd:ValidValuesType" />
+
+<!-- ================= Valid Range Component ===================== -->
+<!--
+<ValidValueRange
+ lowerBound="xs:anySimpleType" ? upperBound="xs:anySimpleType" ?
+ {anyAttribute}* >
+ <documentation />?
+ {any}*
+</ValidValueRange>
+-->
+ <xsd:complexType name= "ValidValueRangeType" mixed="true">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wsrmd:DocumentationType"
+ minOccurs="0" maxOccurs="1" />
+
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="lowerBound" type="xsd:anySimpleType" />
+ <xsd:attribute name="upperBound" type="xsd:anySimpleType" />
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:element name="ValidValueRange" type="wsrmd:ValidValueRangeType" />
+
+<!-- ================ Static Values Component ===================== -->
+<!--
+<StaticValues
+ {anyAttribute}* >
+ <documentation />?
+ {any}*
+</StaticValues>
+-->
+ <xsd:complexType name= "StaticValuesType" mixed="true">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wsrmd:DocumentationType"
+ minOccurs="0" maxOccurs="1" />
+
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:element name="StaticValues" type="wsrmd:StaticValuesType" />
+
+<!-- ================ Initial Values Component ==================== -->
+<!--
+<InitialValues
+ {anyAttribute}* >
+ <documentation />?
+ {any}*
+</InitialValues>
+-->
+ <xsd:complexType name= "InitialValuesType" mixed="true">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wsrmd:DocumentationType"
+ minOccurs="0" maxOccurs="1" />
+
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:element name="InitialValues" type="wsrmd:InitialValuesType" />
+
+
+<!-- =========== MetadataDescriptorReference RP GED =============== -->
+ <xsd:complexType name="MetadataDescriptorReferenceType">
+ <xsd:complexContent>
+ <xsd:extension base="wsa:EndpointReferenceType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="MetadataDescriptorReference"
+ type="wsrmd:MetadataDescriptorReferenceType" />
+
+<!--
+
+Metadata Resource RP Doc
+
+This defines one property - MetadataDescriptor - which must have a cardinality of one.
+
+-->
+
+ <xsd:element name="MetadataResourceRP" type="wsrmd:DefinitionsType"/>
+
+</xsd:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl
new file mode 100644
index 0000000000..5d9d7562f4
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl
@@ -0,0 +1,395 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+
+<wsdl:definitions name="WS-ResourceProperties"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-rpw="http://docs.oasis-open.org/wsrf/rpw-2"
+ xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rpw-2"
+>
+
+<!-- ========================== Imports ========================== -->
+
+ <wsdl:import
+ namespace="http://docs.oasis-open.org/wsrf/rw-2"
+ location="WS-Resource-1_2.wsdl" />
+
+<!-- ===================== Types Definitions ====================== -->
+ <wsdl:types>
+ <xsd:schema>
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/rp-2"
+ schemaLocation="WS-ResourceProperties-1_2.xsd" />
+ </xsd:schema>
+ </wsdl:types>
+
+<!-- ================== GetResourcePropertyDocument ===============
+ GetResourcePropertyDocument()
+ returns: any
+-->
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part name="GetResourcePropertyDocumentRequest"
+ element="wsrf-rp:GetResourcePropertyDocument"/>
+ </wsdl:message>
+
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part name="GetResourcePropertyDocumentResponse"
+ element="wsrf-rp:GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+
+<!-- ===================== GetResourceProperty ====================
+ GetResourceProperty(QName)
+ returns: any
+-->
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part name="GetResourcePropertyRequest"
+ element="wsrf-rp:GetResourceProperty" />
+ </wsdl:message>
+
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part name="GetResourcePropertyResponse"
+ element="wsrf-rp:GetResourcePropertyResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <part name="InvalidResourcePropertyQNameFault"
+ element="wsrf-rp:InvalidResourcePropertyQNameFault" />
+ </wsdl:message>
+
+<!-- ==============GetMultipleResourceProperties ==================
+ GetMultipleResourceProperties(list of QName)
+ returns: sequence of any
+-->
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part name="GetMultipleResourcePropertiesRequest"
+ element="wsrf-rp:GetMultipleResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part name="GetMultipleResourcePropertiesResponse"
+ element="wsrf-rp:GetMultipleResourcePropertiesResponse" />
+ </wsdl:message>
+<!-- ================== PutResourcePropertyDocument ===============
+ PutResourcePropertyDocument(any)
+ returns: any?
+-->
+ <wsdl:message name="PutResourcePropertyDocumentRequest">
+ <wsdl:part name="PutResourcePropertyDocumentRequest"
+ element="wsrf-rp:PutResourcePropertyDocument"/>
+ </wsdl:message>
+
+ <wsdl:message name="PutResourcePropertyDocumentResponse">
+ <wsdl:part name="PutResourcePropertyDocumentResponse"
+ element="wsrf-rp:PutResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+
+ <wsdl:message name="UnableToPutResourcePropertyDocumentFault">
+ <part name="UnableToPutResourcePropertyDocumentFault"
+ element="wsrf-rp:UnableToPutResourcePropertyDocumentFault" />
+ </wsdl:message>
+
+<!-- ================= SetResourceProperties ======================
+ SetResourceProperties(
+ { insert (any)* |
+ update (any)* |
+ delete@QName } +
+ )
+ returns: empty
+-->
+ <wsdl:message name="SetResourcePropertiesRequest">
+ <wsdl:part name="SetResourcePropertiesRequest"
+ element="wsrf-rp:SetResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="SetResourcePropertiesResponse">
+ <wsdl:part name="SetResourcePropertiesResponse"
+ element="wsrf-rp:SetResourcePropertiesResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidModificationFault">
+ <part name="InvalidModificationFault"
+ element="wsrf-rp:InvalidModificationFault" />
+ </wsdl:message>
+
+ <wsdl:message name="UnableToModifyResourcePropertyFault">
+ <part name="UnableToModifyResourcePropertyFault"
+ element="wsrf-rp:UnableToModifyResourcePropertyFault" />
+ </wsdl:message>
+
+ <wsdl:message name="SetResourcePropertyRequestFailedFault">
+ <part name="SetResourcePropertyRequestFailedFault"
+ element="wsrf-rp:SetResourcePropertyRequestFailedFault" />
+ </wsdl:message>
+
+<!-- =============== InsertResourceProperties =====================
+ InsertResourceProperties((any)* )
+ returns: empty
+-->
+ <wsdl:message name="InsertResourcePropertiesRequest">
+ <wsdl:part name="InsertResourcePropertiesRequest"
+ element="wsrf-rp:InsertResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="InsertResourcePropertiesResponse">
+ <wsdl:part name="InsertResourcePropertiesResponse"
+ element="wsrf-rp:InsertResourcePropertiesResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="InsertResourcePropertiesRequestFailedFault">
+ <part name="InsertResourcePropertiesRequestFailedFault"
+ element="wsrf-rp:InsertResourcePropertiesRequestFailedFault" />
+ </wsdl:message>
+
+<!-- =============== UpdateResourceProperties =====================
+ UpdateResourceProperties((any)* )
+ returns: empty
+-->
+ <wsdl:message name="UpdateResourcePropertiesRequest">
+ <wsdl:part name="UpdateResourcePropertiesRequest"
+ element="wsrf-rp:UpdateResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="UpdateResourcePropertiesResponse">
+ <wsdl:part name="UpdateResourcePropertiesResponse"
+ element="wsrf-rp:UpdateResourcePropertiesResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="UpdateResourcePropertiesRequestFailedFault">
+ <part name="UpdateResourcePropertiesRequestFailedFault"
+ element="wsrf-rp:UpdateResourcePropertiesRequestFailedFault" />
+ </wsdl:message>
+
+<!-- =============== DeleteResourceProperties =====================
+ DeleteResourceProperties( ResourceProperty )
+ returns: empty
+-->
+ <wsdl:message name="DeleteResourcePropertiesRequest">
+ <wsdl:part name="DeleteResourcePropertiesRequest"
+ element="wsrf-rp:DeleteResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="DeleteResourcePropertiesResponse">
+ <wsdl:part name="DeleteResourcePropertiesResponse"
+ element="wsrf-rp:DeleteResourcePropertiesResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="DeleteResourcePropertiesRequestFailedFault">
+ <part name="DeleteResourcePropertiesRequestFailedFault"
+ element="wsrf-rp:DeleteResourcePropertiesRequestFailedFault" />
+ </wsdl:message>
+
+<!-- ================ QueryResourceProperties =====================
+ QueryResourceProperties(QueryExpression)
+ returns: any
+-->
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part name="QueryResourcePropertiesRequest"
+ element="wsrf-rp:QueryResourceProperties" />
+ </wsdl:message>
+
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part name="QueryResourcePropertiesResponse"
+ element="wsrf-rp:QueryResourcePropertiesResponse" />
+ </wsdl:message>
+
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <part name="UnknownQueryExpressionDialectFault"
+ element="wsrf-rp:UnknownQueryExpressionDialectFault" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <part name="InvalidQueryExpressionFault"
+ element="wsrf-rp:InvalidQueryExpressionFault" />
+ </wsdl:message>
+
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <part name="QueryEvaluationErrorFault"
+ element="wsrf-rp:QueryEvaluationErrorFault" />
+ </wsdl:message>
+
+<!-- =================== PortType Definitions ===================== -->
+ <wsdl:portType name="GetResourcePropertyDocument">
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input name="GetResourcePropertyDocumentRequest"
+ message="wsrf-rpw:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output name="GetResourcePropertyDocumentResponse"
+ message="wsrf-rpw:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="GetResourceProperty">
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input name="GetResourcePropertyRequest"
+ message="wsrf-rpw:GetResourcePropertyRequest" />
+ <wsdl:output name="GetResourcePropertyResponse"
+ message="wsrf-rpw:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="GetMultipleResourceProperties">
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input name="GetMultipleResourcePropertiesRequest"
+ message="wsrf-rpw:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output name="GetMultipleResourcePropertiesResponse"
+ message="wsrf-rpw:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="PutResourcePropertyDocument">
+ <wsdl:operation name="PutResourcePropertyDocument">
+ <wsdl:input name="PutResourcePropertyDocumentRequest"
+ message="wsrf-rpw:PutResourcePropertyDocumentRequest" />
+ <wsdl:output name="PutResourcePropertyDocumentResponse"
+ message="wsrf-rpw:PutResourcePropertyDocumentResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="UnableToPutResourcePropertyDocumentFault"
+ message="wsrf-rpw:UnableToPutResourcePropertyDocumentFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="SetResourceProperties">
+ <wsdl:operation name="SetResourceProperties">
+ <wsdl:input name="SetResourcePropertiesRequest"
+ message="wsrf-rpw:SetResourcePropertiesRequest" />
+ <wsdl:output name="SetResourcePropertiesResponse"
+ message="wsrf-rpw:SetResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidModificationFault"
+ message="wsrf-rpw:InvalidModificationFault" />
+ <wsdl:fault name="UnableToModifyResourcePropertyFault"
+ message="wsrf-rpw:UnableToModifyResourcePropertyFault" />
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="SetResourcePropertyRequestFailedFault"
+ message="wsrf-rpw:SetResourcePropertyRequestFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="InsertResourceProperties">
+ <wsdl:operation name="InsertResourceProperties">
+ <wsdl:input name="InsertResourcePropertiesRequest"
+ message="wsrf-rpw:InsertResourcePropertiesRequest" />
+ <wsdl:output name="InsertResourcePropertiesResponse"
+ message="wsrf-rpw:InsertResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidModificationFault"
+ message="wsrf-rpw:InvalidModificationFault" />
+ <wsdl:fault name="UnableToModifyResourcePropertyFault"
+ message="wsrf-rpw:UnableToModifyResourcePropertyFault" />
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="InsertResourcePropertiesRequestFailedFault"
+ message="wsrf-rpw:InsertResourcePropertiesRequestFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="UpdateResourceProperties">
+ <wsdl:operation name="UpdateResourceProperties">
+ <wsdl:input name="UpdateResourcePropertiesRequest"
+ message="wsrf-rpw:UpdateResourcePropertiesRequest" />
+ <wsdl:output name="UpdateResourcePropertiesResponse"
+ message="wsrf-rpw:UpdateResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidModificationFault"
+ message="wsrf-rpw:InvalidModificationFault" />
+ <wsdl:fault name="UnableToModifyResourcePropertyFault"
+ message="wsrf-rpw:UnableToModifyResourcePropertyFault" />
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="UpdateResourcePropertiesRequestFailedFault"
+ message="wsrf-rpw:UpdateResourcePropertiesRequestFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+ <wsdl:portType name="DeleteResourceProperties">
+ <wsdl:operation name="DeleteResourceProperties">
+ <wsdl:input name="DeleteResourcePropertiesRequest"
+ message="wsrf-rpw:DeleteResourcePropertiesRequest" />
+ <wsdl:output name="DeleteResourcePropertiesResponse"
+ message="wsrf-rpw:DeleteResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidModificationFault"
+ message="wsrf-rpw:InvalidModificationFault" />
+ <wsdl:fault name="UnableToModifyResourcePropertyFault"
+ message="wsrf-rpw:UnableToModifyResourcePropertyFault" />
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="DeleteResourcePropertiesRequestFailedFault"
+ message="wsrf-rpw:DeleteResourcePropertiesRequestFailedFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+<wsdl:portType name="QueryResourceProperties"
+ wsrf-rp:ResourceProperties="wsrf-rp:QueryExpressionRPDocument">
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input name="QueryResourcePropertiesRequest"
+ message="wsrf-rpw:QueryResourcePropertiesRequest" />
+ <wsdl:output name="QueryResourcePropertiesResponse"
+ message="wsrf-rpw:QueryResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault"
+ message="wsrf-rw:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault"
+ message="wsrf-rw:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault"
+ message="wsrf-rpw:InvalidResourcePropertyQNameFault" />
+ <wsdl:fault name="UnknownQueryExpressionDialectFault"
+ message="wsrf-rpw:UnknownQueryExpressionDialectFault" />
+ <wsdl:fault name="InvalidQueryExpressionFault"
+ message="wsrf-rpw:InvalidQueryExpressionFault" />
+ <wsdl:fault name="QueryEvaluationErrorFault"
+ message="wsrf-rpw:QueryEvaluationErrorFault" />
+ </wsdl:operation>
+
+ </wsdl:portType>
+
+</wsdl:definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd
new file mode 100644
index 0000000000..c408b36db1
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd
@@ -0,0 +1,394 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ elementFormDefault="qualified" attributeFormDefault="unqualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2"
+>
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/bf-2"
+ schemaLocation="WS-BaseFaults-1_2.xsd"
+ />
+<!-- =============== Resource Property Related =================== -->
+<!-- ====== Resource Properties for QueryResourceProperties ======= -->
+ <xsd:element name="QueryExpressionDialect" type="xsd:anyURI"/>
+
+ <xsd:element name="QueryExpressionRPDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:QueryExpressionDialect"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ======= Global Attribute Declaration for WSDL 1.1 portType==== -->
+ <xsd:attribute name="ResourceProperties" type="xsd:QName" />
+
+<!-- = Notification Message for ResourceProperties value change === -->
+ <xsd:complexType name="ResourcePropertyValueChangeNotificationType">
+ <xsd:sequence>
+ <xsd:element name="OldValues" nillable="true"
+ minOccurs="0" maxOccurs="1" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NewValues" nillable="true"
+ minOccurs="1" maxOccurs="1" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="ResourcePropertyValueChangeNotification"
+ type="wsrf-rp:ResourcePropertyValueChangeNotificationType" />
+
+ <xsd:complexType name="QueryExpressionType" mixed="true">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1" processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI" />
+ </xsd:complexType>
+
+ <xsd:element name="QueryExpression" type="wsrf-rp:QueryExpressionType" />
+
+<!-- ======= Message Types for GetResourcePropertyDocument ======= -->
+
+ <xsd:element name="GetResourcePropertyDocument">
+ <xsd:complexType/>
+ </xsd:element>
+
+ <xsd:element name="GetResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ========== Message Types for GetResourceProperty ============ -->
+
+ <xsd:element name="GetResourceProperty"
+ type="xsd:QName" />
+
+ <xsd:element name="GetResourcePropertyResponse" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="InvalidResourcePropertyQNameFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidResourcePropertyQNameFault"
+ type="wsrf-rp:InvalidResourcePropertyQNameFaultType"/>
+
+<!-- ====== Message Types for GetMultipleResourceProperties ======= -->
+ <xsd:element name="GetMultipleResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="ResourceProperty" type="xsd:QName"
+ minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="GetMultipleResourcePropertiesResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ========== Message Types for PutResourceProperty ============ -->
+
+ <xsd:element name="PutResourcePropertyDocument">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="PutResourcePropertyDocumentResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="ResourcePropertyChangeFailureType">
+ <xsd:sequence>
+ <xsd:element name="CurrentValue" minOccurs="0" maxOccurs="1">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="RequestedValue" minOccurs="0" maxOccurs="1">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="Restored" type="xsd:boolean"/>
+ </xsd:complexType>
+
+ <xsd:complexType
+ name="UnableToPutResourcePropertyDocumentFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnableToPutResourcePropertyDocumentFault"
+ type=
+ "wsrf-rp:UnableToPutResourcePropertyDocumentFaultType"/>
+
+<!-- ========= Message Types for SetResourceProperties =========== -->
+
+ <xsd:complexType name="InsertType">
+ <xsd:sequence>
+ <xsd:any processContents="lax"
+ minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Insert" type="wsrf-rp:InsertType"/>
+
+ <xsd:complexType name="UpdateType">
+ <xsd:sequence>
+ <xsd:any processContents="lax"
+ minOccurs="1" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element name="Update" type="wsrf-rp:UpdateType"/>
+
+ <xsd:complexType name="DeleteType">
+ <xsd:attribute name="ResourceProperty"
+ type="xsd:QName" use="required" />
+ </xsd:complexType>
+ <xsd:element name="Delete" type="wsrf-rp:DeleteType"/>
+
+ <xsd:element name="SetResourceProperties">
+ <xsd:complexType>
+ <xsd:choice minOccurs="1" maxOccurs="unbounded">
+ <xsd:element ref="wsrf-rp:Insert"/>
+ <xsd:element ref="wsrf-rp:Update"/>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="SetResourcePropertiesResponse" >
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:complexType
+ name="InvalidModificationFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name=
+ "InvalidModificationFault"
+ type=
+ "wsrf-rp:InvalidModificationFaultType"/>
+
+ <xsd:complexType name="UnableToModifyResourcePropertyFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnableToModifyResourcePropertyFault"
+ type="wsrf-rp:UnableToModifyResourcePropertyFaultType"/>
+
+ <xsd:complexType name="SetResourcePropertyRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="SetResourcePropertyRequestFailedFault"
+ type=
+ "wsrf-rp:SetResourcePropertyRequestFailedFaultType"/>
+
+ <xsd:complexType name="InsertResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InsertResourcePropertiesRequestFailedFault"
+ type=
+ "wsrf-rp:InsertResourcePropertiesRequestFailedFaultType"/>
+
+ <xsd:complexType name="UpdateResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="UpdateResourcePropertiesRequestFailedFault"
+ type="wsrf-rp:UpdateResourcePropertiesRequestFailedFaultType"/>
+
+ <xsd:complexType name="DeleteResourcePropertiesRequestFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType">
+ <xsd:sequence>
+ <xsd:element name="ResourcePropertyChangeFailure" type=
+ "wsrf-rp:ResourcePropertyChangeFailureType"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element
+ name="DeleteResourcePropertiesRequestFailedFault"
+ type="wsrf-rp:DeleteResourcePropertiesRequestFailedFaultType"/>
+
+<!-- ======== Message Types for InsertResourceProperties ========== -->
+ <xsd:element name="InsertResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Insert"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="InsertResourcePropertiesResponse" >
+ <xsd:complexType />
+ </xsd:element>
+
+<!-- ======== Message Types for UpdateResourceProperties ========== -->
+ <xsd:element name="UpdateResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Update"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="UpdateResourcePropertiesResponse" >
+ <xsd:complexType />
+ </xsd:element>
+
+<!-- ======== Message Types for DeleteResourceProperties ========== -->
+ <xsd:element name="DeleteResourceProperties">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:Delete"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="DeleteResourcePropertiesResponse" >
+ <xsd:complexType />
+ </xsd:element>
+
+<!-- ========= Message Types for QueryResourceProperties ========== -->
+
+ <xsd:element name="QueryResourceProperties" >
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:QueryExpression"
+ minOccurs="1" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="QueryResourcePropertiesResponse" >
+ <xsd:complexType>
+ <xsd:complexContent mixed="true">
+ <xsd:restriction base="xsd:anyType">
+ <xsd:sequence>
+ <xsd:any processContents="lax"
+ minOccurs="1" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:restriction>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="UnknownQueryExpressionDialectFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnknownQueryExpressionDialectFault"
+ type="wsrf-rp:UnknownQueryExpressionDialectFaultType"/>
+
+ <xsd:complexType name="InvalidQueryExpressionFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="InvalidQueryExpressionFault"
+ type="wsrf-rp:InvalidQueryExpressionFaultType"/>
+
+ <xsd:complexType name="QueryEvaluationErrorFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="QueryEvaluationErrorFault"
+ type="wsrf-rp:QueryEvaluationErrorFaultType"/>
+
+</xsd:schema> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl
new file mode 100644
index 0000000000..a75cd59728
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ targetNamespace="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:tns="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2"
+ xmlns:wsrf-sgw="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ name="ServiceGroup">
+ <wsdl:types>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <xsd:include schemaLocation="WS-MetadataExchange-2004_09.xsd"/>
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:include schemaLocation="WS-ResourceProperties-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2">
+ <xsd:include schemaLocation="WS-Resource-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/sg-2">
+ <xsd:include schemaLocation="WS-ServiceGroup-1_2.xsd" />
+ </xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="GetMetadataMsg">
+ <wsdl:part name="GetMetadataMsg" element="wsx:GetMetadata" />
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMsg">
+ <wsdl:part name="GetMetadataResponseMsg" element="wsx:Metadata" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part name="ResourceUnknownFault" element="wsrf-r:ResourceUnknownFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part name="ResourceUnavailableFault" element="wsrf-r:ResourceUnavailableFault" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part name="GetResourcePropertyDocumentRequest" element="wsrf-rp:GetResourcePropertyDocument"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part name="GetResourcePropertyDocumentResponse" element="wsrf-rp:GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part name="GetResourcePropertyRequest" element="wsrf-rp:GetResourceProperty" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part name="GetResourcePropertyResponse" element="wsrf-rp:GetResourcePropertyResponse" />
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part name="InvalidResourcePropertyQNameFault" element="wsrf-rp:InvalidResourcePropertyQNameFault" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part name="GetMultipleResourcePropertiesRequest" element="wsrf-rp:GetMultipleResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part name="GetMultipleResourcePropertiesResponse" element="wsrf-rp:GetMultipleResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesRequest">
+ <wsdl:part name="QueryResourcePropertiesRequest" element="wsrf-rp:QueryResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="QueryResourcePropertiesResponse">
+ <wsdl:part name="QueryResourcePropertiesResponse" element="wsrf-rp:QueryResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:message name="UnknownQueryExpressionDialectFault">
+ <wsdl:part name="UnknownQueryExpressionDialectFault" element="wsrf-rp:UnknownQueryExpressionDialectFault" />
+ </wsdl:message>
+ <wsdl:message name="InvalidQueryExpressionFault">
+ <wsdl:part name="InvalidQueryExpressionFault" element="wsrf-rp:InvalidQueryExpressionFault" />
+ </wsdl:message>
+ <wsdl:message name="QueryEvaluationErrorFault">
+ <wsdl:part name="QueryEvaluationErrorFault" element="wsrf-rp:QueryEvaluationErrorFault" />
+ </wsdl:message>
+ <wsdl:portType
+ name="ServiceGroupPortType"
+ wsrf-rp:ResourceProperties="wsrf-sg:ServiceGroupRP">
+ <wsdl:operation name="GetMetadata">
+ <wsdl:input wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"
+ name="GetMetadataMsg" message="tns:GetMetadataMsg"/>
+ <wsdl:output wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"
+ name="GetMetadataResponseMsg" message="tns:GetMetadataResponseMsg"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest" message="tns:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse" message="tns:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest" message="tns:GetResourcePropertyRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse" message="tns:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="tns:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest" message="tns:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse" message="tns:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="tns:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesRequest"
+ name="QueryResourcePropertiesRequest" message="tns:QueryResourcePropertiesRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/QueryResourceProperties/QueryResourcePropertiesResponse"
+ name="QueryResourcePropertiesResponse" message="tns:QueryResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault" message="tns:UnknownQueryExpressionDialectFault"/>
+ <wsdl:fault name="InvalidQueryExpressionFault" message="tns:InvalidQueryExpressionFault"/>
+ <wsdl:fault name="QueryEvaluationErrorFault" message="tns:QueryEvaluationErrorFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="ServiceGroupBinding" type="tns:ServiceGroupPortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata" />
+ <wsdl:input>
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="QueryResourceProperties">
+ <wsdl-soap:operation soapAction="QueryResourceProperties"/>
+ <wsdl:input name="QueryResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="QueryResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="UnknownQueryExpressionDialectFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="UnknownQueryExpressionDialectFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidQueryExpressionFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidQueryExpressionFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="QueryEvaluationErrorFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="QueryEvaluationErrorFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="ServiceGroupService">
+ <wsdl:port name="ServiceGroupPort" binding="tns:ServiceGroupBinding">
+ <wsdl-soap:address location="http://localhost:8080/wsrf/services/ServiceGroup"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd
new file mode 100644
index 0000000000..87238f90e5
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+<xsd:schema
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/sg-2" >
+<!-- ======================== Imports ============================ -->
+
+ <xsd:import
+ namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd"/>
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/bf-2"
+ schemaLocation="WS-BaseFaults-1_2.xsd" />
+ <xsd:import
+ namespace="http://docs.oasis-open.org/wsrf/rp-2"
+ schemaLocation="WS-ResourceProperties-1_2.xsd" />
+
+<!-- =============== Resource Property Related =================== -->
+<!-- ============ Resource Properties for ServiceGroup ============ -->
+ <xsd:simpleType name="AbsoluteOrRelativeTimeType">
+ <xsd:union memberTypes="xsd:dateTime xsd:duration"/>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="ContentElementsType">
+ <xsd:list itemType="xsd:QName"/>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="MemberInterfacesType">
+ <xsd:list itemType="xsd:QName"/>
+ </xsd:simpleType>
+
+ <xsd:element name="MembershipContentRule">
+ <xsd:complexType>
+ <xsd:attribute name="MemberInterfaces"
+ type="wsrf-sg:MemberInterfacesType"/>
+ <xsd:attribute name="ContentElements"
+ type="wsrf-sg:ContentElementsType"
+ use="required"/>
+ <xsd:anyAttribute namespace="##other"
+ processContents="lax"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="RPDocType">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="lax"
+ minOccurs="1" maxOccurs="1" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other"
+ processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="ContentType">
+ <xsd:sequence>
+ <xsd:element name="RPDoc"
+ type="wsrf-sg:RPDocType"
+ minOccurs="0" maxOccurs="1" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other"
+ processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="EntryType">
+ <xsd:sequence>
+ <xsd:element name="ServiceGroupEntryEPR"
+ type="wsa:EndpointReferenceType"
+ minOccurs="1" maxOccurs="1"
+ nillable="true"/>
+ <xsd:element name="MemberServiceEPR"
+ type="wsa:EndpointReferenceType"
+ minOccurs="0" maxOccurs="1"/>
+ <xsd:element ref="wsrf-sg:Content"
+ minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+<!-- ========== Resource Properties for ServiceGroupEntry ========= -->
+
+ <xsd:element name="Entry"
+ type="wsrf-sg:EntryType"/>
+
+ <xsd:element name="Content"
+ type="wsrf-sg:ContentType"/>
+
+ <xsd:element name="MemberEPR"
+ type="wsa:EndpointReferenceType"/>
+
+ <xsd:element name="ServiceGroupEPR"
+ type="wsa:EndpointReferenceType"/>
+
+<!-- =============== Resource Property Related =================== -->
+<!-- ============ Resource Properties for ServiceGroup ============ -->
+ <xsd:element name="ServiceGroupRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-rp:QueryExpressionDialect"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element ref="wsrf-sg:MembershipContentRule"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element ref="wsrf-sg:Entry"
+ minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ========== Resource Properties for ServiceGroupEntry ========= -->
+ <xsd:element name="ServiceGroupEntryRP">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="wsrf-sg:ServiceGroupEPR"
+ minOccurs="1" maxOccurs="1"/>
+ <xsd:element ref="wsrf-sg:MemberEPR"
+ minOccurs="0" maxOccurs="1"/>
+ <xsd:element ref="wsrf-sg:Content"
+ minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+<!-- ================= Message Specific Types ==================== -->
+<!-- ======== Message Types for ServiceGroupRegistration ========= -->
+ <xsd:element name="Add">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="MemberEPR"
+ type="wsa:EndpointReferenceType" />
+ <xsd:element ref="wsrf-sg:Content" />
+ <xsd:element name="InitialTerminationTime"
+ type="wsrf-sg:AbsoluteOrRelativeTimeType"
+ minOccurs="0" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="AddResponse">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="ServiceGroupEntryReference"
+ type="wsa:EndpointReferenceType"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element name="TerminationTime"
+ nillable="true"
+ type="xsd:dateTime"
+ minOccurs="1" maxOccurs="1" />
+ <xsd:element name="CurrentTime"
+ type="xsd:dateTime"
+ minOccurs="1" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="ContentCreationFailedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="ContentCreationFailedFault"
+ type="wsrf-sg:ContentCreationFailedFaultType"/>
+
+ <xsd:complexType name="UnsupportedMemberInterfaceFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="UnsupportedMemberInterfaceFault"
+ type="wsrf-sg:UnsupportedMemberInterfaceFaultType"/>
+
+ <xsd:complexType name="AddRefusedFaultType">
+ <xsd:complexContent>
+ <xsd:extension base="wsrf-bf:BaseFaultType"/>
+ </xsd:complexContent>
+ </xsd:complexType>
+ <xsd:element name="AddRefusedFault"
+ type="wsrf-sg:AddRefusedFaultType"/>
+
+<!-- = Messages Related to ServiceGroup Change Notification ======= -->
+ <xsd:complexType name="ServiceGroupModificationNotificationType">
+ <xsd:sequence>
+ <xsd:element name="ServiceGroupEntryEPR"
+ type="wsa:EndpointReferenceType"
+ minOccurs="1" maxOccurs="1"
+ nillable="true"/>
+ <xsd:element name="MemberServiceEPR"
+ type="wsa:EndpointReferenceType"
+ minOccurs="0" maxOccurs="1"/>
+ <xsd:element ref="wsrf-sg:Content"
+ minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="ServiceGroupRemovalNotificationType">
+ <xsd:complexContent>
+ <xsd:extension
+ base="wsrf-sg:ServiceGroupModificationNotificationType">
+ <xsd:sequence>
+ <xsd:element name="Reason"
+ type="xsd:string"
+ minOccurs="0" maxOccurs="1"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="EntryAdditionNotification"
+ type="wsrf-sg:ServiceGroupModificationNotificationType" />
+
+ <xsd:element name="EntryRemovalNotification"
+ type="wsrf-sg:ServiceGroupRemovalNotificationType" />
+
+</xsd:schema>
diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl
new file mode 100644
index 0000000000..379382c18d
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ targetNamespace="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:tns="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns:wsrf-sg="http://docs.oasis-open.org/wsrf/sg-2"
+ xmlns:wsrf-sgw="http://docs.oasis-open.org/wsrf/sgw-2"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
+ xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2"
+ xmlns:wsrf-rl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2"
+ xmlns:wsrf-rp="http://docs.oasis-open.org/wsrf/rp-2"
+ name="ServiceGroupEntry">
+ <wsdl:types>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://schemas.xmlsoap.org/ws/2004/09/mex">
+ <xsd:include schemaLocation="WS-MetadataExchange-2004_09.xsd"/>
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/rp-2">
+ <xsd:include schemaLocation="WS-ResourceProperties-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/r-2">
+ <xsd:include schemaLocation="WS-Resource-1_2.xsd" />
+ </xsd:schema>
+ <xsd:schema
+ elementFormDefault="qualified"
+ targetNamespace="http://docs.oasis-open.org/wsrf/sg-2">
+ <xsd:include schemaLocation="WS-ServiceGroup-1_2.xsd" />
+ </xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="GetMetadataMsg">
+ <wsdl:part name="GetMetadataMsg" element="wsx:GetMetadata" />
+ </wsdl:message>
+ <wsdl:message name="GetMetadataResponseMsg">
+ <wsdl:part name="GetMetadataResponseMsg" element="wsx:Metadata" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnknownFault">
+ <wsdl:part name="ResourceUnknownFault" element="wsrf-r:ResourceUnknownFault" />
+ </wsdl:message>
+ <wsdl:message name="ResourceUnavailableFault">
+ <wsdl:part name="ResourceUnavailableFault" element="wsrf-r:ResourceUnavailableFault" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentRequest">
+ <wsdl:part name="GetResourcePropertyDocumentRequest" element="wsrf-rp:GetResourcePropertyDocument"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyDocumentResponse">
+ <wsdl:part name="GetResourcePropertyDocumentResponse" element="wsrf-rp:GetResourcePropertyDocumentResponse"/>
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyRequest">
+ <wsdl:part name="GetResourcePropertyRequest" element="wsrf-rp:GetResourceProperty" />
+ </wsdl:message>
+ <wsdl:message name="GetResourcePropertyResponse">
+ <wsdl:part name="GetResourcePropertyResponse" element="wsrf-rp:GetResourcePropertyResponse" />
+ </wsdl:message>
+ <wsdl:message name="InvalidResourcePropertyQNameFault">
+ <wsdl:part name="InvalidResourcePropertyQNameFault" element="wsrf-rp:InvalidResourcePropertyQNameFault" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesRequest">
+ <wsdl:part name="GetMultipleResourcePropertiesRequest" element="wsrf-rp:GetMultipleResourceProperties" />
+ </wsdl:message>
+ <wsdl:message name="GetMultipleResourcePropertiesResponse">
+ <wsdl:part name="GetMultipleResourcePropertiesResponse" element="wsrf-rp:GetMultipleResourcePropertiesResponse" />
+ </wsdl:message>
+ <wsdl:portType
+ name="ServiceGroupEntryPortType"
+ wsrf-rp:ResourceProperties="wsrf-sg:ServiceGroupEntryRP">
+ <wsdl:operation name="GetMetadata">
+ <wsdl:input wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"
+ name="GetMetadataMsg" message="tns:GetMetadataMsg"/>
+ <wsdl:output wsa:Action="http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse"
+ name="GetMetadataResponseMsg" message="tns:GetMetadataResponseMsg"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest"
+ name="GetResourcePropertyDocumentRequest" message="tns:GetResourcePropertyDocumentRequest"/>
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse"
+ name="GetResourcePropertyDocumentResponse" message="tns:GetResourcePropertyDocumentResponse"/>
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest"
+ name="GetResourcePropertyRequest" message="tns:GetResourcePropertyRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse"
+ name="GetResourcePropertyResponse" message="tns:GetResourcePropertyResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="tns:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl:input wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest"
+ name="GetMultipleResourcePropertiesRequest" message="tns:GetMultipleResourcePropertiesRequest" />
+ <wsdl:output wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse"
+ name="GetMultipleResourcePropertiesResponse" message="tns:GetMultipleResourcePropertiesResponse" />
+ <wsdl:fault name="ResourceUnknownFault" message="tns:ResourceUnknownFault"/>
+ <wsdl:fault name="ResourceUnavailableFault" message="tns:ResourceUnavailableFault"/>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault" message="tns:InvalidResourcePropertyQNameFault" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="ServiceGroupEntryBinding" type="tns:ServiceGroupEntryPortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="GetMetadata">
+ <wsdl-soap:operation soapAction="GetMetadata" />
+ <wsdl:input>
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourcePropertyDocument">
+ <wsdl-soap:operation soapAction="GetResourcePropertyDocument"/>
+ <wsdl:input name="GetResourcePropertyDocumentRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyDocumentResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetResourceProperty">
+ <wsdl-soap:operation soapAction="GetResourceProperty"/>
+ <wsdl:input name="GetResourcePropertyRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetResourcePropertyResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="GetMultipleResourceProperties">
+ <wsdl-soap:operation soapAction="GetMultipleResourceProperties"/>
+ <wsdl:input name="GetMultipleResourcePropertiesRequest">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:input><wsdl:output name="GetMultipleResourcePropertiesResponse">
+ <wsdl-soap:body
+ use="encoded"
+ encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+ </wsdl:output>
+ <wsdl:fault name="ResourceUnknownFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnknownFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="ResourceUnavailableFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="ResourceUnavailableFault"/>
+ </wsdl:fault>
+ <wsdl:fault name="InvalidResourcePropertyQNameFault">
+ <wsdl-soap:fault
+ use="encoded"
+ name="InvalidResourcePropertyQNameFault"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="ServiceGroupEntryService">
+ <wsdl:port name="ServiceGroupEntryPort" binding="tns:ServiceGroupEntryBinding">
+ <wsdl-soap:address location="http://localhost:8080/wsrf/services/ServiceGroupEntry"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
diff --git a/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd b/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd
new file mode 100644
index 0000000000..df98513131
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+
+Copyright (C) OASIS Open (2004-2005). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+-->
+
+
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wstop = "http://docs.oasis-open.org/wsn/t-1"
+ targetNamespace = "http://docs.oasis-open.org/wsn/t-1"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+<!-- =============== utility type definitions ==================== -->
+ <xsd:complexType name="Documentation" mixed="true">
+ <xsd:sequence>
+ <xsd:any processContents="lax" minOccurs="0"
+ maxOccurs="unbounded" namespace="##any"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="ExtensibleDocumented" abstract="true"
+ mixed="false">
+ <xsd:sequence>
+ <xsd:element name="documentation" type="wstop:Documentation"
+ minOccurs="0" />
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax" />
+</xsd:complexType>
+
+<xsd:complexType name="QueryExpressionType" mixed="true">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1" processContents="lax" />
+ </xsd:sequence>
+ <xsd:attribute name="Dialect" type="xsd:anyURI" use="required"/>
+</xsd:complexType>
+
+<!-- ================== Topic-Namespace Related ================ -->
+ <xsd:complexType name="TopicNamespaceType">
+ <xsd:complexContent>
+ <xsd:extension base="wstop:ExtensibleDocumented">
+ <xsd:sequence>
+ <xsd:element name="Topic"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="wstop:TopicType">
+ <xsd:attribute name="parent" type="wstop:ConcreteTopicExpression" />
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:NCName"/>
+ <xsd:attribute name="targetNamespace" type="xsd:anyURI"
+ use="required"/>
+ <xsd:attribute name="final" type="xsd:boolean"
+ default="false"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="TopicNamespace" type="wstop:TopicNamespaceType">
+ <xsd:unique name="rootTopicUniqueness">
+ <xsd:selector xpath="wstop:Topic"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ </xsd:element>
+
+ <xsd:attribute name="topicNamespaceLocation" type="xsd:anyURI"/>
+
+
+
+<!-- ===================== Topic Related ========================= -->
+
+ <xsd:complexType name="TopicType">
+ <xsd:complexContent>
+ <xsd:extension base="wstop:ExtensibleDocumented">
+ <xsd:sequence>
+ <xsd:element name="MessagePattern"
+ type="wstop:QueryExpressionType"
+ minOccurs="0" maxOccurs="1" />
+ <xsd:element name="Topic" type="wstop:TopicType"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:unique name="childTopicUniqueness">
+ <xsd:selector xpath="wstop:topic"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ </xsd:element>
+ <xsd:any namespace="##other" minOccurs="0"
+ maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:NCName"/>
+ <xsd:attribute name="messageTypes">
+ <xsd:simpleType>
+ <xsd:list itemType="xsd:QName"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="final" type="xsd:boolean"
+ default="false"/>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+<!-- ================ Topic Set Related =================== -->
+
+ <xsd:complexType name="TopicSetType">
+ <xsd:complexContent>
+ <xsd:extension base="wstop:ExtensibleDocumented">
+ <xsd:sequence>
+ <xsd:any namespace="##other"
+ minOccurs="0" maxOccurs="unbounded"
+ processContents="lax"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="TopicSet" type="wstop:TopicSetType"/>
+<xsd:attribute name="topic" type="xsd:boolean" default="false"/>
+
+<!-- ================ Topic Expression Related =================== -->
+
+ <xsd:simpleType name="FullTopicExpression">
+ <xsd:restriction base="xsd:token">
+ <xsd:annotation>
+ <xsd:documentation>
+ TopicPathExpression ::= TopicPath ( '|' TopicPath )*
+ TopicPath ::= RootTopic ChildTopicExpression*
+ RootTopic ::= NamespacePrefix? ('//')? (NCName | '*')
+ NamespacePrefix ::= NCName ':'
+ ChildTopicExpression ::= '/' '/'? (QName | NCName | '*'| '.')
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:pattern value=
+ "([\i-[:]][\c-[:]]*:)?(//)?([\i-[:]][\c-[:]]*|\*)((/|//)(([\i-[:]][\c-[:]]*:)?[\i-[:]][\c-[:]]*|\*|[.]))*(\|([\i-[:]][\c-[:]]*:)?(//)?([\i-[:]][\c-[:]]*|\*)((/|//)(([\i-[:]][\c-[:]]*:)?[\i-[:]][\c-[:]]*|\*|[.]))*)*">
+ </xsd:pattern>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="ConcreteTopicExpression">
+ <xsd:restriction base="xsd:token">
+ <xsd:annotation>
+ <xsd:documentation>
+ The pattern allows strings matching the following EBNF:
+ ConcreteTopicPath ::= RootTopic ChildTopic*
+ RootTopic ::= QName
+ ChildTopic ::= '/' (QName | NCName)
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:pattern value=
+"(([\i-[:]][\c-[:]]*:)?[\i-[:]][\c-[:]]*)(/([\i-[:]][\c-[:]]*:)?[\i-[:]][\c-[:]]*)*" >
+ </xsd:pattern>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="SimpleTopicExpression">
+ <xsd:restriction base="xsd:QName">
+ <xsd:annotation>
+ <xsd:documentation>
+ The pattern allows strings matching the following EBNF:
+ RootTopic ::= QName
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+</xsd:schema> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd
new file mode 100644
index 0000000000..c24e97a9ce
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<xs:schema
+ targetNamespace="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:muws1="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <xs:import namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd"/>
+
+
+ <xs:element name="ResourceId" type="xs:anyURI"/>
+ <xs:element name="ManageabilityCapability" type="xs:anyURI"/>
+
+
+ <xs:complexType name="CorrelatablePropertiesType">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="Dialect" type="xs:anyURI"/>
+ <xs:attribute name="NegativeAssertionPossible" type="xs:boolean"/>
+ <xs:anyAttribute namespace="##other"/>
+ </xs:complexType>
+
+ <xs:element name="CorrelatableProperties"
+ type="muws1:CorrelatablePropertiesType"/>
+
+
+ <xs:complexType name="ComponentAddressType">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ComponentType">
+ <xs:sequence>
+ <xs:element name="ResourceId" type="xs:anyURI"
+ minOccurs="0"/>
+ <xs:element name="ComponentAddress"
+ type="muws1:ComponentAddressType"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other"/>
+ </xs:complexType>
+
+
+ <xs:complexType name="ManagementEventType">
+ <xs:sequence>
+ <xs:element name="EventId" type="xs:anyURI"/>
+ <xs:element name="SourceComponent" type="muws1:ComponentType"/>
+ <xs:element name="ReporterComponent" type="muws1:ComponentType"
+ minOccurs="0"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="ReportTime" type="xs:dateTime" use="optional"/>
+ <xs:anyAttribute namespace="##other"/>
+ </xs:complexType>
+
+ <xs:element name="ManagementEvent"
+ type="muws1:ManagementEventType"/>
+
+ <xs:element name="ManageabilityEndpointReference"
+ type="wsa:EndpointReferenceType"/>
+
+
+<!--
+ SCHEMA COPY Material
+Copy and paste element references below into the schema of a resource properties document.
+These references are provide to insure that the correct minOccurs/maxOccurs attributes are specified in a resource property document schema.
+
+NOTE: You must import the MUWS Part 1 schema namespace (MUWS1).
+
+ ** Identity Properties **
+ <xs:element ref="muws1:ResourceId"/>
+
+
+ ** ManageabilityCharacteristics Properties **
+ <xs:element ref="muws1:ManageabilityCapability"
+ minOccurs="0" maxOccurs="unbounded"/>
+
+ ** Correlatable Properties **
+ <xs:element ref="muws1:CorrelatableProperties"
+ minOccurs="0" maxOccurs="unbounded"/>
+
+-->
+
+</xs:schema>
+
diff --git a/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd
new file mode 100644
index 0000000000..5ea0954734
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd
@@ -0,0 +1,677 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<xs:schema targetNamespace="http://docs.oasis-open.org/wsdm/muws2-2.xsd"
+ xmlns:muws2="http://docs.oasis-open.org/wsdm/muws2-2.xsd"
+ xmlns:muws1="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ xmlns:wsa="http://www.w3.org/2005/08/addressing"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:import namespace="http://docs.oasis-open.org/wsdm/muws1-2.xsd"
+ schemaLocation="WSDM-MUWS-Part1-1_1.xsd" />
+ <xs:import namespace="http://www.w3.org/2005/08/addressing"
+ schemaLocation="WS-Addressing-2005_08.xsd" />
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="XML-Namespace-1998.xsd" />
+ <xs:complexType name="LangString">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="xml:lang" use="required" />
+ <xs:anyAttribute namespace="##other" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <!-- Begin properties for the Description capability -->
+ <xs:element name="Caption" type="muws2:LangString" />
+ <xs:element name="Description" type="muws2:LangString" />
+ <xs:element name="Version" type="xs:string" />
+ <!-- End properties for the Description capability -->
+ <xs:complexType name="CategoryType">
+ <xs:sequence>
+ <xs:any minOccurs="0" namespace="##any"
+ processContents="lax" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="StateType">
+ <xs:complexContent>
+ <xs:extension base="muws2:CategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="State" type="muws2:StateType" />
+ <xs:element name="EnteredState" type="muws2:StateType" />
+ <xs:element name="PreviousState" type="muws2:StateType" />
+ <xs:complexType name="StateTransitionType">
+ <xs:sequence>
+ <xs:element ref="muws2:EnteredState" />
+ <xs:element ref="muws2:PreviousState" minOccurs="0" />
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax" />
+ </xs:sequence>
+ <xs:attribute name="TransitionIdentifier" type="xs:anyURI"
+ use="optional" />
+ <xs:attribute name="Time" type="xs:dateTime" use="required" />
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ <xs:element name="StateTransition" type="muws2:StateTransitionType" />
+ <!-- Begin properties for the OperationalStatus capability -->
+ <xs:element name="OperationalStatus">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Available" />
+ <xs:enumeration value="PartiallyAvailable" />
+ <xs:enumeration value="Unavailable" />
+ <xs:enumeration value="Unknown" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <!-- End properties for the OperationalStatus capability -->
+ <xs:attributeGroup name="MetricAttributes">
+ <xs:attribute name="ResetAt" type="xs:dateTime" />
+ <xs:attribute name="LastUpdated" type="xs:dateTime" />
+ <xs:attribute name="Duration" type="xs:duration" />
+ </xs:attributeGroup>
+ <!-- Begin properties for the Metrics capability -->
+ <xs:element name="CurrentTime" type="xs:dateTime" />
+ <!-- End properties for the Metrics capability -->
+ <xs:complexType name="RelationshipTypeType">
+ <xs:complexContent>
+ <xs:extension base="muws2:CategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Self">
+ <xs:complexType />
+ </xs:element>
+ <xs:complexType name="RelationshipParticipantType">
+ <xs:sequence>
+ <xs:element ref="muws2:Self" minOccurs="0" />
+ <xs:element ref="muws1:ManageabilityEndpointReference"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xs:element ref="wsa:EndpointReference" minOccurs="0"
+ maxOccurs="unbounded" />
+ <xs:element ref="muws1:ResourceId" minOccurs="0" />
+ <xs:element name="Role" type="xs:anyURI" />
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ <!-- Begin properties for the RelationshipResource capability -->
+ <xs:element name="Name" type="xs:string" />
+ <xs:element name="Type" type="muws2:RelationshipTypeType" />
+ <xs:element name="Participant"
+ type="muws2:RelationshipParticipantType" />
+ <!-- End properties for the RelationshipResource capability -->
+ <xs:complexType name="RelationshipType">
+ <xs:sequence>
+ <xs:element ref="muws2:Name" minOccurs="0" />
+ <xs:element ref="muws2:Type" />
+ <xs:element ref="muws2:Participant" minOccurs="2"
+ maxOccurs="unbounded" />
+ <xs:element name="AccessEndpointReference"
+ type="wsa:EndpointReferenceType" minOccurs="0" />
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ <!-- Begin properties for the Relationship capability -->
+ <xs:element name="Relationship" type="muws2:RelationshipType" />
+ <!-- End properties for the Relationship capability -->
+ <xs:element name="RelationshipCreatedNotification">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="muws2:Relationship" />
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RelationshipDeletedNotification">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="muws2:Relationship" />
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="QueryRelationshipsByType">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="RequestedType" type="xs:QName" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="QueryRelationshipsByTypeResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="muws2:Relationship" minOccurs="0"
+ maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CreationNotification">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="muws1:ManageabilityEndpointReference"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DestructionNotification">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="muws1:ResourceId" minOccurs="0" />
+ </xs:sequence>
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ </xs:element>
+ <xs:complexType name="SituationCategoryType">
+ <xs:complexContent>
+ <xs:extension base="muws2:CategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="SubstitutableMsgType">
+ <xs:sequence>
+ <xs:element name="Value" type="xs:anySimpleType"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="MsgId" type="xs:string" use="required" />
+ <xs:attribute name="MsgIdType" type="xs:anyURI" use="required" />
+ </xs:complexType>
+ <xs:complexType name="SituationType">
+ <xs:sequence>
+ <xs:element name="SituationCategory"
+ type="muws2:SituationCategoryType" />
+ <xs:element name="SuccessDisposition" minOccurs="0">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Successful" />
+ <xs:enumeration value="Unsuccessful" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="SituationTime" type="xs:dateTime" />
+ <xs:element name="Priority" type="xs:short" minOccurs="0" />
+ <xs:element name="Severity" type="xs:short" minOccurs="0" />
+ <xs:element name="Message" type="muws2:LangString"
+ minOccurs="0" />
+ <xs:element name="SubstitutableMsg"
+ type="muws2:SubstitutableMsgType" minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="Situation" type="muws2:SituationType" />
+ <xs:complexType name="EventCorrelationPropertiesType">
+ <xs:sequence>
+ <xs:element name="repeatCount" minOccurs="0"
+ maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:short">
+ <xs:minInclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="elapsedTime" minOccurs="0"
+ maxOccurs="1">
+ <xs:simpleType>
+ <xs:restriction base="xs:long">
+ <xs:minInclusive value="0" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="sequenceNumber" type="xs:unsignedLong" />
+ </xs:complexType>
+ <xs:element name="EventCorrelationProperties"
+ type="muws2:EventCorrelationPropertiesType" />
+ <xs:complexType name="MsgCatalogInformationType">
+ <xs:sequence>
+ <xs:element name="msgCatalog" type="xs:anyURI"
+ minOccurs="1" />
+ <xs:element name="msgCatalogType" type="xs:anyURI"
+ minOccurs="0" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="MsgCatalogInformation"
+ type="muws2:MsgCatalogInformationType" />
+ <!-- ##### Metadata description elements ##### -->
+ <xs:element name="Capability" type="xs:anyURI" />
+ <xs:complexType name="DialectableExpressionType" mixed="true">
+ <xs:sequence>
+ <xs:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ <xs:attribute name="Dialect" type="xs:anyURI" use="required" />
+ <xs:anyAttribute namespace="##other" />
+ </xs:complexType>
+ <xs:element name="ValidWhile"
+ type="muws2:DialectableExpressionType" />
+ <xs:element name="Units" type="xs:string" />
+ <xs:element name="ChangeType">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Counter" />
+ <xs:enumeration value="Gauge" />
+ <xs:enumeration value="Unknown" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="TimeScope">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="Interval" />
+ <xs:enumeration value="PointInTime" />
+ <xs:enumeration value="SinceReset" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="GatheringTime">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="OnChange" />
+ <xs:enumeration value="Periodic" />
+ <xs:enumeration value="OnDemand" />
+ <xs:enumeration value="Unknown" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:element>
+ <xs:element name="CalculationInterval" type="xs:duration" />
+ <xs:element name="MetricGroup" type="xs:anyURI" />
+ <xs:element name="PostCondition"
+ type="muws2:DialectableExpressionType" />
+ <!-- ========= StartSituation ============ -->
+ <xs:element name="StartSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="StartInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StartSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RestartInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StartSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="StartCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StartSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= StopSituation ============ -->
+ <xs:element name="StopSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="StopInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StopSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="AbortInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StopSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PauseInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StopSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="StopCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:StopSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= RequestSituation ============ -->
+ <xs:element name="RequestSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequestInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:RequestSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="RequestCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:RequestSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= DestroySituation ============ -->
+ <xs:element name="DestroySituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DestroyInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:DestroySituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DestroyCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:DestroySituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= CreateSituation ============ -->
+ <xs:element name="CreateSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CreateInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:CreateSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="CreateCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:CreateSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= ConnectSituation ============ -->
+ <xs:element name="ConnectSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ConnectInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ConnectSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ReconnectInitiated">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ConnectSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ConnectCompleted">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ConnectSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= ReportSituation ============ -->
+ <xs:element name="ReportSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="PerformanceReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="SecurityReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="HeartbeatReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="StatusReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="TraceReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="DebugReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="LogReport">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType">
+ <xs:sequence>
+ <xs:element ref="muws2:ReportSituation" />
+ </xs:sequence>
+ </xs:restriction>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= AvailabilitySituation ============ -->
+ <xs:element name="AvailabilitySituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= CapabilitySituation ============ -->
+ <xs:element name="CapabilitySituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= ConfigureSituation ============ -->
+ <xs:element name="ConfigureSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!-- ========= OtherSituation ============ -->
+ <xs:element name="OtherSituation">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:restriction base="muws2:SituationCategoryType" />
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <!--
+ SCHEMA COPY Material
+ Copy and paste element references below into the schema of a resource properties document.
+ These references insure that the correct minOccurs/maxOccurs attributes are specified in a resource property document schema.
+
+ NOTE: You must import the MUWS Part 2 schema namespace (MUWS2).
+
+ ** Description Properties **
+ <xs:element ref="muws2:Caption"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="muws2:Description"
+ minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="muws2:Version"
+ minOccurs="0"/>
+
+ ** Operational Status **
+ <xs:element ref="muws2:OperationalStatus"/>
+
+ ** Metrics **
+ <xs:element ref="muws2:CurrentTime"/>
+
+ ** Relationship **
+ <xs:element ref="muws2:Relationship"
+ minOccurs="0" maxOccurs="unbounded"/>
+
+ ** Relationship Resource **
+ <xs:element ref="muws2:Name" minOccurs="0"/>
+ <xs:element ref="muws2:Type"/>
+ <xs:element ref="muws2:Participant"
+ minOccurs="2" maxOccurs="unbounded"/>
+
+ -->
+</xs:schema>
diff --git a/java/management/client/src/main/java/wsdl/WsResource.rmd b/java/management/client/src/main/java/wsdl/WsResource.rmd
new file mode 100644
index 0000000000..b15f7eca1c
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WsResource.rmd
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<Definitions xmlns="http://docs.oasis-open.org/wsrf/rmd-1" >
+
+ <MetadataDescriptor xmlns:wsrl="http://docs.oasis-open.org/wsrf/rl-2"
+ xmlns:qman="http://amqp.apache.org/qpid/management/qman" name="QManWsResourceMetadata"
+ interface="qman:QManWsResourcePortType"
+ wsdlLocation="http://ws.apache.org/muse/test/wsrf QManWsResource.wsdl" >
+
+ <Property name="wsrl:CurrentTime" modifiability="read-only" mutability="mutable" />
+
+ <Property name="wsrl:TerminationTime" modifiability="read-only" mutability="mutable" />
+ </MetadataDescriptor>
+
+</Definitions> \ No newline at end of file
diff --git a/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl b/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl
new file mode 100644
index 0000000000..83a7e5ad8c
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ targetNamespace="http://ws.apache.org/muse/test/wsrf"
+ xmlns:tns="http://ws.apache.org/muse/test/wsrf"
+ xmlns="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdl-soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ name="WsResourceFactory">
+ <wsdl:types>
+ </wsdl:types>
+ <wsdl:portType name="WsResourceFactoryPortType" >
+ </wsdl:portType>
+ <wsdl:binding name="WsResourceFactoryBinding" type="tns:WsResourceFactoryPortType">
+ <wsdl-soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ </wsdl:binding>
+ <wsdl:service name="WsResourceFactoryService">
+ <wsdl:port name="WsResourceFactoryPort" binding="tns:WsResourceFactoryBinding">
+ <wsdl-soap:address location="http://romagazzarini:8080/wsrf/services/WsResourceFactory"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
diff --git a/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd b/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd
new file mode 100644
index 0000000000..f51b67f78f
--- /dev/null
+++ b/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd
@@ -0,0 +1,46 @@
+<?xml version='1.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.
+
+-->
+
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
+
+ <xs:attribute name="lang" type="xs:language">
+ </xs:attribute>
+
+ <xs:attribute name="space" default="preserve">
+ <xs:simpleType>
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI">
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ </xs:attributeGroup>
+
+</xs:schema>
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java b/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java
new file mode 100644
index 0000000000..9abcd08eef
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Collects all literal constants used in test cases.
+ */
+public interface TestConstants
+{
+ UUID BROKER_ID = UUID.randomUUID();
+ Binary OBJECT_ID = new Binary(new byte []{1,2,3,2,1,1,2,3});
+
+ DomainModel DOMAIN_MODEL = new DomainModel(BROKER_ID);
+
+ String AGE_ATTRIBUTE_NAME = "age";
+ String AGE_ATTRIBUTE_DESCRIPTION = "The age of a person.";
+ String SURNAME_ATTRIBUTE_NAME = "surname";
+ String SURNAME_ATTRIBUTE_DESCRIPTION = "The surname of a person.";
+ Integer _1 = new Integer(1);
+
+ byte [] TEST_RAW_DATA= new byte []{1,4,5,7,8,9,4,44};
+ long NOW = System.currentTimeMillis();
+ int SEVERITY = _1;
+
+ String QPID_PACKAGE_NAME = "qpid";
+ String EXCHANGE_CLASS_NAME = "exchange";
+ String BIND_EVENT_NAME = "bind";
+ Binary HASH = new Binary(new byte []{1,2,3,4,5,6,7,8,9});
+ int VALID_CODE = _1;
+
+ List<Map<String, Object>> EMPTY_PROPERTIES_SCHEMA = new LinkedList<Map<String,Object>>();
+ List<Map<String, Object>> EMPTY_STATISTICS_SCHEMA = new LinkedList<Map<String,Object>>();
+ List<MethodOrEventDataTransferObject> EMPTY_METHODS_SCHEMA = new LinkedList<MethodOrEventDataTransferObject>();
+ List<Map<String, Object>> EMPTY_ARGUMENTS_SCHEMA = new LinkedList<Map<String,Object>>();
+ int _0 = 0;
+ int SAMPLE_ACCESS_CODE = 1;
+ String YEARS = "years";
+ int SAMPLE_MIN_VALUE = 1;
+ int SAMPLE_MAX_VALUE = 120;
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java
new file mode 100644
index 0000000000..72bd45f70f
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java
@@ -0,0 +1,181 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.Map;
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.TestConstants;
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler;
+
+/**
+ * Test case for Configuration singleton.
+ */
+public class ConfigurationTest extends TestCase
+{
+ /**
+ * Tests the singleton behaviour of the configuration object.
+ */
+ public void testSingleton()
+ {
+ assertSame(Configuration.getInstance(),Configuration.getInstance());
+ }
+
+ /**
+ * Tests the execution of getType() method when a unknown code is supplied.
+ *
+ * <br>precondition : the requested type doesn't exist on the configuration.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testGetTypeKO()
+ {
+ try
+ {
+ Configuration.getInstance().getType(TestConstants.VALID_CODE*10001);
+ fail("If an unknwon code is supplied an exception must be thrown.");
+ } catch (UnknownTypeCodeException expected)
+ {
+ assertEquals(TestConstants.VALID_CODE*10001,expected.getCode());
+ }
+ }
+
+ /**
+ * Tests the execution of getAccessMode() method when a unknown code is supplied.
+ *
+ * <br>precondition : the requested access mode doesn't exist on the configuration.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testGetAccessModeKO()
+ {
+ try
+ {
+ Configuration.getInstance().getAccessMode(TestConstants.VALID_CODE*1528);
+ fail("If an unknwon code is supplied an exception must be thrown.");
+ } catch (UnknownAccessCodeException expected)
+ {
+ assertEquals(TestConstants.VALID_CODE*1528,expected.getCode());
+ }
+ }
+
+ /**
+ * Tests the execution of the getBrokerConnectionData when a valid broker id is supplied.
+ *
+ * <br>precondition : on configuration a connection data is stored and associated with the supplied id.
+ * <br>postcondition : the requested connection data is returned and no exception is thrown.
+ */
+ public void testGetBrokerConnectionDataOK() throws Exception
+ {
+ BrokerConnectionData connectionData = new BrokerConnectionData();
+ connectionData.setHost("host");
+ connectionData.setPort("7001");
+ connectionData.setInitialPoolCapacity("0");
+ connectionData.setMaxPoolCapacity("10");
+ connectionData.setMaxWaitTimeout("1");
+ Configuration.getInstance().addBrokerConnectionData(TestConstants.BROKER_ID, connectionData);
+
+ BrokerConnectionData result = Configuration.getInstance().getBrokerConnectionData(TestConstants.BROKER_ID);
+ assertSame(connectionData, result);
+ }
+
+ /**
+ * Tests the execution of the getBrokerConnectionData when a unknown broker id is supplied.
+ *
+ * <br>precondition : on configuration there's no connection data associated with the supplied id.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testGetBrokerConnectionDataKO_withUnknownBrokerId()
+ {
+ UUID brokerId = UUID.randomUUID();
+ try
+ {
+ Configuration.getInstance().getBrokerConnectionData(brokerId);
+ fail("If an unknown broker id is supplied then an exception must be thrown.");
+ } catch(UnknownBrokerException expected)
+ {
+ assertEquals(brokerId.toString(),expected.getMessage());
+ }
+ }
+
+ /**
+ * Tests the execution of the getBrokerConnectionData when a null id is supplied.
+ *
+ * <br>precondition : a null broker is given.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testGetBrokerConnectionDataKO_withNullBrokerId()
+ {
+ try
+ {
+ Configuration.getInstance().getBrokerConnectionData(null);
+ fail("If a null broker id is supplied then an exception must be thrown.");
+ } catch(UnknownBrokerException expected)
+ {
+ }
+ }
+
+ /**
+ * Tests the behaviour of the getManagementQueueHandlers() method.
+ *
+ * <br>precondition: 2 management handlers are in stored configuration
+ * <br>postcondition : 2 management handlers are returned.
+ */
+ public void testGetManagementQueueHandlersOk()
+ {
+ IMessageHandler instrMessageHandler = new InstrumentationMessageHandler();
+ IMessageHandler configMessageHandler = new ConfigurationMessageHandler();
+
+ MessageHandlerMapping instrMapping = new MessageHandlerMapping('i',instrMessageHandler);
+ MessageHandlerMapping configMapping = new MessageHandlerMapping('c',configMessageHandler);
+
+ Configuration.getInstance().addManagementMessageHandlerMapping(instrMapping);
+ Configuration.getInstance().addManagementMessageHandlerMapping(configMapping);
+
+ Map<Character, IMessageHandler> handlerMappings = Configuration.getInstance().getManagementQueueHandlers();
+
+ assertEquals(2,handlerMappings.size());
+ assertEquals(instrMessageHandler,handlerMappings.get(instrMapping.getOpcode()));
+ assertEquals(configMessageHandler,handlerMappings.get(configMapping.getOpcode()));
+ }
+
+ /**
+ * Tests the behaviour of the getManagementQueueHandlers() method.
+ *
+ * <br>precondition: 2 management handlers are in stored configuration
+ * <br>postcondition : 2 management handlers are returned.
+ */
+ public void testGetMethodReplyQueueHandlersOk()
+ {
+ IMessageHandler schemaMessageHandler = new SchemaResponseMessageHandler();
+
+ MessageHandlerMapping schemaMapping = new MessageHandlerMapping('s',schemaMessageHandler);
+
+ Configuration.getInstance().addMethodReplyMessageHandlerMapping(schemaMapping);
+
+ Map<Character, IMessageHandler> handlerMappings = Configuration.getInstance().getMethodReplyQueueHandlers();
+
+ assertEquals(schemaMessageHandler,handlerMappings.get(schemaMapping.getOpcode()));
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java
new file mode 100644
index 0000000000..1e464bf6ae
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java
@@ -0,0 +1,163 @@
+/*
+ *
+ * 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 org.apache.qpid.management.configuration;
+
+import java.util.Map;
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.HeartBeatIndicationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler;
+import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler;
+import org.apache.qpid.management.domain.model.AccessMode;
+import org.apache.qpid.management.domain.model.type.AbsTime;
+import org.apache.qpid.management.domain.model.type.DeltaTime;
+import org.apache.qpid.management.domain.model.type.ObjectReference;
+import org.apache.qpid.management.domain.model.type.Str16;
+import org.apache.qpid.management.domain.model.type.Str8;
+import org.apache.qpid.management.domain.model.type.Uint16;
+import org.apache.qpid.management.domain.model.type.Uint32;
+import org.apache.qpid.management.domain.model.type.Uint64;
+import org.apache.qpid.management.domain.model.type.Uint8;
+import org.xml.sax.SAXException;
+
+/**
+ * Test case for configurator.
+ *
+ * @author Andrea Gazzarini
+ *
+ */
+public class ConfiguratorTest extends TestCase
+{
+ /**
+ * Tests the execution of the configure() method when no configuration file is given.
+ *
+ * <br>precondition : configuration file option is not set
+ * <br>postcondition : no exception is thrown, the configuration is holding no broker data and the predefined mappings are
+ * stored in configuration.
+ */
+ public void testConfigureOK_WithNoConfigurationFile() throws Exception
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ Configuration configuration = Configuration.getInstance();
+
+ assertEquals(new Uint8(), configuration.getType(1));
+ assertEquals(new Uint16(), configuration.getType(2));
+ assertEquals(new Uint32(), configuration.getType(3));
+ assertEquals(new Uint64(), configuration.getType(4));
+ assertEquals(new Str8(), configuration.getType(6));
+ assertEquals(new Str16(), configuration.getType(7));
+ assertEquals(new AbsTime(), configuration.getType(8));
+ assertEquals(new DeltaTime(), configuration.getType(9));
+ assertEquals(new ObjectReference(), configuration.getType(10));
+ assertEquals(new org.apache.qpid.management.domain.model.type.Boolean(), configuration.getType(11));
+ assertEquals(new org.apache.qpid.management.domain.model.type.Uuid(), configuration.getType(14));
+ assertEquals(new org.apache.qpid.management.domain.model.type.Map(), configuration.getType(15));
+
+ assertEquals(AccessMode.RC,configuration.getAccessMode(1));
+ assertEquals(AccessMode.RW,configuration.getAccessMode(2));
+ assertEquals(AccessMode.RO,configuration.getAccessMode(3));
+
+ Map<Character, IMessageHandler> managementHandlers = configuration.getManagementQueueHandlers();
+ assertEquals(4,managementHandlers.size());
+ assertEquals(
+ InstrumentationMessageHandler.class,
+ managementHandlers.get(Protocol.INSTRUMENTATION_CONTENT_RESPONSE_OPCODE).getClass());
+
+ assertEquals(
+ ConfigurationMessageHandler.class,
+ managementHandlers.get(Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE).getClass());
+
+ assertEquals(
+ EventContentMessageHandler.class,
+ managementHandlers.get(Protocol.EVENT_CONTENT_RESPONSE_OPCDE).getClass());
+
+ assertEquals(
+ HeartBeatIndicationMessageHandler.class,
+ managementHandlers.get(Protocol.HEARTBEAT_INDICATION_RESPONSE_OPCODE).getClass());
+
+ Map<Character, IMessageHandler> methodReplyHandlers = configuration.getMethodReplyQueueHandlers();
+ assertEquals(2, methodReplyHandlers.size());
+
+ assertEquals(
+ MethodResponseMessageHandler.class,
+ methodReplyHandlers.get(Protocol.OPERATION_INVOCATION_RESPONSE_OPCODE).getClass());
+
+ assertEquals(
+ SchemaResponseMessageHandler.class,
+ methodReplyHandlers.get(Protocol.SCHEMA_RESPONSE_OPCODE).getClass());
+ }
+
+ /**
+ * Tests the changes of the configurator internal state while configuration file is parsed.
+ *
+ * <br>precondition: N.A.
+ * <br>postcondition: N.A.
+ */
+ public void testDirectorParsing() throws SAXException{
+ Configurator configurator = new Configurator();
+
+ assertSame(Configurator.DEFAULT_PARSER,configurator._currentParser);
+
+ configurator.startElement(null, null, Tag.BROKERS.toString(), null);
+ assertSame(configurator._brokerConfigurationParser,configurator._currentParser);
+ }
+
+ /**
+ * It's not possibile to add twice the same broker connection data.
+ * Is so an exception must be thrown indicating that the given broker is already connected.
+ *
+ * <br>precondition : the given data identifies an already connected broker.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testAddTwoIdenticalBrokers() throws ConfigurationException, BrokerConnectionException
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+
+ BrokerConnectionData data = new BrokerConnectionData("sofia.gazzax.com",5672,"virtualHost","user","pwd",1,4,-1);
+
+ Configuration.getInstance()._brokerConnectionInfos.put(UUID.randomUUID(),data);
+
+ try {
+ configurator.createAndReturnBrokerConnectionData(
+ UUID.randomUUID(),
+ data.getHost(),
+ data.getPort(),
+ "anotherUser",
+ "anotherPassword",
+ data.getVirtualHost(),
+ 33,
+ 12,
+ 1000);
+ fail("If a broker is added twice an exception must be thrown.");
+ } catch (BrokerAlreadyConnectedException expected) {
+ assertEquals(data,expected.getBrokerConnectionData());
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java
new file mode 100644
index 0000000000..af261024bd
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.configuration;
+
+import java.util.UUID;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.TestConstants;
+
+/**
+ * Test case for mapping parsers.
+ *
+ * @author Andrea Gazzarini.
+ */
+public class MappingParsersTest extends TestCase
+{
+ /**
+ * Tests the execution of the broker connection data mapping parser.
+ *
+ * <br>precondition: A broker connection datamapping is built by the parser;
+ * <br>postcondition: the corresponding connection data is available on the configuration.
+ */
+ public void testBrokerConnectionDataParser() throws UnknownBrokerException
+ {
+ String host = "127.0.0.1";
+ String port = "7001";
+ String virtualHost = "test";
+ String username = "username_guest";
+ String password ="password_guest";
+
+ BrokerConnectionDataParser parser = new BrokerConnectionDataParser()
+ {
+ @Override
+ UUID getUUId ()
+ {
+ return TestConstants.BROKER_ID;
+ }
+ };
+
+ parser.setCurrrentAttributeValue(host);
+ parser.setCurrentAttributeName(Tag.HOST.toString());
+ parser.setCurrrentAttributeValue(port);
+ parser.setCurrentAttributeName(Tag.PORT.toString());
+ parser.setCurrrentAttributeValue(virtualHost);
+ parser.setCurrentAttributeName(Tag.VIRTUAL_HOST.toString());
+ parser.setCurrrentAttributeValue(username);
+ parser.setCurrentAttributeName(Tag.USER.toString());
+ parser.setCurrrentAttributeValue(password);
+ parser.setCurrentAttributeName(Tag.PASSWORD.toString());
+ parser.setCurrentAttributeName(Tag.BROKER.toString());
+
+ BrokerConnectionData result = Configuration.getInstance().getBrokerConnectionData(TestConstants.BROKER_ID);
+
+ assertEquals(host,result.getHost());
+ assertEquals(Integer.parseInt(port),result.getPort());
+ assertEquals(virtualHost,result.getVirtualHost());
+ assertEquals(username,result.getUsername());
+ assertEquals(password,result.getPassword());
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java
new file mode 100644
index 0000000000..d6b51b64fc
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.handler.base;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.domain.model.type.Binary;
+
+/**
+ * Test case for Content indication message handler (base class).
+ *
+ * @author Andrea Gazzarini
+ */
+public class ContentIndicationMessageHandlerTest extends TestCase
+{
+ /**
+ * Tests the behaviour of the objectHasBeenRemoved method().
+ */
+ public void testObjectHasBeenRemoved()
+ {
+ ContentIndicationMessageHandler mockHandler = new ContentIndicationMessageHandler()
+ {
+ @Override
+ protected void updateDomainModel (String packageName, String className, Binary classHash, Binary objectId,
+ long timeStampOfCurrentSample, long timeObjectWasCreated, long timeObjectWasDeleted, byte[] contentData)
+ {
+ }
+ };
+
+ long deletionTimestamp = 0;
+ long now = System.currentTimeMillis();
+
+ assertFalse(mockHandler.objectHasBeenRemoved(deletionTimestamp, now));
+
+ deletionTimestamp = now + 1000;
+ assertFalse(mockHandler.objectHasBeenRemoved(deletionTimestamp, now));
+
+ deletionTimestamp = now - 1000;
+ assertTrue(mockHandler.objectHasBeenRemoved(deletionTimestamp, now));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java
new file mode 100644
index 0000000000..c528392a93
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import org.apache.qpid.management.configuration.Configurator;
+
+import junit.framework.TestCase;
+
+/**
+ * Layer supertype for all domain model related test cases.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class BaseDomainModelTestCase extends TestCase
+{
+ /**
+ * Set up fixture for this test case.
+ * In order to execute tests on domain model we need to build the configuration.
+ */
+ @Override
+ protected void setUp () throws Exception
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java
new file mode 100644
index 0000000000..3d3783eb04
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.desc;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.name;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute;
+
+/**
+ * Layer supertype for feature builder test cases.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class BaseQpidFeatureBuilderTestCase extends TestCase
+{
+ protected final static String NAME = "aName";
+
+ protected final static String DESCRIPTION = "A description.";
+
+ protected Map <String,Object> _featureDefinition;
+ protected QpidFeatureBuilder _builder;
+
+ /**
+ * Set up fixture for all concrete builder test cases.
+ */
+ @Override
+ protected void setUp () throws Exception
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ _featureDefinition = new HashMap<String, Object>();
+ _featureDefinition.put(name.name(),NAME);
+ _featureDefinition.put(desc.name(), DESCRIPTION);
+ }
+
+ // Internal test used to avoid code duplication.
+ protected void internalTestForMissingMandatoryAttribute(Attribute ...toBeRemoved)
+ {
+ try
+ {
+ for (Attribute attribute : toBeRemoved)
+ {
+ _featureDefinition.remove(attribute.name());
+ }
+ _builder.build();
+ fail("If a mandatory attribute is missing an exception must be thrown!");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertTrue(expected instanceof MissingFeatureAttributesException);
+ for (Attribute attribute : toBeRemoved)
+ {
+ assertTrue(expected.getMessage().contains(attribute.name()));
+ }
+ }
+ }
+
+ // Internal test used to avoid code duplication.
+ protected void internalTestForMissingOptionalAttribute(Attribute ...toBeRemoved) throws UnableToBuildFeatureException
+ {
+ for (Attribute attribute : toBeRemoved)
+ {
+ _featureDefinition.remove(attribute.name());
+ }
+ _builder.build();
+
+ assertNotNull(_builder.getQpidFeature());
+ assertNotNull(_builder.getManagementFeature());
+ }
+
+
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java
new file mode 100644
index 0000000000..578fa36bc7
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.UUID;
+
+import org.apache.qpid.management.TestConstants;
+
+/**
+ * Test case for domain model entity.
+ *
+ * @author Andrea Gazzarini
+ */
+public class DomainModelTest extends BaseDomainModelTestCase
+{
+ private DomainModel _model;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ _model = new DomainModel(UUID.randomUUID());
+ }
+
+ /**
+ * Tests the execution of the getPackage() method.
+ */
+ public void testGetPackage()
+ {
+ assertFalse(_model.containsPackage(TestConstants.QPID_PACKAGE_NAME));
+
+ QpidPackage qpidPackage = _model.getPackageByName(TestConstants.QPID_PACKAGE_NAME);
+ assertEquals(TestConstants.QPID_PACKAGE_NAME,qpidPackage.getName());
+
+ QpidPackage theSameAsPreviousOne = _model.getPackageByName(TestConstants.QPID_PACKAGE_NAME);
+ assertSame(qpidPackage, theSameAsPreviousOne);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java
new file mode 100644
index 0000000000..553c1c21de
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java
@@ -0,0 +1,187 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.domain.model.type.Uint64;
+import org.apache.qpid.transport.codec.BBDecoder;
+
+public class OptionalPropertiesTest extends TestCase
+{
+ public void testDecoderStateChange()
+ {
+ QpidProperty property = new QpidProperty();
+ assertSame(
+ "Default decoder for properties is the one for mandatory properties.",
+ property._mandatoryPropertyDecoder,
+ property._decoder);
+
+ property.markAsOptional(1);
+ assertSame(
+ "After a property has been marked as optional the corresponding decoder must be installed.",
+ property._optionalPropertyDecoder,
+ property._decoder);
+ }
+
+ /**
+ * Tests the execution of the decode() method when the current property is optional but in the presence bitmask
+ * there's no the corresponding bit set.
+ *
+ * <br>precondition : property is optional and corresponding presence bit is not set.
+ * <br>postcondition : result must be null.
+ */
+ public void testDecodeValueWithOptionalPropertyAndMissingValue()
+ {
+ byte [] presenceBytes = {2};
+
+ QpidProperty property = new QpidProperty();
+
+ // We don't need a decoder so in order to be sure that it won't be invoked set it to null.
+ BBDecoder nullDecoder = null;
+
+ for (int i = 0; i < 8; i++)
+ {
+ // Property number 1 is declaring a value so skip it!
+ if (i != 1)
+ {
+ property.markAsOptional(i);
+ assertNull(property.decodeValue(nullDecoder, presenceBytes));
+ }
+ }
+ }
+
+ /**
+ * Tests the execution of the decode() method when the current property is optional but in the presence bitmask
+ * there's no the corresponding bit set.
+ *
+ * <br>precondition : property is optional and corresponding presence bit is not set.
+ * <br>postcondition : result must be null.
+ */
+ public void testDecodeValueWithOptionalPropertyAndDeclaredValue()
+ {
+ byte [] presenceBytes = {4};
+ Long _44 = new Long(44);
+
+ QpidProperty property = new QpidProperty();
+ property.setType(new Uint64());
+ property.markAsOptional(2);
+
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ buffer.putLong(_44);
+ buffer.rewind();
+ BBDecoder decoder = new BBDecoder();
+
+ decoder.init(buffer);
+ assertEquals(_44,property.decodeValue(decoder, presenceBytes));
+ }
+
+ /**
+ * Tests the execution of the decode() method with a real scenario where there are mandatory and optional
+ * properties.
+ */
+ public void testDecodeValueWithOptionalAndMandatoryProperties()
+ {
+ // With this bitset :
+ //
+ // 1th opt property is null;
+ // 2th opt property is null;
+ // 3th opt property is not null;
+ // 4th opt property is null;
+ // 5th opt propertyis null;
+ // 6th opt property is null;
+ // 7th opt property is null;
+ // 8th opt property is not null;
+ byte [] presenceBytes = {4,1};
+
+ List<QpidProperty> properties = new LinkedList<QpidProperty>();
+
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(true, 0));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(true, 1));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(true, 2));
+ properties.add(createProperty(true, 3));
+ properties.add(createProperty(true, 4));
+ properties.add(createProperty(true, 5));
+ properties.add(createProperty(true, 6));
+ properties.add(createProperty(true, 7));
+ properties.add(createProperty(false, -1));
+ properties.add(createProperty(true, 8));
+
+ Long expectedResults [] = {
+ 1L, // p1
+ 22L, // p2
+ null, // p3
+ 232L, // p4
+ 211L, // p5
+ null, // p6
+ 232L, // p7
+ 211L, // p8
+ 999L, // p9
+ null, // p10
+ null, // p11
+ null, // p12
+ null, // p13
+ null, // p14
+ 626L, // p15
+ 969L // p16
+ };
+
+
+ ByteBuffer buffer = ByteBuffer.allocate(expectedResults.length * 8);
+ for (Long expected : expectedResults)
+ {
+ if (expected != null)
+ {
+ buffer.putLong(expected);
+ }
+ }
+ buffer.rewind();
+ BBDecoder decoder = new BBDecoder();
+
+ decoder.init(buffer);
+ int index = 0;
+ for (QpidProperty property : properties)
+ {
+ assertEquals(expectedResults[index++],property.decodeValue(decoder, presenceBytes));
+ }
+ }
+
+ private QpidProperty createProperty(boolean isOptional, int optionalIndex)
+ {
+ QpidProperty property = new QpidProperty();
+ property.setType(new Uint64());
+ if (isOptional)
+ {
+ property.markAsOptional(optionalIndex);
+ }
+ return property;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java
new file mode 100644
index 0000000000..9d6e176912
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java
@@ -0,0 +1,408 @@
+/*
+*
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.TestConstants;
+import org.apache.qpid.management.configuration.ConfigurationException;
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.QpidClass.QManManagedObject;
+
+/**
+ * Test case for Qpid Class.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidClassTest extends TestCase
+{
+ private QpidClass _class;
+ private QpidPackage _package;
+
+ @Override
+ protected void setUp () throws ConfigurationException
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ _package = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL);
+ _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package);
+ }
+
+ /**
+ * Tests the execution of the getObjectInstance() method.
+ * Basically it tests the addition of a new object instance.
+ *
+ * <br>precondition: class has no object instances.
+ * <br>precondition : class contains the added object instance.
+ */
+ public void testGetObjectInstance()
+ {
+ assertFalse (
+ "Nobody set instance #"+TestConstants.OBJECT_ID+" into this class so why is it there?",
+ _class._objectInstances.containsKey(TestConstants.OBJECT_ID));
+
+ QManManagedObject instance = _class.getObjectInstance(TestConstants.OBJECT_ID, false);
+
+ assertTrue (
+ "Now the instance #"+TestConstants.OBJECT_ID+" should be there...",
+ _class._objectInstances.containsKey(TestConstants.OBJECT_ID));
+
+ assertEquals(instance,_class.getObjectInstance(TestConstants.OBJECT_ID, false));
+ }
+
+ /**
+ * Tests the injection of instrumentation and configuration data (related to a specific object instance) before the
+ * schema is installed.
+ *
+ * <br>precondition : the schema hasn't yet installed on this class.
+ * <br>postcondition : incoming configuration & instrumentation data is stored into the corresponding object instance.
+ */
+ public void testAddInstrumentationAndConfigurationDataBeforeSchemaInstallation()
+ {
+ _class._state = _class._schemaRequestedButNotYetInjected;
+ QManManagedObject objectInstance = _class.getObjectInstance(TestConstants.OBJECT_ID,false);
+
+ assertTrue(
+ "This object instance is a new one so how is it possible that it has already instrumentation data? ",
+ objectInstance._rawInstrumentationData.isEmpty());
+ assertTrue(
+ "This object instance is a new one so how is it possible that it has already configuration data? ",
+ objectInstance._rawConfigurationData.isEmpty());
+
+ byte [] dummyConfigurationData = {1,2,3,4,5,6,7,8};
+ byte [] dummyInstrumentationData = {11,21,31,41,51,61,71,81};
+
+ _class.addConfigurationData(TestConstants.OBJECT_ID, dummyConfigurationData);
+ _class.addInstrumentationData(TestConstants.OBJECT_ID, dummyInstrumentationData);
+
+ assertEquals("Now configuration data should be there...",1,objectInstance._rawConfigurationData.size());
+ assertEquals("Now instrumentation data should be there...",1,objectInstance._rawInstrumentationData.size());
+
+ assertTrue(
+ "Object instance configuration data should be the previously set...",
+ Arrays.equals(objectInstance._rawConfigurationData.get(0),
+ dummyConfigurationData));
+
+ assertTrue(
+ "Object instance instrumentation data should be the previously set...",
+ Arrays.equals(objectInstance._rawInstrumentationData.get(0),
+ dummyInstrumentationData));
+ }
+
+ /**
+ * Tests the internal state change of a class definition.
+ */
+ public void testStateChange() throws UnableToBuildFeatureException
+ {
+ _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ _state = _schemaRequestedButNotYetInjected;
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException {
+ _state = _schemaInjected;
+ }
+ };
+
+ assertSame(
+ "Initial state doesn't match.",
+ _class._schemaNotRequested,
+ _class._state);
+
+ _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA);
+ _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _class._schemaRequestedButNotYetInjected,
+ _class._state);
+
+ _class.setSchema(
+ TestConstants.EMPTY_PROPERTIES_SCHEMA,
+ TestConstants.EMPTY_STATISTICS_SCHEMA,
+ new LinkedList<MethodOrEventDataTransferObject>());
+
+ assertSame(
+ "Request schema has been injected. The current state is not indicating that!",
+ _class._schemaInjected,
+ _class._state);
+ }
+
+ /**
+ * Tests the injection of a valid schema on a QpidClass.
+ *
+ * <br>precondition : a valid arguments is injected on the qpid class.
+ * <br>postcondition : class definition is built successfully.
+ */
+ public void testSchemaInjectionOk() throws UnableToBuildFeatureException
+ {
+ _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package)
+ {
+ @Override
+ void requestSchema() throws Exception
+ {
+ // DO NOTHING : QMan is not running and therefore the schema will be manually injected.
+ }
+
+ @Override
+ void updateInstanceWithConfigurationData(QManManagedObject instance, byte[] rawData)
+ {
+ // DO NOTHING Given raw data is not valid so it cannot be converted.
+ }
+ };
+
+ // Incoming configuration data : that will fire the schema request and a state change
+ // from schema-not-requested to schema-requested-but-not-injected
+ _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA);
+
+ // I must be sure that what is obvious for me it's obvious for QMan... :)
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _class._schemaRequestedButNotYetInjected,
+ _class._state);
+
+ List<Map<String,Object>> propertyDefinitions = new ArrayList<Map<String,Object>>(2);
+ propertyDefinitions.add(
+ createProperty(
+ TestConstants.AGE_ATTRIBUTE_NAME,
+ 1,
+ TestConstants.YEARS,
+ TestConstants.SAMPLE_MIN_VALUE,
+ TestConstants.SAMPLE_MAX_VALUE,
+ null,
+ TestConstants.AGE_ATTRIBUTE_DESCRIPTION,
+ TestConstants._1,
+ false,
+ TestConstants._0));
+
+ propertyDefinitions.add(
+ createProperty(
+ TestConstants.SURNAME_ATTRIBUTE_NAME,
+ TestConstants.SAMPLE_ACCESS_CODE,
+ null,
+ null,
+ null,
+ TestConstants.SAMPLE_MAX_VALUE,
+ TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,
+ TestConstants._1,
+ true,
+ TestConstants._1));
+
+ _class.setSchema(propertyDefinitions, TestConstants.EMPTY_STATISTICS_SCHEMA, TestConstants.EMPTY_METHODS_SCHEMA);
+
+ assertEquals(2,_class._properties.size());
+
+ QpidProperty property = _class._properties.get(TestConstants.AGE_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,property.getName());
+ assertEquals(AccessMode.RC,property.getAccessMode());
+ assertEquals(TestConstants.YEARS,property.getUnit());
+ assertEquals(TestConstants.SAMPLE_MIN_VALUE,property.getMinValue());
+ assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxValue());
+ assertEquals(Integer.MIN_VALUE,property.getMaxLength());
+ assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,property.getDescription());
+ assertEquals(Short.class,property.getJavaType());
+ assertFalse(property.isOptional());
+
+ property = _class._properties.get(TestConstants.SURNAME_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,property.getName());
+ assertEquals(AccessMode.RC,property.getAccessMode());
+ assertNull(property.getUnit());
+ assertEquals(Integer.MIN_VALUE,property.getMinValue());
+ assertEquals(Integer.MIN_VALUE,property.getMaxValue());
+ assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxLength());
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,property.getDescription());
+ assertEquals(Short.class,property.getJavaType());
+ assertTrue(property.isOptional());
+
+ MBeanInfo mbeanInfo = _class._metadata;
+ assertEquals(TestConstants.EXCHANGE_CLASS_NAME,mbeanInfo.getClassName());
+
+ MBeanAttributeInfo [] attributes = mbeanInfo.getAttributes();
+ assertEquals(2,attributes.length);
+
+ MBeanAttributeInfo attribute = attributes[0];
+ assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,attribute.getName());
+ assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,attribute.getDescription());
+ assertFalse(attribute.isWritable());
+ assertTrue(attribute.isReadable());
+ assertEquals(Short.class.getName(),attribute.getType());
+
+ attribute = attributes[1];
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,attribute.getName());
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,attribute.getDescription());
+ assertFalse(attribute.isWritable());
+ assertTrue(attribute.isReadable());
+ assertEquals(Short.class.getName(),attribute.getType());
+ }
+
+ /**
+ * Tests the behaviour of the class when a schema request can't be made.
+ *
+ * <br>precondition : class must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : no exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withRequestSchemaFailure()
+ {
+ _class= new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ throw new Exception();
+ }
+
+ @Override
+ void setSchema(
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException
+ {
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _class._schemaNotRequested,
+ _class._state);
+
+ _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA);
+
+ assertSame(
+ "Current state must be still schema-not-requested.",
+ _class._schemaNotRequested,
+ _class._state);
+ }
+
+ /**
+ * Tests the behaviour of the class when a schema injection fails.
+ *
+ * <br>precondition : class must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : an exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withSchemaInjectionFailure()
+ {
+ _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package)
+ {
+ @Override
+ void requestSchema() throws Exception
+ {
+ // DO NOTHING.
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions)
+ throws UnableToBuildFeatureException
+ {
+ throw new UnableToBuildFeatureException("");
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _class._schemaNotRequested,
+ _class._state);
+
+ _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _class._schemaRequestedButNotYetInjected,
+ _class._state);
+
+ try {
+ _class.setSchema(
+ TestConstants.EMPTY_PROPERTIES_SCHEMA,
+ TestConstants.EMPTY_STATISTICS_SCHEMA,
+ TestConstants.EMPTY_METHODS_SCHEMA);
+ fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception...");
+ } catch (UnableToBuildFeatureException expected) {
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _class._schemaRequestedButNotYetInjected,
+ _class._state);
+ }
+ }
+
+ private Map<String,Object> createProperty(
+ String name,
+ Integer accessCode,
+ String unit,
+ Integer min,
+ Integer max,
+ Integer maxLength,
+ String description,
+ Integer type,
+ boolean optional,
+ Integer index)
+ {
+ Map <String,Object> result = new HashMap<String, Object>();
+ result.put(QpidFeatureBuilder.Attribute.name.name(),name);
+ result.put(QpidFeatureBuilder.Attribute.access.name(), accessCode);
+
+ if (unit != null)
+ {
+ result.put(QpidFeatureBuilder.Attribute.unit.name(),unit);
+ }
+
+ if (min != null)
+ {
+ result.put(QpidFeatureBuilder.Attribute.min.name(), min);
+ }
+
+ if (max != null)
+ {
+ result.put(QpidFeatureBuilder.Attribute.max.name(),max);
+ }
+
+ if (maxLength != null)
+ {
+ result.put(QpidFeatureBuilder.Attribute.maxlen.name(),maxLength);
+ }
+
+ result.put(QpidFeatureBuilder.Attribute.desc.name(), description);
+ result.put(QpidFeatureBuilder.Attribute.type.name(), type);
+ result.put(QpidFeatureBuilder.Attribute.optional.name(),optional ? 1 : 0);
+
+ if (index != null)
+ {
+ result.put(QpidFeatureBuilder.Attribute.index.name(), index);
+ }
+ return result;
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java
new file mode 100644
index 0000000000..4b36d9e5cc
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java
@@ -0,0 +1,293 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.TestConstants;
+import org.apache.qpid.management.configuration.ConfigurationException;
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.model.QpidEvent.QManManagedEvent;
+
+/**
+ * Test case for qpid class entity.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidEventTest extends TestCase
+{
+ private QpidEvent _event;
+ private QpidPackage _qpidPackage;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ _qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL);
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage);
+ }
+
+ /**
+ * Tests the execution of the createEventInstance() method.
+ * Basically it tests the addition of a new event instance.
+ *
+ * <br>precondition: event deifinition has no object instances.
+ * <br>precondition : event definition contains the new object instance.
+ */
+ public void testCreateEventInstance()
+ {
+ assertTrue(
+ "A just created event should be empty. I mean there shouldn't be event instances inside.",
+ _event.hasNoInstances());
+
+ QManManagedEvent instance = createEventInstance();
+
+ assertFalse (
+ "Now a new instance should be there...",
+ _event.hasNoInstances());
+
+ assertEquals(TestConstants.TEST_RAW_DATA,instance._rawEventData);
+ assertEquals(TestConstants.NOW,instance._timestamp);
+ assertEquals(TestConstants.SEVERITY, instance._severity);
+ }
+
+ /**
+ * Tests the internal state change of an event definition.
+ */
+ public void testStateChange() throws UnableToBuildFeatureException
+ {
+ // Let's override this class because this is not an online tests and therefore
+ // QMan is not supposed to be up.
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ // Do Nothing.
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ _state = _schemaInjected;
+ }
+ };
+
+ assertSame(
+ "Initial state doesn't match.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA);
+
+ assertSame(
+ "Request schema has been injected. The current state is not indicating that!",
+ _event._schemaInjected,
+ _event._state);
+ }
+
+ /**
+ * Tests the injection of a valid schema on a QpidEvent.
+ *
+ * <br>precondition : a valid arguments is injected on the qpid event.
+ * <br>postcondition : event definition is built successfully.
+ */
+ public void testSchemaInjectionOK() throws UnableToBuildFeatureException, ConfigurationException, InstanceNotFoundException, MBeanException, ReflectionException
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception
+ {
+ // DO NOTHING : QMan is not running and therefore the schema will be manually injected.
+ }
+
+ @Override
+ void updateEventInstanceWithData(QManManagedEvent instance)
+ {
+ // DO NOTHING : otherwise we should supply a valid raw data to be converted. ;-)
+ }
+ };
+
+ Configurator configurator = new Configurator();
+ configurator.configure();
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String, Object>>();
+ arguments.add(createArgument(TestConstants.AGE_ATTRIBUTE_NAME, TestConstants.AGE_ATTRIBUTE_DESCRIPTION));
+ arguments.add(createArgument(TestConstants.SURNAME_ATTRIBUTE_NAME, TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION));
+
+ // Incoming data : that will fire the schema request and a state change from schema-not-requested to schema-requested-but-not-injected
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ // I must be sure that what is obvious for me it's obvious for QMan... :)
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ // Inject schema
+ _event.setSchema(arguments);
+
+ // Arguments must be 2 + 2 (severity)
+ assertEquals(2,_event._arguments.size());
+
+ QpidProperty argument = _event._arguments.get(TestConstants.AGE_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,argument.getName());
+ assertEquals(AccessMode.RO,argument.getAccessMode());
+ assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,argument.getDescription());
+ assertEquals(Short.class,argument.getJavaType());
+ assertFalse(argument.isOptional());
+
+ argument = _event._arguments.get(TestConstants.SURNAME_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,argument.getName());
+ assertEquals(AccessMode.RO,argument.getAccessMode());
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,argument.getDescription());
+ assertEquals(Short.class,argument.getJavaType());
+ assertFalse(argument.isOptional());
+
+ assertEquals(1,_event._eventInstances.size());
+
+ JmxService service = new JmxService();
+ Set<ObjectName> objectNames = service.getEventMBeans();
+
+ assertEquals(1,objectNames.size());
+ }
+
+ /**
+ * Tests the behaviour of the event class when a schema request can't be made.
+ *
+ * <br>precondition : event must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : no exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withRequestSchemaFailure()
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ throw new Exception();
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ _state = _schemaInjected;
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Current state must be still schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+ }
+
+ /**
+ * Tests the behaviour of the event class when a schema injection fails.
+ *
+ * <br>precondition : event must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : an exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withSchemaInjectionFailure()
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ // DO NOTHING.
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ throw new UnableToBuildFeatureException("");
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ try {
+ _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA);
+ fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception...");
+ } catch (UnableToBuildFeatureException expected) {
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+ }
+ }
+
+ /**
+ * Factory method for qpid managed event instances.
+ *
+ * @return a new QpidManagedEvent with test data inside.
+ */
+ private QManManagedEvent createEventInstance()
+ {
+ return _event.createEventInstance(
+ TestConstants.TEST_RAW_DATA,
+ TestConstants.NOW,
+ TestConstants.SEVERITY);
+ }
+
+ /**
+ * Factory method for event argument.
+ *
+ * @return a new argument metadata.
+ */
+ private Map<String,Object> createArgument(String name,String desc)
+ {
+ Map <String,Object> argument = new HashMap<String, Object>();
+ argument.put(QpidFeatureBuilder.Attribute.name.name(),name);
+ argument.put(QpidFeatureBuilder.Attribute.desc.name(), desc);
+ argument.put(QpidFeatureBuilder.Attribute.type.name(), TestConstants._1);
+ return argument;
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java
new file mode 100644
index 0000000000..06dc35b0b1
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.dir;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.name;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanOperationInfo;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject;
+import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute;
+
+/**
+ * Test case for Qpid Statistic builder.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidMethodBuilderTest extends BaseQpidFeatureBuilderTestCase
+{
+ private final static Integer ARG_COUNT = 3;
+ private MethodOrEventDataTransferObject _methodDefinition;
+
+ private List<Map<String,Object>> _argumentsDefinitons = new ArrayList<Map<String, Object>>();
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ super.setUp();
+ _featureDefinition.put(Names.ARG_COUNT_PARAM_NAME, ARG_COUNT);
+
+ Map<String,Object> arg1 = new HashMap<String,Object>();
+ arg1.put(name.name(), "arg1");
+ arg1.put(type.name(),1);
+ arg1.put(dir.name(),Direction.I.name());
+ arg1.put(unit.name(), "bytes");
+
+ Map<String,Object> arg2 = new HashMap<String,Object>();
+ arg2.put(name.name(), "arg2");
+ arg2.put(type.name(),1);
+ arg2.put(dir.name(),Direction.O.name());
+ arg2.put(unit.name(), "bytes");
+
+ Map<String,Object> arg3 = new HashMap<String,Object>();
+ arg3.put(name.name(), "arg3");
+ arg3.put(type.name(),1);
+ arg3.put(dir.name(),Direction.IO.name());
+ arg3.put(unit.name(), "bytes");
+
+ /*
+ dir yes no yes Direction code for method arguments
+ unit yes yes yes Units for numeric values (i.e. seconds, bytes, etc.)
+ min yes no yes Minimum value for numerics
+ max yes no yes Maximum value for numerics
+ maxlen yes no yes Maximum length for strings
+ desc yes yes yes Description of the argument
+ default yes no yes Default value for the argument
+ */
+ _argumentsDefinitons.add(arg1);
+ _argumentsDefinitons.add(arg2);
+
+ _methodDefinition = new MethodOrEventDataTransferObject(_featureDefinition,_argumentsDefinitons);
+ _builder = QpidFeatureBuilder.createMethodBuilder(_methodDefinition);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't contains type attribute.
+ *
+ * <br>precondition: definition map doesn't contains type attribute.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attribute.
+ */
+ public void testMethodBuilderKO_WithMissingName()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.name);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't contain type, name, index & optional attributes.
+ *
+ * <br>precondition: definition map doesn't contain type, name, index & optional attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testMethodBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.unit);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't unit attribute.
+ * Note that this attribute is optional and therefore the build must succeed.
+ *
+ * <br>precondition: definition map doesn't contain unit attribute.
+ * <br>postcondition : no exception is thrown and the statistic is built.
+ */
+ public void testMethodBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.desc);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains valid values.
+ *
+ * <br>precondition : the statistic definiton map contains valid values.
+ * <br>postcondition : no exception is thrown and the statistisc is built as expected.
+ */
+ public void testMethodBuilderOK() throws UnableToBuildFeatureException
+ {
+ _builder.build();
+
+ QpidMethod method = (QpidMethod) _builder.getQpidFeature();
+ MBeanOperationInfo info = (MBeanOperationInfo) _builder.getManagementFeature();
+
+ assertEquals(NAME,method.getName());
+
+ assertEquals(DESCRIPTION,method.getDescription());
+
+ assertEquals(method.getDescription(),info.getDescription());
+ assertEquals(method.getName(),info.getName());
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java
new file mode 100644
index 0000000000..374011d150
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java
@@ -0,0 +1,171 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.model.type.Uint8;
+
+public class QpidNumberPropertyTest extends TestCase
+{
+ private QpidProperty _property;
+ private Long _value = 55432L;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ _property = new QpidProperty();
+ _property.setName("average");
+ _property.setAccessMode(AccessMode.RW);
+ _property.setType(new Uint8());
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a number and no constraint has been set.
+ *
+ * <br>precondition : property type is a string, no constraint has been set.
+ * <br>postcondition : no exception is thrown and the validation succeeds.
+ */
+ public void testValidationWithoutConstraints() {
+ try
+ {
+ _property.validate(_value);
+ } catch (ValidationException notExpected)
+ {
+ fail("If no constraint has been set on this property why the validation is failing?");
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a number and a max value constraint has been set.
+ *
+ * <br>precondition : property type is a number, max value has been set and property value is greater than max value.
+ * <br>postcondition : an exception is thrown indicating the validation failure.
+ */
+ public void testValidationKO_withMaxValue() {
+ int maxValue = (int)(_value-1);
+ _property.setMaxValue(maxValue);
+
+ try
+ {
+ _property.validate(_value);
+ fail("The given value is violating the installed constraint so an exception must be thrown.");
+ } catch (ValidationException expected)
+ {
+ assertEquals(ValidationException.MAX_VALUE,expected.getConstraintName());
+ assertEquals(maxValue,expected.getConstraintValue());
+ assertEquals((double)_value,expected.getFeatureValue());
+ assertEquals(_property.getName(),expected.getFeatureName());
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a number and a min value constraint has been set.
+ *
+ * <br>precondition : property type is a number, min value has been set and property value is lesser than min value.
+ * <br>postcondition : an exception is thrown indicating the validation failure.
+ */
+ public void testValidationKO_withMinValue() {
+ int minValue = (int)(_value+1);
+ _property.setMinValue(minValue);
+
+ try
+ {
+ _property.validate(_value);
+ fail("The given value is violating the installed constraint so an exception must be thrown.");
+ } catch (ValidationException expected)
+ {
+ assertEquals(ValidationException.MIN_VALUE,expected.getConstraintName());
+ assertEquals(minValue,expected.getConstraintValue());
+ assertEquals((double)_value,expected.getFeatureValue());
+ assertEquals(_property.getName(),expected.getFeatureName());
+ }
+ }
+
+
+ /**
+ * Tests the validation of a qpid property when the number is a string and the property value is null.
+ *
+ * <br>precondition : property type is a number and property value is null..
+ * <br>postcondition : no exception is thrown. That is : the validation succeeds.
+ */
+ public void testValidationOK_withNullValue() {
+ try
+ {
+ _property.validate(null);
+ } catch (ValidationException notExpected)
+ {
+ fail("No constraint has been violated so validate() shouldn't raise an exception.");
+ }
+
+ _property.setMinValue(1);
+ _property.setMaxValue(10);
+
+ try
+ {
+ _property.validate(null);
+ } catch (ValidationException notExpected)
+ {
+ fail("No constraint has been violated so validate() shouldn't raise an exception.");
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a number and a max / min constraints have been set.
+ *
+ * <br>precondition : property type is a number, max / min constraint have been set and property value is wrong.
+ * <br>postcondition : an exception is thrown indicating the validation failure.
+ */
+ public void testValidationOK_withMinAndMaxConstraint() {
+ int minValue = (int)(_value+1);
+ int maxValue = (int)(_value-1);
+ _property.setMinValue(minValue);
+ _property.setMaxValue(maxValue);
+
+ try
+ {
+ _property.validate(_value);
+ fail("The given value is violating the installed constraint so an exception must be thrown.");
+ } catch (ValidationException expected)
+ {
+ assertEquals(ValidationException.MIN_VALUE,expected.getConstraintName());
+ assertEquals(minValue,expected.getConstraintValue());
+ assertEquals((double)_value,expected.getFeatureValue());
+ assertEquals(_property.getName(),expected.getFeatureName());
+ }
+
+ _property.setMinValue(0);
+ try
+ {
+ _property.validate(_value);
+ fail("The given value is violating the installed constraint so an exception must be thrown.");
+ } catch (ValidationException expected)
+ {
+ assertEquals(ValidationException.MAX_VALUE,expected.getConstraintName());
+ assertEquals(maxValue,expected.getConstraintValue());
+ assertEquals((double)_value,expected.getFeatureValue());
+ assertEquals(_property.getName(),expected.getFeatureName());
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java
new file mode 100644
index 0000000000..b7eb9055ba
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java
@@ -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 org.apache.qpid.management.domain.model;
+
+import org.apache.qpid.management.TestConstants;
+
+/**
+ * Test case for Qpid package entity.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidPackageTest extends BaseDomainModelTestCase
+{
+ private QpidPackage _qpidPackage;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ _qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME, TestConstants.DOMAIN_MODEL);
+ }
+
+ /**
+ * Tests the association of a new class with a qpid package.
+ *
+ * <br>precondition : the package is not associated with any class.
+ * <br>postcondition : the package is now associated with the given class.
+ */
+ public void testAddClass() throws UnableToBuildFeatureException {
+ assertFalse(_qpidPackage.alreadyContainsClassDefinition(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH));
+
+ _qpidPackage.getQpidClass(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH, true);
+
+ assertTrue(_qpidPackage.alreadyContainsClassDefinition(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java
new file mode 100644
index 0000000000..8ad177645c
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java
@@ -0,0 +1,269 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.access;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.index;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.max;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.min;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.optional;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit;
+
+import javax.management.MBeanAttributeInfo;
+
+import org.apache.qpid.management.configuration.UnknownTypeCodeException;
+import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute;
+
+/**
+ * Test case for Qpid Property builder.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidPropertyBuilderTest extends BaseQpidFeatureBuilderTestCase
+{
+ private final static Integer MIN = 0;
+ private final static Integer MAX = 120;
+ private final static String UNIT = "bytes";
+
+ private Integer _access;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ super.setUp();
+
+ _access = 1;
+ _featureDefinition.put(access.name(), _access);
+ _featureDefinition.put(unit.name(),UNIT);
+ _featureDefinition.put(min.name(), MIN);
+ _featureDefinition.put(max.name(),MAX);
+
+ _featureDefinition.put(type.name(), 1);
+ _featureDefinition.put(optional.name(),0);
+ _featureDefinition.put(index.name(), 0);
+
+ _builder = QpidFeatureBuilder.createPropertyBuilder(_featureDefinition);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains an unknown type code.
+ *
+ * <br>precondition : the statistic definiton map contains an unknown type code.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testStatisticBuilderKO_WithUnknownType()
+ {
+ int unknownTypeCode =999;
+ try
+ {
+ _featureDefinition.put(type.name(), unknownTypeCode);
+ _builder.build();
+ fail("An unknown type code should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode());
+ }
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains a null value for a metadata attribute.
+ *
+ * <br>precondition : the statistic definiton map contains a null value for a metadata attribute.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testMethodBuilderKO_WithNullMetadataValue()
+ {
+ try
+ {
+ _featureDefinition.put(type.name(), null);
+ _builder.build();
+ fail("An null value for a metadata attribute should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertTrue(expected.getCause() instanceof NullPointerException);
+ }
+ }
+
+ /**
+ * Tests the build process for a property when the definition map contains an invalid metadata type.
+ *
+ * <br>precondition : the property definiton map contains a wrong type for a metadata attribute.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testPropertyBuilderKO_WithClassCastException()
+ {
+ try
+ {
+ _featureDefinition.put(access.name(), new String("a"));
+ _builder.build();
+ fail("A wrong metadata attribute type should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertTrue(expected.getCause() instanceof ClassCastException);
+ }
+ }
+
+ /**
+ * Tests the build process for a property when the definition map contains an unknown type code.
+ *
+ * <br>precondition : the property definiton map contains an unknown type code.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testPropertyBuilderKO_WithUnknownType()
+ {
+ int unknownTypeCode = 999;
+ try
+ {
+ _featureDefinition.put(type.name(), unknownTypeCode);
+ _builder.build();
+ fail("An unknown type code should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode());
+ }
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't contains type attribute.
+ *
+ * <br>precondition: definition map doesn't contains type attribute.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attribute.
+ */
+ public void testPropertyBuilderKO_WithMissingType()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't contain type & name attributes.
+ *
+ * <br>precondition: definition map doesn't contain type & name attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testPropertyBuilderKO_WithMissingTypeAndName()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't contain type & name & index attributes.
+ *
+ * <br>precondition: definition map doesn't contain type & name & index attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndex()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't contain type, name, index & optional attributes.
+ *
+ * <br>precondition: definition map doesn't contain type, name, index & optional attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndexAndOptional()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index,Attribute.optional);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't contain type, name, index, optional and access
+ * attributes.
+ *
+ * <br>precondition: definition map doesn't contain type, name, index, optional and access attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndexAndOptionalAndAccess()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index,Attribute.optional,Attribute.access);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't unit attribute.
+ * Note that this attribute is optional and therefore the build must succeed.
+ *
+ * <br>precondition: definition map doesn't contain unit attribute.
+ * <br>postcondition : no exception is thrown and the property is built.
+ */
+ public void testBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.unit);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't min and max attributes.
+ * Note that those attributes are optional and therefore the build must succeed.
+ *
+ * <br>precondition: definition map doesn't contain min and max attributes.
+ * <br>postcondition : no exception is thrown and the property is built.
+ */
+ public void testBuilderOK_WithMissingMinAndMax() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.min,Attribute.max);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map doesn't description attribute.
+ * Note that this attribute is optional and therefore the build must succeed.
+ *
+ * <br>precondition: definition map doesn't contain description attribute.
+ * <br>postcondition : no exception is thrown and the property is built.
+ */
+ public void testBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.desc);
+ }
+
+ /**
+ * Tests the build process for a property when the definition map contains valid values.
+ *
+ * <br>precondition : the property definiton map contains valid values.
+ * <br>postcondition : no exception is thrown and the property is built as expected.
+ */
+ public void testPropertyBuilderOK() throws UnableToBuildFeatureException
+ {
+ _builder.build();
+
+ QpidProperty property = (QpidProperty) _builder.getQpidFeature();
+ MBeanAttributeInfo info = (MBeanAttributeInfo) _builder.getManagementFeature();
+
+ assertEquals(NAME,property.getName());
+ assertEquals(AccessMode.RC,property.getAccessMode());
+ assertEquals(UNIT,property.getUnit());
+ assertEquals(MIN.intValue(),property.getMinValue());
+ assertEquals(MAX.intValue(),property.getMaxValue());
+ assertEquals(Integer.MIN_VALUE,property.getMaxLength());
+ assertEquals(DESCRIPTION,property.getDescription());
+ assertEquals(Short.class,property.getJavaType());
+ assertFalse(property.isOptional());
+
+ assertEquals(property.getDescription(),info.getDescription());
+ assertEquals(property.getName(),info.getName());
+ assertEquals(property.getJavaType().getName(),info.getType());
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java
new file mode 100644
index 0000000000..b7a8540b2d
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java
@@ -0,0 +1,159 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type;
+import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit;
+
+import javax.management.MBeanAttributeInfo;
+
+import org.apache.qpid.management.configuration.UnknownTypeCodeException;
+import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute;
+
+/**
+ * Test case for Qpid Statistic builder.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidStatisticBuilderTest extends BaseQpidFeatureBuilderTestCase
+{
+ private final static String UNIT = "bytes";
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ super.setUp();
+ _featureDefinition.put(unit.name(),UNIT);
+ _featureDefinition.put(type.name(), 1);
+
+ _builder = QpidFeatureBuilder.createStatisticBuilder(_featureDefinition);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains an unknown type code.
+ *
+ * <br>precondition : the statistic definiton map contains an unknown type code.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testStatisticBuilderKO_WithUnknownType()
+ {
+ int unknownTypeCode = 999;
+ try
+ {
+ _featureDefinition.put(type.name(), unknownTypeCode);
+ _builder.build();
+ fail("An unknown type code should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode());
+ }
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains a null value for a metadata attribute.
+ *
+ * <br>precondition : the statistic definiton map contains a null value for a metadata attribute.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testMethodBuilderKO_WithNullMetadataValue()
+ {
+ try
+ {
+ _featureDefinition.put(type.name(), null);
+ _builder.build();
+ fail("An null value for a metadata attribute should raise an exception to indicate a failure.");
+ } catch (UnableToBuildFeatureException expected)
+ {
+ assertTrue(expected.getCause() instanceof NullPointerException);
+ }
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't contains type attribute.
+ *
+ * <br>precondition: definition map doesn't contains type attribute.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attribute.
+ */
+ public void testStatisticBuilderKO_WithMissingType()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't contain type & name attributes.
+ *
+ * <br>precondition: definition map doesn't contain type & name attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testStatisticBuilderKO_WithMissingTypeAndName()
+ {
+ internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't contain type, name, index & optional attributes.
+ *
+ * <br>precondition: definition map doesn't contain type, name, index & optional attributes.
+ * <br>postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the
+ * missing attributes.
+ */
+ public void testStatisticBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.unit);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map doesn't unit attribute.
+ * Note that this attribute is optional and therefore the build must succeed.
+ *
+ * <br>precondition: definition map doesn't contain unit attribute.
+ * <br>postcondition : no exception is thrown and the statistic is built.
+ */
+ public void testBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException
+ {
+ internalTestForMissingOptionalAttribute(Attribute.desc);
+ }
+
+ /**
+ * Tests the build process for a statistic when the definition map contains valid values.
+ *
+ * <br>precondition : the statistic definiton map contains valid values.
+ * <br>postcondition : no exception is thrown and the statistisc is built as expected.
+ */
+ public void testStatisticBuilderOK() throws UnableToBuildFeatureException
+ {
+ _builder.build();
+
+ QpidStatistic statistic= (QpidStatistic) _builder.getQpidFeature();
+ MBeanAttributeInfo info = (MBeanAttributeInfo) _builder.getManagementFeature();
+
+ assertEquals(NAME,statistic.getName());
+ assertEquals(UNIT,statistic.getUnit());
+ assertEquals(DESCRIPTION,statistic.getDescription());
+ assertEquals(Short.class,statistic.getJavaType());
+
+ assertEquals(statistic.getDescription(),info.getDescription());
+ assertEquals(statistic.getName(),info.getName());
+ assertEquals(statistic.getJavaType().getName(),info.getType());
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java
new file mode 100644
index 0000000000..8aeb7c8550
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.management.domain.model.type.Str16;
+
+public class QpidStringPropertyTest extends TestCase
+{
+ private QpidProperty _property;
+ private final String _5LettersString = "12345";
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ Configurator configurator = new Configurator();
+ configurator.configure();
+ _property = new QpidProperty();
+ _property.setName("name");
+ _property.setAccessMode(AccessMode.RW);
+ _property.setType(new Str16());
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a string and a max length constraint hasn't been set.
+ *
+ * <br>precondition : property type is a string, max length hasn't been set.
+ * <br>postcondition : no exception is thrown. That is : the validation succeeds.
+ */
+ public void testValidationWithoutMaxLength() {
+ try
+ {
+ _property.validate(_5LettersString);
+ } catch (ValidationException notExpected)
+ {
+ fail("No max length has been set on property so validation must succeed.");
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a string and a max length constraint has been set.
+ *
+ * <br>precondition : property type is a string, max length has been set and property value is longer than max length.
+ * <br>postcondition : an exception is thrown indicating the validation failure.
+ */
+ public void testValidationKO_withMaxLength() {
+ int maxLength = 2;
+ _property.setMaxLength(maxLength);
+
+ try
+ {
+ _property.validate(_5LettersString);
+ fail("No max length has been set on property so validation must proceed.");
+ } catch (ValidationException expected)
+ {
+ assertEquals(ValidationException.MAX_LENGTH,expected.getConstraintName());
+ assertEquals(maxLength,expected.getConstraintValue());
+ assertEquals(_5LettersString.length(),expected.getFeatureValue());
+ assertEquals(_property.getName(),expected.getFeatureName());
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a string and the property value is null.
+ *
+ * <br>precondition : property type is a string and property value is null..
+ * <br>postcondition : no exception is thrown. That is : the validation succeeds.
+ */
+ public void testValidationOK_withNullValue() {
+ try
+ {
+ _property.validate(null);
+ } catch (ValidationException notExpected)
+ {
+ fail("No constraint has been violated so validate() shouldn't raise an exception.");
+ }
+
+ _property.setMaxLength(1);
+
+ try
+ {
+ _property.validate(null);
+ } catch (ValidationException notExpected)
+ {
+ fail("No constraint has been violated so validate() shouldn't raise an exception.");
+ }
+ }
+
+ /**
+ * Tests the validation of a qpid property when the type is a string and a max length constraint has been set.
+ *
+ * <br>precondition : property type is a string, max length has been set and property value is not violating that.
+ * <br>postcondition : no exception is thrown. That is : the validation succeeds.
+ */
+ public void testValidationOK_withMaxLength() {
+ int maxLength = (_5LettersString.length()+1);
+ _property.setMaxLength(maxLength);
+
+ try
+ {
+ _property.validate(_5LettersString);
+ } catch (ValidationException notExpected)
+ {
+ fail("No constraint has been violated so validate() shouldn't raise an exception.");
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java
new file mode 100644
index 0000000000..6636c08710
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.model.type;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for "Binary" type.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BinaryTest extends TestCase
+{
+ /**
+ * Tests the lazy & once hash code computation behaviour of the binary type.
+ */
+ public void testHashCodeComputation(){
+ Binary binary = new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3});
+ assertSame(binary.state,binary.hashCodeNotYetComputed);
+
+ int firstResult = binary.hashCode();
+ assertSame(binary.state,binary.hashCodeAlreadyComputed);
+
+ int secondResult = binary.hashCode();
+ assertSame(binary.state,binary.hashCodeAlreadyComputed);
+ assertEquals(firstResult,secondResult);
+ }
+
+ /**
+ * Tests the equals() method of the binary class.
+ * Two binary must be equals only if they contain the same array (that is, two arrays with the same size & content)
+ */
+ public void testIdentity() {
+ Binary binary = new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3});
+ Binary theSame= new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3});
+ Binary aDifferentOne = new Binary(new byte[]{4,2,3,3,4,4,5,3,3,2});
+
+ assertTrue(binary.equals(theSame));
+ assertFalse(binary.equals(aDifferentOne));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java
new file mode 100644
index 0000000000..805c039a6f
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java
@@ -0,0 +1,241 @@
+/*
+ *
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.management.TestConstants;
+import org.apache.qpid.management.domain.handler.base.IMessageHandler;
+import org.apache.qpid.management.domain.model.DomainModel;
+import org.apache.qpid.nclient.util.ByteBufferMessage;
+import org.apache.qpid.transport.codec.Decoder;
+
+/**
+ * Test case for Broker Message Listener.
+ *
+ * @author Andrea Gazzarini
+ */
+public class BrokerMessageListenerTest extends TestCase
+{
+ // An empty message handler user for test.
+ private IMessageHandler _emptyMessageHandler = new IMessageHandler()
+ {
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ }
+ public void setDomainModel (DomainModel domainModel)
+ {
+ }
+ };
+
+ // Another empty message handler user for test.
+ private IMessageHandler _anotherEmptyMessageHandler = new IMessageHandler()
+ {
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ }
+ public void setDomainModel (DomainModel domainModel)
+ {
+ }
+ };
+
+ private Map<Character,IMessageHandler> _handlers = new HashMap<Character, IMessageHandler>();
+ private BrokerMessageListener _listener;
+ private final char opcode1 = 'x';
+ private final char opcode2 = 'y';
+
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ DomainModel domainModel = new DomainModel(TestConstants.BROKER_ID);
+ _listener = new BrokerMessageListener(domainModel);
+
+ _handlers.put(opcode1, _emptyMessageHandler);
+ _handlers.put(opcode2, _anotherEmptyMessageHandler);
+ }
+
+ /**
+ * Tests the installation of message handlers on a broker message listener.
+ *
+ * <br>precondition : no message handler has been installed on message listener.
+ * <br>postcondition : two message handlers are installed on message listener.
+ */
+ public void testSetHandlersOK()
+ {
+ assertTrue(
+ "No handler has yet been installed so how is it possible that the handlers map is not empty?",
+ _listener._handlers.isEmpty());
+
+ _listener.setHandlers(_handlers);
+
+ assertEquals("Now we should have two handlers configured.",2,_listener._handlers.size());
+ assertSame(_listener._handlers.get(opcode1),_emptyMessageHandler);
+ assertSame(_listener._handlers.get(opcode2),_anotherEmptyMessageHandler);
+ }
+
+ /**
+ * Tests the installation of message handlers on a broker message listener.
+ * Specifically it tries to install three message handlers and one of them is throwing an exception at installation time.
+ *
+ * <br>precondition : no message handler has been installed on message listener.
+ * <br>postcondition : two message handlers are installed on message listener. (the one that thrown exception has been
+ * discarded).
+ */
+ public void testSetHandlerOK()
+ {
+ IMessageHandler wrongMessageHandler = new IMessageHandler()
+ {
+
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ }
+
+ public void setDomainModel (DomainModel domainModel)
+ {
+ throw new RuntimeException();
+ }
+ };
+
+ char opcodeForWrongHandler = 'k';
+
+ assertTrue(
+ "No handler has yet been installed so how is it possible that the handlers map is not empty?",
+ _listener._handlers.isEmpty());
+
+ _handlers.put(opcodeForWrongHandler,wrongMessageHandler);
+
+ _listener.setHandlers(_handlers);
+
+ assertEquals("Now we should have two handlers configured.",2,_listener._handlers.size());
+ assertSame(_listener._handlers.get(opcode1),_emptyMessageHandler);
+ assertSame(_listener._handlers.get(opcode2),_anotherEmptyMessageHandler);
+ assertNull(_listener._handlers.get(opcodeForWrongHandler));
+ }
+
+ /**
+ * Tests the execution of the onMessage() method when a message with a bad magic number is received.
+ *
+ * <br>precondition : a message with a bad magic number is received.
+ * <br>postcondition : the processing of the incoming message is skipped and therefore no handler will be called.
+ */
+ public void testOnMessageKO_withBadMagicNumber() throws IOException
+ {
+ IMessageHandler neverCallMe = new IMessageHandler()
+ {
+
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ fail("This test shouldn't never arrive at this point...");
+ }
+
+ public void setDomainModel (DomainModel domainModel)
+ {
+ }
+ };
+
+ String opcodeForNeverCallMeHandler = "w";
+
+ _handlers.put('w',neverCallMe);
+ _listener.setHandlers(_handlers);
+
+ Message message = new ByteBufferMessage();
+ message.appendData( ("AMG"+opcodeForNeverCallMeHandler).getBytes());
+
+ _listener.onMessage(message);
+ }
+
+ /**
+ * Tests the execution of the onMessage() method when the incoming message is a compound message.
+ *
+ * <br>precondition : the incoming message is a compound message.
+ * <br>postcondition : each tokenized message is forwarded to the appropriate handler.
+ */
+ public void testOnMessageOK_WithCompoundMessage() throws Exception
+ {
+ final Map<Character,IMessageHandler> handlersMap = new HashMap<Character,IMessageHandler>();
+ char [] opcodes = {'a','b','c','d','e'};
+
+ class MockMessageHandler implements IMessageHandler
+ {
+ private final char _opcode;
+
+ public MockMessageHandler(char opcode)
+ {
+ this._opcode = opcode;
+ }
+
+ public void process (Decoder decoder, int sequenceNumber)
+ {
+ handlersMap.remove(_opcode);
+ }
+
+ public void setDomainModel (DomainModel domainModel)
+ {
+ // Do nothing here. It's just a mock handler.
+ }
+ };
+
+ for (char opcode : opcodes)
+ {
+ handlersMap.put(opcode, new MockMessageHandler(opcode));
+ }
+
+ // Removes previously injected handlers (i.e. x & y)
+ _listener._handlers.clear();
+ _listener.setHandlers(handlersMap);
+
+ Message compoundMessage = createCompoundMessage(opcodes);
+ _listener.onMessage(compoundMessage);
+
+ assertTrue(handlersMap.isEmpty());
+ }
+
+ // Creates a (non valid) compound message.
+ private Message createCompoundMessage(char[] opcodes) throws IOException {
+ byte [] compoundMessageData = new byte [12 * opcodes.length];
+ Random randomizer = new Random();
+ int position = 0;
+
+ for (char opcode : opcodes) {
+ System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, compoundMessageData, position, MessageTokenizer.MAGIC_NUMBER_BYTES.length);
+ position+=MessageTokenizer.MAGIC_NUMBER_BYTES.length;
+
+ compoundMessageData[position++] = (byte)opcode;
+
+ for (int c = 4; c < 12; c++)
+ {
+ byte aByte = (byte)randomizer.nextInt(127);
+ compoundMessageData[position++] = aByte;
+ }
+ }
+
+ Message compoundMessage = new ByteBufferMessage();
+ compoundMessage.appendData(compoundMessageData);
+ return compoundMessage;
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java
new file mode 100644
index 0000000000..55b8b17f9d
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java
@@ -0,0 +1,140 @@
+/*
+*
+ * 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 org.apache.qpid.management.domain.services;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.util.ByteBufferMessage;
+import org.apache.qpid.transport.codec.BBDecoder;
+
+/**
+ * Tests case for messaeg tokenizer.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MessageTokenizerTest extends TestCase {
+
+ /**
+ * Tests the execution of the message tokenizer when the given message is not a valid AMQP message.
+ *
+ * <br>precondition : the incoming message is not a valid AMQP message.
+ * <br>postcondition : no exception is thrown and there will be exactly one token with the given message.
+ */
+ public void testOK_WithNoMessage() throws IOException{
+ byte [] noMessage = {2,10,120,23,23,23,4,10,11,12,2,1,3,-22};
+
+ Message multiMessage = new ByteBufferMessage();
+ multiMessage.appendData(noMessage);
+ MessageTokenizer tokenizer = new MessageTokenizer(multiMessage);
+
+ assertEquals(1, tokenizer.countTokens());
+ assertEquals(tokenizer.nextElement(),noMessage);
+ assertFalse(tokenizer.hasMoreElements());
+ }
+
+ /**
+ * Tests the execution of the message tokenizer when the given message contains only one message.
+ *
+ * <br>precondition : the incoming message contains only one message.
+ * <br>postcondition : no exception is thrown and there will be exactly one token with the given message.
+ */
+ public void testOK_WithOneMessage() throws IOException{
+ byte [] oneEncodedMessage = {'A','M','2',23,23,23,4,10,11,12,2,1,3,-22};
+
+ Message multiMessage = new ByteBufferMessage();
+ multiMessage.appendData(oneEncodedMessage);
+ MessageTokenizer tokenizer = new MessageTokenizer(multiMessage);
+
+ assertEquals(1, tokenizer.countTokens());
+ assertEquals(tokenizer.nextElement(),oneEncodedMessage);
+ assertFalse(tokenizer.hasMoreElements());
+ }
+
+ /**
+ * Tests the execution of the message tokenizer when the given message contains a random number of messages.
+ *
+ * <br>precondition : the incoming message contains a random number of messages.
+ * <br>postcondition : no exception is thrown and each built token is a valid message starting with right header.
+ */
+ public void testOK_WithRandomNUmberOfMessages() throws IOException{
+ Random randomizer = new Random();
+
+ int howManyLoops = randomizer.nextInt(10000);
+ howManyLoops = (howManyLoops == 0) ? 10 : howManyLoops;
+ byte [] compoundMessageData = new byte [12 * howManyLoops];
+
+ List<byte []> messages = new ArrayList<byte[]>(howManyLoops);
+
+ int position = 0;
+ for (int i = 0; i < howManyLoops; i++)
+ {
+ byte [] message = new byte[12];
+ System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, compoundMessageData, position, MessageTokenizer.MAGIC_NUMBER_BYTES.length);
+ System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, message, 0, MessageTokenizer.MAGIC_NUMBER_BYTES.length);
+ position+=MessageTokenizer.MAGIC_NUMBER_BYTES.length;
+
+ for (int c = 3; c < 12; c++)
+ {
+ byte aByte = (byte)randomizer.nextInt(127);
+ aByte = (aByte == 77) ? (byte)c : aByte;
+ compoundMessageData[position++] = aByte;
+ message[c] = aByte;
+ }
+ messages.add(message);
+ }
+
+ Message multiMessage = new ByteBufferMessage();
+ multiMessage.appendData(compoundMessageData);
+ MessageTokenizer tokenizer = new MessageTokenizer(multiMessage);
+
+ int howManyTokens = tokenizer.countTokens();
+ assertEquals(howManyLoops, howManyTokens);
+
+ int index = 0;
+ while (tokenizer.hasMoreElements())
+ {
+ assertEquals(tokenizer.nextElement(),messages.get(index++));
+ }
+
+ assertEquals((index),howManyTokens);
+ }
+
+ /**
+ * Internal method used for comparison of two messages.
+ *
+ * @param message the token message just built by the tokenizer.
+ * @param expected the expected result.
+ */
+ private void assertEquals(Message message, byte [] expected) throws IOException
+ {
+ ByteBuffer messageContent = message.readData();
+ BBDecoder decoder = new BBDecoder();
+ decoder.init(messageContent);
+ byte [] content = decoder.readReaminingBytes();
+ assertTrue(Arrays.equals(content, expected));
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java
new file mode 100644
index 0000000000..900d14c72e
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+import java.util.UUID;
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.remote.WsResourceClient;
+import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.TestConstants;
+
+/**
+ * Test case for WS-Resource lifecycle management.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class BaseWsDmAdapterTestCase extends TestCase implements TestConstants{
+
+ protected MBeanServer _managementServer;
+ protected ObjectName _resourceObjectName;
+
+ protected WsResourceClient _resourceClient;
+ protected MBeanInfo _mbeanInfo;
+
+ /**
+ * Set up fixture for this test case.
+ *
+ * @throws Exception when the test case intialization fails.
+ */
+ protected void setUp() throws Exception
+ {
+ _managementServer = ManagementFactory.getPlatformMBeanServer();
+
+ ServiceGroupClient serviceGroup = getServiceGroupClient();
+ WsResourceClient [] members = serviceGroup.getMembers();
+
+ assertEquals(
+ "No resource has been yet created so how is " +
+ "it possible that service group children list is not empty?",
+ 0,
+ members.length);
+
+ _managementServer.invoke(
+ Names.QPID_EMULATOR_OBJECT_NAME,
+ "createQueue",
+ new Object[]{_resourceObjectName = createResourceName()},
+ new String[]{ObjectName.class.getName()});
+
+ members = serviceGroup.getMembers();
+ assertEquals(
+ "One resource has just been created so " +
+ "I expect to find it on service group children list...",
+ 1,
+ members.length);
+
+ _resourceClient = members[0];
+ _mbeanInfo = _managementServer.getMBeanInfo(_resourceObjectName);
+ }
+
+ /**
+ * Shutdown procedure for this test case.
+ *
+ * @throws Exception when either the server or some resource fails to shutdown.
+ */
+ @Override
+ protected void tearDown() throws Exception
+ {
+ ServiceGroupClient serviceGroup = getServiceGroupClient();
+ WsResourceClient [] members = serviceGroup.getMembers();
+
+ _managementServer.invoke(
+ Names.QPID_EMULATOR_OBJECT_NAME,
+ "unregister",
+ new Object[]{_resourceObjectName},
+ new String[]{ObjectName.class.getName()});
+
+ members = serviceGroup.getMembers();
+
+ assertEquals(
+ "No resource has been yet created so how is it possible that service group children list is not empty?",
+ 0,
+ members.length);
+ }
+
+ /**
+ * Creates a service group client reference.
+ *
+ * @return a service group client reference.
+ */
+ private ServiceGroupClient getServiceGroupClient()
+ {
+ URI address = URI.create(
+ Protocol.DEFAULT_ENDPOINT_URI.replaceFirst("8080",System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME)));
+ return new ServiceGroupClient(new EndpointReference(address));
+ }
+
+ /**
+ * In order to test the behaviour of the WS-DM adapter, at
+ * least one resource must be created. This is the method that
+ * returns the name (ObjectName on JMX side, Resource-ID on WSDM side)
+ * of that resource
+ *
+ * @return the name of the MBean instance that will be created.
+ * @throws Exception when the name if malformed. Practically never.
+ */
+ private ObjectName createResourceName() throws Exception
+ {
+ return new ObjectName(
+ "Q-MAN:objectId="+UUID.randomUUID()+
+ ", brokerID="+UUID.randomUUID()+
+ ",class=queue"+
+ ",package=org.apache.qpid"+
+ ",name="+System.currentTimeMillis());
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java
new file mode 100644
index 0000000000..615d744546
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.wsdm;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer;
+import org.w3c.dom.Element;
+
+/**
+ * Custom implementation of Muse ReflectionProxyHandler
+ * that uses a base64 serializer for byte arrays.
+ * Note that this proxy handler is only needed for tests because it provides
+ * client side Base64 serializer capability.
+ * In a concrete scenario we don't mind what instrument the client is using in order to
+ * propertly serialize byte arrays.
+ *
+ * @author Andrea Gazzarini
+ */
+public class EnhancedReflectionProxyHandler extends ReflectionProxyHandler
+{
+ @Override
+ protected Element serialize(Object obj, QName qname) throws SoapFault
+ {
+ if (obj == null)
+ {
+ return XmlUtils.createElement(qname);
+ }
+
+ if (obj.getClass() == byte[].class)
+ {
+ return new ByteArraySerializer().toXML(obj, qname);
+ } else
+ {
+ return super.serialize(obj, qname);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Object deserialize(Element xml, Class theClass) throws SoapFault
+ {
+ if (theClass == byte[].class)
+ {
+ return new ByteArraySerializer().fromXML(xml);
+ } else
+ {
+ return super.deserialize(xml, theClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java
new file mode 100644
index 0000000000..d59e7a39e5
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.management.MBeanAttributeInfo;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.resource.WsrfConstants;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+/**
+ * Test case for Web Service Resource Properties interfaces.
+ * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf
+ * (Web Services Resource Properties 1.2 - (WS-ResourceProperties).
+ * For a better explanation see chapter 5 of the specification above.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetMultipleResourcePropertiesTestCase extends BaseWsDmAdapterTestCase
+{
+ /**
+ * Tests the GetMultipleResourceProperties interface when the request contains
+ * an unknwon target resource.
+ *
+ * <br>precondition : the GetMultipleResourceProperties request contains an unknwon resource.
+ * <br>postcondition : a SoapFault is thrown and the corresponding detail contains an
+ * UnknownResourceFault element.
+ */
+ public void testGetMultipleResourcePropertiesKO_WithUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+
+ _resourceClient.getMultipleResourceProperties(new QName[]{});
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+
+ /**
+ * Test the WS-RP GetResourceProperties interface of the WS-DM adapter.
+ *
+ * <br>precondition : a ws resource exists and is registered.
+ * <br>postcondition : Properties are correctly returned according to WSRP interface and they (their value)
+ * are matching with corresponding MBean properties.
+ */
+ public void testGetMultipleResourcePropertiesOK() throws Exception
+ {
+ MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes();
+ QName[] names = new QName[attributesMetadata.length];
+
+ int index = 0;
+ for (MBeanAttributeInfo attributeMetadata : _mbeanInfo.getAttributes())
+ {
+ QName qname = new QName(Names.NAMESPACE_URI,attributeMetadata.getName(),Names.PREFIX);
+ names[index++] = qname;
+ }
+
+ Element[] properties =_resourceClient.getMultipleResourceProperties(names);
+ for (Element element : properties)
+ {
+ String name = element.getLocalName();
+ Object value = _managementServer.getAttribute(_resourceObjectName, name);
+ if ("Name".equals(name))
+ {
+ assertEquals(
+ value,
+ element.getTextContent());
+ } else if ("Durable".equals(name))
+ {
+ assertEquals(
+ value,
+ Boolean.valueOf(element.getTextContent()));
+ } else if ("ExpireTime".equals(name))
+ {
+ assertEquals(
+ value,
+ new Date(Long.valueOf(element.getTextContent())));
+ } else if ("MsgTotalEnqueues".equals(name))
+ {
+ assertEquals(
+ value,
+ Long.valueOf(element.getTextContent()));
+ } else if ("ConsumerCount".equals(name))
+ {
+ assertEquals(
+ value,
+ Integer.valueOf(element.getTextContent()));
+ }else if ("VhostRef".equals(name))
+ {
+ assertEquals(
+ value,
+ UUID.fromString(element.getTextContent()));
+ }
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java
new file mode 100644
index 0000000000..e18e928cf4
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java
@@ -0,0 +1,105 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.lang.reflect.Array;
+
+import javax.management.MBeanAttributeInfo;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.resource.WsrfConstants;
+import org.apache.qpid.management.Names;
+
+/**
+ * Test case for Web Service Resource Properties interfaces.
+ * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf
+ * (Web Services Resource Properties 1.2 - (WS-ResourceProperties).
+ * For a better explanation see chapter 5 of the specification above.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetResourcePropertiesTestCase extends BaseWsDmAdapterTestCase
+{
+
+ /**
+ * Test the WS-RP GetResourceProperty interface of the WS-DM adapter.
+ *
+ * <br>precondition : a ws resource exists and is registered.
+ * <br>postcondition : property values coming from WS-DM resource are the same of the JMX interface.
+ */
+ public void testGetResourcePropertiesOK() throws Exception
+ {
+ MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes();
+ for (MBeanAttributeInfo attributeMetadata : attributesMetadata)
+ {
+ String name = attributeMetadata.getName();
+ Object propertyValues = _resourceClient.getPropertyAsObject(
+ new QName(
+ Names.NAMESPACE_URI,
+ name,
+ Names.PREFIX),
+ Class.forName(attributeMetadata.getType()));
+
+ int length = Array.getLength(propertyValues);
+ if (length != 0)
+ {
+ Object propertyValue = Array.get(propertyValues, 0);
+
+ assertEquals(
+ "Comparison failed for property "+name,
+ _managementServer.getAttribute(_resourceObjectName,name),
+ propertyValue);
+ } else {
+ assertNull(
+ String.format(
+ "\"%s\" property value shouldn't be null. Its value is %s",
+ name,
+ _managementServer.getAttribute(_resourceObjectName,name)),
+ _managementServer.getAttribute(_resourceObjectName,name));
+ }
+ }
+ }
+
+ /**
+ * Tests the GetMultipleResourceProperties interface when the request contains
+ * an unknwon target resource.
+ *
+ * <br>precondition : the GetMultipleResourceProperties request contains an unknwon resource.
+ * <br>postcondition : a SoapFault is thrown and the corresponding detail contains an
+ * UnknownResourceFault element.
+ */
+ public void testGetResourcePropertiesKO_WithUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+
+ _resourceClient.getResourceProperty(new QName("a","b","c"));
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java
new file mode 100644
index 0000000000..862115f841
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java
@@ -0,0 +1,134 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.resource.WsrfConstants;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+/**
+ * Test case for Web Service Resource Properties interfaces.
+ * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf
+ * (Web Services Resource Properties 1.2 - (WS-ResourceProperties).
+ * For a better explanation see chapter 5 of the specification above.
+ *
+ * @author Andrea Gazzarini
+ */
+public class GetResourcePropertyDocumentTestCase extends BaseWsDmAdapterTestCase
+{
+ /**
+ * Tests the GetResourcePropertyDocument interface when the request contains
+ * an unknwon target resource.
+ *
+ * <br>precondition : the GetResourcePropertyDocument contains an unknwon resource.
+ * <br>postcondition : a SoapFault is thrown and the corresponding detail contains an
+ * UnknownResourceFault element.
+ */
+ public void testGetResourcePropertyDocumentKO_WithUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+ _resourceClient.setTrace(true);
+
+ _resourceClient.getResourcePropertyDocument();
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+
+ /**
+ * Tests the WS-RP PutResourcePropertyDocument interface of the WS-DM adapter.
+ *
+ * <br>precondition : a ws resource exists and is registered.
+ * <br>postcondition : A read / write property is correctly set according to WSRP interface.
+ */
+ public void testGetAndPutResourcePropertyDocumentOK() throws Exception
+ {
+ String expectedMgmtPubIntervalValue = "4321";
+ String propertyName = "MgmtPubInterval";
+
+ Element propertiesDocument = _resourceClient.getResourcePropertyDocument();
+ Element [] properties = XmlUtils.getAllElements(propertiesDocument);
+
+ for (Element element : properties)
+ {
+ if (propertyName.equals(element.getLocalName())) {
+ element.setTextContent(expectedMgmtPubIntervalValue);
+ } else {
+ propertiesDocument.removeChild(element);
+ }
+ }
+
+ _resourceClient.putResourcePropertyDocument(propertiesDocument);
+
+ Element newProperties = _resourceClient.getResourcePropertyDocument();
+
+ Element mgmtPubInterval = XmlUtils.getElement(
+ newProperties, new QName(
+ Names.NAMESPACE_URI,
+ propertyName,
+ Names.PREFIX));
+
+ assertEquals(expectedMgmtPubIntervalValue,mgmtPubInterval.getTextContent());
+ }
+
+ /**
+ * Tests the WS-RP PutResourcePropertyDocument interface of the WS-DM adapter.
+ * Specifically it tries to update the value of a read-only property.
+ *
+ * <br>precondition : a ws resource exists, it is registered and has at least one read-only property.
+ * <br>postcondition : An exception is thrown indicating the failure.
+ */
+ public void testGetAndPutResourcePropertyDocumentKO_WithReadOnlyProperty() throws Exception
+ {
+ String propertyName = "Name";
+
+ Element propertiesDocument = _resourceClient.getResourcePropertyDocument();
+ Element [] properties = XmlUtils.getAllElements(propertiesDocument);
+
+ for (Element element : properties)
+ {
+ if (propertyName.equals(element.getLocalName())) {
+ element.setTextContent("ThisIsTheNewValueOfNameProperty");
+ } else {
+ propertiesDocument.removeChild(element);
+ }
+ }
+
+ try
+ {
+ _resourceClient.putResourcePropertyDocument(propertiesDocument);
+ fail("It's not possible to update the value of a read-only property.");
+ } catch (SoapFault expected)
+ {
+
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java
new file mode 100644
index 0000000000..046f2226e6
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java
@@ -0,0 +1,169 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.util.xml.XmlUtils;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.metadata.WsxConstants;
+import org.apache.muse.ws.resource.WsrfConstants;
+import org.apache.muse.ws.resource.metadata.WsrmdConstants;
+import org.apache.qpid.management.Names;
+import org.w3c.dom.Element;
+
+/**
+ * Test case for QMan metadata exchange interface.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MetadataExchangeInterfaceTestCase extends BaseWsDmAdapterTestCase
+{
+ /**
+ * Test the MetadataExchange interface when the corresponding
+ * request doesn't contain a dialect. According to WS-MetadataExchange specs this should be
+ * intended as a "give-me-all-metadata" for that resource.
+ *
+ * <br>precondition : the GetMetadata request doesn't contain a dialect.
+ * <br>postcondition : the whole metadata document is returned with all metadata .
+ * It will contain both WSDL and RMD.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGetMetadataOK_WithoutDialect() throws Exception
+ {
+ Element[] result = (Element[]) _resourceClient.invoke(
+ getProxyHandler(),
+ new Object[]{""});
+
+ assertEquals(2,result.length);
+
+ Element rmdMetadataSection = result[0];
+ Element wsdlMetadataSection = result[1];
+
+ Element rmd = XmlUtils.getFirstElement(rmdMetadataSection);
+ Element wsdl = XmlUtils.getFirstElement(wsdlMetadataSection);
+
+ assertEquals("MetadataDescriptor",rmd.getLocalName());
+ assertEquals("definitions",wsdl.getLocalName());
+ }
+
+ /**
+ * Test the MetadataExchange interface when the WSDL dialect is specified on the request.
+ *
+ * <br>precondition : the GetMetadata request contains WSDL dialect.
+ * <br>postcondition : the resource WSDL metadata document is returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGetMetadataOK_WithWSDLDialect() throws Exception
+ {
+ Element[] result = (Element[]) _resourceClient.invoke(
+ getProxyHandler(),
+ new Object[]{WsxConstants.WSDL_DIALECT});
+
+ assertEquals(1,result.length);
+
+ Element wsdlMetadataSection = result[0];
+
+ Element wsdl = XmlUtils.getFirstElement(wsdlMetadataSection);
+
+ assertEquals("definitions",wsdl.getLocalName());
+ }
+
+ /**
+ * Test the MetadataExchange interface when the RMD dialect is specified on the request.
+ *
+ * <br>precondition : the GetMetadata request contains RMD dialect.
+ * <br>postcondition : the RMD metadata document is returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGetMetadataOK_WithRMDDialect() throws Exception
+ {
+ Element[] result = (Element[]) _resourceClient.invoke(
+ getProxyHandler(),
+ new Object[]{WsrmdConstants.NAMESPACE_URI});
+
+ assertEquals(1,result.length);
+
+ Element rmdMetadataSection = result[0];
+
+ Element wsdl = XmlUtils.getFirstElement(rmdMetadataSection);
+
+ assertEquals("MetadataDescriptor",wsdl.getLocalName());
+ }
+
+ /**
+ * Test the MetadataExchange interface with an unknown metadata dialect.
+ *
+ * <br>precondition : the GetMetadata request contains an unknown dialect.
+ * <br>postcondition : the returned metadata section is empty.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGetMetadataKO_WithoutUnknownDialect() throws Exception
+ {
+ Element [] metadata = (Element[]) _resourceClient.invoke(
+ getProxyHandler(),
+ new Object[]{"HopeThisIsAnUnknownDialect"});
+
+ assertEquals(0,metadata.length);
+ }
+
+ /**
+ * Test the MetadataExchange interface with an unknown metadata dialect.
+ *
+ * <br>precondition : the GetMetadata request contains an unknown dialect.
+ * <br>postcondition : the returned metadata section is empty.
+ */
+ @SuppressWarnings("unchecked")
+ public void testGetMetadataKO_WithoutUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+
+ _resourceClient.invoke(getProxyHandler(), new Object[]{""});
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+
+ /**
+ * Returns a proxy handler used for working with metadata exchange
+ * interface.
+ *
+ * @return a metadata proxy handler.
+ */
+ private ProxyHandler getProxyHandler()
+ {
+ ProxyHandler getMetadataHandler = new ReflectionProxyHandler();
+ getMetadataHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata");
+ getMetadataHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", "wsx"));
+ getMetadataHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", "wsx")});
+ getMetadataHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", "wsx"));
+ getMetadataHandler.setReturnType(Element[].class);
+ return getMetadataHandler;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java
new file mode 100644
index 0000000000..afc4a62085
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java
@@ -0,0 +1,580 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+
+import org.apache.muse.core.proxy.ProxyHandler;
+import org.apache.muse.core.proxy.ReflectionProxyHandler;
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.wsdm.capabilities.Result;
+
+/**
+ * Test case for QMan operation invocation interface.
+ *
+ * @author Andrea Gazzarini
+ */
+public class OperationInvocationInterfaceTestCase extends BaseWsDmAdapterTestCase
+{
+ private Map<String, ProxyHandler> _invocationHandlers = createInvocationHandlers();
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of a byte type array between requestor
+ * and service provider.
+ *
+ * <br>precondition : a WS-Resource exists and is registered and the requested
+ * operation is available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is thrown
+ * and byte array are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withByteArray() throws Exception
+ {
+ byte [] expectedByteResult = {1,3,4,2,2,44,22,3,3,55,66};
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithByteArray"),
+ new Object[]{expectedByteResult});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+
+ Map<String,Object> out = (Map<String, Object>) getOutputParameters.invoke(result);
+
+ assertEquals("Output parameters must be 1.",1,out.size());
+ assertArrayEquals(expectedByteResult, out.get(byte[].class.getName()));
+ }
+
+ /**
+ * Test a simple operation invocation on a WS-Resource.
+ * This method tests a simple operation without any input and output parameters.
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested operation
+ * is available on that.
+ * <br>postcondition : invocations are executed successfully an no exception is thrown.
+ */
+ @SuppressWarnings("unchecked")
+ public void testSimpleOperationInvocationOK() throws Exception
+ {
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("voidWithoutArguments"),
+ null);
+
+ assertNotNull(result);
+ }
+
+ /**
+ * Test a the invocation on a WS-Resource with a method that throws an exception..
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested
+ * operation is available on that.
+ * <br>postcondition : an exception is thrown by the requested method.
+ */
+ @SuppressWarnings("unchecked")
+ public void testInvocationException_OK() throws Exception
+ {
+ try
+ {
+ _resourceClient.invoke(
+ _invocationHandlers.get("throwsException"),
+ null);
+ fail("The requested operation has thrown an exception so a Soap Fault is expected...");
+ } catch(SoapFault expected)
+ {
+ }
+ }
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of UUID type between requestor and service provider.
+ *
+ * <br>precondition : a WS-Resource exists and is registered and the requested operation
+ * is available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is thrown
+ * and parameters are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withUUID() throws Exception
+ {
+ UUID expectedUuid = UUID.randomUUID();
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithUUID"),
+ new Object[]{expectedUuid});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+
+ Map<String,Object> out = (Map<String, Object>) getOutputParameters.invoke(result);
+
+ assertEquals("Output parameters must be 1.",1,out.size());
+ assertEquals(expectedUuid, out.get("uuid"));
+ }
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of Map type between requestor and service provider.
+ * For this test exchanged arrays contain :
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested
+ * operation is available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is
+ * thrown and parameters are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withMap() throws Exception
+ {
+ Map<String,Object> expectedMap = new HashMap<String, Object>();
+ expectedMap.put("p1", new Long(1));
+ expectedMap.put("p2", Boolean.TRUE);
+ expectedMap.put("p3", 1234d);
+ expectedMap.put("p4", 11.2f);
+ expectedMap.put("p5", 1272);
+ expectedMap.put("p6", (short)12);
+ expectedMap.put("p7", "aString");
+ expectedMap.put("p8", "http://qpid.apache.org");
+ expectedMap.put("p9", new Date(12383137128L));
+ expectedMap.put("p10", new byte[]{1,2,2,3,3,4});
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithMap"),
+ new Object[]{expectedMap});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+
+ Map<String,Object> out = (Map<String, Object>) ((Map<String, Object>) getOutputParameters.invoke(result)).get("map");
+
+ assertEquals("Output parameters must be 10.",10,out.size());
+ assertEquals(expectedMap.get("p1"),out.get("p1"));
+ assertEquals(expectedMap.get("p2"),out.get("p2"));
+ assertEquals(expectedMap.get("p3"),out.get("p3"));
+ assertEquals(expectedMap.get("p4"),out.get("p4"));
+ assertEquals(expectedMap.get("p5"),out.get("p5"));
+ assertEquals(expectedMap.get("p6"),out.get("p6"));
+ assertEquals(expectedMap.get("p7"),out.get("p7"));
+ assertEquals(expectedMap.get("p8"),out.get("p8"));
+ assertEquals(expectedMap.get("p9"),out.get("p9"));
+ assertTrue( Arrays.equals((byte[])expectedMap.get("p10"),(byte[])out.get("p10")));
+ }
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of simple types between requestor and
+ * service provider.
+ *
+ * With simple types we mean :
+ *
+ * <ul>
+ * <li>java.lang.Long / long (xsd:long)
+ * <li>java.lang.Integer / int (xsd:int / xsd:integer)
+ * <li>java.lang.Double/ double (xsd:double)
+ * <li>java.lang.Float / float (xsd:float)
+ * <li>java.lang.Short / short (xsd:short)
+ * <li>java.lang.Boolean / boolean (xsd:boolean)
+ * <li>java.lang.String (xsd:string)
+ * <li>java.net.URI (xsd:anyURI)
+ * <li>java.util.Date(xsd:dateTime)
+ * </ul>
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested operation is
+ * available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is thrown and
+ * parameters are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withSimpleTypes() throws Exception
+ {
+ Long expectedLongResult = new Long(1373);
+ Boolean expectedBooleanResult = Boolean.TRUE;
+ Double expectedDoubleResult = new Double(12763.44);
+ Float expectedFloatResult = new Float(2727.233f);
+ Integer expectedIntegerResult = new Integer(28292);
+ Short expectedShortResult = new Short((short)227);
+ String expectedStringResult = "expectedStringResult";
+ URI expectedUriResult = URI.create("http://qpid.apache.org/");
+ Date expectedDateResult = new Date();
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithSimpleTypes"),
+ new Object[]{
+ expectedLongResult,
+ expectedBooleanResult,
+ expectedDoubleResult,
+ expectedFloatResult,
+ expectedIntegerResult,
+ expectedShortResult,
+ expectedStringResult,
+ expectedUriResult,
+ expectedDateResult});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+ Map<String,Object> out = (Map<String, Object>) getOutputParameters.invoke(result);
+
+ assertEquals("Output parameters must be 9.",9,out.size());
+ assertTrue("Long output parameter not found on result object.",out.containsValue(expectedLongResult));
+ assertTrue("Boolean output parameter not found on result object.",out.containsValue(expectedBooleanResult));
+ assertTrue("Double output parameter not found on result object.",out.containsValue(expectedDoubleResult));
+ assertTrue("Float output parameter not found on result object.",out.containsValue(expectedFloatResult));
+ assertTrue("Integer output parameter not found on result object.",out.containsValue(expectedIntegerResult));
+ assertTrue("Short output parameter not found on result object.",out.containsValue(expectedShortResult));
+ assertTrue("String output parameter not found on result object.",out.containsValue(expectedStringResult));
+ assertTrue("URI output parameter not found on result object.",out.containsValue(expectedUriResult));
+ assertTrue("Date output parameter not found on result object.",out.containsValue(expectedDateResult));
+ }
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of arrays between requestor and service provider.
+ * For this test exchanged arrays contain :
+ *
+ * <ul>
+ * <li>java.lang.Long (xsd:long)
+ * <li>java.lang.Integer (xsd:int / xsd:integer)
+ * <li>java.lang.Double (xsd:double)
+ * <li>java.lang.Float (xsd:float)
+ * <li>java.lang.Short (xsd:short)
+ * <li>java.lang.Boolean (xsd:boolean)
+ * <li>java.lang.String (xsd:string)
+ * <li>java.net.URI (xsd:anyURI)
+ * <li>java.util.Date(xsd:dateTime)
+ * </ul>
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested operation is available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is thrown and parameters are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withWrapperArrays() throws Exception
+ {
+ Long [] expectedLongResult = {new Long(2),new Long(1),new Long(3),new Long(4)};
+ Boolean [] expectedBooleanResult = { Boolean.TRUE,Boolean.FALSE,Boolean.FALSE};
+ Double [] expectedDoubleResult = {12763.44d,2832.33d,2292.33d,22293.22d};
+ Float [] expectedFloatResult = {2727.233f,1f,2f,4f,5.4f,33.2f};
+ Integer [] expectedIntegerResult = {1,2,3,4,55,66,77,88,99};
+ Short [] expectedShortResult = {(short)227,(short)23,(short)9};
+ String [] expectedStringResult = {"s1","s2","s333","s4"};
+ URI [] expectedUriResult = {
+ URI.create("http://qpid.apache.org/"),
+ URI.create("http://www.apache.org"),
+ URI.create("http://projects.apache.org")};
+
+ Date [] expectedDateResult = {
+ new Date(),
+ new Date(38211897),
+ new Date(903820382)};
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithArrays"),
+ new Object[]{
+ expectedLongResult,
+ expectedBooleanResult,
+ expectedDoubleResult,
+ expectedFloatResult,
+ expectedIntegerResult,
+ expectedShortResult,
+ expectedStringResult,
+ expectedUriResult,
+ expectedDateResult});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+ Map<String,Object> out = (Map<String, Object>) getOutputParameters.invoke(result);
+
+ assertEquals("Output parameters must be 9.",9,out.size());
+ assertTrue("Long array doesn't match.",Arrays.equals(expectedLongResult, (Long[])out.get(Long.class.getName())));
+ assertTrue("Boolean array doesn't match.",Arrays.equals(expectedBooleanResult, (Boolean[])out.get(Boolean.class.getName())));
+ assertTrue("Double array doesn't match.",Arrays.equals(expectedDoubleResult, (Double[])out.get(Double.class.getName())));
+ assertTrue("Float array doesn't match.",Arrays.equals(expectedFloatResult, (Float[])out.get(Float.class.getName())));
+ assertTrue("Integer array doesn't match.", Arrays.equals(expectedIntegerResult, (Integer[])out.get(Integer.class.getName())));
+ assertTrue("Short array doesn't match.",Arrays.equals(expectedShortResult, (Short[])out.get(Short.class.getName())));
+ assertTrue("String array doesn't match.",Arrays.equals(expectedStringResult, (String[])out.get(String.class.getName())));
+ assertTrue("URI array doesn't match.",Arrays.equals(expectedUriResult, (URI[])out.get(URI.class.getName())));
+ assertTrue("Date array doesn't match.",Arrays.equals(expectedDateResult, (Date[])out.get(Date.class.getName())));
+ }
+
+ /**
+ * Test operation invocation on WS-Resource.
+ * This method tests the exchange of primitive type arrays between requestor and service provider.
+ * NOte that even the sent array contain primtiive type QMan deals only with objects so in the result
+ * object you will find the corresponding wrapper types.
+ *
+ * For this test exchanged arrays contain :
+ *
+ * <ul>
+ * <li>java.lang.Long / long (xsd:long)
+ * <li>java.lang.Integer / int (xsd:int / xsd:integer)
+ * <li>java.lang.Double/ double (xsd:double)
+ * <li>java.lang.Float / float (xsd:float)
+ * <li>java.lang.Short / short (xsd:short)
+ * <li>java.lang.Boolean / boolean (xsd:boolean)
+ * </ul>
+ *
+ * <br>precondition : a ws resource exists and is registered and the requested operation is available on that.
+ * <br>postcondition : invocations are executed successfully, no exception is thrown and parameters are correctly returned.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOperationInvocationOK_withPrimitiveArrays() throws Exception
+ {
+ long [] expectedLongResult = {1L,2L,3L,4L};
+ boolean [] expectedBooleanResult = { true,false,false};
+ double [] expectedDoubleResult = {12763.44d,2832.33d,2292.33d,22293.22d};
+ float [] expectedFloatResult = {2727.233f,1f,2f,4f,5.4f,33.2f};
+ int [] expectedIntegerResult = {1,2,3,4,55,66,77,88,99};
+ short [] expectedShortResult = {(short)227,(short)23,(short)9};
+
+ Object result = _resourceClient.invoke(
+ _invocationHandlers.get("echoWithSimpleTypeArrays"),
+ new Object[]{
+ expectedLongResult,
+ expectedBooleanResult,
+ expectedDoubleResult,
+ expectedFloatResult,
+ expectedIntegerResult,
+ expectedShortResult});
+
+ Method getOutputParameters = result.getClass().getMethod("getOutputParameters");
+ Map<String,Object> out = (Map<String, Object>) getOutputParameters.invoke(result);
+
+ assertEquals("Output parameters must be 6.",6,out.size());
+ assertArrayEquals(expectedLongResult, out.get(long.class.getName()));
+ assertArrayEquals(expectedBooleanResult, out.get(boolean.class.getName()));
+ assertArrayEquals(expectedDoubleResult, out.get(double.class.getName()));
+ assertArrayEquals(expectedFloatResult, out.get(float.class.getName()));
+ assertArrayEquals(expectedIntegerResult, out.get(int.class.getName()));
+ assertArrayEquals(expectedShortResult, out.get(short.class.getName()));
+ }
+
+ /**
+ * Internal method used for array comparison using reflection.
+ *
+ * @param expectedArray the expected array.
+ * @param resultArray the array that must match the expected one.
+ */
+ private void assertArrayEquals(Object expectedArray, Object resultArray)
+ {
+ int expectedArrayLength = Array.getLength(expectedArray);
+ int resultArrayLength = Array.getLength(resultArray);
+
+ assertEquals(expectedArrayLength,resultArrayLength);
+
+ for (int index = 0; index < expectedArrayLength; index++)
+ {
+ Object expected = Array.get(expectedArray, index);
+ Object result = Array.get(resultArray, index);
+
+ assertEquals(expected,result);
+ }
+ }
+
+ private Map<String,ProxyHandler> createInvocationHandlers()
+ {
+ Map<String, ProxyHandler> handlers = new HashMap<String, ProxyHandler>();
+
+ ProxyHandler handler = new ReflectionProxyHandler();
+ handler.setAction(Names.NAMESPACE_URI+"/"+"voidWithoutArguments");
+ handler.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "voidWithoutArgumentsRequest",
+ Names.PREFIX));
+ handler.setRequestParameterNames(new QName[]{});
+ handler.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "voidWithoutArgumentsResponse",
+ Names.PREFIX));
+ handler.setReturnType(Result.class);
+
+ ProxyHandler exceptionHandler = new ReflectionProxyHandler();
+ exceptionHandler.setAction(Names.NAMESPACE_URI+"/"+"throwsException");
+ exceptionHandler.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "throwsExceptionRequest",
+ Names.PREFIX));
+
+ exceptionHandler.setRequestParameterNames(new QName[]{});
+ exceptionHandler.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "throwsExceptionResponse",
+ Names.PREFIX));
+
+ exceptionHandler.setReturnType(Result.class);
+
+ ProxyHandler echoWithWrapperTypesHandler = new ReflectionProxyHandler();
+ echoWithWrapperTypesHandler.setAction(Names.NAMESPACE_URI+"/"+"echoWithSimpleTypes");
+ echoWithWrapperTypesHandler.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithSimpleTypesRequest",
+ Names.PREFIX));
+
+ echoWithWrapperTypesHandler.setRequestParameterNames(new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p7",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p8",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p9",Names.PREFIX),
+ });
+
+ echoWithWrapperTypesHandler.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithSimpleTypesResponse",
+ Names.PREFIX));
+
+ echoWithWrapperTypesHandler.setReturnType(Result.class);
+
+ ProxyHandler echoWithArrayOfWrapperTypes = new ReflectionProxyHandler();
+ echoWithArrayOfWrapperTypes.setAction(Names.NAMESPACE_URI+"/"+"echoWithArrays");
+ echoWithArrayOfWrapperTypes.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithArraysRequest",
+ Names.PREFIX));
+
+ echoWithArrayOfWrapperTypes.setRequestParameterNames(new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p7",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p8",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p9",Names.PREFIX),
+ });
+
+ echoWithArrayOfWrapperTypes.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithArraysResponse",
+ Names.PREFIX));
+
+ echoWithArrayOfWrapperTypes.setReturnType(Result.class);
+
+ ProxyHandler echoWithArrayOfPrimitiveTypes = new ReflectionProxyHandler();
+ echoWithArrayOfPrimitiveTypes.setAction(Names.NAMESPACE_URI+"/"+"echoWithSimpleTypeArrays");
+ echoWithArrayOfPrimitiveTypes.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithSimpleTypeArraysRequest",
+ Names.PREFIX));
+
+ echoWithArrayOfPrimitiveTypes.setRequestParameterNames(new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX),
+ new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX)});
+
+ echoWithArrayOfPrimitiveTypes.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithSimpleTypeArraysResponse",
+ Names.PREFIX));
+
+ echoWithArrayOfPrimitiveTypes.setReturnType(Result.class);
+
+ ProxyHandler echoWithByteArray = new EnhancedReflectionProxyHandler();
+ echoWithByteArray.setAction(Names.NAMESPACE_URI+"/"+"echoWithByteArray");
+ echoWithByteArray.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithByteArrayRequest",
+ Names.PREFIX));
+
+ echoWithByteArray.setRequestParameterNames(
+ new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)});
+
+ echoWithByteArray.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithByteArrayResponse",
+ Names.PREFIX));
+
+ echoWithByteArray.setReturnType(Result.class);
+
+ ProxyHandler echoWithUUID = new EnhancedReflectionProxyHandler();
+ echoWithUUID.setAction(Names.NAMESPACE_URI+"/"+"echoWithUUID");
+ echoWithUUID.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithUUIDRequest",
+ Names.PREFIX));
+
+ echoWithUUID.setRequestParameterNames(
+ new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)});
+
+ echoWithUUID.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithUUIDResponse",
+ Names.PREFIX));
+
+ echoWithUUID.setReturnType(Result.class);
+
+ ProxyHandler echoWithMap = new EnhancedReflectionProxyHandler();
+ echoWithMap.setAction(Names.NAMESPACE_URI+"/"+"echoWithMap");
+ echoWithMap.setRequestName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithMapRequest",
+ Names.PREFIX));
+
+ echoWithMap.setRequestParameterNames(
+ new QName[]{
+ new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)});
+
+ echoWithMap.setResponseName(
+ new QName(
+ Names.NAMESPACE_URI,
+ "echoWithMapResponse",
+ Names.PREFIX));
+
+ echoWithMap.setReturnType(Result.class);
+
+ handlers.put("voidWithoutArguments",handler);
+ handlers.put("echoWithSimpleTypes",echoWithWrapperTypesHandler);
+ handlers.put("echoWithArrays",echoWithArrayOfWrapperTypes);
+ handlers.put("echoWithSimpleTypeArrays", echoWithArrayOfPrimitiveTypes);
+ handlers.put("echoWithByteArray", echoWithByteArray);
+ handlers.put("echoWithUUID", echoWithUUID);
+ handlers.put("echoWithMap", echoWithMap);
+ handlers.put("throwsException",exceptionHandler);
+ return handlers;
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java
new file mode 100644
index 0000000000..6574c278ff
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.io.File;
+
+import org.apache.qpid.management.Names;
+import org.mortbay.component.LifeCycle.Listener;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.webapp.WebAppContext;
+import org.mortbay.start.Monitor;
+
+/**
+ * Web Server startup thread.
+ * It is used on adapter test case in order to start the embedded
+ * web server as a separated thread.
+ *
+ * @author Andrea Gazzarini
+ */
+class ServerThread extends Thread
+{
+ private final Listener _lifecycleListener;
+ private Server _server;
+
+ private SelectChannelConnector _connector;
+
+ /**
+ * Builds a new server thread with the given lifecycle listener.
+ *
+ * @param listener the lifecycle listener.
+ */
+ ServerThread(Listener listener)
+ {
+ this._lifecycleListener = listener;
+ }
+
+ /**
+ * Starts the server.
+ */
+ @Override
+ public void run()
+ {
+ try
+ {
+ Monitor.monitor();
+ _server = new Server();
+ _server.setStopAtShutdown(true);
+
+ _connector=new SelectChannelConnector();
+ _connector.setPort(Integer.parseInt(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME)));
+ _connector.setHost(System.getProperty(Names.ADAPTER_HOST_PROPERTY_NAME));
+
+
+ _server.setConnectors(new Connector[]{_connector});
+
+ WebAppContext webapp = new WebAppContext();
+ webapp.setContextPath("/qman");
+
+ // Additional web application descriptor containing test components.
+ webapp.setDefaultsDescriptor("/org/apache/qpid/management/wsdm/web.xml");
+
+ String webApplicationPath = System.getProperty("qman.war");
+ File rootFolderPath = (webApplicationPath != null) ? new File(webApplicationPath) : new File(".");
+
+ webapp.setWar(rootFolderPath.toURI().toURL().toExternalForm());
+ webapp.addLifeCycleListener(_lifecycleListener);
+ _server.setHandler(webapp);
+ _server.start();
+ System.setProperty(Names.ADAPTER_PORT_PROPERTY_NAME,String.valueOf( _connector.getLocalPort()));
+ _server.join();
+
+ } catch(Exception exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+
+ /**
+ * Shutdown the server.
+ *
+ * @throws Exception when a problem is encountered during shutdown.
+ */
+ void shutdown() throws Exception
+ {
+ _server.stop();
+ }
+
+ /**
+ * Returns the port number where the server is running.
+ *
+ * @return the port number where the server is running.
+ */
+ int getPort()
+ {
+ return _connector.getLocalPort();
+ }
+
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java
new file mode 100644
index 0000000000..87f8905e01
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java
@@ -0,0 +1,219 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.lang.reflect.Array;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.management.MBeanAttributeInfo;
+import javax.xml.namespace.QName;
+
+import org.apache.muse.ws.addressing.soap.SoapFault;
+import org.apache.muse.ws.resource.WsrfConstants;
+import org.apache.qpid.management.Names;
+
+/**
+ * Test case for Set Resource Properties interfaces.
+ *
+ * @author Andrea Gazzarini
+ */
+public class SetResourcePropertiesTestCase extends BaseWsDmAdapterTestCase
+{
+ /**
+ * Test the WS-RP SetResourceProperty interface of the WS-DM adapter.
+ *
+ * <br>precondition : a WS-Resource exists and is registered.
+ * <br>postcondition : property values are correctly updated on the target WS-Resource..
+ */
+ public void testSetResourcePropertiesOK() throws Exception
+ {
+ Map<String, Object> sampleMap = new HashMap<String, Object>();
+ sampleMap.put("Key1", "BLABALABLABALBAL");
+ sampleMap.put("Key2", 182838484l);
+ sampleMap.put("Key3", -928376362);
+ sampleMap.put("Key4", 23762736276.33D);
+ sampleMap.put("Key4", 2327363.2F);
+
+ Map<String, Object> sampleValues = new HashMap<String, Object>();
+ sampleValues.put(String.class.getName(),"SAMPLE_STRING");
+ sampleValues.put(UUID.class.getName(),UUID.randomUUID());
+ sampleValues.put(Boolean.class.getName(),Boolean.FALSE);
+ sampleValues.put(Map.class.getName(),sampleMap);
+ sampleValues.put(Long.class.getName(),283781273L);
+ sampleValues.put(Integer.class.getName(),12727);
+ sampleValues.put(Short.class.getName(),new Short((short)22));
+ sampleValues.put(Date.class.getName(),new Date());
+
+ MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes();
+ boolean atLeastThereIsOneWritableProperty = false;
+
+ for (MBeanAttributeInfo attributeMetadata : attributesMetadata)
+ {
+ String name = attributeMetadata.getName();
+
+ if (attributeMetadata.isWritable())
+ {
+ atLeastThereIsOneWritableProperty = true;
+ Object sampleValue = sampleValues.get(attributeMetadata.getType());
+ Object []values = new Object[]{sampleValue};
+
+ Object result = _managementServer.getAttribute(_resourceObjectName, name);
+ if (result == null)
+ {
+ _resourceClient.insertResourceProperty(
+ new QName(
+ Names.NAMESPACE_URI,
+ name,
+ Names.PREFIX),
+ values);
+ } else
+ {
+ _resourceClient.updateResourceProperty(
+ new QName(
+ Names.NAMESPACE_URI,
+ name,
+ Names.PREFIX),
+ values);
+ }
+
+ Object propertyValues = _resourceClient.getPropertyAsObject(
+ new QName(
+ Names.NAMESPACE_URI,
+ name,
+ Names.PREFIX),
+ Class.forName(attributeMetadata.getType()));
+ int length = Array.getLength(propertyValues);
+ if (length != 0)
+ {
+ Object propertyValue = Array.get(propertyValues, 0);
+
+ assertEquals(
+ "Comparison failed for property "+name,
+ sampleValue,
+ propertyValue);
+ } else {
+ assertNull(
+ String.format(
+ "\"%s\" property value shouldn't be null. Its value is %s",
+ name,
+ _managementServer.getAttribute(_resourceObjectName,name)),
+ sampleValue);
+ }
+ }
+ }
+ assertTrue(
+ "It's not possibile to run successfully this test case if " +
+ "the target WS-Resource has no at least one writable property",
+ atLeastThereIsOneWritableProperty);
+ }
+
+ /**
+ * Test the WS-RP SetResourceProperty interface of the WS-DM adapter when the
+ * target property is null.
+ * According to WS-RP specs this operation is not allowed because in this case a SetResourceProperty with an "Insert"
+ * message should be sent in order to initialize the property.
+ *
+ * <br>precondition : a ws resource exists and is registered. The value of the target property is null.
+ * <br>postcondition : a Soap fault is received indicating the failuire.
+ */
+ public void testSetResourcePropertiesKO() throws Exception
+ {
+ Object typePropertyValue = _managementServer.getAttribute(_resourceObjectName, "Type");
+ assertNull(typePropertyValue);
+
+ try
+ {
+ _resourceClient.updateResourceProperty(
+ new QName(
+ Names.NAMESPACE_URI,
+ "Type",
+ Names.PREFIX),
+ new Object[]{"sampleValue"});
+ fail(
+ "If the property is null on the target ws resource, according " +
+ "to WS-RP specs, an update of its value is not possible.");
+ } catch(SoapFault expected)
+ {
+
+ }
+ }
+
+ /**
+ * Tests the SetResourceProperties (update) interface when the request contains
+ * an unknwon target resource.
+ *
+ * <br>precondition : the SetResourceProperties contains an unknwon resource.
+ * <br>postcondition : a SoapFault is thrown and the corresponding detail contains an
+ * UnknownResourceFault element.
+ */
+ public void testUpdateResourcePropertiesKO_WithUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+
+ _resourceClient.updateResourceProperty(
+ new QName(
+ Names.NAMESPACE_URI,
+ "Type",
+ Names.PREFIX),
+ new Object[]{"sampleValue"});
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+
+ /**
+ * Tests the SetResourceProperties (insert) interface when the request contains
+ * an unknwon target resource.
+ *
+ * <br>precondition : the SetResourceProperties contains an unknwon resource.
+ * <br>postcondition : a SoapFault is thrown and the corresponding detail contains an
+ * UnknownResourceFault element.
+ */
+ public void testInsertResourcePropertiesKO_WithUnknownResourceFault() throws Exception
+ {
+ try
+ {
+ _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME);
+ _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal");
+
+ _resourceClient.insertResourceProperty(
+ new QName(
+ Names.NAMESPACE_URI,
+ "Type",
+ Names.PREFIX),
+ new Object[]{"sampleValue"});
+ } catch(SoapFault expected)
+ {
+ assertEquals(
+ WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(),
+ expected.getDetail().getLocalName());
+ }
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java
new file mode 100644
index 0000000000..91c646467e
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import org.mortbay.component.LifeCycle;
+import org.mortbay.component.LifeCycle.Listener;
+
+/**
+ * Adapter class used to provide an empty (base) implementation of
+ * Lifecycle listener interface.
+ *
+ * Adapter test case needs to be informed about the lifecycle of the
+ * deployed QMan application. Only when its deployment is completed the test
+ * case can run successfully.
+ *
+ * So, following the same logic of Swng event model, this is an adapter that provides
+ * empty implementation of the listener interface (see for example MouseAdapter
+ * for mouse events listener)
+ *
+ * @author Andrea Gazzarini
+ */
+public class WebApplicationLifeCycleListener implements Listener
+{
+ public void lifeCycleFailure(LifeCycle event, Throwable cause)
+ {
+ }
+
+ public void lifeCycleStarted(LifeCycle event)
+ {
+ }
+
+ public void lifeCycleStarting(LifeCycle event)
+ {
+ }
+
+ public void lifeCycleStopped(LifeCycle event)
+ {
+ }
+
+ public void lifeCycleStopping(LifeCycle event)
+ {
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java
new file mode 100644
index 0000000000..f12288c91d
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java
@@ -0,0 +1,156 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.muse.core.serializer.SerializerRegistry;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.Protocol;
+import org.apache.qpid.management.wsdm.capabilities.Result;
+import org.apache.qpid.management.wsdm.muse.serializer.DateSerializer;
+import org.apache.qpid.management.wsdm.muse.serializer.InvocationResultSerializer;
+import org.apache.qpid.management.wsdm.muse.serializer.MapSerializer;
+import org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer;
+import org.apache.qpid.management.wsdm.muse.serializer.UUIDSerializer;
+import org.mortbay.component.LifeCycle;
+import org.mortbay.component.LifeCycle.Listener;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class WsDmAdapterTest
+{
+
+ /**
+ * Test case wide set up.
+ * Provides Server startup & shutdown global procedure.
+ *
+ * @author Andrea Gazzarini
+ */
+ private static class WsDmAdapterTestSetup extends TestSetup
+ {
+ private Object _serverMonitor = new Object();
+
+ Listener listener = new WebApplicationLifeCycleListener()
+ {
+ public void lifeCycleStarted(LifeCycle event)
+ {
+ synchronized (_serverMonitor)
+ {
+ _serverMonitor.notify();
+ }
+ }
+ };
+
+ private ServerThread _server;
+
+ /**
+ * Builds a new test setup with for the given test.
+ *
+ * @param test the decorated test.
+ */
+ public WsDmAdapterTestSetup(Test test)
+ {
+ super(test);
+ }
+
+ /**
+ * Starts up Web server.
+ *
+ * @throws Exception when the server startup fails.
+ */
+ @Override
+ protected void setUp() throws Exception
+ {
+ SerializerRegistry.getInstance().registerSerializer(Object.class, new ObjectSerializer());
+ SerializerRegistry.getInstance().registerSerializer(Date.class, new DateSerializer());
+ SerializerRegistry.getInstance().registerSerializer(Map.class, new MapSerializer());
+ SerializerRegistry.getInstance().registerSerializer(HashMap.class, new MapSerializer());
+ SerializerRegistry.getInstance().registerSerializer(UUID.class, new UUIDSerializer());
+ SerializerRegistry.getInstance().registerSerializer(Result.class, new InvocationResultSerializer());
+
+ System.setProperty(
+ Names.ADAPTER_HOST_PROPERTY_NAME,
+ Protocol.DEFAULT_QMAN_HOSTNAME);
+
+ System.setProperty(
+ Names.ADAPTER_PORT_PROPERTY_NAME,
+ String.valueOf(getFreePort()));
+
+ _server = new ServerThread(listener);
+ _server.start();
+
+ synchronized(_serverMonitor) {
+ _serverMonitor.wait();
+ Thread.sleep(2000);
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ _server.shutdown();
+ }
+ };
+
+ /**
+ * Gets the test suite composition.
+ *
+ * @return the test suite composition.
+ */
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite("Test suite for QMan WS-DM.");
+ /*suite.addTestSuite(MetadataExchangeInterfaceTestCase.class);
+ suite.addTestSuite(OperationInvocationInterfaceTestCase.class);
+ suite.addTestSuite(GetResourcePropertyDocumentTestCase.class);
+ suite.addTestSuite(SetResourcePropertiesTestCase.class);
+ suite.addTestSuite(GetMultipleResourcePropertiesTestCase.class);
+ suite.addTestSuite(GetResourcePropertiesTestCase.class); */
+ return new WsDmAdapterTestSetup(suite);
+ }
+
+ /**
+ * Finds a free port that will be used to run the embedded
+ * web server.
+ *
+ * @return a free port that will be used to run the
+ * embedded web server.
+ */
+ private static int getFreePort() throws IOException {
+ ServerSocket server = null;
+ try
+ {
+ server = new ServerSocket(0);
+ return server.getLocalPort();
+ } finally
+ {
+ server.close();
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java
new file mode 100644
index 0000000000..68c9930ecd
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java
@@ -0,0 +1,335 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javassist.CtClass;
+import javassist.CtMethod;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.xml.namespace.QName;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.domain.handler.impl.QpidDomainObject;
+import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault;
+import org.apache.qpid.management.wsdm.common.MethodInvocationFault;
+import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault;
+import org.apache.qpid.management.wsdm.common.QManFault;
+
+/**
+ * Test case for MBean capability builder.
+ *
+ * @author Andrea Gazzarini
+ */
+public class MBeanCapabilityBuilderTest extends TestCase
+{
+
+ /**
+ * Management interface for an mbean that has no properties and no
+ * methods.
+ *
+ * @author Andrea Gazzarini
+ */
+ public interface NoPropertiesNoMethodsMBean
+ {
+ }
+
+ /**
+ * Implementation of the managenent interface described above.
+ *
+ * @author Andrea Gazzarini
+ */
+ public class NoPropertiesNoMethods implements NoPropertiesNoMethodsMBean
+ {
+ }
+
+ private MBeanCapabilityBuilder _builder;
+ private ObjectName _objectName;
+
+ /**
+ * Set up fixture for this test case.
+ */
+ protected void setUp() throws Exception
+ {
+ _builder = new MBeanCapabilityBuilder();
+ _objectName = new ObjectName("Test:Name=aName,class=DomainObject");
+ }
+
+ /**
+ * Tests that state change that occcurs on the begin() method when the requested
+ * class has not been defined.
+ */
+ public void testBegin_withClassNotYetDefined() throws Exception
+ {
+ _builder.begin(_objectName);
+ assertEquals(_builder._state,_builder._classNotAvailable);
+ }
+
+ /**
+ * Tests that state change that occcurs on the begin() method when the requested
+ * class has not been defined.
+ */
+ public void testBegin_withClassAlreadyDefined() throws Exception
+ {
+ _objectName = new ObjectName("Test:Name=aString,class=MBeanCapabilityBuilder");
+ _builder.begin(_objectName);
+
+ assertTrue(_builder._state instanceof DummyCapabilityBuilder);
+ assertSame(_builder._endAttributeHandler, _builder._noPropertyHasBeenDefined);
+ }
+
+ /**
+ * Tests the generateGetter method().
+ */
+ public void testGenerateGetter()
+ {
+ String name ="MyProperty";
+ String type = Long.class.getName();
+ String expected =
+ "public "+
+ type+
+ " get"+
+ name+
+ "() throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { return ("+
+ type+
+ ") getAttribute(\""+
+ name+
+ "\"); }";
+
+ String result = _builder.generateGetter(type, name,name);
+ assertEquals(expected,result);
+ }
+
+ /**
+ * Tests the generateGetter method().
+ */
+ public void testGenerateSetter()
+ {
+ String name ="MyProperty";
+ String type = Long.class.getName();
+ String expected =
+ "public void setMyProperty("+
+ type+
+ " newValue) throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { setAttribute(\""+
+ name+
+ "\", newValue); }";
+
+ String result = _builder.generateSetter(type, name,name);
+ assertEquals(expected,result);
+ }
+
+ /**
+ * Tests buils of a capability that has no properties and methods
+ *
+ * <br>precondition : the incoming entity definition is empty (no properties and no methods)
+ * <br>postcondition : the capability class is built successfully and has no props and methods.
+ * The getPropertyNames returns an empty QName array.
+ */
+ public void testOK_WithNoPropertiesNoMethods() throws Exception {
+
+ ObjectName name = new ObjectName("Test:Name=NoPropertiesNoMethods");
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ server.registerMBean(new NoPropertiesNoMethods(), name);
+
+ _builder.begin(name);
+ _builder.endAttributes();
+ _builder.endOperations();
+ Class<MBeanCapability> capabilityClass = _builder.getCapabilityClass();
+
+ Field[] fields = capabilityClass.getDeclaredFields();
+ Method [] methods = capabilityClass.getDeclaredMethods();
+
+ assertEquals(Arrays.toString(fields),0,fields.length);
+ assertEquals(Arrays.toString(methods),1,methods.length);
+
+ Method getPropertyNames = methods[0];
+ assertEquals("getPropertyNames",getPropertyNames.getName());
+
+
+ MBeanCapability capability = capabilityClass.newInstance();
+ QName [] properties = (QName[]) getPropertyNames.invoke(capability);
+ assertEquals(0,properties.length);
+ }
+
+ /**
+ * Tests the whole execution of the builder.
+ */
+ @SuppressWarnings("unchecked")
+ public void testBuildOK() throws Exception
+ {
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ QpidDomainObject mbean = new QpidDomainObject();
+ server.registerMBean(mbean, _objectName);
+
+ _builder.begin(_objectName);
+
+ CtClass definition = _builder._capabilityClassDefinition;
+ assertEquals(
+ MBeanCapability.class.getName(),
+ definition.getSuperclass().getName());
+
+ MBeanInfo metadata = server.getMBeanInfo(_objectName);
+
+ for (MBeanAttributeInfo attribute : metadata.getAttributes())
+ {
+ _builder.onAttribute(attribute);
+ checkAttribute(attribute, definition);
+
+ assertSame(
+ _builder._endAttributeHandler,
+ _builder._atLeastThereIsOneProperty);
+ }
+
+ for (MBeanOperationInfo operation : metadata.getOperations())
+ {
+ _builder.onOperation(operation);
+ checkOperation(operation,definition);
+ }
+
+ _builder.endAttributes();
+ _builder.endOperations();
+
+ assertNotNull(_builder.getCapabilityClass());
+ }
+
+ /**
+ * Checks an operation / method after that it has been declared on
+ * capability definition.
+ *
+ * @param operation the (JMX) operation metadata.
+ * @param definition the capability class definition.
+ * @throws Exception when something goes wrong during introspection.
+ */
+ private void checkOperation(MBeanOperationInfo operation, CtClass definition) throws Exception
+ {
+ CtMethod method = definition.getDeclaredMethod(operation.getName());
+ assertNotNull(method);
+
+ checkExceptionTypes(
+ method.getExceptionTypes(),
+ new String[]{
+ QManFault.class.getName(),
+ EntityInstanceNotFoundFault.class.getName(),
+ MethodInvocationFault.class.getName()});
+
+ assertEquals(Result.class.getName(),method.getReturnType().getName());
+
+ CtClass [] parameterTypes = method.getParameterTypes();
+ MBeanParameterInfo [] parameterMetadata = operation.getSignature();
+
+ assertEquals(parameterTypes.length, parameterMetadata.length);
+ for (int i = 0; i < parameterMetadata.length; i++)
+ {
+ assertEquals(
+ parameterTypes[i].getName(),
+ Class.forName(parameterMetadata[i].getType()).getCanonicalName());
+ }
+ }
+
+ /**
+ * Checks the exception types associated with a method.
+ *
+ * @param exceptionTypes the exception types actually thrown.
+ * @param expectedExceptionNames the expected exception types (as strings).
+ */
+ private void checkExceptionTypes(CtClass [] exceptionTypes, String [] expectedExceptionNames)
+ {
+ List<String> exceptionNames = new ArrayList<String>(exceptionTypes.length);
+ for (CtClass exception : exceptionTypes)
+ {
+ exceptionNames.add(exception.getName());
+ }
+
+ for (String expectedExceptionName : expectedExceptionNames)
+ {
+ exceptionNames.remove(expectedExceptionName);
+ }
+
+ assertTrue(exceptionNames.isEmpty());
+ }
+
+ /**
+ * Checks an attribute after that it has been declared on capability definition.
+ *
+ * @param attribute the (JMX) attribute metadata.
+ * @param definition the capability class definition.
+ * @throws Exception when something goes wrong during introspection.
+ */
+ private void checkAttribute(MBeanAttributeInfo attribute, CtClass definition) throws Exception
+ {
+ String name = _builder.getNameForAccessors(attribute.getName());
+
+ String newPropertyDeclaration =
+ new StringBuilder("new QName(Names.NAMESPACE_URI, \"")
+ .append(attribute.getName())
+ .append("\", Names.PREFIX),")
+ .toString();
+ assertTrue(_builder._properties.indexOf(newPropertyDeclaration) != -1);
+
+ if (attribute.isReadable())
+ {
+ CtMethod getter = definition.getDeclaredMethod("get"+name);
+ assertNotNull(getter);
+
+ checkExceptionTypes(
+ getter.getExceptionTypes(),
+ new String[]{
+ QManFault.class.getName(),
+ NoSuchAttributeFault.class.getName(),
+ EntityInstanceNotFoundFault.class.getName()});
+
+ assertEquals(0,getter.getParameterTypes().length);
+ assertEquals(attribute.getType(),getter.getReturnType().getName());
+ }
+
+ if (attribute.isWritable())
+ {
+ CtMethod setter = definition.getDeclaredMethod("set"+name);
+ assertNotNull(setter);
+
+ checkExceptionTypes(
+ setter.getExceptionTypes(),
+ new String[]{
+ QManFault.class.getName(),
+ NoSuchAttributeFault.class.getName(),
+ EntityInstanceNotFoundFault.class.getName()});
+
+ CtClass [] parameterTypes = setter.getParameterTypes();
+
+ assertEquals(1,parameterTypes.length);
+ assertEquals(attribute.getType(),parameterTypes[0].getName());
+ assertEquals(void.class.getName(),setter.getReturnType().getName());
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java
new file mode 100644
index 0000000000..a9a6491209
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.management.ManagementFactory;
+import java.net.URI;
+
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+
+import org.apache.muse.ws.addressing.EndpointReference;
+import org.apache.muse.ws.resource.WsResource;
+import org.apache.muse.ws.resource.impl.SimpleWsResource;
+import org.apache.qpid.management.domain.handler.impl.QpidDomainObject;
+import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault;
+import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault;
+import org.apache.qpid.management.wsdm.common.QManFault;
+
+/**
+ * Test case for MBeanCapability supertype layer..
+ *
+ * @author Andrea Gazzarini
+ */
+public class MBeanCapabilityTest extends TestCase
+{
+ private final String _typeAttributeName = "Type";
+ private final String _newTypeValue = "DomainObject";
+
+ private ObjectName _objectName;
+ private ObjectName _unknownObjectName;
+
+ private MBeanCapability _capability;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ _objectName = new ObjectName("Test:Name=aName");
+ _unknownObjectName = new ObjectName("Test:Type=unknown");
+
+ _capability = new MBeanCapability(){
+ @Override
+ public WsResource getWsResource()
+ {
+ return new SimpleWsResource(){
+ @Override
+ public EndpointReference getEndpointReference()
+ {
+ return new EndpointReference(URI.create("http://qpid.apache.org/qman"));
+ }
+ };
+ }
+ };
+ _capability.setResourceObjectName(_objectName);
+ ManagementFactory.getPlatformMBeanServer().registerMBean(new QpidDomainObject(), _objectName);
+ }
+
+ /**
+ * Tests the execution of the getAttribute() and setAttribute() method.
+ *
+ * <br>precondition : the mbean is registered and a _capability is associated with it.
+ * <br>postcondition : the set value of the requested attribute is correctly returned.
+ */
+ public void testGetAndSetAttributeOK() throws Exception
+ {
+ Object name = _capability.getAttribute(_typeAttributeName);
+ assertNull("Name has an initial value of null so how is possibile that is not null?",name);
+
+ _capability.setAttribute(_typeAttributeName,_newTypeValue);
+
+ name = _capability.getAttribute(_typeAttributeName);
+ assertEquals("Now the name attribute must be set to \""+_newTypeValue+"\"",_newTypeValue,name);
+ }
+
+ /**
+ * Tests the execution of the getAttribute() and setAttribte() methods when an unknown attribute is given..
+ *
+ * <br>precondition : the mbean is registered, a _capability is associated with it and the requested attribute doesn't exist.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testNoSuchAttributeFault() throws Exception
+ {
+ // I suppose that we shouldn't have an attribute with this name...
+ String unknownAttribute = String.valueOf(System.currentTimeMillis());
+
+ try
+ {
+ _capability.getAttribute(unknownAttribute);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(NoSuchAttributeFault expected)
+ {
+ }
+
+ try
+ {
+ _capability.setAttribute(unknownAttribute,null);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(NoSuchAttributeFault expected)
+ {
+ }
+ }
+
+ /**
+ * Tests the execution of the setAttribute,getAttribute and invoke methods when the target mbean
+ * doesn't exists.
+ *
+ * <br>precondition : the object name associated with the capability is not pointing to an existent MBean.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testEntityInstanceNotFoundFault() throws Exception
+ {
+ _capability.setResourceObjectName(_unknownObjectName);
+
+ try
+ {
+ _capability.getAttribute(_typeAttributeName);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(EntityInstanceNotFoundFault expected)
+ {
+ }
+
+ try
+ {
+ _capability.setAttribute(_typeAttributeName,_newTypeValue);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(EntityInstanceNotFoundFault expected)
+ {
+ }
+
+ try
+ {
+ _capability.invoke("operationName", null,null);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(EntityInstanceNotFoundFault expected)
+ {
+ }
+ }
+
+ /**
+ * Tests the execution of the setAttribute,getAttribute and invoke methods when an unknown / unexpected
+ * exception is thrown.
+ *
+ * <br>precondition : the mbean is registered and a capability is associated with it. Something
+ * unexpected happens during method invocation.
+ * <br>postcondition : an exception is thrown indicating the failure.
+ */
+ public void testQManFault() throws Exception
+ {
+ // Emulate a RuntimeException (which is the best example of uncaught exception... :) )
+ _capability.setResourceObjectName(null);
+
+ try
+ {
+ _capability.getAttribute(_typeAttributeName);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(QManFault expected)
+ {
+ }
+
+ try
+ {
+ _capability.setAttribute(_typeAttributeName,_newTypeValue);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(QManFault expected)
+ {
+ }
+
+ try
+ {
+ _capability.invoke("operationName", null,null);
+ fail("An exception must be thrown here in order to indicate that the attribute is unknown.");
+ } catch(QManFault expected)
+ {
+ }
+ }
+
+
+ /**
+ * Shutdown procedure for this test case.
+ */
+ @Override
+ protected void tearDown() throws Exception
+ {
+ ManagementFactory.getPlatformMBeanServer().unregisterMBean(_objectName);
+ }
+}
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java
new file mode 100644
index 0000000000..648c7b2f60
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.apache.muse.ws.notification.NotificationProducer;
+import org.apache.qpid.management.Names;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for QMan adapter capability.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QManAdapterCapabilityTest extends TestCase
+{
+ /**
+ * Tests the execution of the getTopicName() method.
+ *
+ * <br>precondition : an object type is given to the method (null is allowed).
+ * <br>postcondition : according to getTopicName() specs, the name of the
+ * topic associated with the given object type must be returned.
+ */
+ public void testGetTopicName()
+ {
+ final InvocationHandler invocationHandler = new InvocationHandler(){
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ {
+ return null;
+ }
+ };
+
+ QManAdapterCapability capability = new QManAdapterCapability(){
+ @Override
+ NotificationProducer getPublisherCapability()
+ {
+ return (NotificationProducer) Proxy.newProxyInstance(
+ getClass().getClassLoader(),
+ new Class[]{NotificationProducer.class},
+ invocationHandler);
+ }
+ };
+
+ capability.createLifeCycleTopics();
+
+ assertEquals(
+ Names.EVENTS_LIFECYLE_TOPIC_NAME,
+ capability.getTopicName(Names.EVENT));
+
+ assertEquals(
+ Names.OBJECTS_LIFECYLE_TOPIC_NAME,
+ capability.getTopicName(Names.CLASS));
+
+ assertEquals(
+ Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME,
+ capability.getTopicName("This is an unknown object Type @#!--!!@#"));
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java
new file mode 100644
index 0000000000..77cda1c2c1
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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 org.apache.qpid.management.wsdm.capabilities;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.impl.QpidDomainObject;
+import org.w3c.dom.Element;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for Resource Metadata Descriptor Builder.
+ *
+ * @author Andrea Gazzarini
+ */
+public class RmdBuilderTest extends TestCase
+{
+ private MBeanInfo _metadata;
+ private RmdBuilder _builder;
+ private ObjectName _objectName;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+ _objectName = new ObjectName("Test:Name=QpidDomainObject");
+
+ server.registerMBean(new QpidDomainObject(), _objectName);
+ _metadata = server.getMBeanInfo(_objectName);
+
+ _builder = new RmdBuilder();
+ _builder.begin(_objectName);
+
+ assertEquals(_objectName,_builder._objectName);
+ }
+
+ /**
+ * Tests the execution of the onOperation() method.
+ */
+ public void testOnOperation() throws Exception
+ {
+ MBeanAttributeInfo [] attributes = _metadata.getAttributes();
+ for (MBeanAttributeInfo attribute : attributes)
+ {
+ _builder.onAttribute(attribute);
+ }
+
+ Element [] rmd = _builder.getResourceMetadataDescriptor();
+
+ assertEquals(attributes.length,rmd.length);
+
+ for (MBeanAttributeInfo attribute: _metadata.getAttributes())
+ {
+ Element propertyMetadataDescriptor = getPropertyMetadatDescriptor(attribute.getName(), rmd);
+
+ String modifiability = propertyMetadataDescriptor.getAttribute(Names.MODIFIABILITY);
+ String expectedValue =
+ attribute.isWritable()
+ ? Names.READ_WRITE
+ : Names.READ_ONLY;
+ assertEquals(expectedValue,modifiability);
+ }
+ }
+
+ /**
+ * Returns the property metadata descriptor associated with the given attribute name.
+ *
+ * @param name the attribute name.
+ * @param rmd the resource metadata descriptor.
+ * @return the property metadata descriptor associated with the given attribute name.
+ * @throws RuntimeException if metadata for the given attribute is not found.
+ */
+ private Element getPropertyMetadatDescriptor(String name, Element [] rmd)
+ {
+ for (Element propertyMetadataDescriptor : rmd)
+ {
+ if ((Names.PREFIX+":"+name).equals(
+ propertyMetadataDescriptor.getAttribute(Names.NAME_ATTRIBUTE)))
+ {
+ return propertyMetadataDescriptor;
+ }
+ }
+ throw new RuntimeException("Property MetadataDescriptor not found for attribute "+name);
+ }
+} \ No newline at end of file
diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml
new file mode 100644
index 0000000000..df273bd841
--- /dev/null
+++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <servlet>
+ <display-name>Qpid emulator startip</display-name>
+ <servlet-name>QEmu</servlet-name>
+ <servlet-class>org.apache.qpid.management.wsdm.QEmuInitializer</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+</web-app>
diff --git a/java/management/client/web.xml b/java/management/client/web.xml
new file mode 100644
index 0000000000..881fc82f46
--- /dev/null
+++ b/java/management/client/web.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<web-app id="qman" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <description>
+ Q-Man is a Management bridge that exposes one (or several) Qpid
+ broker domain model as MBeans that are accessible through the
+ Java Management Extensions (JMX) and / or WS-DM.
+ </description>
+ <display-name>QManEE</display-name>
+ <listener>
+ <description>
+ Provides lifecycle management for QMan module.
+ </description>
+ <display-name>QMan Lifecycle manager</display-name>
+ <listener-class>org.apache.qpid.management.servlet.QManLifeCycleManager</listener-class>
+ </listener>
+ <servlet>
+ <display-name>QMan Proxy Servlet</display-name>
+ <servlet-name>Proxy</servlet-name>
+ <servlet-class>org.apache.qpid.management.servlet.WSDMAdapter</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+ <servlet>
+ <display-name>View Console (System Overview) Action</display-name>
+ <servlet-name>ViewConsole</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.ConsoleAction</servlet-class>
+ <load-on-startup>5</load-on-startup>
+ </servlet>
+ <servlet>
+ <display-name>View Resources</display-name>
+ <servlet-name>ResourceManagement</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.ResourcesManagementAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>JMX Perspective</display-name>
+ <servlet-name>JmxPerspective</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.JmxPerspectiveAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>WSDM Properties Perspective</display-name>
+ <servlet-name>WsdmPropertiesPerspective</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.WsdmPropertiesPerspectiveAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>WSDM Operations Perspective</display-name>
+ <servlet-name>WsdmOperationsPerspective</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.WsdmOperationsPerspectiveAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>WSDM WSDL Perspective</display-name>
+ <servlet-name>WsdmWsdlPerspective</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.WsdmWsdlPerspectiveAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>WSDM RMD Perspective</display-name>
+ <servlet-name>WsdmRmdPerspective</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.WsdmRmdPerspectiveAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>Logging Configurator</display-name>
+ <servlet-name>LoggingConfiguration</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.LoggingConfigurationAction</servlet-class>
+ </servlet>
+ <servlet>
+ <display-name>Brokers Management</display-name>
+ <servlet-name>BrokersManagement</servlet-name>
+ <servlet-class>org.apache.qpid.management.web.action.BrokersManagementAction</servlet-class>
+ </servlet>
+ <servlet>
+ <description>
+ Connects QMAn to one or more brokers depending from what is
+ specified on the given (via system property) configuration
+ file.
+ </description>
+ <display-name>Connect QMan to Broker</display-name>
+ <servlet-name>ConnectQManToBroker</servlet-name>
+ <servlet-class>org.apache.qpid.management.servlet.ConnectQManToBroker</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>ResourceManagement</servlet-name>
+ <url-pattern>/resources_management</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>WsdmWsdlPerspective</servlet-name>
+ <url-pattern>/wsdm_wsdl_perspective</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>WsdmRmdPerspective</servlet-name>
+ <url-pattern>/wsdm_rmd_perspective</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>WsdmOperationsPerspective</servlet-name>
+ <url-pattern>/wsdm_operations_perspective</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>WsdmPropertiesPerspective</servlet-name>
+ <url-pattern>/wsdm_properties_perspective</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>BrokersManagement</servlet-name>
+ <url-pattern>/brokers_management</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>JmxPerspective</servlet-name>
+ <url-pattern>/jmx_perspective</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>LoggingConfiguration</servlet-name>
+ <url-pattern>/logging_configuration</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>ViewConsole</servlet-name>
+ <url-pattern>/console</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>ConnectQManToBroker</servlet-name>
+ <url-pattern>/test/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>Proxy</servlet-name>
+ <url-pattern>/services/*</url-pattern>
+ </servlet-mapping>
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ </login-config>
+</web-app>
diff --git a/java/management/common/src/main/java/management-common.bnd b/java/management/common/src/main/java/management-common.bnd
index 5c39329f2f..cb28d309a6 100644
--- a/java/management/common/src/main/java/management-common.bnd
+++ b/java/management/common/src/main/java/management-common.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.13.0
+ver: 0.9.0
Bundle-SymbolicName: qpid-management-common
Bundle-Version: ${ver}
diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java
index b5c80a4fed..c0e7293611 100644
--- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java
+++ b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java
@@ -36,8 +36,8 @@ import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParame
* The ManagedBroker is the management interface to expose management
* features of the Broker.
*
- * @version Qpid JMX API 2.2
- * @since Qpid JMX API 1.3
+ * @author Bhupendra Bhardwaj
+ * @version 0.1
*/
public interface ManagedBroker
{
@@ -131,118 +131,4 @@ public interface ManagedBroker
impact= MBeanOperationInfo.ACTION)
void deleteQueue(@MBeanOperationParameter(name= ManagedQueue.TYPE, description="Queue Name")String queueName)
throws IOException, JMException, MBeanException;
-
- /**
- * Resets all message and data statistics for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanOperation(name="resetStatistics",
- description="Resets all message and data statistics for the virtual host",
- impact= MBeanOperationInfo.ACTION)
- void resetStatistics() throws Exception;
-
- /**
- * Peak rate of messages delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageDeliveryRate", description=TYPE + " Peak Message Delivery Rate")
- double getPeakMessageDeliveryRate();
-
- /**
- * Peak rate of bytes delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataDeliveryRate", description=TYPE + " Peak Data Delivery Rate")
- double getPeakDataDeliveryRate();
-
- /**
- * Rate of messages delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageDeliveryRate", description=TYPE + " Message Delivery Rate")
- double getMessageDeliveryRate();
-
- /**
- * Rate of bytes delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataDeliveryRate", description=TYPE + " Data Delivery Rate")
- double getDataDeliveryRate();
-
- /**
- * Total count of messages delivered for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesDelivered", description=TYPE + " Total Messages Delivered")
- long getTotalMessagesDelivered();
-
- /**
- * Total count of bytes for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataDelivered", description=TYPE + " Total Data Delivered")
- long getTotalDataDelivered();
-
- /**
- * Peak rate of messages received per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageReceiptRate", description=TYPE + " Peak Message Receipt Rate")
- double getPeakMessageReceiptRate();
-
- /**
- * Peak rate of bytes received per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataReceiptRate", description=TYPE + " Peak Data Receipt Rate")
- double getPeakDataReceiptRate();
-
- /**
- * Rate of messages received per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageReceiptRate", description=TYPE + " Message Receipt Rate")
- double getMessageReceiptRate();
-
- /**
- * Rate of bytes received per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataReceiptRate", description=TYPE + " Data Receipt Rate")
- double getDataReceiptRate();
-
- /**
- * Total count of messages received for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesReceived", description=TYPE + " Total Messages Received")
- long getTotalMessagesReceived();
-
- /**
- * Total count of bytes received for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataReceived", description=TYPE + " Total Data Received")
- long getTotalDataReceived();
-
- /**
- * Is statistics collection enabled for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="StatisticsEnabled", description=TYPE + " Statistics Enabled")
- boolean isStatisticsEnabled();
}
diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedConnection.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedConnection.java
index d16db65d5d..d6b79d1dde 100644
--- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedConnection.java
+++ b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedConnection.java
@@ -37,9 +37,8 @@ import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParame
/**
* The management interface exposed to allow management of Connections.
- *
- * @version Qpid JMX API 2.2
- * @since Qpid JMX API 1.3
+ * @author Bhupendra Bhardwaj
+ * @version 0.1
*/
public interface ManagedConnection
{
@@ -146,126 +145,4 @@ public interface ManagedConnection
description="Closes this connection and all related channels",
impact= MBeanOperationInfo.ACTION)
void closeConnection() throws Exception;
-
- /**
- * Resets message and data statistics for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanOperation(name="resetStatistics",
- description="Resets message and data statistics for this connection",
- impact= MBeanOperationInfo.ACTION)
- void resetStatistics() throws Exception;
-
- /**
- * Peak rate of messages delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageDeliveryRate", description=TYPE + " Peak Message Delivery Rate")
- double getPeakMessageDeliveryRate();
-
- /**
- * Peak rate of bytes delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataDeliveryRate", description=TYPE + " Peak Data Delivery Rate")
- double getPeakDataDeliveryRate();
-
- /**
- * Rate of messages delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageDeliveryRate", description=TYPE + " Message Delivery Rate")
- double getMessageDeliveryRate();
-
- /**
- * Rate of bytes delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataDeliveryRate", description=TYPE + " Data Delivery Rate")
- double getDataDeliveryRate();
-
- /**
- * Total count of messages delivered for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesDelivered", description=TYPE + " Total Messages Delivered")
- long getTotalMessagesDelivered();
-
- /**
- * Total count of bytes for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataDelivered", description=TYPE + " Total Data Delivered")
- long getTotalDataDelivered();
-
- /**
- * Peak rate of messages received per second for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageReceiptRate", description=TYPE + " Peak Message Receipt Rate")
- double getPeakMessageReceiptRate();
-
- /**
- * Peak rate of bytes received per second for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataReceiptRate", description=TYPE + " Peak Data Receipt Rate")
- double getPeakDataReceiptRate();
-
- /**
- * Rate of messages received per second for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageReceiptRate", description=TYPE + " Message Receipt Rate")
- double getMessageReceiptRate();
-
- /**
- * Rate of bytes received per second for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataReceiptRate", description=TYPE + " Data Receipt Rate")
- double getDataReceiptRate();
-
- /**
- * Total count of messages received for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesReceived", description=TYPE + " Total Messages Received")
- long getTotalMessagesReceived();
-
- /**
- * Total count of bytes received for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataReceived", description=TYPE + " Total Data Received")
- long getTotalDataReceived();
-
- /**
- * Is statistics collection enabled for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="StatisticsEnabled", description=TYPE + " Statistics Enabled")
- boolean isStatisticsEnabled();
-
- /**
- * Sets statistics collection enabled/disabled for this connection.
- *
- * @param enabled
- * @since Qpid JMX API 2.2
- */
- void setStatisticsEnabled(boolean enabled);
}
diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
index 12ae69571e..618403fdca 100644
--- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
+++ b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ServerInformation.java
@@ -22,15 +22,10 @@ package org.apache.qpid.management.common.mbeans;
import java.io.IOException;
-import javax.management.MBeanOperationInfo;
-
import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
/**
* Interface for the ServerInformation MBean
- *
- * @version Qpid JMX API 2.3
* @since Qpid JMX API 1.3
*/
public interface ServerInformation
@@ -47,7 +42,7 @@ public interface ServerInformation
* Qpid JMX API 1.1 can be assumed.
*/
int QPID_JMX_API_MAJOR_VERSION = 2;
- int QPID_JMX_API_MINOR_VERSION = 3;
+ int QPID_JMX_API_MINOR_VERSION = 0;
/**
@@ -85,118 +80,4 @@ public interface ServerInformation
@MBeanAttribute(name="ProductVersion",
description = "The product version string")
String getProductVersion() throws IOException;
-
- /**
- * Resets all message and data statistics for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanOperation(name="resetStatistics",
- description="Resets all message and data statistics for the broker",
- impact= MBeanOperationInfo.ACTION)
- void resetStatistics() throws Exception;
-
- /**
- * Peak rate of messages delivered per second for the virtual host.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageDeliveryRate", description=TYPE + " Peak Message Delivery Rate")
- double getPeakMessageDeliveryRate();
-
- /**
- * Peak rate of bytes delivered per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataDeliveryRate", description=TYPE + " Peak Data Delivery Rate")
- double getPeakDataDeliveryRate();
-
- /**
- * Rate of messages delivered per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageDeliveryRate", description=TYPE + " Message Delivery Rate")
- double getMessageDeliveryRate();
-
- /**
- * Rate of bytes delivered per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataDeliveryRate", description=TYPE + " Data Delivery Rate")
- double getDataDeliveryRate();
-
- /**
- * Total count of messages delivered for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesDelivered", description=TYPE + " Total Messages Delivered")
- long getTotalMessagesDelivered();
-
- /**
- * Total count of bytes for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataDelivered", description=TYPE + " Total Data Delivered")
- long getTotalDataDelivered();
-
- /**
- * Peak rate of messages received per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakMessageReceiptRate", description=TYPE + " Peak Message Receipt Rate")
- double getPeakMessageReceiptRate();
-
- /**
- * Peak rate of bytes received per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="PeakDataReceiptRate", description=TYPE + " Peak Data Receipt Rate")
- double getPeakDataReceiptRate();
-
- /**
- * Rate of messages received per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="MessageReceiptRate", description=TYPE + " Message Receipt Rate")
- double getMessageReceiptRate();
-
- /**
- * Rate of bytes received per second for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="DataReceiptRate", description=TYPE + " Data Receipt Rate")
- double getDataReceiptRate();
-
- /**
- * Total count of messages received for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalMessagesReceived", description=TYPE + " Total Messages Received")
- long getTotalMessagesReceived();
-
- /**
- * Total count of bytes received for the broker.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="TotalDataReceived", description=TYPE + " Total Data Received")
- long getTotalDataReceived();
-
- /**
- * Is statistics collection enabled for this connection.
- *
- * @since Qpid JMX API 2.2
- */
- @MBeanAttribute(name="StatisticsEnabled", description=TYPE + " Statistics Enabled")
- boolean isStatisticsEnabled();
}
diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/UserManagement.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/UserManagement.java
index 1a82c58ee9..2bd00d5802 100644
--- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/UserManagement.java
+++ b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/UserManagement.java
@@ -38,21 +38,38 @@ public interface UserManagement
//TabularType and contained CompositeType key/description information.
//For compatibility reasons, DONT MODIFY the existing key values if expanding the set.
String USERNAME = "Username";
- String RIGHTS_READ_ONLY = "read"; // item deprecated
- String RIGHTS_READ_WRITE = "write"; // item deprecated
- String RIGHTS_ADMIN = "admin"; // item deprecated
-
+ String RIGHTS_READ_ONLY = "read";
+ String RIGHTS_READ_WRITE = "write";
+ String RIGHTS_ADMIN = "admin";
List<String> COMPOSITE_ITEM_NAMES = Collections.unmodifiableList(Arrays.asList(USERNAME, RIGHTS_READ_ONLY, RIGHTS_READ_WRITE, RIGHTS_ADMIN));
List<String> COMPOSITE_ITEM_DESCRIPTIONS = Collections.unmodifiableList(
Arrays.asList("Broker Login username",
- "Item no longer used",
- "Item no longer used",
- "Item no longer used"));
-
+ "Management Console Read Permission",
+ "Management Console Write Permission",
+ "Management Console Admin Permission"));
List<String> TABULAR_UNIQUE_INDEX = Collections.unmodifiableList(Arrays.asList(USERNAME));
//********** Operations *****************//
/**
+ * set password for user.
+ *
+ * Since Qpid JMX API 1.2 this operation expects plain text passwords to be provided. Prior to this, MD5 hashed passwords were supplied.
+ *
+ * @deprecated since Qpid JMX API 1.7
+ *
+ * @param username The username to create
+ * @param password The password for the user
+ *
+ * @return The result of the operation
+ */
+ @Deprecated
+ @MBeanOperation(name = "setPassword", description = "Set password for user.",
+ impact = MBeanOperationInfo.ACTION)
+ boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ //NOTE: parameter name was changed to 'passwd' in Qpid JMX API 1.7 to protect against older, incompatible management clients
+ @MBeanOperationParameter(name = "passwd", description = "Password")char[] password);
+
+ /**
* Set password for a given user.
*
* @since Qpid JMX API 1.7
@@ -66,21 +83,69 @@ public interface UserManagement
impact = MBeanOperationInfo.ACTION)
boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username,
@MBeanOperationParameter(name = "password", description = "Password")String password);
+
+ /**
+ * set rights for users with given details
+ *
+ * @param username The username to create
+ * @param read The set of permission to give the new user
+ * @param write The set of permission to give the new user
+ * @param admin The set of permission to give the new user
+ *
+ * @return The result of the operation
+ */
+ @MBeanOperation(name = "setRights", description = "Set access rights for user.",
+ impact = MBeanOperationInfo.ACTION)
+ boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
+
+ /**
+ * Create users with given details
+ *
+ * Since Qpid JMX API 1.2 this operation expects plain text passwords to be provided. Prior to this, MD5 hashed passwords were supplied.
+ *
+ * @deprecated since Qpid JMX API 1.7
+ *
+ * @param username The username to create
+ * @param password The password for the user
+ * @param read The set of permission to give the new user
+ * @param write The set of permission to give the new user
+ * @param admin The set of permission to give the new user
+ *
+ * @return The result of the operation
+ */
+ @Deprecated
+ @MBeanOperation(name = "createUser", description = "Create new user from system.",
+ impact = MBeanOperationInfo.ACTION)
+ boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ //NOTE: parameter name was changed to 'passwd' in Qpid JMX API 1.7 to protect against older, incompatible management clients
+ @MBeanOperationParameter(name = "passwd", description = "Password")char[] password,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
/**
* Create users with given details.
*
- * @since Qpid JMX API 2.3 / 1.12
+ * @since Qpid JMX API 1.7
*
* @param username The username to create
* @param password The password for the user
+ * @param read The set of permission to give the new user
+ * @param write The set of permission to give the new user
+ * @param admin The set of permission to give the new user
*
- * @return true if the user was created successfully, or false otherwise
+ * @return The result of the operation
*/
@MBeanOperation(name = "createUser", description = "Create a new user.",
impact = MBeanOperationInfo.ACTION)
boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
- @MBeanOperationParameter(name = "password", description = "Password")String password);
+ @MBeanOperationParameter(name = "password", description = "Password")String password,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
/**
* View users returns all the users that are currently available to the system.
@@ -95,11 +160,9 @@ public interface UserManagement
/**
- * Reload the user data
+ * Reload the date from disk
*
- * Since Qpid JMX API 2.3 / 1.12 this operation reloads only the password data.
- * Since Qpid JMX API 1.2 but prior to 2.3 / 1.12 this operation reloads the password and authorisation files.
- * Prior to 1.2, only the authorisation file was reloaded.
+ * Since Qpid JMX API 1.2 this operation reloads the password and authorisation files. Prior to this, only the authorisation file was reloaded.
*
* @return The result of the operation
*/
@@ -109,13 +172,10 @@ public interface UserManagement
/**
* View users returns all the users that are currently available to the system.
- *
- * Since Qpid JMX API 2.3 / 1.12 the items that corresponded to read, write and admin flags
- * are deprecated and always return false.
*
* @return a table of users data (Username, read, write, admin)
*/
- @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.",
+ @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.",
impact = MBeanOperationInfo.INFO)
TabularData viewUsers();
diff --git a/java/management/console/build.xml b/java/management/console/build.xml
new file mode 100644
index 0000000000..8f23030b44
--- /dev/null
+++ b/java/management/console/build.xml
@@ -0,0 +1,27 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<project name="QMF Console" default="build">
+
+ <property name="module.depends" value="common client"/>
+
+ <import file="../../module.xml"/>
+
+</project>
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/AbstractConsole.java b/java/management/console/src/main/java/org/apache/qpid/console/AbstractConsole.java
new file mode 100644
index 0000000000..d95003b1cc
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/AbstractConsole.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+public class AbstractConsole implements Console
+{
+ public AbstractConsole()
+ {
+ }
+
+ public void agentRemoved(Agent agent)
+ {
+ }
+
+ public void brokerConnected(Broker broker)
+ {
+ }
+
+ public void brokerDisconnected(Broker broker)
+ {
+ }
+
+ public void brokerInformation(Broker broker)
+ {
+ }
+
+ public void eventRecieved(Broker broker, QMFEvent anEvent)
+ {
+ }
+
+ public void hearbeatRecieved(Agent agent, long timestamp)
+ {
+ }
+
+ public void methodResponse(Broker broker, long seq, MethodResult response)
+ {
+ }
+
+ public void newAgent(Agent agent)
+ {
+ }
+
+ public void newClass(short kind, ClassKey key)
+ {
+ }
+
+ public void newPackage(String packageName)
+ {
+ }
+
+ public void objectProperties(Broker broker, QMFObject obj)
+ {
+ }
+
+ public void objectStatistics(Broker broker, QMFObject obj)
+ {
+ }
+
+ public Class typeMapping(ClassKey key)
+ {
+ return QMFObject.class;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/Agent.java b/java/management/console/src/main/java/org/apache/qpid/console/Agent.java
new file mode 100644
index 0000000000..e1887d82ea
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/Agent.java
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Agent
+{
+ private static Logger log = LoggerFactory.getLogger(Agent.class);
+
+ public static String AgentKey(long AgentBank, long BrokerBank)
+ {
+ return String.format("%s:%s", AgentBank, BrokerBank);
+ }
+
+ public static long getAgentBank(String routingKey)
+ {
+ String delim = ".";
+ return Long.parseLong(routingKey.split(java.util.regex.Pattern
+ .quote(delim))[3]);
+ }
+
+ public static long getBrokerBank(String routingKey)
+ {
+ String delim = ".";
+ return Long.parseLong(routingKey.split(java.util.regex.Pattern
+ .quote(delim))[2]);
+ }
+
+ public static String routingCode(long AgentBank, long BrokerBank)
+ {
+ return String.format("agent.%s.%s", BrokerBank, AgentBank);
+ }
+
+ private long agentBank;
+ private Broker broker;
+ private long brokerBank;
+ private String label;
+
+ public Agent(Broker broker, long agentBank, String label)
+ {
+ this.setBroker(broker);
+ this.setBrokerBank(broker.brokerBank());
+ this.setAgentBank(agentBank);
+ this.setlabel(label);
+ }
+
+ public final String agentKey()
+ {
+ return Agent.AgentKey(getAgentBank(), getBrokerBank());
+ }
+
+ public final long getAgentBank()
+ {
+ return agentBank;
+ }
+
+ public final Broker getBroker()
+ {
+ return broker;
+ }
+
+ public final long getBrokerBank()
+ {
+ return brokerBank;
+ }
+
+ public final String getlabel()
+ {
+ return label;
+ }
+
+ public final String routingCode()
+ {
+ return Agent.routingCode(getAgentBank(), getBrokerBank());
+ }
+
+ public final void setAgentBank(long value)
+ {
+ agentBank = value;
+ }
+
+ public final void setBroker(Broker value)
+ {
+ broker = value;
+ }
+
+ public final void setBrokerBank(long value)
+ {
+ brokerBank = value;
+ }
+
+ public final void setlabel(String value)
+ {
+ label = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/Broker.java b/java/management/console/src/main/java/org/apache/qpid/console/Broker.java
new file mode 100644
index 0000000000..16c77449f1
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/Broker.java
@@ -0,0 +1,504 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.UUID;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+
+public class Broker implements MessageListener
+{
+ class HeaderInfo
+ {
+ boolean valid;
+ long sequence;
+ char opcode;
+
+ public String toString()
+ {
+ return String.format("%s Header with opcode %s and sequence %s",
+ (valid ? "Valid" : "Invalid"), opcode, sequence);
+ }
+ }
+
+ private static Logger log = LoggerFactory.getLogger(Broker.class);
+ public static final int SYNC_TIME = 60000;
+ // JMS Stuff
+ private javax.jms.Session session;
+ boolean sessionTransacted = false;
+ private String replyName;
+ private String topicName;
+ private MessageProducer prod;
+ private ArrayList<MessageConsumer> consumers = new ArrayList<MessageConsumer>();
+ private Queue reply;
+ private Queue topic;
+ private int acknowledgeMode = javax.jms.Session.AUTO_ACKNOWLEDGE;
+ // QMF Stuff
+ AMQConnection connection;
+ public String url;
+ public java.util.HashMap<String, Agent> Agents = new java.util.HashMap<String, Agent>();
+ private Session consoleSession;
+ private boolean connected = false;
+ private boolean syncInFlight = false;
+ private boolean topicBound = false;
+ private int reqsOutstanding = 0;
+ private Object lockObject = new Object();
+ UUID brokerId = UUID.randomUUID();
+
+ public Broker(org.apache.qpid.console.Session session, String url)
+ {
+ log.debug("Creating a new Broker for url " + url);
+ this.url = url;
+ consoleSession = session;
+ this.tryToConnect();
+ }
+
+ public int brokerBank()
+ {
+ return 1;
+ }
+
+ protected HeaderInfo CheckHeader(Decoder decoder)
+ {
+ HeaderInfo returnValue = new HeaderInfo();
+ returnValue.opcode = 'x';
+ returnValue.sequence = -1;
+ returnValue.valid = false;
+ if (decoder.hasRemaining())
+ {
+ char character = (char) decoder.readUint8();
+ if (character != 'A')
+ {
+ return returnValue;
+ }
+ character = (char) decoder.readUint8();
+ if (character != 'M')
+ {
+ return returnValue;
+ }
+ character = (char) decoder.readUint8();
+ if (character != '2')
+ {
+ return returnValue;
+ }
+ returnValue.valid = true;
+ returnValue.opcode = (char) decoder.readUint8();
+ returnValue.sequence = decoder.readUint32();
+ }
+ return returnValue;
+ }
+
+ public Encoder createEncoder(char opcode, long sequence)
+ {
+ return setHeader(new BBEncoder(1024), opcode, sequence);
+ }
+
+ public Message createMessage(Encoder enc)
+ {
+ try
+ {
+ byte[] buf = new byte[1024];
+ BBEncoder bbenc = (BBEncoder) enc;
+ BytesMessage msg = session.createBytesMessage();
+ ByteBuffer slice = bbenc.buffer();
+ while (slice.hasRemaining())
+ {
+ int n = Math.min(buf.length, slice.remaining());
+ slice.get(buf, 0, n);
+ msg.writeBytes(buf, 0, n);
+ }
+ return msg;
+ } catch (JMSException e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+
+ public void decrementOutstanding()
+ {
+ synchronized (lockObject)
+ {
+ this.reqsOutstanding -= 1;
+ if ((reqsOutstanding == 0) & !topicBound)
+ {
+ for (String key : consoleSession.bindingKeys())
+ {
+ try
+ {
+ // this.clientSession.exchangeBind(topicName,
+ // "qpid.mannagement", key) ;
+ log.debug("Setting Topic Binding " + key);
+ // topicName = "management://qpid.management//" + key;
+ String rk = String.format("&routingkey='%s'", key);
+ Queue aQueue = session.createQueue(topicName + rk);
+ MessageConsumer cons = session.createConsumer(aQueue);
+ cons.setMessageListener(this);
+ consumers.add(cons);
+ } catch (JMSException e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+ topicBound = true;
+ }
+ if ((reqsOutstanding == 0) & syncInFlight)
+ {
+ syncInFlight = false;
+ lockObject.notifyAll();
+ }
+ }
+ }
+
+ private byte[] ensure(int capacity, byte[] body, int size)
+ {
+ if (capacity > body.length)
+ {
+ byte[] copy = new byte[capacity];
+ System.arraycopy(body, 0, copy, 0, size);
+ body = copy;
+ }
+ return body;
+ }
+
+ protected void finalize()
+ {
+ if (connected)
+ {
+ this.shutdown();
+ }
+ }
+
+ public boolean getSyncInFlight()
+ {
+ return syncInFlight;
+ }
+
+ public void incrementOutstanding()
+ {
+ synchronized (lockObject)
+ {
+ this.reqsOutstanding += 1;
+ }
+ }
+
+ public boolean isConnected()
+ {
+ return connected;
+ }
+
+ public void onMessage(Message msg)
+ {
+ Decoder decoder = readBody(msg);
+ HeaderInfo headerInfo = this.CheckHeader(decoder);
+ // log.debug(headerInfo.toString());
+ while (headerInfo.valid)
+ {
+ long seq = headerInfo.sequence;
+ switch (headerInfo.opcode)
+ {
+ case 'b':
+ consoleSession.handleBrokerResponse(this, decoder, seq);
+ break;
+ case 'p':
+ consoleSession.handlePackageIndicator(this, decoder, seq);
+ break;
+ case 'z':
+ consoleSession.handleCommandComplete(this, decoder, seq);
+ break;
+ case 'q':
+ consoleSession.handleClassIndicator(this, decoder, seq);
+ break;
+ case 'm':
+ consoleSession.handleMethodResponse(this, decoder, seq);
+ break;
+ case 'h':
+ consoleSession
+ .handleHeartbeatIndicator(this, decoder, seq, msg);
+ break;
+ case 'e':
+ consoleSession.handleEventIndicator(this, decoder, seq);
+ break;
+ case 's':
+ consoleSession.handleSchemaResponse(this, decoder, seq);
+ break;
+ case 'c':
+ consoleSession.handleContentIndicator(this, decoder, seq, true,
+ false);
+ break;
+ case 'i':
+ consoleSession.handleContentIndicator(this, decoder, seq,
+ false, true);
+ break;
+ case 'g':
+ consoleSession.handleContentIndicator(this, decoder, seq, true,
+ true);
+ break;
+ default:
+ log.error("Invalid message type recieved with opcode "
+ + headerInfo.opcode);
+ break;
+ }
+ headerInfo = this.CheckHeader(decoder);
+ }
+ }
+
+ private Decoder readBody(Message message)
+ {
+ BytesMessage msg = (BytesMessage) message;
+ BBDecoder dec = new BBDecoder();
+ byte[] buf = new byte[1024];
+ byte[] body = new byte[1024];
+ int size = 0;
+ int n;
+ try
+ {
+ while ((n = msg.readBytes(buf)) > 0)
+ {
+ body = ensure(size + n, body, size);
+ System.arraycopy(buf, 0, body, size, n);
+ size += n;
+ }
+ } catch (JMSException e)
+ {
+ throw new ConsoleException(e);
+ }
+ dec.init(ByteBuffer.wrap(body, 0, size));
+ return dec;
+ }
+
+ public void send(Encoder enc)
+ {
+ this.send(this.createMessage(enc), "broker");
+ }
+
+ public void send(Message msg)
+ {
+ this.send(msg, "broker", -1);
+ }
+
+ public void send(Message msg, String routingKey)
+ {
+ this.send(msg, routingKey, -1);
+ }
+
+ public void send(Message msg, String routingKey, int ttl)
+ {
+ synchronized (lockObject)
+ {
+ try
+ {
+ log.debug(String.format("Sending message to routing key '%s'",
+ routingKey));
+ String destName = String.format(
+ "management://qpid.management//?routingkey='%s'",
+ routingKey);
+ log.debug(destName);
+ Queue dest = session.createQueue(destName);
+ // Queue jmsReply = session
+ // createQueue("direct://amq.direct//?routingkey='reply-"
+ // + brokerId + "'");
+ if (ttl != -1)
+ {
+ msg.setJMSExpiration(ttl);
+ }
+ msg.setJMSReplyTo(reply);
+ prod.send(dest, msg);
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+ }
+
+ protected Encoder setHeader(Encoder enc, char opcode, long sequence)
+ {
+ enc.writeUint8((short) 'A');
+ enc.writeUint8((short) 'M');
+ enc.writeUint8((short) '2');
+ enc.writeUint8((short) opcode);
+ enc.writeUint32(sequence);
+ return enc;
+ }
+
+ public void setSyncInFlight(boolean inFlight)
+ {
+ synchronized (lockObject)
+ {
+ syncInFlight = inFlight;
+ lockObject.notifyAll();
+ }
+ }
+
+ public void shutdown()
+ {
+ if (connected)
+ {
+ this.waitForStable();
+ try
+ {
+ session.close();
+ for (MessageConsumer cons : consumers)
+ {
+ cons.close();
+ }
+ connection.close();
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ } finally
+ {
+ this.connected = false;
+ }
+ }
+ }
+
+ protected void tryToConnect()
+ {
+ try
+ {
+ reqsOutstanding = 1;
+ Agent newAgent = new Agent(this, 0, "BrokerAgent");
+ Agents.put(newAgent.agentKey(), newAgent);
+ connection = new AMQConnection(url);
+ session = connection.createSession(sessionTransacted,
+ acknowledgeMode);
+ replyName = String
+ .format(
+ "direct://amq.direct//reply-%s?exclusive='True'&autodelete='True'",
+ brokerId);
+ topicName = String
+ .format(
+ "management://qpid.management//topic-%s?exclusive='True'&autodelete='True'",
+ brokerId);
+ reply = session.createQueue(replyName);
+ MessageConsumer cons = session.createConsumer(reply);
+ cons.setMessageListener(this);
+ consumers.add(cons);
+ prod = session.createProducer(null);
+ topic = session.createQueue(topicName);
+ cons = session.createConsumer(topic);
+ cons.setMessageListener(this);
+ consumers.add(cons);
+ connection.start();
+ // Rest of the topic is bound later. Start er up
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ connected = true;
+ consoleSession.handleBrokerConnect(this);
+ Encoder Encoder = createEncoder('B', 0);
+ this.send(Encoder);
+ }
+
+ public void updateAgent(QMFObject obj)
+ {
+ long agentBank = (Long) obj.getProperty("agentBank");
+ long brokerBank = (Long) obj.getProperty("brokerBank");
+ String key = Agent.AgentKey(agentBank, brokerBank);
+ if (obj.isDeleted())
+ {
+ if (Agents.containsKey(key))
+ {
+ Agent agent = Agents.get(key);
+ Agents.remove(key);
+ consoleSession.handleAgentRemoved(agent);
+ }
+ } else
+ {
+ if (!Agents.containsKey(key))
+ {
+ Agent newAgent = new Agent(this, agentBank, (String) obj
+ .getProperty("label"));
+ Agents.put(key, newAgent);
+ consoleSession.handleNewAgent(newAgent);
+ }
+ }
+ }
+
+ public void waitForStable()
+ {
+ synchronized (lockObject)
+ {
+ if (connected)
+ {
+ long start = System.currentTimeMillis();
+ syncInFlight = true;
+ while (reqsOutstanding != 0)
+ {
+ log.debug("Waiting to recieve messages");
+ try
+ {
+ lockObject.wait(SYNC_TIME);
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ long duration = System.currentTimeMillis() - start;
+ if (duration > SYNC_TIME)
+ {
+ throw new ConsoleException(
+ "Timeout waiting for Broker to Sync");
+ }
+ }
+ }
+ }
+ }
+
+ public void waitForSync(int timeout)
+ {
+ synchronized (lockObject)
+ {
+ long start = System.currentTimeMillis();
+ while (syncInFlight)
+ {
+ try
+ {
+ lockObject.wait(SYNC_TIME);
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+ long duration = System.currentTimeMillis() - start;
+ if (duration > timeout)
+ {
+ throw new ConsoleException("Timeout waiting for Broker to Sync");
+ }
+ }
+ }
+}
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/ClassKey.java b/java/management/console/src/main/java/org/apache/qpid/console/ClassKey.java
new file mode 100644
index 0000000000..1fbf4c7f3d
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/ClassKey.java
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClassKey
+{
+ private static final Logger log = LoggerFactory.getLogger(ClassKey.class);
+ private String packageName;
+ private String className;
+ private long[] hash = new long[4];
+
+ public ClassKey(Decoder dec)
+ {
+ setPackageName(dec.readStr8());
+ setClassName(dec.readStr8());
+ hash[0] = dec.readUint32();
+ hash[1] = dec.readUint32();
+ hash[2] = dec.readUint32();
+ hash[3] = dec.readUint32();
+ }
+
+ public ClassKey(String keyString)
+ {
+ String delims = "[*:*(*)]";
+ String[] parts = keyString.split(delims);
+ if (parts.length < 3)
+ {
+ throw new ConsoleException(
+ "Invalid class key format. Format should be package:class(bytes)");
+ }
+ setPackageName(parts[0]);
+ setClassName(parts[1]);
+ delims = "-";
+ String[] bytes = parts[2].split(delims);
+ if (bytes.length != 4)
+ {
+ throw new ConsoleException(
+ "Invalid class key format. Bytes should be in the format HEX-HEX-HEX-HEX");
+ }
+ hash[0] = Long.parseLong(bytes[0], 16);
+ hash[1] = Long.parseLong(bytes[1], 16);
+ hash[2] = Long.parseLong(bytes[2], 16);
+ hash[3] = Long.parseLong(bytes[3], 16);
+ }
+
+ public void encode(Encoder enc)
+ {
+ enc.writeStr8(getPackageName());
+ enc.writeStr8(getClassName());
+ enc.writeUint32(hash[0]);
+ enc.writeUint32(hash[1]);
+ enc.writeUint32(hash[2]);
+ enc.writeUint32(hash[3]);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if(obj instanceof ClassKey && obj.getClass().equals(this.getClass()))
+ {
+ ClassKey other = (ClassKey) obj;
+ return (other.getKeyString().equals(this.getKeyString()));
+ } else
+ {
+ return false;
+ }
+ }
+
+ public final String getClassName()
+ {
+ return className;
+ }
+
+ public long[] getHash()
+ {
+ return hash;
+ }
+
+ public String getHashString()
+ {
+ return String.format("%08x-%08x-%08x-%08x", hash[0], hash[1], hash[2],
+ hash[3]);
+ }
+
+ public String getKeyString()
+ {
+ String hashString = this.getHashString();
+ return String.format("%s:%s(%s)", getPackageName(), getClassName(),
+ hashString);
+ }
+
+ public String getPackageName()
+ {
+ return packageName;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return getKeyString().hashCode();
+ }
+
+ public void setClassName(String value)
+ {
+ className = value;
+ }
+
+ public void setHash(long[] hash)
+ {
+ this.hash = hash;
+ }
+
+ public void setPackageName(String value)
+ {
+ packageName = value;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("ClassKey: %s", getKeyString());
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/Console.java b/java/management/console/src/main/java/org/apache/qpid/console/Console.java
new file mode 100644
index 0000000000..11b381032a
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/Console.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+public interface Console
+{
+ void agentRemoved(Agent agent);
+
+ void brokerConnected(Broker broker);
+
+ void brokerDisconnected(Broker broker);
+
+ void brokerInformation(Broker broker);
+
+ void eventRecieved(Broker broker, QMFEvent anEvent);
+
+ void hearbeatRecieved(Agent agent, long timestamp);
+
+ void methodResponse(Broker broker, long seq, MethodResult response);
+
+ void newAgent(Agent agent);
+
+ void newClass(short kind, ClassKey key);
+
+ void newPackage(String packageName);
+
+ void objectProperties(Broker broker, QMFObject obj);
+
+ void objectStatistics(Broker broker, QMFObject obj);
+
+ @SuppressWarnings("unchecked")
+ Class typeMapping(ClassKey key);
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/ConsoleException.java b/java/management/console/src/main/java/org/apache/qpid/console/ConsoleException.java
new file mode 100644
index 0000000000..3176da70a6
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/ConsoleException.java
@@ -0,0 +1,48 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.console;
+
+import java.lang.RuntimeException;
+
+public class ConsoleException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public ConsoleException()
+ {
+ super();
+ }
+
+ public ConsoleException(String message)
+ {
+ super(message);
+ }
+
+ public ConsoleException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public ConsoleException(Throwable cause)
+ {
+ super(cause);
+ }
+}
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/EventSeverity.java b/java/management/console/src/main/java/org/apache/qpid/console/EventSeverity.java
new file mode 100644
index 0000000000..d40d41b196
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/EventSeverity.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+public enum EventSeverity
+{
+ EMER(0), ALERT(1), CRIT(2), ERROR(3), WARN(4), NOTIC(5), INFO(6), DEBUG(7);
+ private int intValue;
+
+ private EventSeverity(int value)
+ {
+ intValue = value;
+ }
+
+ public int getValue()
+ {
+ return intValue;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/MethodResult.java b/java/management/console/src/main/java/org/apache/qpid/console/MethodResult.java
new file mode 100644
index 0000000000..34980b50e1
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/MethodResult.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.HashMap;
+
+public class MethodResult
+{
+ private long returnCode;
+ private String text;
+ protected java.util.HashMap<String, Object> returnValues;
+
+ public MethodResult(long aCode, String aMsg,
+ java.util.HashMap<String, Object> args)
+ {
+ setReturnCode(aCode);
+ setText(aMsg);
+ returnValues = args;
+ }
+
+ public long getReturnCode()
+ {
+ return returnCode;
+ }
+
+ public Object getReturnValue(String name)
+ {
+ Object returnValue = null;
+ if (returnValues.containsKey(name))
+ {
+ returnValue = returnValues.get(name);
+ }
+ return returnValue;
+ }
+
+ public HashMap<String, Object> getReturnValues()
+ {
+ return returnValues;
+ }
+
+ public String getText()
+ {
+ return text;
+ }
+
+ public void setReturnCode(long value)
+ {
+ returnCode = value;
+ }
+
+ public void setText(String value)
+ {
+ text = value;
+ }
+
+ @Override
+ public String toString()
+ {
+ String returnString = "";
+ for (java.util.Map.Entry<String, Object> pair : returnValues.entrySet())
+ {
+ returnString = returnString
+ + String.format("(Key: '%s' Value: '%s')", pair.getKey(),
+ pair.getValue());
+ }
+ return String.format(
+ "MethodResult: ReturnCode=%s, Text=%s Values=[%s]",
+ getReturnCode(), getText(), returnString);
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/ObjectID.java b/java/management/console/src/main/java/org/apache/qpid/console/ObjectID.java
new file mode 100644
index 0000000000..6cf5301de5
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/ObjectID.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import org.apache.qpid.transport.codec.*;
+
+public class ObjectID
+{
+ protected long first;
+ protected long second;
+
+ public ObjectID()
+ {
+ }
+
+ public ObjectID(Decoder dec)
+ {
+ first = dec.readUint64();
+ second = dec.readUint64();
+ }
+
+ public ObjectID(long first, long second)
+ {
+ this.first = first;
+ this.second = second;
+ }
+
+ public long agentBank()
+ {
+ return (this.first & 0x000000000FFFFFFF);
+ }
+
+ public long brokerBank()
+ {
+ return (this.first & 0x0000FFFFF0000000L) >> 28;
+ }
+
+ public void encode(Encoder enc)
+ {
+ enc.writeUint64(first);
+ enc.writeUint64(second);
+ }
+
+ public long flags()
+ {
+ return (this.first & 0xF000000000000000L) >> 60;
+ }
+
+ public boolean isDurable()
+ {
+ return sequence() == 0;
+ }
+
+ public long objectNum()
+ {
+ return second;
+ }
+
+ public String routingCode()
+ {
+ return Agent.routingCode(agentBank(), brokerBank());
+ }
+
+ public long sequence()
+ {
+ return (this.first & 0x0FFF000000000000L) >> 48;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "" + flags() + "-" + sequence() + "-" + brokerBank() + "-"
+ + agentBank() + "-" + objectNum();
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/QMFEvent.java b/java/management/console/src/main/java/org/apache/qpid/console/QMFEvent.java
new file mode 100644
index 0000000000..116387acfc
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/QMFEvent.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.HashMap;
+
+import org.apache.qpid.transport.codec.*;
+
+public class QMFEvent
+{
+ private java.util.HashMap<String, Object> arguments;
+ private ClassKey classKey;
+ private Session session;
+ private EventSeverity severity;
+ // FIXME time?
+ private long timestamp;
+
+ public QMFEvent(Session session, Decoder dec)
+ {
+ setSession(session);
+ setClassKey(new ClassKey(dec));
+ setTimestamp(dec.readInt64());
+ setSeverity(EventSeverity.values()[dec.readUint8()]);
+ SchemaClass sClass = getSession().getSchema(getClassKey());
+ setArguments(new java.util.HashMap<String, Object>());
+ if (sClass != null)
+ {
+ for (SchemaArgument arg : sClass.arguments)
+ {
+ getArguments().put(arg.getName(),
+ getSession().decodeValue(dec, arg.getType()));
+ }
+ }
+ }
+
+ public final Object GetArgument(String argName)
+ {
+ return getArguments().get(argName);
+ }
+
+ public final HashMap<String, Object> getArguments()
+ {
+ return arguments;
+ }
+
+ public final ClassKey getClassKey()
+ {
+ return classKey;
+ }
+
+ public final Session getSession()
+ {
+ return session;
+ }
+
+ public final EventSeverity getSeverity()
+ {
+ return severity;
+ }
+
+ public final long getTimestamp()
+ {
+ return timestamp;
+ }
+
+ public final void setArguments(java.util.HashMap<String, Object> value)
+ {
+ arguments = value;
+ }
+
+ public final void setClassKey(ClassKey value)
+ {
+ classKey = value;
+ }
+
+ public final void setSession(Session value)
+ {
+ session = value;
+ }
+
+ public final void setSeverity(EventSeverity value)
+ {
+ severity = value;
+ }
+
+ public final void setTimestamp(long value)
+ {
+ timestamp = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/QMFObject.java b/java/management/console/src/main/java/org/apache/qpid/console/QMFObject.java
new file mode 100644
index 0000000000..1919bac411
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/QMFObject.java
@@ -0,0 +1,423 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import edu.emory.mathcs.backport.java.util.Arrays;
+
+public class QMFObject
+{
+ private static Logger log = LoggerFactory.getLogger(QMFObject.class);
+ protected SchemaClass schema;
+ private java.util.Date createTime;
+ private java.util.Date currentTime;
+ private java.util.Date deleteTime;
+ private ObjectID objectID;
+ private Session session;
+ private boolean managed;
+ public java.util.HashMap<String, Object> properties = new java.util.HashMap<String, Object>();
+ public java.util.HashMap<String, Object> statistics = new java.util.HashMap<String, Object>();
+
+ // This constructor is the "naked" constructor which creates
+ // an object without a session or a schema. It is used by
+ // subclasses which are auto generated
+ public QMFObject()
+ {
+ }
+
+ public QMFObject(QMFObject source)
+ {
+ this.setSession(source.getSession());
+ this.setSchema(source.getSchema());
+ this.managed = source.managed;
+ this.setCurrentTime(source.getCurrentTime());
+ this.setCreateTime(source.getCreateTime());
+ this.setDeleteTime(source.getDeleteTime());
+ this.setObjectID(source.getObjectID());
+ this.properties = source.properties;
+ this.statistics = source.statistics;
+ }
+
+ // This constructor is used by a session make object call to
+ // create a blank object from a schema.
+ public QMFObject(Session session, SchemaClass schema,
+ boolean hasProperties, boolean hasStats, boolean isManaged)
+ {
+ setSession(session);
+ setSchema(schema);
+ managed = isManaged;
+ if (hasProperties)
+ {
+ for (SchemaProperty prop : getSchema().getAllProperties())
+ {
+ Object propValue = null;
+ if (!prop.getOptional())
+ {
+ propValue = Util.defaultValue(prop.getType());
+ }
+ this.setProperty(prop.getName(), propValue);
+ }
+ }
+ if (hasStats)
+ {
+ for (SchemaStatistic stat : getSchema().statistics)
+ {
+ setStatistic(stat.getName(), Util.defaultValue(stat.getType()));
+ }
+ }
+ }
+
+ // This constructor is used by the session to create an object based on a
+ // data
+ // stream by the agent.
+ public QMFObject(Session session, SchemaClass schema, Decoder dec,
+ boolean hasProperties, boolean hasStats, boolean isManaged)
+ {
+ setSession(session);
+ setSchema(schema);
+ managed = isManaged;
+ if (managed)
+ {
+ // FIXME DateTime or Uint64??
+ setCurrentTime(new java.util.Date(dec.readDatetime()));
+ setCreateTime(new java.util.Date(dec.readDatetime()));
+ setDeleteTime(new java.util.Date(dec.readDatetime()));
+ setObjectID(new ObjectID(dec));
+ }
+ if (hasProperties)
+ {
+ java.util.ArrayList<String> excluded = processPresenceMasks(dec,
+ getSchema());
+ for (SchemaProperty prop : getSchema().getAllProperties())
+ {
+ if (excluded.contains(prop.getName()))
+ {
+ // log.Debug(String.Format("Setting Property Default {0}",
+ // prop.Name)) ;
+ safeAddProperty(prop.getName(), null);
+ } else
+ {
+ // log.Debug(String.Format("Setting Property {0}",
+ // prop.Name)) ;
+ safeAddProperty(prop.getName(), session.decodeValue(dec,
+ prop.getType()));
+ }
+ }
+ }
+ if (hasStats)
+ {
+ for (SchemaStatistic stat : getSchema().getAllStatistics())
+ {
+ // log.Debug(String.Format("Setting Statistic {0}", stat.Name))
+ // ;
+ statistics.put(stat.getName(), session.decodeValue(dec, stat
+ .getType()));
+ }
+ }
+ }
+
+ public final long agentBank()
+ {
+ return getObjectID().agentBank();
+ }
+
+ public final long brokerBank()
+ {
+ return getObjectID().brokerBank();
+ }
+
+ public final void encode(Encoder enc)
+ {
+ int mask = 0;
+ int bit = 0;
+ java.util.ArrayList<SchemaProperty> propsToEncode = new java.util.ArrayList<SchemaProperty>();
+ log.debug(String.format("Encoding class %s:%s", getSchema()
+ .getPackageName(), getSchema().getClassName()));
+ enc.writeUint8((short) 20);
+ getSchema().getKey().encode(enc);
+ for (SchemaProperty prop : getSchema().getAllProperties())
+ {
+ if (prop.getOptional())
+ {
+ if (bit == 0)
+ {
+ bit = 1;
+ }
+ if ((properties.containsKey(prop.getName()))
+ && (properties.get(prop.getName()) != null))
+ {
+ mask |= bit;
+ propsToEncode.add(prop);
+ } else
+ {
+ }
+ bit = bit << 1;
+ if (bit == 256)
+ {
+ bit = 0;
+ enc.writeUint8((short) mask);
+ mask = 0;
+ }
+ } else
+ {
+ propsToEncode.add(prop);
+ }
+ }
+ if (bit != 0)
+ {
+ enc.writeUint8((short) mask);
+ }
+ for (SchemaProperty prop : propsToEncode)
+ {
+ Object obj = properties.get(prop.getName());
+ // log.Debug(String.Format("Encoding property {0}", prop.Name)) ;
+ getSession().encodeValue(enc, prop.getType(), obj);
+ }
+ for (SchemaStatistic stat : getSchema().statistics)
+ {
+ Object obj = statistics.get(stat.getName());
+ getSession().encodeValue(enc, stat.getType(), obj);
+ }
+ log.debug("Done");
+ }
+
+ public final Date getCreateTime()
+ {
+ return createTime;
+ }
+
+ public final Date getCurrentTime()
+ {
+ return currentTime;
+ }
+
+ public final Date getDeleteTime()
+ {
+ return deleteTime;
+ }
+
+ protected final ArrayList<SchemaMethod> getMethods()
+ {
+ return getSchema().getAllMethods();
+ }
+
+ public final ObjectID getObjectID()
+ {
+ return objectID;
+ }
+
+ public final Object getProperty(String attributeName)
+ {
+ return properties.get(attributeName);
+ }
+
+ public SchemaClass getSchema()
+ {
+ return schema;
+ }
+
+ public final Session getSession()
+ {
+ return session;
+ }
+
+ protected final MethodResult internalInvokeMethod(String name,
+ List<Object> args, boolean synchronous, int timeToLive)
+ {
+ if (!managed)
+ {
+ throw new ConsoleException("Object is not Managed");
+ }
+ if (getSchema().getMethod(name) == null)
+ {
+ throw new ConsoleException(String.format(
+ "Method named '%s' does not exist", name));
+ }
+ return getSession().invokeMethod(this, name, args, synchronous,
+ timeToLive);
+ }
+
+ public final MethodResult invokeMethod(String name, boolean synchronous,
+ int timeToLive, Object... args)
+ {
+ return this.internalInvokeMethod(name, Arrays.asList(args),
+ synchronous, timeToLive);
+ }
+
+ public final MethodResult invokeMethod(String name, boolean synchronous,
+ Object... args)
+ {
+ return this.internalInvokeMethod(name, Arrays.asList(args),
+ synchronous, Broker.SYNC_TIME);
+ }
+
+ public final MethodResult invokeMethod(String name, int timeToLive,
+ Object... args)
+ {
+ return this.internalInvokeMethod(name, Arrays.asList(args), true,
+ timeToLive);
+ }
+
+ public final MethodResult invokeMethod(String name, Object... args)
+ {
+ return this.internalInvokeMethod(name, Arrays.asList(args), true,
+ Broker.SYNC_TIME);
+ }
+
+ public final boolean isDeleted()
+ {
+ return !getDeleteTime().equals(new java.util.Date(0));
+ }
+
+ protected final ArrayList<String> processPresenceMasks(Decoder dec,
+ SchemaClass schema)
+ {
+ java.util.ArrayList<String> excludes = new java.util.ArrayList<String>();
+ short bit = 0;
+ short mask = 0;
+ for (SchemaProperty prop : getSchema().getAllProperties())
+ {
+ if (prop.getOptional())
+ {
+ // log.Debug(String.Format("Property named {0} is optional",
+ // prop.Name)) ;
+ if (bit == 0)
+ {
+ mask = dec.readUint8();
+ bit = 1;
+ }
+ if ((mask & bit) == 0)
+ {
+ // log.Debug(String.Format("Property named {0} is not present",
+ // prop.Name)) ;
+ excludes.add(prop.getName());
+ }
+ bit *= 2;
+ if (bit == 256)
+ {
+ bit = 0;
+ }
+ }
+ }
+ return excludes;
+ }
+
+ public final String routingKey()
+ {
+ return getObjectID().routingCode();
+ }
+
+ protected final void safeAddProperty(String propName, Object value)
+ {
+ if (properties.containsKey(propName))
+ {
+ properties.put(propName, value);
+ } else
+ {
+ properties.put(propName, value);
+ }
+ }
+
+ public final void setCreateTime(java.util.Date value)
+ {
+ createTime = value;
+ }
+
+ public final void setCurrentTime(java.util.Date value)
+ {
+ currentTime = value;
+ }
+
+ public final void setDeleteTime(java.util.Date value)
+ {
+ deleteTime = value;
+ }
+
+ public final void setObjectID(ObjectID value)
+ {
+ objectID = value;
+ }
+
+ public final void setProperty(String attributeName, Object newValue)
+ {
+ properties.put(attributeName, newValue);
+ }
+
+ public void setSchema(SchemaClass value)
+ {
+ schema = value;
+ }
+
+ public final void setSession(Session value)
+ {
+ session = value;
+ }
+
+ protected final void setStatistic(String attributeName, Object newValue)
+ {
+ statistics.put(attributeName, newValue);
+ }
+
+ @Override
+ public String toString()
+ {
+ String propertyString = "";
+ for (Entry<String, Object> pair : properties.entrySet())
+ {
+ propertyString = propertyString
+ + String.format("(Name: '%0$s' Value: '%1$s')", pair
+ .getKey(), pair.getValue());
+ }
+ String statsString = "";
+ for (Entry<String, Object> sPair : statistics.entrySet())
+ {
+ statsString = statsString
+ + String.format("(Name: '%0$s' Value: '%1$s')", sPair
+ .getKey(), sPair.getValue());
+ }
+ if (managed)
+ {
+ return String
+ .format(
+ "Managed QMFObject %0$s:%1$s(%2$s) Properties: [%3$s] Statistics: [%4$s])",
+ getSchema().getPackageName(), getSchema()
+ .getClassName(), getObjectID(),
+ propertyString, statsString);
+ } else
+ {
+ return String
+ .format(
+ "QMFObject %0$s:%1$s Properties: [%2$s] Statistics: [%3$s]",
+ getSchema().getPackageName(), getSchema()
+ .getClassName(), propertyString,
+ statsString);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaArgument.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaArgument.java
new file mode 100644
index 0000000000..7e83b1b447
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaArgument.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.console;
+
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.Decoder;
+
+public class SchemaArgument extends SchemaVariable
+{
+ private String direction;
+
+ public SchemaArgument(Decoder dec, boolean methodArg)
+ {
+ Map<String, Object> map = dec.readMap();
+ super.populateData(map);
+ if (map.containsKey("dir"))
+ {
+ setDirection((String) map.get("dir"));
+ }
+ }
+
+ public String getDirection()
+ {
+ return direction;
+ }
+
+ public boolean isBidirectional()
+ {
+ return getDirection().equals("IO");
+ }
+
+ public boolean isInput()
+ {
+ return getDirection().equals("I") | getDirection().equals("IO");
+ }
+
+ public boolean isOutput()
+ {
+ return getDirection().equals("O") | getDirection().equals("IO");
+ }
+
+ public void setDirection(String value)
+ {
+ direction = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaClass.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaClass.java
new file mode 100644
index 0000000000..311d81cc8e
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaClass.java
@@ -0,0 +1,251 @@
+/*
+ *
+ * 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 org.apache.qpid.console;//
+
+import java.util.ArrayList;
+
+import org.apache.qpid.transport.codec.*;
+
+public class SchemaClass
+{
+ public static final int CLASS_KIND_EVENT = 2;
+ public static final int CLASS_KIND_TABLE = 1;
+ public ArrayList<SchemaArgument> arguments = new ArrayList<SchemaArgument>();
+ private ClassKey classKey;
+ private int kind;
+ private Session session;
+ private ClassKey superType;
+ public ArrayList<SchemaMethod> methods = new ArrayList<SchemaMethod>();
+ public ArrayList<SchemaProperty> properties = new ArrayList<SchemaProperty>();
+ public ArrayList<SchemaStatistic> statistics = new ArrayList<SchemaStatistic>();
+
+ public SchemaClass(int kind, ClassKey key, Decoder dec, Session session)
+ {
+ // System.Console.WriteLine(key.ClassName) ;
+ setKind(kind);
+ setSession(session);
+ this.setKey(key);
+ boolean hasSupertype = false; //dec.readUint8() != 0;
+ if (kind == CLASS_KIND_TABLE)
+ {
+ int propCount = dec.readUint16();
+ int statCount = dec.readUint16();
+ int methodCount = dec.readUint16();
+ if (hasSupertype)
+ {
+ setSuperType(new ClassKey(dec));
+ }
+ for (int x = 0; x < propCount; x++)
+ {
+ properties.add(new SchemaProperty(dec));
+ }
+ for (int x = 0; x < statCount; x++)
+ {
+ statistics.add(new SchemaStatistic(dec));
+ }
+ for (int x = 0; x < methodCount; x++)
+ {
+ methods.add(new SchemaMethod(dec));
+ }
+ }
+ if (kind == CLASS_KIND_EVENT)
+ {
+ int argCount = dec.readUint16();
+ if (hasSupertype)
+ {
+ setSuperType(new ClassKey(dec));
+ }
+ for (int x = 0; x < argCount; x++)
+ {
+ arguments.add(new SchemaArgument(dec, false));
+ }
+ }
+ }
+
+ public ArrayList<SchemaMethod> getAllMethods()
+ {
+ if (getSuperType() == null)
+ {
+ return methods;
+ } else
+ {
+ ArrayList<SchemaMethod> allMethods = new ArrayList<SchemaMethod>(
+ methods);
+ allMethods.addAll(getSession().getSchema(getSuperType())
+ .getAllMethods());
+ return allMethods;
+ }
+ }
+
+ public ArrayList<SchemaProperty> getAllProperties()
+ {
+ if (getSuperType() == null)
+ {
+ return properties;
+ } else
+ {
+ ArrayList<SchemaProperty> allProperties = new ArrayList<SchemaProperty>(
+ properties);
+ allProperties.addAll(getSession().getSchema(getSuperType())
+ .getAllProperties());
+ return allProperties;
+ }
+ }
+
+ public ArrayList<SchemaStatistic> getAllStatistics()
+ {
+ if (getSuperType() == null)
+ {
+ return statistics;
+ } else
+ {
+ ArrayList<SchemaStatistic> allStats = new ArrayList<SchemaStatistic>(
+ statistics);
+ allStats.addAll(getSession().getSchema(getSuperType())
+ .getAllStatistics());
+ return allStats;
+ }
+ }
+
+ public String getClassKeyString()
+ {
+ return getKey().getKeyString();
+ }
+
+ public String getClassName()
+ {
+ return getKey().getClassName();
+ }
+
+ public ClassKey getKey()
+ {
+ return classKey;
+ }
+
+ public int getKind()
+ {
+ return kind;
+ }
+
+ public SchemaMethod getMethod(String name)
+ {
+ SchemaMethod returnValue = null;
+ for (SchemaMethod method : methods)
+ {
+ if (method.getName().equals(name))
+ {
+ returnValue = method;
+ break;
+ }
+ }
+ return returnValue;
+ }
+
+ public String getPackageName()
+ {
+ return getKey().getPackageName();
+ }
+
+ protected Session getSession()
+ {
+ return session;
+ }
+
+ public ClassKey getSuperType()
+ {
+ return superType;
+ }
+
+ public boolean hasSuperType()
+ {
+ return getSuperType() != null;
+ }
+
+ public void setKey(ClassKey value)
+ {
+ classKey = value;
+ }
+
+ public void setKind(int value)
+ {
+ kind = value;
+ }
+
+ protected void setSession(Session value)
+ {
+ session = value;
+ }
+
+ public void setSuperType(ClassKey value)
+ {
+ superType = value;
+ }
+
+ public ArrayList<SchemaProperty> getProperties()
+ {
+ return properties;
+ }
+
+ public void setProperties(ArrayList<SchemaProperty> properties)
+ {
+ this.properties = properties;
+ }
+
+ public ArrayList<SchemaMethod> getMethods()
+ {
+ return methods;
+ }
+
+ public void setMethods(ArrayList<SchemaMethod> methods)
+ {
+ this.methods = methods;
+ }
+
+ public ArrayList<SchemaStatistic> getStatistics()
+ {
+ return statistics;
+ }
+
+ public void setStatistics(ArrayList<SchemaStatistic> statistics)
+ {
+ this.statistics = statistics;
+ }
+
+ public ArrayList<SchemaArgument> getArguments()
+ {
+ return arguments;
+ }
+
+ public void setArguments(ArrayList<SchemaArgument> arguments)
+ {
+ this.arguments = arguments;
+ }
+
+ public ClassKey getClassKey()
+ {
+ return classKey;
+ }
+
+ public void setClassKey(ClassKey classKey)
+ {
+ this.classKey = classKey;
+ }
+}
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaMethod.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaMethod.java
new file mode 100644
index 0000000000..1c20ae55bb
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaMethod.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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 org.apache.qpid.console;//
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.*;
+
+public class SchemaMethod
+{
+ public ArrayList<SchemaArgument> Arguments = new ArrayList<SchemaArgument>();
+ private int m_ArgCount;
+ private int m_BidirectionalArgCount;
+ private String m_Description;
+ private int m_InputArgCount;
+ private String m_Name;
+ private int m_OutputArgCount;
+
+ public SchemaMethod(Decoder dec)
+ {
+ Map<String, Object> map = dec.readMap();
+ setName((String) map.get("name"));
+ setArgCount((Integer) map.get("argCount"));
+ if (map.containsKey("desc"))
+ {
+ setDescription((String) map.get("desc"));
+ }
+ for (int x = 0; x < getArgCount(); x++)
+ {
+ SchemaArgument arg = new SchemaArgument(dec, true);
+ Arguments.add(arg);
+ if (arg.isInput())
+ {
+ setInputArgCount(getInputArgCount() + 1);
+ }
+ if (arg.isOutput())
+ {
+ setOutputArgCount(getOutputArgCount() + 1);
+ }
+ if (arg.isBidirectional())
+ {
+ setBidirectionalArgCount(getBidirectionalArgCount() + 1);
+ }
+ }
+ }
+
+ public final int getArgCount()
+ {
+ return m_ArgCount;
+ }
+
+ public final int getBidirectionalArgCount()
+ {
+ return m_BidirectionalArgCount;
+ }
+
+ public final String getDescription()
+ {
+ return m_Description;
+ }
+
+ public final int getInputArgCount()
+ {
+ return m_InputArgCount;
+ }
+
+ public final String getName()
+ {
+ return m_Name;
+ }
+
+ public final int getOutputArgCount()
+ {
+ return m_OutputArgCount;
+ }
+
+ public final void setArgCount(int value)
+ {
+ m_ArgCount = value;
+ }
+
+ public final void setBidirectionalArgCount(int value)
+ {
+ m_BidirectionalArgCount = value;
+ }
+
+ public final void setDescription(String value)
+ {
+ m_Description = value;
+ }
+
+ public final void setInputArgCount(int value)
+ {
+ m_InputArgCount = value;
+ }
+
+ public final void setName(String value)
+ {
+ m_Name = value;
+ }
+
+ public final void setOutputArgCount(int value)
+ {
+ m_OutputArgCount = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaProperty.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaProperty.java
new file mode 100644
index 0000000000..8e278ff70d
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaProperty.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.*;
+
+public class SchemaProperty extends SchemaVariable
+{
+ private int access;
+ private boolean index;
+ private boolean optional;
+
+ public SchemaProperty(Decoder dec)
+ {
+ Map<String, Object> map = dec.readMap();
+ super.populateData(map);
+ setName((String) map.get("name"));
+ if (map.containsKey("optional"))
+ {
+ setOptional((Integer) map.get("optional") != 0);
+ }
+ if (map.containsKey("index"))
+ {
+ setIndex((Integer) map.get("index") != 0);
+ }
+ if (map.containsKey("access"))
+ {
+ setAccess((Integer) map.get("access"));
+ }
+ }
+
+ public int getAccess()
+ {
+ return access;
+ }
+
+ public boolean getIndex()
+ {
+ return index;
+ }
+
+ public boolean getOptional()
+ {
+ return optional;
+ }
+
+ public void setAccess(int value)
+ {
+ access = value;
+ }
+
+ public void setIndex(boolean value)
+ {
+ index = value;
+ }
+
+ public void setOptional(boolean value)
+ {
+ optional = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaStatistic.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaStatistic.java
new file mode 100644
index 0000000000..18bce86423
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaStatistic.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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 org.apache.qpid.console;//
+
+import java.util.Map;
+
+import org.apache.qpid.transport.codec.*;
+
+public class SchemaStatistic
+{
+ private String description;
+ private String name;
+ private short type;
+ private String unit;
+
+ public SchemaStatistic(Decoder dec)
+ {
+ Map<String, Object> map = dec.readMap();
+ setName((String) map.get("name"));
+ setType(Short.parseShort("" + map.get("type")));
+ if (map.containsKey("unit"))
+ {
+ setUnit((String) map.get("unit"));
+ }
+ if (map.containsKey("description"))
+ {
+ setDescription((String) map.get("description"));
+ }
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public short getType()
+ {
+ return type;
+ }
+
+ public String getUnit()
+ {
+ return unit;
+ }
+
+ public void setDescription(String value)
+ {
+ description = value;
+ }
+
+ public void setName(String value)
+ {
+ name = value;
+ }
+
+ public void setType(short value)
+ {
+ type = value;
+ }
+
+ public void setUnit(String value)
+ {
+ unit = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SchemaVariable.java b/java/management/console/src/main/java/org/apache/qpid/console/SchemaVariable.java
new file mode 100644
index 0000000000..483a17d0de
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SchemaVariable.java
@@ -0,0 +1,185 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.Map;
+
+public abstract class SchemaVariable
+{
+ private String defaultVariable;
+ private String description;
+ private Integer max;
+ private Integer maxLength;
+ private Integer min;
+ private String name;
+ private String refClass;
+ private String refPackage;
+ private short type;
+ private String unit;
+
+ public SchemaVariable()
+ {
+ }
+
+ public String getDefault()
+ {
+ return defaultVariable;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public Integer getMax()
+ {
+ return max;
+ }
+
+ public Integer getMaxLength()
+ {
+ return maxLength;
+ }
+
+ public Integer getMin()
+ {
+ return min;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getRefClass()
+ {
+ return refClass;
+ }
+
+ public String getRefPackage()
+ {
+ return refPackage;
+ }
+
+ public short getType()
+ {
+ return type;
+ }
+
+ public String getUnit()
+ {
+ return unit;
+ }
+
+ protected void populateData(Map<String, Object> map)
+ {
+ if (map.containsKey("name"))
+ {
+ setName((String) map.get("name"));
+ }
+ if (map.containsKey("type"))
+ {
+ setType(Short.parseShort(("" + map.get("type"))));
+ }
+ if (map.containsKey("unit"))
+ {
+ setUnit((String) map.get("unit"));
+ }
+ if (map.containsKey("min"))
+ {
+ setMin((Integer) map.get("min"));
+ }
+ if (map.containsKey("max"))
+ {
+ setMax((Integer) map.get("max"));
+ }
+ if (map.containsKey("maxlen"))
+ {
+ setMaxLength((Integer) map.get("maxlen"));
+ }
+ if (map.containsKey("description"))
+ {
+ setDescription((String) map.get("description"));
+ }
+ if (map.containsKey("refClass"))
+ {
+ setRefClass((String) map.get("refClass"));
+ }
+ if (map.containsKey("refPackage"))
+ {
+ setRefPackage((String) map.get("refPackage"));
+ }
+ if (map.containsKey("Default"))
+ {
+ setDefault((String) map.get("default"));
+ }
+ }
+
+ public void setDefault(String value)
+ {
+ defaultVariable = value;
+ }
+
+ public void setDescription(String value)
+ {
+ description = value;
+ }
+
+ public void setMax(Integer value)
+ {
+ max = value;
+ }
+
+ public void setMaxLength(Integer value)
+ {
+ maxLength = value;
+ }
+
+ public void setMin(Integer value)
+ {
+ min = value;
+ }
+
+ public void setName(String value)
+ {
+ name = value;
+ }
+
+ public void setRefClass(String value)
+ {
+ refClass = value;
+ }
+
+ public void setRefPackage(String value)
+ {
+ refPackage = value;
+ }
+
+ public void setType(short value)
+ {
+ type = value;
+ }
+
+ public void setUnit(String value)
+ {
+ unit = value;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/SequenceManager.java b/java/management/console/src/main/java/org/apache/qpid/console/SequenceManager.java
new file mode 100644
index 0000000000..4c5fcc7355
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/SequenceManager.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.util.HashMap;
+
+public class SequenceManager
+{
+ private long sequence = 0;
+ private HashMap<Long, Object> pending = new HashMap<Long, Object>();
+ private Object lockObject = new Object();
+
+ public SequenceManager()
+ {
+ }
+
+ public Object release(long seq)
+ {
+ Object returnValue = null;
+ synchronized (lockObject)
+ {
+ returnValue = pending.get(seq);
+ pending.remove(seq);
+ }
+ return returnValue;
+ }
+
+ public long reserve(Object data)
+ {
+ long returnValue = 0;
+ synchronized (lockObject)
+ {
+ returnValue = sequence;
+ sequence += 1;
+ pending.put(returnValue, data);
+ }
+ return returnValue;
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/Session.java b/java/management/console/src/main/java/org/apache/qpid/console/Session.java
new file mode 100644
index 0000000000..a590a95546
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/Session.java
@@ -0,0 +1,980 @@
+/*
+ *
+ * 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 org.apache.qpid.console;//
+
+import java.lang.reflect.Constructor;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.jms.Message;
+
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Session
+{
+ private static Logger log = LoggerFactory.getLogger(Session.class);
+ public static final int CONTEXT_SYNC = 1;
+ public static final int CONTEXT_STARTUP = 2;
+ public static final int CONTEXT_MULTIGET = 3;
+ public static final int DEFAULT_GET_WAIT_TIME = 60000;
+ public boolean recieveObjects = true;
+ public boolean recieveEvents = true;
+ public boolean recieveHeartbeat = true;
+ public boolean userBindings = false;
+ public Console console;
+ protected HashMap<String, HashMap<String, SchemaClass>> packages = new HashMap<String, HashMap<String, SchemaClass>>();
+ protected ArrayList<Broker> brokers = new ArrayList<Broker>();
+ protected SequenceManager sequenceManager = new SequenceManager();
+ protected Object lockObject = new Object();
+ protected ArrayList<Long> syncSequenceList = new ArrayList<Long>();
+ protected ArrayList<QMFObject> getResult;
+ protected Object syncResult;
+
+ public Session()
+ {
+ }
+
+ public Session(Console console)
+ {
+ this.console = console;
+ }
+
+ public void addBroker(String url)
+ {
+ Broker broker = new Broker(this, url);
+ brokers.add(broker);
+ java.util.HashMap<String, Object> args = new java.util.HashMap<String, Object>();
+ args.put("_class", "agent");
+ args.put("_broker", broker);
+ this.getObjects(args);
+ }
+
+ public ArrayList<String> bindingKeys()
+ {
+ ArrayList<String> bindings = new ArrayList<String>();
+ bindings.add("schema.#");
+ if (recieveObjects && recieveEvents && recieveHeartbeat && !userBindings)
+ {
+ bindings.add("console.#");
+ } else
+ {
+ if (recieveObjects && !userBindings)
+ {
+ bindings.add("console.obj.#");
+ } else
+ {
+ bindings.add("console.obj.*.*.org.apache.qpid.broker.agent");
+ }
+ if (recieveEvents)
+ {
+ bindings.add("console.event.#");
+ }
+ if (recieveHeartbeat)
+ {
+ bindings.add("console.heartbeat.#");
+ }
+ }
+ return bindings;
+ }
+
+ public void close()
+ {
+ for (Broker broker : brokers.toArray(new Broker[0]))
+ {
+ this.removeBroker(broker);
+ }
+ }
+
+ protected QMFObject createQMFObject(SchemaClass schema,
+ boolean hasProperties, boolean hasStats, boolean isManaged)
+ {
+ Class realClass = QMFObject.class;
+ if (console != null)
+ {
+ realClass = console.typeMapping(schema.getKey());
+ }
+ Class[] types = new Class[]
+ { Session.class, SchemaClass.class, boolean.class, boolean.class,
+ boolean.class };
+ Object[] args = new Object[]
+ { this, schema, hasProperties, hasStats, isManaged };
+ try
+ {
+ Constructor ci = realClass.getConstructor(types);
+ return (QMFObject) ci.newInstance(args);
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+
+ protected QMFObject createQMFObject(SchemaClass schema, Decoder dec,
+ boolean hasProperties, boolean hasStats, boolean isManaged)
+ {
+ Class realClass = QMFObject.class;
+ if (console != null)
+ {
+ realClass = console.typeMapping(schema.getKey());
+ }
+ Class[] types = new Class[]
+ { Session.class, SchemaClass.class, Decoder.class, boolean.class,
+ boolean.class, boolean.class };
+ Object[] args = new Object[]
+ { this, schema, dec, hasProperties, hasStats, isManaged };
+ try
+ {
+ log.debug("" + realClass);
+ Constructor ci = realClass.getConstructor(types);
+ return (QMFObject) ci.newInstance(args);
+ } catch (Exception e)
+ {
+ throw new ConsoleException(e);
+ }
+ }
+
+ public Object decodeValue(Decoder dec, short type)
+ {
+ switch (type)
+ {
+ case 1: // U8
+ return dec.readUint8();
+ case 2: // U16
+ return dec.readUint16();
+ case 3: // U32
+ return dec.readUint32();
+ case 4: // U64
+ return dec.readUint64();
+ case 6: // SSTR
+ return dec.readStr8();
+ case 7: // LSTR
+ return dec.readStr16();
+ case 8: // ABSTIME
+ return dec.readDatetime();
+ case 9: // DELTATIME
+ return dec.readUint32();
+ case 10: // ref
+ return new ObjectID(dec);
+ case 11: // bool
+ return dec.readUint8() != 0;
+ case 12: // float
+ return dec.readFloat();
+ case 13: // double
+ return dec.readDouble();
+ case 14: // UUID
+ return dec.readUuid();
+ case 15: // Ftable
+ return dec.readMap();
+ case 16: // int8
+ return dec.readInt8();
+ case 17: // int16
+ return dec.readInt16();
+ case 18: // int32
+ return dec.readInt32();
+ case 19: // int64
+ return dec.readInt64();
+ case 20: // Object
+ // Peek into the inner type code, make sure
+ // it is actually an object
+ Object returnValue = null;
+ short innerTypeCode = dec.readUint8();
+ if (innerTypeCode != 20)
+ {
+ returnValue = this.decodeValue(dec, innerTypeCode);
+ } else
+ {
+ ClassKey classKey = new ClassKey(dec);
+ synchronized (lockObject)
+ {
+ SchemaClass sClass = getSchema(classKey);
+ if (sClass != null)
+ {
+ returnValue = this.createQMFObject(sClass, dec, true,
+ true, false);
+ }
+ }
+ }
+ return returnValue;
+ case 21: // List
+ BBDecoder lDec = new BBDecoder();
+ lDec.init(ByteBuffer.wrap(dec.readVbin32()));
+ long count = lDec.readUint32();
+ ArrayList<Object> newList = new ArrayList<Object>();
+ while (count > 0)
+ {
+ short innerType = lDec.readUint8();
+ newList.add(this.decodeValue(lDec, innerType));
+ count -= 1;
+ }
+ return newList;
+ case 22: // Array
+ BBDecoder aDec = new BBDecoder();
+ aDec.init(ByteBuffer.wrap(dec.readVbin32()));
+ long cnt = aDec.readUint32();
+ short innerType = aDec.readUint8();
+ ArrayList<Object> aList = new ArrayList<Object>();
+ while (cnt > 0)
+ {
+ aList.add(this.decodeValue(aDec, innerType));
+ cnt -= 1;
+ }
+ return aList;
+ default:
+ throw new ConsoleException(String.format("Invalid Type Code: %s",
+ type));
+ }
+ }
+
+ public void encodeValue(Encoder enc, short type, Object val)
+ {
+ try
+ {
+ switch (type)
+ {
+ case 1: // U8
+ enc.writeUint8(((Short) val).shortValue());
+ break;
+ case 2: // U16
+ enc.writeUint16(((Integer) val).intValue());
+ break;
+ case 3: // U32
+ enc.writeUint32(((Integer) val).longValue());
+ break;
+ case 4: // U64
+ enc.writeUint64(((Long) val).longValue());
+ break;
+ case 6: // SSTR
+ enc.writeStr8((String) val);
+ break;
+ case 7: // LSTR
+ enc.writeStr16((String) val);
+ break;
+ case 8: // ABSTIME
+ enc.writeDatetime(((Long) val).longValue());
+ break;
+ case 9: // DELTATIME
+ enc.writeUint32(((Long) val).longValue());
+ break;
+ case 10: // ref
+ ((ObjectID) val).encode(enc);
+ break;
+ case 11:
+ if (((Boolean) val).booleanValue())
+ {
+ enc.writeUint8((short) 1);
+ } else
+ {
+ enc.writeUint8((short) 0);
+ }
+ break;
+ case 12: // FLOAT
+ enc.writeFloat(((Float) val).floatValue());
+ break;
+ case 13: // DOUBLE
+ enc.writeDouble(((Double) val).doubleValue());
+ break;
+ case 14: // UUID
+ enc.writeUuid((UUID) val);
+ break;
+ case 15: // Ftable
+ enc.writeMap((HashMap) val);
+ break;
+ case 16: // int8
+ enc.writeInt8((Byte) val);
+ break;
+ case 17: // int16
+ enc.writeInt16((Short) val);
+ break;
+ case 18: // int32
+ enc.writeInt32((Integer) val);
+ break;
+ case 19: // int64
+ enc.writeInt64((Long) val);
+ break;
+ case 20: // Object
+ // Check that the object has a session, if not
+ // take ownership of it
+ QMFObject qObj = (QMFObject) val;
+ if (qObj.getSession() == null)
+ {
+ qObj.setSession(this);
+ }
+ qObj.encode(enc);
+ break;
+ case 21: // List
+ ArrayList<Object> items = (ArrayList<Object>) val;
+ BBEncoder lEnc = new BBEncoder(1);
+ lEnc.init();
+ lEnc.writeUint32(items.size());
+ for (Object obj : items)
+ {
+ short innerType = Util.qmfType(obj);
+ lEnc.writeUint8(innerType);
+ this.encodeValue(lEnc, innerType, obj);
+ }
+ enc.writeVbin32(lEnc.segment().array());
+ break;
+ case 22: // Array
+ ArrayList<Object> aItems = (ArrayList<Object>) val;
+ BBEncoder aEnc = new BBEncoder(1);
+ aEnc.init();
+ long aCount = aItems.size();
+ aEnc.writeUint32(aCount);
+ if (aCount > 0)
+ {
+ Object anObj = aItems.get(0);
+ short innerType = Util.qmfType(anObj);
+ aEnc.writeUint8(innerType);
+ for (Object obj : aItems)
+ {
+ this.encodeValue(aEnc, innerType, obj);
+ }
+ }
+ enc.writeVbin32(aEnc.segment().array());
+ break;
+ default:
+ throw new ConsoleException(String.format(
+ "Invalid Type Code: %s", type));
+ }
+ } catch (ClassCastException e)
+ {
+ String msg = String.format(
+ "Class cast exception for typecode %s, type %s ", type, val
+ .getClass());
+ log.error(msg);
+ throw new ConsoleException(msg + type, e);
+ }
+ }
+
+ public Broker getBroker(long BrokerBank)
+ {
+ Broker returnValue = null;
+ for (Broker broker : brokers)
+ {
+ if (broker.brokerBank() == BrokerBank)
+ {
+ returnValue = broker;
+ break;
+ }
+ }
+ return returnValue;
+ }
+
+ public ArrayList<ClassKey> getClasses(String packageName)
+ {
+ ArrayList<ClassKey> returnValue = new ArrayList<ClassKey>();
+ this.waitForStable();
+ if (packages.containsKey(packageName))
+ {
+ for (SchemaClass sClass : packages.get(packageName).values())
+ {
+ returnValue.add(sClass.getKey());
+ }
+ }
+ return returnValue;
+ }
+
+ public ArrayList<QMFObject> getObjects(
+ java.util.HashMap<String, Object> args)
+ {
+ ArrayList<Broker> brokerList = null;
+ ArrayList<Agent> agentList = new ArrayList<Agent>();
+ if (args.containsKey("_broker"))
+ {
+ brokerList = new ArrayList<Broker>();
+ brokerList.add((Broker) args.get("_broker"));
+ } else
+ {
+ brokerList = this.brokers;
+ }
+ for (Broker broker : brokerList)
+ {
+ broker.waitForStable();
+ }
+ if (args.containsKey("_agent"))
+ {
+ Agent agent = (Agent) args.get("_agent");
+ if (brokerList.contains(agent.getBroker()))
+ {
+ agentList.add(agent);
+ } else
+ {
+ throw new ConsoleException(
+ "Agent is not managed by this console or the supplied broker");
+ }
+ } else
+ {
+ if (args.containsKey("_objectId"))
+ {
+ ObjectID oid = (ObjectID) args.get("_objectId");
+ for (Broker broker : brokers)
+ {
+ for (Agent agent : broker.Agents.values())
+ {
+ if ((agent.getAgentBank() == oid.agentBank())
+ && (agent.getBrokerBank() == oid.brokerBank()))
+ {
+ agentList.add(agent);
+ }
+ }
+ }
+ } else
+ {
+ for (Broker broker : brokerList)
+ {
+ for (Agent agent : broker.Agents.values())
+ {
+ if (agent.getBroker().isConnected())
+ {
+ agentList.add(agent);
+ }
+ }
+ }
+ }
+ }
+ getResult = new ArrayList<QMFObject>();
+ if (agentList.size() > 0)
+ {
+ // FIXME Add a bunch of other suff too
+ for (Agent agent : agentList)
+ {
+ HashMap<String, Object> getParameters = new HashMap<String, Object>();
+ Broker broker = agent.getBroker();
+ long seq = -1;
+ synchronized (lockObject)
+ {
+ seq = sequenceManager.reserve(Session.CONTEXT_MULTIGET);
+ syncSequenceList.add(seq);
+ }
+ String packageName = (String) args.get("_package");
+ String className = (String) args.get("_class");
+ ClassKey key = (ClassKey) args.get("_key");
+ Object sClass = args.get("_schema");
+ Object oid = args.get("_objectID");
+ long[] hash = (long[]) args.get("_hash");
+ if ((className == null) && (oid == null))
+ {
+ throw new ConsoleException(
+ "No class supplied, use '_schema', '_key', '_class', or '_objectId' argument");
+ }
+ if (oid != null)
+ {
+ getParameters.put("_objectID", oid);
+ } else
+ {
+ if (sClass != null)
+ {
+ key = (key != null) ? key : ((SchemaClass) sClass)
+ .getKey();
+ }
+ if (key != null)
+ {
+ className = (className != null) ? className : key
+ .getClassName();
+ packageName = (packageName != null) ? packageName : key
+ .getPackageName();
+ hash = (hash != null) ? hash : key.getHash();
+ }
+ if (packageName != null)
+ {
+ getParameters.put("_package", packageName);
+ }
+ if (className != null)
+ {
+ getParameters.put("_class", className);
+ }
+ if (hash != null)
+ {
+ getParameters.put("_hash", hash);
+ }
+ for (java.util.Map.Entry<String, Object> pair : args
+ .entrySet())
+ {
+ if (!pair.getKey().startsWith("_"))
+ {
+ getParameters.put(pair.getKey(), pair.getValue());
+ }
+ }
+ }
+ Encoder enc = broker.createEncoder('G', seq);
+ enc.writeMap(getParameters);
+ String routingKey = agent.routingCode();
+ Message msg = broker.createMessage(enc);
+ log.debug("Get Object Keys: ");
+ for (String pKey : getParameters.keySet())
+ {
+ log.debug(String.format("\tKey: '%s' Value: '%s'", pKey,
+ getParameters.get(pKey)));
+ }
+ broker.send(msg, routingKey);
+ }
+ int waittime = DEFAULT_GET_WAIT_TIME;
+ boolean timeout = false;
+ if (args.containsKey("_timeout"))
+ {
+ waittime = (Integer) args.get("_timeout");
+ }
+ long start = System.currentTimeMillis();
+ synchronized (lockObject)
+ {
+ // FIXME ERROR
+ while (syncSequenceList.size() > 0)
+ {
+ try
+ {
+ lockObject.wait(waittime);
+ } catch (InterruptedException e)
+ {
+ throw new ConsoleException(e);
+ }
+ long duration = System.currentTimeMillis() - start;
+ if (duration > waittime)
+ {
+ for (long pendingSeq : syncSequenceList)
+ {
+ sequenceManager.release(pendingSeq);
+ }
+ syncSequenceList.clear();
+ timeout = true;
+ }
+ }
+ }
+ // FIXME Add the error logic
+ if ((getResult.isEmpty()) && timeout)
+ {
+ throw new ConsoleException("Get Request timed out");
+ }
+ }
+ return getResult;
+ }
+
+ public ArrayList<String> getPackages()
+ {
+ this.waitForStable();
+ ArrayList<String> returnValue = new ArrayList<String>();
+ for (String name : packages.keySet())
+ {
+ returnValue.add(name);
+ }
+ return returnValue;
+ }
+
+ public SchemaClass getSchema(ClassKey key)
+ {
+ return getSchema(key, true);
+ }
+
+ protected SchemaClass getSchema(ClassKey key, boolean waitForStable)
+ {
+ if (waitForStable)
+ {
+ this.waitForStable();
+ }
+ SchemaClass returnValue = null;
+ returnValue = packages.get(key.getPackageName())
+ .get(key.getKeyString());
+ return returnValue;
+ }
+
+ public void handleAgentRemoved(Agent agent)
+ {
+ if (console != null)
+ {
+ console.agentRemoved(agent);
+ }
+ }
+
+ public void handleBrokerConnect(Broker broker)
+ {
+ if (console != null)
+ {
+ console.brokerConnected(broker);
+ }
+ }
+
+ public void handleBrokerDisconnect(Broker broker)
+ {
+ if (console != null)
+ {
+ console.brokerDisconnected(broker);
+ }
+ }
+
+ public void handleBrokerResponse(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ if (console != null)
+ {
+ console.brokerInformation(broker);
+ }
+ long seq = sequenceManager.reserve(CONTEXT_STARTUP);
+ Encoder encoder = broker.createEncoder('P', seq);
+ broker.send(encoder);
+ }
+
+ public void handleClassIndicator(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ short kind = decoder.readUint8();
+ ClassKey classKey = new ClassKey(decoder);
+ boolean unknown = false;
+ synchronized (lockObject)
+ {
+ if (packages.containsKey(classKey.getPackageName()))
+ {
+ if (!packages.get(classKey.getPackageName()).containsKey(
+ classKey.getKeyString()))
+ {
+ unknown = true;
+ }
+ }
+ }
+ if (unknown)
+ {
+ broker.incrementOutstanding();
+ long seq = sequenceManager.reserve(Session.CONTEXT_STARTUP);
+ Encoder enc = broker.createEncoder('S', seq);
+ classKey.encode(enc);
+ broker.send(enc);
+ }
+ }
+
+ public void handleCommandComplete(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ long code = decoder.readUint32();
+ String text = decoder.readStr8();
+ Object context = this.sequenceManager.release(sequence);
+ if (context.equals(CONTEXT_STARTUP))
+ {
+ broker.decrementOutstanding();
+ } else
+ {
+ if ((context.equals(CONTEXT_SYNC)) && broker.getSyncInFlight())
+ {
+ broker.setSyncInFlight(false);
+ } else
+ {
+ if (context.equals(CONTEXT_MULTIGET)
+ && syncSequenceList.contains(sequence))
+ {
+ synchronized (lockObject)
+ {
+ syncSequenceList.remove(sequence);
+ if (syncSequenceList.isEmpty())
+ {
+ lockObject.notifyAll();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void handleContentIndicator(Broker broker, Decoder decoder,
+ long sequence, boolean hasProperties, boolean hasStatistics)
+ {
+ ClassKey key = new ClassKey(decoder);
+ SchemaClass sClass = null;
+ ;
+ synchronized (lockObject)
+ {
+ sClass = getSchema(key, false);
+ }
+ if (sClass != null)
+ {
+ QMFObject obj = this.createQMFObject(sClass, decoder,
+ hasProperties, hasStatistics, true);
+ if (key.getPackageName().equals("org.apache.qpid.broker")
+ && key.getClassName().equals("agent") && hasProperties)
+ {
+ broker.updateAgent(obj);
+ }
+ synchronized (lockObject)
+ {
+ if (syncSequenceList.contains(sequence))
+ {
+ if (!obj.isDeleted() && this.selectMatch(obj))
+ {
+ getResult.add(obj);
+ }
+ }
+ }
+ if (console != null)
+ {
+ if (hasProperties)
+ {
+ console.objectProperties(broker, obj);
+ }
+ if (hasStatistics)
+ {
+ console.objectStatistics(broker, obj);
+ }
+ }
+ }
+ }
+
+ public void handleEventIndicator(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ if (console != null)
+ {
+ QMFEvent newEvent = new QMFEvent(this, decoder);
+ console.eventRecieved(broker, newEvent);
+ }
+ }
+
+ public void handleHeartbeatIndicator(Broker broker, Decoder decoder,
+ long sequence, Message msg)
+ {
+ if (console != null)
+ {
+ long brokerBank = 1;
+ long agentBank = 0;
+ try
+ {
+ // FIXME HOW DO WE GET THE ROUTING KEY
+ // String routingKey = msg.DeliveryProperties.getRoutingKey();
+ String routingKey = null;
+ if (routingKey != null)
+ {
+ agentBank = Agent.getBrokerBank(routingKey);
+ brokerBank = Agent.getBrokerBank(routingKey);
+ }
+ } catch (Throwable e)
+ {
+ log.warn("Internal QPID error", e);
+ }
+ String agentKey = Agent.AgentKey(agentBank, brokerBank);
+ long timestamp = decoder.readUint64();
+ if (broker.Agents.containsKey(agentKey))
+ {
+ Agent agent = broker.Agents.get(agentKey);
+ console.hearbeatRecieved(agent, timestamp);
+ }
+ }
+ }
+
+ public void handleMethodResponse(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ long code = decoder.readUint32();
+ String text = decoder.readStr16();
+ java.util.HashMap<String, Object> outArgs = new java.util.HashMap<String, Object>();
+ Object obj = sequenceManager.release(sequence);
+ if (obj == null)
+ {
+ return;
+ }
+ Object[] pair = (Object[]) obj;
+ if (code == 0)
+ {
+ for (SchemaArgument arg : ((SchemaMethod) pair[0]).Arguments)
+ {
+ if (arg.isOutput())
+ {
+ outArgs.put(arg.getName(), this.decodeValue(decoder, arg
+ .getType()));
+ }
+ }
+ }
+ MethodResult result = new MethodResult(code, text, outArgs);
+ if ((Boolean) pair[1])
+ {
+ this.syncResult = result;
+ broker.setSyncInFlight(false);
+ }
+ if (console != null)
+ {
+ console.methodResponse(broker, sequence, result);
+ }
+ }
+
+ // Callback Methods
+ public void handleNewAgent(Agent agent)
+ {
+ if (console != null)
+ {
+ console.newAgent(agent);
+ }
+ }
+
+ public void handlePackageIndicator(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ String packageName = decoder.readStr8();
+ boolean notify = false;
+ if (!packages.containsKey(packageName))
+ {
+ synchronized (lockObject)
+ {
+ packages.put(packageName,
+ new java.util.HashMap<String, SchemaClass>());
+ notify = true;
+ }
+ }
+ if (notify && console != null)
+ {
+ console.newPackage(packageName);
+ }
+ broker.incrementOutstanding();
+ long seq = sequenceManager.reserve(Session.CONTEXT_STARTUP);
+ Encoder enc = broker.createEncoder('Q', seq);
+ enc.writeStr8(packageName);
+ broker.send(enc);
+ }
+
+ public void handleSchemaResponse(Broker broker, Decoder decoder,
+ long sequence)
+ {
+ short kind = decoder.readUint8();
+ ClassKey classKey = new ClassKey(decoder);
+ SchemaClass sClass = new SchemaClass(kind, classKey, decoder, this);
+ synchronized (lockObject)
+ {
+ java.util.HashMap<String, SchemaClass> classMappings = packages
+ .get(sClass.getPackageName());
+ classMappings.remove(sClass.getClassKeyString());
+ classMappings.put(sClass.getClassKeyString(), sClass);
+ log.debug(classKey.toString());
+ }
+ sequenceManager.release(sequence);
+ broker.decrementOutstanding();
+ if (console != null)
+ {
+ this.console.newClass(kind, classKey);
+ }
+ }
+
+ public MethodResult invokeMethod(QMFObject obj, String name,
+ List<Object> args, boolean synchronous, int timeToLive)
+ {
+ Broker aBroker = this.getBroker(obj.brokerBank());
+ long seq = this.sendMethodRequest(obj, aBroker, name, args,
+ synchronous, timeToLive);
+ if (seq != 0)
+ {
+ if (!synchronous)
+ {
+ return null;
+ }
+ try
+ {
+ aBroker.waitForSync(timeToLive);
+ } catch (Throwable e)
+ {
+ sequenceManager.release(seq);
+ throw new ConsoleException(e);
+ }
+ // FIXME missing error logic in the broker
+ return (MethodResult) syncResult;
+ }
+ return null;
+ }
+
+ public QMFObject makeObject(ClassKey key)
+ {
+ SchemaClass sClass = this.getSchema(key);
+ if (sClass == null)
+ {
+ throw new ConsoleException("No schema found for class "
+ + key.toString());
+ }
+ return this.createQMFObject(sClass, true, true, false);
+ }
+
+ public QMFObject makeObject(String keyString)
+ {
+ return this.makeObject(new ClassKey(keyString));
+ }
+
+ public void removeBroker(Broker broker)
+ {
+ if (brokers.contains(broker))
+ {
+ brokers.remove(broker);
+ }
+ broker.shutdown();
+ }
+
+ public boolean selectMatch(QMFObject obj)
+ {
+ return true;
+ }
+
+ protected long sendMethodRequest(QMFObject obj, Broker aBroker,
+ String name, List<Object> args, boolean synchronous, int timeToLive)
+ {
+ SchemaMethod method = obj.getSchema().getMethod(name);
+ if (args == null)
+ {
+ args = new ArrayList<Object>();
+ }
+ long seq = 0;
+ if (method != null)
+ {
+ Object[] pair =
+ { method, synchronous };
+ seq = sequenceManager.reserve(pair);
+ Encoder enc = aBroker.createEncoder('M', seq);
+ obj.getObjectID().encode(enc);
+ obj.getSchema().getKey().encode(enc);
+ enc.writeStr8(name);
+ if (args.size() < method.getInputArgCount())
+ {
+ throw new ConsoleException(String.format(
+ "Incorrect number of arguments: expected %s, got %s",
+ method.getInputArgCount(), args.size()));
+ }
+ int argIndex = 0;
+ for (SchemaArgument arg : method.Arguments)
+ {
+ if (arg.isInput())
+ {
+ this.encodeValue(enc, arg.getType(), args.get(argIndex));
+ argIndex += 1;
+ }
+ }
+ Message msg = aBroker.createMessage(enc);
+ if (synchronous)
+ {
+ aBroker.setSyncInFlight(true);
+ }
+ aBroker.send(msg, obj.routingKey(), timeToLive);
+ }
+ return seq;
+ }
+
+ protected void waitForStable()
+ {
+ for (Broker broker : brokers)
+ {
+ broker.waitForStable();
+ }
+ }
+}
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/Util.java b/java/management/console/src/main/java/org/apache/qpid/console/Util.java
new file mode 100644
index 0000000000..a9e4d68601
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/Util.java
@@ -0,0 +1,184 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.UUID;
+
+public class Util
+{
+ private static HashMap<Class, Short> ENCODINGS = new HashMap<Class, Short>();
+ static
+ {
+ ENCODINGS.put(String.class, (short) 7);
+ ENCODINGS.put(Short.class, (short) 1);
+ ENCODINGS.put(Float.class, (short) 13);
+ ENCODINGS.put(QMFObject.class, (short) 20);
+ ENCODINGS.put(Integer.class, (short) 17);
+ ENCODINGS.put(Long.class, (short) 18);
+ ENCODINGS.put(ArrayList.class, (short) 21);
+ }
+
+ public static String accessName(int type)
+ {
+ switch (type)
+ {
+ // case 0: return "UNKNOWN" ;
+ case 1:
+ return "RC";
+ case 2:
+ return "RW";
+ case 3:
+ return "RO";
+ }
+ throw new ConsoleException(String.format("Invalid Access Code: %s",
+ type));
+ }
+
+ public static String byteString(byte[] bytes)
+ {
+ return new String(bytes, Charset.forName("UTF-8"));
+ }
+
+ public static Object defaultValue(short type)
+ {
+ switch (type)
+ {
+ // case 0: return "UNKNOWN" ;
+ case 1:
+ return 0;
+ case 2:
+ return 0;
+ case 3:
+ return 0l;
+ case 4:
+ return 0l;
+ case 5:
+ return false;
+ case 6:
+ return "";
+ case 7:
+ return "";
+ case 8:
+ return 0l;
+ case 9:
+ return 0l;
+ case 10:
+ return new ObjectID();
+ case 11:
+ return false;
+ case 12:
+ return 0f;
+ case 13:
+ return 0d;
+ case 14:
+ return new UUID(0, 0);
+ case 15:
+ return new HashMap<String, Object>();
+ case 16:
+ return 0;
+ case 17:
+ return 0;
+ case 18:
+ return 0l;
+ case 19:
+ return 0l;
+ case 20:
+ return null;
+ case 21:
+ return new java.util.ArrayList<Object>();
+ case 22:
+ return new java.util.ArrayList<Object>();
+ }
+ throw new ConsoleException(String.format("Invalid Type Code: %s", type));
+ }
+
+ public static short qmfType(Object obj)
+ {
+ if (ENCODINGS.containsKey(obj.getClass()))
+ {
+ return ENCODINGS.get(obj.getClass());
+ } else
+ {
+ throw new ConsoleException(String.format("Unkown Type of %s", obj
+ .getClass()));
+ }
+ }
+
+ public static String typeName(short type)
+ {
+ switch (type)
+ {
+ // case 0: return "UNKNOWN" ;
+ case 1:
+ return "uint8";
+ case 2:
+ return "uint16";
+ case 3:
+ return "uint32";
+ case 4:
+ return "uint64";
+ case 5:
+ return "bool";
+ case 6:
+ return "short-string";
+ case 7:
+ return "long-string";
+ case 8:
+ return "abs-time";
+ case 9:
+ return "delta-time";
+ case 10:
+ return "reference";
+ case 11:
+ return "boolean";
+ case 12:
+ return "float";
+ case 13:
+ return "double";
+ case 14:
+ return "uuid";
+ case 15:
+ return "field-table";
+ case 16:
+ return "int8";
+ case 17:
+ return "int16";
+ case 18:
+ return "int32";
+ case 19:
+ return "int64";
+ case 20:
+ return "object";
+ case 21:
+ return "list";
+ case 22:
+ return "array";
+ }
+ throw new ConsoleException(String.format("Invalid Type Code: %s", type));
+ }
+
+ protected Util()
+ {
+ }
+} \ No newline at end of file
diff --git a/java/management/console/src/main/java/org/apache/qpid/console/XMLUtil.java b/java/management/console/src/main/java/org/apache/qpid/console/XMLUtil.java
new file mode 100644
index 0000000000..dcbcb5b6b6
--- /dev/null
+++ b/java/management/console/src/main/java/org/apache/qpid/console/XMLUtil.java
@@ -0,0 +1,155 @@
+package org.apache.qpid.console;
+/*
+ *
+ * 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.
+ *
+ */
+
+
+public class XMLUtil
+{
+ public static String commonAttributes(SchemaVariable var)
+ {
+ String returnString = "";
+ if (var.getDescription() != null)
+ {
+ returnString = returnString
+ + String.format(" desc='%s'", var.getDescription());
+ }
+ if (var.getRefPackage() != null)
+ {
+ returnString = returnString
+ + String.format(" refPackage='%s'", var.getRefPackage());
+ }
+ if (var.getRefClass() != null)
+ {
+ returnString = returnString
+ + String.format(" refClass='%s'", var.getRefClass());
+ }
+ if (var.getUnit() != null)
+ {
+ returnString = returnString
+ + String.format(" unit='%s'", var.getUnit());
+ }
+ if (var.getMin() != null)
+ {
+ returnString = returnString
+ + String.format(" min='%s'", var.getMin());
+ }
+ if (var.getMax() != null)
+ {
+ returnString = returnString
+ + String.format(" max='%s'", var.getMax());
+ }
+ if (var.getMaxLength() != null)
+ {
+ returnString = returnString
+ + String.format(" maxLength='%s'", var.getMaxLength());
+ }
+ return returnString;
+ }
+
+ public static String schemaXML(Session sess, String packageName)
+ {
+ String returnValue = String.format("<schema package='%s'>\n",
+ packageName);
+ for (ClassKey key : sess.getClasses(packageName))
+ {
+ SchemaClass schema = sess.getSchema(key);
+ if (schema.getKind() == 1)
+ {
+ if (schema.getSuperType() == null)
+ {
+ returnValue += String.format(
+ "\t<class name='%s' hash='%s'>\n", key
+ .getClassName(), key.getHashString());
+ } else
+ {
+ returnValue += String.format(
+ "\t<class name='%s' hash='%s' extends='%s'>\n", key
+ .getClassName(), key.getHashString(),
+ schema.getSuperType().getKeyString());
+ }
+ for (SchemaProperty prop : schema.getProperties())
+ {
+ Object[] attributes = new Object[5];
+ attributes[0] = prop.getName();
+ attributes[1] = Util.typeName(prop.getType());
+ attributes[2] = Util.accessName(prop.getAccess());
+ attributes[3] = prop.getOptional() ? "True" : "False ";
+ attributes[4] = XMLUtil.commonAttributes(prop);
+ returnValue += String
+ .format(
+ "\t\t<property name='%s' type='%s' access='%s' optional='%s'%s/>\n",
+ attributes);
+ }
+ for (SchemaMethod meth : schema.getMethods())
+ {
+ returnValue += String.format("\t\t<method name='%s'/>\n",
+ meth.getName());
+ for (SchemaArgument arg : meth.Arguments)
+ {
+ Object[] attributes = new Object[4];
+ attributes[0] = arg.getName();
+ attributes[1] = arg.getDirection();
+ attributes[2] = Util.typeName(arg.getType());
+ attributes[3] = XMLUtil.commonAttributes(arg);
+ returnValue += String
+ .format(
+ "\t\t\t<arg name='%s' dir='%s' type='%s'%s/>\n",
+ attributes);
+ }
+ returnValue += String.format("\t\t</method>\n");
+ }
+ returnValue += String.format("\t</class>\n");
+ } else
+ {
+ returnValue += String.format("\t<event name='%s' hash='%s'>\n",
+ key.getClassName(), key.getHashString());
+ for (SchemaArgument arg : schema.getArguments())
+ {
+ Object[] attributes = new Object[4];
+ attributes[0] = arg.getName();
+ attributes[1] = Util.typeName(arg.getType());
+ attributes[2] = XMLUtil.commonAttributes(arg);
+ returnValue += String.format(
+ "\t\t\t<arg name='%s' type='%s'%s/>\n", attributes);
+ }
+ returnValue += String.format("\t</event>\n");
+ }
+ }
+ returnValue += String.format("</schema>\n");
+ return returnValue;
+ }
+
+ public static String schemaXML(Session sess, String[] packageNames)
+ {
+ String returnValue = "<schemas>\n";
+ for (String pack : packageNames)
+ {
+ returnValue += XMLUtil.schemaXML(sess, pack);
+ returnValue += "\n";
+ }
+ returnValue += "</schemas>\n";
+ return returnValue;
+ }
+
+ protected XMLUtil()
+ {
+ }
+}
diff --git a/java/management/console/src/test/java/org/apache/qpid/console/ClassKeyTest.java b/java/management/console/src/test/java/org/apache/qpid/console/ClassKeyTest.java
new file mode 100644
index 0000000000..dc16aaac5b
--- /dev/null
+++ b/java/management/console/src/test/java/org/apache/qpid/console/ClassKeyTest.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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 org.apache.qpid.console;
+
+import junit.framework.TestCase;
+
+public class ClassKeyTest extends TestCase
+{
+ public void testCreation()
+ {
+ ClassKey key = new ClassKey(
+ "some.package:Class(00000001-00000002-00000003-00000004)");
+ assertEquals("some.package", key.getPackageName());
+ assertEquals("Class", key.getClassName());
+ assertEquals("00000001-00000002-00000003-00000004", key.getHashString());
+ assertEquals(1, key.getHash()[0]);
+ assertEquals(2, key.getHash()[1]);
+ assertEquals(3, key.getHash()[2]);
+ assertEquals(4, key.getHash()[3]);
+ }
+}
diff --git a/java/management/eclipse-plugin/META-INF/MANIFEST.MF b/java/management/eclipse-plugin/META-INF/MANIFEST.MF
index 0df308dff1..124fe1e767 100644
--- a/java/management/eclipse-plugin/META-INF/MANIFEST.MF
+++ b/java/management/eclipse-plugin/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-ManifestVersion: 2
Bundle-Name: Qpid JMX Management Console Plug-in
Bundle-SymbolicName: org.apache.qpid.management.ui; singleton:=true
-Bundle-Version: 0.13.0
+Bundle-Version: 0.9.0
Bundle-Activator: org.apache.qpid.management.ui.Activator
Bundle-Vendor: Apache Software Foundation
Bundle-Localization: plugin
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
index 4a59176374..20cfec3758 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -47,7 +47,7 @@ public abstract class ApplicationRegistry
//max supported broker management interface supported by this release of the management console
public static final int SUPPORTED_QPID_JMX_API_MAJOR_VERSION = 2;
- public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 3;
+ public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 0;
public static final String DATA_DIR = System.getProperty("user.home") + File.separator + ".qpidmc";
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
index a8fb864cf6..3561e16098 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
@@ -21,7 +21,6 @@
package org.apache.qpid.management.ui.jmx;
import java.util.HashMap;
-import java.util.Map;
import javax.management.ObjectName;
@@ -32,36 +31,14 @@ public class JMXManagedObject extends ManagedBean
{
private ObjectName _objName;
+ @SuppressWarnings("unchecked")
public JMXManagedObject(ObjectName objName)
{
super();
this._objName = objName;
setUniqueName(_objName.toString());
- setDomain(_objName.getDomain());
-
- HashMap<String,String> props = new HashMap<String,String>(_objName.getKeyPropertyList());
-
- for(Map.Entry<String,String> entry : props.entrySet())
- {
- String value = entry.getValue();
-
- if(value != null)
- {
- try
- {
- //if the name is quoted in the ObjectName, unquote it
- value = ObjectName.unquote(value);
- entry.setValue(value);
- }
- catch(IllegalArgumentException e)
- {
- //ignore, this just means the name is not quoted
- //and can be left unchanged
- }
- }
- }
-
- super.setProperties(props);
+ setDomain(_objName.getDomain());
+ super.setProperties(new HashMap(_objName.getKeyPropertyList()));
}
public ObjectName getObjectName()
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
index 35cc9f6e27..e42b3c53b6 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
@@ -61,7 +61,7 @@ public class NotificationObject
{
if (_source instanceof ObjectName)
{
- return unquote(((ObjectName)_source).getKeyProperty("name"));
+ return ((ObjectName)_source).getKeyProperty("name");
}
return null;
@@ -71,31 +71,12 @@ public class NotificationObject
{
if (_source instanceof ObjectName)
{
- return unquote(((ObjectName)_source).getKeyProperty(VIRTUAL_HOST));
+ return ((ObjectName)_source).getKeyProperty(VIRTUAL_HOST);
}
return null;
}
-
- private String unquote(String value)
- {
- if(value != null)
- {
- try
- {
- //if the value is quoted in the ObjectName, unquote it
- value = ObjectName.unquote(value);
- }
- catch(IllegalArgumentException e)
- {
- //ignore, this just means the value is not quoted
- //and can be left unchanged
- }
- }
-
- return value;
- }
-
+
public String getMessage()
{
return _message;
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
index 527fc67be3..1fef89d6b5 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
@@ -131,8 +131,6 @@ public class MBeanTabFolderFactory
}
break;
case VHOST_MANAGER:
- createAttributesTab(tabFolder, mbean);
-
tab = new TabItem(tabFolder, SWT.NONE);
tab.setText("Operations");
controller = new VHostTabControl(tabFolder, mbean, mbsc);
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/LegacySupportingUserManagement.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/LegacySupportingUserManagement.java
deleted file mode 100644
index 0fc94a5972..0000000000
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/LegacySupportingUserManagement.java
+++ /dev/null
@@ -1,132 +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.
- *
- */
-package org.apache.qpid.management.ui.views.users;
-
-import javax.management.MBeanOperationInfo;
-
-import org.apache.qpid.management.common.mbeans.UserManagement;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
-import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter;
-
-/**
- * UserManagement interface extension to provide the method signatures
- * for old UserManagement methods no longer supported by the broker.
- *
- * This interface is used only for the creation of MBean proxy objects
- * within the management console, for backwards compatibility with
- * functionality in older broker versions.
- */
-public interface LegacySupportingUserManagement extends UserManagement
-{
- /**
- * set password for user.
- *
- * Since Qpid JMX API 1.2 this operation expects plain text passwords to be provided. Prior to this, MD5 hashed passwords were supplied.
- *
- * @deprecated since Qpid JMX API 1.7
- *
- * @param username The username for which the password is to be set
- * @param password The password for the user
- *
- * @return The result of the operation
- */
- @Deprecated
- @MBeanOperation(name = "setPassword", description = "Set password for user.",
- impact = MBeanOperationInfo.ACTION)
- boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username,
- //NOTE: parameter name was changed to 'passwd' in Qpid JMX API 1.7 to protect against older, incompatible management clients
- @MBeanOperationParameter(name = "passwd", description = "Password")char[] password);
-
- /**
- * Set rights for users with given details.
- * Since Qpid JMX API 2.3 all invocations will cause an exception to be thrown
- * as access rights can no longer be maintain via this interface.
- *
- * @deprecated since Qpid JMX API 2.3 / 1.12
- *
- * @param username The username to create
- * @param read The set of permission to give the new user
- * @param write The set of permission to give the new user
- * @param admin The set of permission to give the new user
- *
- * @return The result of the operation
- */
- @Deprecated
- @MBeanOperation(name = "setRights", description = "Set access rights for user.",
- impact = MBeanOperationInfo.ACTION)
- boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username,
- @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
- @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
- @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
-
- /**
- * Create users with given details.
- * Since Qpid JMX API 2.3 if the user passes true for parameters read, write, or admin, a
- * exception will be thrown as access rights can no longer be maintain via this interface.
- *
- * Since Qpid JMX API 1.2 this operation expects plain text passwords to be provided. Prior to this, MD5 hashed passwords were supplied.
- *
- * @deprecated since Qpid JMX API 1.7
- *
- * @param username The username to create
- * @param password The password for the user
- * @param read The set of permission to give the new user
- * @param write The set of permission to give the new user
- * @param admin The set of permission to give the new user
- *
- * @return true if the user was created successfully, or false otherwise
- */
- @Deprecated
- @MBeanOperation(name = "createUser", description = "Create new user from system.",
- impact = MBeanOperationInfo.ACTION)
- boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
- //NOTE: parameter name was changed to 'passwd' in Qpid JMX API 1.7 to protect against older, incompatible management clients
- @MBeanOperationParameter(name = "passwd", description = "Password")char[] password,
- @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
- @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
- @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
-
- /**
- * Create users with given details.
- * Since Qpid JMX API 2.3 if the user passes true for parameters read, write, or admin, a
- * exception will be thrown as access rights can no longer be maintain via this interface.
- *
- * @deprecated since Qpid JMX API 2.3 / 1.12
- * @since Qpid JMX API 1.7
- *
- * @param username The username to create
- * @param password The password for the user
- * @param read The set of permission to give the new user
- * @param write The set of permission to give the new user
- * @param admin The set of permission to give the new user
- *
- * @return true if the user was created successfully, or false otherwise
- */
- @Deprecated
- @MBeanOperation(name = "createUser", description = "Create a new user.",
- impact = MBeanOperationInfo.ACTION)
- boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
- @MBeanOperationParameter(name = "password", description = "Password")String password,
- @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
- @MBeanOperationParameter(name = "readAndWrite", description = "Administration write")boolean write,
- @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
-
-}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
index 2c540bf982..fdcc25d337 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
@@ -37,6 +37,7 @@ import javax.management.openmbean.TabularDataSupport;
import org.apache.qpid.management.ui.ApiVersion;
import org.apache.qpid.management.ui.ApplicationRegistry;
import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.common.mbeans.UserManagement;
import org.apache.qpid.management.ui.jmx.JMXManagedObject;
import org.apache.qpid.management.ui.jmx.MBeanUtility;
import org.apache.qpid.management.ui.views.TabControl;
@@ -82,7 +83,7 @@ public class UserManagementTabControl extends TabControl
private TableViewer _tableViewer = null;
private TabularDataSupport _userDetails = null;
- private LegacySupportingUserManagement _ummb;
+ private UserManagement _ummb;
private ApiVersion _ApiVersion;
public UserManagementTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
@@ -90,9 +91,9 @@ public class UserManagementTabControl extends TabControl
super(tabFolder);
_mbean = mbean;
_ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
- _ummb = (LegacySupportingUserManagement)
+ _ummb = (UserManagement)
MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
- LegacySupportingUserManagement.class, false);
+ UserManagement.class, false);
_toolkit = new FormToolkit(_tabFolder.getDisplay());
_form = _toolkit.createScrolledForm(_tabFolder);
_form.getBody().setLayout(new GridLayout());
@@ -170,13 +171,6 @@ public class UserManagementTabControl extends TabControl
String[] titles = { "Username", "JMX Management Rights" };
int[] bounds = { 310, 200 };
- if(!settingManagementRightsSupported())
- {
- //Since Qpid JMX API 2.3 / 1.12 only Username is used
- titles = new String[]{ "Username"};
- bounds = new int[]{ 310 };
- }
-
for (int i = 0; i < titles.length; i++)
{
final int index = i;
@@ -220,16 +214,7 @@ public class UserManagementTabControl extends TabControl
Composite buttonsComposite = _toolkit.createComposite(tableComposite);
gridData = new GridData(SWT.FILL, SWT.TOP, false, false);
- if(!settingManagementRightsSupported())
- {
- //The 'Set Rights' button is not shown from Qpid JMX API 2.3 / 1.12
- //onward, provide less space
- gridData.heightHint = 135;
- }
- else
- {
- gridData.heightHint = 165;
- }
+ gridData.heightHint = 165;
buttonsComposite.setLayoutData(gridData);
buttonsComposite.setLayout(new GridLayout());
@@ -307,14 +292,14 @@ public class UserManagementTabControl extends TabControl
if (returnValue == InputDialog.OK)
{
- char[] passwordArray = id.getValue().toCharArray();
+ char[] password = id.getValue().toCharArray();
// Qpid JMX API 1.1 and below expects the password to be sent as a hashed value.
if (_ApiVersion.lessThanOrEqualTo(1,1))
{
try
{
- passwordArray = ViewUtility.getHash(id.getValue());
+ password = ViewUtility.getHash(id.getValue());
}
catch (Exception hashException)
{
@@ -327,18 +312,7 @@ public class UserManagementTabControl extends TabControl
try
{
- boolean result;
-
- //For Qpid JMX API >=1.7 use String based method instead of older char[] based method.
- if(_ApiVersion.greaterThanOrEqualTo(1, 7))
- {
- result = _ummb.setPassword(user, id.getValue());
- }
- else
- {
- result = _ummb.setPassword(user, passwordArray);
- }
-
+ boolean result = _ummb.setPassword(user, password);
ViewUtility.operationResultFeedback(result, "Updated user password", "Failed to update user password");
}
catch(Exception e2)
@@ -350,34 +324,25 @@ public class UserManagementTabControl extends TabControl
}
}
});
-
- final Button setRightsButton;
- if(!settingManagementRightsSupported())
- {
- //The 'Set Rights' button is not used from Qpid JMX API 2.3 / 1.12 onward
- setRightsButton = null;
- }
- else
+
+ final Button setRightsButton = _toolkit.createButton(buttonsComposite, "Set Rights ...", SWT.PUSH);
+ gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
+ gridData.widthHint = 125;
+ setRightsButton.setLayoutData(gridData);
+ setRightsButton.setEnabled(false);
+ setRightsButton.addSelectionListener(new SelectionAdapter()
{
- setRightsButton = _toolkit.createButton(buttonsComposite, "Set Rights ...", SWT.PUSH);
- gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
- gridData.widthHint = 125;
- setRightsButton.setLayoutData(gridData);
- setRightsButton.setEnabled(false);
- setRightsButton.addSelectionListener(new SelectionAdapter()
+ public void widgetSelected(SelectionEvent e)
{
- public void widgetSelected(SelectionEvent e)
- {
- int selectionIndex = _table.getSelectionIndex();
+ int selectionIndex = _table.getSelectionIndex();
- if (selectionIndex != -1)
- {
- setRights(setRightsButton.getShell());
- }
+ if (selectionIndex != -1)
+ {
+ setRights(setRightsButton.getShell());
}
- });
- }
-
+ }
+ });
+
_tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent evt)
{
@@ -386,20 +351,14 @@ public class UserManagementTabControl extends TabControl
if (selectionIndex == -1)
{
deleteUsersButton.setEnabled(false);
+ setRightsButton.setEnabled(false);
setPasswordButton.setEnabled(false);
- if(setRightsButton != null)
- {
- setRightsButton.setEnabled(false);
- }
return;
}
else
{
deleteUsersButton.setEnabled(true);
- if(setRightsButton != null)
- {
- setRightsButton.setEnabled(true);
- }
+ setRightsButton.setEnabled(true);
}
if (_table.getSelectionCount() > 1)
@@ -427,17 +386,11 @@ public class UserManagementTabControl extends TabControl
//this only reloaded the JMX rights file before Qpid JMX API 1.2
_toolkit.createLabel(miscGroup, " Loads the current management rights file from disk");
}
- else if(settingManagementRightsSupported())
- {
- //from Qpid JMX API 1.2 to 2.3 / 1.12 it also reloads the password file
- _toolkit.createLabel(miscGroup, " Loads the current password and management rights files from disk");
- }
else
{
- //since Qpid JMX API 2.3 / 1.12 it only reloads the password file
- _toolkit.createLabel(miscGroup, " Loads the current password data");
+ //since Qpid JMX API 1.2 it also reloads the password file
+ _toolkit.createLabel(miscGroup, " Loads the current password and management rights files from disk");
}
-
reloadUserDetails.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
@@ -500,7 +453,7 @@ public class UserManagementTabControl extends TabControl
{
case 0 : // username column
return (String) ((CompositeData) element).get(USERNAME);
- case 1 : // rights column (used for API < 2.3 / 1.12)
+ case 1 : // rights column
return classifyUserRights((CompositeData) element);
default :
return "-";
@@ -557,11 +510,11 @@ public class UserManagementTabControl extends TabControl
int comparison = 0;
switch(column)
{
- case 0: //username column
+ case 0:
comparison = String.valueOf(user1.get(USERNAME)).compareTo(
String.valueOf(user2.get(USERNAME)));
break;
- case 1: // rights column (used for API < 2.3 / 1.12)
+ case 1:
comparison = classifyUserRights(user1).compareTo(classifyUserRights(user2));
break;
default:
@@ -602,12 +555,7 @@ public class UserManagementTabControl extends TabControl
private void setRights(final Shell parent)
{
- if(!settingManagementRightsSupported())
- {
- throw new UnsupportedOperationException("Setting management rights" +
- " is not supported using this version of the broker management API: " + (_ApiVersion));
- }
-
+
int selectionIndex = _table.getSelectionIndex();
if (selectionIndex == -1)
@@ -751,13 +699,6 @@ public class UserManagementTabControl extends TabControl
shell.open();
}
-
- protected boolean settingManagementRightsSupported()
- {
- //setting management access rights was supported until Qpid JMX API 1.12 / 2.3
- return _ApiVersion.lessThan(1,12) ||
- (_ApiVersion.greaterThanOrEqualTo(2, 0) && _ApiVersion.lessThan(2,3));
- }
private void addUser(final Shell parent)
{
@@ -765,8 +706,7 @@ public class UserManagementTabControl extends TabControl
Composite usernameComposite = _toolkit.createComposite(shell, SWT.NONE);
usernameComposite.setBackground(shell.getBackground());
- GridData usernameCompGridData = new GridData(SWT.FILL, SWT.TOP, true, false);
- usernameComposite.setLayoutData(usernameCompGridData);
+ usernameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
usernameComposite.setLayout(new GridLayout(2,false));
_toolkit.createLabel(usernameComposite,"Username:").setBackground(shell.getBackground());
@@ -775,45 +715,28 @@ public class UserManagementTabControl extends TabControl
Composite passwordComposite = _toolkit.createComposite(shell, SWT.NONE);
passwordComposite.setBackground(shell.getBackground());
- GridData passwordCompGridData = new GridData(SWT.FILL, SWT.TOP, true, false);
- passwordComposite.setLayoutData(passwordCompGridData);
+ passwordComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
passwordComposite.setLayout(new GridLayout(2,false));
_toolkit.createLabel(passwordComposite,"Password:").setBackground(shell.getBackground());
final Text passwordText = new Text(passwordComposite, SWT.BORDER | SWT.PASSWORD);
passwordText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Group buttonGroup = new Group(shell, SWT.NONE);
+ buttonGroup.setText("JMX Management Rights");
+ buttonGroup.setBackground(shell.getBackground());
+ buttonGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ buttonGroup.setLayout(new GridLayout(4,false));
- final Button readButton;
- final Button writeButton;
- final Button adminButton;
- if(settingManagementRightsSupported())
- {
- Group buttonGroup = new Group(shell, SWT.NONE);
- buttonGroup.setText("JMX Management Rights");
- buttonGroup.setBackground(shell.getBackground());
- buttonGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
- buttonGroup.setLayout(new GridLayout(4,false));
-
- final Button noneButton = new Button(buttonGroup, SWT.RADIO);
- noneButton.setText("No Access");
- noneButton.setSelection(true);
- readButton = new Button(buttonGroup, SWT.RADIO);
- readButton.setText("Read Only");
- writeButton = new Button(buttonGroup, SWT.RADIO);
- writeButton.setText("Read + Write");
- adminButton = new Button(buttonGroup, SWT.RADIO);
- adminButton.setText("Admin");
- }
- else
- {
- readButton = null;
- writeButton = null;
- adminButton = null;
- //The lack of rights settings will cause the dialog to,
- //shrink so add width hints to the other components
- passwordCompGridData.widthHint = 350;
- usernameCompGridData.widthHint = 350;
- }
+ final Button noneButton = new Button(buttonGroup, SWT.RADIO);
+ noneButton.setText("No Access");
+ noneButton.setSelection(true);
+ final Button readButton = new Button(buttonGroup, SWT.RADIO);
+ readButton.setText("Read Only");
+ final Button writeButton = new Button(buttonGroup, SWT.RADIO);
+ writeButton.setText("Read + Write");
+ final Button adminButton = new Button(buttonGroup, SWT.RADIO);
+ adminButton.setText("Admin");
Composite okCancelButtonsComp = _toolkit.createComposite(shell);
okCancelButtonsComp.setBackground(shell.getBackground());
@@ -861,36 +784,22 @@ public class UserManagementTabControl extends TabControl
return;
}
}
-
- //read the access rights selections if required
- boolean read = false;
- boolean write = false;
- boolean admin = false;
- if(settingManagementRightsSupported())
- {
- read = readButton.getSelection();
- write = writeButton.getSelection();
- admin = adminButton.getSelection();
- }
+
+ boolean read = readButton.getSelection();
+ boolean write = writeButton.getSelection();
+ boolean admin = adminButton.getSelection();
shell.dispose();
try
{
boolean result = false;
-
- if (!settingManagementRightsSupported())
- {
- // If we have Qpid JMX API 2.3 / 1.12 or above, use newer createUser method without rights parameters.
- result = _ummb.createUser(username, password);
- }
- else if (_ApiVersion.greaterThanOrEqualTo(1,7))
+ // If we have Qpid JMX API 1.7 or above, use newer createUser method with String based password.
+ if (_ApiVersion.greaterThanOrEqualTo(1,7))
{
- // If we have Qpid JMX API 1.7 or above, use newer createUser method with String based password.
result = _ummb.createUser(username, password, read, write, admin);
}
else
{
- // Else we have Qpid JMX API 1.6 or below, use older createUser method with char[] based password.
result = _ummb.createUser(username, passwordChars, read, write, admin);
}
diff --git a/java/management/tools/qpid-cli/Guide.txt b/java/management/tools/qpid-cli/Guide.txt
new file mode 100644
index 0000000000..db841ebaa1
--- /dev/null
+++ b/java/management/tools/qpid-cli/Guide.txt
@@ -0,0 +1,143 @@
+
+ * How to connect with the Broker *
+ ---------------------------------
+
+Before you come in to this state you have to build the source or you
+can get the binary and extract then set the QPID_CLI environment
+variable to the main directory of the source or binary,then only you
+are in a position to start working with management console. First
+check whether the broker is up and running. In order to simply connect
+with the broker you can run the qpid-cli script which required
+arguments.
+
+${QPID_CLI}/bin/qpid-cli -h [HostName of IP of the broker ] -p [Port
+of the broker]
+
+Default values for arguments -h [localhost] -p [8999]
+
+ * One Shot mode *
+ -----------------
+
+With one shot mode you can run interactive mode commands for one time
+and disconnect with the broker.This feature is useful when you want to
+run particular command in the management console using a script which
+is running in the normal console.What you have to do is you have to
+give the command you want to run with the qpid-cli script running
+command.
+
+Ex 1: $QPID_CLI/bin/qpid-cli queue list -- This will list the queue
+objects and disconnect.
+
+Ex 2: $QPID_CLI/bin/qpid-cli queue view -n ping - This will display
+information about all the message in the queue with the name of ping
+
+Likewise you can run any command in one shot mode and get the output
+for one time.
+
+ * Report Generation Mode *
+ -------------------------
+
+If you want to generate reports you can do it by defining your
+required information using a property file. There's a sample property
+file in the parent directory and you can have a look and get an idea
+about that.You can generate reports by giving a time interval in the
+property file. In order to start the daemon mode you have to run the
+qpid-cli script with the option : -r by giving the path for your
+property file.
+
+Ex: $QPID_CLI/bin/qpid-cli -r ../report.property
+
+You should specify a property file in order to run the daemon mode and
+get information repeatedly.
+
+ * Interactive mode with number of command *
+ -------------------------------------------
+
+This is the mode you get when you run the qpid-cli script without the
+one shot mode and without the daemon mode with [-r] option.Once you
+connect with the broker it display you a prompt [qpid-admin-$], then
+you can run several commands to can perform following tasks.
+
+For all the commands object type is command and most important command
+so you can use this option value without giving the option letter by
+giving that option value at the beginning of the command.
+
+Ex: [list -o queue ] can use this command like this dropping -o option
+[queue list]
+Ex: [list -o queue -n ping] = [queue list -n ping]
+
+ * Data displaying commands *
+ ----------------------------
+
+This is the set of commands which display the information about
+broker.
+
+list :
+------
+list information about the given object type with limited
+number of attributes and you can use number of command options to get
+different useful behaviors with the list command.You can get the
+complete description about the command by running the command like
+this.[list -h].
+
+info :
+------
+list all the attributes of a given object type. This command
+works very similar way to list command. You can use -h option for help
+and get complete description of the info command.
+
+view :
+------
+view information about the content of the message in the queue
+object. In order to run this command you have to specify the object
+type at the beginning.You can give how many message informations you
+want to view from the top of the queue by using -t option.
+
+Ex : queue view -n message_queue -t 5
+[list the message info for top 5 messages in queue message_queue]
+
+viewcontent :
+-------------
+view the content of the a given message in the
+queue. You have to give the messageId as a parameter with -id option
+letters.
+
+Ex: queue viewcontent -n message_queue -id 12
+[list the content encoding and Mimetype of the message with the
+messageId for the give message which is in the queue message_queue]
+
+ * Data modification commands *
+ ------------------------------
+
+This is a set of commands which allow users to deal with messages in
+queues.Users can delete messages from a give queue and user's can move
+one message from one queue to another queue.
+
+delete :
+--------
+Using this command user can delete a give message from a given
+queue you can specify how many messages you want to delete from the
+queue from the top of the queue by using -t option.If user does not
+give how many messages to delete from the top of the queue program is
+going to delete all the messages from the queue after giving a prompt
+to confirm the deletion.
+
+Ex: queue delete -n message_queue -t 3
+[Delete top three messages in the queue message_queue ]
+
+move :
+------
+This command allow user to move number of messages from one
+queue to another queue. First you have to specify from which queue you
+want to move messages by using -n1 and -v1 option letters(-n1 queue
+name/ -v1 virtual host).Then you have to use -n2 option to give the
+target queue name and then you have to give From messageId and To
+messageId using -fmid and -tmid option letters to specify the messages
+range you want to do the move operation.
+
+Ex: queue move -n1 message_queue -n2 ping -fmid 13 -tmid 15
+[This will move messages with the messageId range of 13-15 from queue
+message_queue to queue ping.
+
+
+
diff --git a/java/management/tools/qpid-cli/LICENSE b/java/management/tools/qpid-cli/LICENSE
new file mode 100644
index 0000000000..c6432e459f
--- /dev/null
+++ b/java/management/tools/qpid-cli/LICENSE
@@ -0,0 +1,225 @@
+=========================================================================
+== 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.
+
+
+=============================================================================
+== JLine (BSD) License
+=============================================================================
+Copyright (c) 2008, Apache Software Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+
+
+
diff --git a/java/management/tools/qpid-cli/NOTICE b/java/management/tools/qpid-cli/NOTICE
new file mode 100644
index 0000000000..f1d9e54095
--- /dev/null
+++ b/java/management/tools/qpid-cli/NOTICE
@@ -0,0 +1,12 @@
+Apache Qpid
+Copyright 2006-2008 Apache Software Foundation
+This product includes software developed at
+Apache Software Foundation (http://www.apache.org/)
+
+Handling console input is provided bye the Jline library package,
+JLine is a Java library for handling console input. It is similar
+in functionality to BSD editline and GNU readline.Original software is
+available from
+
+http://jline.sourceforge.net/index.html
+
diff --git a/java/management/tools/qpid-cli/README.txt b/java/management/tools/qpid-cli/README.txt
new file mode 100644
index 0000000000..6db439aad0
--- /dev/null
+++ b/java/management/tools/qpid-cli/README.txt
@@ -0,0 +1,64 @@
+README
+n======
+
+INSTALL
+=======
+ source
+ ======
+ 1.Set the environment variable QPID_HOME to the root directory of the repository or the release.
+
+ 2.Run these command to build the source
+
+ ant compile OR run the ant build in the parent directory(main ant script)
+
+ 3.To launch the CLI run the script in bin folder with appropriate parameters.
+
+ ex:
+
+ Linux $QPID_HOME/bin/qpid-cli -h 10.8.100.122 -p 8334
+ Windows %QPID_HOME%/bin/qpid-cli.bat -h 10.8.100.122 -p 8334
+
+ -h hostname (default localhost)
+ -p broker port (default 8999)
+
+ binary
+ ======
+ 1.Set the environment variable QPID_HOME to the root directory of the repository or the release.
+
+ 2.To launch the CLI run the script in bin folder with appropriate parameters.
+
+ ex:
+
+ Linux $QPID_HOME/bin/qpid-cli -h 10.8.100.122 -p 8334
+ Windows %QPID_HOME%/bin/qpid-cli.bat -h 10.8.100.122 -p 8334
+
+ -h hostname (default localhost)
+ -p broker port (default 8999)
+
+ 3. No test cases are included in the binary version.
+
+TESTING
+=======
+
+1.Test source is located in the test directory.If you want to run the tests please start the
+Qpid java broker and run following ant targets.
+
+ ant compile-tests This compile all the test sources
+ ant test This runs all the test cases
+2.If you want to test with a remote broker please use the source release and change the constants in ConnectionConstants.java
+class.(Default values are BROKER_HOSTNAME="localhost" BROKER_PORT="8999")
+
+For more informations please visit the project home page.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java/management/tools/qpid-cli/bin/qpid-cli b/java/management/tools/qpid-cli/bin/qpid-cli
new file mode 100755
index 0000000000..0efb49dddd
--- /dev/null
+++ b/java/management/tools/qpid-cli/bin/qpid-cli
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# License to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+if [ -z "$QPID_HOME" ]; then
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
+fi
+
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-all.jar
+
+# Set other variables used by the qpid-run script before calling
+export JAVA=java \
+ JAVA_VM=-server \
+ JAVA_MEM=-Xmx1024m \
+ QPID_CLASSPATH=$QPID_LIBS
+
+. qpid-run org.apache.qpid.CommandLineInterpreter "$@"
diff --git a/java/management/tools/qpid-cli/bin/qpid-cli.bat b/java/management/tools/qpid-cli/bin/qpid-cli.bat
new file mode 100755
index 0000000000..452ddb65ee
--- /dev/null
+++ b/java/management/tools/qpid-cli/bin/qpid-cli.bat
@@ -0,0 +1,28 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+set CLASSPATH=%CLASSPATH%;%QPID_HOME%/lib/jline-0.9.94.jar
+set CLASSPATH=%CLASSPATH%;%QPID_HOME%/lib/junit-4.4.jar
+set CLASSPATH=%CLASSPATH%;%QPID_HOME%/lib/qpid-cli-1.0.jar
+set CLASSPATH=%CLASSPATH%;%QPID_HOME%/lib/qpid-management-common-M4.jar
+set CLASSPATH=%CLASSPATH%;%QPID_HOME%/management/tools/qpid-cli/main/classes/
+java -classpath %CLASSPATH% org.apache.qpid.CommandLineInterpreter %1
+
+
+
+
diff --git a/java/management/tools/qpid-cli/build.xml b/java/management/tools/qpid-cli/build.xml
new file mode 100644
index 0000000000..7026cd2fd2
--- /dev/null
+++ b/java/management/tools/qpid-cli/build.xml
@@ -0,0 +1,31 @@
+<!--
+ -
+ - 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.
+ -
+ -->
+<project name="qpid-cli">
+
+ <property name="module.depends" value="common management/common" />
+ <property name="module.test.depends" value="common client" />
+ <property name="module.src" value="src" />
+ <!-- Disable tests as per QPID-1342 -->
+ <!--property name="module.test.src" value="test" /-->
+
+ <import file="../../../module.xml"/>
+
+</project>
diff --git a/java/management/tools/qpid-cli/report.property b/java/management/tools/qpid-cli/report.property
new file mode 100644
index 0000000000..46734d52a8
--- /dev/null
+++ b/java/management/tools/qpid-cli/report.property
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+object=queue
+column=Name,MessageCount,ActiveConsumerCount,Durable
+filter.name=ping
+filter.virtualhost=test
+output=csv
+seperator=|
+interval=1
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/Command.java b/java/management/tools/qpid-cli/src/org/apache/qpid/Command.java
new file mode 100644
index 0000000000..eadc87186f
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/Command.java
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+public interface Command
+{
+ public void execute();
+
+ public void printusage();
+
+ public String optionchecker(String string);
+
+ public boolean checkoptionsetting(String string);
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/CommandExecutionEngine.java b/java/management/tools/qpid-cli/src/org/apache/qpid/CommandExecutionEngine.java
new file mode 100644
index 0000000000..69f261b4ba
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/CommandExecutionEngine.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.utils.JMXinfo;
+
+public class CommandExecutionEngine
+{
+ private static Map<String, Class<? extends Command>> _commands = new HashMap<String, Class<? extends Command>>();
+ private Command currentcommand = null;
+ private String commandname = null;
+ private JMXinfo info = null;
+
+ public CommandExecutionEngine(JMXinfo info)
+ {
+ this.info = info;
+ this.commandname = info.getCommandLineOptionParser().getcommandname();
+ }
+
+ public boolean CommandSelector() throws Exception
+ {
+ Class<? extends Command> commandClass = _commands.get(this.commandname);
+ if (commandClass != null)
+ {
+ Class<?> parameterTypes = JMXinfo.class;
+ currentcommand = (Command) commandClass.getConstructor(parameterTypes).newInstance(info);
+ }
+ else
+ {
+ usage();
+ return false;
+ }
+ return true;
+ }
+
+ public static void addCommand(String name, Class<? extends Command> newCommand)
+ {
+ _commands.put(name, newCommand);
+ }
+
+ public static Map<String, Class<? extends Command>> getCommands()
+ {
+ return _commands;
+ }
+
+ public void runcommand()
+ {
+ currentcommand.execute();
+ }
+
+ public void usage()
+ {
+ System.out.println(commandname + ":Command not found");
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/CommandLineInterpreter.java b/java/management/tools/qpid-cli/src/org/apache/qpid/CommandLineInterpreter.java
new file mode 100644
index 0000000000..d8e76172bc
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/CommandLineInterpreter.java
@@ -0,0 +1,263 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+import jline.ArgumentCompletor;
+import jline.ConsoleReader;
+import jline.SimpleCompletor;
+
+import org.apache.qpid.commands.Commanddelete;
+import org.apache.qpid.commands.Commandget;
+import org.apache.qpid.commands.Commandhelp;
+import org.apache.qpid.commands.Commandinfo;
+import org.apache.qpid.commands.Commandlist;
+import org.apache.qpid.commands.Commandmove;
+import org.apache.qpid.commands.Commandset;
+import org.apache.qpid.commands.Commandview;
+import org.apache.qpid.commands.Commandviewcontent;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXConfiguration;
+import org.apache.qpid.utils.JMXinfo;
+
+public class CommandLineInterpreter
+{
+ private static final String OBJECT_VIRTUALHOST = "virtualhost";
+ private static final String OBJECT_USERMANAGEMENT = "usermanagement";
+ private static final String OBJECT_CONNECTION = "connection";
+ private static final String OBJECT_EXCHANGE = "exchange";
+ private static final String OBJECT_QUEUE = "queue";
+ private static final String COMMAND_QUIT = "quit";
+ private static final String COMMAND_EXIT = "exit";
+
+ public static void main(String[] args)
+ {
+ Connector conn = null;
+ try
+ {
+ // Create an RMI connector client and
+ // connect it to the RMI connector server
+
+ /*
+ * checking the commandline options and parse them in to config
+ * method
+ */
+ JMXConnector jmxc = null;
+ MBeanServerConnection mbsc = null;
+ ConsoleReader reader = new ConsoleReader();
+ reader.setBellEnabled(false);
+ CommandLineOptionParser commandlineoptionparser = null;
+
+ if ((args == null) || (args.length) == 0)
+ {
+ Usage();
+ }
+ /*
+ * here special constructor is calling, when parsing options,in here
+ * first option value is starting from minus sign so this is handle
+ * by a special constructor
+ */
+ else
+ {
+ if (args[0].startsWith("-"))
+ {
+ commandlineoptionparser = new CommandLineOptionParser(args, args[0]); // if
+ // user
+ // specify
+ // any
+ // argument
+ // with
+ // the
+ // qpid-cli
+ // script
+ }
+ }
+
+ registerCommands();
+
+ /* Connecting with the broker */
+ try
+ {
+ if (commandlineoptionparser == null)
+ commandlineoptionparser = new CommandLineOptionParser(args);
+
+ JMXConfiguration config = new JMXConfiguration(commandlineoptionparser.getAlloptions());
+ conn = ConnectorFactory.getConnector(config.gethostname(), config.getport(), config.getUsername(),
+ config.getPassword());
+ jmxc = conn.getConnector();
+ mbsc = conn.getMBeanServerConnection();
+ if (config.checkoptionsetting("r", commandlineoptionparser.getAlloptions()))
+ {
+ JMXinfo info = new JMXinfo(jmxc, commandlineoptionparser, mbsc);
+ ReportGenerator reportgen = new ReportGenerator(config.optionchecker("r", commandlineoptionparser
+ .getAlloptions()), info);
+ reportgen.loadproperties();
+ reportgen.run();
+ }
+ /*
+ * This implementation is for the people who are using the
+ * interactive mode for one shot this run the user given command
+ * and exit
+ */
+ for (int i = 0; i < args.length; i++)
+ {
+ if (CommandExecutionEngine.getCommands().keySet().contains(args[i]))
+ {
+ oneshotmode(args, commandlineoptionparser, jmxc, mbsc);
+ return;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ connectionrefuse(ex);
+ return;
+ }
+ /* In this point connection has been established */
+ String line;
+ String[] command;
+
+ /* prividing GNU readline features using Jline library */
+ PrintWriter out = new PrintWriter(System.out);
+ SimpleCompletor completer = new SimpleCompletor(new String[] {
+ COMMAND_EXIT, COMMAND_QUIT, OBJECT_QUEUE, OBJECT_EXCHANGE, OBJECT_CONNECTION,
+ OBJECT_USERMANAGEMENT, OBJECT_VIRTUALHOST});
+ for (String commandName : CommandExecutionEngine.getCommands().keySet())
+ {
+ completer.addCandidateString(commandName);
+ }
+ reader.addCompletor(new ArgumentCompletor(completer));
+ while ((line = reader.readLine("qpid-admin-$ ")) != null)
+ {
+ out.flush();
+ if (removeSpaces(line).equalsIgnoreCase(COMMAND_QUIT) || removeSpaces(line).equalsIgnoreCase(COMMAND_EXIT))
+ break;
+ else if (line.length() == 0)
+ continue;
+ else
+ {
+ command = line.split("\\s+");
+ commandlineoptionparser = new CommandLineOptionParser(command);
+ JMXinfo info = new JMXinfo(jmxc, commandlineoptionparser, mbsc);
+ CommandExecutionEngine engine = new CommandExecutionEngine(info);
+ if (engine.CommandSelector())
+ engine.runcommand();
+ }
+ }
+
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ private static void registerCommands()
+ {
+ CommandExecutionEngine.addCommand(Commanddelete.COMMAND_NAME, Commanddelete.class);
+ CommandExecutionEngine.addCommand(Commandget.COMMAND_NAME, Commandget.class);
+ CommandExecutionEngine.addCommand(Commandhelp.COMMAND_NAME, Commandhelp.class);
+ CommandExecutionEngine.addCommand(Commandinfo.COMMAND_NAME, Commandinfo.class);
+ CommandExecutionEngine.addCommand(Commandlist.COMMAND_NAME, Commandlist.class);
+ CommandExecutionEngine.addCommand(Commandmove.COMMAND_NAME, Commandmove.class);
+ CommandExecutionEngine.addCommand(Commandset.COMMAND_NAME, Commandset.class);
+ CommandExecutionEngine.addCommand(Commandview.COMMAND_NAME, Commandview.class);
+ CommandExecutionEngine.addCommand(Commandviewcontent.COMMAND_NAME, Commandviewcontent.class);
+ }
+
+ private static void Usage()
+ {
+ System.out.println("Connecting to localhost Qpid java broker...");
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+
+ private static void connectionrefuse(Exception e)
+ {
+ String message = e.getLocalizedMessage();
+ if (e instanceof SecurityException)
+ {
+ message = " authentication failed, please check username and password";
+ }
+ else
+ {
+ Throwable cause = e.getCause();
+ while (cause != null)
+ {
+ message = cause.getMessage();
+ cause = cause.getCause();
+ }
+ }
+
+ System.out.println("Cannot connect with the broker: " + message);
+ }
+
+ public static String[] oneshotmode(String[] args, CommandLineOptionParser commandlineoptionparser,
+ JMXConnector jmxc, MBeanServerConnection mbsc) throws Exception
+ {
+ int check = 0;
+ String[] temp;
+ for (int i = 0; i < args.length; i++)
+ {
+
+ if (args[i].compareTo("-h") == 0)
+ check++;
+ else if (args[i].compareTo("-p") == 0)
+ check++;
+ }
+ for (int i = 0; i < (args.length - 2 * check); i++)
+ { // mulitply by 2 because have to remove the option letter with the
+ // option value//
+ args[i] = args[i + check * 2];
+ }
+
+ commandlineoptionparser = new CommandLineOptionParser(args); // change
+ // the args
+ // string
+ // array
+ // which
+ // works as
+ // interactive
+ // mode//
+ JMXinfo info = new JMXinfo(jmxc, commandlineoptionparser, mbsc);
+ CommandExecutionEngine engine = new CommandExecutionEngine(info);
+ if (engine.CommandSelector())
+ engine.runcommand();
+ return args;
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/Connector.java b/java/management/tools/qpid-cli/src/org/apache/qpid/Connector.java
new file mode 100644
index 0000000000..2b887077c3
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/Connector.java
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+public class Connector
+{
+ private JMXConnector jmxc = null;
+ private MBeanServerConnection mbsc = null;
+
+ public Connector(JMXConnector jmxc, MBeanServerConnection mbsc)
+ {
+
+ this.jmxc = jmxc;
+ this.mbsc = mbsc;
+
+ }
+
+ public JMXConnector getConnector()
+ {
+ return jmxc;
+ }
+
+ public MBeanServerConnection getMBeanServerConnection()
+ {
+ return mbsc;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/ConnectorFactory.java b/java/management/tools/qpid-cli/src/org/apache/qpid/ConnectorFactory.java
new file mode 100644
index 0000000000..84ba94c5c4
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/ConnectorFactory.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+import org.apache.qpid.management.common.JMXConnnectionFactory;
+
+public class ConnectorFactory
+{
+
+ private static final long TIMEOUT = 30 * 1000;
+
+ public static Connector getConnector(String host, String port, String username, String password) throws Exception
+ {
+
+ JMXConnector jmxc = null;
+ MBeanServerConnection mbsc = null;
+ try
+ {
+ jmxc = JMXConnnectionFactory.getJMXConnection(TIMEOUT, host, Integer.parseInt(port), username, password);
+ mbsc = jmxc.getMBeanServerConnection();
+ }
+ catch (NumberFormatException e)
+ {
+ System.out.println("Illegal port entered:" + port);
+ System.exit(1);
+ }
+ return new Connector(jmxc, mbsc);
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/ReportGenerator.java b/java/management/tools/qpid-cli/src/org/apache/qpid/ReportGenerator.java
new file mode 100644
index 0000000000..9d14f78b42
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/ReportGenerator.java
@@ -0,0 +1,195 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import org.apache.qpid.commands.objects.*;
+import org.apache.qpid.utils.JMXinfo;
+
+import javax.management.MBeanServerConnection;
+import java.util.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class ReportGenerator implements Runnable
+{
+
+ String[] propertyname = { "object", "column", "filter.name", "filter.virtualhost", "output", "seperator",
+ "interval" };
+ String[] propertyvalue = null;
+ String propertyfilepath = null;
+ String[] columnvalue = null;
+ List<String> columns = null;
+ Properties props = null;
+ JMXinfo info = null;
+ int interval = 10;
+
+ public void run()
+ {
+ for (;;) // creating infinite loop
+ {
+ generatereport();
+ try
+ {
+ Thread.sleep((long)this.interval * 60000L);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public ReportGenerator(String propfile, JMXinfo info)
+ {
+ this.propertyfilepath = propfile;
+ props = new Properties();
+ propertyvalue = new String[propertyname.length];
+ this.info = info;
+ columns = new ArrayList<String>();
+ }
+
+ public void loadproperties() // get all the property file values and set the
+ // columen values//
+ {
+ try
+ {
+
+ props.load(new FileInputStream(this.propertyfilepath));
+ for (int i = 0; i < propertyname.length; i++)
+ {
+ propertyvalue[i] = props.getProperty(propertyname[i]);
+ }
+ this.setcolumnvalues();
+ this.setinterval();
+ }
+
+ // catch exception in case properties file does not exist
+
+ catch (IOException e)
+ {
+ System.out.println("Oooops Give property file is not exist");
+ }
+ }
+
+ public void generatereport()
+ {
+ this.listobjects(propertyvalue[0]);
+ }
+
+ private void setcolumnvalues()
+ {
+ columnvalue = propertyvalue[1].split(",");
+ for (int i = 0; i < columnvalue.length; i++)
+ {
+ columns.add(columnvalue[i]);
+ }
+ }
+
+ private void setinterval()
+ {
+ this.interval = (new Integer(propertyvalue[6])).intValue();
+ }
+
+ private void listobjects(String option_value)
+ {
+ /*
+ * pring usage if use is not give the correct option letter or no
+ * options
+ */
+ if (option_value == null)
+ {
+ // System.out.println("testing");
+ return;
+ }
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ Set set = null;
+ ObjectNames objname = null;
+
+ try
+ {
+ if (option_value.compareToIgnoreCase("queue") == 0 || option_value.compareToIgnoreCase("queues") == 0)
+ {
+ objname = new QueueObject(mbsc);
+
+ }
+ else if (option_value.compareToIgnoreCase("Virtualhosts") == 0
+ || option_value.compareToIgnoreCase("Virtualhost") == 0)
+ {
+ objname = new VirtualHostObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Exchange") == 0
+ || option_value.compareToIgnoreCase("Exchanges") == 0)
+ {
+ objname = new ExchangeObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Connection") == 0
+ || option_value.compareToIgnoreCase("Connections") == 0)
+ {
+ objname = new ConnectionObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("all") == 0)
+ {
+ objname = new AllObjects(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Usermanagement") == 0
+ || option_value.compareToIgnoreCase("Usermanagmenets") == 0)
+ {
+ objname = new UserManagementObject(mbsc);
+ // this.name = option_value;
+ }
+ else
+ {
+ printusage();
+ echo("Wrong objectName");
+ return;
+ }
+ objname.setQueryString(this.propertyvalue[0], this.propertyvalue[2], this.propertyvalue[3]);
+ objname.returnObjects();
+ if (objname.getSet().size() != 0)
+ {
+ objname.reportgenerator(this.propertyvalue[4], this.propertyvalue[5], columns);
+ }
+ else
+ {
+ printusage();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void echo(String str)
+ {
+ System.out.println(str);
+ }
+
+ public void printusage()
+ {
+ System.out.println("Wrong option or wrong option value");
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/CommandImpl.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/CommandImpl.java
new file mode 100644
index 0000000000..6fdae4c0a6
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/CommandImpl.java
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.util.Map;
+
+import org.apache.qpid.Command;
+import org.apache.qpid.utils.CommandLineOption;
+import org.apache.qpid.utils.JMXinfo;
+
+public abstract class CommandImpl implements Command
+{
+ protected JMXinfo info = null;
+
+ private String name;
+ private String virtualhost = null;
+ private String object = null;
+
+ private String outputformat = null;
+ private String seperator = ",";
+
+ public CommandImpl(JMXinfo info)
+ {
+ this.info = info;
+ }
+
+ public CommandImpl()
+ {
+
+ }
+
+ protected void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return this.name;
+ }
+
+ protected boolean hasName()
+ {
+ if (this.name == null)
+ return false;
+
+ else
+ return true;
+ }
+
+ protected void setObject(String object)
+ {
+ this.object = object;
+ }
+
+ public String getObject()
+ {
+ return this.object;
+ }
+
+ protected void setOutputFormat(String outputformat)
+ {
+ this.outputformat = outputformat;
+ }
+
+ protected String getOutputFormat()
+ {
+ return outputformat;
+ }
+
+ protected void setSeperator(String seperator)
+ {
+ this.seperator = seperator;
+ }
+
+ protected String getSeperator()
+ {
+ return seperator;
+ }
+
+ protected void setVirtualhost(String virtualhost)
+ {
+ this.virtualhost = virtualhost;
+ }
+
+ public String getVirtualhost()
+ {
+ return this.virtualhost;
+ }
+
+ public String optionchecker(String option_letter)
+ {
+ Map map = info.getCommandLineOptionParser().getAlloptions();
+ if (map == null)
+ return null;
+ CommandLineOption option = (CommandLineOption) map.get(option_letter);
+ if (option == null)
+ return null;
+ String value = option.getOptionValue();
+ return value;
+ }
+
+ public boolean checkoptionsetting(String option_letter)
+ {
+ Map map = info.getCommandLineOptionParser().getAlloptions();
+ if (map == null)
+ return false;
+ CommandLineOption option = (CommandLineOption) map.get(option_letter);
+ if (option == null)
+ return false;
+ String value = option.getOptionType();
+
+ if (value != null)
+ return true;
+ else
+ return false;
+ }
+
+ public void echo(String str)
+ {
+ System.out.println(str);
+ }
+
+ public void unrecognizeoption()
+ {
+ echo("list: Unrecognized option");
+ echo("Try --help for more information");
+ }
+
+ public abstract void execute();
+
+ public abstract void printusage();
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commanddelete.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commanddelete.java
new file mode 100644
index 0000000000..cdbb8f1d4f
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commanddelete.java
@@ -0,0 +1,199 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commanddelete extends CommandImpl
+{
+ private int number = 0;
+ private QueueObject objname;
+ private MBeanServerConnection mbsc;
+ private String method1, method2;
+ private ObjectName queue;
+ public static final String COMMAND_NAME = "delete";
+
+ public Commanddelete(JMXinfo info)
+ {
+ super(info);
+ this.mbsc = info.getmbserverconnector();
+ this.objname = new QueueObject(mbsc);
+ this.method1 = "deleteMessageFromTop";
+ this.method2 = "clearQueue";
+
+ }
+
+ public void deletemessages()
+ {
+ Set set = null;
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ set = objname.returnObjects();
+
+ if (objname.getSet().size() != 0)
+ {
+ Iterator it = set.iterator();
+ this.queue = (ObjectName) it.next();
+ try
+ {
+ if (this.number == 0)
+ {
+ echo("");
+ System.out.print("Do you want to delete all the messages from the Queue [Y/N] :");
+ InputStreamReader isr = new InputStreamReader(System.in);
+ BufferedReader br = new BufferedReader(isr);
+ String s = br.readLine();
+ echo(s);
+ if (s.compareToIgnoreCase("y") == 0)
+ this.mbsc.invoke(queue, this.method2, null, null);
+ else
+ return;
+ }
+ else if (objname.getmessagecount(this.queue) < this.number)
+ {
+ echo("Given number is Greater than the Queue Depth");
+ return;
+ }
+ else
+ {
+ for (int i = 0; i < this.number; i++)
+ {
+ this.mbsc.invoke(queue, this.method1, null, null);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("The Queue you have specified is not in the current broker");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ if (object.compareToIgnoreCase("queue") == 0)
+ setObject(object);
+ else
+ {
+ unrecognizeoption();
+ echo("This command is only applicable for delete command so please start with queue");
+ }
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ name = optionchecker("n");
+
+ setName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ vhost = optionchecker("v");
+ setVirtualhost(vhost);
+ }
+ if (checkoptionsetting("top") || checkoptionsetting("t"))
+ {
+ String number = optionchecker("top");
+ if (number == null)
+ number = optionchecker("t");
+
+ setnumber(removeSpaces(number));
+ }
+ this.deletemessages();
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:delete [OPTION] ... [OBJECT TYPE]...\n");
+ echo("Delete the top most messages from the given queue object\n");
+ echo("To specify the desired queue you have to give the virtualhost name and the queue name with following commands\n");
+ echo("Where possible options include:\n");
+ echo(" -v --virtualhost Give the virtuallhost name of the desired queue");
+ echo(" -n --name Give the queue name of the desired queue you want to do the delete operation");
+ echo(" -t --top Give how many number of messages you want to delete from the top (Default = all the messages will be deleted");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+
+ private void setnumber(String number)
+ {
+ Integer i = new Integer(number);
+ this.number = i.intValue();
+ }
+
+ public int getnumber()
+ {
+ return this.number;
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandget.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandget.java
new file mode 100644
index 0000000000..cb67edeb34
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandget.java
@@ -0,0 +1,211 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.commands.objects.ObjectNames;
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import java.util.Set;
+
+public class Commandget extends CommandImpl
+{
+
+ private String _attributeName;
+ private String _value;
+ public static final String COMMAND_NAME = "get";
+
+ public Commandget(JMXinfo info)
+ {
+ super(info);
+ }
+
+ private void getAttribute(String option_value)
+ {
+ if (option_value == null)
+ {
+ printusage();
+ return;
+ }
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ Set set = null;
+ ObjectNames objname = null;
+
+ try
+ {
+ if (option_value.compareToIgnoreCase("queue") == 0 || option_value.compareToIgnoreCase("queues") == 0)
+ {
+ objname = new QueueObject(mbsc);
+ }
+ else
+ {
+ printusage();
+ echo("Wrong objectName");
+ return;
+ }
+
+ if (_attributeName == null)
+ {
+ echo("attribute name not specified. See --help for details");
+ return;
+ }
+
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ objname.returnObjects();
+
+ if (objname.getSet().size() != 1)
+ {
+ echo("Your query returned more than one object to set was this intended?\n" + objname.getQueryString());
+ }
+ else if (objname.getSet().size() == 1)
+ {
+ ObjectName object = (ObjectName) objname.getSet().iterator().next();
+
+ Object value = objname.getAttribute(object, _attributeName);
+
+ echo(value.toString());
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("You might be querying wrong " + this.getObject() + " name with --name or -n option ");
+ echo("");
+ echo("No " + this.getObject() + "Type Objects might not in the broker currently");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+ if (checkoptionsetting("output"))
+ {
+ setOutputFormat(optionchecker("output"));
+ if (checkoptionsetting("separator"))
+ {
+ setSeperator(optionchecker("separator"));
+ }
+ }
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ setObject(object);
+
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ {
+ name = optionchecker("n");
+ }
+
+ setName(name);
+ }
+
+ if (checkoptionsetting("attribute") || checkoptionsetting("a"))
+ {
+ String name = optionchecker("attribute");
+ if (name == null)
+ {
+ name = optionchecker("a");
+ }
+
+ setAttributeName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ {
+ vhost = optionchecker("v");
+ }
+ setVirtualhost(vhost);
+ }
+ getAttribute(this.getObject());
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ {
+ printusage();
+ }
+ else
+ {
+ unrecognizeoption();
+ }
+ }
+
+ private void setAttributeName(String name)
+ {
+ this._attributeName = name;
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:set [OPTION] ... [OBJECT TYPE]...\n");
+ echo("List the information about the given object\n");
+ echo("Where possible options include:\n");
+ echo(" -o --object type of objects which you want to list\n");
+ echo(" ex: < list -o queue > : lists all the queues created in the java broker\n");
+ echo(" For now list command is supporting following object typse \n");
+ echo(" Queue Connection VirtualHost UserMangement Exchange");
+ echo(" Or You can specify object type by giving it at the beginning");
+ echo(" rather giving it as a argument");
+ echo(" Ex:< queue list > this command is equal to list -o queue \n");
+ echo(" -v --virtualhost After specifying the object type you can filter output with this option");
+ echo(" list objects with the given virtualhost which will help to find ");
+ echo(" identical queue objects with -n option");
+ echo(" ex: queue list -v develop ment");
+ echo(" -n --name After specifying what type of objects you want to monitor you can filter");
+ echo(" the output using -n option by specifying the name of the object you want ");
+ echo(" to monitor exactly");
+ echo(" ex: <list -o queue -n ping> : list all the queue objects having queue name");
+ echo(" of ping");
+ echo(" ex: <queue list -n ping -v development> list all the queue objects with name ");
+ echo(" of ping and virtualhost of developement \n");
+ echo(" -a --attribute ");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandhelp.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandhelp.java
new file mode 100644
index 0000000000..502ac89f74
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandhelp.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandhelp extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "help";
+
+ public Commandhelp(JMXinfo info)
+ {
+ }
+
+ public void execute()
+ {
+ printusage();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Current version of qpid CLI is supporting following commands");
+ echo("");
+ echo("[list] This command is listing limited information about a given type of object");
+ echo(" For more information about list command run `list --help`");
+ echo("[info] This command is listing All the information about a given type of object");
+ echo(" For more information about list command run `info --help`");
+
+ echo("");
+ echo("[exit] This command is disconnect the connection with the Qpid Java broker and go back to normal propmt");
+ echo("[quit] This command is disconnect the connection with the Qpid Java broker and go back to normal propmt");
+ echo("");
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandinfo.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandinfo.java
new file mode 100644
index 0000000000..7094a8fc7f
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandinfo.java
@@ -0,0 +1,206 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.util.Set;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.commands.objects.AllObjects;
+import org.apache.qpid.commands.objects.ConnectionObject;
+import org.apache.qpid.commands.objects.ExchangeObject;
+import org.apache.qpid.commands.objects.ObjectNames;
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.commands.objects.UserManagementObject;
+import org.apache.qpid.commands.objects.VirtualHostObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandinfo extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "info";
+
+ public Commandinfo(JMXinfo info)
+ {
+ super(info);
+ }
+
+ private void listobjects(String option_value)
+ {
+ /*
+ * pring usage if use is not give the correct option letter or no
+ * options
+ */
+ if (option_value == null)
+ {
+ // System.out.println("testing");
+ printusage();
+ return;
+ }
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ Set set = null;
+ ObjectNames objname = null;
+
+ try
+ {
+ if (option_value.compareToIgnoreCase("queue") == 0 || option_value.compareToIgnoreCase("queues") == 0)
+ {
+ objname = new QueueObject(mbsc);
+
+ }
+ else if (option_value.compareToIgnoreCase("Virtualhosts") == 0
+ || option_value.compareToIgnoreCase("Virtualhost") == 0)
+ {
+ objname = new VirtualHostObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Exchange") == 0
+ || option_value.compareToIgnoreCase("Exchanges") == 0)
+ {
+ objname = new ExchangeObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Connection") == 0
+ || option_value.compareToIgnoreCase("Connections") == 0)
+ {
+ objname = new ConnectionObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("all") == 0)
+ {
+ objname = new AllObjects(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Usermanagement") == 0
+ || option_value.compareToIgnoreCase("Usermanagmenets") == 0)
+ {
+ objname = new UserManagementObject(mbsc);
+ // this.name = option_value;
+ }
+ else
+ {
+ printusage();
+ echo("Wrong objectName");
+ return;
+ }
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ objname.returnObjects();
+ if (objname.getSet().size() != 0)
+ {
+ objname.displayinfo(this.getOutputFormat(), this.getSeperator());
+
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("You might querying wrong " + this.getObject() + " name with --name or -n option ");
+ echo("");
+ echo("No "+this.getObject() + "Type Objects might not be in the broker currently");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+ if (checkoptionsetting("output"))
+ {
+ setOutputFormat(optionchecker("output"));
+ if (checkoptionsetting("separator"))
+ setSeperator(optionchecker("separator"));
+ }
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ setObject(object);
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ name = optionchecker("n");
+
+ setName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ vhost = optionchecker("v");
+ setVirtualhost(vhost);
+ }
+ listobjects(this.getObject());
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:info [OPTION] ... [OBJECT TYPE]...\n");
+ echo("Give ALL the information about the given object\n");
+ echo("Where possible options include:\n");
+ echo(" -o --object type of objects which you want to list\n");
+ echo(" ex: < list -o queue > : lists all the queues created in the java broker\n");
+ echo(" For now list command is supporting following object typse \n");
+ echo(" Queue Connection VirtualHost UserMangement Exchange");
+ echo(" Or You can specify object type by giving it at the beginning rather giving ");
+ echo(" it as a argument");
+ echo(" Ex:< queue info > this command is equal to <info -o queue> command \n");
+ echo(" -v --virtualhost After specifying the object type you can filter output with this option");
+ echo(" list objects with the given virtualhost which will help to find identical");
+ echo(" queue objects with -n option");
+ echo(" ex: queue info -v developement");
+ echo(" -output Specify which output format you want to get the ouput");
+ echo(" Although the option is there current version supports only for CSV output format");
+ echo(" -separator This option use with output option to specify which separator you want to get the CSV output (default seperator is comma");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+ echo(" -n --name After specifying what type of objects you want to monitor you can filter");
+ echo(" the output using -n option by specifying the name of the object you want");
+ echo(" to monitor exactly");
+ echo(" ex: <queue info -n ping> : Give all the information about queue objects ");
+ echo(" having queue name of ping\n");
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandlist.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandlist.java
new file mode 100644
index 0000000000..68ee593ba0
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandlist.java
@@ -0,0 +1,232 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.util.Set;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.commands.objects.AllObjects;
+import org.apache.qpid.commands.objects.ConnectionObject;
+import org.apache.qpid.commands.objects.ExchangeObject;
+import org.apache.qpid.commands.objects.ObjectNames;
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.commands.objects.UserManagementObject;
+import org.apache.qpid.commands.objects.VirtualHostObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandlist extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "list";
+
+ public Commandlist(JMXinfo info)
+ {
+ super(info);
+ }
+
+ private void listobjects(String option_value)
+ {
+ /*
+ * pring usage if use is not give the correct option letter or no
+ * options
+ */
+ if (option_value == null)
+ {
+ // System.out.println("testing");
+ printusage();
+ return;
+ }
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ Set set = null;
+ ObjectNames objname = null;
+
+ try
+ {
+ if (option_value.compareToIgnoreCase("queue") == 0 || option_value.compareToIgnoreCase("queues") == 0)
+ {
+ objname = new QueueObject(mbsc);
+
+ }
+ else if (option_value.compareToIgnoreCase("Virtualhosts") == 0
+ || option_value.compareToIgnoreCase("Virtualhost") == 0)
+ {
+ objname = new VirtualHostObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Exchange") == 0
+ || option_value.compareToIgnoreCase("Exchanges") == 0)
+ {
+ objname = new ExchangeObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Connection") == 0
+ || option_value.compareToIgnoreCase("Connections") == 0)
+ {
+ objname = new ConnectionObject(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("all") == 0)
+ {
+ objname = new AllObjects(mbsc);
+ // this.name = option_value;
+ }
+ else if (option_value.compareToIgnoreCase("Usermanagement") == 0
+ || option_value.compareToIgnoreCase("Usermanagmenets") == 0)
+ {
+ objname = new UserManagementObject(mbsc);
+ // this.name = option_value;
+ }
+ else
+ {
+ printusage();
+ echo("Wrong objectName");
+ return;
+ }
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ objname.returnObjects();
+ if (objname.getSet().size() != 0)
+ {
+ if (this.getObject().compareToIgnoreCase("queue") == 0
+ || this.getObject().compareToIgnoreCase("queues") == 0)
+ objname.displayqueues(this.getOutputFormat(), this.getSeperator());
+ else
+ objname.displayobjects(this.getOutputFormat(), this.getSeperator());
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("You might quering wrong " + this.getObject() + " name with --name or -n option ");
+ echo("");
+ echo(this.getObject() + "Type Objects might not in the broker currently");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void listdomains()
+ {
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ try
+ {
+ String[] domains = mbsc.getDomains();
+ echo("DOMAINS");
+ for (int i = 0; i < domains.length; i++)
+ echo("\tDomain[" + i + "] = " + domains[i]);
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+ if (checkoptionsetting("output"))
+ {
+ setOutputFormat(optionchecker("output"));
+ if (checkoptionsetting("separator"))
+ setSeperator(optionchecker("separator"));
+ }
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ setObject(object);
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ name = optionchecker("n");
+
+ setName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ vhost = optionchecker("v");
+ setVirtualhost(vhost);
+ }
+ listobjects(this.getObject());
+ }
+ else if (checkoptionsetting("domain") || checkoptionsetting("d"))
+ listdomains();
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:list [OPTION] ... [OBJECT TYPE]...\n");
+ echo("List the information about the given object\n");
+ echo("Where possible options include:\n");
+ echo(" -o --object type of objects which you want to list\n");
+ echo(" ex: < list -o queue > : lists all the queues created in the java broker\n");
+ echo(" For now list command is supporting following object typse \n");
+ echo(" Queue Connection VirtualHost UserMangement Exchange");
+ echo(" Or You can specify object type by giving it at the beginning");
+ echo(" rather giving it as a argument");
+ echo(" Ex:< queue list > this command is equal to list -o queue \n");
+ echo(" -d --domain list all the domains of objects available for remote monitoring\n");
+ echo(" -v --virtualhost After specifying the object type you can filter output with this option");
+ echo(" list objects with the given virtualhost which will help to find ");
+ echo(" identical queue objects with -n option");
+ echo(" ex: queue list -v develop ment");
+ echo(" -output Specify which output format you want to get the ouput");
+ echo(" Although the option is there current version supports only for CSV output format");
+ echo(" -separator This option use with output option to specify which separator you want to get the CSV output (default seperator is comma");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+ echo(" -n --name After specifying what type of objects you want to monitor you can filter");
+ echo(" the output using -n option by specifying the name of the object you want ");
+ echo(" to monitor exactly");
+ echo(" ex: <list -o queue -n ping> : list all the queue objects having queue name");
+ echo(" of ping");
+ echo(" ex: <queue list -n ping -v development> list all the queue objects with name ");
+ echo(" of ping and virtualhost of developement \n");
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandmove.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandmove.java
new file mode 100644
index 0000000000..6d1803409b
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandmove.java
@@ -0,0 +1,259 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandmove extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "move";
+
+ private String name1 = null, name2 = null, vhost1 = null, vhost2 = null, method1 = null, method2 = null; // target
+ // and
+ // starting
+ // queue
+ // specifications
+ // happen
+ // with
+ // these
+ // options
+ private QueueObject queue1;
+ private MBeanServerConnection mbsc;
+ private ObjectName queue;
+ private int fmid = 0, tmid = 0;
+
+ public Commandmove(JMXinfo info)
+ {
+ super(info);
+
+ this.mbsc = info.getmbserverconnector();
+ this.queue1 = new QueueObject(mbsc);
+ this.method1 = "moveMessages";
+ this.method2 = "getMessagesOnTheQueue";
+
+ }
+
+ public void movemessages()
+ {
+ Set set = null;
+ queue1.setQueryString(this.getObject(), this.name1, this.vhost1);
+ set = queue1.returnObjects();
+ if (queue1.getSet().size() != 0)
+ { // find the queue
+ Iterator it = set.iterator();
+ this.queue = (ObjectName) it.next();
+ }
+ else
+ {
+ if (isname1() || isname2())
+ { // if the specified queue is not there in the broker
+
+ echo("The Queue you have specified is not in the current broker");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+ try
+ {
+ Object[] params1 = { getfmid(), gettmid(), this.name2 };
+ String[] signature1 = { new String("long"), new String("long"), new String("java.lang.String") };
+ this.mbsc.invoke(this.queue, this.method1, params1, signature1);
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ echo("Given messageId's might be wrong please run the view command and check messageId's you have given\n");
+ echo("From MessageId should be greater than 0 and should less than To messageId");
+ }
+
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ if (object.compareToIgnoreCase("queue") == 0)
+ setObject(object);
+ else
+ {
+ unrecognizeoption();
+ echo("This command is only applicable for queue command so please start with queue");
+ }
+ if (checkoptionsetting("n2") && checkoptionsetting("n1"))
+ {
+ setname1(optionchecker("n1"));
+ setname2(optionchecker("n2"));
+ }
+ else
+ {
+ echo("You have to specify both n1 and n2 option value to move a message"); /*
+ * when
+ * user
+ * forget
+ * to
+ * specify
+ * target
+ * or
+ * starting
+ * queue
+ * name
+ */
+ return;
+ }
+
+ if (checkoptionsetting("v1"))
+ {
+
+ setvhost1(optionchecker("v1"));
+ }
+ if (checkoptionsetting("tmid") && checkoptionsetting("fmid"))
+ {
+ String tmid = optionchecker("tmid");
+ String fmid = optionchecker("fmid");
+
+ settomessageIdandfrommessageId(removeSpaces(tmid), removeSpaces(fmid));
+ }
+ else
+ {
+ echo("You have to set from MessageId and to MessageId in order to move messages between queues");
+ echo("To view MessageId's use <view> command with -n and -v options");
+ return;
+ }
+ this.movemessages();
+
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:move [OPTION] ... [OBJECT TYPE]...\n");
+ echo("Move the top most messages from the given queue object to the given destination object\n");
+ echo("To specify the desired queues you have to give the virtualhost name and the queue name with following commands\n");
+ echo("Where possible options include:\n");
+ echo(" -v1 Give the virtuallhost name from which queue you want to move messages");
+ echo(" -n1 Give the queue name which you want to move messages from");
+ echo(" -n2 Give the queue name of the destination queue");
+ echo(" -tmid Give From MessageId you want to move from the Queue");
+ echo(" -fmid Give To MessageId you want to move from the Queue");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+
+ private void setname1(String name)
+ {
+ this.name1 = name;
+ }
+
+ private void setname2(String name)
+ {
+ this.name2 = name;
+ }
+
+ private boolean isname1()
+ {
+ if (this.name1 == null)
+ return false;
+
+ else
+ return true;
+ }
+
+ private boolean isname2()
+ {
+ if (this.name2 == null)
+ return false;
+
+ else
+ return true;
+ }
+
+ private void setvhost1(String vhost)
+ {
+ this.vhost1 = vhost;
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+
+ private void settomessageIdandfrommessageId(String tmid, String fmid)
+ {
+ Integer i = new Integer(tmid);
+ Integer j = new Integer(fmid);
+ this.tmid = i.intValue();
+ this.fmid = j.intValue();
+ }
+
+ public int gettmid()
+ {
+ return this.tmid;
+ }
+
+ public int getfmid()
+ {
+ return this.fmid;
+ }
+
+ public String getname1()
+ {
+ return this.name1;
+ }
+
+ public String getname2()
+ {
+ return this.name2;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandset.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandset.java
new file mode 100644
index 0000000000..e70b7b17ad
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandset.java
@@ -0,0 +1,260 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.commands;
+
+import org.apache.qpid.commands.objects.ObjectNames;
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+import javax.management.Attribute;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import java.util.Set;
+
+public class Commandset extends CommandImpl
+{
+ private String _attributeName;
+ private String _value;
+ public static final String COMMAND_NAME = "set";
+
+ public Commandset(JMXinfo info)
+ {
+ super(info);
+ }
+
+ private void setAttribute(String option_value)
+ {
+ /*
+ * print usage if use is not give the correct option letter or no
+ * options
+ */
+ if (option_value == null)
+ {
+ printusage();
+ return;
+ }
+ MBeanServerConnection mbsc = info.getmbserverconnector();
+ Set set = null;
+ ObjectNames objname = null;
+
+ try
+ {
+ if (option_value.compareToIgnoreCase("queue") == 0 || option_value.compareToIgnoreCase("queues") == 0)
+ {
+ objname = new QueueObject(mbsc);
+ }
+ else
+ {
+ printusage();
+ echo("Wrong objectName");
+ return;
+ }
+
+ if (_attributeName == null)
+ {
+ echo("attribute name not specified. See --help for details");
+ return;
+ }
+
+ if (_value == null)
+ {
+ echo("new value not specified. See --help for details");
+ return;
+ }
+
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ objname.returnObjects();
+
+ if (objname.getSet().size() != 1)
+ {
+ echo("Your query returned more than one object to set was this intended?" + objname.getQueryString());
+ }
+ else if (objname.getSet().size() == 1)
+ {
+ ObjectName object = (ObjectName) objname.getSet().iterator().next();
+
+ Object value = objname.getAttribute(object, _attributeName);
+
+ Object attributeValue = _value;
+
+ try
+ {
+ if (value instanceof Integer)
+ {
+ attributeValue = Integer.valueOf(_value);
+ }
+ else if (value instanceof Long)
+ {
+ attributeValue = Long.valueOf(_value);
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ echo("Value(" + _attributeName + ") should be of type " + value.getClass().getName());
+ return;
+ }
+
+ Attribute attribute = new Attribute(_attributeName, attributeValue);
+
+ objname.setAttribute(object, attribute);
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("You might be querying wrong " + this.getObject() + " name with --name or -n option ");
+ echo("");
+ echo("No " + this.getObject() + "Type Objects might not in the broker currently");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+ if (checkoptionsetting("output"))
+ {
+ setOutputFormat(optionchecker("output"));
+ if (checkoptionsetting("separator"))
+ {
+ setSeperator(optionchecker("separator"));
+ }
+ }
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ setObject(object);
+
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ {
+ name = optionchecker("n");
+ }
+
+ setName(name);
+ }
+
+ if (checkoptionsetting("attribute") || checkoptionsetting("a"))
+ {
+ String name = optionchecker("attribute");
+ if (name == null)
+ {
+ name = optionchecker("a");
+ }
+
+ setAttributeName(name);
+ }
+
+ if (checkoptionsetting("set") || checkoptionsetting("s"))
+ {
+ String value = optionchecker("set");
+ if (value == null)
+ {
+ value = optionchecker("s");
+ }
+
+ setAttributeValue(value);
+ }
+
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ {
+ vhost = optionchecker("v");
+ }
+ setVirtualhost(vhost);
+ }
+ setAttribute(this.getObject());
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ {
+ printusage();
+ }
+ else
+ {
+ unrecognizeoption();
+ }
+ }
+
+ private void setAttributeValue(String value)
+ {
+ _value = value;
+ }
+
+ private void setAttributeName(String name)
+ {
+ this._attributeName = name;
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:set [OPTION] ... [OBJECT TYPE]...\n");
+ echo("List the information about the given object\n");
+ echo("Where possible options include:\n");
+ echo(" -o --object type of objects which you want to list\n");
+ echo(" ex: < list -o queue > : lists all the queues created in the java broker\n");
+ echo(" For now list command is supporting following object typse \n");
+ echo(" Queue Connection VirtualHost UserMangement Exchange");
+ echo(" Or You can specify object type by giving it at the beginning");
+ echo(" rather giving it as a argument");
+ echo(" Ex:< queue list > this command is equal to list -o queue \n");
+ echo(" -v --virtualhost After specifying the object type you can filter output with this option");
+ echo(" list objects with the given virtualhost which will help to find ");
+ echo(" identical queue objects with -n option");
+ echo(" ex: queue list -v develop ment");
+ echo(" -n --name After specifying what type of objects you want to monitor you can filter");
+ echo(" the output using -n option by specifying the name of the object you want ");
+ echo(" to monitor exactly");
+ echo(" ex: <list -o queue -n ping> : list all the queue objects having queue name");
+ echo(" of ping");
+ echo(" ex: <queue list -n ping -v development> list all the queue objects with name ");
+ echo(" of ping and virtualhost of developement \n");
+ echo(" -a --attribute ");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandview.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandview.java
new file mode 100644
index 0000000000..e3bcc7e543
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandview.java
@@ -0,0 +1,255 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandview extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "view";
+
+ private int number = 0;
+ private QueueObject objname;
+ private MBeanServerConnection mbsc;
+ private String method1;
+ private ObjectName queue;
+
+ public Commandview(JMXinfo info)
+ {
+ super(info);
+ this.mbsc = info.getmbserverconnector();
+ this.objname = new QueueObject(mbsc);
+ this.method1 = "viewMessages";
+
+ }
+
+ public void viewmessages()
+ {
+ objname.setQueryString(this.getObject(), this.getName(), this.getVirtualhost());
+ Set set = objname.returnObjects();
+ String header = "", temp_header = "", message_data = "", outline = "";
+
+ if (objname.getSet().size() != 0)
+ {
+ Iterator it = set.iterator();
+ this.queue = (ObjectName) it.next();
+ try
+ {
+ if (objname.getmessagecount(this.queue) == 0)
+ {
+ echo("Selected Queue doesn't contain any messages");
+ return;
+ }
+ if (this.number == 0)
+ this.number = objname.getmessagecount(this.queue);
+
+ if (objname.getmessagecount(this.queue) < this.number)
+ {
+ echo("Given number is Greater than the Queue Depth");
+ return;
+ }
+ else
+ {
+ Object[] params = { 1, this.number };
+ String[] signature = { new String("int"), new String("int") };
+ TabularDataSupport data = (TabularDataSupport) this.mbsc.invoke(queue, this.method1, params,
+ signature);
+
+ Set entrySet = data.entrySet();
+ ArrayList<Map.Entry> list = new ArrayList<Map.Entry>(entrySet);
+ if (list.size() != 0)
+ {// no data}
+ for (int i = 0; i < list.size(); i++)
+ {
+ CompositeData compositedata = (CompositeData) (list.get(i)).getValue();
+ List<String> itemNames = new ArrayList<String>(compositedata.getCompositeType().keySet());
+ if (i == 0) // display the table headers
+ {
+ for (int j = 0; j < itemNames.size(); j++)
+ {
+ temp_header = "";
+ if (j != 1) // skipping header information
+ {
+ temp_header = itemNames.get(j);
+ while (temp_header.length() < 15)
+ temp_header = " " + temp_header;
+
+ header = header + temp_header + "|";
+ }
+ else
+ continue;
+ }
+ echo(header);
+ while (outline.length() < header.length())
+ outline = outline + "-";
+ echo(outline);
+ }
+
+ for (int j = 0; j < itemNames.size(); j++)
+ {
+ temp_header = "";
+ if (j != 1)
+ {
+ temp_header = String.valueOf(compositedata.get(itemNames.get(j)));
+ while (temp_header.length() < 15)
+ temp_header = " " + temp_header;
+ message_data = message_data + temp_header + "|";
+ }
+ else
+ // header information is not displaying
+ // unless user specify header information is
+ // needed
+ continue;
+
+ }
+ echo(message_data);
+ header = "";
+ message_data = "";
+ }
+ }
+ else
+ {
+ System.out.println("No Data to Display");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("The Queue you have specified is not in the current broker");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ if (object.compareToIgnoreCase("queue") == 0)
+ setObject(object);
+ else
+ {
+ unrecognizeoption();
+ echo("This command is only applicable for delete command so please start with queue");
+ }
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ name = optionchecker("n");
+
+ setName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ vhost = optionchecker("v");
+ setVirtualhost(vhost);
+ }
+ if (checkoptionsetting("top") || checkoptionsetting("t"))
+ {
+ String number = optionchecker("top");
+ if (number == null)
+ number = optionchecker("t");
+
+ setnumber(removeSpaces(number));
+ }
+ this.viewmessages();
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:view [OPTION] ... [OBJECT TYPE]...\n");
+ echo("view the information about given number of messages from the given queue object\n");
+ echo("To specify the desired queue you have to give the virtualhost name and the queue name with following commands\n");
+ echo("Where possible options include:\n");
+ echo(" -v --virtualhost Give the virtuallhost name of the desired queue");
+ echo(" -n --name Give the queue name of the desired queue you want to view messages");
+ echo(" -t --top Give how many number of messages you want to delete from the top (Default = all the messages will be deleted");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+
+ private void setnumber(String number)
+ {
+ Integer i = new Integer(number);
+ this.number = i.intValue();
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+
+ public int getnumber()
+ {
+ return number;
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandviewcontent.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandviewcontent.java
new file mode 100644
index 0000000000..d1ae1c1893
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/Commandviewcontent.java
@@ -0,0 +1,248 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.qpid.commands.objects.QueueObject;
+import org.apache.qpid.utils.JMXinfo;
+
+public class Commandviewcontent extends CommandImpl
+{
+
+ public static final String COMMAND_NAME = "viewcontent";
+
+ private long number = 0;
+ private QueueObject objname;
+ private MBeanServerConnection mbsc;
+ private String method1;
+ private ObjectName queue;
+
+ public Commandviewcontent(JMXinfo info)
+ {
+ super(info);
+ this.mbsc = info.getmbserverconnector();
+ this.objname = new QueueObject(mbsc);
+ this.method1 = "viewMessageContent";
+
+ }
+
+ public void viewcontent()
+ {
+ objname.setQueryString(getObject(), getName(), getVirtualhost());
+ Set set = objname.returnObjects();
+ String temp_header = "", header = "", message_data = "", encoding = null;
+
+ if (objname.getSet().size() != 0)
+ {
+ Iterator it = set.iterator();
+ this.queue = (ObjectName) it.next();
+ try
+ {
+ if (objname.getmessagecount(this.queue) == 0)
+ {
+ echo("Selected Queue doesn't contain any messages");
+ return;
+ }
+ if (this.number == 0)
+ {
+ echo("You haven't selected a MessageId Please use -id and give a message id");
+ echo("Or run view command with same arguemnts to view messageId list for the queue");
+ }
+ else
+ {
+ Object[] params = { this.number };
+ String[] signature = { new String("long") };
+ CompositeData data = (CompositeData) this.mbsc.invoke(queue, this.method1, params, signature);
+ List<String> itemNames = new ArrayList<String>(data.getCompositeType().keySet());
+ for (int j = 0; j < itemNames.size(); j++)
+ {
+ temp_header = "";
+ temp_header = itemNames.get(j);
+ while (temp_header.length() < 15)
+ temp_header = " " + temp_header;
+
+ header = header + temp_header + "|";
+ }
+ echo(header);
+ encoding = String.valueOf(data.get(itemNames.get(2))); // set
+ // the
+ // encoding
+ // at
+ // the
+ // beginning
+ // because
+ // encoding
+ // comes
+ // later
+ // in
+ // the
+ // loop
+ if (encoding == null || encoding.length() == 0)
+ {
+ encoding = Charset.defaultCharset().name();
+
+ }
+ for (int j = 0; j < itemNames.size(); j++)
+ {
+ temp_header = "";
+ if (j != 1)
+ {
+ temp_header = String.valueOf(data.get(itemNames.get(j)));
+ while (temp_header.length() < 15)
+ temp_header = " " + temp_header;
+ }
+ else
+ {
+ Byte[] arrayItems = (Byte[]) data.get(itemNames.get(j));
+ byte[] byteArray = new byte[arrayItems.length];
+ for (int i = 0; i < arrayItems.length; i++)
+ {
+ byteArray[i] = arrayItems[i];
+ temp_header = new String(byteArray, encoding);
+ while (temp_header.length() < 15)
+ temp_header = " " + temp_header;
+ }
+ }
+ message_data = message_data + temp_header + "|";
+
+ }
+ echo(message_data);
+ }
+ }
+ catch (Exception ex)
+ {
+ echo("Given MessageId is invalid, There's no message with the given messageId");
+ ex.printStackTrace();
+ return;
+ }
+
+ }
+ else
+ {
+ if (hasName())
+ {
+
+ echo("The Queue you have specified is not in the current broker");
+ echo("");
+ }
+ else
+ {
+ printusage();
+ }
+ }
+ }
+
+ public void execute()
+ {
+ /*
+ * In here you it's easy to handle any number of otpions which are going
+ * to add with the list command which works with main option object or o
+ */
+
+ if (checkoptionsetting("object") || checkoptionsetting("o"))
+ {
+ String object = optionchecker("object");
+ if (object == null)
+ {
+ object = optionchecker("o");
+ }
+ if (object.compareToIgnoreCase("queue") == 0)
+ setObject(object);
+ else
+ {
+ unrecognizeoption();
+ echo("This command is only applicable for delete command so please start with queue");
+ }
+ if (checkoptionsetting("name") || checkoptionsetting("n"))
+ {
+ String name = optionchecker("name");
+ if (name == null)
+ name = optionchecker("n");
+
+ setName(name);
+ }
+ if (checkoptionsetting("virtualhost") || checkoptionsetting("v"))
+ {
+ String vhost = optionchecker("virtualhost");
+ if (vhost == null)
+ vhost = optionchecker("v");
+ setVirtualhost(vhost);
+ }
+ if (checkoptionsetting("messageid") || checkoptionsetting("id"))
+ {
+ String number = optionchecker("id");
+ if (number == null)
+ number = optionchecker("id");
+
+ setnumber(removeSpaces(number));
+ }
+ this.viewcontent();
+ }
+ else if (checkoptionsetting("h") || checkoptionsetting("help"))
+ printusage();
+ else
+ unrecognizeoption();
+ }
+
+ public void printusage()
+ {
+ echo("");
+ echo("Usage:viewcontent [OPTION] ... [OBJECT TYPE]...\n");
+ echo("view the information about given number of messages from the given queue object\n");
+ echo("To specify the desired queue you have to give the virtualhost name and the queue name with following commands\n");
+ echo("Where possible options include:\n");
+ echo(" -v --virtualhost Give the virtuallhost name of the desired queue");
+ echo(" -n --name Give the queue name of the desired queue you want to view messages");
+ echo(" -id Give the messageId of the required message you want to view the content");
+ echo(" -h --help Display the help and back to the qpid-cli prompt\n");
+
+ }
+
+ private void setnumber(String number)
+ {
+ this.number = Long.valueOf(number);
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+
+ public long getnumber()
+ {
+ return this.number;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/AllObjects.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/AllObjects.java
new file mode 100644
index 0000000000..8b2099f3e0
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/AllObjects.java
@@ -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.
+ *
+ */
+
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+public class AllObjects extends ObjectNames
+{
+
+ public AllObjects(MBeanServerConnection mbsc)
+ {
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name)
+ {
+ querystring = "org.apache.qpid:*";
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ConnectionObject.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ConnectionObject.java
new file mode 100644
index 0000000000..2746b2016f
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ConnectionObject.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+public class ConnectionObject extends ObjectNames
+{
+ public ConnectionObject(MBeanServerConnection mbsc)
+ {
+ /* calling parent classes constructor */
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+ if (name != null && vhost == null)
+ querystring = "org.apache.qpid:type=Connection,name=" + name + ",*";
+ else if (name != null && vhost != null)
+ querystring = "org.apache.qpid:type=Connection,VirtualHost=" + vhost + ",name=" + name + ",*";
+ else if (name == null && vhost != null)
+ querystring = "org.apache.qpid:type=Connection,VirtualHost=" + vhost + ",*";
+ else
+ querystring = "org.apache.qpid:type=Connection,*";
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ExchangeObject.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ExchangeObject.java
new file mode 100644
index 0000000000..96d7e6e5dc
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ExchangeObject.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+public class ExchangeObject extends ObjectNames
+{
+ public ExchangeObject(MBeanServerConnection mbsc)
+ {
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+ if (name != null && vhost == null)
+ querystring = "org.apache.qpid:type=VirtualHost.Exchange,name=" + name + ",*";
+ else if (name != null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + vhost + ",name=" + name + ",*";
+ else if (name == null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + vhost + ",*";
+ else
+ querystring = "org.apache.qpid:type=VirtualHost.Exchange,*";
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ObjectNames.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ObjectNames.java
new file mode 100644
index 0000000000..1432f18018
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/ObjectNames.java
@@ -0,0 +1,591 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.Attribute;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+
+public class ObjectNames
+{
+ public String querystring = null;
+ public MBeanServerConnection mbsc;
+ public Set<ObjectName> set = null;
+ public String attributes = "";
+ public String attributevalues = "";// = null;
+
+ private static final Map<String,Integer> QUEUE_ATTRIBUTES = new HashMap<String,Integer>();
+ static
+ {
+ QUEUE_ATTRIBUTES.put(ManagedQueue.ATTR_NAME, 1);
+ QUEUE_ATTRIBUTES.put(ManagedQueue.ATTR_DURABLE, 2);
+ QUEUE_ATTRIBUTES.put(ManagedQueue.ATTR_ACTIVE_CONSUMER_COUNT, 3);
+ QUEUE_ATTRIBUTES.put(ManagedQueue.ATTR_MSG_COUNT, 4);
+ QUEUE_ATTRIBUTES.put(ManagedQueue.ATTR_RCVD_MSG_COUNT, 5);
+ }
+
+ public ObjectNames(MBeanServerConnection mbsc)
+ {
+ this.mbsc = mbsc;
+ }
+
+ public Set<ObjectName> returnObjects()
+ {
+ try
+ {
+ set = mbsc.queryNames(new ObjectName(querystring), null);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ return set;
+ }
+
+ public void echo(String str)
+ {
+ System.out.println(str);
+ }
+
+ /* display appropriate objects according to the ojbect type */
+
+ public void displayobjects(String output, String seperator)
+ {
+ Iterator it = set.iterator();
+ String line = "";
+ String temp2 = "";
+ int iterator = 0;
+ try
+ {
+ do
+ {
+ ObjectName temp_object = null;
+ if (it.hasNext())
+ {
+ temp_object = (ObjectName) it.next();
+ if (temp_object == null)
+ System.out.println("null test");
+ }
+ // echo(temp_object.getCanonicalKeyPropertyListString());
+ MBeanInfo bean_info = mbsc.getMBeanInfo(temp_object);
+ MBeanAttributeInfo[] attr_info = bean_info.getAttributes();
+ if (attr_info == null)
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ if (output == null)
+ echo(temp);
+
+ }
+ else
+ {
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+
+ try
+ {
+ String temp1 = attr.getName();
+ if (output == null)
+ {
+ while (temp1.length() < 15)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ attributes = attributes + temp1 + seperator;
+ else
+ {
+ echo("Wrong output format current version is supporting only for CSV");
+ return;
+ }
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ }
+ }
+ if (attributes.equalsIgnoreCase(""))
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ echo(temp);
+ echo("There are no attributes for this object Type");
+ continue;
+ }
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+ temp2 = null;
+ try
+ {
+ toWrite = mbsc.getAttribute(temp_object, attr.getName());
+ }
+ catch (Exception x)
+ {
+ temp2 = "-";
+ }
+ if (toWrite != null)
+ temp2 = toWrite.toString();
+ else
+ temp2 = "-";
+ if (output == null)
+ {
+
+ while (temp2.length() < 15)
+ temp2 = " " + temp2;
+
+ attributevalues = attributevalues + temp2 + "|";
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ attributevalues = attributevalues + temp2 + seperator;
+
+ // echo(temp1 + " " + temp2 + " " + temp3);
+
+ }
+ }
+ iterator++;
+ if (iterator == 1)
+ {
+ echo(attributes);
+ for (int i = 0; i < attributes.length(); i++)
+ line = line + "-";
+ if (output == null)
+ echo(line);
+ }
+ echo(attributevalues);
+ line = "";
+ attributes = "";
+ attributevalues = "";
+ } while (it.hasNext());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void reportgenerator(String output, String seperator, List<String> column)
+ {
+ Iterator it = set.iterator();
+ String line = "";
+ String temp2 = "";
+ int iterator = 0;
+ try
+ {
+ do
+ {
+ ObjectName temp_object = null;
+ if (it.hasNext())
+ {
+ temp_object = (ObjectName) it.next();
+ if (temp_object == null)
+ System.out.println("null test");
+ }
+ // echo(temp_object.getCanonicalKeyPropertyListString());
+ MBeanInfo bean_info = mbsc.getMBeanInfo(temp_object);
+ MBeanAttributeInfo[] attr_info = bean_info.getAttributes();
+ if (attr_info == null)
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ if (output == null)
+ echo(temp);
+
+ }
+ else
+ {
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+
+ try
+ {
+ String temp1 = attr.getName();
+ if (column.contains(temp1))
+ {
+ if (output == null)
+ {
+ while (temp1.length() < 15)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ attributes = attributes + temp1 + seperator;
+ else
+ {
+ echo("Wrong output format current version is supporting only for CSV");
+ return;
+ }
+ }
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ }
+ }
+ if (attributes.equalsIgnoreCase(""))
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ echo(temp);
+ echo("There are no attributes for this object Type");
+ return;
+ }
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+ temp2 = null;
+ if (column.contains(attr.getName()))
+ {
+ try
+ {
+ toWrite = mbsc.getAttribute(temp_object, attr.getName());
+ }
+ catch (Exception x)
+ {
+ temp2 = "-";
+ }
+ if (toWrite != null)
+ temp2 = toWrite.toString();
+ else
+ temp2 = "-";
+ if (output == null)
+ {
+
+ while (temp2.length() < 15)
+ temp2 = " " + temp2;
+
+ attributevalues = attributevalues + temp2 + "|";
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ attributevalues = attributevalues + temp2 + seperator;
+
+ // echo(temp1 + " " + temp2 + " " + temp3);
+
+ }
+
+ }
+ }
+ iterator++;
+ if (iterator == 1)
+ {
+ echo(attributes);
+ for (int i = 0; i < attributes.length(); i++)
+ line = line + "-";
+ if (output == null)
+ echo(line);
+ }
+ echo(attributevalues);
+ line = "";
+ attributes = "";
+ attributevalues = "";
+ } while (it.hasNext());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void displayqueues(String output, String seperator)
+ {
+ Iterator it = set.iterator();
+ String line = "";
+ int iterator = 0;
+ String temp1 = "";
+ String temp2 = "";
+ try
+ {
+ do
+ {
+ ObjectName temp_object = null;
+ if (it.hasNext())
+ {
+ temp_object = (ObjectName) it.next();
+ }
+ // echo(temp_object.getCanonicalKeyPropertyListString());
+ MBeanInfo bean_info = mbsc.getMBeanInfo(temp_object);
+ MBeanAttributeInfo[] attr_info = bean_info.getAttributes();
+ if (attr_info == null)
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ if (output == null)
+ echo(temp);
+
+ }
+ else
+ {
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+ Integer attr_count = QUEUE_ATTRIBUTES.get(attr.getName());
+
+ if(attr_count == null)
+ {
+ continue;
+ }
+
+ try
+ {
+ toWrite = mbsc.getAttribute(temp_object, attr.getName());
+ if (output == null)
+ {
+ switch (attr_count)
+ {
+ case 1:
+ case 2:
+ temp1 = attr.getName();
+ while (temp1.length() < 10)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ temp2 = toWrite.toString();
+ while (temp2.length() < 10)
+ temp2 = " " + temp2;
+ attributevalues = attributevalues + temp2 + "|";
+ break;
+ case 3:
+ temp1 = attr.getName();
+ while (temp1.length() < 20)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ temp2 = toWrite.toString();
+ while (temp2.length() < 20)
+ temp2 = " " + temp2;
+ attributevalues = attributevalues + temp2 + "|";
+ break;
+ case 4:
+ temp1 = attr.getName();
+ while (temp1.length() < 13)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ temp2 = toWrite.toString();
+ while (temp2.length() < 13)
+ temp2 = " " + temp2;
+ attributevalues = attributevalues + temp2 + "|";
+ break;
+ case 5:
+ temp1 = attr.getName();
+ while (temp1.length() < 20)
+ temp1 = " " + temp1;
+ attributes = attributes + temp1 + "|";
+ temp2 = toWrite.toString();
+ while (temp2.length() < 20)
+ temp2 = " " + temp2;
+ attributevalues = attributevalues + temp2 + "|";
+ break;
+ }
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ {
+ temp1 = attr.getName();
+ attributes = attributes + temp1 + seperator;
+ temp2 = toWrite.toString();
+ attributevalues = attributevalues + temp2 + seperator;
+ }
+ else
+ {
+ echo("Wrong output format specified currently CLI supports only csv output format");
+ return;
+ }
+
+ }
+ catch (Exception x)
+ {
+ x.printStackTrace();
+ }
+
+ }
+ }
+ iterator++;
+ if (iterator == 1)
+ {
+ for (int i = 0; i < attributes.length(); i++)
+ line = line + "-";
+ if (output == null)
+ echo(line);
+ echo(attributes);
+ if (output == null)
+ echo(line);
+ }
+ echo(attributevalues);
+ line = "";
+ attributes = "";
+ attributevalues = "";
+ } while (it.hasNext());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public void displayinfo(String output, String seperator)
+ {
+ Iterator it = set.iterator();
+ String temp1, temp2 = "";
+ try
+ {
+ do
+ {
+
+ ObjectName temp_object = null;
+ if (it.hasNext())
+ {
+ temp_object = (ObjectName) it.next();
+ }
+ // echo(temp_object.getCanonicalKeyPropertyListString());
+ MBeanInfo bean_info = mbsc.getMBeanInfo(temp_object);
+ MBeanAttributeInfo[] attr_info = bean_info.getAttributes();
+ if (attr_info == null)
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ echo(temp);
+
+ }
+ else
+ {
+ echo(temp_object.toString());
+ String temp = "";
+ while (temp_object.toString().length() > temp.length())
+ temp = "=" + temp;
+ echo(temp);
+
+ for (MBeanAttributeInfo attr : attr_info)
+ {
+ Object toWrite = null;
+
+ try
+ {
+ toWrite = mbsc.getAttribute(temp_object, attr.getName());
+ }
+ catch (Exception x)
+ {
+ temp2 = "-";
+ }
+ temp1 = attr.getName();
+ if (toWrite != null)
+ temp2 = toWrite.toString();
+
+ if (output == null)
+ {
+ while (temp1.length() < 35)
+ temp1 = " " + temp1;
+
+ while (temp2.length() < 35)
+ temp2 = " " + temp2;
+ echo(temp1 + " " + temp2);
+ }
+ else if (output.compareToIgnoreCase("csv") == 0)
+ echo(temp1 + seperator + temp2);
+ else
+ {
+ echo("Wrong output format specified currently CLI supports only csv output format");
+ return;
+ }
+ }
+ echo("");
+ echo("");
+
+ }
+ } while (it.hasNext());
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+
+ }
+
+ public void setQueryStringforinfo(String object, String name, String virtualhost)
+ {
+
+ }
+
+ public String getQueryString()
+ {
+ return querystring;
+ }
+
+ public Set getSet()
+ {
+ return set;
+ }
+
+ public Object getAttribute(ObjectName object, String attribute)
+ {
+ try
+ {
+ return mbsc.getAttribute(object, attribute);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ public void setAttribute(ObjectName object, Attribute attribute)
+ {
+ try
+ {
+ mbsc.setAttribute(object, attribute);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/QueueObject.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/QueueObject.java
new file mode 100644
index 0000000000..fcf0464ced
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/QueueObject.java
@@ -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.
+ *
+ */
+
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+
+public class QueueObject extends ObjectNames
+{
+ public QueueObject(MBeanServerConnection mbsc)
+ {
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+ if (name != null && vhost == null)
+ querystring = "org.apache.qpid:type=VirtualHost.Queue,name=" + name + ",*";
+ else if (name != null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + vhost + ",name=" + name + ",*";
+ else if (name == null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + vhost + ",*";
+ else
+ querystring = "org.apache.qpid:type=VirtualHost.Queue,*";
+ }
+
+ public int getmessagecount(ObjectName queue)
+ {
+ Number depth = null;
+
+ try
+ {
+ depth = (Number) mbsc.getAttribute(queue, ManagedQueue.ATTR_MSG_COUNT);
+
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ if (depth != null)
+ return depth.intValue();
+ else
+ return -1;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/UserManagementObject.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/UserManagementObject.java
new file mode 100644
index 0000000000..fd5bc0ca72
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/UserManagementObject.java
@@ -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.
+ *
+ */
+
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+public class UserManagementObject extends ObjectNames
+{
+ public UserManagementObject(MBeanServerConnection mbsc)
+ {
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+ querystring = "org.apache.qpid:type=UserManagement,*";
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/VirtualHostObject.java b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/VirtualHostObject.java
new file mode 100644
index 0000000000..77f8b66ac0
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/commands/objects/VirtualHostObject.java
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+public class VirtualHostObject extends ObjectNames
+{
+
+ public VirtualHostObject(MBeanServerConnection mbsc)
+ {
+ super(mbsc);
+ }
+
+ public void setQueryString(String object, String name, String vhost)
+ {
+ if (name != null && vhost == null)
+ querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,name=" + name + ",*";
+ else if (name != null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + vhost + ",name=" + name
+ + ",*";
+ else if (name == null && vhost != null)
+ querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + vhost + ",*";
+ else
+ querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,*";
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOption.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOption.java
new file mode 100644
index 0000000000..a443d6f789
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOption.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+import java.util.ArrayList;
+
+public class CommandLineOption implements CommandLineOptionConstants
+{
+ private String type;
+ private ArrayList optionValues;
+
+ public CommandLineOption(String type, String[] values)
+ {
+ setOptionType(type);
+ ArrayList arrayList = new ArrayList(values.length);
+ for (int i = 0; i < values.length; i++)
+ {
+ arrayList.add(values[i]);
+ }
+ this.optionValues = arrayList;
+ }
+
+ private void setOptionType(String type)
+ {
+ // cater for the long options first
+ if (type.startsWith("--"))
+ {
+ type = type.replaceFirst("--", "");
+ }
+ if (type.startsWith("-"))
+ {
+ type = type.replaceFirst("-", "");
+ }
+
+ // we do not change the case of the option!
+
+ this.type = type;
+ }
+
+ /**
+ * @param type
+ */
+ public CommandLineOption(String type, ArrayList values)
+ {
+ setOptionType(type);
+
+ if (null != values)
+ {
+ this.optionValues = values;
+ }
+ }
+
+ /**
+ * @return Returns the type.
+ * @see CommandLineOptionConstants
+ */
+ public String getOptionType()
+ {
+ return type;
+ }
+
+ /**
+ * @return Returns the optionValues.
+ */
+ public String getOptionValue()
+ {
+ if ((optionValues != null) && (optionValues.size() > 0))
+ {
+ return (String) optionValues.get(0);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @return Returns the optionValues.
+ */
+ public ArrayList getOptionValues()
+ {
+ return optionValues;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionConstants.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionConstants.java
new file mode 100644
index 0000000000..be82dbfcaa
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionConstants.java
@@ -0,0 +1,37 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+public interface CommandLineOptionConstants
+{
+ static interface JMXCommandLineOptionConstants
+ {
+ String HOST_OPTION = "h";
+ String PORT_OPTION = "p";
+ String INTERVAL_OPTION = "i";
+ String REPORT_OPTION = "r";
+ String USER_OPTION = "u";
+ String PASSWORD_OPTION = "w";
+
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionParser.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionParser.java
new file mode 100644
index 0000000000..fbf87bac01
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/CommandLineOptionParser.java
@@ -0,0 +1,231 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+public class CommandLineOptionParser
+{
+ private static int STARTED = 0;
+ private static int NEW_OPTION = 1;
+ private static int SUB_PARAM_OF_OPTION = 2;
+
+ private Map commandlineoption;
+ private String commandname;
+
+ public CommandLineOptionParser(Map commandlineoptions)
+ {
+ this.commandlineoption = commandlineoptions;
+ }
+
+ public CommandLineOptionParser(String[] args)
+ {
+ /* check whether user just type the enter key */
+ this.commandlineoption = this.parse(args);
+
+ }
+
+ public CommandLineOptionParser(String[] args, String first)
+ {
+ this.commandname = first;
+ this.commandlineoption = this.parsefirst(args);
+ }
+
+ public Map parse(String[] args)
+ {
+ Map commandLineOptions = new HashMap();
+
+ if (0 == args.length)
+ {
+ return commandLineOptions;
+ }
+ else if (1 == args.length)
+ {
+ commandname = args[0];
+ return commandLineOptions;
+ }
+ /* when user is not giving the command line option with a "=" */
+ // if (!args[2].startsWith("-"))
+ // return commandLineOptions;
+ // State 0 means started
+ // State 1 means earlier one was a new -option
+ // State 2 means earlier one was a sub param of a -option
+ int state = STARTED;
+ ArrayList optionBundle = null;
+ String optionType = null;
+ CommandLineOption commandLineOption;
+ String newcommand = "";
+ String[] newargs;
+ int j;
+ if (args[1].compareTo("list") == 0 || args[1].compareTo("info") == 0 || args[1].compareTo("delete") == 0
+ || args[1].compareTo("move") == 0 || args[1].compareTo("view") == 0
+ || args[1].compareTo("viewcontent") == 0)
+ {
+ String object = args[0];
+ for (j = 0; j < (args.length - 1); j++)
+ {
+ newcommand = newcommand + args[j + 1] + " ";
+ }
+ newcommand = newcommand + "-o " + object;
+ newargs = newcommand.split(" ");
+ args = newargs;
+ }
+ else if (!args[1].startsWith("-")) // if user give command like list
+ // queue or something without minus
+ // argument
+ return commandLineOptions; // for the second wordxi
+
+ commandname = args[0];
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].startsWith("-"))
+ {
+ if (STARTED == state)
+ {
+ // fresh one
+ state = NEW_OPTION;
+ optionType = args[i];
+ }
+ else if (SUB_PARAM_OF_OPTION == state || NEW_OPTION == state)
+ {
+ // new one but old one should be saved
+ commandLineOption = new CommandLineOption(optionType, optionBundle);
+ commandLineOptions.put(commandLineOption.getOptionType(), commandLineOption);
+ state = NEW_OPTION;
+ optionType = args[i];
+ optionBundle = null;
+
+ }
+ }
+ else
+ {
+ if (NEW_OPTION == state)
+ {
+ optionBundle = new ArrayList();
+ optionBundle.add(args[i]);
+ state = SUB_PARAM_OF_OPTION;
+
+ }
+ else if (SUB_PARAM_OF_OPTION == state)
+ {
+ optionBundle.add(args[i]);
+ }
+
+ }
+ }
+ commandLineOption = new CommandLineOption(optionType, optionBundle);
+ commandLineOptions.put(commandLineOption.getOptionType(), commandLineOption);
+ return commandLineOptions;
+
+ }
+
+ public Map parsefirst(String[] args)
+ {
+ Map commandLineOptions = new HashMap();
+ if (0 == args.length)
+ {
+ return commandLineOptions;
+ }
+ else if (1 == args.length)
+ {
+ return commandLineOptions;
+ }
+ /* when user is not giving the command line option with a "=" */
+ // if (!args[2].startsWith("-"))
+ // return commandLineOptions;
+ // State 0 means started
+ // State 1 means earlier one was a new -option
+ // State 2 means earlier one was a sub param of a -option
+ int state = STARTED;
+ ArrayList optionBundle = null;
+ String optionType = null;
+ CommandLineOption commandLineOption;
+ String newcommand = "";
+ String[] newargs;
+ int j;
+
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].startsWith("-"))
+ {
+ if (STARTED == state)
+ {
+ // fresh one
+ state = NEW_OPTION;
+ optionType = args[i];
+ }
+ else if (SUB_PARAM_OF_OPTION == state || NEW_OPTION == state)
+ {
+ // new one but old one should be saved
+ commandLineOption = new CommandLineOption(optionType, optionBundle);
+ commandLineOptions.put(commandLineOption.getOptionType(), commandLineOption);
+ state = NEW_OPTION;
+ optionType = args[i];
+ optionBundle = null;
+
+ }
+ }
+ else
+ {
+ if (NEW_OPTION == state)
+ {
+ optionBundle = new ArrayList();
+ optionBundle.add(args[i]);
+ state = SUB_PARAM_OF_OPTION;
+
+ }
+ else if (SUB_PARAM_OF_OPTION == state)
+ {
+ optionBundle.add(args[i]);
+ }
+
+ }
+ }
+ commandLineOption = new CommandLineOption(optionType, optionBundle);
+ commandLineOptions.put(commandLineOption.getOptionType(), commandLineOption);
+ return commandLineOptions;
+
+ }
+
+ public Map getAlloptions()
+ {
+ return this.commandlineoption;
+ }
+
+ public String getcommandname()
+ {
+ return this.commandname;
+ }
+
+ private static String removeSpaces(String s)
+ {
+ StringTokenizer st = new StringTokenizer(s, " ", false);
+ String t = "";
+ while (st.hasMoreElements())
+ t += st.nextElement();
+ return t;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfigProperty.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfigProperty.java
new file mode 100644
index 0000000000..55240054a9
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfigProperty.java
@@ -0,0 +1,29 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+public class JMXConfigProperty
+{
+
+ private static final String DEFAULT_HOST_NAME = "localhost";
+ private static final String DEFAULT_PORT = "8999";
+ private static final String DEFAULT_INTERVAL = "4000";
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfiguration.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfiguration.java
new file mode 100644
index 0000000000..76aab11e25
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXConfiguration.java
@@ -0,0 +1,182 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+import java.util.Map;
+
+public class JMXConfiguration
+{
+ private String hostname = "localhost";
+ private String port = "8999";
+ private String interval = "40000";
+ private String outputpath = ".";
+ private String report_file = "report.output";
+ private boolean isreport_mode = false;
+ private String username = null;
+ private String password = null;
+
+ public JMXConfiguration(Map map)
+ {
+ if (checkoptionsetting(CommandLineOptionConstants.JMXCommandLineOptionConstants.HOST_OPTION, map))
+ {
+ this.hostname = optionchecker(CommandLineOptionConstants.JMXCommandLineOptionConstants.HOST_OPTION, map);
+ }
+ if (checkoptionsetting(CommandLineOptionConstants.JMXCommandLineOptionConstants.PORT_OPTION, map))
+ {
+ this.port = optionchecker(CommandLineOptionConstants.JMXCommandLineOptionConstants.PORT_OPTION, map);
+ }
+ if (checkoptionsetting(CommandLineOptionConstants.JMXCommandLineOptionConstants.REPORT_OPTION, map))
+ {
+
+ this.report_file = optionchecker(CommandLineOptionConstants.JMXCommandLineOptionConstants.REPORT_OPTION,
+ map);
+ }
+ if (checkoptionsetting(CommandLineOptionConstants.JMXCommandLineOptionConstants.USER_OPTION, map))
+ {
+
+ this.setUsername(optionchecker(CommandLineOptionConstants.JMXCommandLineOptionConstants.USER_OPTION, map));
+ }
+
+ if (checkoptionsetting(CommandLineOptionConstants.JMXCommandLineOptionConstants.PASSWORD_OPTION, map))
+ {
+ this.setPassword(optionchecker(CommandLineOptionConstants.JMXCommandLineOptionConstants.PASSWORD_OPTION,
+ map));
+ }
+
+ }
+
+ public void sethostname(String hostname)
+ {
+ this.hostname = hostname;
+ }
+
+ public void setport(String port)
+ {
+ this.port = port;
+ }
+
+ public void setinterval(String interval)
+ {
+ this.interval = interval;
+ }
+
+ public void setoutputpath(String output)
+ {
+ this.outputpath = output;
+ }
+
+ public String gethostname()
+ {
+ return this.hostname;
+ }
+
+ public String getport()
+ {
+ return this.port;
+ }
+
+ public String getinterval()
+ {
+ return this.interval;
+ }
+
+ public String getoutputpath()
+ {
+ return this.outputpath;
+ }
+
+ public CommandLineOption loadoption(String option, Map options)
+ {
+ CommandLineOption op = null;
+ if (option != null)
+ {
+ op = (CommandLineOption) options.get(option);
+
+ }
+ return op;
+
+ }
+
+ public void setreportfile(String reportfile)
+ {
+ this.report_file = reportfile;
+ this.isreport_mode = true;
+
+ }
+
+ public boolean isreportmode()
+ {
+ return this.isreport_mode;
+ }
+
+ public String getreportfile()
+ {
+ return this.report_file;
+ }
+
+ public String optionchecker(String option_letter, Map map)
+ {
+
+ if (map == null)
+ return null;
+ CommandLineOption option = (CommandLineOption) map.get(option_letter);
+ if (option == null)
+ return null;
+ String value = option.getOptionValue();
+ return value;
+ }
+
+ public boolean checkoptionsetting(String option_letter, Map map)
+ {
+ if (map == null)
+ return false;
+ CommandLineOption option = (CommandLineOption) map.get(option_letter);
+ if (option == null)
+ return false;
+ String value = option.getOptionType();
+
+ if (value != null)
+ return true;
+ else
+ return false;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXinfo.java b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXinfo.java
new file mode 100644
index 0000000000..09de4a248f
--- /dev/null
+++ b/java/management/tools/qpid-cli/src/org/apache/qpid/utils/JMXinfo.java
@@ -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 org.apache.qpid.utils;
+
+import javax.management.remote.JMXConnector;
+import javax.management.MBeanServerConnection;
+
+public class JMXinfo
+{
+ private JMXConnector jmxconnector;
+ private CommandLineOptionParser input;
+ private MBeanServerConnection mbserverconnector;
+
+ public JMXinfo(JMXConnector jmxc, CommandLineOptionParser input, MBeanServerConnection mbsc)
+ {
+ this.jmxconnector = jmxc;
+ this.input = input;
+ this.mbserverconnector = mbsc;
+ }
+
+ public JMXConnector getjmxconnectot()
+ {
+ return jmxconnector;
+ }
+
+ public CommandLineOptionParser getCommandLineOptionParser()
+ {
+ return input;
+ }
+
+ public MBeanServerConnection getmbserverconnector()
+ {
+ return mbserverconnector;
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/AllTest.java b/java/management/tools/qpid-cli/test/org/apache/qpid/AllTest.java
new file mode 100644
index 0000000000..d9758245cd
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/AllTest.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.apache.qpid.commands.*;
+import org.apache.qpid.commands.objects.*;
+import org.apache.qpid.utils.TestCommandLineOption;
+import org.apache.qpid.utils.TestCommandLineOptionParser;
+import org.apache.qpid.utils.TestJMXConfiguration;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( { TestCommand.class, TestCommandExecutionEngine.class, TestCommandLineOption.class,
+ TestCommandLineOptionParser.class, TestConnector.class, TestJMXConfiguration.class, TestAllObject.class,
+ TestConnectionObject.class, TestExchangeObject.class, TestQueueObject.class, TestVirtualHostObject.class,
+ TestUserManagementObject.class, TestCommanddelete.class, TestCommandlist.class, TestCommandinfo.class,
+ TestCommandmove.class, TestCommandview.class, TestCommandviewcontent.class, TestCommandLineInterpreter.class
+
+})
+public class AllTest
+{
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/ConnectionConstants.java b/java/management/tools/qpid-cli/test/org/apache/qpid/ConnectionConstants.java
new file mode 100644
index 0000000000..90163460ce
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/ConnectionConstants.java
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid;
+
+public interface ConnectionConstants
+{
+ String BROKER_HOSTNAME = "localhost";
+ String BROKER_PORT = "8999";
+ String USERNAME = "guest";
+ String PASSWORD = "guest";
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandExecutionEngine.java b/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandExecutionEngine.java
new file mode 100644
index 0000000000..6889e8faad
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandExecutionEngine.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import java.io.IOException;
+
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXinfo;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommandExecutionEngine
+{
+ String line;
+ String[] command;
+ CommandLineOptionParser commandlineoptionparser;
+ JMXinfo info;
+ CommandExecutionEngine engine;
+ Connector connector;
+
+ @Before
+ public void setup() throws Exception
+ {
+
+ connector = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+
+ }
+
+ @Test
+ public void TestCommandSelector() throws Exception
+ {
+ line = "list -o queue";
+ command = line.split(" ");
+ commandlineoptionparser = new CommandLineOptionParser(command);
+ info = new JMXinfo(connector.getConnector(), commandlineoptionparser, connector.getMBeanServerConnection());
+ engine = new CommandExecutionEngine(info);
+ Assert.assertEquals(engine.CommandSelector(), true);
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ connector.getConnector().close();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandLineInterpreter.java b/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandLineInterpreter.java
new file mode 100644
index 0000000000..07344598bf
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/TestCommandLineInterpreter.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommandLineInterpreter
+{
+
+ // CommandLineInterpreter test = new CommandLineInterpreter();
+ /*
+ * In this class there are only methodes which are displaying data on
+ * console so no test can be written
+ */
+ String command = "-h " + ConnectionConstants.BROKER_HOSTNAME + " -p " + ConnectionConstants.BROKER_PORT
+ + " info -o queue -n ping -v test";
+ Connector conn = null;
+ JMXConnector jmxc = null;
+ MBeanServerConnection mbsc = null;
+ CommandLineOptionParser parser = null;
+
+ String[] args = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ args = command.split(" ");
+ // System.out.println(args[0]);
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ jmxc = conn.getConnector();
+ mbsc = conn.getMBeanServerConnection();
+ parser = new CommandLineOptionParser(args, args[0]);
+
+ }
+
+ @Test
+ public void TestSetQueryString() throws Exception
+ {
+ CommandLineInterpreter.oneshotmode(args, parser, jmxc, mbsc);
+ Assert.assertEquals(args[0], "info");
+ Assert.assertEquals(args[1], "-o");
+ Assert.assertEquals(args[2], "queue");
+ Assert.assertEquals(args[3], "-n");
+ Assert.assertEquals(args[4], "ping");
+ Assert.assertEquals(args[5], "-v");
+ Assert.assertEquals(args[6], "test");
+ }
+
+ @After
+ public void cleanup()
+ {
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/TestConnector.java b/java/management/tools/qpid-cli/test/org/apache/qpid/TestConnector.java
new file mode 100644
index 0000000000..ea450b5caa
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/TestConnector.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid;
+
+import java.io.IOException;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestConnector
+{
+ Connector test;
+ JMXServiceURL svc_url;
+ JMXConnector connector;
+ MBeanServerConnection mbsc;
+
+ @Before
+ public void setup() throws Exception
+ {
+ test = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ String url = "service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi";
+
+ }
+
+ @Test
+ public void testGetConnector()
+ {
+ Assert.assertEquals(test.getConnector(), test.getConnector());
+ }
+
+ @Test
+ public void testGetMBeanServerConnection()
+ {
+ Assert.assertEquals(test.getMBeanServerConnection(), test.getMBeanServerConnection());
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+
+ test.getConnector().close();
+ test = null;
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace(); // To change body of catch statement use File |
+ // Settings | File Templates.
+ }
+ test = null;
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/TestReportGenerator.java b/java/management/tools/qpid-cli/test/org/apache/qpid/TestReportGenerator.java
new file mode 100644
index 0000000000..c14f4bb1bb
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/TestReportGenerator.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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 org.apache.qpid;
+
+public class TestReportGenerator
+{
+
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommand.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommand.java
new file mode 100644
index 0000000000..085d7220e9
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommand.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.commands;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.Command;
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXinfo;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommand
+{
+ String command = "list -o queue";
+ String[] list;
+ Connector test;
+ MBeanServerConnection mbsc;
+ JMXinfo info;
+ CommandLineOptionParser parser;
+ Command cmd;
+
+ @Before
+ public void setup() throws Exception
+ {
+ list = command.split(" ");
+ parser = new CommandLineOptionParser(list);
+ test = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ info = new JMXinfo(test.getConnector(), parser, test.getMBeanServerConnection());
+ cmd = new Commandinfo(info);
+
+ }
+
+ @Test
+ public void TestOptionChecker()
+ {
+ Assert.assertEquals(cmd.optionchecker("o"), "queue");
+ }
+
+ @Test
+ public void TestCheckOptionSetting()
+ {
+ Assert.assertEquals(cmd.checkoptionsetting("o"), true);
+ Assert.assertEquals(cmd.checkoptionsetting("p"), false);
+ }
+
+ @After
+ public void cleanup()
+ {
+ parser = null;
+ test = null;
+ info = null;
+ cmd = null;
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommanddelete.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommanddelete.java
new file mode 100644
index 0000000000..60249c6940
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommanddelete.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.commands;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.Assert;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.utils.JMXinfo;
+import org.apache.qpid.utils.CommandLineOptionParser;
+
+import javax.management.remote.JMXConnector;
+import javax.management.MBeanServerConnection;
+
+public class TestCommanddelete
+{
+ JMXinfo info = null;
+ String command = "delete -o queue -n ping -v test -t 1";
+ Commanddelete delete = null;
+ Connector conn;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ delete = new Commanddelete(info);
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ delete.execute();
+ Assert.assertEquals(delete.getObject(), "queue");
+ Assert.assertEquals(delete.getVirtualhost(), "test");
+ Assert.assertEquals(delete.getName(), "ping");
+ Assert.assertEquals(delete.getnumber(), 1);
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandinfo.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandinfo.java
new file mode 100644
index 0000000000..24263eea73
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandinfo.java
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.utils.JMXinfo;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.ConnectionConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Assert;
+import org.junit.After;
+
+import javax.management.remote.JMXConnector;
+import javax.management.MBeanServerConnection;
+
+public class TestCommandinfo
+{
+ JMXinfo info = null;
+ String command = "info -o queue -n ping -v test";
+ CommandImpl infocommand = null;
+ Connector conn = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ infocommand = new Commandinfo(info);
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ infocommand.execute();
+ Assert.assertEquals(infocommand.getObject(), "queue");
+ Assert.assertEquals(infocommand.getVirtualhost(), "test");
+ Assert.assertEquals(infocommand.getName(), "ping");
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandlist.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandlist.java
new file mode 100644
index 0000000000..ac759889fd
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandlist.java
@@ -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.
+ *
+ */
+package org.apache.qpid.commands;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXinfo;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommandlist
+{
+ /*
+ * All the methods in Commandlist doesn't have any arguments and no return
+ * type.
+ */
+ JMXinfo info = null;
+ String command = "list -o queue -n ping -v test";
+ Commandlist list = null;
+ Connector conn = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ list = new Commandlist(info);
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ list.execute();
+ Assert.assertEquals(list.getObject(), "queue");
+ Assert.assertEquals(list.getVirtualhost(), "test");
+ Assert.assertEquals(list.getName(), "ping");
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandmove.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandmove.java
new file mode 100644
index 0000000000..3ff7890662
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandmove.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXinfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.After;
+import org.junit.Assert;
+
+import javax.management.remote.JMXConnector;
+import javax.management.MBeanServerConnection;
+
+public class TestCommandmove
+{
+ JMXinfo info = null;
+ String command = "move -o queue -n1 ping -v1 test -n2 message_queue -fmid 10 -tmid 12";
+ Commandmove move = null;
+ Connector conn = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ move = new Commandmove(info);
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ move.execute();
+ Assert.assertEquals(move.getObject(), "queue");
+ Assert.assertEquals(move.getVirtualhost(), "test");
+ Assert.assertEquals(move.getname1(), "ping");
+ Assert.assertEquals(move.getname2(), "message_queue");
+ Assert.assertEquals(move.getfmid(), 10);
+ Assert.assertEquals(move.gettmid(), 12);
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandview.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandview.java
new file mode 100644
index 0000000000..f46b8626b8
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandview.java
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.Connector;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.utils.JMXinfo;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Assert;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+
+public class TestCommandview
+{
+ JMXinfo info = null;
+ String command = "view -o queue -n ping -v test -t 10";
+ Commandview view = null;
+ Connector conn = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ view = new Commandview(info);
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ view.execute();
+ Assert.assertEquals(view.getObject(), "queue");
+ Assert.assertEquals(view.getVirtualhost(), "test");
+ Assert.assertEquals(view.getName(), "ping");
+ Assert.assertEquals(view.getnumber(), 10);
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandviewcontent.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandviewcontent.java
new file mode 100644
index 0000000000..f4a8f22aff
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/TestCommandviewcontent.java
@@ -0,0 +1,78 @@
+/*
+ *
+ * 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 org.apache.qpid.commands;
+
+import org.apache.qpid.utils.JMXinfo;
+import org.apache.qpid.utils.CommandLineOptionParser;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.apache.qpid.ConnectionConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.After;
+import org.junit.Assert;
+
+import javax.management.remote.JMXConnector;
+import javax.management.MBeanServerConnection;
+
+public class TestCommandviewcontent
+{
+ JMXinfo info = null;
+ String command = "viewcontent -o queue -n ping -v test -id 10";
+ Commandviewcontent viewcontent = null;
+ Connector conn = null;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ JMXConnector jmxc = conn.getConnector();
+ MBeanServerConnection mbsc = conn.getMBeanServerConnection();
+ CommandLineOptionParser parser = new CommandLineOptionParser(command.split(" "));
+ info = new JMXinfo(jmxc, parser, mbsc);
+ viewcontent = new Commandviewcontent(info);
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ viewcontent.execute();
+ Assert.assertEquals(viewcontent.getObject(), "queue");
+ Assert.assertEquals(viewcontent.getnumber(), 10);
+ Assert.assertEquals(viewcontent.getName(), "ping");
+ Assert.assertEquals(viewcontent.getVirtualhost(), "test");
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestAllObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestAllObject.java
new file mode 100644
index 0000000000..af993e9205
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestAllObject.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestAllObject {
+ Connector conn;
+ MBeanServerConnection mbsc;
+ AllObjects test;
+ String test1,test2;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME,ConnectionConstants.BROKER_PORT, ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new AllObjects(mbsc);
+ test1 = "empty input1";
+ test2 = "empty input2";
+
+
+ }
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test1,test2);
+ Assert.assertEquals(test.querystring,"org.apache.qpid:*");
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try{
+ conn.getConnector().close();
+ }catch(Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestConnectionObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestConnectionObject.java
new file mode 100644
index 0000000000..f91a519108
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestConnectionObject.java
@@ -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.
+ *
+ */
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestConnectionObject
+{
+ Connector conn;
+ MBeanServerConnection mbsc;
+ ConnectionObject test;
+ String test1, test2, test3;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new ConnectionObject(mbsc);
+ test1 = "ping";
+ test2 = "test";
+ test3 = "object";
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test3, test1, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=Connection,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=Connection,VirtualHost=test,*");
+ test.querystring = null;
+ test.setQueryString(test3, test1, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=Connection,VirtualHost=test,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=Connection,*");
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestExchangeObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestExchangeObject.java
new file mode 100644
index 0000000000..5ffbe9854f
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestExchangeObject.java
@@ -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.
+ *
+ */
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestExchangeObject
+{
+ Connector conn;
+ MBeanServerConnection mbsc;
+ ExchangeObject test;
+ String test1, test2, test3;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new ExchangeObject(mbsc);
+ test1 = "ping";
+ test2 = "test";
+ test3 = "object";
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test3, test1, null);
+ // System.out.println(test.querystring);
+ // System.out.println("org.apache.qpid:type=VitualHost.Exchange,name=ping,*");
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Exchange,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=test,*");
+ test.querystring = null;
+ test.setQueryString(test3, test1, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=test,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, null);
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestObjectNames.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestObjectNames.java
new file mode 100644
index 0000000000..600c567368
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestObjectNames.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+public class TestObjectNames
+{
+
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestQueueObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestQueueObject.java
new file mode 100644
index 0000000000..fb7f42e1ae
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestQueueObject.java
@@ -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.
+ *
+ */
+package org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestQueueObject
+{
+ Connector conn;
+ MBeanServerConnection mbsc;
+ QueueObject test;
+ String test1, test2, test3;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new QueueObject(mbsc);
+ test1 = "ping";
+ test2 = "test";
+ test3 = "object";
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test3, test1, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Queue,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,*");
+ test.querystring = null;
+ test.setQueryString(test3, test1, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.Queue,*");
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestUserManagementObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestUserManagementObject.java
new file mode 100644
index 0000000000..863bf62311
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestUserManagementObject.java
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestUserManagementObject
+{
+ Connector conn;
+ MBeanServerConnection mbsc;
+ UserManagementObject test;
+ String test1, test2, test3;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new UserManagementObject(mbsc);
+ test1 = "ping";
+ test2 = "test";
+ test3 = "object";
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test3, test1, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=UserManagement,*");
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestVirtualHostObject.java b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestVirtualHostObject.java
new file mode 100644
index 0000000000..29c4db30a5
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/commands/objects/TestVirtualHostObject.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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 org.apache.qpid.commands.objects;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.ConnectionConstants;
+import org.apache.qpid.Connector;
+import org.apache.qpid.ConnectorFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestVirtualHostObject
+{
+ Connector conn;
+ MBeanServerConnection mbsc;
+ VirtualHostObject test;
+ String test1, test2, test3;
+
+ @Before
+ public void startup() throws Exception
+ {
+ conn = ConnectorFactory.getConnector(ConnectionConstants.BROKER_HOSTNAME, ConnectionConstants.BROKER_PORT,
+ ConnectionConstants.USERNAME, ConnectionConstants.PASSWORD);
+ mbsc = conn.getMBeanServerConnection();
+ test = new VirtualHostObject(mbsc);
+ test1 = "ping";
+ test2 = "test";
+ test3 = "object";
+
+ }
+
+ @Test
+ public void TestSetQueryString()
+ {
+ test.setQueryString(test3, test1, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.VirtualHostManager,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, test2);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=test,*");
+ test.querystring = null;
+ test.setQueryString(test3, test1, test2);
+ Assert.assertEquals(test.querystring,
+ "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=test,name=ping,*");
+ test.querystring = null;
+ test.setQueryString(test3, null, null);
+ Assert.assertEquals(test.querystring, "org.apache.qpid:type=VirtualHost.VirtualHostManager,*");
+
+ }
+
+ @After
+ public void cleanup()
+ {
+ try
+ {
+ conn.getConnector().close();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOption.java b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOption.java
new file mode 100644
index 0000000000..e2a03f52ad
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOption.java
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommandLineOption
+{
+ String input1;
+ String input2;
+ String options;
+ String[] list;
+ CommandLineOption option;
+
+ @Before
+ public void setup()
+ {
+ input1 = "-h";
+ input2 = "--help";
+ options = "localhost testing";
+ list = options.split(" ");
+ option = new CommandLineOption(input1, list);
+
+ }
+
+ @Test
+ public void TestGetOptinValue()
+ {
+ Assert.assertEquals(option.getOptionValue(), "localhost");
+ }
+
+ @Test
+ public void TestGetOptionType()
+ {
+ Assert.assertEquals(option.getOptionType(), "h");
+ }
+
+ @After
+ public void cleanup()
+ {
+ option = null;
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOptionParser.java b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOptionParser.java
new file mode 100644
index 0000000000..964c350fc5
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestCommandLineOptionParser.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestCommandLineOptionParser
+{
+ CommandLineOptionParser parser;
+ String[] input;
+ CommandLineOption option1;
+ CommandLineOption option2;
+ ArrayList list1;
+ ArrayList list2;
+
+ @Before
+ public void setup()
+ {
+ String temp = "run -h localhost -p 23232";
+ input = temp.split(" ");
+ parser = new CommandLineOptionParser(input);
+ list1 = new ArrayList();
+ list2 = new ArrayList();
+ }
+
+ @Test
+ public void TestParse()
+ {
+ Map hash = new HashMap();
+
+ list1.add("localhost");
+ list2.add("23232");
+ option1 = new CommandLineOption("h", list1);
+ option2 = new CommandLineOption("p", list2);
+ hash.put("h", option1);
+ hash.put("p", option2);
+ option1 = (CommandLineOption) parser.parse(input).get("h");
+ Assert.assertEquals(option1.getOptionType(), "h");
+ Assert.assertEquals(option1.getOptionValue(), "localhost");
+ option1 = (CommandLineOption) parser.parse(input).get("p");
+ Assert.assertEquals(option1.getOptionType(), "p");
+ Assert.assertEquals(option1.getOptionValue(), "23232");
+ Assert.assertEquals(parser.parse(input).size(), hash.size());
+ }
+
+ @After
+ public void cleanup()
+ {
+ parser = null;
+ option1 = null;
+ option2 = null;
+
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfigProperty.java b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfigProperty.java
new file mode 100644
index 0000000000..20234d1153
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfigProperty.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+public class TestJMXConfigProperty
+{
+
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfiguration.java b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfiguration.java
new file mode 100644
index 0000000000..40cde00953
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXConfiguration.java
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 org.apache.qpid.utils;
+
+import java.util.ArrayList;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestJMXConfiguration
+{
+ CommandLineOptionParser clop;
+ JMXConfiguration jmc;
+ CommandLineOption option;
+ String[] input;
+
+ @Before
+ public void setup()
+ {
+ String temp = "command -h 127.0.0.1 -p 1234";
+ input = temp.split(" ");
+ clop = new CommandLineOptionParser(input);
+ jmc = new JMXConfiguration(clop.getAlloptions());
+ }
+
+ @Test
+ public void TestLoadOption()
+ {
+ ArrayList list = new ArrayList();
+ list.add("127.0.0.1");
+ option = new CommandLineOption("-h", list);
+ CommandLineOption expect = jmc.loadoption("h", clop.getAlloptions());
+ Assert.assertEquals(expect.getOptionType(), option.getOptionType());
+ Assert.assertEquals(expect.getOptionValue(), option.getOptionValue());
+ }
+
+ @After
+ public void cleanup()
+ {
+ clop = null;
+ jmc = null;
+ option = null;
+ }
+}
diff --git a/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXinfo.java b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXinfo.java
new file mode 100644
index 0000000000..aae39bcb37
--- /dev/null
+++ b/java/management/tools/qpid-cli/test/org/apache/qpid/utils/TestJMXinfo.java
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.utils;
+
+public class TestJMXinfo
+{
+ /*
+ * this class is having only three simple getter methods. Therefore no
+ * testcases
+ */
+}
diff --git a/java/maven-settings.xml b/java/maven-settings.xml
deleted file mode 100644
index 985f39b6f1..0000000000
--- a/java/maven-settings.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<settings>
-</settings>
diff --git a/java/module.xml b/java/module.xml
index 349fb91e4a..d3954a1544 100644
--- a/java/module.xml
+++ b/java/module.xml
@@ -66,8 +66,6 @@
<property name="module.release.bz2" location="${module.release}/${module.namever}.tar.bz2"/>
<property name="module.genpom.args" value=""/>
- <property name="maven.remote.repo" value="file://${module.release.base}/maven"/>
-
<property name="broker.log.prefix" value="BROKER: "/>
<property name="broker.log.interleave" value="true"/>
@@ -77,7 +75,6 @@
<property name="module.coverage" location="${module.build}/coverage"/>
<property name="cobertura.datafile" location="${module.instrumented}/cobetura.ser"/>
-
<available property="module.test.src.exists" file="${module.test.src}"/>
<available property="module.etc.exists" file="${module.etc}"/>
<available property="module.bin.exists" file="${module.bin}"/>
@@ -207,6 +204,7 @@
<mkdir dir="${build.etc}"/>
<mkdir dir="${build.lib}"/>
<mkdir dir="${build.results}"/>
+ <mkdir dir="${build.data}"/>
<mkdir dir="${build.plugins}"/>
<mkdir dir="${module.classes}"/>
<mkdir dir="${module.precompiled}"/>
@@ -222,8 +220,8 @@
<arg line='"${project.root}/genpom"'/>
<arg line='-s "${project.root}/lib/poms"'/>
<arg line='-o "${build.scratch}/qpid-${module.name}.pom"'/>
- <arg line="-u ${project.url}"/>
- <arg line="-g ${project.groupid}"/>
+ <arg line="-u http://qpid.apache.org"/>
+ <arg line="-g org.apache.qpid"/>
<arg line="-v ${project.version}${maven.version.suffix}"/>
<arg line="-p qpid"/>
<arg line='-m "${module.depends}"'/>
@@ -239,14 +237,14 @@
<artifact:pom id="module.pom" file="${build.scratch}/qpid-${module.name}.pom"/>
- <artifact:install file="${module.jar}" pomRefId="module.pom" settingsFile="${maven.settings.xml}">
+ <artifact:install file="${module.jar}" pomRefId="module.pom">
<localRepository path="${maven.local.repo}"/>
</artifact:install>
- <artifact:deploy file="${module.jar}" pomRefId="module.pom" uniqueVersion="${maven.unique.version}" settingsFile="${maven.settings.xml}">
+ <artifact:deploy file="${module.jar}" pomRefId="module.pom" uniqueVersion="${maven.unique.version}">
<attach file="${module.source.jar}" classifier="sources"/>
<localRepository path="${maven.local.repo}"/>
- <remoteRepository url="${maven.remote.repo}"/>
+ <remoteRepository url="file://${module.release.base}/maven"/>
</artifact:deploy>
</target>
@@ -280,8 +278,7 @@
<javac target="${java.target}" source="${java.source}"
destdir="${module.test.classes}" debug="on"
deprecation="${javac.deprecation}"
- srcdir="${module.test.src}"
- includeantruntime="false">
+ srcdir="${module.test.src}">
<classpath refid="module.test.path"/>
</javac>
@@ -295,7 +292,7 @@
</target>
- <property name="profile" value="java-mms.0-10"/>
+ <property name="profile" value="default"/>
<property name="testprofile.file" value="${test.profiles}/${profile}.testprofile"/>
<available file="${testprofile.file}" property="testprofile.file.present"/>
@@ -303,29 +300,29 @@
<property file="${testprofile.file}" prefix="preload"/>
<property name="preload.include" value=""/>
- <property name="profiles" value="${preload.include} ${profile}"/>
+ <condition property="profiles"
+ value="${preload.include} ${profile}"
+ else="default ${preload.include} ${profile}">
+ <equals arg1="${profile}" arg2="default"/>
+ </condition>
<map property="_profile_files" value="${profiles}" join=" ">
<globmapper from="*" to="*.testprofile"/>
</map>
-
- <delete file="${build.scratch}/test-${profile}.properties" quiet="true"/>
<concat destfile="${build.scratch}/test-${profile}.properties" force="no" fixlastline="yes">
- <filelist dir="${test.profiles}" files="testprofile.defaults"/>
<filelist dir="${test.profiles}" files="${_profile_files}"/>
</concat>
<property file="${build.scratch}/test-${profile}.properties"/>
<map property="test.excludefiles" value="${test.excludes}">
- <globmapper from="*" to="${test.profiles}/*;"/>
+ <globmapper from="*" to="${test.profiles}/*"/>
</map>
+
<condition property="dontruntest" value="dontruntest" else="runtest">
<contains substring="${module.name}" string="${exclude.modules}" />
</condition>
<property name="jvm.args" value=""/>
- <property name="broker.existing.qpid.work" value=""/>
-
<target name="test" depends="build,compile-tests" if="module.test.src.exists"
unless="${dontruntest}" description="execute unit tests">
@@ -334,8 +331,7 @@
<echo message="Using profile:${profile}" level="info"/>
<junit fork="yes" forkmode="once" maxmemory="${test.mem}" reloading="no"
haltonfailure="${haltonfailure}" haltonerror="${haltonerror}"
- failureproperty="test.failures" printsummary="on" timeout="6000000"
- dir="${project.root}" >
+ failureproperty="test.failures" printsummary="on" timeout="6000000" >
<jvmarg line="${jvm.args}" />
@@ -347,6 +343,14 @@
<sysproperty key="log4j.configuration" value="${log4j.configuration}"/>
<sysproperty key="java.naming.factory.initial" value="${java.naming.factory.initial}"/>
<sysproperty key="java.naming.provider.url" value="${java.naming.provider.url}"/>
+ <sysproperty key="broker" value="${broker}"/>
+ <sysproperty key="broker.clean" value="${broker.clean}"/>
+ <sysproperty key="broker.clean.between.tests" value="${broker.clean.between.tests}"/>
+ <sysproperty key="broker.persistent" value="${broker.persistent}"/>
+ <sysproperty key="broker.version" value="${broker.version}"/>
+ <sysproperty key="broker.ready" value="${broker.ready}" />
+ <sysproperty key="broker.stopped" value="${broker.stopped}" />
+ <sysproperty key="broker.config" value="${broker.config}" />
<sysproperty key="messagestore.class.name" value="${messagestore.class.name}" />
<sysproperty key="test.output" value="${module.results}"/>
<sysproperty key="qpid.amqp.version" value="${qpid.amqp.version}"/>
@@ -397,15 +401,6 @@
</target>
- <target name="report-module" description="generate junit reports for each module">
- <junitreport todir="${module.results}">
- <fileset dir="${module.results}">
- <include name="TEST-*.xml"/>
- </fileset>
- <report format="frames" todir="${module.results}/report/html"/>
- </junitreport>
- </target>
-
<target name="touch-failed" if="test.failures">
<touch file="${module.failed}"/>
<touch file="${build.failed}"/>
@@ -652,6 +647,9 @@
<fileset dir="${module.classes}">
<include name="**/*.class"/>
</fileset>
+ <fileset dir="${module.test.classes}">
+ <include name="**/*.class"/>
+ </fileset>
</cobertura-instrument>
</target>
@@ -660,8 +658,7 @@
<mkdir dir="${build.coveragereport}" />
<junit fork="yes" forkmode="once" maxmemory="${test.mem}" reloading="no"
haltonfailure="${haltonfailure}" haltonerror="${haltonerror}"
- failureproperty="test.failures" printsummary="on" timeout="600000"
- dir="${project.root}" >
+ failureproperty="test.failures" printsummary="on" timeout="600000" >
<sysproperty key="amqj.logging.level" value="${amqj.logging.level}"/>
<sysproperty key="amqj.protocol.logging.level" value="${amqj.protocol.logging.level}"/>
@@ -671,6 +668,7 @@
<sysproperty key="java.naming.factory.initial" value="${java.naming.factory.initial}"/>
<sysproperty key="java.naming.provider.url" value="${java.naming.provider.url}"/>
<sysproperty key="broker" value="${broker}"/>
+ <sysproperty key="broker.clean" value="${broker.clean}"/>
<sysproperty key="broker.version" value="${broker.version}"/>
<sysproperty key="broker.ready" value="${broker.ready}" />
<sysproperty key="test.output" value="${module.results}"/>
@@ -816,84 +814,4 @@ qpid.name=${project.name}
<touch file="${velocity.timestamp}" />
</target>
- <target name="eclipse" depends="eclipse-setup,eclipse-project,eclipse-source-only,eclipse-source-and-test"/>
-
- <target name="eclipse-setup">
- <taskdef name="eclipse" classname="prantl.ant.eclipse.EclipseTask" />
-
- <!-- Build set of directories representing the dependencies -->
-
- <dirset id="eclipse.required.projectdirs.path" dir="${project.root}" includes="${module.depends} ${module.test.depends} neverBeEmpty">
- <!-- Select only those projects from module.depends that contain a build.xml. This serves to exclude dependencies that
- don't become Eclipse projects e.g. broker-plugins and common-tests -->
- <present targetdir="${project.root}">
- <mapper type="glob" from="*" to="*/build.xml"/>
- </present>
- </dirset>
-
- <!-- Convert from the set of directories into Eclipse project names proceeded by forward slashes -->
-
- <pathconvert property="eclipse.required.projectnames" refid="eclipse.required.projectdirs.path" pathsep=" " dirsep="-">
- <map from="${project.root}${file.separator}" to=''/>
- </pathconvert>
- <map property="eclipse.required.slashedprojectnames" value="${eclipse.required.projectnames}" join="${path.separator}">
- <globmapper from="*" to="/*"/>
- </map>
-
- <echo message="Ant module dependencies : ${module.depends} ${module.test.depends} converted to Eclipse required project(s): ${eclipse.required.slashedprojectnames}"/>
- <path id="eclipse.required.slashedprojectnames.path">
- <pathelement path="${eclipse.required.slashedprojectnames}"/>
- </path>
- </target>
-
- <!-- Create the Eclipse .project -->
- <target name="eclipse-project">
- <eclipse updatealways="${eclipse.updatealways}">
- <project name="${module.name}"/>
-
- <!-- If the Eclipse task were to ever support the generation of
- linked resources, we would configure it to generate
- the following:
-
- scratch_src -> ${module.precompiled}
-
- in each project. This would avoid the 'linked sources'
- manual step documented on the Wiki.
- -->
- </eclipse>
- </target>
-
- <!-- Create the Eclipse .classpath -->
- <target name="eclipse-source-only" unless="module.test.src.exists">
- <eclipse updatealways="${eclipse.updatealways}">
- <settings>
- <jdtcore compilercompliance="${eclipse.compilercompliance}" />
- </settings>
- <classpath>
- <container path="${eclipse.container}" />
- <source path="${module.src}" />
- <source pathref="eclipse.required.slashedprojectnames.path" />
- <library pathref="module.libs"/>
- <output path="classes" />
- </classpath>
- </eclipse>
- </target>
-
- <!-- Create the Eclipse .classpath -->
- <target name="eclipse-source-and-test" if="module.test.src.exists">
- <eclipse updatealways="${eclipse.updatealways}">
- <settings>
- <jdtcore compilercompliance="${eclipse.compilercompliance}" />
- </settings>
- <classpath>
- <container path="${eclipse.container}" />
- <source path="${module.src}" />
- <source path="${module.test.src}" />
- <source pathref="eclipse.required.slashedprojectnames.path" />
- <library pathref="module.libs"/>
- <library pathref="module.test.libs"/>
- <output path="classes" />
- </classpath>
- </eclipse>
- </target>
</project>
diff --git a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java b/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
index d94ca5592b..3ad6c021bd 100644
--- a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
+++ b/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
@@ -20,6 +20,9 @@
*/
package org.apache.qpid.client.message;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.SimpleByteBufferAllocator;
+
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.ObjectMessage;
diff --git a/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java b/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java
index 76fd318625..cac0064785 100644
--- a/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java
+++ b/java/perftests/src/main/java/org/apache/qpid/config/AMQConnectionFactoryInitialiser.java
@@ -21,11 +21,8 @@
package org.apache.qpid.config;
import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.config.ConnectionFactoryInitialiser;
import org.apache.qpid.config.ConnectorConfig;
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.url.URLSyntaxException;
import javax.jms.ConnectionFactory;
@@ -33,15 +30,6 @@ class AMQConnectionFactoryInitialiser implements ConnectionFactoryInitialiser
{
public ConnectionFactory getFactory(ConnectorConfig config)
{
- try
- {
- final ConnectionURL connectionUrl = new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL +
- "://guest:guest@/test_path?brokerlist='tcp://" + config.getHost() + ":" + config.getPort() + "'");
- return new AMQConnectionFactory(connectionUrl);
- }
- catch (URLSyntaxException e)
- {
- throw new RuntimeException("Problem building URL", e);
- }
+ return new AMQConnectionFactory(config.getHost(), config.getPort(), "/test_path");
}
}
diff --git a/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java b/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
new file mode 100644
index 0000000000..e2e97ab6f8
--- /dev/null
+++ b/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
@@ -0,0 +1,207 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import org.apache.qpid.junit.extensions.TestThreadAware;
+import org.apache.qpid.junit.extensions.TimingController;
+import org.apache.qpid.junit.extensions.TimingControllerAware;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import java.util.LinkedList;
+
+/**
+ * MessageThroughputPerf runs a test over a {@link Circuit} controlled by the test parameters. It logs timings of
+ * the time required to receive samples consisting of batches of messages.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Measure message throughput accross a test circuit. <td> {@link Circuit}
+ * </table>
+ *
+ * @todo Check that all of the messages were sent. Check that the receiving end got the same number of messages as
+ * the publishing end.
+ *
+ * @todo Set this up to run with zero sized tests. Size zero means send forever. Continuous sending to be interrupted
+ * by completion of the test duration, or shutdown hook when the user presses Ctrl-C.
+ */
+public class MessageThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(MessageThroughputPerf.class);
+
+ /** Holds the timing controller, used to log test timings from self-timed tests. */
+ private TimingController timingController;
+
+ /** Thread local to hold the per-thread test setup fields. */
+ ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public MessageThroughputPerf(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the a basic P2P test case.
+ *
+ * @param numMessages The number of messages to send in the test.
+ */
+ public void testThroughput(int numMessages)
+ {
+ log.debug("public void testThroughput(): called");
+
+ PerThreadSetup setup = threadSetup.get();
+ assertNoFailures(setup.testCircuit.test(numMessages, new LinkedList<Assertion>()));
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as known to the test
+ * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ * name "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ log.debug("public String getTestCaseNameForTestMethod(String methodName = " + methodName + "): called");
+
+ return "DEFAULT_CIRCUIT_TEST";
+ }
+
+ /**
+ * Used by test runners that can supply a {@link org.apache.qpid.junit.extensions.TimingController} to set the
+ * controller on an aware test.
+ *
+ * @param controller The timing controller.
+ */
+ public void setTimingController(TimingController controller)
+ {
+ timingController = controller;
+ }
+
+ /**
+ * Overrides the parent setUp method so that the in-vm broker creation is not done on a per test basis.
+ *
+ * @throws Exception Any exceptions allowed to fall through and fail the test.
+ */
+ protected void setUp() throws Exception
+ {
+ NDC.push(getName());
+
+ setTestProps(TestContextProperties.getInstance(MessagingTestConfigProperties.defaults));
+ }
+
+ /**
+ * Overrides the parent setUp method so that the in-vm broker clean-up is not done on a per test basis.
+ */
+ protected void tearDown()
+ {
+ NDC.pop();
+ }
+
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ // Run the test setup tasks. This may create an in-vm broker, if a decorator has injected a task for this.
+ getTaskHandler().runSetupTasks();
+
+ // Get the test parameters, any overrides on the command line will have been applied.
+ ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ // Customize the test parameters.
+ testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST");
+ testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue");
+
+ // Get the test circuit factory to create test circuits and run the standard test procedure through.
+ CircuitFactory circuitFactory = getCircuitFactory();
+
+ // Create the test circuit. This projects the circuit onto the available test nodes and connects it up.
+ Circuit testCircuit = circuitFactory.createCircuit(null, testProps);
+
+ // Store the test configuration for the thread.
+ PerThreadSetup setup = new PerThreadSetup();
+ setup.testCircuit = testCircuit;
+ threadSetup.set(setup);
+ }
+
+ /**
+ * Called after all threads have completed their setup.
+ */
+ public void postThreadSetUp()
+ {
+ //Nothing to do here, potentially implement preFill as per PingTestPerf.
+ }
+
+ /**
+ * Called when a test thread is destroyed.
+ */
+ public void threadTearDown()
+ {
+ // Run the test teardown tasks. This may destroy the in-vm broker, if a decorator has injected a task for this.
+ getTaskHandler().runSetupTasks();
+ }
+
+ /**
+ * Holds the per-thread test configurations.
+ */
+ protected static class PerThreadSetup
+ {
+ /** Holds the test circuit to run tests on. */
+ Circuit testCircuit;
+ }
+
+ /**
+ * Compiles all the tests in this class into a suite.
+ *
+ * @return The test suite.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Qpid Throughput Performance Tests");
+
+ suite.addTest(new MessageThroughputPerf("testThroughput"));
+
+ return suite;
+ }
+}
diff --git a/java/resources/NOTICE b/java/resources/NOTICE
index add7753a4b..607c1c1580 100644
--- a/java/resources/NOTICE
+++ b/java/resources/NOTICE
@@ -10,6 +10,13 @@ available from
http://www.slf4j.org/
+Concurrency utlitity classes are provided by the backport-util-concurrent
+library package, which is open source software, written by
+Dawid Kurzyniec, and copyright by Distributed Computing Laboratory,
+Emory University. The original software is available from
+
+ http://dcl.mathcs.emory.edu/util/backport-util-concurrent/
+
Data compression support is provided by the JZLib library package,
which is open source software, written by JCraft, and copyright
by JCraft. The original software is available from
diff --git a/java/systests/build.xml b/java/systests/build.xml
index fb2bae1d47..1da0a6d355 100644
--- a/java/systests/build.xml
+++ b/java/systests/build.xml
@@ -19,18 +19,10 @@ nn - or more contributor license agreements. See the NOTICE file
-
-->
<project name="System Tests" default="build">
-
- <condition property="systests.optional.depends" value="bdbstore" else="">
- <and>
- <contains string="${modules.opt}" substring="bdbstore"/>
- <contains string="${profile}" substring="bdb"/>
- </and>
- </condition>
-
- <property name="module.depends" value="client management/common broker broker/test common common/test junit-toolkit ${systests.optional.depends}"/>
+ <property name="module.depends" value="client management/tools/qpid-cli management/common broker broker/test common common/test junit-toolkit"/>
<property name="module.test.src" location="src/main/java"/>
<property name="module.test.excludes"
- value="**/DropInTest.java,**/TestClientControlledTest.java"/>
+ value="**/TTLTest.java,**/DropInTest.java,**/TestClientControlledTest.java"/>
<import file="../module.xml"/>
diff --git a/java/systests/etc/config-systests-ServerConfigurationTest-New.xml b/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
new file mode 100644
index 0000000000..d1dce019dd
--- /dev/null
+++ b/java/systests/etc/config-systests-ServerConfigurationTest-New.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+
+<broker>
+ <work>${QPID_WORK}</work>
+ <conf>${QPID_HOME}/etc</conf>
+ <passwordDir>${conf}</passwordDir>
+ <plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory>
+ <cache-directory>${QPID_WORK}/cache</cache-directory>
+ <connector>
+ <transport>nio</transport>
+ <port>5672</port>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>false</enabled>
+ <jmxport>8999</jmxport>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${passwordDir}/passwd</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <jmx>
+ <access>${passwordDir}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
+ </security>
+
+ <virtualhosts>${conf}/virtualhosts-ServerConfigurationTest-New.xml</virtualhosts>
+
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+</broker>
+
+
diff --git a/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml b/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
new file mode 100644
index 0000000000..1de0389533
--- /dev/null
+++ b/java/systests/etc/config-systests-ServerConfigurationTest-Old.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+<work>${QPID_WORK}</work>
+<conf>${QPID_HOME}/etc</conf>
+<passwordDir>${conf}</passwordDir>
+<plugin-directory>${QPID_HOME}/lib/plugins</plugin-directory>
+<cache-directory>${QPID_WORK}/cache</cache-directory>
+<connector>
+<transport>nio</transport>
+<port>5672</port>
+<socketReceiveBuffer>32768</socketReceiveBuffer>
+<socketSendBuffer>32768</socketSendBuffer>
+</connector>
+<management>
+<enabled>false</enabled>
+<jmxport>8999</jmxport>
+</management>
+<advanced>
+<filterchain enableExecutorPool="true"/>
+<enablePooledAllocator>false</enablePooledAllocator>
+<enableDirectBuffers>false</enableDirectBuffers>
+<framesize>65535</framesize>
+<compressBufferOnQueue>false</compressBufferOnQueue>
+</advanced>
+<security>
+<principal-databases>
+<principal-database>
+<name>passwordfile</name>
+<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
+<attributes>
+<attribute>
+<name>passwordFile</name>
+<value>${passwordDir}/passwd</value>
+</attribute>
+</attributes>
+</principal-database>
+</principal-databases>
+<jmx>
+<access>${passwordDir}/jmxremote.access</access>
+<principal-database>passwordfile</principal-database>
+</jmx>
+</security>
+<virtualhosts>${conf}/virtualhosts-ServerConfigurationTest-New.xml
+<default>dev-only</default>
+<virtualhost>
+<name>dev-only</name>
+<dev-only>
+<store>
+<class>org.apache.qpid.server.store.MemoryMessageStore</class>
+<environment-path>${work}/bdbstore/dev-only-store</environment-path>
+</store>
+<queues>
+<exchange>amq.direct</exchange>
+<maximumQueueDepth>102400</maximumQueueDepth>
+<maximumMessageSize>20480</maximumMessageSize>
+<maximumMessageAge>60000</maximumMessageAge>
+<queue>
+<name>dev-queue</name>
+</queue>
+</queues>
+</dev-only>
+</virtualhost>
+</virtualhosts>
+<heartbeat>
+<delay>0</delay>
+<timeoutFactor>2.0</timeoutFactor>
+</heartbeat>
+<queue>
+<auto_register>true</auto_register>
+</queue>
+</configuration>
diff --git a/java/systests/etc/config-systests-acl-settings.xml b/java/systests/etc/config-systests-acl-settings.xml
new file mode 100644
index 0000000000..eebc75f05f
--- /dev/null
+++ b/java/systests/etc/config-systests-acl-settings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+<broker>
+ <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-acl.xml</virtualhosts>
+</broker>
+
+
diff --git a/java/systests/etc/config-systests-acl.xml b/java/systests/etc/config-systests-acl.xml
new file mode 100644
index 0000000000..535108235e
--- /dev/null
+++ b/java/systests/etc/config-systests-acl.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+<configuration>
+ <system/>
+ <override>
+ <xml fileName="${test.config}" optional="true"/>
+ <xml fileName="${QPID_HOME}/etc/config-systests-acl-settings.xml"/>
+ <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
+ <xml fileName="${QPID_HOME}/etc/config.xml"/>
+ </override>
+</configuration>
diff --git a/java/systests/etc/config-systests-aclv2.xml b/java/systests/etc/config-systests-aclv2.xml
index e8b971a2a0..33563e7891 100644
--- a/java/systests/etc/config-systests-aclv2.xml
+++ b/java/systests/etc/config-systests-aclv2.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
+ <xml fileName="${test.config}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/config-systests-aclv2-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config.xml"/>
diff --git a/java/systests/etc/config-systests-bdb-settings.xml b/java/systests/etc/config-systests-bdb-settings.xml
deleted file mode 100644
index 4fa69d0abc..0000000000
--- a/java/systests/etc/config-systests-bdb-settings.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- -
- - 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.
- -
- -->
-<broker>
- <virtualhosts>${QPID_HOME}/etc/virtualhosts-systests-bdb.xml</virtualhosts>
-</broker>
-
-
diff --git a/java/systests/etc/config-systests-bdb.xml b/java/systests/etc/config-systests-bdb.xml
deleted file mode 100644
index 9364006fcc..0000000000
--- a/java/systests/etc/config-systests-bdb.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- -
- - 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.
- -
- -->
-<configuration>
- <system/>
- <override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
- <xml fileName="${QPID_HOME}/etc/config-systests-bdb-settings.xml"/>
- <xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
- <xml fileName="${QPID_HOME}/etc/config.xml"/>
- </override>
-</configuration>
diff --git a/java/systests/etc/config-systests-derby.xml b/java/systests/etc/config-systests-derby.xml
index 303154d8f0..ba27a0c020 100644
--- a/java/systests/etc/config-systests-derby.xml
+++ b/java/systests/etc/config-systests-derby.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
+ <xml fileName="${test.config}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/config-systests-derby-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config.xml"/>
diff --git a/java/systests/etc/config-systests-firewall-2.xml b/java/systests/etc/config-systests-firewall-2.xml
index a9fd86b8e5..38ff9ddbb0 100644
--- a/java/systests/etc/config-systests-firewall-2.xml
+++ b/java/systests/etc/config-systests-firewall-2.xml
@@ -32,16 +32,30 @@
<ssl>
<enabled>false</enabled>
<sslOnly>false</sslOnly>
- <keyStorePath>/path/to/keystore.ks</keyStorePath>
- <keyStorePassword>keystorepass</keyStorePassword>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
</ssl>
+ <qpidnio>false</qpidnio>
+ <protectio>
+ <enabled>false</enabled>
+ <readBufferLimitSize>262144</readBufferLimitSize>
+ <writeBufferLimitSize>262144</writeBufferLimitSize>
+ </protectio>
+ <transport>nio</transport>
<port>5672</port>
<sslport>8672</sslport>
- <socketReceiveBuffer>262144</socketReceiveBuffer>
- <socketSendBuffer>262144</socketSendBuffer>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
</connector>
<management>
<enabled>false</enabled>
+ <jmxport>8999</jmxport>
+ <ssl>
+ <enabled>false</enabled>
+ <!-- Update below path to your keystore location, eg ${conf}/qpid.keystore -->
+ <keyStorePath>${prefix}/../test-profiles/test_resources/ssl/keystore.jks</keyStorePath>
+ <keyStorePassword>password</keyStorePassword>
+ </ssl>
</management>
<advanced>
<filterchain enableExecutorPool="true"/>
@@ -54,8 +68,10 @@
</advanced>
<security>
- <pd-auth-manager>
+ <principal-databases>
+ <!-- Example use of Base64 encoded MD5 hashes for authentication via CRAM-MD5-Hashed -->
<principal-database>
+ <name>passwordfile</name>
<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
<attributes>
<attribute>
@@ -64,10 +80,15 @@
</attribute>
</attributes>
</principal-database>
- </pd-auth-manager>
+ </principal-databases>
<msg-auth>false</msg-auth>
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
+
<firewall default-action="deny"/>
</security>
diff --git a/java/systests/etc/config-systests-firewall-3.xml b/java/systests/etc/config-systests-firewall-3.xml
index f0f3423f43..6c0ee7ee3c 100644
--- a/java/systests/etc/config-systests-firewall-3.xml
+++ b/java/systests/etc/config-systests-firewall-3.xml
@@ -28,20 +28,34 @@
<connector>
<!-- To enable SSL edit the keystorePath and keystorePassword
and set enabled to true.
- To disable Non-SSL port set sslOnly to true -->
+ To disasble Non-SSL port set sslOnly to true -->
<ssl>
<enabled>false</enabled>
<sslOnly>false</sslOnly>
- <keyStorePath>/path/to/keystore.ks</keyStorePath>
- <keyStorePassword>keystorepass</keyStorePassword>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
</ssl>
+ <qpidnio>false</qpidnio>
+ <protectio>
+ <enabled>false</enabled>
+ <readBufferLimitSize>262144</readBufferLimitSize>
+ <writeBufferLimitSize>262144</writeBufferLimitSize>
+ </protectio>
+ <transport>nio</transport>
<port>5672</port>
<sslport>8672</sslport>
- <socketReceiveBuffer>262144</socketReceiveBuffer>
- <socketSendBuffer>262144</socketSendBuffer>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
</connector>
<management>
<enabled>false</enabled>
+ <jmxport>8999</jmxport>
+ <ssl>
+ <enabled>false</enabled>
+ <!-- Update below path to your keystore location, eg ${conf}/qpid.keystore -->
+ <keyStorePath>${prefix}/../test-profiles/test_resources/ssl/keystore.jks</keyStorePath>
+ <keyStorePassword>password</keyStorePassword>
+ </ssl>
</management>
<advanced>
<filterchain enableExecutorPool="true"/>
@@ -54,8 +68,10 @@
</advanced>
<security>
- <pd-auth-manager>
+ <principal-databases>
+ <!-- Example use of Base64 encoded MD5 hashes for authentication via CRAM-MD5-Hashed -->
<principal-database>
+ <name>passwordfile</name>
<class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
<attributes>
<attribute>
@@ -64,10 +80,15 @@
</attribute>
</attributes>
</principal-database>
- </pd-auth-manager>
+ </principal-databases>
<msg-auth>false</msg-auth>
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
+
<firewall default-action="deny">
<rule access="allow" network="127.0.0.1"/>
</firewall>
diff --git a/java/systests/etc/config-systests-firewall.xml b/java/systests/etc/config-systests-firewall.xml
index c73ac6a687..c0ce71210f 100644
--- a/java/systests/etc/config-systests-firewall.xml
+++ b/java/systests/etc/config-systests-firewall.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
+ <xml fileName="${test.config}" optional="true"/>
<xml fileName="${QPID_FIREWALL_CONFIG_SETTINGS}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/config-systests-firewall-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
diff --git a/java/systests/etc/config-systests-settings.xml b/java/systests/etc/config-systests-settings.xml
index 88533400d3..751ff133cb 100644
--- a/java/systests/etc/config-systests-settings.xml
+++ b/java/systests/etc/config-systests-settings.xml
@@ -20,20 +20,11 @@
-
-->
<broker>
- <connector>
- <ssl>
- <port>15671</port>
- <enabled>false</enabled>
- <sslOnly>false</sslOnly>
- <keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath>
- <keyStorePassword>password</keyStorePassword>
- </ssl>
- </connector>
<management>
<enabled>false</enabled>
<ssl>
<enabled>false</enabled>
- <keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks</keyStorePath>
+ <keyStorePath>${QPID_HOME}/../test-profiles/test_resources/ssl/keystore.jks</keyStorePath>
<keyStorePassword>password</keyStorePassword>
</ssl>
</management>
diff --git a/java/systests/etc/config-systests.xml b/java/systests/etc/config-systests.xml
index 0e8f2803e3..5d7d878e76 100644
--- a/java/systests/etc/config-systests.xml
+++ b/java/systests/etc/config-systests.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.config}" optional="true"/>
+ <xml fileName="${test.config}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/config-systests-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/config.xml"/>
</override>
diff --git a/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml b/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml
new file mode 100644
index 0000000000..1b6845662b
--- /dev/null
+++ b/java/systests/etc/virtualhosts-ServerConfigurationTest-New.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+<virtualhosts>
+ <default>dev-only</default>
+ <virtualhost>
+ <name>dev-only</name>
+ <dev-only>
+ <queues>
+ <exchange>amq.direct</exchange>
+ <!-- Small defaults for development -->
+ <maximumQueueDepth>102400</maximumQueueDepth> <!-- 100k -->
+ <maximumMessageSize>20480</maximumMessageSize> <!-- 20kb -->
+ <maximumMessageAge>60000</maximumMessageAge> <!-- 1 mins -->
+
+ <queue>
+ <name>dev-queue</name>
+ </queue>
+ </queues>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ <environment-path>${QPID_WORK}/bdbstore/dev-only-store</environment-path>
+ </store>
+ </dev-only>
+ </virtualhost>
+</virtualhosts>
+ \ No newline at end of file
diff --git a/java/systests/etc/virtualhosts-systests-acl-settings.xml b/java/systests/etc/virtualhosts-systests-acl-settings.xml
new file mode 100644
index 0000000000..ffbace569f
--- /dev/null
+++ b/java/systests/etc/virtualhosts-systests-acl-settings.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+<virtualhosts>
+ <virtualhost>
+ <name>test</name>
+ <test>
+ <queues>
+ <exchange>amq.direct</exchange>
+ <!-- 4Mb -->
+ <maximumQueueDepth>4235264</maximumQueueDepth>
+ <!-- 2Mb -->
+ <maximumMessageSize>2117632</maximumMessageSize>
+ <!-- 10 mins -->
+ <maximumMessageAge>600000</maximumMessageAge>
+ </queues>
+
+
+ <security>
+ <access_control_list>
+ <!-- This section grants pubish rights to an exchange + routing key pair -->
+ <publish>
+ <exchanges>
+ <exchange>
+ <name>amq.direct</name>
+ <routing_keys>
+ <!-- Allow clients to publish requests -->
+ <routing_key>
+ <value>example.RequestQueue</value>
+ <users>
+ <user>client</user>
+ </users>
+ </routing_key>
+
+ <!-- Allow the processor to respond to a client on their Temporary Topic -->
+ <routing_key>
+ <value>tmp_*</value>
+ <users>
+ <user>server</user>
+ </users>
+ </routing_key>
+ <routing_key>
+ <value>TempQueue*</value>
+ <users>
+ <user>server</user>
+ </users>
+ </routing_key>
+ </routing_keys>
+ </exchange>
+ </exchanges>
+ </publish>
+
+ <!-- This section grants users the ability to consume from the broker -->
+ <consume>
+ <queues>
+ <temporary>
+ <users>
+ <user>client</user>
+ </users>
+ </temporary>
+
+ <!-- Only allow the server to consume from the Request Queue-->
+ <queue>
+ <name>example.RequestQueue</name>
+ <users>
+ <user>server</user>
+ </users>
+ </queue>
+
+ <!-- Allow client and server to consume from the kipper Queue-->
+ <queue>
+ <name>clientid:kipper</name>
+ <users>
+ <user>client</user>
+ <user>server</user>
+ </users>
+ </queue>
+ </queues>
+ </consume>
+
+ <!-- This section grants users the ability to create queues and exchanges -->
+ <create>
+ <queues>
+ <temporary>
+ <users>
+ <user>client</user>
+ </users>
+ </temporary>
+
+ <!-- Allow clients to create queue on this exchange-->
+ <queue>
+ <exchanges>
+ <exchange>
+ <name>amq.direct</name>
+ <users>
+ <user>client</user>
+ <user>server</user>
+ </users>
+ </exchange>
+ <exchange>
+ <name>amq.topic</name>
+ <users>
+ <user>client</user>
+ <user>server</user>
+ </users>
+ </exchange>
+ </exchanges>
+ </queue>
+
+ <!-- everyone can create the kipper queue -->
+ <queue>
+ <name>clientid:kipper</name>
+ <users>
+ <user>client</user>
+ <user>server</user>
+ </users>
+ </queue>
+
+ <!-- Allow the server to create the Request Queue-->
+ <queue>
+ <name>example.RequestQueue</name>
+ <users>
+ <user>server</user>
+ </users>
+ </queue>
+ </queues>
+ </create>
+
+ <delete>
+ <queues>
+ <!-- only client can delete the kipper queue -->
+ <queue>
+ <name>clientid:kipper</name>
+ <users>
+ <user>client</user>
+ </users>
+ </queue>
+ </queues>
+ </delete>
+ </access_control_list>
+ </security>
+ </test>
+ </virtualhost>
+
+ <virtualhost>
+ <name>test2</name>
+ <test2>
+ <security>
+ <access_control_list>
+ <!-- This section grants specific users full permissions to all artifacts in this virtualhost -->
+ <access>
+ <users>
+ <user>guest</user>
+ </users>
+ </access>
+ </access_control_list>
+ </security>
+ </test2>
+ </virtualhost>
+</virtualhosts>
+
+
diff --git a/java/systests/etc/virtualhosts-systests-acl.xml b/java/systests/etc/virtualhosts-systests-acl.xml
new file mode 100644
index 0000000000..4a56c39de0
--- /dev/null
+++ b/java/systests/etc/virtualhosts-systests-acl.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - 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.
+ -
+ -->
+<configuration>
+ <system/>
+ <override>
+ <xml fileName="${test.virtualhosts}" optional="true"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-acl-settings.xml"/>
+ <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
+ </override>
+</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-aclv2.xml b/java/systests/etc/virtualhosts-systests-aclv2.xml
index db396d7ab1..eb96577487 100644
--- a/java/systests/etc/virtualhosts-systests-aclv2.xml
+++ b/java/systests/etc/virtualhosts-systests-aclv2.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
+ <xml fileName="${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts-systests-aclv2-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
</override>
diff --git a/java/systests/etc/virtualhosts-systests-bdb-settings.xml b/java/systests/etc/virtualhosts-systests-bdb-settings.xml
deleted file mode 100644
index ce16523f13..0000000000
--- a/java/systests/etc/virtualhosts-systests-bdb-settings.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- -
- - 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.
- -
- -->
-<virtualhosts>
- <work>${QPID_WORK}</work>
-
- <virtualhost>
- <name>localhost</name>
- <localhost>
- <store>
- <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
- <environment-path>${work}/bdbstore/localhost-store</environment-path>
- </store>
- </localhost>
- </virtualhost>
-
- <virtualhost>
- <name>development</name>
- <development>
- <store>
- <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
- <environment-path>${work}/bdbstore/development-store</environment-path>
- </store>
- </development>
- </virtualhost>
-
- <virtualhost>
- <name>test</name>
- <test>
- <store>
- <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
- <environment-path>${work}/bdbstore/test-store</environment-path>
- </store>
- </test>
- </virtualhost>
-</virtualhosts>
-
-
diff --git a/java/systests/etc/virtualhosts-systests-bdb.xml b/java/systests/etc/virtualhosts-systests-bdb.xml
deleted file mode 100644
index 367fee65ac..0000000000
--- a/java/systests/etc/virtualhosts-systests-bdb.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!--
- -
- - 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.
- -
- -->
-<configuration>
- <system/>
- <override>
- <xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
- <xml fileName="${QPID_HOME}/etc/virtualhosts-systests-bdb-settings.xml"/>
- <xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
- </override>
-</configuration>
diff --git a/java/systests/etc/virtualhosts-systests-derby.xml b/java/systests/etc/virtualhosts-systests-derby.xml
index 3745100e1f..171be37416 100644
--- a/java/systests/etc/virtualhosts-systests-derby.xml
+++ b/java/systests/etc/virtualhosts-systests-derby.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
+ <xml fileName="${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts-systests-derby-settings.xml"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
</override>
diff --git a/java/systests/etc/virtualhosts-systests-firewall.xml b/java/systests/etc/virtualhosts-systests-firewall.xml
index c5c6a86d7c..51ab6739b3 100644
--- a/java/systests/etc/virtualhosts-systests-firewall.xml
+++ b/java/systests/etc/virtualhosts-systests-firewall.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
+ <xml fileName="${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_FIREWALL_VIRTUALHOSTS_SETTINGS}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
</override>
diff --git a/java/systests/etc/virtualhosts-systests.xml b/java/systests/etc/virtualhosts-systests.xml
index d6aeefac72..71f1cc9889 100644
--- a/java/systests/etc/virtualhosts-systests.xml
+++ b/java/systests/etc/virtualhosts-systests.xml
@@ -22,7 +22,7 @@
<configuration>
<system/>
<override>
- <xml fileName="${QPID_HOME}/${test.virtualhosts}" optional="true"/>
+ <xml fileName="${test.virtualhosts}" optional="true"/>
<xml fileName="${QPID_HOME}/etc/virtualhosts.xml"/>
</override>
</configuration>
diff --git a/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java b/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
new file mode 100644
index 0000000000..5323ad28bf
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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 org.apache.mina.transport.vmpipe.support;
+
+import org.apache.mina.common.IdleStatus;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This file is a patch to override MINA, because of the IdentityHashMap bug. Workaround to be supplied in MINA 1.0.7.
+ * This patched file will be removed once upgraded onto a newer MINA.
+ *
+ * Dectects idle sessions and fires <tt>sessionIdle</tt> events to them.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class VmPipeIdleStatusChecker
+{
+ private static final VmPipeIdleStatusChecker INSTANCE = new VmPipeIdleStatusChecker();
+
+ public static VmPipeIdleStatusChecker getInstance()
+ {
+ return INSTANCE;
+ }
+
+ private final Map sessions = new HashMap(); // will use as a set
+
+ private final Worker worker = new Worker();
+
+ private VmPipeIdleStatusChecker()
+ {
+ worker.start();
+ }
+
+ public void addSession(VmPipeSessionImpl session)
+ {
+ synchronized (sessions)
+ {
+ sessions.put(session, session);
+ }
+ }
+
+ private class Worker extends Thread
+ {
+ private Worker()
+ {
+ super("VmPipeIdleStatusChecker");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ for (;;)
+ {
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ { }
+
+ long currentTime = System.currentTimeMillis();
+
+ synchronized (sessions)
+ {
+ Iterator it = sessions.keySet().iterator();
+ while (it.hasNext())
+ {
+ VmPipeSessionImpl session = (VmPipeSessionImpl) it.next();
+ if (!session.isConnected())
+ {
+ it.remove();
+ }
+ else
+ {
+ notifyIdleSession(session, currentTime);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyIdleSession(VmPipeSessionImpl session, long currentTime)
+ {
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE,
+ Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE,
+ Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE)));
+ }
+
+ private void notifyIdleSession0(VmPipeSessionImpl session, long currentTime, long idleTime, IdleStatus status,
+ long lastIoTime)
+ {
+ if ((idleTime > 0) && (lastIoTime != 0) && ((currentTime - lastIoTime) >= idleTime))
+ {
+ session.increaseIdleCount(status);
+ session.getFilterChain().fireSessionIdle(session, status);
+ }
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
index 7ea4416f3b..ca10126aa7 100644
--- a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
@@ -30,16 +30,19 @@ import javax.jms.TextMessage;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.client.transport.TransportConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase
{
+
+ private static final int NUM_MESSAGES = 1000;
+
private Connection con;
private Session session;
private AMQQueue queue;
private MessageConsumer consumer;
- private int numMessages;
private static final Logger _logger = LoggerFactory.getLogger(AMQQueueDeferredOrderingTest.class);
@@ -85,8 +88,6 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase
{
super.setUp();
- numMessages = isBrokerStorePersistent() ? 300 : 1000;
-
_logger.info("Create Connection");
con = getConnection();
_logger.info("Create Session");
@@ -105,19 +106,19 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase
// Setup initial messages
_logger.info("Creating first producer thread");
- producerThread = new ASyncProducer(queue, 0, numMessages / 2);
+ producerThread = new ASyncProducer(queue, 0, NUM_MESSAGES / 2);
producerThread.start();
// Wait for them to be done
producerThread.join();
// Setup second set of messages to produce while we consume
_logger.info("Creating second producer thread");
- producerThread = new ASyncProducer(queue, numMessages / 2, numMessages);
+ producerThread = new ASyncProducer(queue, NUM_MESSAGES / 2, NUM_MESSAGES);
producerThread.start();
// Start consuming and checking they're in order
_logger.info("Consuming messages");
- for (int i = 0; i < numMessages; i++)
+ for (int i = 0; i < NUM_MESSAGES; i++)
{
Message msg = consumer.receive(3000);
assertNotNull("Message should not be null", msg);
diff --git a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java
index 29a44ecec3..a8a23c2c41 100644
--- a/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java
@@ -36,6 +36,7 @@ import javax.jms.Session;
import javax.naming.Context;
import javax.naming.spi.InitialContextFactory;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.slf4j.Logger;
diff --git a/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java b/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java
new file mode 100644
index 0000000000..29b4dd82a7
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/client/MultipleJCAProviderRegistrationTest.java
@@ -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.
+ *
+ */
+package org.apache.qpid.client;
+
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.client.transport.TransportConnection;
+
+import java.io.File;
+import java.security.Provider;
+import java.security.Security;
+import java.util.List;
+import java.util.LinkedList;
+
+/**
+ * QPID-1394 : Test to ensure that the client can register their custom JCAProviders after the broker to ensure that
+ * the Qpid custom authentication SASL plugins are used.
+ */
+public class MultipleJCAProviderRegistrationTest extends QpidBrokerTestCase
+{
+
+ public void setUp() throws Exception
+ {
+ _broker = VM;
+
+ super.setUp();
+ }
+
+ public void test() throws Exception
+ {
+ // Get the providers before connection
+ Provider[] providers = Security.getProviders();
+
+ // Force the client to load the providers
+ getConnection();
+
+ Provider[] afterConnectionCreation = Security.getProviders();
+
+ // Find the additions
+ List additions = new LinkedList();
+ for (Provider afterCreation : afterConnectionCreation)
+ {
+ boolean found = false;
+ for (Provider provider : providers)
+ {
+ if (provider == afterCreation)
+ {
+ found=true;
+ break;
+ }
+ }
+
+ // Record added registies
+ if (!found)
+ {
+ additions.add(afterCreation);
+ }
+ }
+
+ assertTrue("Client did not register any providers", additions.size() > 0);
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java
index 40a0d32b01..303da29389 100644
--- a/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java
@@ -135,7 +135,7 @@ public class ResetMessageListenerTest extends QpidBrokerTestCase
try
{
assertTrue("Did not receive all first batch of messages",
- _allFirstMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS));
+ _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS));
_logger.info("Received first batch of messages");
}
catch (InterruptedException e)
@@ -212,7 +212,7 @@ public class ResetMessageListenerTest extends QpidBrokerTestCase
try
{
- assertTrue(_allSecondMessagesSent.await(MSG_COUNT, TimeUnit.SECONDS));
+ assertTrue(_allSecondMessagesSent.await(1000, TimeUnit.MILLISECONDS));
}
catch (InterruptedException e)
{
diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java
deleted file mode 100644
index 66f8fe0546..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java
+++ /dev/null
@@ -1,949 +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.
- */
-package org.apache.qpid.client.failover;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.jms.TransactionRolledBackException;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.jms.ConnectionListener;
-import org.apache.qpid.test.utils.FailoverBaseCase;
-
-/**
- * Test suite to test all possible failover corner cases
- */
-public class FailoverBehaviourTest extends FailoverBaseCase implements ConnectionListener, ExceptionListener
-{
- private static final String TEST_MESSAGE_FORMAT = "test message {0}";
-
- /** Indicates whether tests are run against clustered broker */
- private static boolean CLUSTERED = Boolean.getBoolean("profile.clustered");
-
- /** Default number of messages to send before failover */
- private static final int DEFAULT_NUMBER_OF_MESSAGES = 10;
-
- /** Actual number of messages to send before failover */
- protected int _messageNumber = Integer.getInteger("profile.failoverMsgCount", DEFAULT_NUMBER_OF_MESSAGES);
-
- /** Test connection */
- protected Connection _connection;
-
- /**
- * Failover completion latch is used to wait till connectivity to broker is
- * restored
- */
- private CountDownLatch _failoverComplete;
-
- /**
- * Consumer session
- */
- private Session _consumerSession;
-
- /**
- * Test destination
- */
- private Destination _destination;
-
- /**
- * Consumer
- */
- private MessageConsumer _consumer;
-
- /**
- * Producer session
- */
- private Session _producerSession;
-
- /**
- * Producer
- */
- private MessageProducer _producer;
-
- /**
- * Holds exception sent into {@link ExceptionListener} on failover
- */
- private JMSException _exceptionListenerException;
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
-
- _connection = getConnection();
- _connection.setExceptionListener(this);
- ((AMQConnection) _connection).setConnectionListener(this);
- _failoverComplete = new CountDownLatch(1);
- }
-
- /**
- * Test whether MessageProducer can successfully publish messages after
- * failover and rollback transaction
- */
- public void testMessageProducingAndRollbackAfterFailover() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
- produceMessages();
- causeFailure();
-
- assertFailoverException();
- // producer should be able to send messages after failover
- _producer.send(_producerSession.createTextMessage("test message " + _messageNumber));
-
- // rollback after failover
- _producerSession.rollback();
-
- // tests whether sending and committing is working after failover
- produceMessages();
- _producerSession.commit();
-
- // tests whether receiving and committing is working after failover
- consumeMessages();
- _consumerSession.commit();
- }
-
- /**
- * Test whether {@link TransactionRolledBackException} is thrown on commit
- * of dirty transacted session after failover.
- * <p>
- * Verifies whether second after failover commit is successful.
- */
- public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnProducingMessages() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
- produceMessages();
- causeFailure();
-
- assertFailoverException();
-
- // producer should be able to send messages after failover
- _producer.send(_producerSession.createTextMessage("test message " + _messageNumber));
-
- try
- {
- _producerSession.commit();
- fail("TransactionRolledBackException is expected on commit after failover with dirty session!");
- }
- catch (JMSException t)
- {
- assertTrue("Expected TransactionRolledBackException but thrown " + t,
- t instanceof TransactionRolledBackException);
- }
-
- // simulate process of user replaying the transaction
- produceMessages("replayed test message {0}", _messageNumber, false);
-
- // no exception should be thrown
- _producerSession.commit();
-
- // only messages sent after rollback should be received
- consumeMessages("replayed test message {0}", _messageNumber);
-
- // no exception should be thrown
- _consumerSession.commit();
- }
-
- /**
- * Tests JMSException is not thrown on commit with a clean session after
- * failover
- */
- public void testNoJMSExceptionThrownOnCommitAfterFailoverWithCleanProducerSession() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
-
- causeFailure();
-
- assertFailoverException();
-
- // should not throw an exception for a clean session
- _producerSession.commit();
-
- // tests whether sending and committing is working after failover
- produceMessages();
- _producerSession.commit();
-
- // tests whether receiving and committing is working after failover
- consumeMessages();
- _consumerSession.commit();
- }
-
- /**
- * Tests {@link TransactionRolledBackException} is thrown on commit of dirty
- * transacted session after failover.
- * <p>
- * Verifies whether second after failover commit is successful.
- */
- public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnMessageReceiving() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
- produceMessages();
- _producerSession.commit();
-
- // receive messages but do not commit
- consumeMessages();
-
- causeFailure();
-
- assertFailoverException();
-
- try
- {
- // should throw TransactionRolledBackException
- _consumerSession.commit();
- fail("TransactionRolledBackException is expected on commit after failover");
- }
- catch (Exception t)
- {
- assertTrue("Expected TransactionRolledBackException but thrown " + t,
- t instanceof TransactionRolledBackException);
- }
-
- resendMessagesIfNecessary();
-
- // consume messages successfully
- consumeMessages();
- _consumerSession.commit();
- }
-
- /**
- * Tests JMSException is not thrown on commit with a clean session after failover
- */
- public void testNoJMSExceptionThrownOnCommitAfterFailoverWithCleanConsumerSession() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
- produceMessages();
- _producerSession.commit();
-
- consumeMessages();
- _consumerSession.commit();
-
- causeFailure();
-
- assertFailoverException();
-
- // should not throw an exception with a clean consumer session
- _consumerSession.commit();
- }
-
- /**
- * Test that TransactionRolledBackException is thrown on commit of
- * dirty session in asynchronous consumer after failover.
- */
- public void testTransactionRolledBackExceptionThrownOnCommitAfterFailoverOnReceivingMessagesAsynchronously()
- throws Exception
- {
- init(Session.SESSION_TRANSACTED, false);
- FailoverTestMessageListener ml = new FailoverTestMessageListener();
- _consumer.setMessageListener(ml);
-
- _connection.start();
-
- produceMessages();
- _producerSession.commit();
-
- // wait for message receiving
- ml.awaitForEnd();
-
- assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter());
-
- // assert messages
- int counter = 0;
- for (Message message : ml.getReceivedMessages())
- {
- assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++);
- }
- ml.reset();
-
- causeFailure();
- assertFailoverException();
-
-
- try
- {
- _consumerSession.commit();
- fail("TransactionRolledBackException should be thrown!");
- }
- catch (TransactionRolledBackException e)
- {
- // that is what is expected
- }
-
- resendMessagesIfNecessary();
-
- // wait for message receiving
- ml.awaitForEnd();
-
- assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter());
-
- // assert messages
- counter = 0;
- for (Message message : ml.getReceivedMessages())
- {
- assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++);
- }
-
- // commit again. It should be successful
- _consumerSession.commit();
- }
-
- /**
- * Test that {@link Session#rollback()} does not throw exception after failover
- * and that we are able to consume messages.
- */
- public void testRollbackAfterFailover() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
-
- produceMessages();
- _producerSession.commit();
-
- consumeMessages();
-
- causeFailure();
-
- assertFailoverException();
-
- _consumerSession.rollback();
-
- resendMessagesIfNecessary();
-
- // tests whether receiving and committing is working after failover
- consumeMessages();
- _consumerSession.commit();
- }
-
- /**
- * Test that {@link Session#rollback()} does not throw exception after receiving further messages
- * after failover, and we can receive published messages after rollback.
- */
- public void testRollbackAfterReceivingAfterFailover() throws Exception
- {
- init(Session.SESSION_TRANSACTED, true);
-
- produceMessages();
- _producerSession.commit();
-
- consumeMessages();
- causeFailure();
-
- assertFailoverException();
-
- resendMessagesIfNecessary();
-
- consumeMessages();
-
- _consumerSession.rollback();
-
- // tests whether receiving and committing is working after failover
- consumeMessages();
- _consumerSession.commit();
- }
-
- /**
- * Test that {@link Session#recover()} does not throw an exception after failover
- * and that we can consume messages after recover.
- */
- public void testRecoverAfterFailover() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // consume messages but do not acknowledge them
- consumeMessages();
-
- causeFailure();
-
- assertFailoverException();
-
- _consumerSession.recover();
-
- resendMessagesIfNecessary();
-
- // tests whether receiving and acknowledgment is working after recover
- Message lastMessage = consumeMessages();
- lastMessage.acknowledge();
- }
-
- /**
- * Test that receiving more messages after failover and then calling
- * {@link Session#recover()} does not throw an exception
- * and that we can consume messages after recover.
- */
- public void testRecoverWithConsumedMessagesAfterFailover() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // consume messages but do not acknowledge them
- consumeMessages();
-
- causeFailure();
-
- assertFailoverException();
-
- // publishing should work after failover
- resendMessagesIfNecessary();
-
- // consume messages again on a dirty session
- consumeMessages();
-
- // recover should successfully restore session
- _consumerSession.recover();
-
- // tests whether receiving and acknowledgment is working after recover
- Message lastMessage = consumeMessages();
- lastMessage.acknowledge();
- }
-
- /**
- * Test that first call to {@link Message#acknowledge()} after failover
- * throws a JMSEXception if session is dirty.
- */
- public void testAcknowledgeAfterFailover() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // consume messages but do not acknowledge them
- Message lastMessage = consumeMessages();
- causeFailure();
-
- assertFailoverException();
-
- try
- {
- // an implicit recover performed when acknowledge throws an exception due to failover
- lastMessage.acknowledge();
- fail("JMSException should be thrown");
- }
- catch (JMSException t)
- {
- // TODO: assert error code and/or expected exception type
- }
-
- resendMessagesIfNecessary();
-
- // tests whether receiving and acknowledgment is working after recover
- lastMessage = consumeMessages();
- lastMessage.acknowledge();
- }
-
- /**
- * Test that calling acknowledge before failover leaves the session
- * clean for use after failover.
- */
- public void testAcknowledgeBeforeFailover() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // consume messages and acknowledge them
- Message lastMessage = consumeMessages();
- lastMessage.acknowledge();
-
- causeFailure();
-
- assertFailoverException();
-
- produceMessages();
-
- // tests whether receiving and acknowledgment is working after recover
- lastMessage = consumeMessages();
- lastMessage.acknowledge();
- }
-
- /**
- * Test that receiving of messages after failover prior to calling
- * {@link Message#acknowledge()} still results in acknowledge throwing an exception.
- */
- public void testAcknowledgeAfterMessageReceivingAfterFailover() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // consume messages but do not acknowledge them
- consumeMessages();
- causeFailure();
-
- assertFailoverException();
-
- resendMessagesIfNecessary();
-
- // consume again on dirty session
- Message lastMessage = consumeMessages();
- try
- {
- // an implicit recover performed when acknowledge throws an exception due to failover
- lastMessage.acknowledge();
- fail("JMSException should be thrown");
- }
- catch (JMSException t)
- {
- // TODO: assert error code and/or expected exception type
- }
-
- // tests whether receiving and acknowledgment is working on a clean session
- lastMessage = consumeMessages();
- lastMessage.acknowledge();
- }
-
- /**
- * Tests that call to {@link Message#acknowledge()} after failover throws an exception in asynchronous consumer
- * and we can consume messages after acknowledge.
- */
- public void testAcknowledgeAfterFailoverForAsynchronousConsumer() throws Exception
- {
- init(Session.CLIENT_ACKNOWLEDGE, false);
- FailoverTestMessageListener ml = new FailoverTestMessageListener();
- _consumer.setMessageListener(ml);
- _connection.start();
-
- produceMessages();
-
- // wait for message receiving
- ml.awaitForEnd();
-
- assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter());
-
- // assert messages
- int counter = 0;
- Message currentMessage = null;
- for (Message message : ml.getReceivedMessages())
- {
- assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++);
- currentMessage = message;
- }
- ml.reset();
-
- causeFailure();
- assertFailoverException();
-
-
- try
- {
- currentMessage.acknowledge();
- fail("JMSException should be thrown!");
- }
- catch (JMSException e)
- {
- // TODO: assert error code and/or expected exception type
- }
-
- resendMessagesIfNecessary();
-
- // wait for message receiving
- ml.awaitForEnd();
-
- assertEquals("Received unexpected number of messages!", _messageNumber, ml.getMessageCounter());
-
- // assert messages
- counter = 0;
- for (Message message : ml.getReceivedMessages())
- {
- assertReceivedMessage(message, TEST_MESSAGE_FORMAT, counter++);
- currentMessage = message;
- }
-
- // acknowledge again. It should be successful
- currentMessage.acknowledge();
- }
-
- /**
- * Test whether {@link Session#recover()} works as expected after failover
- * in AA mode.
- */
- public void testRecoverAfterFailoverInAutoAcknowledgeMode() throws Exception
- {
- init(Session.AUTO_ACKNOWLEDGE, true);
-
- produceMessages();
-
- // receive first message in order to start a dispatcher thread
- Message receivedMessage = _consumer.receive(1000l);
- assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0);
-
- causeFailure();
-
- assertFailoverException();
-
- _consumerSession.recover();
-
- resendMessagesIfNecessary();
-
- // tests whether receiving is working after recover
- consumeMessages();
- }
-
- public void testClientAcknowledgedSessionCloseAfterFailover() throws Exception
- {
- sessionCloseAfterFailoverImpl(Session.CLIENT_ACKNOWLEDGE);
- }
-
- public void testTransactedSessionCloseAfterFailover() throws Exception
- {
- sessionCloseAfterFailoverImpl(Session.SESSION_TRANSACTED);
- }
-
- public void testAutoAcknowledgedSessionCloseAfterFailover() throws Exception
- {
- sessionCloseAfterFailoverImpl(Session.AUTO_ACKNOWLEDGE);
- }
-
- /**
- * Tests {@link Session#close()} for session with given acknowledge mode
- * to ensure that close works after failover.
- *
- * @param acknowledgeMode session acknowledge mode
- * @throws JMSException
- */
- private void sessionCloseAfterFailoverImpl(int acknowledgeMode) throws JMSException
- {
- init(acknowledgeMode, true);
- produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, false);
- if (acknowledgeMode == Session.SESSION_TRANSACTED)
- {
- _producerSession.commit();
- }
-
- // intentionally receive message but do not commit or acknowledge it in
- // case of transacted or CLIENT_ACK session
- Message receivedMessage = _consumer.receive(1000l);
- assertReceivedMessage(receivedMessage, TEST_MESSAGE_FORMAT, 0);
-
- causeFailure();
-
- assertFailoverException();
-
- // for transacted/client_ack session
- // no exception should be thrown but transaction should be automatically
- // rolled back
- _consumerSession.close();
- }
-
- /**
- * A helper method to instantiate produce and consumer sessions, producer
- * and consumer.
- *
- * @param acknowledgeMode
- * acknowledge mode
- * @param startConnection
- * indicates whether connection should be started
- * @throws JMSException
- */
- private void init(int acknowledgeMode, boolean startConnection) throws JMSException
- {
- boolean isTransacted = acknowledgeMode == Session.SESSION_TRANSACTED ? true : false;
-
- _consumerSession = _connection.createSession(isTransacted, acknowledgeMode);
- _destination = _consumerSession.createQueue(getTestQueueName() + "_" + System.currentTimeMillis());
- _consumer = _consumerSession.createConsumer(_destination);
-
- if (startConnection)
- {
- _connection.start();
- }
-
- _producerSession = _connection.createSession(isTransacted, acknowledgeMode);
- _producer = _producerSession.createProducer(_destination);
-
- }
-
- /**
- * Resends messages if reconnected to a non-clustered broker
- *
- * @throws JMSException
- */
- private void resendMessagesIfNecessary() throws JMSException
- {
- if (!CLUSTERED)
- {
- // assert that a new broker does not have messages on a queue
- if (_consumer.getMessageListener() == null)
- {
- Message message = _consumer.receive(100l);
- assertNull("Received a message after failover with non-clustered broker!", message);
- }
- // re-sending messages if reconnected to a non-clustered broker
- produceMessages(true);
- }
- }
-
- /**
- * Produces a default number of messages with default text content into test
- * queue
- *
- * @throws JMSException
- */
- private void produceMessages() throws JMSException
- {
- produceMessages(false);
- }
-
- private void produceMessages(boolean seperateProducer) throws JMSException
- {
- produceMessages(TEST_MESSAGE_FORMAT, _messageNumber, seperateProducer);
- }
-
- /**
- * Consumes a default number of messages and asserts their content.
- *
- * @return last consumed message
- * @throws JMSException
- */
- private Message consumeMessages() throws JMSException
- {
- return consumeMessages(TEST_MESSAGE_FORMAT, _messageNumber);
- }
-
- /**
- * Produces given number of text messages with content matching given
- * content pattern
- *
- * @param messagePattern message content pattern
- * @param messageNumber number of messages to send
- * @param standaloneProducer whether to use the existing producer or a new one.
- * @throws JMSException
- */
- private void produceMessages(String messagePattern, int messageNumber, boolean standaloneProducer) throws JMSException
- {
- Session producerSession;
- MessageProducer producer;
-
- if(standaloneProducer)
- {
- producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
- producer = producerSession.createProducer(_destination);
- }
- else
- {
- producerSession = _producerSession;
- producer = _producer;
- }
-
- for (int i = 0; i < messageNumber; i++)
- {
- String text = MessageFormat.format(messagePattern, i);
- Message message = producerSession.createTextMessage(text);
- producer.send(message);
- }
-
- if(standaloneProducer)
- {
- producerSession.commit();
- }
- }
-
- /**
- * Consumes given number of text messages and asserts that their content
- * matches given pattern
- *
- * @param messagePattern
- * messages content pattern
- * @param messageNumber
- * message number to received
- * @return last consumed message
- * @throws JMSException
- */
- private Message consumeMessages(String messagePattern, int messageNumber) throws JMSException
- {
- Message receivedMesssage = null;
- for (int i = 0; i < messageNumber; i++)
- {
- receivedMesssage = _consumer.receive(1000l);
- assertReceivedMessage(receivedMesssage, messagePattern, i);
- }
- return receivedMesssage;
- }
-
- /**
- * Asserts received message
- *
- * @param receivedMessage
- * received message
- * @param messagePattern
- * messages content pattern
- * @param messageIndex
- * message index
- */
- private void assertReceivedMessage(Message receivedMessage, String messagePattern, int messageIndex)
- {
- assertNotNull("Expected message [" + messageIndex + "] is not received!", receivedMessage);
- assertTrue("Failure to receive message [" + messageIndex + "], expected TextMessage but received "
- + receivedMessage, receivedMessage instanceof TextMessage);
- String expectedText = MessageFormat.format(messagePattern, messageIndex);
- String receivedText = null;
- try
- {
- receivedText = ((TextMessage) receivedMessage).getText();
- }
- catch (JMSException e)
- {
- fail("JMSException occured while getting message text:" + e.getMessage());
- }
- assertEquals("Failover is broken! Expected [" + expectedText + "] but got [" + receivedText + "]",
- expectedText, receivedText);
- }
-
- /**
- * Causes failover and waits till connection is re-established.
- */
- private void causeFailure()
- {
- causeFailure(getFailingPort(), DEFAULT_FAILOVER_TIME * 2);
- }
-
- /**
- * Causes failover by stopping broker on given port and waits till
- * connection is re-established during given time interval.
- *
- * @param port
- * broker port
- * @param delay
- * time interval to wait for connection re-establishement
- */
- private void causeFailure(int port, long delay)
- {
- failBroker(port);
-
- awaitForFailoverCompletion(delay);
- }
-
- private void awaitForFailoverCompletion(long delay)
- {
- _logger.info("Awaiting Failover completion..");
- try
- {
- if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS))
- {
- fail("Failover did not complete");
- }
- }
- catch (InterruptedException e)
- {
- fail("Test was interrupted:" + e.getMessage());
- }
- }
-
- private void assertFailoverException()
- {
- // TODO: assert exception is received (once implemented)
- // along with error code and/or expected exception type
- }
-
- @Override
- public void bytesSent(long count)
- {
- }
-
- @Override
- public void bytesReceived(long count)
- {
- }
-
- @Override
- public boolean preFailover(boolean redirect)
- {
- return true;
- }
-
- @Override
- public boolean preResubscribe()
- {
- return true;
- }
-
- @Override
- public void failoverComplete()
- {
- _failoverComplete.countDown();
- }
-
- @Override
- public void onException(JMSException e)
- {
- _exceptionListenerException = e;
- }
-
- private class FailoverTestMessageListener implements MessageListener
- {
- // message counter
- private AtomicInteger _counter = new AtomicInteger();
-
- private List<Message> _receivedMessage = new ArrayList<Message>();
-
- private volatile CountDownLatch _endLatch;
-
- public FailoverTestMessageListener() throws JMSException
- {
- _endLatch = new CountDownLatch(1);
- }
-
- @Override
- public void onMessage(Message message)
- {
- _receivedMessage.add(message);
- if (_counter.incrementAndGet() % _messageNumber == 0)
- {
- _endLatch.countDown();
- }
- }
-
- public void reset()
- {
- _receivedMessage.clear();
- _endLatch = new CountDownLatch(1);
- _counter.set(0);
- }
-
- public List<Message> getReceivedMessages()
- {
- return _receivedMessage;
- }
-
- public Object awaitForEnd() throws InterruptedException
- {
- return _endLatch.await((long) _messageNumber, TimeUnit.SECONDS);
- }
-
- public int getMessageCounter()
- {
- return _counter.get();
- }
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java b/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java
index bf96dae02e..004ce5ea8f 100644
--- a/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/message/AMQPEncodedMapMessageTest.java
@@ -27,7 +27,6 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
import javax.jms.Connection;
import javax.jms.JMSException;
@@ -52,7 +51,6 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
private Session _session;
MessageConsumer _consumer;
MessageProducer _producer;
- UUID myUUID = UUID.randomUUID();
public void setUp() throws Exception
{
@@ -121,8 +119,7 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
m.setFloat("Float", Integer.MAX_VALUE + 5000);
m.setInt("Int", Integer.MAX_VALUE - 5000);
m.setShort("Short", (short)58);
- m.setString("String", "Hello");
- m.setObject("uuid", myUUID);
+ m.setString("String", "Hello");
_producer.send(m);
AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT);
@@ -143,7 +140,6 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
assertEquals(Integer.MAX_VALUE - 5000,m.getInt("Int"));
assertEquals((short)58,m.getShort("Short"));
assertEquals("Hello",m.getString("String"));
- assertEquals(myUUID,(UUID)m.getObject("uuid"));
}
@@ -153,11 +149,7 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
List<Integer> myList = getList();
- m.setObject("List", myList);
-
- List<UUID> uuidList = new ArrayList<UUID>();
- uuidList.add(myUUID);
- m.setObject("uuid-list", uuidList);
+ m.setObject("List", myList);
_producer.send(m);
AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT);
@@ -175,10 +167,6 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
assertEquals(i,j.intValue());
i++;
}
-
- List<UUID> list2 = (List<UUID>)msg.getObject("uuid-list");
- assertNotNull("UUID List not received",list2);
- assertEquals(myUUID,list2.get(0));
}
public void testMessageWithMapEntries() throws JMSException
@@ -186,12 +174,8 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
MapMessage m = _session.createMapMessage();
Map<String,String> myMap = getMap();
- m.setObject("Map", myMap);
-
- Map<String,UUID> uuidMap = new HashMap<String,UUID>();
- uuidMap.put("uuid", myUUID);
- m.setObject("uuid-map", uuidMap);
+ m.setObject("Map", myMap);
_producer.send(m);
AMQPEncodedMapMessage msg = (AMQPEncodedMapMessage)_consumer.receive(RECEIVE_TIMEOUT);
@@ -207,10 +191,6 @@ public class AMQPEncodedMapMessageTest extends QpidBrokerTestCase
assertEquals("String" + i,map.get("Key" + i));
i++;
}
-
- Map<String,UUID> map2 = (Map<String,UUID>)msg.getObject("uuid-map");
- assertNotNull("Map not received",map2);
- assertEquals(myUUID,map2.get("uuid"));
}
public void testMessageWithNestedListsAndMaps() throws JMSException
diff --git a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
index d754979ab9..8cdf12eaa4 100644
--- a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java
@@ -31,72 +31,62 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.transport.Connection;
public class SSLTest extends QpidBrokerTestCase
-{
- private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks";
- private static final String KEYSTORE_PASSWORD = "password";
- private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks";
- private static final String TRUSTSTORE_PASSWORD = "password";
- private static final String CERT_ALIAS_APP1 = "app1";
- private static final String CERT_ALIAS_APP2 = "app2";
-
+{
+
@Override
protected void setUp() throws Exception
{
- if(isJavaBroker())
- {
- setTestClientSystemProperty("profile.use_ssl", "true");
- setConfigurationProperty("connector.ssl.enabled", "true");
- setConfigurationProperty("connector.ssl.sslOnly", "true");
- }
-
- // set the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
- setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
- setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
- setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
- setSystemProperty("javax.net.debug", "ssl");
+ System.setProperty("javax.net.debug", "ssl");
super.setUp();
}
- public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception
+ @Override
+ protected void tearDown() throws Exception
+ {
+ System.setProperty("javax.net.debug", "");
+ super.tearDown();
+ }
+
+ public void testCreateSSLContextFromConnectionURLParams()
{
if (Boolean.getBoolean("profile.use_ssl"))
- {
- // Clear the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", null);
- setSystemProperty("javax.net.ssl.keyStorePassword", null);
- setSystemProperty("javax.net.ssl.trustStore", null);
- setSystemProperty("javax.net.ssl.trustStorePassword", null);
-
+ {
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
"?ssl='true'&ssl_verify_hostname='true'" +
"&key_store='%s'&key_store_password='%s'" +
"&trust_store='%s'&trust_store_password='%s'" +
"'";
- url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT,
- KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD);
+ String keyStore = System.getProperty("javax.net.ssl.keyStore");
+ String keyStorePass = System.getProperty("javax.net.ssl.keyStorePassword");
+ String trustStore = System.getProperty("javax.net.ssl.trustStore");
+ String trustStorePass = System.getProperty("javax.net.ssl.trustStorePassword");
- AMQConnection con = new AMQConnection(url);
- assertNotNull("connection should be successful", con);
- Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
- assertNotNull("create session should be successful", ssn);
- }
- }
-
- public void testCreateSSLConnectionUsingSystemProperties() throws Exception
- {
- if (Boolean.getBoolean("profile.use_ssl"))
- {
-
- String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s?ssl='true''";
-
- url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT);
+ url = String.format(url,System.getProperty("test.port.ssl"),
+ keyStore,keyStorePass,trustStore,trustStorePass);
- AMQConnection con = new AMQConnection(url);
- assertNotNull("connection should be successful", con);
- Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
- assertNotNull("create session should be successful", ssn);
+ // temporarily set the trust/key store jvm args to something else
+ // to ensure we only read from the connection URL param.
+ System.setProperty("javax.net.ssl.trustStore","fessgsdgd");
+ System.setProperty("javax.net.ssl.trustStorePassword","fessgsdgd");
+ System.setProperty("javax.net.ssl.keyStore","fessgsdgd");
+ System.setProperty("javax.net.ssl.keyStorePassword","fessgsdgd");
+ try
+ {
+ AMQConnection con = new AMQConnection(url);
+ Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
+ }
+ catch (Exception e)
+ {
+ fail("SSL Connection should be successful");
+ }
+ finally
+ {
+ System.setProperty("javax.net.ssl.trustStore",trustStore);
+ System.setProperty("javax.net.ssl.trustStorePassword",trustStorePass);
+ System.setProperty("javax.net.ssl.keyStore",keyStore);
+ System.setProperty("javax.net.ssl.keyStorePassword",keyStorePass);
+ }
}
}
@@ -105,8 +95,8 @@ public class SSLTest extends QpidBrokerTestCase
if (Boolean.getBoolean("profile.use_ssl"))
{
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" +
- QpidBrokerTestCase.DEFAULT_SSL_PORT +
- "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP1 + "''";
+ System.getProperty("test.port.ssl") +
+ "?ssl='true'&ssl_cert_alias='app1''";
AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url);
Connection transportCon = con.getConnection();
@@ -115,8 +105,8 @@ public class SSLTest extends QpidBrokerTestCase
con.close();
url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" +
- QpidBrokerTestCase.DEFAULT_SSL_PORT +
- "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP2 + "''";
+ System.getProperty("test.port.ssl") +
+ "?ssl='true'&ssl_cert_alias='app2''";
con = new AMQTestConnection_0_10(url);
transportCon = con.getConnection();
@@ -126,12 +116,12 @@ public class SSLTest extends QpidBrokerTestCase
}
}
- public void testVerifyHostNameWithIncorrectHostname()
+ public void testVerifyHostName()
{
if (Boolean.getBoolean("profile.use_ssl"))
{
String url = "amqp://guest:guest@test/?brokerlist='tcp://127.0.0.1:" +
- QpidBrokerTestCase.DEFAULT_SSL_PORT +
+ System.getProperty("test.port.ssl") +
"?ssl='true'&ssl_verify_hostname='true''";
try
@@ -150,53 +140,42 @@ public class SSLTest extends QpidBrokerTestCase
}
}
- public void testVerifyLocalHost() throws Exception
+ public void testVerifyLocalHost()
{
if (Boolean.getBoolean("profile.use_ssl"))
{
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" +
- QpidBrokerTestCase.DEFAULT_SSL_PORT +
+ System.getProperty("test.port.ssl") +
"?ssl='true'&ssl_verify_hostname='true''";
-
- AMQConnection con = new AMQConnection(url);
- assertNotNull("connection should have been created", con);
- }
+
+ try
+ {
+ AMQConnection con = new AMQConnection(url);
+ }
+ catch (Exception e)
+ {
+ fail("Hostname verification should succeed");
+ }
+ }
}
- public void testVerifyLocalHostLocalDomain() throws Exception
+ public void testVerifyLocalHostLocalDomain()
{
if (Boolean.getBoolean("profile.use_ssl"))
{
String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost.localdomain:" +
- QpidBrokerTestCase.DEFAULT_SSL_PORT +
+ System.getProperty("test.port.ssl") +
"?ssl='true'&ssl_verify_hostname='true''";
-
- AMQConnection con = new AMQConnection(url);
- assertNotNull("connection should have been created", con);
- }
- }
-
- public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception
- {
- if (Boolean.getBoolean("profile.use_ssl"))
- {
- // Clear the ssl system properties
- setSystemProperty("javax.net.ssl.keyStore", null);
- setSystemProperty("javax.net.ssl.keyStorePassword", null);
- setSystemProperty("javax.net.ssl.trustStore", null);
- setSystemProperty("javax.net.ssl.trustStorePassword", null);
- String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
- "?ssl='true'&ssl_verify_hostname='true'" +
- "&trust_store='%s'&trust_store_password='%s'" +
- "'";
-
- url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, TRUSTSTORE,TRUSTSTORE_PASSWORD);
-
- AMQConnection con = new AMQConnection(url);
- assertNotNull("connection should be successful", con);
- Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
- assertNotNull("create session should be successful", ssn);
+ try
+ {
+ AMQConnection con = new AMQConnection(url);
+ }
+ catch (Exception e)
+ {
+ fail("Hostname verification should succeed");
+ }
+
}
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java b/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java
deleted file mode 100644
index d7ee203fdf..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/jms/xa/XAResourceTest.java
+++ /dev/null
@@ -1,116 +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.
- *
- */
-package org.apache.qpid.jms.xa;
-
-import javax.jms.XAConnection;
-import javax.jms.XAConnectionFactory;
-import javax.jms.XASession;
-import javax.transaction.xa.XAResource;
-
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.util.FileUtils;
-
-public class XAResourceTest extends QpidBrokerTestCase
-{
-
- private static final String FACTORY_NAME = "default";
- private static final String ALT_FACTORY_NAME = "connection2";
-
- /*
- * Test with multiple XAResources originating from the same connection factory. XAResource(s) will be equal,
- * as they originate from the same session.
- */
- public void testIsSameRMSingleCF() throws Exception
- {
- XAConnectionFactory factory = getConnectionFactory(FACTORY_NAME);
- XAConnection conn = factory.createXAConnection();
- XASession session = conn.createXASession();
- XAResource xaResource1 = session.getXAResource();
- XAResource xaResource2 = session.getXAResource();
-
- assertEquals("XAResource objects not equal", xaResource1, xaResource2);
- assertTrue("isSameRM not true for identical objects", xaResource1.isSameRM(xaResource2));
-
- session.close();
- conn.close();
- }
-
- /*
- * Test with multiple XAResources originating from different connection factory's and different sessions. XAResources will not be
- * equal as they do not originate from the same session. As the UUID from the broker will be the same, isSameRM will be true.
- *
- */
- public void testIsSameRMMultiCF() throws Exception
- {
- startBroker(FAILING_PORT);
- ConnectionURL url = getConnectionFactory(FACTORY_NAME).getConnectionURL();
- XAConnectionFactory factory = new AMQConnectionFactory(url);
- XAConnectionFactory factory2 = new AMQConnectionFactory(url);
- XAConnectionFactory factory3 = getConnectionFactory(ALT_FACTORY_NAME);
-
- XAConnection conn = factory.createXAConnection();
- XAConnection conn2 = factory2.createXAConnection();
- XAConnection conn3 = factory3.createXAConnection();
-
- XASession session = conn.createXASession();
- XASession session2 = conn2.createXASession();
- XASession session3 = conn3.createXASession();
-
- XAResource xaResource1 = session.getXAResource();
- XAResource xaResource2 = session2.getXAResource();
- XAResource xaResource3 = session3.getXAResource();
-
- assertFalse("XAResource objects should not be equal", xaResource1.equals(xaResource2));
- assertTrue("isSameRM not true for identical objects", xaResource1.isSameRM(xaResource2));
- assertFalse("isSameRM true for XA Resources created by two different brokers", xaResource1.isSameRM(xaResource3));
-
- conn.close();
- conn2.close();
- conn3.close();
- }
-
- @Override
- public void stopBroker(int port) throws Exception
- {
- if (isBrokerPresent(port))
- {
- super.stopBroker(port);
- }
- }
-
- @Override
- public void tearDown() throws Exception
- {
- try
- {
- super.tearDown();
- }
- finally
- {
- // Ensure we shutdown any secondary brokers
- stopBroker(FAILING_PORT);
- FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort());
- }
- }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java
index 12a1682212..19657ef396 100644
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/management/jmx/ManagementActorLoggingTest.java
@@ -68,6 +68,61 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
/**
* Description:
+ * When a JMX Management connection is made then this will be logged out.
+ *
+ * Input:
+ *
+ * 1. Running Broker
+ * 2. Connect Management client via JMX
+ * Output:
+ *
+ * <date> MNG-1007 : Open <user>
+ *
+ * Validation Steps:
+ * 1. The MNG ID is correct
+ * 2. The user is correct
+ *
+ * On connection close a MNG-1008 is expected
+ *
+ * * <date> MNG-1008 : Close
+ *
+ * Validation Steps:
+ * 1. The MNG ID is correct
+ *
+ * @throws java.io.IOException - if there is a problem reseting the log monitor
+ */
+ public void testJMXManagementConsoleConnection() throws IOException
+ {
+ List<String> results = waitAndFindMatches("MNG-1007");
+
+ assertEquals("Unexpected Management Connection count", 1, results.size());
+
+ String log = getLogMessage(results, 0);
+
+ validateMessageID("MNG-1007", log);
+
+ assertTrue("User not in log message:" + log, log.endsWith(USER));
+ // Extract the id from the log string
+ // MESSAGE [mng:1(rmi://169.24.29.116)] MNG-1007 : Open : User admin
+ int connectionID = Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + "");
+
+ results = findMatches("MNG-1008");
+
+ assertEquals("Unexpected Management Connection close count", 0, results.size());
+
+ _jmxUtils.close();
+ _closed = true;
+
+ results = waitAndFindMatches("MNG-1008");
+
+ assertEquals("Unexpected Management Connection count", 1, results.size());
+
+ assertEquals("Close does not have same id as open,", connectionID,
+ Integer.parseInt(fromActor(getLog(results.get(0))).charAt(4) + ""));
+ }
+
+ /**
+ * Description:
* When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message.
* Input:
*
@@ -106,7 +161,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
});
//Remove the connection close from any 0-10 connections
- _monitor.markDiscardPoint();
+ _monitor.reset();
// Get a managedConnection
ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*");
@@ -147,7 +202,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
*/
public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException
{
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createExchange("test", getName(), "direct", false);
@@ -171,7 +226,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException
{
//Remove any previous exchange declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createExchange("test", getName(), "topic", false);
@@ -196,7 +251,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException
{
//Remove any previous exchange declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createExchange("test", getName(), "fanout", false);
@@ -221,7 +276,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException
{
//Remove any previous exchange declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createExchange("test", getName(), "headers", false);
@@ -265,7 +320,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createQueue("test", getName(), null, false);
@@ -308,7 +363,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testQueueDeleteViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createQueue("test", getName(), null, false);
@@ -354,7 +409,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createQueue("test", getName(), null, false);
@@ -381,7 +436,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createQueue("test", getName(), null, false);
@@ -408,7 +463,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createQueue("test", getName(), null, false);
@@ -455,7 +510,7 @@ public class ManagementActorLoggingTest extends AbstractTestLogging
public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException
{
//Remove any previous queue declares
- _monitor.markDiscardPoint();
+ _monitor.reset();
_jmxUtils.createExchange("test", getName(), "direct", false);
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java
deleted file mode 100644
index 9839c6e475..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageConnectionStatisticsTest.java
+++ /dev/null
@@ -1,102 +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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jms.Connection;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-/**
- * Test enabling generation of message statistics on a per-connection basis.
- */
-public class MessageConnectionStatisticsTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- // no statistics generation configured
- }
-
- /**
- * Test statistics on a single connection
- */
- public void testEnablingStatisticsPerConnection() throws Exception
- {
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
-
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- List<String> addresses = new ArrayList<String>();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
-
- addresses.add(mc.getRemoteAddress());
- }
- assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
-
- Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- test.start();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- continue;
- }
- mc.setStatisticsEnabled(true);
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- }
-
- sendUsing(test, 5, 200);
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
- else
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
- }
- assertEquals("Incorrect vhost total", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- test.close();
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java
deleted file mode 100644
index 383c4c00a8..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsConfigurationTest.java
+++ /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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-/**
- * Test enabling generation of message statistics on a per-connection basis.
- */
-public class MessageStatisticsConfigurationTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", Boolean.toString(getName().contains("Broker")));
- setConfigurationProperty("statistics.generation.virtualhosts", Boolean.toString(getName().contains("Virtualhost")));
- setConfigurationProperty("statistics.generation.connections", Boolean.toString(getName().contains("Connection")));
- }
-
- /**
- * Just broker statistics.
- */
- public void testGenerateBrokerStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Just virtualhost statistics.
- */
- public void testGenerateVirtualhostStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Just connection statistics.
- */
- public void testGenerateConnectionStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 0, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 0, vhost.getTotalDataReceived());
- assertFalse("Vhost statistics should not be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 0, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 0, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertFalse("Server statistics should not be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Both broker and virtualhost statistics.
- */
- public void testGenerateBrokerAndVirtualhostStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 0, mc.getTotalDataReceived());
- assertFalse("Connection statistics should not be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-
- /**
- * Broker, virtualhost and connection statistics.
- */
- public void testGenerateBrokerVirtualhostAndConnectionStatistics() throws Exception
- {
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection data", 1000, mc.getTotalDataReceived());
- assertTrue("Connection statistics should be enabled", mc.isStatisticsEnabled());
- }
-
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
- assertEquals("Incorrect vhost data", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost data", 1000, vhost.getTotalDataReceived());
- assertTrue("Vhost statistics should be enabled", vhost.isStatisticsEnabled());
-
- assertEquals("Incorrect server total messages", 5, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 1000, _jmxUtils.getServerInformation().getTotalDataReceived());
- assertTrue("Server statistics should be enabled", _jmxUtils.getServerInformation().isStatisticsEnabled());
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java
deleted file mode 100644
index c374d23473..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsDeliveryTest.java
+++ /dev/null
@@ -1,110 +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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.Session;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-/**
- * Test statistics for delivery and receipt.
- */
-public class MessageStatisticsDeliveryTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", "true");
- setConfigurationProperty("statistics.generation.virtualhosts", "true");
- setConfigurationProperty("statistics.generation.connections", "true");
- }
-
- public void testDeliveryAndReceiptStatistics() throws Exception
- {
- ManagedBroker vhost = _jmxUtils.getManagedBroker("test");
-
- sendUsing(_test, 5, 200);
- Thread.sleep(1000);
-
- List<String> addresses = new ArrayList<String>();
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived());
-
- addresses.add(mc.getRemoteAddress());
- }
-
- assertEquals("Incorrect vhost delivery total", 0, vhost.getTotalMessagesDelivered());
- assertEquals("Incorrect vhost delivery data", 0, vhost.getTotalDataDelivered());
- assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived());
-
- Connection test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- test.start();
- receiveUsing(test, 5);
-
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- if (addresses.contains(mc.getRemoteAddress()))
- {
- assertEquals("Incorrect connection delivery total", 0, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 0, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 5, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 1000, mc.getTotalDataReceived());
- }
- else
- {
- assertEquals("Incorrect connection delivery total", 5, mc.getTotalMessagesDelivered());
- assertEquals("Incorrect connection delivery data", 1000, mc.getTotalDataDelivered());
- assertEquals("Incorrect connection receipt total", 0, mc.getTotalMessagesReceived());
- assertEquals("Incorrect connection receipt data", 0, mc.getTotalDataReceived());
- }
- }
- assertEquals("Incorrect vhost delivery total", 5, vhost.getTotalMessagesDelivered());
- assertEquals("Incorrect vhost delivery data", 1000, vhost.getTotalDataDelivered());
- assertEquals("Incorrect vhost receipt total", 5, vhost.getTotalMessagesReceived());
- assertEquals("Incorrect vhost receipt data", 1000, vhost.getTotalDataReceived());
-
- test.close();
- }
-
- protected void receiveUsing(Connection con, int number) throws Exception
- {
- Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- createQueue(session);
- MessageConsumer consumer = session.createConsumer(_queue);
- for (int i = 0; i < number; i++)
- {
- Message msg = consumer.receive(1000);
- assertNotNull("Message " + i + " was not received", msg);
- }
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java
deleted file mode 100644
index 180440c0d6..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsReportingTest.java
+++ /dev/null
@@ -1,90 +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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import java.util.List;
-
-import org.apache.qpid.util.LogMonitor;
-
-/**
- * Test generation of message statistics reporting.
- */
-public class MessageStatisticsReportingTest extends MessageStatisticsTestCase
-{
- protected LogMonitor _monitor;
-
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", "true");
- setConfigurationProperty("statistics.generation.virtualhosts", "true");
-
- if (getName().equals("testEnabledStatisticsReporting"))
- {
- setConfigurationProperty("statistics.reporting.period", "10");
- }
-
- _monitor = new LogMonitor(_outputFile);
- }
-
- /**
- * Test enabling reporting.
- */
- public void testEnabledStatisticsReporting() throws Exception
- {
- sendUsing(_test, 10, 100);
- sendUsing(_dev, 20, 100);
- sendUsing(_local, 15, 100);
-
- Thread.sleep(10 * 1000); // 15s
-
- List<String> brokerStatsData = _monitor.findMatches("BRK-1008");
- List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009");
- List<String> vhostStatsData = _monitor.findMatches("VHT-1003");
- List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004");
-
- assertEquals("Incorrect number of broker data stats log messages", 2, brokerStatsData.size());
- assertEquals("Incorrect number of broker message stats log messages", 2, brokerStatsMessages.size());
- assertEquals("Incorrect number of virtualhost data stats log messages", 6, vhostStatsData.size());
- assertEquals("Incorrect number of virtualhost message stats log messages", 6, vhostStatsMessages.size());
- }
-
- /**
- * Test not enabling reporting.
- */
- public void testNotEnabledStatisticsReporting() throws Exception
- {
- sendUsing(_test, 10, 100);
- sendUsing(_dev, 20, 100);
- sendUsing(_local, 15, 100);
-
- Thread.sleep(10 * 1000); // 15s
-
- List<String> brokerStatsData = _monitor.findMatches("BRK-1008");
- List<String> brokerStatsMessages = _monitor.findMatches("BRK-1009");
- List<String> vhostStatsData = _monitor.findMatches("VHT-1003");
- List<String> vhostStatsMessages = _monitor.findMatches("VHT-1004");
-
- assertEquals("Incorrect number of broker data stats log messages", 0, brokerStatsData.size());
- assertEquals("Incorrect number of broker message stats log messages", 0, brokerStatsMessages.size());
- assertEquals("Incorrect number of virtualhost data stats log messages", 0, vhostStatsData.size());
- assertEquals("Incorrect number of virtualhost message stats log messages", 0, vhostStatsMessages.size());
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
deleted file mode 100644
index 824ae41b97..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTest.java
+++ /dev/null
@@ -1,218 +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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import javax.jms.Connection;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
-
-/**
- * Test generation of message statistics.
- */
-public class MessageStatisticsTest extends MessageStatisticsTestCase
-{
- public void configureStatistics() throws Exception
- {
- setConfigurationProperty("statistics.generation.broker", "true");
- setConfigurationProperty("statistics.generation.virtualhosts", "true");
- setConfigurationProperty("statistics.generation.connections", "true");
- }
-
- /**
- * Test message totals.
- */
- public void testMessageTotals() throws Exception
- {
- sendUsing(_test, 10, 100);
- sendUsing(_dev, 20, 100);
- sendUsing(_local, 5, 100);
- sendUsing(_local, 5, 100);
- sendUsing(_local, 5, 100);
- Thread.sleep(2000);
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
- ManagedBroker dev = _jmxUtils.getManagedBroker("development");
- ManagedBroker local = _jmxUtils.getManagedBroker("localhost");
-
- if (!isBroker010())
- {
- long total = 0;
- long data = 0;
- for (ManagedConnection mc : _jmxUtils.getAllManagedConnections())
- {
- total += mc.getTotalMessagesReceived();
- data += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect connection total", 45, total);
- assertEquals("Incorrect connection data", 4500, data);
- }
- assertEquals("Incorrect server total", 45, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server data", 4500, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- if (!isBroker010())
- {
- long testTotal = 0;
- long testData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- testTotal += mc.getTotalMessagesReceived();
- testData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 10, testTotal);
- assertEquals("Incorrect test connection data", 1000, testData);
- }
- assertEquals("Incorrect test vhost total", 10, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost data", 1000, test.getTotalDataReceived());
-
- if (!isBroker010())
- {
- long devTotal = 0;
- long devData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("development"))
- {
- devTotal += mc.getTotalMessagesReceived();
- devData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 20, devTotal);
- assertEquals("Incorrect test connection data", 2000, devData);
- }
- assertEquals("Incorrect development total", 20, dev.getTotalMessagesReceived());
- assertEquals("Incorrect development data", 2000, dev.getTotalDataReceived());
-
- if (!isBroker010())
- {
- long localTotal = 0;
- long localData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("localhost"))
- {
- localTotal += mc.getTotalMessagesReceived();
- localData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test connection total", 15, localTotal);
- assertEquals("Incorrect test connection data", 1500, localData);
- }
- assertEquals("Incorrect localhost total", 15, local.getTotalMessagesReceived());
- assertEquals("Incorrect localhost data", 1500, local.getTotalDataReceived());
- }
-
- /**
- * Test message totals when a connection is closed.
- */
- public void testMessageTotalsWithClosedConnections() throws Exception
- {
- Connection temp = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- temp.start();
-
- sendUsing(_test, 10, 100);
- sendUsing(temp, 10, 100);
- sendUsing(_test, 10, 100);
- Thread.sleep(2000);
-
- temp.close();
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
-
- if (!isBroker010())
- {
- long total = 0;
- long data = 0;
- for (ManagedConnection mc : _jmxUtils.getAllManagedConnections())
- {
- total += mc.getTotalMessagesReceived();
- data += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect active connection total", 20, total);
- assertEquals("Incorrect active connection data", 2000, data);
- }
- assertEquals("Incorrect server total", 30, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server data", 3000, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- if (!isBroker010())
- {
- long testTotal = 0;
- long testData = 0;
- for (ManagedConnection mc : _jmxUtils.getManagedConnections("test"))
- {
- testTotal += mc.getTotalMessagesReceived();
- testData += mc.getTotalDataReceived();
- }
- assertEquals("Incorrect test active connection total", 20, testTotal);
- assertEquals("Incorrect test active connection data", 20 * 100, testData);
- }
- assertEquals("Incorrect test vhost total", 30, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost data", 30 * 100, test.getTotalDataReceived());
- }
-
- /**
- * Test message peak rate generation.
- */
- public void testMessagePeakRates() throws Exception
- {
- sendUsing(_test, 2, 10);
- Thread.sleep(10000);
- sendUsing(_dev, 4, 10);
- Thread.sleep(10000);
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
- ManagedBroker dev = _jmxUtils.getManagedBroker("development");
-
- assertApprox("Incorrect test vhost peak messages", 0.2d, 1.0d, test.getPeakMessageReceiptRate());
- assertApprox("Incorrect test vhost peak data", 0.2d, 10.0d, test.getPeakDataReceiptRate());
- assertApprox("Incorrect dev vhost peak messages", 0.2d, 2.0d, dev.getPeakMessageReceiptRate());
- assertApprox("Incorrect dev vhost peak data", 0.2d, 20.0d, dev.getPeakDataReceiptRate());
-
- assertApprox("Incorrect server peak messages", 0.2d, 2.0d, _jmxUtils.getServerInformation().getPeakMessageReceiptRate());
- assertApprox("Incorrect server peak data", 0.2d, 20.0d, _jmxUtils.getServerInformation().getPeakDataReceiptRate());
- }
-
- /**
- * Test message totals when a vhost has its statistics reset
- */
- public void testMessageTotalVhostReset() throws Exception
- {
- sendUsing(_test, 10, 10);
- sendUsing(_dev, 10, 10);
- Thread.sleep(2000);
-
- ManagedBroker test = _jmxUtils.getManagedBroker("test");
- ManagedBroker dev = _jmxUtils.getManagedBroker("development");
-
- assertEquals("Incorrect test vhost total messages", 10, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost total data", 100, test.getTotalDataReceived());
- assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived());
- assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived());
-
- assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived());
-
- test.resetStatistics();
-
- assertEquals("Incorrect test vhost total messages", 0, test.getTotalMessagesReceived());
- assertEquals("Incorrect test vhost total data", 0, test.getTotalDataReceived());
- assertEquals("Incorrect dev vhost total messages", 10, dev.getTotalMessagesReceived());
- assertEquals("Incorrect dev vhost total data", 100, dev.getTotalDataReceived());
-
- assertEquals("Incorrect server total messages", 20, _jmxUtils.getServerInformation().getTotalMessagesReceived());
- assertEquals("Incorrect server total data", 200, _jmxUtils.getServerInformation().getTotalDataReceived());
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java b/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java
deleted file mode 100644
index a5b3aa283c..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/management/jmx/MessageStatisticsTestCase.java
+++ /dev/null
@@ -1,128 +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.
- *
- */
-package org.apache.qpid.management.jmx;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.test.utils.JMXTestUtils;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-/**
- * Test generation of message statistics.
- */
-public abstract class MessageStatisticsTestCase extends QpidBrokerTestCase
-{
- protected static final String USER = "admin";
-
- protected JMXTestUtils _jmxUtils;
- protected Connection _test, _dev, _local;
- protected String _queueName = "statistics";
- protected Destination _queue;
- protected String _brokerUrl;
-
- @Override
- public void setUp() throws Exception
- {
- _jmxUtils = new JMXTestUtils(this, USER, USER);
- _jmxUtils.setUp();
-
- configureStatistics();
-
- super.setUp();
-
- _brokerUrl = getBroker().toString();
- _test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
- _dev = new AMQConnection(_brokerUrl, USER, USER, "clientid", "development");
- _local = new AMQConnection(_brokerUrl, USER, USER, "clientid", "localhost");
-
- _test.start();
- _dev.start();
- _local.start();
-
- _jmxUtils.open();
- }
-
- protected void createQueue(Session session) throws AMQException, JMSException
- {
- _queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName);
- if (!((AMQSession<?,?>) session).isQueueBound((AMQDestination) _queue))
- {
- ((AMQSession<?,?>) session).createQueue(new AMQShortString(_queueName), false, true, false, null);
- ((AMQSession<?,?>) session).declareAndBind((AMQDestination) new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, _queueName));
- }
- }
-
-
- @Override
- public void tearDown() throws Exception
- {
- _jmxUtils.close();
-
- _test.close();
- _dev.close();
- _local.close();
-
- super.tearDown();
- }
-
- /**
- * Configure statistics generation properties on the broker.
- */
- public abstract void configureStatistics() throws Exception;
-
- protected void sendUsing(Connection con, int number, int size) throws Exception
- {
- Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
- createQueue(session);
- MessageProducer producer = session.createProducer(_queue);
- String content = new String(new byte[size]);
- TextMessage msg = session.createTextMessage(content);
- for (int i = 0; i < number; i++)
- {
- producer.send(msg);
- }
- }
-
- /**
- * Asserts that the actual value is within the expected value plus or
- * minus the given error.
- */
- public void assertApprox(String message, double error, double expected, double actual)
- {
- double min = expected * (1.0d - error);
- double max = expected * (1.0d + error);
- String assertion = String.format("%s: expected %f +/- %d%%, actual %f",
- message, expected, (int) (error * 100.0d), actual);
- assertTrue(assertion, actual > min && actual < max);
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java
index 27b4de0a8e..f9227c53ba 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java
@@ -70,13 +70,13 @@ public class BrokerStartupTest extends AbstractTestLogging
{
// This logging startup code only occurs when you run a Java broker,
// that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker() && !isInternalBroker())
+ if (isJavaBroker() && isExternalBroker())
{
//Remove test Log4j config from the commandline
- _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l"));
+ _broker = _broker.substring(0, _broker.indexOf("-l"));
// Add an invalid value
- _brokerCommand += " -l invalid";
+ _broker += " -l invalid";
// The broker has a built in default log4j configuration set up
// so if the the broker cannot load the -l value it will use default
diff --git a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java
index 6d379e14d8..d4c550bc08 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java
@@ -61,6 +61,21 @@ public class ServerConfigurationFileTest extends QpidBrokerTestCase
_serverConfig.getConfig().getProperty(property));
}
+ public void testProtectIOEnabled() throws ConfigurationException
+ {
+ validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_ENABLED);
+ }
+
+ public void testProtectIOReadBufferLimitSize() throws ConfigurationException
+ {
+ validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE);
+ }
+
+ public void testProtectIOWriteBufferLimitSize() throws ConfigurationException
+ {
+ validatePropertyDefinedInFile(ServerConfiguration.CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE);
+ }
+
public void testStatusUpdates() throws ConfigurationException
{
validatePropertyDefinedInFile(ServerConfiguration.STATUS_UPDATES);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
index 4a92f04b30..2d89d319d7 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
@@ -83,9 +83,15 @@ public class MessagingTestConfigProperties
/** Holds the name of the default connection factory configuration property. */
public static final String CONNECTION_PROPNAME = "connectionfactory.broker";
+ /** Defeins the default connection configuration. */
+ public static final String CONNECTION_DEFAULT = "amqp://guest:guest@clientid/?brokerlist='vm://:1'";
+
/** Holds the name of the property to get the test broker url from. */
public static final String BROKER_PROPNAME = "qpid.test.broker";
+ /** Holds the default broker url for the test. */
+ public static final String BROKER_DEFAULT = "vm://:1";
+
/** Holds the name of the property to get the test broker virtual path. */
public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
@@ -268,6 +274,7 @@ public class MessagingTestConfigProperties
static
{
defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+ defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
@@ -277,6 +284,7 @@ public class MessagingTestConfigProperties
defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java b/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java
index 470fcefae3..ec222ff03d 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/failover/FailoverMethodTest.java
@@ -20,40 +20,58 @@
*/
package org.apache.qpid.server.failover;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
+import junit.framework.TestCase;
-import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionListener
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import java.util.concurrent.CountDownLatch;
+
+public class FailoverMethodTest extends InternalBrokerBaseCase implements ExceptionListener
{
private CountDownLatch _failoverComplete = new CountDownLatch(1);
protected static final Logger _logger = LoggerFactory.getLogger(FailoverMethodTest.class);
+ @Override
+ public void createBroker() throws Exception
+ {
+ super.createBroker();
+ TransportConnection.createVMBroker(ApplicationRegistry.DEFAULT_INSTANCE);
+ }
+ @Override
+ public void stopBroker()
+ {
+ TransportConnection.killVMBroker(ApplicationRegistry.DEFAULT_INSTANCE);
+ super.stopBroker();
+ }
/**
* Test that the round robin method has the correct delays.
- * The first connection will work but the localhost connection should fail but the duration it takes
+ * The first connection to vm://:1 will work but the localhost connection should fail but the duration it takes
* to report the failure is what is being tested.
*
+ * @throws URLSyntaxException
+ * @throws InterruptedException
+ * @throws JMSException
*/
- public void testFailoverRoundRobinDelay() throws Exception
+ public void testFailoverRoundRobinDelay() throws URLSyntaxException, InterruptedException, JMSException
{
- //note: The first broker has no connect delay and the default 1 retry
+ //note: The VM broker has no connect delay and the default 1 retry
// while the tcp:localhost broker has 3 retries with a 2s connect delay
String connectionString = "amqp://guest:guest@/test?brokerlist=" +
- "'tcp://:" + getPort() +
+ "'vm://:" + ApplicationRegistry.DEFAULT_INSTANCE +
";tcp://localhost:5670?connectdelay='2000',retries='3''";
AMQConnectionURL url = new AMQConnectionURL(connectionString);
@@ -61,15 +79,13 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
try
{
long start = System.currentTimeMillis();
- AMQConnection connection = new AMQConnection(url);
+ AMQConnection connection = new AMQConnection(url, null);
connection.setExceptionListener(this);
stopBroker();
- _failoverComplete.await(30, TimeUnit.SECONDS);
- assertEquals("failoverLatch was not decremented in given timeframe",
- 0, _failoverComplete.getCount());
+ _failoverComplete.await();
long end = System.currentTimeMillis();
@@ -96,24 +112,23 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
}
}
- public void testFailoverSingleDelay() throws Exception
+ public void testFailoverSingleDelay() throws URLSyntaxException, AMQVMBrokerCreationException,
+ InterruptedException, JMSException
{
- String connectionString = "amqp://guest:guest@/test?brokerlist='tcp://localhost:" + getPort() + "?connectdelay='2000',retries='3''";
+ String connectionString = "amqp://guest:guest@/test?brokerlist='vm://:1?connectdelay='2000',retries='3''";
AMQConnectionURL url = new AMQConnectionURL(connectionString);
try
{
long start = System.currentTimeMillis();
- AMQConnection connection = new AMQConnection(url);
+ AMQConnection connection = new AMQConnection(url, null);
connection.setExceptionListener(this);
stopBroker();
- _failoverComplete.await(30, TimeUnit.SECONDS);
- assertEquals("failoverLatch was not decremented in given timeframe",
- 0, _failoverComplete.getCount());
+ _failoverComplete.await();
long end = System.currentTimeMillis();
@@ -129,8 +144,8 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
assertTrue("Failover took less than 6 seconds", duration > 6000);
// Ensure we don't have delays before initial connection and reconnection.
- // We allow 3 second for initial connection and failover logic on top of 6s of sleep.
- assertTrue("Failover took more than 9 seconds:(" + duration + ")", duration < 9000);
+ // We allow 1 second for initial connection and failover logic on top of 6s of sleep.
+ assertTrue("Failover took more than 7 seconds:(" + duration + ")", duration < 7000);
}
catch (AMQException e)
{
@@ -140,15 +155,11 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
public void onException(JMSException e)
{
- if (e.getLinkedException() instanceof AMQDisconnectedException || e.getLinkedException() instanceof AMQConnectionClosedException)
+ if (e.getLinkedException() instanceof AMQDisconnectedException)
{
_logger.debug("Received AMQDisconnectedException");
_failoverComplete.countDown();
}
- else
- {
- _logger.error("Unexpected underlying exception", e.getLinkedException());
- }
}
/**
@@ -157,37 +168,28 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
*
* Test validates that there is a connection delay as required on initial
* connection.
+ *
+ * @throws URLSyntaxException
+ * @throws AMQVMBrokerCreationException
+ * @throws InterruptedException
+ * @throws JMSException
*/
- public void testNoFailover() throws Exception
+ public void testNoFailover() throws URLSyntaxException, AMQVMBrokerCreationException,
+ InterruptedException, JMSException
{
- if (!isInternalBroker())
- {
- // QPID-3359
- // These tests always used to be inVM tests, then QPID-2815, with removal of ivVM,
- // converted the test to use QpidBrokerTestCase. However, since then we notice this
- // test fails on slower CI boxes. It turns out the test design is *extremely*
- // sensitive the length of time the broker takes to start up.
- //
- // Making the test a same-VM test to temporarily avoid the issue. In long term, test
- // needs redesigned to avoid the issue.
- return;
- }
-
int CONNECT_DELAY = 2000;
- String connectionString = "amqp://guest:guest@/test?brokerlist='tcp://localhost:" + getPort() + "?connectdelay='" + CONNECT_DELAY + "'," +
+ String connectionString = "amqp://guest:guest@/test?brokerlist='vm://:1?connectdelay='" + CONNECT_DELAY + "'," +
"retries='3'',failover='nofailover'";
-
AMQConnectionURL url = new AMQConnectionURL(connectionString);
- Thread brokerStart = null;
try
{
//Kill initial broker
stopBroker();
//Create a thread to start the broker asynchronously
- brokerStart = new Thread(new Runnable()
+ Thread brokerStart = new Thread(new Runnable()
{
public void run()
{
@@ -196,7 +198,7 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
//Wait before starting broker
// The wait should allow atleast 1 retries to fail before broker is ready
Thread.sleep(750);
- startBroker();
+ createBroker();
}
catch (Exception e)
{
@@ -210,8 +212,9 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
brokerStart.start();
long start = System.currentTimeMillis();
+
//Start the connection so it will use the retries
- AMQConnection connection = new AMQConnection(url);
+ AMQConnection connection = new AMQConnection(url, null);
long end = System.currentTimeMillis();
@@ -225,16 +228,13 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
//Ensure we collect the brokerStart thread
brokerStart.join();
- brokerStart = null;
start = System.currentTimeMillis();
//Kill connection
stopBroker();
- _failoverComplete.await(30, TimeUnit.SECONDS);
- assertEquals("failoverLatch was not decremented in given timeframe",
- 0, _failoverComplete.getCount());
+ _failoverComplete.await();
end = System.currentTimeMillis();
@@ -249,23 +249,6 @@ public class FailoverMethodTest extends QpidBrokerTestCase implements ExceptionL
{
fail(e.getMessage());
}
- finally
- {
- // Guard against the case where the broker took too long to start
- // and the initial connection failed to be formed.
- if (brokerStart != null)
- {
- brokerStart.join();
- }
- }
- }
-
- public void stopBroker(int port) throws Exception
- {
- if (isBrokerPresent(port))
- {
- super.stopBroker(port);
- }
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java
index fd33266414..4c2758241e 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/failover/MessageDisappearWithIOExceptionTest.java
@@ -20,10 +20,13 @@
*/
package org.apache.qpid.server.failover;
+import org.apache.mina.common.WriteTimeoutException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.test.utils.FailoverBaseCase;
+import org.apache.qpid.AMQConnectionClosedException;
import javax.jms.Destination;
import javax.jms.Message;
@@ -31,7 +34,6 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -193,7 +195,7 @@ public class MessageDisappearWithIOExceptionTest extends FailoverBaseCase implem
// Send IO Exception - causing failover
_connection.getProtocolHandler().
- exception(new IOException("IOException to cause failover."));
+ exception(new WriteTimeoutException("WriteTimeoutException to cause failover."));
// Verify Failover occured through ConnectionListener
assertTrue("Failover did not occur",
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java
index 484c2afeb5..f56f428f0b 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java
@@ -349,7 +349,7 @@ public class AbstractTestLogging extends QpidBrokerTestCase
public boolean waitForMessage(String message, long wait) throws FileNotFoundException, IOException
{
- return _monitor.waitForMessage(message, wait);
+ return _monitor.waitForMessage(message, wait, true);
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
index aef98b8a2a..05aaf16af1 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
@@ -46,7 +46,7 @@ public class AlertingTest extends AbstractTestLogging
{
// Update the configuration to make our virtualhost Persistent.
makeVirtualHostPersistent(VIRTUALHOST);
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "5000");
+ setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.expiredMessageCheckPeriod", "5000");
_numMessages = 50;
@@ -136,7 +136,7 @@ public class AlertingTest extends AbstractTestLogging
stopBroker();
// Rest the monitoring clearing the current output file.
- _monitor.markDiscardPoint();
+ _monitor.reset();
startBroker();
wasAlertFired();
}
@@ -169,14 +169,14 @@ public class AlertingTest extends AbstractTestLogging
stopBroker();
- _monitor.markDiscardPoint();
+ _monitor.reset();
// Change max message count to 5, start broker and make sure that that's triggered at the right time
setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5");
startBroker();
- if (isInternalBroker())
+ if (!isExternalBroker())
{
assertEquals("Alert Max Msg Count is not correct", 5, ApplicationRegistry.getInstance().getVirtualHostRegistry().
getVirtualHost(VIRTUALHOST).getQueueRegistry().getQueue(new AMQShortString(_destination.getQueueName())).
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
index be2da128bc..97914f84a5 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BindingLoggingTest.java
@@ -55,7 +55,7 @@ public class BindingLoggingTest extends AbstractTestLogging
{
super.setUp();
//Ignore broker startup messages
- _monitor.markDiscardPoint();
+ _monitor.reset();
_connection = getConnection();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
index 7969ffc059..8fd2c085c3 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
@@ -21,8 +21,6 @@
package org.apache.qpid.server.logging;
import junit.framework.AssertionFailedError;
-
-import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.Main;
import org.apache.qpid.transport.ConnectionException;
import org.apache.qpid.util.LogMonitor;
@@ -153,12 +151,12 @@ public class BrokerLoggingTest extends AbstractTestLogging
{
// This logging startup code only occurs when you run a Java broker,
// that broker must be started via Main so not an InVM broker.
- if (isJavaBroker() && isExternalBroker() && !isInternalBroker())
+ if (isJavaBroker() && isExternalBroker())
{
String TESTID = "BRK-1007";
//Remove test Log4j config from the commandline
- _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l"));
+ _broker = _broker.substring(0, _broker.indexOf("-l"));
startBroker();
@@ -205,7 +203,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
1, findMatches(TESTID).size());
//3
- String defaultLog4j = System.getProperty(QPID_HOME) + "/" + BrokerOptions.DEFAULT_LOG_CONFIG_FILE;
+ String defaultLog4j = _configFile.getParent() + "/" + Main.DEFAULT_LOG_CONFIG_FILENAME;
assertTrue("Log4j file(" + defaultLog4j + ") details not correctly logged:" + getMessageString(log),
getMessageString(log).endsWith(defaultLog4j));
@@ -242,11 +240,12 @@ public class BrokerLoggingTest extends AbstractTestLogging
*/
public void testBrokerStartupCustomLog4j() throws Exception
{
- // This logging startup code only occurs when you run a Java broker
+ // This logging startup code only occurs when you run a Java broker,
+ // that broker must be started via Main so not an InVM broker.
if (isJavaBroker() && isExternalBroker())
{
// Get custom -l value used during testing for the broker startup
- String customLog4j = _brokerCommand.substring(_brokerCommand.indexOf("-l") + 2).trim();
+ String customLog4j = _broker.substring(_broker.indexOf("-l") + 2);
String TESTID = "BRK-1007";
@@ -519,7 +518,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath"));
setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword"));
- Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port"));
+ Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.sslport"));
startBroker();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java
index 1b2ec9c092..02d0d6f334 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ChannelLoggingTest.java
@@ -77,7 +77,7 @@ public class ChannelLoggingTest extends AbstractTestLogging
validateMessageID("CHN-1001", log);
assertEquals("Incorrect Channel in actor:"+fromActor(log), isBroker010()? 0 : 1, getChannelID(fromActor(log)));
- if (!isBroker010())
+ if (isBroker08())
{
// Wait to ensure that the CHN-1004 message is logged
waitForMessage("CHN-1004");
@@ -89,7 +89,7 @@ public class ChannelLoggingTest extends AbstractTestLogging
log = getLogMessage(results, 0);
// MESSAGE [con:0(guest@anonymous(3273383)/test)/ch:1] CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number}
validateMessageID("CHN-1004", log);
- assertEquals("Incorrect Channel in actor:"+fromActor(log), 1, getChannelID(fromActor(log)));
+ assertEquals("Incorrect Channel in actor:"+fromActor(log), isBroker010()? 0 : 1, getChannelID(fromActor(log)));
assertTrue("Prefetch Count not correct",getMessageString(fromMessage(log)).endsWith("Count "+PREFETCH));
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java
index d45bde2d98..16c529316a 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/DerbyMessageStoreLoggingTest.java
@@ -496,7 +496,7 @@ public class DerbyMessageStoreLoggingTest extends MemoryMessageStoreLoggingTest
stopBroker();
// Clear our monitor
- _monitor.markDiscardPoint();
+ _monitor.reset();
startBroker();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java
index 602bdb66b5..32adc49521 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java
@@ -58,7 +58,7 @@ public class DurableQueueLoggingTest extends AbstractTestLogging
{
super.setUp();
//Ensure we only have logs from our test
- _monitor.markDiscardPoint();
+ _monitor.reset();
_connection = getConnection();
_session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java
index ec96f778f6..1e48f34f99 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ExchangeLoggingTest.java
@@ -20,16 +20,6 @@
*/
package org.apache.qpid.server.logging;
-import java.io.IOException;
-import java.util.List;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession_0_10;
import org.apache.qpid.framing.AMQFrame;
@@ -38,6 +28,13 @@ import org.apache.qpid.framing.ExchangeDeleteBody;
import org.apache.qpid.framing.ExchangeDeleteOkBody;
import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Queue;
+import javax.jms.Session;
+import java.io.IOException;
+import java.util.List;
+
/**
* Exchange
*
@@ -125,7 +122,7 @@ public class ExchangeLoggingTest extends AbstractTestLogging
public void testExchangeCreate() throws JMSException, IOException
{
//Ignore broker startup messages
- _monitor.markDiscardPoint();
+ _monitor.reset();
_session.createConsumer(_queue);
// Ensure we have received the EXH log msg.
@@ -179,7 +176,7 @@ public class ExchangeLoggingTest extends AbstractTestLogging
public void testExchangeDelete() throws Exception, IOException
{
//Ignore broker startup messages
- _monitor.markDiscardPoint();
+ _monitor.reset();
//create the exchange by creating a consumer
_session.createConsumer(_queue);
@@ -217,38 +214,4 @@ public class ExchangeLoggingTest extends AbstractTestLogging
}
- public void testDiscardedMessage() throws Exception
- {
- //Ignore broker startup messages
- _monitor.markDiscardPoint();
-
- if (!isBroker010())
- {
- // Default 0-8..-0-9-1 behaviour is for messages to be rejected (returned to client).
- setTestClientSystemProperty("qpid.default_mandatory", "false");
- }
-
- _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Do not create consumer so queue is not created and message will be discarded.
- final MessageProducer producer = _session.createProducer(_queue);
-
- // Sending message
- final TextMessage msg = _session.createTextMessage("msg");
- producer.send(msg);
-
- final String expectedMessageBody = "Discarded Message : Name: " + _name + " Routing Key: " + _queue.getQueueName();
-
- // Ensure we have received the EXH log msg.
- waitForMessage("EXH-1003");
-
- List<String> results = findMatches(EXH_PREFIX);
- assertEquals("Result set larger than expected.", 2, results.size());
-
- final String log = getLogMessage(results, 1);
- validateMessageID("EXH-1003", log);
-
- final String message = getMessageString(fromMessage(log));
- assertEquals("Log Message not as expected", expectedMessageBody, message);
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java
index 24e6aa4207..595c0d5f35 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/ManagementLoggingTest.java
@@ -22,7 +22,6 @@ package org.apache.qpid.server.logging;
import junit.framework.AssertionFailedError;
-import org.apache.qpid.server.configuration.ServerConfiguration;
import org.apache.qpid.util.LogMonitor;
import java.util.List;
@@ -77,8 +76,9 @@ public class ManagementLoggingTest extends AbstractTestLogging
*/
public void testManagementStartupEnabled() throws Exception
{
- // This test only works on java brokers
- if (isJavaBroker())
+ // This test only works on external java brokers due to the fact that
+ // Management is disabled on InVM brokers.
+ if (isJavaBroker() && isExternalBroker())
{
startBrokerAndCreateMonitor(true, false);
@@ -130,7 +130,9 @@ public class ManagementLoggingTest extends AbstractTestLogging
*/
public void testManagementStartupDisabled() throws Exception
{
- if (isJavaBroker())
+ // This test only works on external java brokers due to the fact that
+ // Management is disabled on InVM brokers.
+ if (isJavaBroker() && isExternalBroker())
{
startBrokerAndCreateMonitor(false, false);
@@ -189,7 +191,9 @@ public class ManagementLoggingTest extends AbstractTestLogging
*/
public void testManagementStartupRMIEntries() throws Exception
{
- if (isJavaBroker())
+ // This test only works on external java brokers due to the fact that
+ // Management is disabled on InVM brokers.
+ if (isJavaBroker() && isExternalBroker())
{
startBrokerAndCreateMonitor(true, false);
@@ -207,7 +211,7 @@ public class ManagementLoggingTest extends AbstractTestLogging
validateMessageID("MNG-1002", log);
//Check the RMI Registry port is as expected
- int mPort = getManagementPort(getPort());
+ int mPort = getPort() + (DEFAULT_MANAGEMENT_PORT - DEFAULT_PORT);
assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log),
getMessageString(log).endsWith(String.valueOf(mPort)));
@@ -218,7 +222,7 @@ public class ManagementLoggingTest extends AbstractTestLogging
// We expect the RMI Registry port (the defined 'management port') to be
// 100 lower than the JMX RMIConnector Server Port (the actual JMX server)
- int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET;
+ int jmxPort = mPort + 100;
assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log),
getMessageString(log).endsWith(String.valueOf(jmxPort)));
}
@@ -246,7 +250,9 @@ public class ManagementLoggingTest extends AbstractTestLogging
*/
public void testManagementStartupSSLKeystore() throws Exception
{
- if (isJavaBroker())
+ // This test only works on external java brokers due to the fact that
+ // Management is disabled on InVM brokers.
+ if (isJavaBroker() && isExternalBroker())
{
startBrokerAndCreateMonitor(true, true);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java
index 76ebda0ebd..b8a42c0ab3 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/QueueLoggingTest.java
@@ -53,7 +53,7 @@ public class QueueLoggingTest extends AbstractTestLogging
{
super.setUp();
//Remove broker startup logging messages
- _monitor.markDiscardPoint();
+ _monitor.reset();
_connection = getConnection();
_session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
index b6efe53580..6e156f091e 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
@@ -58,7 +58,7 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
{
super.setUp();
//Remove broker startup logging messages
- _monitor.markDiscardPoint();
+ _monitor.reset();
_connection = getConnection();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
index 398c83a8d8..a5aec3edce 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
@@ -78,10 +78,21 @@ public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase implements Conn
BrokerDetails details = _connectionURL.getBrokerDetails(0);
- // This will attempt to failover for 3 seconds.
- // Local testing suggests failover takes 2 seconds
- details.setProperty(BrokerDetails.OPTIONS_RETRY, "10");
- details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "500");
+ // Due to the problem with SingleServer delaying on all connection
+ // attempts. So using a high retry value.
+ if (_broker.equals(VM))
+ {
+ // Local testing suggests InVM restart takes under a second
+ details.setProperty(BrokerDetails.OPTIONS_RETRY, "5");
+ details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "200");
+ }
+ else
+ {
+ // This will attempt to failover for 3 seconds.
+ // Local testing suggests failover takes 2 seconds
+ details.setProperty(BrokerDetails.OPTIONS_RETRY, "10");
+ details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "500");
+ }
super.setUp();
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java
deleted file mode 100644
index 277e84d66d..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java
+++ /dev/null
@@ -1,247 +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.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-public class MultipleTransactedBatchProducerTest extends QpidBrokerTestCase
-{
- private static final Logger _logger = Logger.getLogger(MultipleTransactedBatchProducerTest.class);
-
- private static final int MESSAGE_COUNT = 1000;
- private static final int BATCH_SIZE = 50;
- private static final int NUM_PRODUCERS = 2;
- private static final int NUM_CONSUMERS = 3;
- private static final Random RANDOM = new Random();
-
- private CountDownLatch _receivedLatch;
- private String _queueName;
-
- private volatile String _failMsg;
-
- public void setUp() throws Exception
- {
- //debug level logging often makes this test pass artificially, turn the level down to info.
- setSystemProperty("amqj.server.logging.level", "INFO");
- _receivedLatch = new CountDownLatch(MESSAGE_COUNT * NUM_PRODUCERS);
- setConfigurationProperty("management.enabled", "true");
- super.setUp();
- _queueName = getTestQueueName();
- _failMsg = null;
- }
-
- /**
- * When there are multiple producers submitting batches of messages to a given
- * queue using transacted sessions, it is highly probable that concurrent
- * enqueue() activity will occur and attempt delivery of their message to the
- * same subscription. In this scenario it is likely that one of the attempts
- * will succeed and the other will result in use of the deliverAsync() method
- * to start a queue Runner and ensure delivery of the message.
- *
- * A defect within the processQueue() method used by the Runner would mean that
- * delivery of these messages may not occur, should the Runner stop before all
- * messages have been processed. Such a defect was discovered and found to be
- * most visible when Selectors are used such that one and only one subscription
- * can/will accept any given message, but multiple subscriptions are present,
- * and one of the earlier subscriptions receives more messages than the others.
- *
- * This test is to validate that the processQueue() method is able to correctly
- * deliver all of the messages present for asynchronous delivery to subscriptions,
- * by utilising multiple batch transacted producers to create the scenario and
- * ensure all messages are received by a consumer.
- */
- public void testMultipleBatchedProducersWithMultipleConsumersUsingSelectors() throws Exception
- {
- String selector1 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 0");
- String selector2 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 1");
- String selector3 = ("(\"" + _queueName +"\" % " + NUM_CONSUMERS + ") = 2");
-
- //create consumers
- Connection conn1 = getConnection();
- conn1.setExceptionListener(new ExceptionHandler("conn1"));
- Session sess1 = conn1.createSession(true, Session.SESSION_TRANSACTED);
- MessageConsumer cons1 = sess1.createConsumer(sess1.createQueue(_queueName), selector1);
- cons1.setMessageListener(new Cons(sess1,"consumer1"));
-
- Connection conn2 = getConnection();
- conn2.setExceptionListener(new ExceptionHandler("conn2"));
- Session sess2 = conn2.createSession(true, Session.SESSION_TRANSACTED);
- MessageConsumer cons2 = sess2.createConsumer(sess2.createQueue(_queueName), selector2);
- cons2.setMessageListener(new Cons(sess2,"consumer2"));
-
- Connection conn3 = getConnection();
- conn3.setExceptionListener(new ExceptionHandler("conn3"));
- Session sess3 = conn3.createSession(true, Session.SESSION_TRANSACTED);
- MessageConsumer cons3 = sess3.createConsumer(sess3.createQueue(_queueName), selector3);
- cons3.setMessageListener(new Cons(sess3,"consumer3"));
-
- conn1.start();
- conn2.start();
- conn3.start();
-
- //create producers
- Connection connA = getConnection();
- connA.setExceptionListener(new ExceptionHandler("connA"));
- Connection connB = getConnection();
- connB.setExceptionListener(new ExceptionHandler("connB"));
- Thread producer1 = new Thread(new ProducerThread(connA, _queueName, "producer1"));
- Thread producer2 = new Thread(new ProducerThread(connB, _queueName, "producer2"));
-
- producer1.start();
- Thread.sleep(10);
- producer2.start();
-
- //await delivery of the messages
- int timeout = isBrokerStorePersistent() ? 300 : 75;
- boolean result = _receivedLatch.await(timeout, TimeUnit.SECONDS);
-
- assertNull("Test failed because: " + String.valueOf(_failMsg), _failMsg);
- assertTrue("Some of the messages were not all recieved in the given timeframe, remaining count was: "+_receivedLatch.getCount(),
- result);
-
- }
-
- @Override
- public Message createNextMessage(Session session, int msgCount) throws JMSException
- {
- Message message = super.createNextMessage(session,msgCount);
-
- //bias at least 50% of the messages to the first consumers selector because
- //the issue presents itself primarily when an earlier subscription completes
- //delivery after the later subscriptions
- int val;
- if (msgCount % 2 == 0)
- {
- val = 0;
- }
- else
- {
- val = RANDOM.nextInt(Integer.MAX_VALUE);
- }
-
- message.setIntProperty(_queueName, val);
-
- return message;
- }
-
- private class Cons implements MessageListener
- {
- private Session _sess;
- private String _desc;
-
- public Cons(Session sess, String desc)
- {
- _sess = sess;
- _desc = desc;
- }
-
- public void onMessage(Message message)
- {
- _receivedLatch.countDown();
- int msgCount = 0;
- int msgID = 0;
- try
- {
- msgCount = message.getIntProperty(INDEX);
- msgID = message.getIntProperty(_queueName);
- }
- catch (JMSException e)
- {
- _logger.error(_desc + " received exception: " + e.getMessage(), e);
- failAsyncTest(e.getMessage());
- }
-
- _logger.info("Consumer received message:"+ msgCount + " with ID: " + msgID);
-
- try
- {
- _sess.commit();
- }
- catch (JMSException e)
- {
- _logger.error(_desc + " received exception: " + e.getMessage(), e);
- failAsyncTest(e.getMessage());
- }
- }
- }
-
- private class ProducerThread implements Runnable
- {
- private Connection _conn;
- private String _dest;
- private String _desc;
-
- public ProducerThread(Connection conn, String dest, String desc)
- {
- _conn = conn;
- _dest = dest;
- _desc = desc;
- }
-
- public void run()
- {
- try
- {
- Session session = _conn.createSession(true, Session.SESSION_TRANSACTED);
- sendMessage(session, session.createQueue(_dest), MESSAGE_COUNT, BATCH_SIZE);
- }
- catch (Exception e)
- {
- _logger.error(_desc + " received exception: " + e.getMessage(), e);
- failAsyncTest(e.getMessage());
- }
- }
- }
-
- private class ExceptionHandler implements javax.jms.ExceptionListener
- {
- private String _desc;
-
- public ExceptionHandler(String description)
- {
- _desc = description;
- }
-
- public void onException(JMSException e)
- {
- _logger.error(_desc + " received exception: " + e.getMessage(), e);
- failAsyncTest(e.getMessage());
- }
- }
-
- private void failAsyncTest(String msg)
- {
- _logger.error("Failing test because: " + msg);
- _failMsg = msg;
- }
-} \ No newline at end of file
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java
index 2ce1251eab..6203e8a194 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.queue;
import junit.framework.TestCase;
import junit.framework.Assert;
import org.apache.log4j.Logger;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQQueue;
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
index a724e6c66e..f78b327209 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/ProducerFlowControlTest.java
@@ -64,7 +64,7 @@ public class ProducerFlowControlTest extends AbstractTestLogging
_jmxUtilConnected=false;
super.setUp();
- _monitor.markDiscardPoint();
+ _monitor.reset();
producerConnection = getConnection();
producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
index aeeecb2dff..74f50e8659 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
@@ -110,13 +110,18 @@ public class QueueDepthWithSelectorTest extends QpidBrokerTestCase
try
{
Connection connection = getConnection();
- AMQSession session = (AMQSession)connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- long queueDepth = session.getQueueDepth((AMQDestination) _queue);
+ Thread.sleep(2000);
+ long queueDepth = ((AMQSession) session).getQueueDepth((AMQDestination) _queue);
assertEquals("Session reports Queue depth not as expected", expectedDepth, queueDepth);
connection.close();
}
+ catch (InterruptedException e)
+ {
+ fail(e.getMessage());
+ }
catch (AMQException e)
{
fail(e.getMessage());
@@ -153,10 +158,6 @@ public class QueueDepthWithSelectorTest extends QpidBrokerTestCase
{
assertTrue("Message " + msgId + " not received.", msgIdRecevied[msgId]);
}
-
- //do a synchronous op to ensure the acks are processed
- //on the broker before proceeding
- ((AMQSession)_clientSession).sync();
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
index 32b0185f88..f845ff1214 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
@@ -52,6 +52,7 @@ import org.apache.qpid.url.URLSyntaxException;
*
* TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase}
*
+ * @see SimpleACLTest
* @see ExternalACLTest
* @see ExternalACLFileTest
* @see ExternalACLJMXTest
@@ -64,7 +65,10 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
protected CountDownLatch _exceptionReceived;
/** Override this to return the name of the configuration XML file. */
- public abstract String getConfig();
+ public String getConfig()
+ {
+ return "config-systests-acl.xml";
+ }
/** Override this to setup external ACL files for virtual hosts. */
public List<String> getHostList()
@@ -83,8 +87,14 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
@Override
public void setUp() throws Exception
{
+ if (QpidHome == null)
+ {
+ fail("QPID_HOME not set");
+ }
+
// Initialise ACLs.
- _configFile = new File("build" + File.separator + "etc" + File.separator + getConfig());
+ _configFile = new File(QpidHome, "etc" + File.separator + getConfig());
+
// Initialise ACL files
for (String virtualHost : getHostList())
{
@@ -150,7 +160,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
*/
public void setUpACLFile(String virtualHost) throws IOException, ConfigurationException
{
- String path = "build" + File.separator + "etc";
+ String path = QpidHome + File.separator + "etc";
String className = StringUtils.substringBeforeLast(getClass().getSimpleName().toLowerCase(), "test");
String testName = StringUtils.substringAfter(getName(), "test").toLowerCase();
@@ -190,7 +200,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
}
PrintWriter out = new PrintWriter(new FileWriter(aclFile));
- out.println(String.format("# %s", getTestName()));
+ out.println(String.format("# %s", _testName));
for (String line : rules)
{
out.println(line);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
index 254e1fe6ac..4603cc1862 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
@@ -18,620 +18,11 @@
*/
package org.apache.qpid.server.security.acl;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.IllegalStateException;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.jms.Topic;
-import javax.jms.TopicSubscriber;
-import javax.naming.NamingException;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.url.URLSyntaxException;
-
-/**
- * Tests the V2 ACLs. The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using
- * JMS to contact the broker.
- */
-public class ExternalACLTest extends AbstractACLTestCase
+public class ExternalACLTest extends SimpleACLTest
{
- public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
-
- //Do something to show connection is active.
- sess.rollback();
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Connection was not created due to:" + e);
- }
- }
-
- public void testAccessVhostAuthorisedGuestSuccess() throws IOException, Exception
- {
- //The 'guest' user has no access to the 'test' vhost, as tested below in testAccessNoRights(), and so
- //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming
- //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given
- //this right in the 'test2' vhost.
-
- try
- {
- //get a connection to the 'test2' vhost using the guest user and perform various actions.
- Connection conn = getConnection("test2", "guest", "guest");
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- conn.start();
-
- //create Queues and consumers for each
- Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName());
- Queue tempQueue = sess.createTemporaryQueue();
- MessageConsumer consumer = sess.createConsumer(namedQueue);
- MessageConsumer tempConsumer = sess.createConsumer(tempQueue);
-
- //send a message to each queue (also causing an exchange declare)
- MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null);
- ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"),
- DeliveryMode.NON_PERSISTENT, 0, 0L, false, false);
- ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"),
- DeliveryMode.NON_PERSISTENT, 0, 0L, false, false);
-
- //consume the messages from the queues
- consumer.receive(2000);
- tempConsumer.receive(2000);
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testAccessNoRightsFailure() throws Exception
- {
- try
- {
- Connection conn = getConnection("test", "guest", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
- sess.rollback();
-
- fail("Connection was created.");
- }
- catch (JMSException e)
- {
- // JMSException -> linkedException -> cause = AMQException (403 or 320)
- Exception linkedException = e.getLinkedException();
- assertNotNull("There was no linked exception", linkedException);
- Throwable cause = linkedException.getCause();
- assertNotNull("Cause was null", cause);
- assertTrue("Wrong linked exception type", cause instanceof AMQException);
- AMQConstant errorCode = isBroker010() ? AMQConstant.CONNECTION_FORCED : AMQConstant.ACCESS_REFUSED;
- assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode());
- }
- }
-
- public void testClientDeleteQueueSuccess() throws Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
-
- // create kipper
- Topic kipper = sess.createTopic("kipper");
- TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper");
-
- subscriber.close();
- sess.unsubscribe("kipper");
-
- //Do something to show connection is active.
- sess.rollback();
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testServerDeleteQueueFailure() throws Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
-
- // create kipper
- Topic kipper = sess.createTopic("kipper");
- TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper");
-
- subscriber.close();
- sess.unsubscribe("kipper");
-
- //Do something to show connection is active.
- sess.rollback();
- conn.close();
- }
- catch (JMSException e)
- {
- // JMSException -> linedException = AMQException.403
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testClientConsumeFromTempQueueSuccess() throws AMQException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- sess.createConsumer(sess.createTemporaryQueue());
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- sess.createConsumer(sess.createQueue("IllegalQueue"));
-
- fail("Test failed as consumer was created.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- //Create Temporary Queue - can't use the createTempQueue as QueueName is null.
- ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"),
- true, false, false);
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- //Create a Named Queue
- ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false);
-
- fail("Test failed as Queue creation succeded.");
- //conn will be automatically closed
- }
- catch (AMQException e)
- {
- check403Exception(e);
- }
- }
-
- public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
-
- conn.start();
-
- MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue"));
-
- sender.send(sess.createTextMessage("test"));
-
- //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker.
- sess.commit();
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test publish failed:" + e);
- }
- }
-
- public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null);
-
- Queue queue = sess.createQueue("example.RequestQueue");
-
- // Send a message that we will wait to be sent, this should give the broker time to process the msg
- // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
- // queue existence.
- ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"),
- DeliveryMode.NON_PERSISTENT, 0, 0L, false, false);
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test publish failed:" + e);
- }
- }
-
- public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null);
-
- Queue queue = session.createQueue("Invalid");
-
- // Send a message that we will wait to be sent, this should give the broker time to close the connection
- // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
- // queue existence.
- ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"),
- DeliveryMode.NON_PERSISTENT, 0, 0L, false, false);
-
- // Test the connection with a valid consumer
- // This may fail as the session may be closed before the queue or the consumer created.
- Queue temp = session.createTemporaryQueue();
-
- session.createConsumer(temp).close();
-
- //Connection should now be closed and will throw the exception caused by the above send
- conn.close();
-
- fail("Close is not expected to succeed.");
- }
- catch (IllegalStateException e)
- {
- _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- sess.createConsumer(sess.createQueue("example.RequestQueue"));
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "client", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- sess.createConsumer(sess.createQueue("Invalid"));
-
- fail("Test failed as consumer was created.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- sess.createConsumer(sess.createTemporaryQueue());
-
- fail("Test failed as consumer was created.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- //Create Temporary Queue
- ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false);
-
- conn.close();
- }
- catch (Exception e)
- {
- fail("Test failed due to:" + e.getMessage());
- }
- }
-
- public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
-
- Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- //Create a Named Queue
- ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false);
-
- fail("Test failed as creation succeded.");
- }
- catch (Exception e)
- {
- check403Exception(e);
- }
- }
-
- public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
- Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- session.createTemporaryQueue();
-
- fail("Test failed as creation succeded.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
- public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception
- {
- try
- {
- Connection connection = getConnection("test", "server", "guest");
-
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- connection.start();
-
- ((AMQSession<?, ?>) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"),
- true, false, false);
-
- fail("Test failed as creation succeded.");
- }
- catch (Exception e)
- {
- check403Exception(e);
- }
- }
-
- /**
- * This test uses both the cilent and sender to validate that the Server is able to publish to a temporary queue.
- * The reason the client must be involved is that the Server is unable to create its own Temporary Queues.
- *
- * @throws AMQException
- * @throws URLSyntaxException
- * @throws JMSException
- */
- public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
- {
- //Set up the Server
- Connection serverConnection = getConnection("test", "server", "guest");
-
- Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED);
-
- Queue requestQueue = serverSession.createQueue("example.RequestQueue");
-
- MessageConsumer server = serverSession.createConsumer(requestQueue);
-
- serverConnection.start();
-
- //Set up the consumer
- Connection clientConnection = getConnection("test", "client", "guest");
-
- //Send a test mesage
- Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- Queue responseQueue = clientSession.createTemporaryQueue();
-
- MessageConsumer clientResponse = clientSession.createConsumer(responseQueue);
-
- clientConnection.start();
-
- Message request = clientSession.createTextMessage("Request");
-
- assertNotNull("Response Queue is null", responseQueue);
-
- request.setJMSReplyTo(responseQueue);
-
- clientSession.createProducer(requestQueue).send(request);
-
- try
- {
- Message msg = null;
-
- msg = server.receive(2000);
-
- while (msg != null && !((TextMessage) msg).getText().equals("Request"))
- {
- msg = server.receive(2000);
- }
-
- assertNotNull("Message not received", msg);
-
- assertNotNull("Reply-To is Null", msg.getJMSReplyTo());
-
- MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo());
-
- sender.send(serverSession.createTextMessage("Response"));
-
- //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker.
- serverSession.commit();
-
- //Ensure Response is received.
- Message clientResponseMsg = clientResponse.receive(2000);
- assertNotNull("Client did not receive response message,", clientResponseMsg);
- assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText());
-
- }
- catch (Exception e)
- {
- fail("Test publish failed:" + e);
- }
- finally
- {
- try
- {
- serverConnection.close();
- }
- finally
- {
- clientConnection.close();
- }
- }
- }
-
- public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
- {
- try
- {
- Connection conn = getConnection("test", "server", "guest");
-
- ((AMQConnection) conn).setConnectionListener(this);
-
- Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- conn.start();
-
- MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null);
-
- Queue queue = session.createQueue("Invalid");
-
- // Send a message that we will wait to be sent, this should give the broker time to close the connection
- // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
- // queue existence.
- ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"),
- DeliveryMode.NON_PERSISTENT, 0, 0L, false, false);
-
- // Test the connection with a valid consumer
- // This may not work as the session may be closed before the queue or consumer creation can occur.
- // The correct JMSexception with linked error will only occur when the close method is recevied whilst in
- // the failover safe block
- session.createConsumer(session.createQueue("example.RequestQueue")).close();
-
- //Connection should now be closed and will throw the exception caused by the above send
- conn.close();
-
- fail("Close is not expected to succeed.");
- }
- catch (IllegalStateException e)
- {
- _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error.");
- }
- catch (JMSException e)
- {
- check403Exception(e.getLinkedException());
- }
- }
-
-
@Override
public String getConfig()
{
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
new file mode 100644
index 0000000000..a50817e659
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
@@ -0,0 +1,644 @@
+/*
+ * 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 org.apache.qpid.server.security.acl;
+
+import java.io.IOException;
+
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.IllegalStateException;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.jms.TopicSubscriber;
+import javax.naming.NamingException;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.url.URLSyntaxException;
+
+/**
+ * Basic access control list tests.
+ *
+ * These tests require an access control security plugin to be configured in the broker, and carry out various broker
+ * operations that will succeed or fail depending on the user and virtual host. See the {@code config-systests-acl-setup.xml}
+ * configuration file for the SimpleXML version of the ACLs used by the Java broker only, or the various {@code .txt}
+ * files in the system tests directory for the external version 3 ACL files used by both the Java and C++ brokers.
+ * <p>
+ * This class can be extended and the {@link #getConfig()} method overridden to run the same tests with a different type
+ * of access control mechanism. Extension classes should differ only in the configuration file used, but extra tests can be
+ * added that are specific to a particular configuration.
+ * <p>
+ * The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using
+ * JMS to contact the broker.
+ *
+ * @see ExternalACLTest
+ */
+public class SimpleACLTest extends AbstractACLTestCase
+{
+ public void testAccessAuthorizedSuccess() throws AMQException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+ Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
+ conn.start();
+
+ //Do something to show connection is active.
+ sess.rollback();
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Connection was not created due to:" + e);
+ }
+ }
+
+ public void testAccessVhostAuthorisedGuestSuccess() throws IOException, Exception
+ {
+ //The 'guest' user has no access to the 'test' vhost, as tested below in testAccessNoRights(), and so
+ //is unable to perform actions such as connecting (and by extension, creating a queue, and consuming
+ //from a queue etc). In order to test the vhost-wide 'access' ACL right, the 'guest' user has been given
+ //this right in the 'test2' vhost.
+
+ try
+ {
+ //get a connection to the 'test2' vhost using the guest user and perform various actions.
+ Connection conn = getConnection("test2", "guest", "guest");
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ conn.start();
+
+ //create Queues and consumers for each
+ Queue namedQueue = sess.createQueue("vhostAccessCreatedQueue" + getTestQueueName());
+ Queue tempQueue = sess.createTemporaryQueue();
+ MessageConsumer consumer = sess.createConsumer(namedQueue);
+ MessageConsumer tempConsumer = sess.createConsumer(tempQueue);
+
+ //send a message to each queue (also causing an exchange declare)
+ MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null);
+ ((org.apache.qpid.jms.MessageProducer) sender).send(namedQueue, sess.createTextMessage("test"),
+ DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true);
+ ((org.apache.qpid.jms.MessageProducer) sender).send(tempQueue, sess.createTextMessage("test"),
+ DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true);
+
+ //consume the messages from the queues
+ consumer.receive(2000);
+ tempConsumer.receive(2000);
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testAccessNoRightsFailure() throws Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "guest", "guest");
+ Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
+ conn.start();
+ sess.rollback();
+
+ fail("Connection was created.");
+ }
+ catch (JMSException e)
+ {
+ // JMSException -> linkedException -> cause = AMQException (403 or 320)
+ Exception linkedException = e.getLinkedException();
+ assertNotNull("There was no linked exception", linkedException);
+ Throwable cause = linkedException.getCause();
+ assertNotNull("Cause was null", cause);
+ assertTrue("Wrong linked exception type", cause instanceof AMQException);
+ AMQConstant errorCode = isBroker010() ? AMQConstant.CONTEXT_IN_USE : AMQConstant.ACCESS_REFUSED;
+ assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode());
+ }
+ }
+
+ public void testClientDeleteQueueSuccess() throws Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+ Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
+ conn.start();
+
+ // create kipper
+ Topic kipper = sess.createTopic("kipper");
+ TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper");
+
+ subscriber.close();
+ sess.unsubscribe("kipper");
+
+ //Do something to show connection is active.
+ sess.rollback();
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testServerDeleteQueueFailure() throws Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+ Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
+ conn.start();
+
+ // create kipper
+ Topic kipper = sess.createTopic("kipper");
+ TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper");
+
+ subscriber.close();
+ sess.unsubscribe("kipper");
+
+ //Do something to show connection is active.
+ sess.rollback();
+ conn.close();
+ }
+ catch (JMSException e)
+ {
+ // JMSException -> linedException = AMQException.403
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testClientConsumeFromTempQueueSuccess() throws AMQException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ sess.createConsumer(sess.createTemporaryQueue());
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ sess.createConsumer(sess.createQueue("IllegalQueue"));
+
+ fail("Test failed as consumer was created.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ //Create Temporary Queue - can't use the createTempQueue as QueueName is null.
+ ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("doesnt_matter_as_autodelete_means_tmp"),
+ true, false, false);
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ //Create a Named Queue
+ ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false);
+
+ fail("Test failed as Queue creation succeded.");
+ //conn will be automatically closed
+ }
+ catch (AMQException e)
+ {
+ check403Exception(e);
+ }
+ }
+
+ public void testClientPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
+
+ conn.start();
+
+ MessageProducer sender = sess.createProducer(sess.createQueue("example.RequestQueue"));
+
+ sender.send(sess.createTextMessage("test"));
+
+ //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker.
+ sess.commit();
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test publish failed:" + e);
+ }
+ }
+
+ public void testClientPublishValidQueueSuccess() throws AMQException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ MessageProducer sender = ((AMQSession<?, ?>) sess).createProducer(null);
+
+ Queue queue = sess.createQueue("example.RequestQueue");
+
+ // Send a message that we will wait to be sent, this should give the broker time to process the msg
+ // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
+ // queue existence.
+ ((org.apache.qpid.jms.MessageProducer) sender).send(queue, sess.createTextMessage("test"),
+ DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true);
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test publish failed:" + e);
+ }
+ }
+
+ public void testClientPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null);
+
+ Queue queue = session.createQueue("Invalid");
+
+ // Send a message that we will wait to be sent, this should give the broker time to close the connection
+ // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
+ // queue existence.
+ ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"),
+ DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true);
+
+ // Test the connection with a valid consumer
+ // This may fail as the session may be closed before the queue or the consumer created.
+ Queue temp = session.createTemporaryQueue();
+
+ session.createConsumer(temp).close();
+
+ //Connection should now be closed and will throw the exception caused by the above send
+ conn.close();
+
+ fail("Close is not expected to succeed.");
+ }
+ catch (IllegalStateException e)
+ {
+ _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testServerConsumeFromNamedQueueValid() throws AMQException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ sess.createConsumer(sess.createQueue("example.RequestQueue"));
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testServerConsumeFromNamedQueueInvalid() throws AMQException, URLSyntaxException, NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "client", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ sess.createConsumer(sess.createQueue("Invalid"));
+
+ fail("Test failed as consumer was created.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testServerConsumeFromTemporaryQueue() throws AMQException, URLSyntaxException, NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ sess.createConsumer(sess.createTemporaryQueue());
+
+ fail("Test failed as consumer was created.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testServerCreateNamedQueueValid() throws JMSException, URLSyntaxException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ //Create Temporary Queue
+ ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("example.RequestQueue"), false, false, false);
+
+ conn.close();
+ }
+ catch (Exception e)
+ {
+ fail("Test failed due to:" + e.getMessage());
+ }
+ }
+
+ public void testServerCreateNamedQueueInvalid() throws JMSException, URLSyntaxException, AMQException, NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ //Create a Named Queue
+ ((AMQSession<?, ?>) sess).createQueue(new AMQShortString("IllegalQueue"), false, false, false);
+
+ fail("Test failed as creation succeded.");
+ }
+ catch (Exception e)
+ {
+ check403Exception(e);
+ }
+ }
+
+ public void testServerCreateTemporaryQueueInvalid() throws NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ session.createTemporaryQueue();
+
+ fail("Test failed as creation succeded.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+
+ public void testServerCreateAutoDeleteQueueInvalid() throws NamingException, JMSException, AMQException, Exception
+ {
+ try
+ {
+ Connection connection = getConnection("test", "server", "guest");
+
+ Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ connection.start();
+
+ ((AMQSession<?, ?>) session).createQueue(new AMQShortString("again_ensure_auto_delete_queue_for_temporary"),
+ true, false, false);
+
+ fail("Test failed as creation succeded.");
+ }
+ catch (Exception e)
+ {
+ check403Exception(e);
+ }
+ }
+
+ /**
+ * This test uses both the cilent and sender to validate that the Server is able to publish to a temporary queue.
+ * The reason the client must be involved is that the Server is unable to create its own Temporary Queues.
+ *
+ * @throws AMQException
+ * @throws URLSyntaxException
+ * @throws JMSException
+ */
+ public void testServerPublishUsingTransactionSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
+ {
+ //Set up the Server
+ Connection serverConnection = getConnection("test", "server", "guest");
+
+ Session serverSession = serverConnection.createSession(true, Session.SESSION_TRANSACTED);
+
+ Queue requestQueue = serverSession.createQueue("example.RequestQueue");
+
+ MessageConsumer server = serverSession.createConsumer(requestQueue);
+
+ serverConnection.start();
+
+ //Set up the consumer
+ Connection clientConnection = getConnection("test", "client", "guest");
+
+ //Send a test mesage
+ Session clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Queue responseQueue = clientSession.createTemporaryQueue();
+
+ MessageConsumer clientResponse = clientSession.createConsumer(responseQueue);
+
+ clientConnection.start();
+
+ Message request = clientSession.createTextMessage("Request");
+
+ assertNotNull("Response Queue is null", responseQueue);
+
+ request.setJMSReplyTo(responseQueue);
+
+ clientSession.createProducer(requestQueue).send(request);
+
+ try
+ {
+ Message msg = null;
+
+ msg = server.receive(2000);
+
+ while (msg != null && !((TextMessage) msg).getText().equals("Request"))
+ {
+ msg = server.receive(2000);
+ }
+
+ assertNotNull("Message not received", msg);
+
+ assertNotNull("Reply-To is Null", msg.getJMSReplyTo());
+
+ MessageProducer sender = serverSession.createProducer(msg.getJMSReplyTo());
+
+ sender.send(serverSession.createTextMessage("Response"));
+
+ //Send the message using a transaction as this will allow us to retrieve any errors that occur on the broker.
+ serverSession.commit();
+
+ //Ensure Response is received.
+ Message clientResponseMsg = clientResponse.receive(2000);
+ assertNotNull("Client did not receive response message,", clientResponseMsg);
+ assertEquals("Incorrect message received", "Response", ((TextMessage) clientResponseMsg).getText());
+
+ }
+ catch (Exception e)
+ {
+ fail("Test publish failed:" + e);
+ }
+ finally
+ {
+ try
+ {
+ serverConnection.close();
+ }
+ finally
+ {
+ clientConnection.close();
+ }
+ }
+ }
+
+ public void testServerPublishInvalidQueueSuccess() throws AMQException, URLSyntaxException, JMSException, NamingException, Exception
+ {
+ try
+ {
+ Connection conn = getConnection("test", "server", "guest");
+
+ ((AMQConnection) conn).setConnectionListener(this);
+
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ conn.start();
+
+ MessageProducer sender = ((AMQSession<?, ?>) session).createProducer(null);
+
+ Queue queue = session.createQueue("Invalid");
+
+ // Send a message that we will wait to be sent, this should give the broker time to close the connection
+ // before we finish this test. Message is set !immed !mand as the queue is invalid so want to test ACLs not
+ // queue existence.
+ ((org.apache.qpid.jms.MessageProducer) sender).send(queue, session.createTextMessage("test"),
+ DeliveryMode.NON_PERSISTENT, 0, 0L, false, false, true);
+
+ // Test the connection with a valid consumer
+ // This may not work as the session may be closed before the queue or consumer creation can occur.
+ // The correct JMSexception with linked error will only occur when the close method is recevied whilst in
+ // the failover safe block
+ session.createConsumer(session.createQueue("example.RequestQueue")).close();
+
+ //Connection should now be closed and will throw the exception caused by the above send
+ conn.close();
+
+ fail("Close is not expected to succeed.");
+ }
+ catch (IllegalStateException e)
+ {
+ _logger.info("QPID-2345: Session became closed and we got that error rather than the authentication error.");
+ }
+ catch (JMSException e)
+ {
+ check403Exception(e.getLinkedException());
+ }
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java
index 044a0af335..f40e95885d 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java
@@ -35,8 +35,16 @@ public class FirewallConfigTest extends QpidBrokerTestCase
@Override
protected void setUp() throws Exception
{
+ // do setup
+ final String QPID_HOME = System.getProperty("QPID_HOME");
+
+ if (QPID_HOME == null)
+ {
+ fail("QPID_HOME not set");
+ }
+
// Setup initial config file.
- _configFile = new File("build/etc/config-systests-firewall.xml");
+ _configFile = new File(QPID_HOME, "etc/config-systests-firewall.xml");
// Setup temporary config file
_tmpConfig = File.createTempFile("config-systests-firewall", ".xml");
@@ -77,8 +85,14 @@ public class FirewallConfigTest extends QpidBrokerTestCase
public void testVhostAllowBrokerDeny() throws Exception
{
+ if (_broker.equals(VM))
+ {
+ //No point running this test with an InVM broker as the
+ //firewall plugin only functions for TCP connections.
+ return;
+ }
- _configFile = new File("build/etc/config-systests-firewall-2.xml");
+ _configFile = new File(System.getProperty("QPID_HOME"), "etc/config-systests-firewall-2.xml");
super.setUp();
@@ -111,7 +125,14 @@ public class FirewallConfigTest extends QpidBrokerTestCase
public void testVhostDenyBrokerAllow() throws Exception
{
- _configFile = new File("build/etc/config-systests-firewall-3.xml");
+ if (_broker.equals(VM))
+ {
+ //No point running this test with an InVM broker as the
+ //firewall plugin only functions for TCP connections.
+ return;
+ }
+
+ _configFile = new File(System.getProperty("QPID_HOME"), "etc/config-systests-firewall-3.xml");
super.setUp();
@@ -256,6 +277,11 @@ public class FirewallConfigTest extends QpidBrokerTestCase
private void testFirewall(boolean initial, boolean inVhost, Runnable restartOrReload) throws Exception
{
+ if (_broker.equals(VM))
+ {
+ // No point running this test in a vm broker
+ return;
+ }
writeFirewallFile(initial, inVhost);
setConfigurationProperty("management.enabled", String.valueOf(true));
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
index 107c730a7e..13a9dd73b8 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
@@ -94,7 +94,7 @@ public class CancelTest extends QpidBrokerTestCase
browser.close();
MessageConsumer consumer = _clientSession.createConsumer(_queue);
- assertNotNull( consumer.receive(2000l) );
+ assertNotNull( consumer.receive() );
consumer.close();
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
index d6caf05d33..97d825177c 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
@@ -59,7 +59,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
_queue = _clientSession.createQueue(getTestQueueName());
_clientSession.createConsumer(_queue).close();
-
+
//Ensure there are no messages on the queue to start with.
checkQueueDepth(0);
}
@@ -490,7 +490,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
}
- assertTrue("We should get atleast " + messages + " msgs (found " + msgCount +").", msgCount >= messages);
+ assertTrue("We should get atleast " + messages + " msgs.", msgCount >= messages);
if (_logger.isDebugEnabled())
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
index 8c3c247e2b..51589c705f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
@@ -25,37 +25,25 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
-import java.util.Properties;
-
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.QueueReceiver;
-import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
-import javax.jms.TopicSession;
-import javax.jms.TopicSubscriber;
import javax.naming.Context;
-import javax.naming.InitialContext;
import org.apache.qpid.client.AMQAnyDestination;
-import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQSession_0_10;
-import org.apache.qpid.client.message.QpidMessageProperties;
import org.apache.qpid.client.messaging.address.Node.ExchangeNode;
import org.apache.qpid.client.messaging.address.Node.QueueNode;
import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
import org.apache.qpid.messaging.Address;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.transport.ExecutionErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -199,7 +187,9 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs()));
}
-
+
+ // todo add tests for delete options
+
public void testCreateQueue() throws Exception
{
Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
@@ -212,7 +202,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
"durable: true ," +
"x-declare: " +
"{" +
- "exclusive: true," +
+ "auto-delete: true," +
"arguments: {" +
"'qpid.max_size': 1000," +
"'qpid.max_count': 100" +
@@ -228,9 +218,6 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
"}";
AMQDestination dest = new AMQAnyDestination(addr);
MessageConsumer cons = jmsSession.createConsumer(dest);
- cons.close();
-
- // Even if the consumer is closed the queue and the bindings should be intact.
assertTrue("Queue not created as expected",(
(AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
@@ -259,44 +246,12 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
(AMQSession_0_10)jmsSession).isQueueBound("amq.match",
dest.getAddressName(),null, args));
- MessageProducer prod = jmsSession.createProducer(dest);
- prod.send(jmsSession.createTextMessage("test"));
-
- MessageConsumer cons2 = jmsSession.createConsumer(jmsSession.createQueue("ADDR:my-queue"));
- Message m = cons2.receive(1000);
- assertNotNull("Should receive message sent to my-queue",m);
- assertEquals("The subject set in the message is incorrect","hello",m.getStringProperty(QpidMessageProperties.QPID_SUBJECT));
}
public void testCreateExchange() throws Exception
{
- createExchangeImpl(false, false);
- }
-
- /**
- * Verify creating an exchange via an Address, with supported
- * exchange-declare arguments.
- */
- public void testCreateExchangeWithArgs() throws Exception
- {
- createExchangeImpl(true, false);
- }
-
- /**
- * Verify that when creating an exchange via an Address, if a
- * nonsense argument is specified the broker throws an execution
- * exception back on the session with NOT_IMPLEMENTED status.
- */
- public void testCreateExchangeWithNonsenseArgs() throws Exception
- {
- createExchangeImpl(true, true);
- }
-
- private void createExchangeImpl(final boolean withExchangeArgs,
- final boolean useNonsenseArguments) throws Exception
- {
Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
-
+
String addr = "ADDR:my-exchange/hello; " +
"{ " +
"create: always, " +
@@ -306,36 +261,17 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
"x-declare: " +
"{ " +
"type:direct, " +
- "auto-delete: true" +
- createExchangeArgsString(withExchangeArgs, useNonsenseArguments) +
+ "auto-delete: true, " +
+ "arguments: {" +
+ "'qpid.msg_sequence': 1, " +
+ "'qpid.ive': 1" +
+ "}" +
"}" +
"}" +
"}";
AMQDestination dest = new AMQAnyDestination(addr);
-
- MessageConsumer cons;
- try
- {
- cons = jmsSession.createConsumer(dest);
- if(useNonsenseArguments)
- {
- fail("Expected execution exception during exchange declare did not occur");
- }
- }
- catch(JMSException e)
- {
- if(useNonsenseArguments && e.getCause().getMessage().contains(ExecutionErrorCode.NOT_IMPLEMENTED.toString()))
- {
- //expected because we used an argument which the broker doesn't have functionality
- //for. We can't do the rest of the test as a result of the exception, just stop.
- return;
- }
- else
- {
- fail("Unexpected exception whilst creating consumer: " + e);
- }
- }
+ MessageConsumer cons = jmsSession.createConsumer(dest);
assertTrue("Exchange not created as expected",(
(AMQSession_0_10)jmsSession).isExchangeExist(dest, (ExchangeNode)dest.getTargetNode() , true));
@@ -350,66 +286,16 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
cons = jmsSession.createConsumer(dest);
}
- private String createExchangeArgsString(final boolean withExchangeArgs,
- final boolean useNonsenseArguments)
- {
- String argsString;
-
- if(withExchangeArgs && useNonsenseArguments)
- {
- argsString = ", arguments: {" +
- "'abcd.1234.wxyz': 1, " +
- "}";
- }
- else if(withExchangeArgs)
- {
- argsString = ", arguments: {" +
- "'qpid.msg_sequence': 1, " +
- "'qpid.ive': 1" +
- "}";
- }
- else
- {
- argsString = "";
- }
-
- return argsString;
- }
-
- public void checkQueueForBindings(Session jmsSession, AMQDestination dest,String headersBinding) throws Exception
- {
- assertTrue("Queue not created as expected",(
- (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
-
- assertTrue("Queue not bound as expected",(
- (AMQSession_0_10)jmsSession).isQueueBound("",
- dest.getAddressName(),dest.getAddressName(), null));
-
- assertTrue("Queue not bound as expected",(
- (AMQSession_0_10)jmsSession).isQueueBound("amq.direct",
- dest.getAddressName(),"test", null));
-
- assertTrue("Queue not bound as expected",(
- (AMQSession_0_10)jmsSession).isQueueBound("amq.topic",
- dest.getAddressName(),"a.#", null));
-
- Address a = Address.parse(headersBinding);
- assertTrue("Queue not bound as expected",(
- (AMQSession_0_10)jmsSession).isQueueBound("amq.match",
- dest.getAddressName(),null, a.getOptions()));
- }
-
- /**
- * Test goal: Verifies that a producer and consumer creation triggers the correct
- * behavior for x-bindings specified in node props.
- */
public void testBindQueueWithArgs() throws Exception
{
+ Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
- Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
String headersBinding = "{exchange: 'amq.match', arguments: {x-match: any, dep: sales, loc: CA}}";
- String addr = "node: " +
+ String addr = "ADDR:my-queue/hello; " +
+ "{ " +
+ "create: always, " +
+ "node: " +
"{" +
"durable: true ," +
"x-declare: " +
@@ -424,14 +310,28 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
"}" +
"}";
+ AMQDestination dest = new AMQAnyDestination(addr);
+ MessageConsumer cons = jmsSession.createConsumer(dest);
+
+ assertTrue("Queue not created as expected",(
+ (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
+
+ assertTrue("Queue not bound as expected",(
+ (AMQSession_0_10)jmsSession).isQueueBound("",
+ dest.getAddressName(),dest.getAddressName(), null));
- AMQDestination dest1 = new AMQAnyDestination("ADDR:my-queue/hello; {create: receiver, " +addr);
- MessageConsumer cons = jmsSession.createConsumer(dest1);
- checkQueueForBindings(jmsSession,dest1,headersBinding);
+ assertTrue("Queue not bound as expected",(
+ (AMQSession_0_10)jmsSession).isQueueBound("amq.direct",
+ dest.getAddressName(),"test", null));
+
+ assertTrue("Queue not bound as expected",(
+ (AMQSession_0_10)jmsSession).isQueueBound("amq.topic",
+ dest.getAddressName(),"a.#", null));
- AMQDestination dest2 = new AMQAnyDestination("ADDR:my-queue2/hello; {create: sender, " +addr);
- MessageProducer prod = jmsSession.createProducer(dest2);
- checkQueueForBindings(jmsSession,dest2,headersBinding);
+ Address a = Address.parse(headersBinding);
+ assertTrue("Queue not bound as expected",(
+ (AMQSession_0_10)jmsSession).isQueueBound("amq.match",
+ dest.getAddressName(),null, a.getOptions()));
}
/**
@@ -567,6 +467,39 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
}
/**
+ * Test goal: Verifies that and address based destination can be used successfully
+ * as a reply to.
+ */
+ public void testAddressBasedReplyTo() throws Exception
+ {
+ Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
+
+ String addr = "ADDR:amq.direct/x512; {create: receiver, " +
+ "link : {name : 'MY.RESP.QUEUE', " +
+ "x-declare : { auto-delete: true, exclusive: true, " +
+ "arguments : {'qpid.max_size': 1000, 'qpid.policy_type': ring }} } }";
+
+ Destination replyTo = new AMQAnyDestination(addr);
+ Destination dest =new AMQAnyDestination("ADDR:amq.direct/Hello");
+
+ MessageConsumer cons = jmsSession.createConsumer(dest);
+ MessageProducer prod = jmsSession.createProducer(dest);
+ Message m = jmsSession.createTextMessage("Hello");
+ m.setJMSReplyTo(replyTo);
+ prod.send(m);
+
+ Message msg = cons.receive(1000);
+ assertNotNull("consumer should have received the message",msg);
+
+ MessageConsumer replyToCons = jmsSession.createConsumer(replyTo);
+ MessageProducer replyToProd = jmsSession.createProducer(msg.getJMSReplyTo());
+ replyToProd.send(jmsSession.createTextMessage("reply"));
+
+ Message replyToMsg = replyToCons.receive(1000);
+ assertNotNull("The reply to consumer should have got the message",replyToMsg);
+ }
+
+ /**
* Test goal: Verifies that session.createQueue method
* works as expected both with the new and old addressing scheme.
*/
@@ -587,22 +520,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
cons.close();
// Using the ADDR method
- // default case
queue = ssn.createQueue("ADDR:my-queue2");
- try
- {
- prod = ssn.createProducer(queue);
- fail("The client should throw an exception, since there is no queue present in the broker");
- }
- catch(Exception e)
- {
- String s = "The name 'my-queue2' supplied in the address " +
- "doesn't resolve to an exchange or a queue";
- assertEquals(s,e.getCause().getCause().getMessage());
- }
-
- // explicit create case
- queue = ssn.createQueue("ADDR:my-queue2; {create: sender}");
prod = ssn.createProducer(queue);
cons = ssn.createConsumer(queue);
assertTrue("my-queue2 was not created as expected",(
@@ -629,25 +547,11 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
}
/**
- * Test goal: Verifies that session.creatTopic method works as expected
- * both with the new and old addressing scheme.
+ * Test goal: Verifies that session.creatTopic method
+ * works as expected both with the new and old addressing scheme.
*/
public void testSessionCreateTopic() throws Exception
{
- sessionCreateTopicImpl(false);
- }
-
- /**
- * Test goal: Verifies that session.creatTopic method works as expected
- * both with the new and old addressing scheme when adding exchange arguments.
- */
- public void testSessionCreateTopicWithExchangeArgs() throws Exception
- {
- sessionCreateTopicImpl(true);
- }
-
- private void sessionCreateTopicImpl(boolean withExchangeArgs) throws Exception
- {
Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
// Using the BURL method
@@ -667,7 +571,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
prod.send(ssn.createTextMessage("test"));
assertNotNull("consumer should receive a message",cons.receive(1000));
cons.close();
-
+
String addr = "ADDR:vehicles/bus; " +
"{ " +
"create: always, " +
@@ -677,8 +581,11 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
"x-declare: " +
"{ " +
"type:direct, " +
- "auto-delete: true" +
- createExchangeArgsString(withExchangeArgs, false) +
+ "auto-delete: true, " +
+ "arguments: {" +
+ "'qpid.msg_sequence': 1, " +
+ "'qpid.ive': 1" +
+ "}" +
"}" +
"}, " +
"link: {name : my-topic, " +
@@ -790,7 +697,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
public void testSubscriptionForSameDestination() throws Exception
{
Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
- Destination dest = ssn.createTopic("ADDR:amq.topic/foo; {link:{durable:true}}");
+ Destination dest = ssn.createTopic("ADDR:amq.topic/foo");
MessageConsumer consumer1 = ssn.createConsumer(dest);
MessageConsumer consumer2 = ssn.createConsumer(dest);
MessageProducer prod = ssn.createProducer(dest);
@@ -889,297 +796,4 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
{
}
}
-
- public void testQueueReceiversAndTopicSubscriber() throws Exception
- {
- Queue queue = new AMQAnyDestination("ADDR:my-queue; {create: always}");
- Topic topic = new AMQAnyDestination("ADDR:amq.topic/test");
-
- QueueSession qSession = ((AMQConnection)_connection).createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
- QueueReceiver receiver = qSession.createReceiver(queue);
-
- TopicSession tSession = ((AMQConnection)_connection).createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
- TopicSubscriber sub = tSession.createSubscriber(topic);
-
- Session ssn = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- MessageProducer prod1 = ssn.createProducer(ssn.createQueue("ADDR:my-queue"));
- prod1.send(ssn.createTextMessage("test1"));
-
- MessageProducer prod2 = ssn.createProducer(ssn.createTopic("ADDR:amq.topic/test"));
- prod2.send(ssn.createTextMessage("test2"));
-
- Message msg1 = receiver.receive();
- assertNotNull(msg1);
- assertEquals("test1",((TextMessage)msg1).getText());
-
- Message msg2 = sub.receive();
- assertNotNull(msg2);
- assertEquals("test2",((TextMessage)msg2).getText());
- }
-
- public void testDurableSubscriber() throws Exception
- {
- Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
-
- Properties props = new Properties();
- props.setProperty("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory");
- props.setProperty("destination.address1", "ADDR:amq.topic");
- props.setProperty("destination.address2", "ADDR:amq.direct/test");
- String addrStr = "ADDR:amq.topic/test; {link:{name: my-topic," +
- "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}";
- props.setProperty("destination.address3", addrStr);
- props.setProperty("topic.address4", "hello.world");
- addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}";
- props.setProperty("destination.address5", addrStr);
-
- Context ctx = new InitialContext(props);
-
- for (int i=1; i < 5; i++)
- {
- Topic topic = (Topic) ctx.lookup("address"+i);
- createDurableSubscriber(ctx,ssn,"address"+i,topic);
- }
-
- Topic topic = ssn.createTopic("ADDR:news.us");
- createDurableSubscriber(ctx,ssn,"my-dest",topic);
-
- Topic namedQueue = (Topic) ctx.lookup("address5");
- try
- {
- createDurableSubscriber(ctx,ssn,"my-queue",namedQueue);
- fail("Exception should be thrown. Durable subscribers cannot be created for Queues");
- }
- catch(JMSException e)
- {
- assertEquals("Durable subscribers can only be created for Topics",
- e.getMessage());
- }
- }
-
- private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic) throws Exception
- {
- MessageConsumer cons = ssn.createDurableSubscriber(topic, destName);
- MessageProducer prod = ssn.createProducer(topic);
-
- Message m = ssn.createTextMessage(destName);
- prod.send(m);
- Message msg = cons.receive(1000);
- assertNotNull(msg);
- assertEquals(destName,((TextMessage)msg).getText());
- ssn.unsubscribe(destName);
- }
-
- public void testDeleteOptions() throws Exception
- {
- Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
- MessageConsumer cons;
-
- // default (create never, assert never) -------------------
- // create never --------------------------------------------
- String addr1 = "ADDR:testQueue1;{create: always, delete: always}";
- AMQDestination dest = new AMQAnyDestination(addr1);
- try
- {
- cons = jmsSession.createConsumer(dest);
- cons.close();
- }
- catch(JMSException e)
- {
- fail("Exception should not be thrown. Exception thrown is : " + e);
- }
-
- assertFalse("Queue not deleted as expected",(
- (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
-
-
- String addr2 = "ADDR:testQueue2;{create: always, delete: receiver}";
- dest = new AMQAnyDestination(addr2);
- try
- {
- cons = jmsSession.createConsumer(dest);
- cons.close();
- }
- catch(JMSException e)
- {
- fail("Exception should not be thrown. Exception thrown is : " + e);
- }
-
- assertFalse("Queue not deleted as expected",(
- (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
-
-
- String addr3 = "ADDR:testQueue3;{create: always, delete: sender}";
- dest = new AMQAnyDestination(addr3);
- try
- {
- cons = jmsSession.createConsumer(dest);
- MessageProducer prod = jmsSession.createProducer(dest);
- prod.close();
- }
- catch(JMSException e)
- {
- fail("Exception should not be thrown. Exception thrown is : " + e);
- }
-
- assertFalse("Queue not deleted as expected",(
- (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
-
-
- }
-
- /**
- * Test Goals : 1. Test if the client sets the correct accept mode for unreliable
- * and at-least-once.
- * 2. Test default reliability modes for Queues and Topics.
- * 3. Test if an exception is thrown if exactly-once is used.
- * 4. Test if an exception is thrown if at-least-once is used with topics.
- *
- * Test Strategy: For goal #1 & #2
- * For unreliable and at-least-once the test tries to receives messages
- * in client_ack mode but does not ack the messages.
- * It will then close the session, recreate a new session
- * and will then try to verify the queue depth.
- * For unreliable the messages should have been taken off the queue.
- * For at-least-once the messages should be put back onto the queue.
- *
- */
-
- public void testReliabilityOptions() throws Exception
- {
- String addr1 = "ADDR:testQueue1;{create: always, delete : receiver, link : {reliability : unreliable}}";
- acceptModeTest(addr1,0);
-
- String addr2 = "ADDR:testQueue2;{create: always, delete : receiver, link : {reliability : at-least-once}}";
- acceptModeTest(addr2,2);
-
- // Default accept-mode for topics
- acceptModeTest("ADDR:amq.topic/test",0);
-
- // Default accept-mode for queues
- acceptModeTest("ADDR:testQueue1;{create: always}",2);
-
- String addr3 = "ADDR:testQueue2;{create: always, delete : receiver, link : {reliability : exactly-once}}";
- try
- {
- AMQAnyDestination dest = new AMQAnyDestination(addr3);
- fail("An exception should be thrown indicating it's an unsupported type");
- }
- catch(Exception e)
- {
- assertTrue(e.getCause().getMessage().contains("The reliability mode 'exactly-once' is not yet supported"));
- }
-
- String addr4 = "ADDR:amq.topic/test;{link : {reliability : at-least-once}}";
- try
- {
- AMQAnyDestination dest = new AMQAnyDestination(addr4);
- Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);
- MessageConsumer cons = ssn.createConsumer(dest);
- fail("An exception should be thrown indicating it's an unsupported combination");
- }
- catch(Exception e)
- {
- assertTrue(e.getCause().getMessage().contains("AT-LEAST-ONCE is not yet supported for Topics"));
- }
- }
-
- private void acceptModeTest(String address, int expectedQueueDepth) throws Exception
- {
- Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);
- MessageConsumer cons;
- MessageProducer prod;
-
- AMQDestination dest = new AMQAnyDestination(address);
- cons = ssn.createConsumer(dest);
- prod = ssn.createProducer(dest);
-
- for (int i=0; i < expectedQueueDepth; i++)
- {
- prod.send(ssn.createTextMessage("Msg" + i));
- }
-
- for (int i=0; i < expectedQueueDepth; i++)
- {
- Message msg = cons.receive(1000);
- assertNotNull(msg);
- assertEquals("Msg" + i,((TextMessage)msg).getText());
- }
-
- ssn.close();
- ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);
- long queueDepth = ((AMQSession) ssn).getQueueDepth(dest);
- assertEquals(expectedQueueDepth,queueDepth);
- cons.close();
- prod.close();
- }
-
- public void testDestinationOnSend() throws Exception
- {
- Session ssn = _connection.createSession(false,Session.CLIENT_ACKNOWLEDGE);
- MessageConsumer cons = ssn.createConsumer(ssn.createTopic("ADDR:amq.topic/test"));
- MessageProducer prod = ssn.createProducer(null);
-
- Queue queue = ssn.createQueue("ADDR:amq.topic/test");
- prod.send(queue,ssn.createTextMessage("A"));
-
- Message msg = cons.receive(1000);
- assertNotNull(msg);
- assertEquals("A",((TextMessage)msg).getText());
- prod.close();
- cons.close();
- }
-
- public void testReplyToWithNamelessExchange() throws Exception
- {
- System.setProperty("qpid.declare_exchanges","false");
- replyToTest("ADDR:my-queue;{create: always}");
- System.setProperty("qpid.declare_exchanges","true");
- }
-
- public void testReplyToWithCustomExchange() throws Exception
- {
- replyToTest("ADDR:hello;{create:always,node:{type:topic}}");
- }
-
- private void replyToTest(String replyTo) throws Exception
- {
- Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- Destination replyToDest = AMQDestination.createDestination(replyTo);
- MessageConsumer replyToCons = session.createConsumer(replyToDest);
-
- Destination dest = session.createQueue("ADDR:amq.direct/test");
-
- MessageConsumer cons = session.createConsumer(dest);
- MessageProducer prod = session.createProducer(dest);
- Message m = session.createTextMessage("test");
- m.setJMSReplyTo(replyToDest);
- prod.send(m);
-
- Message msg = cons.receive();
- MessageProducer prodR = session.createProducer(msg.getJMSReplyTo());
- prodR.send(session.createTextMessage("x"));
-
- Message m1 = replyToCons.receive();
- assertNotNull("The reply to consumer should have received the messsage",m1);
- }
-
- public void testAltExchangeInAddressString() throws Exception
- {
- String addr1 = "ADDR:my-exchange/test; {create: always, node:{type: topic,x-declare:{alternate-exchange:'amq.fanout'}}}";
- Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- String altQueueAddr = "ADDR:my-alt-queue;{create: always, delete: receiver,node:{x-bindings:[{exchange:'amq.fanout'}] }}";
- MessageConsumer cons = session.createConsumer(session.createQueue(altQueueAddr));
-
- MessageProducer prod = session.createProducer(session.createTopic(addr1));
- prod.send(session.createMessage());
- prod.close();
- assertNotNull("The consumer on the queue bound to the alt-exchange should receive the message",cons.receive(1000));
-
- String addr2 = "ADDR:test-queue;{create:sender, delete: sender,node:{type:queue,x-declare:{alternate-exchange:'amq.fanout'}}}";
- prod = session.createProducer(session.createTopic(addr2));
- prod.send(session.createMessage());
- prod.close();
- assertNotNull("The consumer on the queue bound to the alt-exchange should receive the message",cons.receive(1000));
- cons.close();
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
index 3068deecf8..fcbab273e5 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
@@ -299,7 +299,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
details.setProperty(BrokerDetails.OPTIONS_RETRY, String.valueOf(RETRIES));
details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, String.valueOf(DELAY));
- connection = new AMQConnection(connectionURL);
+ connection = new AMQConnection(connectionURL, null);
((AMQConnection) connection).setConnectionListener(this);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java
index b1c8b5682f..49a608190d 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/message/SelectorTest.java
@@ -23,7 +23,6 @@ package org.apache.qpid.test.client.message;
import java.util.concurrent.CountDownLatch;
import javax.jms.DeliveryMode;
-import javax.jms.Destination;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.Message;
@@ -31,7 +30,6 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
-import javax.jms.TextMessage;
import junit.framework.Assert;
@@ -52,6 +50,7 @@ public class SelectorTest extends QpidBrokerTestCase implements MessageListener
private AMQConnection _connection;
private AMQDestination _destination;
private int count;
+ public String _connectionString = "vm://:1";
private static final String INVALID_SELECTOR = "Cost LIKE 5";
CountDownLatch _responseLatch = new CountDownLatch(1);
@@ -281,36 +280,31 @@ public class SelectorTest extends QpidBrokerTestCase implements MessageListener
Assert.assertNotNull("Msg5 should not be null", msg5);
}
- public void testSelectorWithJMSDeliveryMode() throws Exception
+ public static void main(String[] argv) throws Exception
{
- Session session = _connection.createSession(false, Session.SESSION_TRANSACTED);
+ SelectorTest test = new SelectorTest();
+ test._connectionString = (argv.length == 0) ? "localhost:3000" : argv[0];
- Destination dest1 = session.createTopic("test1");
- Destination dest2 = session.createTopic("test2");
-
- MessageProducer prod1 = session.createProducer(dest1);
- MessageProducer prod2 = session.createProducer(dest2);
- MessageConsumer consumer1 = session.createConsumer(dest1,"JMSDeliveryMode = 'PERSISTENT'");
- MessageConsumer consumer2 = session.createConsumer(dest2,"JMSDeliveryMode = 'NON_PERSISTENT'");
-
- Message msg1 = session.createTextMessage("Persistent");
- prod1.send(msg1);
- prod2.send(msg1);
-
- prod1.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
- prod2.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
-
- Message msg2 = session.createTextMessage("Non_Persistent");
- prod1.send(msg2);
- prod2.send(msg2);
-
- TextMessage m1 = (TextMessage)consumer1.receive(1000);
- assertEquals("Consumer1 should receive the persistent message","Persistent",m1.getText());
- assertNull("Consumer1 should not receiver another message",consumer1.receive(1000));
-
- TextMessage m2 = (TextMessage)consumer2.receive(1000);
- assertEquals("Consumer2 should receive the non persistent message","Non_Persistent",m2.getText());
- assertNull("Consumer2 should not receiver another message",consumer2.receive(1000));
+ try
+ {
+ while (true)
+ {
+ if (test._connectionString.contains("vm://:1"))
+ {
+ test.setUp();
+ }
+ test.testUsingOnMessage();
+
+ if (test._connectionString.contains("vm://:1"))
+ {
+ test.tearDown();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
}
-
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java
index 6189c37306..1a23eee8ab 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitTimeoutDelayTest.java
@@ -63,7 +63,7 @@ public class SyncWaitTimeoutDelayTest extends SyncWaitDelayTest
catch (JMSException e)
{
assertTrue("Wrong exception type received.", e.getLinkedException() instanceof AMQTimeoutException);
- assertTrue("Wrong message received on exception.", e.getMessage().startsWith("Exception during commit"));
+ assertTrue("Wrong message received on exception.", e.getMessage().startsWith("Failed to commit"));
// As we are using Nano time ensure to multiply up the millis.
assertTrue("Timeout was more than 30s default", (System.nanoTime() - start) < (1000000L * 1000 * 30));
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
new file mode 100644
index 0000000000..c11f75e742
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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 org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.LocalAMQPCircuitFactory;
+
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * AMQPFeatureDecorator applies decorations to {@link FrameworkBaseCase} tests, so that they may use Qpid/AMQP specific
+ * features, not available through JMS. For example, the immediate and mandatory flags. This decorator replaces the
+ * standard test circuit factory on the base class with one that allows these features to be used.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Substitute the circuit factory with an AMQP/Qpid specific one.
+ * </table>
+ *
+ * @todo This wrapper substitutes in a LocalAMQPCircuitFactory, which is fine for local tests. For distributed tests
+ * the Fanout or Interop factories are substituted in by their decorators instead. These actually use
+ * distributed circuit static create methods to build the circuits, which should actually be changed to a factory,
+ * so that static methods do not need to be used. The distributed circuit creater delegates the circuit
+ * construction to remote test nodes. This decorator should not be used with distributed tests, or should be made
+ * aware of them, in which case it might ensure that an AMQP feature (implied already by other properties) flag
+ * is passed out to the remote test nodes, and provide a mechansim for them to decorate their circuit creation
+ * with AMQP features too. Add factory substituion/decoration mechansim for test clients, here or in a seperate
+ * class.
+ */
+public class AMQPFeatureDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test test decorator from another one.
+ *
+ * @param test The test test.
+ */
+ public AMQPFeatureDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ if (test instanceof FrameworkBaseCase)
+ {
+ FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test;
+ frameworkTest.setCircuitFactory(new LocalAMQPCircuitFactory());
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "AMQPFeatureDecorator: [test = \"" + test + "\"]";
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java
new file mode 100644
index 0000000000..2708253d86
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java
@@ -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.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+import org.apache.qpid.test.framework.CauseFailureUserPrompt;
+
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * CauseFailureDecorator applies decorations to {@link BrokerLifecycleAware} tests, so that they may use different failure
+ * mechanisms. It is capable of detecting when a test case uses in-vm brokers, and setting up an automatic failure
+ * for those tests, so that the current live broker can be shut-down by test cases. For external brokers, automatic
+ * failure could be implemented, for example by having a kill script. At the moment this sets up the failure to prompt
+ * a user interactively to cause a failure, using {@link CauseFailureUserPrompt}.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup automatic failures for in-vm brokers. <td> {@link CauseFailureInVM}
+ * <tr><td> Setup user generated failures for external brokers. <td> {@link CauseFailureUserPrompt}.
+ * <tr><td>
+ * </table>
+ *
+ * @todo Slight problem in that CauseFailureInVM is Qpid specific, whereas CauseFailureUserPrompt is not. Would like the
+ * failure decorator to be non-qpid specific so that it can test failure of any JMS implementation too. Either pass
+ * in class name of failure mechanism, set it up in the in-vm decorator instead of here but with prompt user as the
+ * default for when the in-vm decorator is not used?
+ */
+public class CauseFailureDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test test decorator from another one.
+ *
+ * @param test The test test.
+ */
+ public CauseFailureDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ if (test instanceof BrokerLifecycleAware)
+ {
+ BrokerLifecycleAware failureTest = (BrokerLifecycleAware) test;
+ failureTest.setFailureMechanism(new CauseFailureUserPrompt());
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "CauseFailureDecorator: [test = \"" + test + "\"]";
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java
new file mode 100644
index 0000000000..3e03ad0872
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * 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 org.apache.qpid.test.framework.qpid;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.test.framework.CauseFailure;
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Cause messaging broker failure on the active in-vm broker.
+ * <td> {@link TransportConnection}, {@link ApplicationRegistry}
+ * </table>
+ */
+public class CauseFailureInVM implements CauseFailure
+{
+ /** Holds the in-vm broker instrumented test case to create failures for. */
+ private BrokerLifecycleAware inVMTest;
+
+ /**
+ * Creates an automated failure mechanism for testing against in-vm brokers. The test to create the mechanism
+ * for is specified, and as this failure is for in-vm brokers, the test must be {@link org.apache.qpid.test.framework.BrokerLifecycleAware}. The test
+ * must also report that it is currently being run against an in-vm broker, and it is a runtime error if it is not,
+ * as the creator of this failure mechanism should already have checked that it is.
+ *
+ * @param inVMTest The test case to create an automated failure mechanism for.
+ */
+ public CauseFailureInVM(BrokerLifecycleAware inVMTest)
+ {
+ // Check that the test is really using in-vm brokers.
+ if (!inVMTest.usingInVmBroker())
+ {
+ throw new RuntimeException(
+ "Cannot create in-vm broker failure mechanism for a test that is not using in-vm brokers.");
+ }
+
+ this.inVMTest = inVMTest;
+ }
+
+ /**
+ * Causes the active message broker to fail.
+ */
+ public void causeFailure()
+ {
+ int liveBroker = inVMTest.getLiveBroker();
+
+ TransportConnection.killVMBroker(liveBroker);
+ ApplicationRegistry.remove(liveBroker);
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
new file mode 100644
index 0000000000..b92a72a654
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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 org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import org.apache.qpid.junit.extensions.SetupTaskAware;
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * InVMBrokerDecorator is a test decorator, that is activated when running tests against an in-vm broker only. Its
+ * purpose is to automatically create, and close and delete an in-vm broker, during the set-up and tear-down of
+ * each test case. This decorator may only be used in conjunction with tests that extend {@link FrameworkBaseCase}.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create/Destroy an in-vm broker on every test run.
+ * </table>
+ *
+ * @todo May need to add a more fine grained injection point for the in-vm broker management, as this acts at the
+ * suite level, rather than the individual test level.
+ *
+ * @todo Management of in-vm brokers for failure testing. Failure test setups may need to set their connection url to
+ * use multiple broker (vm://:1;vm://:2), with fail-over between them. There is round-robin fail-over, but also
+ * retry? A test case using an in-vm broker needs to record which one it is using, so that it can be
+ * killed/restarted.
+ */
+public class InVMBrokerDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test suite decorator from another one.
+ *
+ * @param test The test suite.
+ */
+ public InVMBrokerDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with in-vm broker creation and clean-up added to the tests task stack.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ // Check that the test to have an in-vm broker setup/teardown task added to it, is actually a framework
+ // test that can handle setup tasks.
+ if ((test instanceof SetupTaskAware))
+ {
+ SetupTaskAware frameworkTest = (SetupTaskAware) test;
+
+ frameworkTest.chainSetupTask(new Runnable()
+ {
+ public void run()
+ {
+ // Ensure that the in-vm broker is created.
+ try
+ {
+ ApplicationRegistry.getInstance(1);
+ TransportConnection.createVMBroker(1);
+ }
+ catch (AMQVMBrokerCreationException e)
+ {
+ throw new RuntimeException("In-VM broker creation failed: " + e.getMessage(), e);
+ }
+ }
+ });
+
+ frameworkTest.chainTearDownTask(new Runnable()
+ {
+ public void run()
+ {
+ // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
+ TransportConnection.killVMBroker(1);
+ ApplicationRegistry.remove(1);
+ }
+ });
+
+ // Check if the test is aware whether or not it can control the broker life cycle, and if so provide
+ // additional instrumentation for it to control the in-vm broker through.
+ if (test instanceof BrokerLifecycleAware)
+ {
+ BrokerLifecycleAware inVMTest = (BrokerLifecycleAware) test;
+ inVMTest.setInVmBrokers();
+ inVMTest.setLiveBroker(1);
+ inVMTest.setFailureMechanism(new CauseFailureInVM(inVMTest));
+ }
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "InVMBrokerDecorator: [test = " + test + "]";
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java b/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java
new file mode 100644
index 0000000000..d4bab657d7
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java
@@ -0,0 +1,154 @@
+/*
+ *
+ * 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 org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.ACK_MODE_PROPNAME;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.PUBSUB_PROPNAME;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import javax.jms.*;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * TTLTest checks that time-to-live is applied to messages. The test sends messages with a variety of TTL stamps on them
+ * then after a pause attempts to receive those messages. Only messages with a large enough TTL to have survived the pause
+ * should be receiveable. This test case also applies an additional assertion against the broker, that the message store
+ * is empty at the end of the test.
+ *
+ * <p/>This test is designed to run over local circuits only, as it must control a timed pause between sending and receiving
+ * messages to that TTL can be applied to purge some of the messages.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo Use an interface or other method to mark this test as local only.
+ *
+ * @todo Implement the message store assertion for in-vm broker. Could also be done for external broker, for example
+ * by using diagnostic exchange.
+ *
+ * @todo Implement and add a queue depth assertion too. This might already be in another test to copy from.
+ *
+ * @todo Create variations on test theme, for different ack mode and tx and message sizes etc.
+ *
+ * @todo Add an allowable margin of error to the test, as ttl may not be precise.
+ */
+public class TTLTest extends FrameworkBaseCase
+{
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public TTLTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Checks that all messages sent with a TTL shorter than a pause between sending them and attempting to receive them
+ * will fail to arrive. Once all messages have been purged by TTL or received, check that they no longer exist on
+ * the broker.
+ *
+ * @throws javax.jms.JMSException Allowed to fall through and fail test.
+ */
+ public void testTTLP2P() throws Exception
+ {
+ String errorMessages = "";
+ Random r = new Random();
+
+ // Used to accumulate correctly received messages in.
+ List<Message> receivedMessages = new LinkedList<Message>();
+
+ // Set up the test properties to match the test case requirements.
+ getTestProps().setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE);
+ getTestProps().setProperty(PUBSUB_PROPNAME, false);
+
+ // Create the test circuit from the test configuration parameters.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(getConnection(), getTestProps());
+
+ // This test case assumes it is using a local circuit.
+ LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit;
+
+ Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession();
+ MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer();
+ MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer();
+
+ // Send some tests messages, with random TTLs, some shorter and some longer than the pause time.
+ for (int i = 0; i < 100; i++)
+ {
+ Message testMessage = TestUtils.createTestMessageOfSize(producerSession, 10);
+
+ // Set the TTL on the message and record its value in the message headers.
+ long ttl = 500 + r.nextInt(1500);
+ producer.setTimeToLive(ttl);
+ testMessage.setLongProperty("testTTL", ttl);
+
+ producer.send(testMessage);
+ // producerSession.commit();
+ }
+
+ // Inject a pause to allow some messages to be purged by TTL.
+ TestUtils.pause(1000);
+
+ // Attempt to receive back all of the messages, confirming by the message time stamps and TTLs that only
+ // those received should have avoided being purged by the TTL.
+ boolean timedOut = false;
+
+
+ Message testMessage = null;
+
+ do
+ {
+ testMessage = consumer.receive(1000);
+
+ long ttl = testMessage.getLongProperty("testTTL");
+ long timeStamp = testMessage.getJMSTimestamp();
+ long now = System.currentTimeMillis();
+
+ if ((timeStamp + ttl) < now)
+ {
+ errorMessages +=
+ "Received message [sent: " + timeStamp + ", ttl: " + ttl + ", received: " + now
+ + "] which should have been purged by its TTL.\n";
+ }
+ /*else
+ {
+ receivedMessages.add(testMessage);
+ }*/
+ } while (!timedOut && testMessage != null);
+
+ // Check that the queue and message store on the broker are empty.
+ // assertTrue("Message store is not empty.", messageStoreEmpty.apply());
+ // assertTrue("Queue is not empty.", queueEmpty.apply());
+
+ assertTrue(errorMessages, "".equals(errorMessages));
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java
index 23efb656d2..4b45a96c20 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/Acknowledge2ConsumersTest.java
@@ -23,7 +23,7 @@ package org.apache.qpid.test.unit.ack;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.FailoverBaseCase;
import javax.jms.Connection;
import javax.jms.JMSException;
@@ -32,7 +32,7 @@ import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
-public class Acknowledge2ConsumersTest extends QpidBrokerTestCase
+public class Acknowledge2ConsumersTest extends FailoverBaseCase
{
protected static int NUM_MESSAGES = 100;
protected Connection _con;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java
deleted file mode 100644
index 06be5cf456..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/ClientAcknowledgeTest.java
+++ /dev/null
@@ -1,82 +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.
- */
-package org.apache.qpid.test.unit.ack;
-
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-public class ClientAcknowledgeTest extends QpidBrokerTestCase
-{
- private static final long ONE_DAY_MS = 1000l * 60 * 60 * 24;
- private Connection _connection;
- private Queue _queue;
- private Session _consumerSession;
- private MessageConsumer _consumer;
- private MessageProducer _producer;
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
- _queue = getTestQueue();
- _connection = getConnection();
- }
-
- /**
- * Test that message.acknowledge actually acknowledges, regardless of
- * the flusher thread period, by restarting the broker after calling
- * acknowledge, and then verifying after restart that the message acked
- * is no longer present. This test requires a persistent store.
- */
- public void testClientAckWithLargeFlusherPeriod() throws Exception
- {
- setTestClientSystemProperty("qpid.session.max_ack_delay", Long.toString(ONE_DAY_MS));
- _consumerSession = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- _consumer = _consumerSession.createConsumer(_queue);
- _connection.start();
-
- _producer = _consumerSession.createProducer(_queue);
- _producer.send(createNextMessage(_consumerSession, 1));
- _producer.send(createNextMessage(_consumerSession, 2));
-
- Message message = _consumer.receive(1000l);
- assertNotNull("Message has not been received", message);
- assertEquals("Unexpected message is received", 1, message.getIntProperty(INDEX));
- message.acknowledge();
-
- //restart broker to allow verification of the acks
- //without explicitly closing connection (which acks)
- restartBroker();
-
- // try to receive the message again, which should fail (as it was ackd)
- _connection = getConnection();
- _connection.start();
- _consumerSession = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- _consumer = _consumerSession.createConsumer(_queue);
- message = _consumer.receive(1000l);
- assertNotNull("Message has not been received", message);
- assertEquals("Unexpected message is received", 2, message.getIntProperty(INDEX));
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java
index 13c78c1e14..6c83136511 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/QuickAcking.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.test.unit.ack;
-import java.util.concurrent.CountDownLatch;
+import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java
index 66ca1d8345..5e7ba5482d 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java
@@ -46,7 +46,7 @@ public class RecoverTest extends FailoverBaseCase
{
static final Logger _logger = LoggerFactory.getLogger(RecoverTest.class);
- private volatile Exception _error;
+ private Exception _error;
private AtomicInteger count;
protected AMQConnection _connection;
@@ -249,13 +249,14 @@ public class RecoverTest extends FailoverBaseCase
{
if (!message.getJMSRedelivered())
{
- setError(new Exception("Message not marked as redelivered on what should be second delivery attempt"));
+ setError(
+ new Exception("Message not marked as redelivered on what should be second delivery attempt"));
}
}
else
{
- _logger.error(message.toString());
- setError(new Exception("Message delivered too many times!: " + count));
+ System.err.println(message);
+ fail("Message delivered too many times!: " + count);
}
}
catch (JMSException e)
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
index 0731d56204..59ce64eb4f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
@@ -21,6 +21,7 @@ package org.apache.qpid.test.unit.basic;
import junit.framework.Assert;
+import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
@@ -44,7 +45,6 @@ import javax.jms.MessageNotWriteableException;
import javax.jms.MessageProducer;
import javax.jms.Session;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
index 3af215d1d5..abf8da799c 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.test.unit.basic;
+import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
@@ -39,8 +41,6 @@ import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
@@ -105,7 +105,7 @@ public class FieldTableMessageTest extends QpidBrokerTestCase implements Message
{
int count = _count;
_waitForCompletion = new CountDownLatch(_count);
- send(count);
+ send(count);
_waitForCompletion.await(20, TimeUnit.SECONDS);
check();
_logger.info("Completed without failure");
@@ -125,15 +125,12 @@ public class FieldTableMessageTest extends QpidBrokerTestCase implements Message
}
- void check() throws JMSException, AMQFrameDecodingException, IOException
+ void check() throws JMSException, AMQFrameDecodingException
{
for (Object m : received)
{
- final BytesMessage bytesMessage = (BytesMessage) m;
- final long bodyLength = bytesMessage.getBodyLength();
- byte[] data = new byte[(int) bodyLength];
- bytesMessage.readBytes(data);
- FieldTable actual = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(data)), bodyLength);
+ ByteBuffer buffer = ((JMSBytesMessage) m).getData();
+ FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining());
for (String key : _expected.keys())
{
assertEquals("Values for " + key + " did not match", _expected.getObject(key), actual.getObject(key));
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
index 87eae32cf8..3a5f676ca6 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
@@ -23,6 +23,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
index 3c7962d873..c6b8069300 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
@@ -21,13 +21,14 @@
package org.apache.qpid.test.unit.basic.close;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.url.AMQBindingURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
-import javax.jms.Queue;
import javax.jms.Session;
public class CloseTest extends QpidBrokerTestCase
@@ -40,7 +41,7 @@ public class CloseTest extends QpidBrokerTestCase
Session session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
- Queue queue = session.createQueue("test-queue");
+ AMQQueue queue = new AMQQueue(new AMQBindingURL("test-queue"));
MessageConsumer consumer = session.createConsumer(queue);
MessageProducer producer_not_used_but_created_for_testing = session.createProducer(queue);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
index 53a7533869..292bcd6039 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
@@ -20,15 +20,28 @@
*/
package org.apache.qpid.test.unit.client;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.jms.Connection;
+import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.QueueSession;
import javax.jms.Session;
+import javax.jms.TextMessage;
import javax.jms.TopicSession;
import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionDelegate_0_10;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
@@ -40,9 +53,9 @@ import org.slf4j.LoggerFactory;
public class AMQConnectionTest extends QpidBrokerTestCase
{
- protected static AMQConnection _connection;
- protected static AMQTopic _topic;
- protected static AMQQueue _queue;
+ private static AMQConnection _connection;
+ private static AMQTopic _topic;
+ private static AMQQueue _queue;
private static QueueSession _queueSession;
private static TopicSession _topicSession;
protected static final Logger _logger = LoggerFactory.getLogger(AMQConnectionTest.class);
@@ -50,14 +63,15 @@ public class AMQConnectionTest extends QpidBrokerTestCase
protected void setUp() throws Exception
{
super.setUp();
- createConnection();
+ _connection = (AMQConnection) getConnection("guest", "guest");
_topic = new AMQTopic(_connection.getDefaultTopicExchangeName(), new AMQShortString("mytopic"));
_queue = new AMQQueue(_connection.getDefaultQueueExchangeName(), new AMQShortString("myqueue"));
}
-
- protected void createConnection() throws Exception
+
+ protected void tearDown() throws Exception
{
- _connection = (AMQConnection) getConnection("guest", "guest");
+ _connection.close();
+ super.tearDown();
}
/**
@@ -196,50 +210,60 @@ public class AMQConnectionTest extends QpidBrokerTestCase
public void testPrefetchSystemProperty() throws Exception
{
- _connection.close();
- setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(2).toString());
-
- createConnection();
- _connection.start();
- // Create two consumers on different sessions
- Session consSessA = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
- MessageConsumer consumerA = consSessA.createConsumer(_queue);
+ String oldPrefetch = System.getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME);
+ try
+ {
+ _connection.close();
+ System.setProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(2).toString());
+ _connection = (AMQConnection) getConnection();
+ _connection.start();
+ // Create two consumers on different sessions
+ Session consSessA = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer consumerA = consSessA.createConsumer(_queue);
- Session producerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- MessageProducer producer = producerSession.createProducer(_queue);
+ Session producerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(_queue);
- // Send 3 messages
- for (int i = 0; i < 3; i++)
- {
- producer.send(producerSession.createTextMessage("test"));
- }
-
- MessageConsumer consumerB = null;
- // 0-8, 0-9, 0-9-1 prefetch is per session, not consumer.
- if (!isBroker010())
- {
- Session consSessB = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
- consumerB = consSessB.createConsumer(_queue);
- }
- else
- {
- consumerB = consSessA.createConsumer(_queue);
- }
+ // Send 3 messages
+ for (int i = 0; i < 3; i++)
+ {
+ producer.send(producerSession.createTextMessage("test"));
+ }
+
+ MessageConsumer consumerB = null;
+ if (isBroker08())
+ {
+ Session consSessB = _connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
+ consumerB = consSessB.createConsumer(_queue);
+ }
+ else
+ {
+ consumerB = consSessA.createConsumer(_queue);
+ }
- Message msg;
- // Check that consumer A has 2 messages
- for (int i = 0; i < 2; i++)
- {
+ Message msg;
+ // Check that consumer A has 2 messages
+ for (int i = 0; i < 2; i++)
+ {
+ msg = consumerA.receive(1500);
+ assertNotNull("Consumer A should receive 2 messages",msg);
+ }
+
msg = consumerA.receive(1500);
- assertNotNull("Consumer A should receive 2 messages",msg);
+ assertNull("Consumer A should not have received a 3rd message",msg);
+
+ // Check that consumer B has the last message
+ msg = consumerB.receive(1500);
+ assertNotNull("Consumer B should have received the message",msg);
+ }
+ finally
+ {
+ if (oldPrefetch == null)
+ {
+ oldPrefetch = ClientProperties.MAX_PREFETCH_DEFAULT;
+ }
+ System.setProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, oldPrefetch);
}
-
- msg = consumerA.receive(1500);
- assertNull("Consumer A should not have received a 3rd message",msg);
-
- // Check that consumer B has the last message
- msg = consumerB.receive(1500);
- assertNotNull("Consumer B should have received the message",msg);
}
public void testGetChannelID() throws Exception
@@ -262,5 +286,120 @@ public class AMQConnectionTest extends QpidBrokerTestCase
}
}
}
+
+ /**
+ * Test Strategy : Kill -STOP the broker and see
+ * if the client terminates the connection with a
+ * read timeout.
+ * The broker process is cleaned up in the test itself
+ * and avoids using process.waitFor() as it hangs.
+ */
+ public void testHeartBeat() throws Exception
+ {
+ boolean windows =
+ ((String) System.getProperties().get("os.name")).matches("(?i).*windows.*");
+
+ if (!isCppBroker() || windows)
+ {
+ return;
+ }
+
+ Process process = null;
+ int port = getPort(0);
+ String pid = null;
+ try
+ {
+ // close the connection and shutdown the broker started by QpidTest
+ _connection.close();
+ stopBroker(port);
+
+ System.setProperty("qpid.heartbeat", "1");
+
+ // in case this broker gets stuck, atleast the rest of the tests will not fail.
+ port = port + 200;
+ String startCmd = getBrokerCommand(port);
+
+ // start a broker using a script
+ ProcessBuilder pb = new ProcessBuilder(System.getProperty("broker.start"));
+ pb.redirectErrorStream(true);
+
+ Map<String, String> env = pb.environment();
+ env.put("BROKER_CMD",startCmd);
+ env.put("BROKER_READY",System.getProperty(BROKER_READY));
+
+ Process startScript = pb.start();
+ startScript.waitFor();
+ startScript.destroy();
+
+ Connection con =
+ new AMQConnection("amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:" + port + "'");
+ final AtomicBoolean lock = new AtomicBoolean(false);
+
+ String cmd = "/usr/bin/pgrep -f " + port;
+ process = Runtime.getRuntime().exec("/bin/bash");
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(process.getInputStream()));
+ PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(process.getOutputStream())), true);
+ out.println(cmd);
+ pid = reader.readLine();
+ try
+ {
+ Integer.parseInt(pid);
+ }
+ catch (NumberFormatException e)
+ {
+ // Error! try to read further to gather the error msg.
+ String line;
+ _logger.debug(pid);
+ while ((line = reader.readLine()) != null )
+ {
+ _logger.debug(line);
+ }
+ throw new Exception( "Unable to get the brokers pid " + pid);
+ }
+ _logger.debug("pid : " + pid);
+
+ con.setExceptionListener(new ExceptionListener(){
+
+ public void onException(JMSException e)
+ {
+ synchronized(lock) {
+ lock.set(true);
+ lock.notifyAll();
+ }
+ }
+ });
+ out.println("kill -STOP " + pid);
+
+ synchronized(lock){
+ lock.wait(2500);
+ }
+ out.close();
+ reader.close();
+ assertTrue("Client did not terminate the connection, check log for details",lock.get());
+ }
+ catch(Exception e)
+ {
+ throw e;
+ }
+ finally
+ {
+ System.setProperty("qpid.heartbeat", "");
+
+ if (process != null)
+ {
+ process.destroy();
+ }
+
+ Process killScript = Runtime.getRuntime().exec(System.getProperty("broker.kill") + " " + pid);
+ killScript.waitFor();
+ killScript.destroy();
+ cleanBroker();
+ }
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(AMQConnectionTest.class);
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java
deleted file mode 100644
index 5f3daa407a..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSSLConnectionTest.java
+++ /dev/null
@@ -1,57 +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.
- *
- */
-
-package org.apache.qpid.test.unit.client;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionURL;
-
-public class AMQSSLConnectionTest extends AMQConnectionTest
-{
- private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks";
- private static final String KEYSTORE_PASSWORD = "password";
- private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks";
- private static final String TRUSTSTORE_PASSWORD = "password";
-
- @Override
- protected void setUp() throws Exception
- {
- setTestClientSystemProperty("profile.use_ssl", "true");
- setConfigurationProperty("connector.ssl.enabled", "true");
- setConfigurationProperty("connector.ssl.sslOnly", "true");
- super.setUp();
- }
-
- protected void createConnection() throws Exception
- {
-
- final String sslPrototypeUrl = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" +
- "?ssl='true'&ssl_verify_hostname='false'" +
- "&key_store='%s'&key_store_password='%s'" +
- "&trust_store='%s'&trust_store_password='%s'" +
- "'";
-
- final String url = String.format(sslPrototypeUrl,System.getProperty("test.port.ssl"),
- KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD);
-
- _connection = (AMQConnection) getConnection(new AMQConnectionURL(url));
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
index 8577fb5b6a..33575b58aa 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.test.unit.client;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.jms.Connection;
@@ -34,9 +32,11 @@ import javax.jms.Session;
*
* Test to validate that setting the respective qpid.declare_queues,
* qpid.declare_exchanges system properties functions as expected.
+ *
*/
public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
{
+
public void testQueueDeclare() throws Exception
{
setSystemProperty("qpid.declare_queues", "false");
@@ -53,8 +53,11 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
fail("JMSException should be thrown as the queue does not exist");
}
catch (JMSException e)
- {
- checkExceptionErrorCode(e, AMQConstant.NOT_FOUND);
+ {
+ assertTrue("Exception should be that the queue does not exist :" +
+ e.getMessage(),
+ e.getMessage().contains("does not exist"));
+
}
}
@@ -76,15 +79,10 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
}
catch (JMSException e)
{
- checkExceptionErrorCode(e, AMQConstant.NOT_FOUND);
+ assertTrue("Exception should be that the exchange does not exist :" +
+ e.getMessage(),
+ e.getMessage().contains("Exchange " + EXCHANGE_TYPE + " does not exist"));
}
}
- private void checkExceptionErrorCode(JMSException original, AMQConstant code)
- {
- Exception linked = original.getLinkedException();
- assertNotNull("Linked exception should have been set", linked);
- assertTrue("Linked exception should be an AMQException", linked instanceof AMQException);
- assertEquals("Error code should be " + code.getCode(), code, ((AMQException) linked).getErrorCode());
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
index aae8b1feb9..79e2ff8148 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
@@ -24,6 +24,7 @@ import junit.textui.TestRunner;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.slf4j.Logger;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
index 2e8a2d049d..f0794c9dab 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
@@ -25,9 +25,11 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.*;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,67 +49,70 @@ public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionLis
private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseTest.class);
Connection _connection;
+ private String _brokerlist = "vm://:1";
private Session _session;
private static final long SYNC_TIMEOUT = 500;
private int TEST = 0;
- /**
- * Close channel, use chanel with same id ensure error.
- *
- * This test is only valid for non 0-10 connection .
+ /*
+ close channel, use chanel with same id ensure error.
*/
public void testReusingChannelAfterFullClosure() throws Exception
{
- _connection=newConnection();
-
- // Create Producer
- try
+ // this is testing an inVM Connetion conneciton
+ if (isJavaBroker() && !isExternalBroker())
{
- _connection.start();
-
- createChannelAndTest(1);
+ _connection=newConnection();
- // Cause it to close
+ // Create Producer
try
{
- _logger.info("Testing invalid exchange");
- declareExchange(1, "", "name_that_will_lookup_to_null", false);
- fail("Exchange name is empty so this should fail ");
- }
- catch (AMQException e)
- {
- assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode());
- }
+ _connection.start();
- // Check that
- try
- {
- _logger.info("Testing valid exchange should fail");
- declareExchange(1, "topic", "amq.topic", false);
- fail("This should not succeed as the channel should be closed ");
- }
- catch (AMQException e)
- {
- if (_logger.isInfoEnabled())
+ createChannelAndTest(1);
+
+ // Cause it to close
+ try
+ {
+ _logger.info("Testing invalid exchange");
+ declareExchange(1, "", "name_that_will_lookup_to_null", false);
+ fail("Exchange name is empty so this should fail ");
+ }
+ catch (AMQException e)
{
- _logger.info("Exception occured was:" + e.getErrorCode());
+ assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode());
}
- assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode());
+ // Check that
+ try
+ {
+ _logger.info("Testing valid exchange should fail");
+ declareExchange(1, "topic", "amq.topic", false);
+ fail("This should not succeed as the channel should be closed ");
+ }
+ catch (AMQException e)
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Exception occured was:" + e.getErrorCode());
+ }
- _connection=newConnection();
- }
+ assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode());
- checkSendingMessage();
+ _connection=newConnection();
+ }
- _session.close();
- _connection.close();
+ checkSendingMessage();
- }
- catch (JMSException e)
- {
- e.printStackTrace();
- fail(e.getMessage());
+ _session.close();
+ _connection.close();
+
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
}
}
@@ -301,19 +306,27 @@ public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionLis
private Connection newConnection()
{
- Connection connection = null;
+ AMQConnection connection = null;
try
{
- connection = getConnection();
+ connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'");
- ((AMQConnection) connection).setConnectionListener(this);
+ connection.setConnectionListener(this);
_session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
connection.start();
}
- catch (Exception e)
+ catch (JMSException e)
+ {
+ fail("Creating new connection when:" + e.getMessage());
+ }
+ catch (AMQException e)
+ {
+ fail("Creating new connection when:" + e.getMessage());
+ }
+ catch (URLSyntaxException e)
{
fail("Creating new connection when:" + e.getMessage());
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java
index 91e681131f..dc2f59c384 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/CloseAfterConnectionFailureTest.java
@@ -55,7 +55,7 @@ public class CloseAfterConnectionFailureTest extends QpidBrokerTestCase implemen
try
{
//Start the connection so it will use the retries
- connection = new AMQConnection(url);
+ connection = new AMQConnection(url, null);
connection.setExceptionListener(this);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
index 7f166d07fe..6d1b6de238 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
import java.util.Map;
import javax.jms.Connection;
-import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
@@ -99,31 +98,6 @@ public class ConnectionCloseTest extends QpidBrokerTestCase
delta.size() < deltaThreshold);
}
- /**
- * This test is added due to QPID-3453 to test connection closing when AMQ
- * session is not closed but underlying transport session is in detached
- * state and transport connection is closed
- */
- public void testConnectionCloseOnOnForcibleBrokerStop() throws Exception
- {
- Connection connection = getConnection();
- connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- stopBroker();
-
- // we need to close connection explicitly in order to verify that
- // closing of connection having transport session in DETACHED state and
- // transport connection in CLOSED state does not throw an exception
- try
- {
- connection.close();
- }
- catch (JMSException e)
- {
- // session closing should not fail
- fail("Cannot close connection:" + e.getMessage());
- }
- }
-
private void dumpStacks(Map<Thread,StackTraceElement[]> map)
{
for (Map.Entry<Thread,StackTraceElement[]> entry : map.entrySet())
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java
deleted file mode 100644
index 545081fb43..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionFactoryTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.apache.qpid.test.unit.client.connection;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-public class ConnectionFactoryTest extends QpidBrokerTestCase
-{
-
- /**
- * The username & password specified should not override the default
- * specified in the URL.
- */
- public void testCreateConnectionWithUsernamePassword() throws Exception
- {
-
- String brokerUrl = getBroker().toString();
- String URL = "amqp://guest:guest@clientID/test?brokerlist='" + brokerUrl + "'";
- AMQConnectionFactory factory = new AMQConnectionFactory(URL);
-
- AMQConnection con = (AMQConnection)factory.createConnection();
- assertEquals("Usernames used is different from the one in URL","guest",con.getConnectionURL().getUsername());
- assertEquals("Password used is different from the one in URL","guest",con.getConnectionURL().getPassword());
-
- try
- {
- AMQConnection con2 = (AMQConnection)factory.createConnection("user","pass");
- assertEquals("Usernames used is different from the one in URL","user",con2.getConnectionURL().getUsername());
- assertEquals("Password used is different from the one in URL","pass",con2.getConnectionURL().getPassword());
- }
- catch(Exception e)
- {
- // ignore
- }
-
- AMQConnection con3 = (AMQConnection)factory.createConnection();
- assertEquals("Usernames used is different from the one in URL","guest",con3.getConnectionURL().getUsername());
- assertEquals("Password used is different from the one in URL","guest",con3.getConnectionURL().getPassword());
- }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
index f18f365f20..04fc611cd1 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
@@ -20,31 +20,32 @@
*/
package org.apache.qpid.test.unit.client.connection;
-import javax.jms.Connection;
-import javax.jms.QueueSession;
-import javax.jms.TopicSession;
-
import org.apache.qpid.AMQConnectionFailureException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnresolvedAddressException;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.client.AMQAuthenticationException;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.jms.BrokerDetails;
-import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.jms.BrokerDetails;
+
+import javax.jms.Connection;
+import javax.jms.QueueSession;
+import javax.jms.TopicSession;
+import javax.naming.NamingException;
public class ConnectionTest extends QpidBrokerTestCase
{
- String _broker_NotRunning = "tcp://localhost:" + findFreePort();
-
+ String _broker_NotRunning = "vm://:2";
String _broker_BadDNS = "tcp://hg3sgaaw4lgihjs";
public void testSimpleConnection() throws Exception
@@ -82,21 +83,21 @@ public class ConnectionTest extends QpidBrokerTestCase
+ "&temporaryTopicExchange='tmp.topic'");
System.err.println(url.toString());
- conn = new AMQConnection(url);
+ conn = new AMQConnection(url, null);
AMQSession sess = (AMQSession) conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- sess.declareExchange(new AMQShortString("test.direct"),
+
+ sess.declareExchange(new AMQShortString("test.direct"),
ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false);
- sess.declareExchange(new AMQShortString("tmp.direct"),
+ sess.declareExchange(new AMQShortString("tmp.direct"),
ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false);
- sess.declareExchange(new AMQShortString("tmp.topic"),
+ sess.declareExchange(new AMQShortString("tmp.topic"),
ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false);
- sess.declareExchange(new AMQShortString("test.topic"),
+ sess.declareExchange(new AMQShortString("test.topic"),
ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false);
QueueSession queueSession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
@@ -112,7 +113,7 @@ public class ConnectionTest extends QpidBrokerTestCase
queueSession.close();
TopicSession topicSession = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-
+
AMQTopic topic = (AMQTopic) topicSession.createTopic("silly.topic");
assertEquals(topic.getExchangeName().toString(), "test.topic");
@@ -270,7 +271,7 @@ public class ConnectionTest extends QpidBrokerTestCase
}
connection.close();
}
-
+
public void testUnsupportedSASLMechanism() throws Exception
{
BrokerDetails broker = getBroker();
@@ -286,64 +287,10 @@ public class ConnectionTest extends QpidBrokerTestCase
}
catch (Exception e)
{
- assertTrue("Unexpected exception message : " + e.getMessage(),
- e.getMessage().contains("Client and broker have no SASL mechanisms in common."));
- assertTrue("Unexpected exception message : " + e.getMessage(),
- e.getMessage().contains("Client restricted itself to : MY_MECH"));
-
- }
- }
-
- /**
- * Tests that when the same user connects twice with same clientid, the second connection
- * fails if the clientid verification feature is enabled (which uses a dummy 0-10 Session
- * with the clientid as its name to detect the previous usage of the clientid by the user)
- */
- public void testClientIDVerificationForSameUser() throws Exception
- {
- setTestSystemProperty(ClientProperties.QPID_VERIFY_CLIENT_ID, "true");
-
- BrokerDetails broker = getBroker();
- try
- {
- Connection con = new AMQConnection(broker.toString(), "guest", "guest",
- "client_id", "test");
-
- Connection con2 = new AMQConnection(broker.toString(), "guest", "guest",
- "client_id", "test");
-
- fail("The client should throw a ConnectionException stating the" +
- " client ID is not unique");
- }
- catch (Exception e)
- {
- assertTrue("Incorrect exception thrown: " + e.getMessage(),
- e.getMessage().contains("ClientID must be unique"));
- }
- }
-
- /**
- * Tests that when different users connects with same clientid, the second connection
- * succeeds even though the clientid verification feature is enabled (which uses a dummy
- * 0-10 Session with the clientid as its name; these are only verified unique on a
- * per-principal basis)
- */
- public void testClientIDVerificationForDifferentUsers() throws Exception
- {
- setTestSystemProperty(ClientProperties.QPID_VERIFY_CLIENT_ID, "true");
-
- BrokerDetails broker = getBroker();
- try
- {
- Connection con = new AMQConnection(broker.toString(), "guest", "guest",
- "client_id", "test");
-
- Connection con2 = new AMQConnection(broker.toString(), "admin", "admin",
- "client_id", "test");
- }
- catch (Exception e)
- {
- fail("Unexpected exception thrown, client id was not unique but usernames were different! " + e.getMessage());
+ assertTrue("Incorrect exception thrown",
+ e.getMessage().contains("The following SASL mechanisms " +
+ "[MY_MECH]" +
+ " specified by the client are not supported by the broker"));
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
index 0057422c8f..cec9d292cf 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
@@ -47,15 +47,13 @@ public class ExceptionListenerTest extends QpidBrokerTestCase
{
public void onException(JMSException e)
{
- _logger.debug("&&&&&&&&&&&&&&&&&&&&&&&&&&&& Caught exception &&&&&&&&&&&&&&&&&&&&&&&&&&&& ", e);
fired.countDown();
}
});
- _logger.debug("%%%%%%%%%%%%%%%% Stopping Broker %%%%%%%%%%%%%%%%%%%%%");
+
stopBroker();
- _logger.debug("%%%%%%%%%%%%%%%% Stopped Broker %%%%%%%%%%%%%%%%%%%%%");
- if (!fired.await(5, TimeUnit.SECONDS))
+ if (!fired.await(3, TimeUnit.SECONDS))
{
fail("exception listener was not fired");
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
index 8ad8fa77d7..fd28b86762 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
@@ -20,25 +20,26 @@
*/
package org.apache.qpid.test.unit.client.message;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.ObjectMessage;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
public class ObjectMessageTest extends QpidBrokerTestCase implements MessageListener
{
private static final Logger _logger = LoggerFactory.getLogger(ObjectMessageTest.class);
@@ -66,7 +67,7 @@ public class ObjectMessageTest extends QpidBrokerTestCase implements MessageList
connection.start();
// create a publisher
- producer = session.createProducer(destination, false, false);
+ producer = session.createProducer(destination, false, false, true);
A a1 = new A(1, "A");
A a2 = new A(2, "a");
B b = new B(1, "B");
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
index 836684c965..278b9e9c04 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
@@ -25,26 +25,27 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
+import org.apache.mina.transport.vmpipe.VmPipeAddress;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.transport.TestNetworkConnection;
+import org.apache.qpid.transport.TestNetworkDriver;
public class AMQProtocolSessionTest extends QpidBrokerTestCase
{
- private static class TestProtocolSession extends AMQProtocolSession
+ private static class AMQProtSession extends AMQProtocolSession
{
- public TestProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection)
+ public AMQProtSession(AMQProtocolHandler protocolHandler, AMQConnection connection)
{
super(protocolHandler,connection);
}
- public TestNetworkConnection getNetworkConnection()
+ public TestNetworkDriver getNetworkDriver()
{
- return (TestNetworkConnection) _protocolHandler.getNetworkConnection();
+ return (TestNetworkDriver) _protocolHandler.getNetworkDriver();
}
public AMQShortString genQueueName()
@@ -53,7 +54,7 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase
}
}
- private TestProtocolSession _testSession;
+ private AMQProtSession _testSession;
protected void setUp() throws Exception
{
@@ -61,10 +62,10 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase
AMQConnection con = (AMQConnection) getConnection("guest", "guest");
AMQProtocolHandler protocolHandler = new AMQProtocolHandler(con);
- protocolHandler.setNetworkConnection(new TestNetworkConnection());
-
+ protocolHandler.setNetworkDriver(new TestNetworkDriver());
+
//don't care about the values set here apart from the dummy IoSession
- _testSession = new TestProtocolSession(protocolHandler , con);
+ _testSession = new AMQProtSession(protocolHandler , con);
}
public void testTemporaryQueueWildcard() throws UnknownHostException
@@ -92,9 +93,14 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase
checkTempQueueName(new InetSocketAddress(InetAddress.getByName("1080:0:0:0:8:800:200C:417A"), 1234), "tmp_1080_0_0_0_8_800_200c_417a_1234_1");
}
+ public void testTemporaryQueuePipe() throws UnknownHostException
+ {
+ checkTempQueueName(new VmPipeAddress(1), "tmp_vm_1_1");
+ }
+
private void checkTempQueueName(SocketAddress address, String queueName)
{
- _testSession.getNetworkConnection().setLocalAddress(address);
+ _testSession.getNetworkDriver().setLocalAddress(address);
assertEquals("Wrong queue name", queueName, _testSession.genQueueName().asString());
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
index c98e403671..8c806fa2da 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
@@ -22,145 +22,237 @@
package org.apache.qpid.test.unit.client.temporaryqueue;
import javax.jms.Connection;
+import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;
import javax.jms.TextMessage;
+import junit.framework.Assert;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.jms.ConnectionListener;
-/**
- * Tests the behaviour of {@link TemporaryQueue}.
- */
-public class TemporaryQueueTest extends QpidBrokerTestCase
+import java.util.ArrayList;
+import java.util.List;
+import java.util.LinkedList;
+
+public class TemporaryQueueTest extends QpidBrokerTestCase implements ExceptionListener
{
- /**
- * Tests the basic produce/consume behaviour of a temporary queue.
- */
- public void testMessageDeliveryUsingTemporaryQueue() throws Exception
+ private List<Exception> _exceptions = new ArrayList<Exception>();
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception
{
- final Connection conn = getConnection();
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryQueue queue = session.createTemporaryQueue();
+ super.tearDown();
+ }
+
+ protected Connection createConnection() throws Exception
+ {
+ return getConnection("guest", "guest");
+ }
+
+ public void testTemporaryQueue() throws Exception
+ {
+ Connection conn = createConnection();
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryQueue queue = session.createTemporaryQueue();
assertNotNull(queue);
- final MessageProducer producer = session.createProducer(queue);
- final MessageConsumer consumer = session.createConsumer(queue);
+ MessageProducer producer = session.createProducer(queue);
+ MessageConsumer consumer = session.createConsumer(queue);
conn.start();
producer.send(session.createTextMessage("hello"));
TextMessage tm = (TextMessage) consumer.receive(2000);
- assertNotNull("Message not received", tm);
+ assertNotNull(tm);
assertEquals("hello", tm.getText());
- }
- /**
- * Tests that a temporary queue cannot be used by another {@link Session}.
- */
- public void testUseFromAnotherSessionProhibited() throws Exception
- {
- final Connection conn = getConnection();
- final Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryQueue queue = session1.createTemporaryQueue();
- assertNotNull(queue);
+ try
+ {
+ queue.delete();
+ fail("Expected JMSException : should not be able to delete while there are active consumers");
+ }
+ catch (JMSException je)
+ {
+ ; //pass
+ }
+
+ consumer.close();
try
{
- session2.createConsumer(queue);
- fail("Expected a JMSException when subscribing to a temporary queue created on a different session");
+ queue.delete();
}
catch (JMSException je)
{
- //pass
- assertEquals("Cannot consume from a temporary destination created on another session", je.getMessage());
+ fail("Unexpected Exception: " + je.getMessage());
}
+
+ conn.close();
}
- /**
- * Tests that the client is able to explicitly delete a temporary queue using
- * {@link TemporaryQueue#delete()} and is prevented from deleting one that
- * still has consumers.
- *
- * Note: Under < 0-10 {@link TemporaryQueue#delete()} only marks the queue as deleted
- * on the client. 0-10 causes the queue to be deleted from the Broker.
- */
- public void testExplictTemporaryQueueDeletion() throws Exception
+ public void tUniqueness() throws Exception
{
- final Connection conn = getConnection();
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final AMQSession<?, ?> amqSession = (AMQSession<?, ?>)session; // Required to observe the queue binding on the Broker
- final TemporaryQueue queue = session.createTemporaryQueue();
- assertNotNull(queue);
- final MessageConsumer consumer = session.createConsumer(queue);
- conn.start();
+ int numProcs = Runtime.getRuntime().availableProcessors();
+ final int threadsProc = 5;
- assertTrue("Queue should be bound", amqSession.isQueueBound((AMQDestination)queue));
+ runUniqueness(1, 10);
+ runUniqueness(numProcs * threadsProc, 10);
+ runUniqueness(numProcs * threadsProc, 100);
+ runUniqueness(numProcs * threadsProc, 500);
+ }
- try
+ void runUniqueness(int makers, int queues) throws Exception
+ {
+ Connection connection = createConnection();
+
+ Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ List<TempQueueMaker> tqList = new LinkedList<TempQueueMaker>();
+
+ //Create Makers
+ for (int m = 0; m < makers; m++)
{
- queue.delete();
- fail("Expected JMSException : should not be able to delete while there are active consumers");
+ tqList.add(new TempQueueMaker(session, queues));
}
- catch (JMSException je)
+
+
+ List<Thread> threadList = new LinkedList<Thread>();
+
+ //Create Makers
+ for (TempQueueMaker maker : tqList)
{
- //pass
- assertEquals("Temporary Queue has consumers so cannot be deleted", je.getMessage());
+ threadList.add(new Thread(maker));
}
- consumer.close();
- // Now deletion should succeed.
- queue.delete();
+ //Start threads
+ for (Thread thread : threadList)
+ {
+ thread.start();
+ }
- try
+ // Join Threads
+ for (Thread thread : threadList)
{
- session.createConsumer(queue);
- fail("Exception not thrown");
+ try
+ {
+ thread.join();
+ }
+ catch (InterruptedException e)
+ {
+ fail("Couldn't correctly join threads");
+ }
}
- catch (JMSException je)
+
+
+ List<AMQQueue> list = new LinkedList<AMQQueue>();
+
+ // Test values
+ for (TempQueueMaker maker : tqList)
{
- //pass
- assertEquals("Cannot consume from a deleted destination", je.getMessage());
+ check(maker, list);
}
- if (isBroker010())
+ Assert.assertEquals("Not enough queues made.", makers * queues, list.size());
+
+ connection.close();
+ }
+
+ private void check(TempQueueMaker tq, List<AMQQueue> list)
+ {
+ for (AMQQueue q : tq.getList())
{
- assertFalse("Queue should no longer be bound", amqSession.isQueueBound((AMQDestination)queue));
+ if (list.contains(q))
+ {
+ fail(q + " already exists.");
+ }
+ else
+ {
+ list.add(q);
+ }
}
}
- /**
- * Tests that a temporary queue remains available for reuse even after its initial
- * consumer has disconnected.
- *
- * This test would fail under < 0-10 as their temporary queues are deleted automatically
- * (broker side) after the last consumer disconnects (so message2 would be lost). For this
- * reason this test is excluded from those profiles.
- */
- public void testTemporaryQueueReused() throws Exception
+
+ class TempQueueMaker implements Runnable
{
- final Connection conn = getConnection();
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryQueue queue = session.createTemporaryQueue();
- assertNotNull(queue);
+ List<AMQQueue> _queues;
+ Session _session;
+ private int _count;
- final MessageProducer producer1 = session.createProducer(queue);
- final MessageConsumer consumer1 = session.createConsumer(queue);
- conn.start();
- producer1.send(session.createTextMessage("message1"));
- producer1.send(session.createTextMessage("message2"));
- TextMessage tm = (TextMessage) consumer1.receive(2000);
- assertNotNull("Message not received by first consumer", tm);
- assertEquals("message1", tm.getText());
- consumer1.close();
-
- final MessageConsumer consumer2 = session.createConsumer(queue);
- conn.start();
- tm = (TextMessage) consumer2.receive(2000);
- assertNotNull("Message not received by second consumer", tm);
- assertEquals("message2", tm.getText());
- consumer2.close();
+
+ TempQueueMaker(Session session, int queues) throws JMSException
+ {
+ _queues = new LinkedList<AMQQueue>();
+
+ _count = queues;
+
+ _session = session;
+ }
+
+ public void run()
+ {
+ int i = 0;
+ try
+ {
+ for (; i < _count; i++)
+ {
+ _queues.add((AMQQueue) _session.createTemporaryQueue());
+ }
+ }
+ catch (JMSException jmse)
+ {
+ //stop
+ }
+ }
+
+ List<AMQQueue> getList()
+ {
+ return _queues;
+ }
+ }
+
+ public void testQPID1217() throws Exception
+ {
+ Connection conA = getConnection();
+ conA.setExceptionListener(this);
+ Session sessA = conA.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryQueue temp = sessA.createTemporaryQueue();
+
+ MessageProducer prod = sessA.createProducer(temp);
+ prod.send(sessA.createTextMessage("hi"));
+
+ Thread.sleep(500);
+ assertTrue("Exception received", _exceptions.isEmpty());
+
+ Connection conB = getConnection();
+ Session sessB = conB.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ JMSException ex = null;
+ try
+ {
+ MessageConsumer consB = sessB.createConsumer(temp);
+ }
+ catch (JMSException e)
+ {
+ ex = e;
+ }
+ assertNotNull(ex);
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(TemporaryQueueTest.class);
}
+
+ public void onException(JMSException arg0)
+ {
+ _exceptions.add(arg0);
+ }
+
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
index f5e0ed75d2..de092fc893 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
@@ -50,6 +50,7 @@ public class MessageRequeueTest extends QpidBrokerTestCase
protected final String queue = "direct://amq.direct//message-requeue-test-queue";
protected String payload = "Message:";
+ //protected final String BROKER = "vm://:1";
protected final String BROKER = "tcp://127.0.0.1:5672";
private boolean testReception = true;
@@ -154,8 +155,8 @@ public class MessageRequeueTest extends QpidBrokerTestCase
_logger.info("consumed: " + messagesReceived);
assertEquals("number of consumed messages does not match initial data", (int) numTestMessages, messagesReceived);
- // with 0_10 we can have a delivery tag of 0
- if (!conn.isBroker010())
+ // wit 0_10 we can have a delivery tag of 0
+ if (conn.isBroker08())
{
for (long b : messageLog)
{
@@ -223,7 +224,7 @@ public class MessageRequeueTest extends QpidBrokerTestCase
StringBuilder list = new StringBuilder();
list.append("Failed to receive:");
int failed = 0;
- if (!conn.isBroker010())
+ if (conn.isBroker08())
{
for (long b : receieved)
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
index 80422cf3e9..989ac98747 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
@@ -52,7 +52,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase
*/
public void testDurSubRestoredAfterNonPersistentMessageSent() throws Exception
{
- if (isBrokerStorePersistent())
+ if (isBrokerStorePersistent() || !isBroker08())
{
TopicConnectionFactory factory = getConnectionFactory();
Topic topic = (Topic) getInitialContext().lookup(_topicName);
@@ -116,7 +116,7 @@ public class DurableSubscriberTest extends QpidBrokerTestCase
*/
public void testDurSubRestoresMessageSelector() throws Exception
{
- if (isBrokerStorePersistent())
+ if (isBrokerStorePersistent() || !isBroker08())
{
TopicConnectionFactory factory = getConnectionFactory();
Topic topic = (Topic) getInitialContext().lookup(_topicName);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
index 97452ad1c8..830421a01f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
@@ -25,14 +25,12 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.NonQpidObjectMessage;
-import org.apache.qpid.client.message.QpidMessageProperties;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
@@ -41,11 +39,7 @@ import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.Session;
-import javax.jms.Topic;
-
import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
/**
* @author Apache Software Foundation
@@ -169,39 +163,4 @@ public class JMSPropertiesTest extends QpidBrokerTestCase
con.close();
}
- /**
- * Test Goal : Test if custom message properties can be set and retrieved properly with out an error.
- * Also test if unsupported properties are filtered out. See QPID-2930.
- */
- public void testQpidExtensionProperties() throws Exception
- {
- Connection con = getConnection("guest", "guest");
- Session ssn = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- con.start();
-
- Topic topic = ssn.createTopic("test");
- MessageConsumer consumer = ssn.createConsumer(topic);
- MessageProducer prod = ssn.createProducer(topic);
- Message m = ssn.createMessage();
- m.setObjectProperty("foo-bar", "foobar".getBytes());
- m.setObjectProperty(QpidMessageProperties.AMQP_0_10_APP_ID, "my-app-id");
- prod.send(m);
-
- Message msg = consumer.receive(1000);
- assertNotNull(msg);
-
- Enumeration<String> enu = msg.getPropertyNames();
- Map<String,String> map = new HashMap<String,String>();
- while (enu.hasMoreElements())
- {
- String name = enu.nextElement();
- String value = msg.getStringProperty(name);
- map.put(name, value);
- }
-
- assertFalse("Property 'foo-bar' should have been filtered out",map.containsKey("foo-bar"));
- assertEquals("Property "+ QpidMessageProperties.AMQP_0_10_APP_ID + " should be present","my-app-id",msg.getStringProperty(QpidMessageProperties.AMQP_0_10_APP_ID));
- assertEquals("Property "+ QpidMessageProperties.AMQP_0_10_ROUTING_KEY + " should be present","test",msg.getStringProperty(QpidMessageProperties.AMQP_0_10_ROUTING_KEY));
-
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
index 39691a5c7c..0f799073b4 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
@@ -20,10 +20,6 @@
*/
package org.apache.qpid.test.unit.message;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQHeadersExchange;
import org.apache.qpid.client.AMQQueue;
@@ -54,8 +50,21 @@ import javax.jms.StreamMessage;
*/
public class StreamMessageTest extends QpidBrokerTestCase
{
+
private static final Logger _logger = LoggerFactory.getLogger(StreamMessageTest.class);
+ public String _connectionString = "vm://:1";
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
public void testStreamMessageEOF() throws Exception
{
Connection con = (AMQConnection) getConnection("guest", "guest");
@@ -105,7 +114,6 @@ public class StreamMessageTest extends QpidBrokerTestCase
try
{
msg2.readByte();
- fail("Expected exception not thrown");
}
catch (Exception e)
{
@@ -117,9 +125,6 @@ public class StreamMessageTest extends QpidBrokerTestCase
public void testModifyReceivedMessageExpandsBuffer() throws Exception
{
- final CountDownLatch awaitMessages = new CountDownLatch(1);
- final AtomicReference<Throwable> listenerCaughtException = new AtomicReference<Throwable>();
-
AMQConnection con = (AMQConnection) getConnection("guest", "guest");
AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
AMQQueue queue = new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("testQ"));
@@ -129,38 +134,28 @@ public class StreamMessageTest extends QpidBrokerTestCase
public void onMessage(Message message)
{
- final StreamMessage sm = (StreamMessage) message;
+ StreamMessage sm = (StreamMessage) message;
try
{
sm.clearBody();
- // it is legal to extend a stream message's content
sm.writeString("dfgjshfslfjshflsjfdlsjfhdsljkfhdsljkfhsd");
}
- catch (Throwable t)
- {
- listenerCaughtException.set(t);
- }
- finally
+ catch (JMSException e)
{
- awaitMessages.countDown();
+ _logger.error("Error when writing large string to received msg: " + e, e);
+ fail("Error when writing large string to received msg" + e);
}
}
});
Connection con2 = (AMQConnection) getConnection("guest", "guest");
AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- MessageProducer producer = producerSession.createProducer(queue);
+ MessageProducer mandatoryProducer = producerSession.createProducer(queue);
con.start();
StreamMessage sm = producerSession.createStreamMessage();
sm.writeInt(42);
- producer.send(sm);
-
- // Allow up to five seconds for the message to arrive with the consumer
- final boolean completed = awaitMessages.await(5, TimeUnit.SECONDS);
- assertTrue("Message did not arrive with consumer within a reasonable time", completed);
- final Throwable listenerException = listenerCaughtException.get();
- assertNull("No exception should be caught by listener : " + listenerException, listenerException);
-
+ mandatoryProducer.send(sm);
+ Thread.sleep(2000);
con.close();
con2.close();
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java
index 978ebfa93f..fe929b4965 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/UTF8Test.java
@@ -20,20 +20,17 @@
*/
package org.apache.qpid.test.unit.message;
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.util.Properties;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.Session;
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.naming.InitialContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import javax.naming.InitialContext;
+import javax.jms.*;
+import java.util.Properties;
+import java.io.*;
/**
@@ -44,6 +41,8 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase;
*/
public class UTF8Test extends QpidBrokerTestCase
{
+ private static final Logger _logger = LoggerFactory.getLogger(UTF8Test.class);
+
public void testPlainEn() throws Exception
{
invoke("UTF8En");
@@ -66,24 +65,38 @@ public class UTF8Test extends QpidBrokerTestCase
private void runTest(String exchangeName, String queueName, String routingKey, String data) throws Exception
{
- Connection con = getConnection();
- Session sess = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
- final Destination dest = getDestination(exchangeName, routingKey, queueName);
-
- final MessageConsumer msgCons = sess.createConsumer(dest);
- con.start();
+ _logger.info("Running test for exchange: " + exchangeName
+ + " queue Name: " + queueName
+ + " routing key: " + routingKey);
+ declareQueue(exchangeName, routingKey, queueName);
+ javax.jms.Connection con = getConnection();
+ javax.jms.Session sess = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
+ Destination dest = getDestination(exchangeName, routingKey, queueName);
// Send data
MessageProducer msgProd = sess.createProducer(dest);
TextMessage message = sess.createTextMessage(data);
msgProd.send(message);
-
// consume data
+ MessageConsumer msgCons = sess.createConsumer(dest);
+ con.start();
TextMessage m = (TextMessage) msgCons.receive(RECEIVE_TIMEOUT);
assertNotNull(m);
assertEquals(m.getText(), data);
}
+ private void declareQueue(String exch, String routkey, String qname) throws Exception
+ {
+ Connection conn = new Connection();
+ conn.connect("localhost", QpidBrokerTestCase.DEFAULT_PORT, "test", "guest", "guest",false);
+ Session sess = conn.createSession(0);
+ sess.exchangeDeclare(exch, "direct", null, null);
+ sess.queueDeclare(qname, null, null);
+ sess.exchangeBind(qname, exch, routkey, null);
+ sess.sync();
+ conn.close();
+ }
+
private Destination getDestination(String exch, String routkey, String qname) throws Exception
{
Properties props = new Properties();
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java
new file mode 100644
index 0000000000..3ec7937812
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/publish/DirtyTransactedPublishTest.java
@@ -0,0 +1,403 @@
+/*
+ *
+ * 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 org.apache.qpid.test.unit.publish;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.test.utils.FailoverBaseCase;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TransactionRolledBackException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * QPID-1816 : Whilst testing Acknoledgement after failover this completes testing
+ * of the client after failover. When we have a dirty session we should receive
+ * an error if we attempt to publish. This test ensures that both in the synchronous
+ * and asynchronous message delivery paths we receive the expected exceptions at
+ * the expected time.
+ */
+public class DirtyTransactedPublishTest extends FailoverBaseCase implements ConnectionListener
+{
+ protected CountDownLatch _failoverCompleted = new CountDownLatch(1);
+
+ protected int NUM_MESSAGES;
+ protected Connection _connection;
+ protected Queue _queue;
+ protected Session _consumerSession;
+ protected MessageConsumer _consumer;
+ protected MessageProducer _producer;
+
+ private static final String MSG = "MSG";
+ private static final String SEND_FROM_ON_MESSAGE_TEXT = "sendFromOnMessage";
+ protected CountDownLatch _receviedAll;
+ protected AtomicReference<Exception> _causeOfFailure = new AtomicReference<Exception>(null);
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ NUM_MESSAGES = 10;
+
+ _queue = getTestQueue();
+
+ //Create Producer put some messages on the queue
+ _connection = getConnection();
+ }
+
+ /**
+ * Initialise the test variables
+ * @param transacted is this a transacted test
+ * @param mode if not trasacted then what ack mode to use
+ * @throws Exception if there is a setup issue.
+ */
+ protected void init(boolean transacted, int mode) throws Exception
+ {
+ _consumerSession = _connection.createSession(transacted, mode);
+ _consumer = _consumerSession.createConsumer(_queue);
+ _producer = _consumerSession.createProducer(_queue);
+
+ // These should all end up being prefetched by session
+ sendMessage(_consumerSession, _queue, 1);
+
+ assertEquals("Wrong number of messages on queue", 1,
+ ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue));
+ }
+
+ /**
+ * If a transacted session has failed over whilst it has uncommitted sent
+ * data then we need to throw a TransactedRolledbackException on commit()
+ *
+ * The alternative would be to maintain a replay buffer so that the message
+ * could be resent. This is not currently implemented
+ *
+ * @throws Exception if something goes wrong.
+ */
+ public void testDirtySendingSynchronousTransacted() throws Exception
+ {
+ Session producerSession = _connection.createSession(true, Session.SESSION_TRANSACTED);
+
+ // Ensure we get failover notifications
+ ((AMQConnection) _connection).setConnectionListener(this);
+
+ MessageProducer producer = producerSession.createProducer(_queue);
+
+ // Create and send message 0
+ Message msg = producerSession.createMessage();
+ msg.setIntProperty(INDEX, 0);
+ producer.send(msg);
+
+ // DON'T commit message .. fail connection
+
+ failBroker(getFailingPort());
+
+ // Ensure destination exists for sending
+ producerSession.createConsumer(_queue).close();
+
+ // Send the next message
+ msg.setIntProperty(INDEX, 1);
+ try
+ {
+ producer.send(msg);
+ fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException.");
+ }
+ catch (JMSException jmse)
+ {
+ assertEquals("Early warning of dirty session not correct",
+ "Failover has occurred and session is dirty so unable to send.", jmse.getMessage());
+ }
+
+ // Ignore that the session is dirty and attempt to commit to validate the
+ // exception is thrown. AND that the above failure notification did NOT
+ // clean up the session.
+
+ try
+ {
+ producerSession.commit();
+ fail("Session is dirty we should get an TransactionRolledBackException");
+ }
+ catch (TransactionRolledBackException trbe)
+ {
+ // Normal path.
+ }
+
+ // Resending of messages should now work ok as the commit was forcilbly rolledback
+ msg.setIntProperty(INDEX, 0);
+ producer.send(msg);
+ msg.setIntProperty(INDEX, 1);
+ producer.send(msg);
+
+ producerSession.commit();
+
+ assertEquals("Wrong number of messages on queue", 2,
+ ((AMQSession) producerSession).getQueueDepth((AMQDestination) _queue));
+ }
+
+ /**
+ * If a transacted session has failed over whilst it has uncommitted sent
+ * data then we need to throw a TransactedRolledbackException on commit()
+ *
+ * The alternative would be to maintain a replay buffer so that the message
+ * could be resent. This is not currently implemented
+ *
+ * @throws Exception if something goes wrong.
+ */
+ public void testDirtySendingOnMessageTransacted() throws Exception
+ {
+ NUM_MESSAGES = 1;
+ _receviedAll = new CountDownLatch(NUM_MESSAGES);
+ ((AMQConnection) _connection).setConnectionListener(this);
+
+ init(true, Session.SESSION_TRANSACTED);
+
+ _consumer.setMessageListener(new MessageListener()
+ {
+
+ public void onMessage(Message message)
+ {
+ try
+ {
+ // Create and send message 0
+ Message msg = _consumerSession.createMessage();
+ msg.setIntProperty(INDEX, 0);
+ _producer.send(msg);
+
+ // DON'T commit message .. fail connection
+
+ failBroker(getFailingPort());
+
+ // rep
+ repopulateBroker();
+
+ // Destination will exist as this failBroker will populate
+ // the queue with 1 message
+
+ // Send the next message
+ msg.setIntProperty(INDEX, 1);
+ try
+ {
+ _producer.send(msg);
+ fail("Should fail with Qpid as we provide early warning of the dirty session via a JMSException.");
+ }
+ catch (JMSException jmse)
+ {
+ assertEquals("Early warning of dirty session not correct",
+ "Failover has occurred and session is dirty so unable to send.", jmse.getMessage());
+ }
+
+ // Ignore that the session is dirty and attempt to commit to validate the
+ // exception is thrown. AND that the above failure notification did NOT
+ // clean up the session.
+
+ try
+ {
+ _consumerSession.commit();
+ fail("Session is dirty we should get an TransactionRolledBackException");
+ }
+ catch (TransactionRolledBackException trbe)
+ {
+ // Normal path.
+ }
+
+ // Resend messages
+ msg.setIntProperty(INDEX, 0);
+ msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT);
+ _producer.send(msg);
+ msg.setIntProperty(INDEX, 1);
+ msg.setStringProperty(MSG, SEND_FROM_ON_MESSAGE_TEXT);
+ _producer.send(msg);
+
+ _consumerSession.commit();
+
+ // Stop this consumer .. can't do _consumer.stop == DEADLOCK
+ // this doesn't seem to stop dispatcher running
+ _connection.stop();
+
+ // Signal that the onMessage send part of test is complete
+ // main thread can validate that messages are correct
+ _receviedAll.countDown();
+
+ }
+ catch (Exception e)
+ {
+ fail(e);
+ }
+
+ }
+
+ });
+
+ _connection.start();
+
+ if (!_receviedAll.await(10000L, TimeUnit.MILLISECONDS))
+ {
+ // Check to see if we ended due to an exception in the onMessage handler
+ Exception cause = _causeOfFailure.get();
+ if (cause != null)
+ {
+ cause.printStackTrace();
+ fail(cause.getMessage());
+ }
+ else
+ {
+ fail("All messages not received:" + _receviedAll.getCount() + "/" + NUM_MESSAGES);
+ }
+ }
+
+ // Check to see if we ended due to an exception in the onMessage handler
+ Exception cause = _causeOfFailure.get();
+ if (cause != null)
+ {
+ cause.printStackTrace();
+ fail(cause.getMessage());
+ }
+
+ _consumer.close();
+ _consumerSession.close();
+
+ _consumerSession = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _connection.start();
+
+ // Validate that we could send the messages as expected.
+ assertEquals("Wrong number of messages on queue", 3,
+ ((AMQSession) _consumerSession).getQueueDepth((AMQDestination) _queue));
+
+ MessageConsumer consumer = _consumerSession.createConsumer(_queue);
+
+ //Validate the message sent to setup the failed over broker.
+ Message message = consumer.receive(1000);
+ assertNotNull("Message " + 0 + " not received.", message);
+ assertEquals("Incorrect message received", 0, message.getIntProperty(INDEX));
+
+ // Validate the two messages sent from within the onMessage
+ for (int index = 0; index <= 1; index++)
+ {
+ message = consumer.receive(1000);
+ assertNotNull("Message " + index + " not received.", message);
+ assertEquals("Incorrect message received", index, message.getIntProperty(INDEX));
+ assertEquals("Incorrect message text for message:" + index, SEND_FROM_ON_MESSAGE_TEXT, message.getStringProperty(MSG));
+ }
+
+ assertNull("Extra message received.", consumer.receiveNoWait());
+
+ _consumerSession.close();
+
+ assertEquals("Wrong number of messages on queue", 0,
+ ((AMQSession) getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE)).getQueueDepth((AMQDestination) _queue));
+ }
+
+ private void repopulateBroker() throws Exception
+ {
+ // Repopulate this new broker so we can test what happends after failover
+
+ //Get the connection to the first (main port) broker.
+ Connection connection = getConnection();
+ // Use a transaction to send messages so we can be sure they arrive.
+ Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+ // ensure destination is created.
+ session.createConsumer(_queue).close();
+
+ sendMessage(session, _queue, NUM_MESSAGES);
+
+ assertEquals("Wrong number of messages on queue", NUM_MESSAGES,
+ ((AMQSession) session).getQueueDepth((AMQDestination) _queue));
+
+ connection.close();
+ }
+
+ // AMQConnectionListener Interface.. used so we can validate that we
+ // actually failed over.
+
+ public void bytesSent(long count)
+ {
+ }
+
+ public void bytesReceived(long count)
+ {
+ }
+
+ public boolean preFailover(boolean redirect)
+ {
+ //Allow failover
+ return true;
+ }
+
+ public boolean preResubscribe()
+ {
+ //Allow failover
+ return true;
+ }
+
+ public void failoverComplete()
+ {
+ _failoverCompleted.countDown();
+ }
+
+ /**
+ * Override so we can block until failover has completd
+ *
+ * @param port int the port of the broker to fail.
+ */
+ @Override
+ public void failBroker(int port)
+ {
+ super.failBroker(port);
+
+ try
+ {
+ if (!_failoverCompleted.await(DEFAULT_FAILOVER_TIME, TimeUnit.MILLISECONDS))
+ {
+ fail("Failover did not occur in specified time:" + DEFAULT_FAILOVER_TIME);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ fail("Failover was interuppted");
+ }
+ }
+
+ /**
+ * Pass the given exception back to the waiting thread to fail the test run.
+ *
+ * @param e The exception that is causing the test to fail.
+ */
+ protected void fail(Exception e)
+ {
+ _causeOfFailure.set(e);
+ // End the test.
+ while (_receviedAll.getCount() != 0)
+ {
+ _receviedAll.countDown();
+ }
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
index 9ea116ae53..d799b141c0 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
@@ -262,7 +262,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
producer.send(session1.createTextMessage("B"));
_logger.info("Receive message on consumer 1 :expecting B");
- msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT);
+ msg = consumer1.receive(500);
assertNotNull("Consumer 1 should get message 'B'.", msg);
assertEquals("Incorrect Message received on consumer1.", "B", ((TextMessage) msg).getText());
_logger.info("Receive message on consumer 1 :expecting null");
@@ -287,13 +287,13 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
else
{
_logger.info("Receive message on consumer 3 :expecting B");
- msg = consumer3.receive(POSITIVE_RECEIVE_TIMEOUT);
+ msg = consumer3.receive(500);
assertNotNull("Consumer 3 should get message 'B'.", msg);
assertEquals("Incorrect Message received on consumer3.", "B", ((TextMessage) msg).getText());
}
_logger.info("Receive message on consumer 1 :expecting C");
- msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT);
+ msg = consumer1.receive(500);
assertNotNull("Consumer 1 should get message 'C'.", msg);
assertEquals("Incorrect Message received on consumer1.", "C", ((TextMessage) msg).getText());
_logger.info("Receive message on consumer 1 :expecting null");
@@ -301,7 +301,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
assertNull("There should be no more messages for consumption on consumer1.", msg);
_logger.info("Receive message on consumer 3 :expecting C");
- msg = consumer3.receive(POSITIVE_RECEIVE_TIMEOUT);
+ msg = consumer3.receive(500);
assertNotNull("Consumer 3 should get message 'C'.", msg);
assertEquals("Incorrect Message received on consumer3.", "C", ((TextMessage) msg).getText());
_logger.info("Receive message on consumer 3 :expecting null");
@@ -358,7 +358,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
// Send message and check that both consumers get it and only it.
producer.send(session0.createTextMessage("A"));
- msg = consumer1.receive(POSITIVE_RECEIVE_TIMEOUT);
+ msg = consumer1.receive(500);
assertNotNull("Message should be available", msg);
assertEquals("Message Text doesn't match", "A", ((TextMessage) msg).getText());
msg = consumer1.receive(500);
@@ -729,7 +729,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
conn.start();
- Message rMsg = subB.receive(POSITIVE_RECEIVE_TIMEOUT);
+ Message rMsg = subB.receive(1000);
assertNotNull(rMsg);
assertEquals("Content was wrong",
"testResubscribeWithChangedSelectorAndRestart2",
@@ -797,7 +797,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase
conn.start();
- Message rMsg = subTwo.receive(POSITIVE_RECEIVE_TIMEOUT);
+ Message rMsg = subTwo.receive(1000);
assertNotNull(rMsg);
assertEquals("Content was wrong",
"testResubscribeWithChangedSelectorAndRestart1",
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java
deleted file mode 100644
index c89b13a0f9..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TemporaryTopicTest.java
+++ /dev/null
@@ -1,182 +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.
- *
- */
-package org.apache.qpid.test.unit.topic;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TemporaryTopic;
-import javax.jms.TextMessage;
-
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-
-/**
- * Tests the behaviour of {@link TemporaryTopic}.
- */
-public class TemporaryTopicTest extends QpidBrokerTestCase
-{
- /**
- * Tests the basic publish/subscribe behaviour of a temporary topic. Single
- * message is sent to two subscribers.
- */
- public void testMessageDeliveryUsingTemporaryTopic() throws Exception
- {
- final Connection conn = getConnection();
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryTopic topic = session.createTemporaryTopic();
- assertNotNull(topic);
- final MessageProducer producer = session.createProducer(topic);
- final MessageConsumer consumer1 = session.createConsumer(topic);
- final MessageConsumer consumer2 = session.createConsumer(topic);
- conn.start();
- producer.send(session.createTextMessage("hello"));
-
- final TextMessage tm1 = (TextMessage) consumer1.receive(2000);
- final TextMessage tm2 = (TextMessage) consumer2.receive(2000);
-
- assertNotNull("Message not received by subscriber1", tm1);
- assertEquals("hello", tm1.getText());
- assertNotNull("Message not received by subscriber2", tm2);
- assertEquals("hello", tm2.getText());
- }
-
- /**
- * Tests that the client is able to explicitly delete a temporary topic using
- * {@link TemporaryTopic#delete()} and is prevented from deleting one that
- * still has consumers.
- *
- * Note: Under < 0-10 {@link TemporaryTopic#delete()} only marks the queue as deleted
- * on the client. 0-10 causes the topic to be deleted from the Broker.
- */
- public void testExplictTemporaryTopicDeletion() throws Exception
- {
- final Connection conn = getConnection();
-
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryTopic topic = session.createTemporaryTopic();
- assertNotNull(topic);
- final MessageConsumer consumer = session.createConsumer(topic);
- conn.start();
- try
- {
- topic.delete();
- fail("Expected JMSException : should not be able to delete while there are active consumers");
- }
- catch (JMSException je)
- {
- //pass
- assertEquals("Temporary Topic has consumers so cannot be deleted", je.getMessage());
- }
-
- consumer.close();
-
- // Now deletion should succeed.
- topic.delete();
-
- try
- {
- session.createConsumer(topic);
- fail("Exception not thrown");
- }
- catch (JMSException je)
- {
- //pass
- assertEquals("Cannot consume from a deleted destination", je.getMessage());
- }
- }
-
- /**
- * Tests that a temporary topic cannot be used by another {@link Session}.
- */
- public void testUseFromAnotherSessionProhibited() throws Exception
- {
- final Connection conn = getConnection();
- final Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryTopic topic = session1.createTemporaryTopic();
-
- try
- {
- session2.createConsumer(topic);
- fail("Expected a JMSException when subscribing to a temporary topic created on a different session");
- }
- catch (JMSException je)
- {
- // pass
- assertEquals("Cannot consume from a temporary destination created on another session", je.getMessage());
- }
- }
-
- /**
- * Tests that the client is prohibited from creating a durable subscriber for a temporary
- * queue.
- */
- public void testDurableSubscriptionProhibited() throws Exception
- {
- final Connection conn = getConnection();
-
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryTopic topic = session.createTemporaryTopic();
- assertNotNull(topic);
- try
- {
- session.createDurableSubscriber(topic, null);
- fail("Expected JMSException : should not be able to create durable subscription from temp topic");
- }
- catch (JMSException je)
- {
- //pass
- assertEquals("Cannot create a durable subscription with a temporary topic: " + topic.toString(), je.getMessage());
- }
- }
-
- /**
- * Tests that a temporary topic remains available for reuse even after its initial
- * subscribers have disconnected.
- */
- public void testTemporaryTopicReused() throws Exception
- {
- final Connection conn = getConnection();
- final Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final TemporaryTopic topic = session.createTemporaryTopic();
- assertNotNull(topic);
-
- final MessageProducer producer = session.createProducer(topic);
- final MessageConsumer consumer1 = session.createConsumer(topic);
- conn.start();
- producer.send(session.createTextMessage("message1"));
- TextMessage tm = (TextMessage) consumer1.receive(2000);
- assertNotNull("Message not received by first consumer", tm);
- assertEquals("message1", tm.getText());
- consumer1.close();
-
- final MessageConsumer consumer2 = session.createConsumer(topic);
- conn.start();
- producer.send(session.createTextMessage("message2"));
- tm = (TextMessage) consumer2.receive(2000);
- assertNotNull("Message not received by second consumer", tm);
- assertEquals("message2", tm.getText());
- consumer2.close();
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
index 826545a23d..eee232e113 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
@@ -20,28 +20,38 @@
*/
package org.apache.qpid.test.unit.topic;
-import javax.jms.Connection;
import javax.jms.InvalidDestinationException;
-import javax.jms.Message;
+import javax.jms.JMSException;
import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
import javax.jms.Session;
+import javax.jms.TemporaryTopic;
import javax.jms.TextMessage;
-import javax.jms.Topic;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.AMQTopicSessionAdaptor;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
/** @author Apache Software Foundation */
public class TopicSessionTest extends QpidBrokerTestCase
{
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+
public void testTopicSubscriptionUnsubscription() throws Exception
{
@@ -218,6 +228,83 @@ public class TopicSessionTest extends QpidBrokerTestCase
con.close();
}
+ public void testSendingSameMessage() throws Exception
+ {
+ AMQConnection conn = (AMQConnection) getConnection("guest", "guest");
+ TopicSession session = conn.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
+ TemporaryTopic topic = session.createTemporaryTopic();
+ assertNotNull(topic);
+ TopicPublisher producer = session.createPublisher(topic);
+ MessageConsumer consumer = session.createConsumer(topic);
+ conn.start();
+ TextMessage sentMessage = session.createTextMessage("Test Message");
+ producer.send(sentMessage);
+ session.commit();
+ TextMessage receivedMessage = (TextMessage) consumer.receive(2000);
+ assertNotNull(receivedMessage);
+ assertEquals(sentMessage.getText(), receivedMessage.getText());
+ producer.send(sentMessage);
+ session.commit();
+ receivedMessage = (TextMessage) consumer.receive(2000);
+ assertNotNull(receivedMessage);
+ assertEquals(sentMessage.getText(), receivedMessage.getText());
+ session.commit();
+ conn.close();
+
+ }
+
+ public void testTemporaryTopic() throws Exception
+ {
+ AMQConnection conn = (AMQConnection) getConnection("guest", "guest");
+ TopicSession session = conn.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
+ TemporaryTopic topic = session.createTemporaryTopic();
+ assertNotNull(topic);
+ TopicPublisher producer = session.createPublisher(topic);
+ MessageConsumer consumer = session.createConsumer(topic);
+ conn.start();
+ producer.send(session.createTextMessage("hello"));
+ session.commit();
+ TextMessage tm = (TextMessage) consumer.receive(2000);
+ assertNotNull(tm);
+ assertEquals("hello", tm.getText());
+ session.commit();
+ try
+ {
+ topic.delete();
+ fail("Expected JMSException : should not be able to delete while there are active consumers");
+ }
+ catch (JMSException je)
+ {
+ ; //pass
+ }
+
+ consumer.close();
+
+ try
+ {
+ topic.delete();
+ }
+ catch (JMSException je)
+ {
+ fail("Unexpected Exception: " + je.getMessage());
+ }
+
+ TopicSession session2 = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+ try
+ {
+ session2.createConsumer(topic);
+ fail("Expected a JMSException when subscribing to a temporary topic created on adifferent session");
+ }
+ catch (JMSException je)
+ {
+ ; // pass
+ }
+
+
+ conn.close();
+ }
+
+
public void testNoLocal() throws Exception
{
@@ -311,39 +398,56 @@ public class TopicSessionTest extends QpidBrokerTestCase
}
/**
- * This tests was added to demonstrate QPID-3542. The Java Client when used with the CPP Broker was failing to
- * ack messages received that did not match the selector. This meant the messages remained indefinitely on the Broker.
+ * This tests QPID-1191, where messages which are sent to a topic but are not consumed by a subscriber
+ * due to a selector can be leaked.
+ * @throws Exception
*/
- public void testNonMatchingMessagesHandledCorrectly() throws Exception
+ public void testNonMatchingMessagesDoNotFillQueue() throws Exception
{
- final String topicName = getName();
- final String clientId = "clientId" + topicName;
- final Connection con1 = getConnection();
- final Session session1 = con1.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final Topic topic1 = session1.createTopic(topicName);
- final AMQQueue internalNameOnBroker = new AMQQueue("amq.topic", "clientid" + ":" + clientId);
+ AMQConnection con = (AMQConnection) getConnection("guest", "guest");
+
+ // Setup Topic
+ AMQTopic topic = new AMQTopic(con, "testNoLocal");
+
+ TopicSession session = con.createTopicSession(true, AMQSession.NO_ACKNOWLEDGE);
// Setup subscriber with selector
- final TopicSubscriber subscriberWithSelector = session1.createDurableSubscriber(topic1, clientId, "Selector = 'select'", false);
- final MessageProducer publisher = session1.createProducer(topic1);
+ TopicSubscriber selector = session.createSubscriber(topic, "Selector = 'select'", false);
+ TopicPublisher publisher = session.createPublisher(topic);
- con1.start();
+ con.start();
+ TextMessage m;
+ TextMessage message;
// Send non-matching message
- final Message sentMessage = session1.createTextMessage("hello");
- sentMessage.setStringProperty("Selector", "nonMatch");
- publisher.send(sentMessage);
+ message = session.createTextMessage("non-matching 1");
+ publisher.publish(message);
+ session.commit();
- // Try to consume non-message, expect this to fail.
- final Message message1 = subscriberWithSelector.receive(1000);
- assertNull("should not have received message", message1);
- subscriberWithSelector.close();
+ // Send and consume matching message
+ message = session.createTextMessage("hello");
+ message.setStringProperty("Selector", "select");
- session1.close();
+ publisher.publish(message);
+ session.commit();
+
+ m = (TextMessage) selector.receive(1000);
+ assertNotNull("should have received message", m);
+ assertEquals("Message contents were wrong", "hello", m.getText());
- // Now verify queue depth on broker.
- final Session session2 = con1.createSession(false, Session.AUTO_ACKNOWLEDGE);
- final long depth = ((AMQSession) session2).getQueueDepth(internalNameOnBroker);
- assertEquals("Expected queue depth of zero", 0, depth);
+ // Send non-matching message
+ message = session.createTextMessage("non-matching 2");
+ publisher.publish(message);
+ session.commit();
+
+ // Assert queue count is 0
+ long depth = ((AMQTopicSessionAdaptor) session).getSession().getQueueDepth(topic);
+ assertEquals("Queue depth was wrong", 0, depth);
+
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(TopicSessionTest.class);
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java
deleted file mode 100644
index fd8beffbe6..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java
+++ /dev/null
@@ -1,74 +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.
- *
- */
-package org.apache.qpid.test.unit.transacted;
-
-/**
- * This verifies that the default behaviour is not to time out transactions.
- */
-public class TransactionTimeoutDisabledTest extends TransactionTimeoutTestCase
-{
- @Override
- protected void configure() throws Exception
- {
- // Setup housekeeping every second
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100");
-
- // No transaction timeout configuration.
- }
-
- public void testProducerIdleCommit() throws Exception
- {
- try
- {
- send(5, 0);
-
- sleep(2.0f);
-
- _psession.commit();
- }
- catch (Exception e)
- {
- fail("Should have succeeded");
- }
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testProducerOpenCommit() throws Exception
- {
- try
- {
- send(5, 0.3f);
-
- _psession.commit();
- }
- catch (Exception e)
- {
- fail("Should have succeeded");
- }
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java
deleted file mode 100644
index f554b0089e..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java
+++ /dev/null
@@ -1,308 +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.
- *
- */
-package org.apache.qpid.test.unit.transacted;
-
-/**
- * This tests the behaviour of transactional sessions when the {@code transactionTimeout} configuration
- * is set for a virtual host.
- *
- * A producer that is idle for too long or open for too long will have its connection closed and
- * any further operations will fail with a 408 resource timeout exception. Consumers will not
- * be affected by the transaction timeout configuration.
- */
-public class TransactionTimeoutTest extends TransactionTimeoutTestCase
-{
-
- protected void configure() throws Exception
- {
- // Setup housekeeping every second
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100");
-
- if (getName().contains("ProducerIdle"))
- {
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500");
- }
- else if (getName().contains("ProducerOpen"))
- {
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0");
- }
- else
- {
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500");
- setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000");
- }
- }
-
- public void testProducerIdle() throws Exception
- {
- sleep(2.0f);
-
- _psession.commit();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testProducerIdleCommit() throws Exception
- {
- send(5, 0);
- // Idle for more than idleClose to generate idle-warns and cause a close.
- sleep(2.0f);
-
- try
- {
- _psession.commit();
- fail("Exception not thrown");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(10, 0);
-
- check(IDLE);
- }
-
- public void testProducerIdleCommitTwice() throws Exception
- {
- send(5, 0);
- // Idle for less than idleClose to generate idle-warns
- sleep(1.0f);
-
- _psession.commit();
-
- send(5, 0);
- // Now idle for more than idleClose to generate more idle-warns and cause a close.
- sleep(2.0f);
-
- try
- {
- _psession.commit();
- fail("Exception not thrown");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(15, 0);
-
- check(IDLE);
- }
-
- public void testProducerIdleRollback() throws Exception
- {
- send(5, 0);
- // Now idle for more than idleClose to generate more idle-warns and cause a close.
- sleep(2.0f);
- try
- {
- _psession.rollback();
- fail("Exception not thrown");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(10, 0);
-
- check(IDLE);
- }
-
- public void testProducerIdleRollbackTwice() throws Exception
- {
- send(5, 0);
- // Idle for less than idleClose to generate idle-warns
- sleep(1.0f);
- _psession.rollback();
- send(5, 0);
- // Now idle for more than idleClose to generate more idle-warns and cause a close.
- sleep(2.0f);
- try
- {
- _psession.rollback();
- fail("should fail");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(15, 0);
-
- check(IDLE);
- }
-
- public void testProducerOpenCommit() throws Exception
- {
- try
- {
- // Sleep between sends to cause open warns and then cause a close.
- send(6, 0.5f);
- _psession.commit();
- fail("Exception not thrown");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(0, 10);
-
- check(OPEN);
- }
-
- public void testProducerOpenCommitTwice() throws Exception
- {
- send(5, 0);
- sleep(1.0f);
- _psession.commit();
-
- try
- {
- // Now sleep between sends to cause open warns and then cause a close.
- send(6, 0.5f);
- _psession.commit();
- fail("Exception not thrown");
- }
- catch (Exception e)
- {
- _exception = e;
- }
-
- monitor(0, 10);
-
- check(OPEN);
- }
-
- public void testConsumerCommitClose() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- expect(1, 0);
-
- _csession.commit();
-
- sleep(3.0f);
-
- _csession.close();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testConsumerIdleReceiveCommit() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- sleep(2.0f);
-
- expect(1, 0);
-
- sleep(2.0f);
-
- _csession.commit();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testConsumerIdleCommit() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- expect(1, 0);
-
- sleep(2.0f);
-
- _csession.commit();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testConsumerIdleRollback() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- expect(1, 0);
-
- sleep(2.0f);
-
- _csession.rollback();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testConsumerOpenCommit() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- sleep(3.0f);
-
- _csession.commit();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-
- public void testConsumerOpenRollback() throws Exception
- {
- send(1, 0);
-
- _psession.commit();
-
- sleep(3.0f);
-
- _csession.rollback();
-
- assertEquals("Listener should not have received exception", 0, getNumberOfDeliveredExceptions());
-
- monitor(0, 0);
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java
deleted file mode 100644
index 2b90d38049..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java
+++ /dev/null
@@ -1,246 +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.
- *
- */
-package org.apache.qpid.test.unit.transacted;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.jms.DeliveryMode;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.TextMessage;
-
-import junit.framework.TestCase;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.jms.Session;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.util.LogMonitor;
-
-/**
- * The {@link TestCase} for transaction timeout testing.
- */
-public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase implements ExceptionListener
-{
- public static final String VIRTUALHOST = "test";
- public static final String TEXT = "0123456789abcdefghiforgettherest";
- public static final String CHN_OPEN_TXN = "CHN-1007";
- public static final String CHN_IDLE_TXN = "CHN-1008";
- public static final String IDLE = "Idle";
- public static final String OPEN = "Open";
-
- protected LogMonitor _monitor;
- protected AMQConnection _con;
- protected Session _psession, _csession;
- protected Queue _queue;
- protected MessageConsumer _consumer;
- protected MessageProducer _producer;
- private CountDownLatch _exceptionLatch = new CountDownLatch(1);
- protected AtomicInteger _exceptionCount = new AtomicInteger(0);
- protected String _message;
- protected Exception _exception;
- protected AMQConstant _code;
-
- /**
- * Subclasses must implement this to configure transaction timeout parameters.
- */
- protected abstract void configure() throws Exception;
-
- protected void setUp() throws Exception
- {
- // Configure timeouts
- configure();
-
- // Monitor log file
- _monitor = new LogMonitor(_outputFile);
-
- // Start broker
- super.setUp();
-
- // Connect to broker
- String broker = ("tcp://localhost:" + DEFAULT_PORT);
- ConnectionURL url = new AMQConnectionURL("amqp://guest:guest@clientid/test?brokerlist='" + broker + "'&maxprefetch='1'");
- _con = (AMQConnection) getConnection(url);
- _con.setExceptionListener(this);
- _con.start();
-
- // Create queue
- Session qsession = _con.createSession(true, Session.SESSION_TRANSACTED);
- AMQShortString queueName = new AMQShortString("test");
- _queue = new AMQQueue(qsession.getDefaultQueueExchangeName(), queueName, queueName, false, true);
- qsession.close();
-
- // Create producer and consumer
- producer();
- consumer();
- }
-
- protected void tearDown() throws Exception
- {
- try
- {
- _con.close();
- }
- finally
- {
- super.tearDown();
- }
- }
-
- /**
- * Create a transacted persistent message producer session.
- */
- protected void producer() throws Exception
- {
- _psession = _con.createSession(true, Session.SESSION_TRANSACTED);
- _producer = _psession.createProducer(_queue);
- _producer.setDeliveryMode(DeliveryMode.PERSISTENT);
- }
-
- /**
- * Create a transacted message consumer session.
- */
- protected void consumer() throws Exception
- {
- _csession = _con.createSession(true, Session.SESSION_TRANSACTED);
- _consumer = _csession.createConsumer(_queue);
- }
-
- /**
- * Send a number of messages to the queue, optionally pausing after each.
- */
- protected void send(int count, float delay) throws Exception
- {
- for (int i = 0; i < count; i++)
- {
- sleep(delay);
- Message msg = _psession.createTextMessage(TEXT);
- msg.setIntProperty("i", i);
- _producer.send(msg);
- }
- }
-
- /**
- * Sleep for a number of seconds.
- */
- protected void sleep(float seconds) throws Exception
- {
- try
- {
- Thread.sleep((long) (seconds * 1000.0f));
- }
- catch (InterruptedException ie)
- {
- throw new RuntimeException("Interrupted");
- }
- }
-
- /**
- * Check for idle and open messages.
- *
- * Either exactly zero messages, or +-2 error accepted around the specified number.
- */
- protected void monitor(int idle, int open) throws Exception
- {
- List<String> idleMsgs = _monitor.findMatches(CHN_IDLE_TXN);
- List<String> openMsgs = _monitor.findMatches(CHN_OPEN_TXN);
-
- String idleErr = "Expected " + idle + " but found " + idleMsgs.size() + " txn idle messages";
- String openErr = "Expected " + open + " but found " + openMsgs.size() + " txn open messages";
-
- if (idle == 0)
- {
- assertTrue(idleErr, idleMsgs.isEmpty());
- }
- else
- {
- assertTrue(idleErr, idleMsgs.size() >= idle - 2 && idleMsgs.size() <= idle + 2);
- }
-
- if (open == 0)
- {
- assertTrue(openErr, openMsgs.isEmpty());
- }
- else
- {
- assertTrue(openErr, openMsgs.size() >= open - 2 && openMsgs.size() <= open + 2);
- }
- }
-
- /**
- * Receive a number of messages, optionally pausing after each.
- */
- protected void expect(int count, float delay) throws Exception
- {
- for (int i = 0; i < count; i++)
- {
- sleep(delay);
- Message msg = _consumer.receive(1000);
- assertNotNull("Message should not be null", msg);
- assertTrue("Message should be a text message", msg instanceof TextMessage);
- assertEquals("Message content does not match expected", TEXT, ((TextMessage) msg).getText());
- assertEquals("Message order is incorrect", i, msg.getIntProperty("i"));
- }
- }
-
- /**
- * Checks that the correct exception was thrown and was received
- * by the listener with a 506 error code.
- */
- protected void check(String reason)throws InterruptedException
- {
- assertTrue("Should have caught exception in listener", _exceptionLatch.await(1, TimeUnit.SECONDS));
- assertNotNull("Should have thrown exception to client", _exception);
- assertTrue("Exception message should contain '" + reason + "': " + _message, _message.contains(reason + " transaction timed out"));
- assertNotNull("Exception should have an error code", _code);
- assertEquals("Error code should be 506", AMQConstant.RESOURCE_ERROR, _code);
- }
-
- /** @see javax.jms.ExceptionListener#onException(javax.jms.JMSException) */
- public void onException(JMSException jmse)
- {
- _exceptionLatch.countDown();
- _exceptionCount.incrementAndGet();
-
- _message = jmse.getLinkedException().getMessage();
- if (jmse.getLinkedException() instanceof AMQException)
- {
- _code = ((AMQException) jmse.getLinkedException()).getErrorCode();
- }
- }
-
- protected int getNumberOfDeliveredExceptions()
- {
- return _exceptionCount.get();
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java
deleted file mode 100644
index 8345803d56..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerHolder.java
+++ /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.
- *
- */
-package org.apache.qpid.test.utils;
-
-public interface BrokerHolder
-{
- void shutdown();
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
index 10217585c1..d3b429e315 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
@@ -34,10 +34,24 @@ public class FailoverBaseCase extends QpidBrokerTestCase
{
protected static final Logger _logger = LoggerFactory.getLogger(FailoverBaseCase.class);
+ public static int FAILING_VM_PORT = 2;
+ public static int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt"));
public static final long DEFAULT_FAILOVER_TIME = 10000L;
protected int failingPort;
+ protected int getFailingPort()
+ {
+ if (_broker.equals(VM))
+ {
+ return FAILING_VM_PORT;
+ }
+ else
+ {
+ return FAILING_PORT;
+ }
+ }
+
protected void setUp() throws java.lang.Exception
{
super.setUp();
@@ -68,14 +82,6 @@ public class FailoverBaseCase extends QpidBrokerTestCase
return _connectionFactory;
}
- @Override
- public void stopBroker(int port) throws Exception
- {
- if (isBrokerPresent(port))
- {
- super.stopBroker(port);
- }
- }
public void tearDown() throws Exception
{
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
deleted file mode 100644
index 340f00fed8..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
+++ /dev/null
@@ -1,50 +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.
- *
- */
-package org.apache.qpid.test.utils;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.Broker;
-
-public class InternalBrokerHolder implements BrokerHolder
-{
- private static final Logger LOGGER = Logger.getLogger(InternalBrokerHolder.class);
- private final Broker _broker;
-
- public InternalBrokerHolder(final Broker broker)
- {
- if(broker == null)
- {
- throw new IllegalArgumentException("Broker must not be null");
- }
-
- _broker = broker;
- }
-
- public void shutdown()
- {
- LOGGER.info("Shutting down Broker instance");
-
- _broker.shutdown();
-
- LOGGER.info("Broker instance shutdown");
- }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
index 1fde6c7c73..ff80c91fac 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java
@@ -21,8 +21,6 @@
package org.apache.qpid.test.utils;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Set;
import javax.management.JMException;
@@ -33,17 +31,14 @@ import javax.management.ObjectName;
import javax.management.MalformedObjectNameException;
import javax.management.remote.JMXConnector;
-import junit.framework.TestCase;
-
import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.commands.objects.AllObjects;
import org.apache.qpid.management.common.JMXConnnectionFactory;
import org.apache.qpid.management.common.mbeans.ManagedBroker;
-import org.apache.qpid.management.common.mbeans.ManagedConnection;
import org.apache.qpid.management.common.mbeans.ManagedExchange;
import org.apache.qpid.management.common.mbeans.LoggingManagement;
import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
import org.apache.qpid.management.common.mbeans.ManagedQueue;
-import org.apache.qpid.management.common.mbeans.ServerInformation;
import org.apache.qpid.management.common.mbeans.UserManagement;
/**
@@ -236,10 +231,10 @@ public class JMXTestUtils
public ObjectName getVirtualHostManagerObjectName(String vhostName)
{
// Get the name of the test manager
- String query = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost="
- + ObjectName.quote(vhostName) + ",*";
+ AllObjects allObject = new AllObjects(_mbsc);
+ allObject.querystring = "org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=" + vhostName + ",*";
- Set<ObjectName> objectNames = queryObjects(query);
+ Set<ObjectName> objectNames = allObject.returnObjects();
_test.assertNotNull("Null ObjectName Set returned", objectNames);
_test.assertEquals("Incorrect number test vhosts returned", 1, objectNames.size());
@@ -263,14 +258,14 @@ public class JMXTestUtils
public ObjectName getQueueObjectName(String virtualHostName, String queue)
{
// Get the name of the test manager
- String query = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost="
- + ObjectName.quote(virtualHostName) + ",name="
- + ObjectName.quote(queue) + ",*";
+ AllObjects allObject = new AllObjects(_mbsc);
+ allObject.querystring = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + virtualHostName + ",name=" + queue + ",*";
- Set<ObjectName> objectNames = queryObjects(query);
+ Set<ObjectName> objectNames = allObject.returnObjects();
_test.assertNotNull("Null ObjectName Set returned", objectNames);
- _test.assertEquals("Incorrect number of queues with name '" + queue + "' returned", 1, objectNames.size());
+ _test.assertEquals("Incorrect number of queues with name '" + allObject.querystring +
+ "' returned", 1, objectNames.size());
// We have verified we have only one value in objectNames so return it
ObjectName objectName = objectNames.iterator().next();
@@ -291,11 +286,10 @@ public class JMXTestUtils
public ObjectName getExchangeObjectName(String virtualHostName, String exchange)
{
// Get the name of the test manager
- String query = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost="
- + ObjectName.quote(virtualHostName) + ",name="
- + ObjectName.quote(exchange) + ",*";
+ AllObjects allObject = new AllObjects(_mbsc);
+ allObject.querystring = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + virtualHostName + ",name=" + exchange + ",*";
- Set<ObjectName> objectNames = queryObjects(query);
+ Set<ObjectName> objectNames = allObject.returnObjects();
_test.assertNotNull("Null ObjectName Set returned", objectNames);
_test.assertEquals("Incorrect number of exchange with name '" + exchange + "' returned", 1, objectNames.size());
@@ -307,9 +301,12 @@ public class JMXTestUtils
}
@SuppressWarnings("static-access")
- public <T> T getManagedObject(Class<T> managedClass, String query)
+ public <T> T getManagedObject(Class<T> managedClass, String queryString)
{
- Set<ObjectName> objectNames = queryObjects(query);
+ AllObjects allObject = new AllObjects(_mbsc);
+ allObject.querystring = queryString;
+
+ Set<ObjectName> objectNames = allObject.returnObjects();
_test.assertNotNull("Null ObjectName Set returned", objectNames);
_test.assertEquals("More than one " + managedClass + " returned", 1, objectNames.size());
@@ -324,16 +321,6 @@ public class JMXTestUtils
return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, managedClass, false);
}
- public <T> List<T> getManagedObjectList(Class<T> managedClass, Set<ObjectName> objectNames)
- {
- List<T> objects = new ArrayList<T>();
- for (ObjectName name : objectNames)
- {
- objects.add(getManagedObject(managedClass, name));
- }
- return objects;
- }
-
public ManagedBroker getManagedBroker(String virtualHost)
{
return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost));
@@ -368,68 +355,4 @@ public class JMXTestUtils
ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement");
return getManagedObject(UserManagement.class, objectName);
}
-
- /**
- * Retrive {@link ServerInformation} JMX MBean.
- */
- public ServerInformation getServerInformation()
- {
- // Get the name of the test manager
- String query = "org.apache.qpid:type=ServerInformation,name=ServerInformation,*";
-
- Set<ObjectName> objectNames = queryObjects(query);
-
- TestCase.assertNotNull("Null ObjectName Set returned", objectNames);
- TestCase.assertEquals("Incorrect number of objects returned", 1, objectNames.size());
-
- // We have verified we have only one value in objectNames so return it
- return getManagedObject(ServerInformation.class, objectNames.iterator().next());
- }
-
- /**
- * Retrive all {@link ManagedConnection} objects.
- */
- public List<ManagedConnection> getAllManagedConnections()
- {
- // Get the name of the test manager
- String query = "org.apache.qpid:type=VirtualHost.Connection,VirtualHost=*,name=*";
-
- Set<ObjectName> objectNames = queryObjects(query);
-
- TestCase.assertNotNull("Null ObjectName Set returned", objectNames);
-
- return getManagedObjectList(ManagedConnection.class, objectNames);
- }
-
- /**
- * Retrive all {@link ManagedConnection} objects for a particular virtual host.
- */
- public List<ManagedConnection> getManagedConnections(String vhost)
- {
- // Get the name of the test manager
- String query = "org.apache.qpid:type=VirtualHost.Connection,VirtualHost=" + ObjectName.quote(vhost) + ",name=*";
-
- Set<ObjectName> objectNames = queryObjects(query);
-
- TestCase.assertNotNull("Null ObjectName Set returned", objectNames);
-
- return getManagedObjectList(ManagedConnection.class, objectNames);
- }
-
- /**
- * Returns the Set of ObjectNames returned by the broker for the given query,
- * or null if there is problem while performing the query.
- */
- private Set<ObjectName> queryObjects(String query)
- {
- try
- {
- return _mbsc.queryNames(new ObjectName(query), null);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- return null;
- }
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
index bb44aea659..ae38a75e7a 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java
@@ -25,7 +25,6 @@ import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.net.MalformedURLException;
-import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -52,22 +51,22 @@ import javax.naming.NamingException;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.server.Broker;
-import org.apache.qpid.server.BrokerOptions;
-import org.apache.qpid.server.ProtocolExclusion;
import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.protocol.AmqpProtocolVersion;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
import org.apache.qpid.server.store.DerbyMessageStore;
import org.apache.qpid.url.URLSyntaxException;
-import org.apache.qpid.util.FileUtils;
import org.apache.qpid.util.LogMonitor;
/**
@@ -75,14 +74,7 @@ import org.apache.qpid.util.LogMonitor;
*/
public class QpidBrokerTestCase extends QpidTestCase
{
-
- public enum BrokerType
- {
- EXTERNAL /** Test case relies on a Broker started independently of the test-suite */,
- INTERNAL /** Test case starts an embedded broker within this JVM */,
- SPAWNED /** Test case spawns a new broker as a separate process */
- }
- protected final static String QpidHome = System.getProperty("QPID_HOME");
+ protected final String QpidHome = System.getProperty("QPID_HOME");
protected File _configFile = new File(System.getProperty("broker.config"));
protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class);
@@ -90,7 +82,9 @@ public class QpidBrokerTestCase extends QpidTestCase
protected long RECEIVE_TIMEOUT = 1000l;
+ private Map<String, String> _propertiesSetForTestOnly = new HashMap<String, String>();
private Map<String, String> _propertiesSetForBroker = new HashMap<String, String>();
+ private Map<Logger, Level> _loggerLevelSetForTest = new HashMap<Logger, Level>();
private XMLConfiguration _testConfiguration = new XMLConfiguration();
private XMLConfiguration _testVirtualhosts = new XMLConfiguration();
@@ -112,10 +106,9 @@ public class QpidBrokerTestCase extends QpidTestCase
// system properties
private static final String BROKER_LANGUAGE = "broker.language";
- private static final String BROKER_TYPE = "broker.type";
- private static final String BROKER_COMMAND = "broker.command";
+ private static final String BROKER = "broker";
+ private static final String BROKER_CLEAN = "broker.clean";
private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests";
- private static final String BROKER_EXISTING_QPID_WORK = "broker.existing.qpid.work";
private static final String BROKER_VERSION = "broker.version";
protected static final String BROKER_READY = "broker.ready";
private static final String BROKER_STOPPED = "broker.stopped";
@@ -123,29 +116,29 @@ public class QpidBrokerTestCase extends QpidTestCase
private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave";
private static final String BROKER_LOG_PREFIX = "broker.log.prefix";
private static final String BROKER_PERSITENT = "broker.persistent";
- private static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes";
-
// values
protected static final String JAVA = "java";
protected static final String CPP = "cpp";
+ protected static final String VM = "vm";
+ protected static final String EXTERNAL = "external";
+ private static final String VERSION_08 = "0-8";
+ private static final String VERSION_010 = "0-10";
protected static final String QPID_HOME = "QPID_HOME";
public static final int DEFAULT_VM_PORT = 1;
public static final int DEFAULT_PORT = Integer.getInteger("test.port", ServerConfiguration.DEFAULT_PORT);
- public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt"));
- public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER);
- public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", ServerConfiguration.DEFAULT_SSL_PORT);
+ public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT);
+ public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.sslport", ServerConfiguration.DEFAULT_SSL_PORT);
protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA);
- protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase());
- protected String _brokerCommand = System.getProperty(BROKER_COMMAND);
+ protected String _broker = System.getProperty(BROKER, VM);
+ private String _brokerClean = System.getProperty(BROKER_CLEAN, null);
private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS);
- private final AmqpProtocolVersion _brokerVersion = AmqpProtocolVersion.valueOf(System.getProperty(BROKER_VERSION, ""));
- protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir"));
+ private String _brokerVersion = System.getProperty(BROKER_VERSION, VERSION_08);
+ protected String _output = System.getProperty(TEST_OUTPUT);
protected Boolean _brokerPersistent = Boolean.getBoolean(BROKER_PERSITENT);
- private String _brokerProtocolExcludes = System.getProperty(BROKER_PROTOCOL_EXCLUDES);
protected static String _brokerLogPrefix = System.getProperty(BROKER_LOG_PREFIX,"BROKER: ");
protected static boolean _interleaveBrokerLog = Boolean.getBoolean(BROKER_LOG_INTERLEAVE);
@@ -154,11 +147,13 @@ public class QpidBrokerTestCase extends QpidTestCase
protected PrintStream _brokerOutputStream;
- protected Map<Integer, BrokerHolder> _brokers = new HashMap<Integer, BrokerHolder>();
+ protected Map<Integer, Process> _brokers = new HashMap<Integer, Process>();
protected InitialContext _initialContext;
protected AMQConnectionFactory _connectionFactory;
+ protected String _testName;
+
// the connections created for a given test
protected List<Connection> _connections = new ArrayList<Connection>();
public static final String QUEUE = "queue";
@@ -200,6 +195,7 @@ public class QpidBrokerTestCase extends QpidTestCase
public void runBare() throws Throwable
{
+ _testName = getClass().getSimpleName() + "." + getName();
String qname = getClass().getName() + "." + getName();
// Initialize this for each test run
@@ -214,13 +210,8 @@ public class QpidBrokerTestCase extends QpidTestCase
if (redirected)
{
_outputFile = new File(String.format("%s/TEST-%s.out", _output, qname));
- out = new PrintStream(new FileOutputStream(_outputFile), true);
+ out = new PrintStream(_outputFile);
err = new PrintStream(String.format("%s/TEST-%s.err", _output, qname));
-
- // This is relying on behaviour specific to log4j 1.2.12. If we were to upgrade to 1.2.13 or
- // beyond we must change either code (or config) to ensure that ConsoleAppender#setFollow
- // is set to true otherwise log4j logging will not respect the following reassignment.
-
System.setOut(out);
System.setErr(err);
@@ -235,6 +226,7 @@ public class QpidBrokerTestCase extends QpidTestCase
}
}
+ _logger.info("========== start " + _testName + " ==========");
try
{
super.runBare();
@@ -255,18 +247,19 @@ public class QpidBrokerTestCase extends QpidTestCase
_logger.error("exception stopping broker", e);
}
- // reset properties used in the test
- revertSystemProperties();
- revertLoggingLevels();
-
if(_brokerCleanBetweenTests)
{
- final String qpidWork = System.getProperty("QPID_WORK");
- cleanBrokerWork(qpidWork);
- createBrokerWork(qpidWork);
+ try
+ {
+ cleanBroker();
+ }
+ catch (Exception e)
+ {
+ _logger.error("exception cleaning up broker", e);
+ }
}
- _logger.info("========== stop " + getTestName() + " ==========");
+ _logger.info("========== stop " + _testName + " ==========");
if (redirected)
{
@@ -285,23 +278,11 @@ public class QpidBrokerTestCase extends QpidTestCase
@Override
protected void setUp() throws Exception
{
- super.setUp();
-
if (!_configFile.exists())
{
fail("Unable to test without config file:" + _configFile);
}
- String existingQpidWorkPath = System.getProperty(BROKER_EXISTING_QPID_WORK);
- if(existingQpidWorkPath != null && !existingQpidWorkPath.equals(""))
- {
-
- String qpidWork = getQpidWork(_brokerType, getPort());
- File existing = new File(existingQpidWorkPath);
- cleanBrokerWork(qpidWork);
- FileUtils.copyRecursive(existing, new File(qpidWork));
- }
-
startBroker();
}
@@ -402,8 +383,13 @@ public class QpidBrokerTestCase extends QpidTestCase
}
}
+ public void startBroker() throws Exception
+ {
+ startBroker(0);
+ }
+
/**
- * Return the management port in use by the broker on this main port
+ * Return the management portin use by the broker on this main port
*
* @param mainPort the broker's main port.
*
@@ -411,7 +397,7 @@ public class QpidBrokerTestCase extends QpidTestCase
*/
protected int getManagementPort(int mainPort)
{
- return mainPort + (DEFAULT_MANAGEMENT_PORT - DEFAULT_PORT);
+ return mainPort + (DEFAULT_MANAGEMENT_PORT - (_broker.equals(VM) ? DEFAULT_VM_PORT : DEFAULT_PORT));
}
/**
@@ -426,7 +412,11 @@ public class QpidBrokerTestCase extends QpidTestCase
protected int getPort(int port)
{
- if (!_brokerType.equals(BrokerType.EXTERNAL))
+ if (_broker.equals(VM))
+ {
+ return port == 0 ? DEFAULT_VM_PORT : port;
+ }
+ else if (!_broker.equals(EXTERNAL))
{
return port == 0 ? DEFAULT_PORT : port;
}
@@ -438,19 +428,11 @@ public class QpidBrokerTestCase extends QpidTestCase
protected String getBrokerCommand(int port) throws MalformedURLException
{
- final int sslPort = port-1;
- final String protocolExcludesList = getProtocolExcludesList(port, sslPort);
- return _brokerCommand
+ return _broker
.replace("@PORT", "" + port)
- .replace("@SSL_PORT", "" + sslPort)
+ .replace("@SSL_PORT", "" + (port - 1))
.replace("@MPORT", "" + getManagementPort(port))
- .replace("@CONFIG_FILE", _configFile.toString())
- .replace("@EXCLUDES", protocolExcludesList);
- }
-
- public void startBroker() throws Exception
- {
- startBroker(0);
+ .replace("@CONFIG_FILE", _configFile.toString());
}
public void startBroker(int port) throws Exception
@@ -461,52 +443,55 @@ public class QpidBrokerTestCase extends QpidTestCase
saveTestConfiguration();
saveTestVirtualhosts();
- if(_brokers.get(port) != null)
- {
- throw new IllegalStateException("There is already an existing broker running on port " + port);
- }
-
- if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker())
+ Process process = null;
+ if (_broker.equals(VM))
{
+ setConfigurationProperty("management.jmxport", String.valueOf(getManagementPort(port)));
setConfigurationProperty(ServerConfiguration.MGMT_CUSTOM_REGISTRY_SOCKET, String.valueOf(false));
saveTestConfiguration();
-
- BrokerOptions options = new BrokerOptions();
- options.setConfigFile(_configFile.getAbsolutePath());
- options.addPort(port);
-
- addExcludedPorts(port, DEFAULT_SSL_PORT, options);
-
- options.setJmxPortRegistryServer(getManagementPort(port));
-
- //Set the log config file, relying on the log4j.configuration system property
- //set on the JVM by the JUnit runner task in module.xml.
- options.setLogConfigFile(new URL(System.getProperty("log4j.configuration")).getFile());
-
- Broker broker = new Broker();
- _logger.info("starting internal broker (same JVM)");
- broker.startup(options);
-
- _brokers.put(port, new InternalBrokerHolder(broker));
+
+ // create an in_VM broker
+ final ConfigurationFileApplicationRegistry registry = new ConfigurationFileApplicationRegistry(_configFile);
+ try
+ {
+ ApplicationRegistry.initialise(registry, port);
+ }
+ catch (Exception e)
+ {
+ _logger.error("Broker initialise failed due to:",e);
+ try
+ {
+ registry.close();
+ }
+ catch (Throwable closeE)
+ {
+ closeE.printStackTrace();
+ }
+ throw e;
+ }
+ TransportConnection.createVMBroker(port);
}
- else if (!_brokerType.equals(BrokerType.EXTERNAL))
+ else if (!_broker.equals(EXTERNAL))
{
- // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests
- final String qpidWork = getQpidWork(_brokerType, port);
String cmd = getBrokerCommand(port);
- _logger.info("starting external broker: " + cmd);
+ _logger.info("starting broker: " + cmd);
ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+"));
pb.redirectErrorStream(true);
+
Map<String, String> env = pb.environment();
+
String qpidHome = System.getProperty(QPID_HOME);
env.put(QPID_HOME, qpidHome);
+
//Augment Path with bin directory in QPID_HOME.
env.put("PATH", env.get("PATH").concat(File.pathSeparator + qpidHome + "/bin"));
//Add the test name to the broker run.
// DON'T change PNAME, qpid.stop needs this value.
- env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + getTestName() + "\"");
- env.put("QPID_WORK", qpidWork);
+ env.put("QPID_PNAME", "-DPNAME=QPBRKR -DTNAME=\"" + _testName + "\"");
+ // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests
+ env.put("QPID_WORK", System.getProperty("QPID_WORK")+ "/" + port);
+
// Use the environment variable to set amqj.logging.level for the broker
// The value used is a 'server' value in the test configuration to
@@ -558,10 +543,7 @@ public class QpidBrokerTestCase extends QpidTestCase
}
}
- // cpp broker requires that the work directory is created
- createBrokerWork(qpidWork);
-
- Process process = pb.start();;
+ process = pb.start();
Piper p = new Piper(process.getInputStream(),
_brokerOutputStream,
@@ -575,106 +557,44 @@ public class QpidBrokerTestCase extends QpidTestCase
_logger.info("broker failed to become ready (" + p.ready + "):" + p.getStopLine());
//Ensure broker has stopped
process.destroy();
- cleanBrokerWork(qpidWork);
+ cleanBroker();
throw new RuntimeException("broker failed to become ready:"
+ p.getStopLine());
}
try
{
- //test that the broker is still running and hasn't exited unexpectedly
int exit = process.exitValue();
_logger.info("broker aborted: " + exit);
- cleanBrokerWork(qpidWork);
+ cleanBroker();
throw new RuntimeException("broker aborted: " + exit);
}
catch (IllegalThreadStateException e)
{
- // this is expect if the broker started successfully
- }
-
- _brokers.put(port, new SpawnedBrokerHolder(process));
- }
- }
-
- private void addExcludedPorts(int port, int sslPort, BrokerOptions options)
- {
- final String protocolExcludesList = getProtocolExcludesList(port, sslPort);
-
- if (protocolExcludesList.equals(""))
- {
- return;
- }
- final String[] toks = protocolExcludesList.split("\\s");
-
- if(toks.length % 2 != 0)
- {
- throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolExcludesList + "'");
- }
- for (int i = 0; i < toks.length; i=i+2)
- {
- String excludeArg = toks[i];
- final int excludedPort = Integer.parseInt(toks[i+1]);
- options.addExcludedPort(ProtocolExclusion.lookup(excludeArg), excludedPort);
-
- _logger.info("Adding protocol exclusion " + excludeArg + " " + excludedPort);
- }
- }
-
- protected String getProtocolExcludesList(int port, int sslPort)
- {
- final String protocolExcludesList =
- _brokerProtocolExcludes.replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort);
- return protocolExcludesList;
- }
-
- private boolean existingInternalBroker()
- {
- for(BrokerHolder holder : _brokers.values())
- {
- if(holder instanceof InternalBrokerHolder)
- {
- return true;
+ // this is expect if the broker started succesfully
}
}
- return false;
- }
-
- private String getQpidWork(BrokerType broker, int port)
- {
- if (!broker.equals(BrokerType.EXTERNAL))
- {
- return System.getProperty("QPID_WORK")+ "/" + port;
- }
-
- return System.getProperty("QPID_WORK");
+ _brokers.put(port, process);
}
public String getTestConfigFile()
{
- return _output + "/" + getTestQueueName() + "-config.xml";
+ String path = _output == null ? System.getProperty("java.io.tmpdir") : _output;
+ return path + "/" + getTestQueueName() + "-config.xml";
}
public String getTestVirtualhostsFile()
{
- return _output + "/" + getTestQueueName() + "-virtualhosts.xml";
- }
-
- private String relativeToQpidHome(String file)
- {
- return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + "/","");
+ String path = _output == null ? System.getProperty("java.io.tmpdir") : _output;
+ return path + "/" + getTestQueueName() + "-virtualhosts.xml";
}
protected void saveTestConfiguration() throws ConfigurationException
{
- // Specify the test config file
+ // Specifiy the test config file
String testConfig = getTestConfigFile();
- String relative = relativeToQpidHome(testConfig);
-
- setSystemProperty("test.config", relative);
- _logger.info("Set test.config property to: " + relative);
- _logger.info("Saving test virtualhosts file at: " + testConfig);
+ setSystemProperty("test.config", testConfig);
// Create the file if configuration does not exist
if (_testConfiguration.isEmpty())
@@ -686,13 +606,9 @@ public class QpidBrokerTestCase extends QpidTestCase
protected void saveTestVirtualhosts() throws ConfigurationException
{
- // Specify the test virtualhosts file
+ // Specifiy the test virtualhosts file
String testVirtualhosts = getTestVirtualhostsFile();
- String relative = relativeToQpidHome(testVirtualhosts);
-
- setSystemProperty("test.virtualhosts", relative);
- _logger.info("Set test.virtualhosts property to: " + relative);
- _logger.info("Saving test virtualhosts file at: " + testVirtualhosts);
+ setSystemProperty("test.virtualhosts", testVirtualhosts);
// Create the file if configuration does not exist
if (_testVirtualhosts.isEmpty())
@@ -702,33 +618,30 @@ public class QpidBrokerTestCase extends QpidTestCase
_testVirtualhosts.save(testVirtualhosts);
}
- protected void cleanBrokerWork(final String qpidWork)
+ public void cleanBroker()
{
- if (qpidWork != null)
+ if (_brokerClean != null)
{
- _logger.info("Cleaning broker work dir: " + qpidWork);
+ _logger.info("clean: " + _brokerClean);
- File file = new File(qpidWork);
- if (file.exists())
+ try
{
- final boolean success = FileUtils.delete(file, true);
- if(!success)
- {
- throw new RuntimeException("Failed to recursively delete beneath : " + file);
- }
- }
- }
- }
+ ProcessBuilder pb = new ProcessBuilder(_brokerClean.split("\\s+"));
+ pb.redirectErrorStream(true);
+ Process clean = pb.start();
+ new Piper(clean.getInputStream(),_brokerOutputStream).start();
- protected void createBrokerWork(final String qpidWork)
- {
- if (qpidWork != null)
- {
- final File dir = new File(qpidWork);
- dir.mkdirs();
- if (!dir.isDirectory())
+ clean.waitFor();
+
+ _logger.info("clean exited: " + clean.exitValue());
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (InterruptedException e)
{
- throw new RuntimeException("Failed to created Qpid work directory : " + qpidWork);
+ throw new RuntimeException(e);
}
}
}
@@ -742,18 +655,21 @@ public class QpidBrokerTestCase extends QpidTestCase
{
port = getPort(port);
- _logger.info("stopping broker on port : " + port);
- BrokerHolder broker = _brokers.remove(port);
- broker.shutdown();
+ _logger.info("stopping broker: " + getBrokerCommand(port));
+ Process process = _brokers.remove(port);
+ if (process != null)
+ {
+ process.destroy();
+ process.waitFor();
+ _logger.info("broker exited: " + process.exitValue());
+ }
+ else if (_broker.equals(VM))
+ {
+ TransportConnection.killVMBroker(port);
+ ApplicationRegistry.remove(port);
+ }
}
- public boolean isBrokerPresent(int port) throws Exception
- {
- port = getPort(port);
-
- return _brokers.containsKey(port);
- }
-
/**
* Attempt to set the Java Broker to use the BDBMessageStore for persistence
* Falling back to the DerbyMessageStore if
@@ -895,14 +811,20 @@ public class QpidBrokerTestCase extends QpidTestCase
}
/**
- * Set a System property for the client (and broker if using the same vm) of this test.
+ * Set a System (-D) property for the external Broker of this test.
*
* @param property The property to set
* @param value the value to set it to.
*/
protected void setTestClientSystemProperty(String property, String value)
{
- setTestSystemProperty(property, value);
+ if (!_propertiesSetForTestOnly.containsKey(property))
+ {
+ // Record the current value so we can revert it later.
+ _propertiesSetForTestOnly.put(property, System.getProperty(property));
+ }
+
+ System.setProperty(property, value);
}
/**
@@ -910,7 +832,20 @@ public class QpidBrokerTestCase extends QpidTestCase
*/
protected void revertSystemProperties()
{
- revertTestSystemProperties();
+ for (String key : _propertiesSetForTestOnly.keySet())
+ {
+ String value = _propertiesSetForTestOnly.get(key);
+ if (value != null)
+ {
+ System.setProperty(key, value);
+ }
+ else
+ {
+ System.clearProperty(key);
+ }
+ }
+
+ _propertiesSetForTestOnly.clear();
// We don't change the current VMs settings for Broker only properties
// so we can just clear this map
@@ -918,7 +853,7 @@ public class QpidBrokerTestCase extends QpidTestCase
}
/**
- * Add an environment variable for the external broker environment
+ * Add an environtmen variable for the external broker environment
*
* @param property the property to set
* @param value the value to set it to
@@ -929,23 +864,57 @@ public class QpidBrokerTestCase extends QpidTestCase
}
/**
+ * Adjust the VMs Log4j Settings just for this test run
+ *
+ * @param logger the logger to change
+ * @param level the level to set
+ */
+ protected void setLoggerLevel(Logger logger, Level level)
+ {
+ assertNotNull("Cannot set level of null logger", logger);
+ assertNotNull("Cannot set Logger("+logger.getName()+") to null level.",level);
+
+ if (!_loggerLevelSetForTest.containsKey(logger))
+ {
+ // Record the current value so we can revert it later.
+ _loggerLevelSetForTest.put(logger, logger.getLevel());
+ }
+
+ logger.setLevel(level);
+ }
+
+ /**
+ * Restore the logging levels defined by this test.
+ */
+ protected void revertLoggingLevels()
+ {
+ for (Logger logger : _loggerLevelSetForTest.keySet())
+ {
+ logger.setLevel(_loggerLevelSetForTest.get(logger));
+ }
+
+ _loggerLevelSetForTest.clear();
+
+ }
+
+ /**
* Check whether the broker is an 0.8
*
* @return true if the broker is an 0_8 version, false otherwise.
*/
public boolean isBroker08()
{
- return _brokerVersion.equals(AmqpProtocolVersion.v0_8);
+ return _brokerVersion.equals(VERSION_08);
}
public boolean isBroker010()
{
- return _brokerVersion.equals(AmqpProtocolVersion.v0_10);
+ return _brokerVersion.equals(VERSION_010);
}
protected boolean isJavaBroker()
{
- return _brokerLanguage.equals("java") || _brokerType.equals("vm");
+ return _brokerLanguage.equals("java") || _broker.equals("vm");
}
protected boolean isCppBroker()
@@ -955,14 +924,9 @@ public class QpidBrokerTestCase extends QpidTestCase
protected boolean isExternalBroker()
{
- return !_brokerType.equals("vm"); //TODO
+ return !_broker.equals("vm");
}
-
- protected boolean isInternalBroker()
- {
- return _brokerType.equals(BrokerType.INTERNAL);
- }
-
+
protected boolean isBrokerStorePersistent()
{
return _brokerPersistent;
@@ -1002,9 +966,9 @@ public class QpidBrokerTestCase extends QpidTestCase
* Get the default connection factory for the currently used broker
* Default factory is "local"
*
- * @return A connection factory
+ * @return A conection factory
*
- * @throws Exception if there is an error getting the factory
+ * @throws Exception if there is an error getting the tactory
*/
public AMQConnectionFactory getConnectionFactory() throws NamingException
{
@@ -1028,15 +992,20 @@ public class QpidBrokerTestCase extends QpidTestCase
*
* @param factoryName The factory name
*
- * @return A connection factory
+ * @return A conection factory
*
* @throws Exception if there is an error getting the tactory
*/
public AMQConnectionFactory getConnectionFactory(String factoryName) throws NamingException
{
+ if (_broker.equals(VM))
+ {
+ factoryName += ".vm";
+ }
+
return (AMQConnectionFactory) getInitialContext().lookup(factoryName);
}
-
+
public Connection getConnection() throws JMSException, NamingException
{
return getConnection("guest", "guest");
@@ -1066,7 +1035,7 @@ public class QpidBrokerTestCase extends QpidTestCase
{
_logger.info("get connection");
Connection con = getConnectionFactory().createConnection(username, password);
- //add the connection in the list of connections
+ //add the connection in the lis of connections
_connections.add(con);
return con;
}
@@ -1074,8 +1043,16 @@ public class QpidBrokerTestCase extends QpidTestCase
public Connection getClientConnection(String username, String password, String id) throws JMSException, URLSyntaxException, AMQException, NamingException
{
_logger.info("get Connection");
- Connection con = getConnectionFactory().createConnection(username, password, id);
- //add the connection in the list of connections
+ Connection con;
+ if (_broker.equals(VM))
+ {
+ con = new AMQConnection("vm://:1", username, password, id, "test");
+ }
+ else
+ {
+ con = getConnectionFactory().createConnection(username, password, id);
+ }
+ //add the connection in the lis of connections
_connections.add(con);
return con;
}
@@ -1104,12 +1081,18 @@ public class QpidBrokerTestCase extends QpidTestCase
protected void tearDown() throws java.lang.Exception
{
- super.tearDown();
-
- // close all the connections used by this test.
- for (Connection c : _connections)
+ try
{
- c.close();
+ // close all the connections used by this test.
+ for (Connection c : _connections)
+ {
+ c.close();
+ }
+ }
+ finally{
+ // Ensure any problems with close does not interfer with property resets
+ revertSystemProperties();
+ revertLoggingLevels();
}
}
@@ -1166,7 +1149,7 @@ public class QpidBrokerTestCase extends QpidTestCase
/**
* Send messages to the given destination.
*
- * If session is transacted then messages will be committed before returning
+ * If session is transacted then messages will be commited before returning
*
* @param session the session to use for sending
* @param destination where to send them to
@@ -1174,7 +1157,7 @@ public class QpidBrokerTestCase extends QpidTestCase
*
* @param batchSize the batchSize in which to commit, 0 means no batching,
* but a single commit at the end
- * @return the sent message
+ * @return the sent messgse
*
* @throws Exception
*/
@@ -1187,7 +1170,7 @@ public class QpidBrokerTestCase extends QpidTestCase
/**
* Send messages to the given destination.
*
- * If session is transacted then messages will be committed before returning
+ * If session is transacted then messages will be commited before returning
*
* @param session the session to use for sending
* @param destination where to send them to
@@ -1196,7 +1179,7 @@ public class QpidBrokerTestCase extends QpidTestCase
* @param offset offset allows the INDEX value of the message to be adjusted.
* @param batchSize the batchSize in which to commit, 0 means no batching,
* but a single commit at the end
- * @return the sent message
+ * @return the sent messgse
*
* @throws Exception
*/
@@ -1207,8 +1190,7 @@ public class QpidBrokerTestCase extends QpidTestCase
MessageProducer producer = session.createProducer(destination);
- int i = offset;
- for (; i < (count + offset); i++)
+ for (int i = offset; i < (count + offset); i++)
{
Message next = createNextMessage(session, i);
@@ -1231,7 +1213,7 @@ public class QpidBrokerTestCase extends QpidTestCase
// we have no batchSize or
// our count is not divible by batchSize.
if (session.getTransacted() &&
- ( batchSize == 0 || (i-1) % batchSize != 0))
+ ( batchSize == 0 || count % batchSize != 0))
{
session.commit();
}
@@ -1326,26 +1308,29 @@ public class QpidBrokerTestCase extends QpidTestCase
*/
public void reloadBrokerSecurityConfig() throws Exception
{
- JMXTestUtils jmxu = new JMXTestUtils(this, "admin" , "admin");
- jmxu.open();
-
- try
+ if (_broker.equals(VM))
{
- ConfigurationManagement configMBean = jmxu.getConfigurationManagement();
- configMBean.reloadSecurityConfiguration();
+ ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections();
}
- finally
+ else
{
- jmxu.close();
- }
-
- LogMonitor _monitor = new LogMonitor(_outputFile);
- assertTrue("The expected server security configuration reload did not occur",
- _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT));
- }
+ JMXTestUtils jmxu = new JMXTestUtils(this, "admin" , "admin");
+ jmxu.open();
+
+ try
+ {
+ ConfigurationManagement configMBean = jmxu.getConfigurationManagement();
+ configMBean.reloadSecurityConfiguration();
+ }
+ finally
+ {
+ jmxu.close();
+ }
+
+ LogMonitor _monitor = new LogMonitor(_outputFile);
+ assertTrue("The expected server security configuration reload did not occur",
+ _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT));
- protected int getFailingPort()
- {
- return FAILING_PORT;
+ }
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java
deleted file mode 100644
index 65239bbe02..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/SpawnedBrokerHolder.java
+++ /dev/null
@@ -1,58 +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.
- *
- */
-package org.apache.qpid.test.utils;
-
-import org.apache.log4j.Logger;
-
-public class SpawnedBrokerHolder implements BrokerHolder
-{
- private static final Logger LOGGER = Logger.getLogger(SpawnedBrokerHolder.class);
-
- private final Process _process;
-
- public SpawnedBrokerHolder(final Process process)
- {
- if(process == null)
- {
- throw new IllegalArgumentException("Process must not be null");
- }
-
- _process = process;
- }
-
- public void shutdown()
- {
- LOGGER.info("Destroying broker process");
-
- _process.destroy();
-
- try
- {
- _process.waitFor();
- LOGGER.info("broker exited: " + _process.exitValue());
- }
- catch (InterruptedException e)
- {
- LOGGER.error("Interrupted whilst waiting for process destruction");
- Thread.currentThread().interrupt();
- }
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java b/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java
new file mode 100644
index 0000000000..f1eb8159b6
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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 org.apache.qpid.test.utils.protocol;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoService;
+import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.IoSessionConfig;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.common.support.BaseIoSession;
+
+public class TestIoSession extends BaseIoSession {
+
+ private String _stringLocalAddress;
+ private int _localPort;
+
+ public SocketAddress getLocalAddress()
+ {
+ //create a new address for testing purposes using member variables
+ return new InetSocketAddress(_stringLocalAddress,_localPort);
+ }
+
+ protected void updateTrafficMask() {
+ //dummy
+ }
+
+ public IoService getService() {
+ return null;
+ }
+
+ public IoServiceConfig getServiceConfig() {
+ return null;
+ }
+
+ public IoHandler getHandler() {
+ return null;
+ }
+
+ public IoSessionConfig getConfig() {
+ return null;
+ }
+
+ public IoFilterChain getFilterChain() {
+ return null;
+ }
+
+ public TransportType getTransportType() {
+ return null;
+ }
+
+ public SocketAddress getRemoteAddress() {
+ return null;
+ }
+
+ public SocketAddress getServiceAddress() {
+ return null;
+ }
+
+ public int getScheduledWriteRequests() {
+ return 0;
+ }
+
+ public int getScheduledWriteBytes() {
+ return 0;
+ }
+
+ public String getStringLocalAddress() {
+ return _stringLocalAddress;
+ }
+
+ public void setStringLocalAddress(String _stringLocalAddress) {
+ this._stringLocalAddress = _stringLocalAddress;
+ }
+
+ public int getLocalPort() {
+ return _localPort;
+ }
+
+ public void setLocalPort(int _localPort) {
+ this._localPort = _localPort;
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java
index c09e63308c..a5e2b80f64 100644
--- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java
+++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java
@@ -27,9 +27,11 @@ import org.apache.log4j.SimpleLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
-import java.io.LineNumberReader;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
@@ -43,12 +45,10 @@ import java.util.LinkedList;
public class LogMonitor
{
// The file that the log statements will be written to.
- private final File _logfile;
+ private File _logfile;
// The appender we added to the get messages
- private final FileAppender _appender;
-
- private int _linesToSkip = 0;
+ private FileAppender _appender;
/**
* Create a new LogMonitor that creates a new Log4j Appender and monitors
@@ -78,7 +78,6 @@ public class LogMonitor
if (file != null && file.exists())
{
_logfile = file;
- _appender = null;
}
else
{
@@ -100,13 +99,13 @@ public class LogMonitor
* @param wait the time in ms to wait for the message to occur
* @return true if the message was found
*
- * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws java.io.FileNotFoundException if the Log file can nolonger be found
* @throws IOException thrown when reading the log file
*/
public List<String> waitAndFindMatches(String message, long wait)
throws FileNotFoundException, IOException
{
- if (waitForMessage(message, wait))
+ if (waitForMessage(message, wait, true))
{
return findMatches(message);
}
@@ -117,9 +116,7 @@ public class LogMonitor
}
/**
- * Checks the log for instances of the search string. If the caller
- * has previously called {@link #markDiscardPoint()}, lines up until the discard
- * point are not considered.
+ * Checks the log for instances of the search string.
*
* The pattern parameter can take any valid argument used in String.contains()
*
@@ -133,99 +130,66 @@ public class LogMonitor
*/
public List<String> findMatches(String pattern) throws IOException
{
-
- List<String> results = new LinkedList<String>();
-
- LineNumberReader reader = new LineNumberReader(new FileReader(_logfile));
- try
- {
- while (reader.ready())
- {
- String line = reader.readLine();
- if (reader.getLineNumber() > _linesToSkip && line.contains(pattern))
- {
- results.add(line);
- }
- }
- }
- finally
- {
- reader.close();
- }
-
- return results;
+ return FileUtils.searchFile(_logfile, pattern);
}
/**
- * Checks the log file for a given message to appear. If the caller
- * has previously called {@link #markDiscardPoint()}, lines up until the discard
- * point are not considered.
+ * Checks the log file for a given message to appear.
*
* @param message the message to wait for in the log
* @param wait the time in ms to wait for the message to occur
+ *
+ * @param printFileOnFailure should we print the contents that have been
+ * read if we fail ot find the message.
* @return true if the message was found
*
- * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws java.io.FileNotFoundException if the Log file can nolonger be found
* @throws IOException thrown when reading the log file
*/
- public boolean waitForMessage(String message, long wait)
+ public boolean waitForMessage(String message, long wait, boolean printFileOnFailure)
throws FileNotFoundException, IOException
{
// Loop through alerts until we're done or wait ms seconds have passed,
// just in case the logfile takes a while to flush.
- LineNumberReader reader = null;
- try
+ BufferedReader reader = new BufferedReader(new FileReader(_logfile));
+ boolean found = false;
+ long endtime = System.currentTimeMillis() + wait;
+ ArrayList<String> contents = new ArrayList<String>();
+ while (!found && System.currentTimeMillis() < endtime)
{
- reader = new LineNumberReader(new FileReader(_logfile));
-
- boolean found = false;
- long endtime = System.currentTimeMillis() + wait;
- while (!found && System.currentTimeMillis() < endtime)
+ while (reader.ready())
{
- boolean ready = true;
- while (ready = reader.ready())
- {
- String line = reader.readLine();
-
- if (reader.getLineNumber() > _linesToSkip)
- {
- if (line.contains(message))
- {
- found = true;
- break;
- }
- }
- }
- if (!ready)
+ String line = reader.readLine();
+ contents.add(line);
+ if (line.contains(message))
{
- try
- {
- Thread.sleep(50);
- }
- catch (InterruptedException ie)
- {
- Thread.currentThread().interrupt();
- }
+ found = true;
}
}
- return found;
-
}
- finally
+ if (!found && printFileOnFailure)
{
- if (reader != null)
+ for (String line : contents)
{
- reader.close();
+ System.out.println(line);
}
}
+ return found;
}
+
+ public boolean waitForMessage(String message, long alertLogWaitPeriod) throws FileNotFoundException, IOException
+ {
+ return waitForMessage(message, alertLogWaitPeriod, true);
+ }
+
+
/**
* Read the log file in to memory as a String
*
* @return the current contents of the log file
*
- * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws java.io.FileNotFoundException if the Log file can nolonger be found
* @throws IOException thrown when reading the log file
*/
public String readFile() throws FileNotFoundException, IOException
@@ -244,37 +208,14 @@ public class LogMonitor
}
/**
- * Marks the discard point in the log file.
+ * Clears the log file and writes: 'Log Monitor Reset' at the start of the file
*
- * @throws java.io.FileNotFoundException if the Log file can no longer be found
+ * @throws java.io.FileNotFoundException if the Log file can nolonger be found
* @throws IOException thrown if there is a problem with the log file
*/
- public void markDiscardPoint() throws FileNotFoundException, IOException
- {
- _linesToSkip = countLinesInFile();
- }
-
- private int countLinesInFile() throws IOException
+ public void reset() throws FileNotFoundException, IOException
{
- int lineCount = 0;
- BufferedReader br = null;
- try
- {
- br = new BufferedReader(new FileReader(_logfile));
- while(br.readLine() != null)
- {
- lineCount++;
- }
-
- return lineCount;
- }
- finally
- {
- if (br != null)
- {
- br.close();
- }
- }
+ new FileOutputStream(_logfile).getChannel().truncate(0);
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java
index 89f707fbef..a99abe4b94 100644
--- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitorTest.java
@@ -155,7 +155,7 @@ public class LogMonitorTest extends TestCase
String notLogged = "This text was not logged";
- validateLogDoesNotContainMessage(_monitor, notLogged);
+ validateLogDoesNotContainsMessage(_monitor, notLogged);
}
public void testWaitForMessage_Timeout() throws IOException
@@ -168,27 +168,28 @@ public class LogMonitorTest extends TestCase
// Verify that we can time out waiting for a message
assertFalse("Message was logged ",
- _monitor.waitForMessage(message, TIME_OUT / 2));
+ _monitor.waitForMessage(message, TIME_OUT / 2, false));
// Verify that the message did eventually get logged.
assertTrue("Message was never logged.",
_monitor.waitForMessage(message, TIME_OUT));
}
- public void testDiscardPoint() throws IOException
+ public void testReset() throws IOException
{
- String firstMessage = getName() + ": Test Message1";
- Logger.getRootLogger().warn(firstMessage);
+ String message = getName() + ": Test Message";
+
+ Logger.getRootLogger().warn(message);
+
+ validateLogContainsMessage(_monitor, message);
- validateLogContainsMessage(_monitor, firstMessage);
+ String LOG_RESET_TEXT = "Log Monitor Reset";
- _monitor.markDiscardPoint();
+ validateLogDoesNotContainsMessage(_monitor, LOG_RESET_TEXT);
- validateLogDoesNotContainMessage(_monitor, firstMessage);
+ _monitor.reset();
- String secondMessage = getName() + ": Test Message2";
- Logger.getRootLogger().warn(secondMessage);
- validateLogContainsMessage(_monitor, secondMessage);
+ assertEquals("", _monitor.readFile());
}
public void testRead() throws IOException
@@ -213,7 +214,7 @@ public class LogMonitorTest extends TestCase
*
* @throws IOException if a problems occurs
*/
- protected void validateLogDoesNotContainMessage(LogMonitor log, String message)
+ protected void validateLogDoesNotContainsMessage(LogMonitor log, String message)
throws IOException
{
List<String> results = log.findMatches(message);
diff --git a/java/test-profiles/08StandaloneExcludes b/java/test-profiles/08StandaloneExcludes
new file mode 100644
index 0000000000..b482a14c6d
--- /dev/null
+++ b/java/test-profiles/08StandaloneExcludes
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+
+//======================================================================
+//Exclude the following from brokers defaulting to the 0-8 protocol
+//======================================================================
+
+// This test requires a broker capable of 0-8/9 and 0-10
+org.apache.qpid.test.client.message.JMSDestinationTest#testReceiveResend
+
+// QPID-2478 test fails when run against broker using 0-8/9
+org.apache.qpid.test.client.message.JMSDestinationTest#testGetDestinationWithCustomExchange
+
+// The new addressing based sytanx is not supported for AMQP 0-8/0-9 versions
+org.apache.qpid.test.client.destination.AddressBasedDestinationTest#*
+org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
+org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
+
+// Those tests are written against the 0.10 path
+org.apache.qpid.test.unit.message.UTF8Test#*
+org.apache.qpid.client.MessageListenerTest#testSynchronousReceiveNoWait
+
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnsupportedSASLMechanism
diff --git a/java/test-profiles/CPPExcludes b/java/test-profiles/CPPExcludes
index 39b4d542db..e89b09cca2 100755
--- a/java/test-profiles/CPPExcludes
+++ b/java/test-profiles/CPPExcludes
@@ -17,17 +17,11 @@
// under the License.
//
-// QPID-3391: the C++ broker does not currently validate the exchange creation arguments
-org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testCreateExchangeWithNonsenseArgs
-
-//This test requires SSL, but SSL is only enabled for the C++ broker in the cpp.ssl test profile
-//which runs *all* the tests with SSL, so this one can be excluded safely enough
-org.apache.qpid.test.unit.client.AMQSSLConnectionTest#*
-
org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#*
org.apache.qpid.client.ResetMessageListenerTest#*
// This test is not finished
+org.apache.qpid.test.testcases.TTLTest#*
org.apache.qpid.test.client.failover.FailoverTest#test4MinuteFailover
// Those tests are testing 0.8 specific semantics
@@ -64,6 +58,9 @@ org.apache.qpid.test.unit.client.connection.ConnectionTest#testDefaultExchanges
// 0-10 c++ broker in cpp.testprofile is started with no auth so won't pass this test
org.apache.qpid.test.unit.client.connection.ConnectionTest#testPasswordFailureConnection
+// c++ broker doesn't do selectors, so this will fail
+org.apache.qpid.test.unit.topic.TopicSessionTest#testNonMatchingMessagesDoNotFillQueue
+
// InVM Broker tests
org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#*
@@ -139,10 +136,14 @@ org.apache.qpid.server.failover.MessageDisappearWithIOExceptionTest#*
// These are recent test additions that are failing with the c++ broker
// Temporarily disabling until properly investigated.
+org.apache.qpid.test.unit.publish.DirtyTransactedPublishTest#*
org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#*
org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage#*
+// Temporarily adding the following until the issues are sorted out.
+org.apache.qpid.test.unit.client.AMQConnectionTest#testHeartBeat
+
//Excluded due to QPID-1447 : CPP broker does not have SlowConsumer Disconnection
org.apache.qpid.systest.GlobalQueuesTest#*
org.apache.qpid.systest.GlobalTopicsTest#*
@@ -164,26 +165,6 @@ org.apache.qpid.server.security.firewall.FirewallConfigTest#*
org.apache.qpid.server.security.firewall.FirewallConfigurationTest#*
org.apache.qpid.server.plugins.PluginTest#*
-// Transacion timeouts not implemented in CPP broker
-org.apache.qpid.test.unit.transacted.TransactionTimeoutDisabledTest#*
-org.apache.qpid.test.unit.transacted.TransactionTimeoutConfigurationTest#*
-org.apache.qpid.test.unit.transacted.TransactionTimeoutTest#*
-
// Java broker only
org.apache.qpid.server.logging.management.LoggingManagementMBeanTest#*
org.apache.qpid.server.management.AMQUserManagementMBeanTest#*
-
-// QPID-3133: On 0-10, the exception listener is currently not invoked when reconnection fails to occurs.
-org.apache.qpid.server.failover.FailoverMethodTest#*
-
-//QPID-3468: exclude QueueBrowser related failover tests
-org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverAsQueueBrowserCreated
diff --git a/java/test-profiles/CPPTransientExcludes b/java/test-profiles/CPPTransientExcludes
index a214cf5b5c..47f24db19c 100644
--- a/java/test-profiles/CPPTransientExcludes
+++ b/java/test-profiles/CPPTransientExcludes
@@ -27,6 +27,3 @@ org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash
org.apache.qpid.test.unit.xa.TopicTest#testRecover
org.apache.qpid.test.unit.xa.QueueTest#testRecover
org.apache.qpid.test.unit.xa.QueueTest#testSendAndRecover
-
-// test requires a persistent store
-org.apache.qpid.test.unit.ack.ClientAcknowledgeTest#testClientAckWithLargeFlusherPeriod
diff --git a/java/test-profiles/Excludes b/java/test-profiles/Excludes
index b1edd07f87..ff6993fa0b 100644
--- a/java/test-profiles/Excludes
+++ b/java/test-profiles/Excludes
@@ -17,6 +17,13 @@
// under the License.
//
+org.apache.qpid.client.MultipleJCAProviderRegistrationTest#test
+// QPID-1715, QPID-1715 : Client Error Handling on close is still broken
+org.apache.qpid.server.queue.QueueCreateTest#testCreatePriorityString
+org.apache.qpid.server.queue.QueueCreateTest#testCreateFlowToDiskValidNoSize
+org.apache.qpid.server.queue.QueueCreateTest#testCreateFlowToDiskInvalid
+org.apache.qpid.server.queue.QueueCreateTest#testCreateFlowToDiskInvalidSize
+
//
// QPID-2031 : Broker is not cleanly shutdown by QpidTestCase
//
@@ -26,7 +33,7 @@ org.apache.qpid.server.logging.BrokerLoggingTest#testBrokerShutdownStopped
org.apache.qpid.server.logging.VirtualHostLoggingTest#testVirtualhostClosure
org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClose
-// QPID-3424 : Test fails to start external broker due to Derby Exception.
+// QPID-XXX : Test fails to start external broker due to Derby Exception.
org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#*
// QPID-1816 : Client Ack has not been addressed
@@ -44,4 +51,3 @@ org.apache.qpid.test.unit.ack.AcknowledgeAfterFailoverTest#*
// QPID-2418 : The queue backing the dur sub is not currently deleted at subscription change, so the test will fail.
org.apache.qpid.test.unit.ct.DurableSubscriberTest#testResubscribeWithChangedSelectorAndRestart
-org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain
diff --git a/java/test-profiles/Java010Excludes b/java/test-profiles/Java010Excludes
index e7718b982d..3486d5c70c 100755
--- a/java/test-profiles/Java010Excludes
+++ b/java/test-profiles/Java010Excludes
@@ -37,6 +37,9 @@ org.apache.qpid.test.client.FlowControlTest#*
// 0-10 protocol doesn't support message bouncing
org.apache.qpid.server.exchange.ReturnUnroutableMandatoryMessageTest#*
+// QPID-1727 , QPID-1726 :c++ broker does not support flow to disk on transient queues. Also it requries a persistent store impl. for Apache
+org.apache.qpid.test.client.QueueBrowsingFlowToDiskTest#*
+
// 0-10 and 0-9 connections dont generate the exact same logging due to protocol differences
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelStartsFlowStopped
org.apache.qpid.server.logging.ChannelLoggingTest#testChannelStartConsumerFlowStarted
@@ -44,49 +47,35 @@ org.apache.qpid.server.logging.SubscriptionLoggingTest#testSubscriptionSuspend
// 0-10 Broker does not have a JMX connection MBean
org.apache.qpid.management.jmx.ManagementActorLoggingTest#testConnectionCloseViaManagement
-org.apache.qpid.management.jmx.MessageConnectionStatisticsTest#*
+
+// 0-10 has different ideas about clientid and ownership of queues
+org.apache.qpid.server.queue.ModelTest#*
// 0-10 is not supported by the MethodRegistry
org.apache.qpid.test.unit.close.JavaServerCloseRaceConditionTest#*
+// QPID-2084 : this test needs more work for 0-10
+org.apache.qpid.test.unit.client.DynamicQueueExchangeCreateTest#*
+
//QPID-942 : Implemented Channel.Flow based Producer Side flow control to the Java Broker (not in CPP Broker)
org.apache.qpid.server.queue.ProducerFlowControlTest#*
//QPID-1950 : Commit to test this failure. This is a MINA only failure so it cannot be tested when using 010.
org.apache.qpid.server.failover.MessageDisappearWithIOExceptionTest#*
-//QPID-1864: rollback with subscriptions does not work in 0-10 yet
-org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage
-
-// This test uses 0-8 channel frames
-org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#*
+//QPID-2471 : Issues with 0-10 recovery
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverInAutoAckListener
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testRecoverInAutoAckListener
-//QPID-3422: test fails because ring queue is not implemented on java broker
-org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testBrowseMode
+// Temporarily disabling until properly investigated.
+org.apache.qpid.test.unit.publish.DirtyTransactedPublishTest#*
-// QPID-3133: On 0-10, the exception listener is currently not invoked when reconnection fails to occurs.
-org.apache.qpid.server.failover.FailoverMethodTest#*
-
-// QPID-3392: the Java broker does not yet implement exchange creation arguments
-org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testCreateExchangeWithArgs
-org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testSessionCreateTopicWithExchangeArgs
-
-// QPID-1935: the following tests are failing on 0.10 profiles
-org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
-
-// QPID-3432: These tests test the behaviour of 0-8..-0-9-1 specific system property (amqj.default_syncwrite_timeout)
-org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#*
-org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#*
+//rollback with subscriptions does not work in 0-10 yet
+org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverInAutoAckListener
-//QPID-3468: exclude QueueBrowser related failover tests
-org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverAsQueueBrowserCreated
-org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverWithQueueBrowser
-org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverAsQueueBrowserCreated
+//Temporarily adding the following until the issues are sorted out.
+//Should probably raise JIRAs for them.
+org.apache.qpid.transport.network.mina.MINANetworkDriverTest#*
+org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testCreateExchange
+org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testBrowseMode
diff --git a/java/test-profiles/JavaBDBExcludes b/java/test-profiles/JavaBDBExcludes
deleted file mode 100644
index 3fac01cb6d..0000000000
--- a/java/test-profiles/JavaBDBExcludes
+++ /dev/null
@@ -1,22 +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.
-//
-
-//This test is subclassed within the bdbstore module to enable it to run and
-//also add some bdb-specific tests. It is excluded to prevent running twice.
-org.apache.qpid.server.store.MessageStoreTest#*
diff --git a/java/test-profiles/JavaDerbyExcludes b/java/test-profiles/JavaDerbyExcludes
deleted file mode 100644
index 3caa360d48..0000000000
--- a/java/test-profiles/JavaDerbyExcludes
+++ /dev/null
@@ -1,21 +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.
-//
-
-org.apache.qpid.server.store.berkeleydb.BDBMessageStoreTest#*
-org.apache.qpid.server.store.berkeleydb.BDBUpgradeTest#*
diff --git a/java/test-profiles/JavaExcludes b/java/test-profiles/JavaExcludes
index 8de36cbd9a..c38a250abc 100644
--- a/java/test-profiles/JavaExcludes
+++ b/java/test-profiles/JavaExcludes
@@ -17,29 +17,38 @@
// under the License.
//
-// QPID-1823: this takes ages to run
-org.apache.qpid.client.SessionCreateTest#*
+// Those tests are not finished
+org.apache.qpid.test.testcases.TTLTest#*
+org.apache.qpid.test.testcases.FailoverTest#*
-//QPID-2845: The queue policy types used by the C++ broker are not currently supported by the Java broker
-org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
-org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
-
-///////////////////////////////////////////////////////
-//Moved from JavaStandaloneExcludes when it was removed
-///////////////////////////////////////////////////////
-
-// QPID-3426: The following test is broken.
// This is a long running test so should exclude from normal runs
org.apache.qpid.test.client.failover.FailoverTest#test4MinuteFailover
-// This test may use QpidTestCase but it is not using the getConnection and is hardwired to InVM
-org.apache.qpid.test.unit.client.connection.CloseAfterConnectionFailureTest#*
-
-//QPID-1818, QPID-1821 : Client code path does not correctly restore a transacted session after failover.
+//QPID-1818 : Client code path does not correctly restore a transacted session after failover.
org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#*
-//XA functionality is not fully implemented yet
-org.apache.qpid.jms.xa.XAResourceTest#*
+// QPID-1823: this takes ages to run
+org.apache.qpid.client.SessionCreateTest#*
+
+// related to QPID-2471. Temporarily disabling these tests until I figure out why they are failing with the Java broker.
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverResendsMsgs
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverResendsMsgsAckOnEarlier
+org.apache.qpid.test.unit.ack.RecoverTest#testAcknowledgePerConsumer
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testRecoverResendsMsgs
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testRecoverResendsMsgsAckOnEarlier
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testAcknowledgePerConsumer
+
+// related to QPID-2471. These are new test cases and fail with the Java broker.
+org.apache.qpid.test.unit.ack.RecoverTest#testOderingWithAsyncConsumer
+org.apache.qpid.test.unit.ack.RecoverTest#testOderingWithSyncConsumer
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testOderingWithAsyncConsumer
+org.apache.qpid.test.unit.ack.FailoverBeforeConsumingRecoverTest#testOderingWithSyncConsumer
+
+org.apache.qpid.test.client.queue.LVQTest#*
-//The Java broker doesnt support client auth
-org.apache.qpid.client.ssl.SSLTest#testMultipleCertsInSingleStore
+// Session resume is not supported in the Java client
+org.apache.qpid.transport.ConnectionTest#testResumeNonemptyReplayBuffer
+
+//QPID-2845: The queue policy types used by the C++ broker are not currently supported by the Java broker
+org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
+org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
diff --git a/java/test-profiles/JavaInVMExcludes b/java/test-profiles/JavaInVMExcludes
new file mode 100644
index 0000000000..7e7da4302e
--- /dev/null
+++ b/java/test-profiles/JavaInVMExcludes
@@ -0,0 +1,43 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+//======================================================================
+//Exclude the following tests when running the InVM default test profile
+//======================================================================
+
+// The FirewallPlugin only operates for TCP connections, the tests NO-OP when run InVM
+org.apache.qpid.server.security.firewall.FirewallConfigTest#*
+
+// This test requires a broker capable of 0-8/9 and 0-10
+org.apache.qpid.test.client.message.JMSDestinationTest#testReceiveResend
+
+// QPID-2478 test fails when run against broker using 0-8/9
+org.apache.qpid.test.client.message.JMSDestinationTest#testGetDestinationWithCustomExchange
+
+// related to QPID-2471. Temporarily disabling these tests until I figure out why they are failing with the Java broker.
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverResendsMsgs
+org.apache.qpid.test.unit.ack.RecoverTest#testRecoverResendsMsgsAckOnEarlier
+org.apache.qpid.test.unit.ack.RecoverTest#testAcknowledgePerConsumer
+
+// related to QPID-2471. These are new test cases and fail with the Java broker.
+org.apache.qpid.test.unit.ack.RecoverTest#testOderingWithAsyncConsumer
+org.apache.qpid.test.unit.ack.RecoverTest#testOderingWithSyncConsumer
+
+//The VM broker does not export the logging management JMX MBean
+org.apache.qpid.server.security.acl.ExternalAdminACLTest#*
diff --git a/java/test-profiles/JavaPre010Excludes b/java/test-profiles/JavaPre010Excludes
deleted file mode 100644
index 8344cd98c2..0000000000
--- a/java/test-profiles/JavaPre010Excludes
+++ /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.
-//
-
-//======================================================================
-//Exclude the following from brokers using the 0-8/0-9/0-9-1 protocols
-//======================================================================
-
-// This test requires a broker capable of 0-8/0-9/0-9-1 and 0-10 concurrently
-org.apache.qpid.test.client.message.JMSDestinationTest#testReceiveResend
-
-// QPID-2478 test fails when run against broker using 0-8/9
-org.apache.qpid.test.client.message.JMSDestinationTest#testGetDestinationWithCustomExchange
-
-// The new addressing based syntax is not supported for AMQP 0-8/0-9 versions
-org.apache.qpid.test.client.destination.AddressBasedDestinationTest#*
-org.apache.qpid.test.client.queue.QueuePolicyTest#testRingPolicy
-org.apache.qpid.test.client.queue.QueuePolicyTest#testRejectPolicy
-org.apache.qpid.test.unit.message.JMSPropertiesTest#testApplicationProperties
-
-// Those tests are written against the 0.10 path
-org.apache.qpid.test.unit.message.UTF8Test#*
-org.apache.qpid.client.MessageListenerTest#testSynchronousReceiveNoWait
-
-// Tests 0.10 client feature
-org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnsupportedSASLMechanism
-
-// uses AMQP 0-10 related properties
-org.apache.qpid.test.unit.message.JMSPropertiesTest#testQpidExtensionProperties
-
-// LVQ tests use new address syntax and can not be run on 0.9.1 profiles
-org.apache.qpid.test.client.queue.LVQTest#*
-
-// Verification of unique client id is 0-10 specific
-org.apache.qpid.test.unit.client.connection.ConnectionTest#testClientIDVerificationForSameUser
-org.apache.qpid.test.unit.client.connection.ConnectionTest#testClientIDVerificationForDifferentUsers
-
-// Under AMQP 0-8..0-9-1 temporary queues are deleted on consumer close, rather than connection close
-// and for this reason this test would fail.
-org.apache.qpid.test.unit.client.temporaryqueue.TemporaryQueueTest#testTemporaryQueueReused
-
diff --git a/java/test-profiles/JavaStandaloneExcludes b/java/test-profiles/JavaStandaloneExcludes
new file mode 100644
index 0000000000..d208a20d15
--- /dev/null
+++ b/java/test-profiles/JavaStandaloneExcludes
@@ -0,0 +1,55 @@
+//
+// 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.
+//
+
+// This is a long running test so should exclude from normal runs
+org.apache.qpid.test.client.failover.FailoverTest#test4MinuteFailover
+
+// Those tests require failover support
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.testcases.FailoverTest#*
+org.apache.qpid.test.client.failover.FailoverTest#*
+
+// InVM Broker tests awaiting resolution of QPID-1103
+org.apache.qpid.test.client.timeouts.SyncWaitDelayTest#*
+org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#*
+
+// This test currently does not pick up the runtime location of the nonVm queueBacking store.
+org.apache.qpid.test.unit.close.FlowToDiskBackingQueueDeleteTest#*
+
+// This test may use QpidTestCase but it is not using the getConnection and is hardwired to InVM
+org.apache.qpid.test.unit.client.connection.CloseAfterConnectionFailureTest#*
+
+//QPID-1818 : Client code path does not correctly restore a transacted session after failover.
+org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#*
+
+// This test requires the standard configuration file for validation.
+// Excluding here does not reduce test coverage.
+org.apache.qpid.server.configuration.ServerConfigurationFileTest#*
+
diff --git a/java/test-profiles/JavaTransientExcludes b/java/test-profiles/JavaTransientExcludes
index 67190a6fcc..2ea46795d9 100644
--- a/java/test-profiles/JavaTransientExcludes
+++ b/java/test-profiles/JavaTransientExcludes
@@ -19,7 +19,6 @@
//These tests require a persistent store
org.apache.qpid.server.store.PersistentStoreTest#*
-org.apache.qpid.test.unit.ack.ClientAcknowledgeTest#testClientAckWithLargeFlusherPeriod
org.apache.qpid.test.unit.ct.DurableSubscriberTest#*
@@ -31,6 +30,3 @@ org.apache.qpid.server.store.MessageStoreTest#testQueuePersistence
org.apache.qpid.server.store.MessageStoreTest#testDurableQueueRemoval
org.apache.qpid.server.store.MessageStoreTest#testExchangePersistence
org.apache.qpid.server.store.MessageStoreTest#testDurableExchangeRemoval
-
-org.apache.qpid.server.store.berkeleydb.BDBMessageStoreTest#*
-org.apache.qpid.server.store.berkeleydb.BDBUpgradeTest#*
diff --git a/java/test-profiles/clean-dir b/java/test-profiles/clean-dir
new file mode 100755
index 0000000000..4d6141b4ab
--- /dev/null
+++ b/java/test-profiles/clean-dir
@@ -0,0 +1,25 @@
+
+#!/bin/bash
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+
+
+rm -rf $@; mkdir $@
diff --git a/java/test-profiles/cpp.async.testprofile b/java/test-profiles/cpp.async.testprofile
index 5357e87687..c3d47f0ce6 100644
--- a/java/test-profiles/cpp.async.testprofile
+++ b/java/test-profiles/cpp.async.testprofile
@@ -19,5 +19,3 @@
include=cpp
profile.excludes=CPPPrefetchExcludes
broker.modules=--load-module ${broker.module.store}
-broker.persistent=true
-
diff --git a/java/test-profiles/cpp.ssl.excludes b/java/test-profiles/cpp.ssl.excludes
index 14c8ac2fe3..4d499c57b9 100644
--- a/java/test-profiles/cpp.ssl.excludes
+++ b/java/test-profiles/cpp.ssl.excludes
@@ -18,10 +18,3 @@
//
#org.apache.qpid.test.client.failover.FailoverTest#*
-
-//This test does not supply a client keystore, therefore it cant login to the C++ broker
-//in this test profile as it demands client certificate authentication
-org.apache.qpid.client.ssl.SSLTest#testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly
-
-//QPID-3431: excluding because this takes 30+ mins to run on the C++ SSL profile for some reason
-org.apache.qpid.client.SessionCreateTest#testSessionCreationLimit
diff --git a/java/test-profiles/cpp.ssl.testprofile b/java/test-profiles/cpp.ssl.testprofile
index b3bb5e22f7..bf71384835 100644
--- a/java/test-profiles/cpp.ssl.testprofile
+++ b/java/test-profiles/cpp.ssl.testprofile
@@ -23,7 +23,7 @@ broker.modules=--load-module ${broker.module.ssl} --ssl-cert-name localhost.loca
profile.use_ssl=true
broker.ready= Listening for SSL connections
-javax.net.ssl.keyStore=${test.profiles}/test_resources/ssl/java_client_keystore.jks
+javax.net.ssl.keyStore=${test.profiles}/test_resources/ssl/keystore.jks
javax.net.ssl.keyStorePassword=password
-javax.net.ssl.trustStore=${test.profiles}/test_resources/ssl/java_client_truststore.jks
+javax.net.ssl.trustStore=${test.profiles}/test_resources/ssl/certstore.jks
javax.net.ssl.trustStorePassword=password
diff --git a/java/test-profiles/cpp.testprofile b/java/test-profiles/cpp.testprofile
index 7cc7fdc821..694e22f48c 100644
--- a/java/test-profiles/cpp.testprofile
+++ b/java/test-profiles/cpp.testprofile
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-broker.version=v0_10
+broker.version=0-10
broker.language=cpp
broker.dir=${project.root}/../cpp/src
@@ -32,8 +32,7 @@ broker.stopped=Exception constructed
broker.modules=
broker.args=
-broker.type=spawned
-broker.command=${broker.executable} -p @PORT --data-dir ${project.root}/build/work/@PORT -t --auth no --no-module-dir ${broker.modules} ${broker.args}
+broker=${broker.executable} -p @PORT --data-dir ${build.data}/@PORT -t --auth no --no-module-dir ${broker.modules} ${broker.args}
profile.excludes=CPPPrefetchExcludes CPPTransientExcludes
test.excludes=Excludes CPPExcludes ${profile}.excludes ${profile.excludes} cpp.excludes
diff --git a/java/test-profiles/default.testprofile b/java/test-profiles/default.testprofile
new file mode 100644
index 0000000000..df8148f787
--- /dev/null
+++ b/java/test-profiles/default.testprofile
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+java.naming.factory.initial=org.apache.qpid.jndi.PropertiesFileInitialContextFactory
+java.naming.provider.url=${test.profiles}/test-provider.properties
+
+broker.version=0-8
+broker=vm
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work
+broker.ready=Listening on TCP port
+broker.start=${test.profiles}/start-broker
+broker.kill=${test.profiles}/kill-broker
+broker.config=${project.root}/build/etc/config-systests.xml
+messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore
+
+max_prefetch=1000
+qpid.dest_syntax=BURL
+
+log=debug
+amqj.logging.level=${log}
+amqj.server.logging.level=${log}
+amqj.protocol.logging.level=${log}
+root.logging.level=warn
+log4j.configuration=file:///${test.profiles}/log4j-test.xml
+log4j.debug=false
+
+# Note test-provider.properties also has variables of same name.
+# Keep in sync
+test.port=15672
+test.mport=18999
+#Note : Management will start open second port on: mport + 100 : 19099
+test.port.ssl=15671
+test.port.alt=25672
+test.port.alt.ssl=25671
+
+test.exclude=true
+profile.excludes=JavaTransientExcludes JavaInVMExcludes 08StandaloneExcludes
+test.excludes=Excludes XAExcludes JavaExcludes ${profile}.excludes ${profile.excludes}
+test.fork=no
+test.mem=512M
+test=*Test
+haltonfailure=no
+haltonerror=no
+exclude.modules=none
+
+profile.clustered=false
diff --git a/java/test-profiles/java-bdb-spawn.0-10.testprofile b/java/test-profiles/java-bdb-spawn.0-10.testprofile
deleted file mode 100644
index cba348b67f..0000000000
--- a/java/test-profiles/java-bdb-spawn.0-10.testprofile
+++ /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.
-#
-
-broker.language=java
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-bdb.xml
-messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes
-broker.clean.between.tests=true
-broker.persistent=true
-broker.version=v0_10
-
diff --git a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
deleted file mode 100644
index b04fea21b6..0000000000
--- a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile
+++ /dev/null
@@ -1,36 +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.
-#
-
-broker.language=java
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-bdb.xml
-messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
-broker.clean.between.tests=true
-broker.persistent=true
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-broker.version=v0_9_1
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-
diff --git a/java/test-profiles/java-bdb.0-10.testprofile b/java/test-profiles/java-bdb.0-10.testprofile
deleted file mode 100644
index 3ef93a68cb..0000000000
--- a/java/test-profiles/java-bdb.0-10.testprofile
+++ /dev/null
@@ -1,32 +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.
-#
-
-broker.language=java
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-bdb.xml
-messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes
-broker.clean.between.tests=true
-broker.persistent=true
-broker.version=v0_10
-
diff --git a/java/test-profiles/java-bdb.0-9-1.testprofile b/java/test-profiles/java-bdb.0-9-1.testprofile
deleted file mode 100644
index 101d38f4b9..0000000000
--- a/java/test-profiles/java-bdb.0-9-1.testprofile
+++ /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.
-#
-
-broker.language=java
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-bdb.xml
-messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore
-profile.excludes=JavaExcludes JavaPersistentExcludes JavaPre010Excludes JavaBDBExcludes
-broker.clean.between.tests=true
-broker.persistent=true
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-broker.version=v0_9_1
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-
diff --git a/java/test-profiles/java-dby-spawn.0-10.testprofile b/java/test-profiles/java-dby-spawn.0-10.testprofile
deleted file mode 100644
index 5bd6f330d5..0000000000
--- a/java/test-profiles/java-dby-spawn.0-10.testprofile
+++ /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.
-#
-broker.language=java
-broker.version=v0_10
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-derby.xml
-messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes
-broker.clean.between.tests=true
-broker.persistent=true
diff --git a/java/test-profiles/java-dby-spawn.0-9-1.testprofile b/java/test-profiles/java-dby-spawn.0-9-1.testprofile
deleted file mode 100644
index e7212d30f8..0000000000
--- a/java/test-profiles/java-dby-spawn.0-9-1.testprofile
+++ /dev/null
@@ -1,35 +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.
-#
-broker.version=v0_9_1
-broker.language=java
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-derby.xml
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
-broker.clean.between.tests=true
-broker.persistent=true
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-
diff --git a/java/test-profiles/java-dby.0-10.testprofile b/java/test-profiles/java-dby.0-10.testprofile
deleted file mode 100644
index 9c23d18f45..0000000000
--- a/java/test-profiles/java-dby.0-10.testprofile
+++ /dev/null
@@ -1,30 +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.
-#
-broker.language=java
-broker.version=v0_10
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-derby.xml
-messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes
-broker.clean.between.tests=true
-broker.persistent=true
diff --git a/java/test-profiles/java-dby.0-9-1.testprofile b/java/test-profiles/java-dby.0-9-1.testprofile
deleted file mode 100644
index 83f43d8dbf..0000000000
--- a/java/test-profiles/java-dby.0-9-1.testprofile
+++ /dev/null
@@ -1,36 +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.
-#
-broker.version=v0_9_1
-broker.language=java
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.config=build/etc/config-systests-derby.xml
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
-profile.excludes=JavaPersistentExcludes JavaDerbyExcludes JavaPre010Excludes
-broker.clean.between.tests=true
-broker.persistent=true
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-
diff --git a/java/test-profiles/java-derby.0.10.testprofile b/java/test-profiles/java-derby.0.10.testprofile
new file mode 100644
index 0000000000..ca9115d30d
--- /dev/null
+++ b/java/test-profiles/java-derby.0.10.testprofile
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+broker.language=java
+broker.version=0-10
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.config=${project.root}/build/etc/config-systests-derby.xml
+messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
+profile.excludes=JavaStandaloneExcludes JavaPersistentExcludes Java010Excludes
+broker.clean.between.tests=true
+broker.persistent=true
diff --git a/java/test-profiles/java-derby.testprofile b/java/test-profiles/java-derby.testprofile
new file mode 100644
index 0000000000..d22e35f07e
--- /dev/null
+++ b/java/test-profiles/java-derby.testprofile
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+broker.language=java
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT --exclude-0-10 @PORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work
+broker.ready=BRK-1004
+broker.stopped=Exception
+broker.config=${project.root}/build/etc/config-systests-derby.xml
+messagestore.class.name=org.apache.qpid.server.store.DerbyMessageStore
+profile.excludes=JavaStandaloneExcludes JavaPersistentExcludes 08StandaloneExcludes
+broker.clean.between.tests=true
+broker.persistent=true
+#
+# Do not enable. Allow client to attempt 0-10 and negotiate downwards
+#
+#qpid.amqp.version=0-91
+
diff --git a/java/test-profiles/java-mms-spawn.0-10.testprofile b/java/test-profiles/java-mms-spawn.0-10.testprofile
deleted file mode 100644
index 5e5d2e8a6b..0000000000
--- a/java/test-profiles/java-mms-spawn.0-10.testprofile
+++ /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.
-#
-broker.version=v0_10
-broker.language=java
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-10
-profile.excludes=JavaTransientExcludes Java010Excludes
diff --git a/java/test-profiles/java-mms-spawn.0-9-1.testprofile b/java/test-profiles/java-mms-spawn.0-9-1.testprofile
deleted file mode 100644
index 05b1f89452..0000000000
--- a/java/test-profiles/java-mms-spawn.0-9-1.testprofile
+++ /dev/null
@@ -1,30 +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.
-#
-broker.version=v0_9_1
-broker.language=java
-broker.type=spawned
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java-mms.0-10.testprofile b/java/test-profiles/java-mms.0-10.testprofile
deleted file mode 100644
index 209d384422..0000000000
--- a/java/test-profiles/java-mms.0-10.testprofile
+++ /dev/null
@@ -1,27 +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.
-#
-broker.language=java
-broker.version=v0_10
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-
-profile.excludes=JavaTransientExcludes Java010Excludes
diff --git a/java/test-profiles/java-mms.0-9-1.testprofile b/java/test-profiles/java-mms.0-9-1.testprofile
deleted file mode 100644
index 37efa097bb..0000000000
--- a/java/test-profiles/java-mms.0-9-1.testprofile
+++ /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.
-#
-broker.language=java
-broker.version=v0_9_1
-broker.type=internal
-#broker.command only used for the second broker during failover tests in this profile
-broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES -c @CONFIG_FILE -l test-profiles/log4j-test.xml
-broker.ready=BRK-1004
-broker.stopped=Exception
-broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT
-#
-# Do not enable. Allow client to attempt 0-10 and negotiate downwards
-#
-#qpid.amqp.version=0-91
-profile.excludes=JavaTransientExcludes JavaPre010Excludes
diff --git a/java/test-profiles/java.0.10.testprofile b/java/test-profiles/java.0.10.testprofile
new file mode 100644
index 0000000000..fa87b22e92
--- /dev/null
+++ b/java/test-profiles/java.0.10.testprofile
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+broker.language=java
+broker.version=0-10
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work
+broker.ready=BRK-1004
+broker.stopped=Exception
+
+profile.excludes=JavaTransientExcludes JavaStandaloneExcludes Java010Excludes
diff --git a/java/test-profiles/java.testprofile b/java/test-profiles/java.testprofile
new file mode 100644
index 0000000000..c8c776d3e1
--- /dev/null
+++ b/java/test-profiles/java.testprofile
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+broker.language=java
+broker=${project.root}/build/bin/qpid-server -p @PORT -m @MPORT --exclude-0-10 @PORT -c @CONFIG_FILE -l ${test.profiles}/log4j-test.xml
+broker.clean=${test.profiles}/clean-dir ${build.data} ${project.root}/build/work
+broker.ready=BRK-1004
+broker.stopped=Exception
+#
+# Do not enable. Allow client to attempt 0-10 and negotiate downwards
+#
+#qpid.amqp.version=0-91
+profile.excludes=JavaTransientExcludes JavaStandaloneExcludes 08StandaloneExcludes
diff --git a/java/test-profiles/log4j-test.xml b/java/test-profiles/log4j-test.xml
index 062acaaac9..9adfd68202 100644
--- a/java/test-profiles/log4j-test.xml
+++ b/java/test-profiles/log4j-test.xml
@@ -59,6 +59,10 @@
<level value="ERROR"/>
</logger>
+ <logger name="org.apache.qpid.server.virtualhost.VirtualHostImpl$1HouseKeepingTask">
+ <level value="WARN"/>
+ </logger>
+
<root>
<level value="${root.logging.level}"/>
<appender-ref ref="console" />
diff --git a/java/test-profiles/python_tests/Java010PythonExcludes b/java/test-profiles/python_tests/Java010PythonExcludes
deleted file mode 100644
index 31d2a8affc..0000000000
--- a/java/test-profiles/python_tests/Java010PythonExcludes
+++ /dev/null
@@ -1,22 +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.
-//
-
-// QPID-3477: Java broker does not handle rejection code specified in test
-qpid.tests.messaging.endpoints.SessionTests.testReject
-
diff --git a/java/test-profiles/test-provider.properties b/java/test-profiles/test-provider.properties
index fe27cfcfaf..8cea012c1d 100644
--- a/java/test-profiles/test-provider.properties
+++ b/java/test-profiles/test-provider.properties
@@ -30,12 +30,16 @@ test.port.alt.ssl=25671
connectionfactory.default = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port}'
connectionfactory.default.ssl = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.ssl}?ssl='true''
+connectionfactory.default.vm = amqp://username:password@clientid/test?brokerlist='vm://:1'
connectionfactory.failover = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt};tcp://localhost:${test.port}'&sync_ack='true'&sync_publish='all'&failover='roundrobin?cyclecount='20''
connectionfactory.failover.ssl = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt.ssl}?ssl='true';tcp://localhost:${test.port.ssl}?ssl='true''&sync_ack='true'&sync_publish='all'&failover='roundrobin?cyclecount='20''
+connectionfactory.failover.vm = amqp://username:password@clientid/test?brokerlist='vm://:2;vm://:1'&failover='roundrobin?cyclecount='20''
connectionfactory.connection1 = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port}'
connectionfactory.connection2 = amqp://username:password@clientid/test?brokerlist='tcp://localhost:${test.port.alt}'
+connectionfactory.connection1.vm = amqp://username:password@clientid/test?brokerlist='vm://:1'
+connectionfactory.connection2.vm = amqp://username:password@clientid/test?brokerlist='vm://:2'
queue.MyQueue = example.MyQueue
diff --git a/java/test-profiles/test_resources/ssl/java_client_truststore.jks b/java/test-profiles/test_resources/ssl/certstore.jks
index 2af95f21f8..2af95f21f8 100644
--- a/java/test-profiles/test_resources/ssl/java_client_truststore.jks
+++ b/java/test-profiles/test_resources/ssl/certstore.jks
Binary files differ
diff --git a/java/test-profiles/test_resources/ssl/java_broker.crt b/java/test-profiles/test_resources/ssl/java_broker.crt
deleted file mode 100644
index 7543ee8a7d..0000000000
--- a/java/test-profiles/test_resources/ssl/java_broker.crt
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICVzCCAcCgAwIBAgIFAJVWeugwDQYJKoZIhvcNAQEFBQAwQTELMAkGA1UEBhMC
-Q0ExEDAOBgNVBAgTB09udGFyaW8xDTALBgNVBAoTBEFDTUUxETAPBgNVBAMTCE15
-Um9vdENBMB4XDTExMDgxNzEzNTQ1NFoXDTExMTExNzEzNTQ1NFowejEQMA4GA1UE
-BhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQ
-MA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEeMBwGA1UEAxMVbG9j
-YWxob3N0LmxvY2FsZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCj
-VSo/qOCDsPXQ2HKn2M4ey1FzK6NORkWYefFu5fDFJUKKPXXA8Ey9rPDv+XGGIQKI
-6JlmD2nnjp8Em7+/xa6u4XbFqLR8ycmgldGB7r8RbH3B7KYY3s4AxL9A3/TzHza4
-FJAk2X4LTVWHuX8tB/JyLS6695NSLoI5xKW4maARxwIDAQABoyIwIDAJBgNVHRME
-AjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBBQUAA4GBAFsexncH
-xxTjk9YMoPpjjU0t/UgzjBLEruIIQQ/EtcZIOEqNCDwpzfgY/x7GVCy8VjLISgzK
-xJsNv75F/vP8a4eaeTRJmrvVcWUZJu6r/A8WNwJVYUvXhy2+jbfdp/UMlRg+ODw7
-GMU9ILQW4LGJnTtJKrlVrcQqzw6IZRduEE65
------END CERTIFICATE-----
diff --git a/java/test-profiles/test_resources/ssl/java_broker.req b/java/test-profiles/test_resources/ssl/java_broker.req
deleted file mode 100644
index 05fc8b0eda..0000000000
--- a/java/test-profiles/test_resources/ssl/java_broker.req
+++ /dev/null
@@ -1,10 +0,0 @@
------BEGIN NEW CERTIFICATE REQUEST-----
-MIIBujCCASMCAQAwejEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UE
-BxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEeMBwGA1UEAxMV
-bG9jYWxob3N0LmxvY2FsZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjVSo/qOCD
-sPXQ2HKn2M4ey1FzK6NORkWYefFu5fDFJUKKPXXA8Ey9rPDv+XGGIQKI6JlmD2nnjp8Em7+/xa6u
-4XbFqLR8ycmgldGB7r8RbH3B7KYY3s4AxL9A3/TzHza4FJAk2X4LTVWHuX8tB/JyLS6695NSLoI5
-xKW4maARxwIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAjXXfPRv7xQYY3R8lZ78/0gbXZ35Lq/1h
-6sxShXfqXxFXE8oP4uGLTlsnSvfsHQL60ihKP3V+nv/zIxNudAsrM57x70owUWyp/bm0XXD89X0T
-zEBP9OQexDTwC2r/8gvYMi++022LMTluEPw29bCsp6usuKh61eLmekprpNlhs5M=
------END NEW CERTIFICATE REQUEST-----
diff --git a/java/test-profiles/test_resources/ssl/java_broker_keystore.jks b/java/test-profiles/test_resources/ssl/java_broker_keystore.jks
deleted file mode 100644
index 4c4449e20d..0000000000
--- a/java/test-profiles/test_resources/ssl/java_broker_keystore.jks
+++ /dev/null
Binary files differ
diff --git a/java/test-profiles/test_resources/ssl/java_client_keystore.jks b/java/test-profiles/test_resources/ssl/keystore.jks
index e3a850a248..e3a850a248 100644
--- a/java/test-profiles/test_resources/ssl/java_client_keystore.jks
+++ b/java/test-profiles/test_resources/ssl/keystore.jks
Binary files differ
diff --git a/java/test-profiles/testprofile.defaults b/java/test-profiles/testprofile.defaults
deleted file mode 100644
index bd2faa7915..0000000000
--- a/java/test-profiles/testprofile.defaults
+++ /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.
-#
-java.naming.factory.initial=org.apache.qpid.jndi.PropertiesFileInitialContextFactory
-java.naming.provider.url=${test.profiles}/test-provider.properties
-
-broker.ready=Listening on TCP
-broker.config=build/etc/config-systests.xml
-messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore
-broker.protocol.excludes=
-broker.persistent=false
-
-max_prefetch=1000
-qpid.dest_syntax=BURL
-
-log=debug
-amqj.logging.level=${log}
-amqj.server.logging.level=${log}
-amqj.protocol.logging.level=${log}
-root.logging.level=warn
-log4j.configuration=file:///${test.profiles}/log4j-test.xml
-log4j.debug=false
-
-# Note test-provider.properties also has variables of same name.
-# Keep in sync
-test.port=15672
-test.mport=18999
-#Note : Management will start open second port on: mport + 100 : 19099
-test.port.ssl=15671
-test.port.alt=25672
-test.port.alt.ssl=25671
-
-test.exclude=true
-profile.excludes=
-test.excludes=Excludes XAExcludes JavaExcludes ${profile}.excludes ${profile.excludes}
-test.mem=512M
-test=*Test
-haltonfailure=no
-haltonerror=no
-exclude.modules=none
-
-profile.clustered=false
-
-
diff --git a/java/tools/bin/Profile-run-from-source b/java/tools/bin/Profile-run-from-source
deleted file mode 100755
index f8ec45ccff..0000000000
--- a/java/tools/bin/Profile-run-from-source
+++ /dev/null
@@ -1,71 +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.
-#
-
-# Sets the environment for running the scripts from a source checkout.
-txtbld=$(tput bold) # Bold
-txtrst=$(tput sgr0) # Reset
-txtred=$(tput setaf 1) # red
-txtgreen=$(tput setaf 2) # green
-
-echo "${txtbld}Setting the environment to run qpid java tools from a source checkout${txtrst}"
-
-abs_path()
-{
- D=`dirname "$1"`
- echo "`cd \"$D\" 2>/dev/null && pwd`"
-}
-
-export QPID_CHECKOUT=`abs_path "../../../../"`
-echo "${txtgreen}Using source checkout at $QPID_CHECKOUT${txtrst}"
-
-export PATH=$QPID_CHECKOUT/java/tools/bin:$PATH
-
-if [ "$JAVA" = "" ] ; then
- export JAVA=$(which java)
-fi
-
-#------------- Required for perf_report, qpid-bench & qpid-python-testkit ----------------
-
-export VENDOR_LIB=$QPID_CHECKOUT/java/build/lib
-export CLASSPATH=`find $VENDOR_LIB -name '*.jar' | tr '\n' ':'`
-export LOG_CONFIG="-Dlog4j.configuration=file:///$QPID_CHECKOUT/java/tools/etc/test.log4j"
-
-
-#------------- Required for qpid-python-testkit -----------------------------------------
-
-PYTHONPATH=$QPID_CHECKOUT/python/qpid:$QPID_CHECKOUT/cpp/src/test/brokertest.py:$PYTHONPATH
-export PATH=$QPID_CHECKOUT/python:$PATH
-
-if [ -x $QPID_CHECKOUT/cpp/src/qpidd ]; then
- QPIDD_EXEC=$QPID_CHECKOUT/cpp/src/qpidd
-else
- echo "${txtred}WARNING: Qpid CPP broker executable not found. You will not be able to run qpid-python-testkit${txtrst}"
-fi
-
-if [ -x $QPID_CHECKOUT/cpp/src/.libs/cluster.so ]; then
- CLUSTER_LIB=$QPID_CHECKOUT/cpp/src/.libs/cluster.so
-else
- echo "${txtred}WARNING: Qpid cluster.so not found.You will not be able to run qpid-python-testkit${txtrst}"
-fi
-
-if [ "$STORE_LIB" = "" ] ; then
- echo "${txtred}WARNING: Please point the STORE_LIB variable to the message store module. If not persistence tests will not write messages to disk.${txtrst}"
-fi
-
-export PYTHONPATH QPIDD_EXEC CLUSTER_LIB
diff --git a/java/tools/bin/check-qpid-java-env b/java/tools/bin/check-qpid-java-env
deleted file mode 100755
index dedd6e06ea..0000000000
--- a/java/tools/bin/check-qpid-java-env
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-if [ -z "$LOG_CONFIG" ]; then
- echo "Please set the appropriate parameters for logging as it may affect performance. Ex log4j defaults to DEBUG if not configured properly"
- exit -1
-fi
-
-if [ -z "$JAVA_MEM" ]; then
- JAVA_MEM=-Xmx1024m
-fi
-
-if [ -z "$JAVA" ]; then
- echo "Please set the path to the correct java executable to JAVA"
- exit -1
-fi
-
-if [ -z "$CLASSPATH" ]; then
- echo "Please set the $CLASSPATH variable to point to the jar/class files"
- exit -1
-fi
diff --git a/java/tools/bin/controller b/java/tools/bin/controller
deleted file mode 100644
index fab8614039..0000000000
--- a/java/tools/bin/controller
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# This starts the controller for coordinating perf tests/
-
-. check-qpid-java-env
-
-PROGRAM_NAME=controller
-CONSUMER_COUNT=1
-PRODUCER_COUNT=1
-DURATION=-1
-TEST_NAME="TEST_NAME"
-EXTRA_JVM_ARGS=""
-
-TEMP=$(getopt -n $PROGRAM_NAME -o c:p:d:n:a:h --long consumers:,producers:,jvm-args:help -- "$@")
-
-usage()
-{
- printf "\n%s\n" "Usage: controller [option].."
-
- printf "\n%31s\n%52s\n" "-c, --consumer-count=count" "No of consumers participating in the test"
-
- printf "\n%31s\n%52s\n" "-p, --producer-count=count" "No of producers participating in the test"
-
- printf "\n%24s\n%94s\n" "-d, --duration=mins" "The duration of the test in mins. If not specified, it will just run one iteration."
-
- printf "\n%27s\n%32s\n" "-n, --name=<test-name>" "The name of the test."
-
- printf "\n%19s\n%50s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify"
-}
-
-eval set -- "$TEMP"
-while true; do
- case $1 in
- -c|--consumer-count)
- CONSUMER_COUNT="$2"; shift; shift; continue
- ;;
- -p|--producer-count)
- PRODUCER_COUNT="$2"; shift; shift; continue
- ;;
- -d|--duration)
- DURATION="$2"; shift; shift; continue
- ;;
- -n|--name)
- TEST_NAME="$2"; shift; shift; continue
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -a|--jvm-args)
- EXTRA_JVM_ARGS="$2"; shift; shift; continue
- ;;
- --)
- # no more arguments to parse
- break
- ;;
- *)
- # no more arguments to parse
- break
- ;;
- esac
-done
-
-CONTROLLER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dprod_count=$PRODUCER_COUNT -Dcons_count=$CONSUMER_COUNT -Dprint_std_dev=true -Dduration=${DURATION}"
-
-
-waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; }
-cleanup()
-{
- pids=`ps aux | grep java | grep PerfTestController | awk '{print $2}'`
- if [ "$pids" != "" ]; then
- kill -3 $pids
- kill -9 $pids >/dev/null 2>&1
- fi
-}
-
-run_controller()
-{
- TEST_ARGS="$LOG_CONFIG $JAVA_MEM $CONTROLLER_ARGS $EXTRA_JVM_ARGS"
- echo "Running controller with : $TEST_ARGS" > test.out
- $JAVA -cp $CLASSPATH $TEST_ARGS org.apache.qpid.tools.PerfTestController >> test.out &
- waitfor test.out "Controller: Completed the test"
- sleep 2 #give a grace period to shutdown
- print_result $TEST_NAME
-}
-
-print_result()
-{
- prod_rate=`cat test.out | grep "Avg Producer rate" | awk '{print $5}'`
- sys_rate=`cat test.out | grep "System Throughput" | awk '{print $4}'`
- cons_rate=`cat test.out | grep "Avg Consumer rate" | awk '{print $5}'`
- avg_latency=`cat test.out | grep "Avg System Latency" | awk '{print $5}'`
- min_latency=`cat test.out | grep "Min System Latency" | awk '{print $5}'`
- max_latency=`cat test.out | grep "Max System Latency" | awk '{print $5}'`
- std_dev=`cat test.out | grep "Avg System Std Dev" | awk '{print $6}'`
-
- printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|%7.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency $std_dev
- echo "--------------------------------------------------------------------------------------------------------"
-}
-
-trap cleanup EXIT
-
-rm -rf *.out
-
-if [ "$DURATION" = -1 ]; then
- echo "Test report on " `date +%F`
- echo "========================================================================================================"
- echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|Std Dev|"
- echo "--------------------------------------------------------------------------------------------------------"
-else
- echo "Test in progress....Tail stats-csv.log to see results being printed for each iteration."
-fi
-
-run_controller
diff --git a/java/tools/bin/perf-report b/java/tools/bin/perf-report
deleted file mode 100755
index 7de3f2b602..0000000000
--- a/java/tools/bin/perf-report
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# This will run the following test cases defined below and produce
-# a report in tabular format.
-
-QUEUE="queue;{create:always,node:{x-declare:{auto-delete:true}}}"
-DURA_QUEUE="dqueue;{create:always,node:{durable:true,x-declare:{auto-delete:true}}}"
-TOPIC="amq.topic/test"
-DURA_TOPIC="amq.topic/test;{create:always,link:{durable:true}}"
-
-COMMON_CONFIG="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'"
-
-waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; }
-cleanup()
-{
- pids=`ps aux | grep java | grep Perf | awk '{print $2}'`
- if [ "$pids" != "" ]; then
- kill -3 $pids
- kill -9 $pids >/dev/null 2>&1
- fi
-}
-
-# $1 test name
-# $2 consumer options
-# $3 producer options
-run_testcase()
-{
- sh run-sub $COMMON_CONFIG $2 > sub.out &
- sh run-pub $COMMON_CONFIG $3 > pub.out &
- waitfor pub.out "Controller: Completed the test"
- sleep 2 #give a grace period to shutdown
- print_result $1
- mv pub.out $1.pub.out
- mv sub.out $1.sub.out
-}
-
-print_result()
-{
- prod_rate=`cat pub.out | grep "Avg Producer rate" | awk '{print $5}'`
- sys_rate=`cat pub.out | grep "System Throughput" | awk '{print $4}'`
- cons_rate=`cat pub.out | grep "Avg Consumer rate" | awk '{print $5}'`
- avg_latency=`cat pub.out | grep "Avg System Latency" | awk '{print $5}'`
- min_latency=`cat pub.out | grep "Min System Latency" | awk '{print $5}'`
- max_latency=`cat pub.out | grep "Max System Latency" | awk '{print $5}'`
-
- printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11.2f|%11.2f|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency
- echo "------------------------------------------------------------------------------------------------"
-}
-
-trap cleanup EXIT
-rm -rf *.out #cleanup old files.
-
-echo "Test report on " `date +%F`
-echo "================================================================================================"
-echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|"
-echo "------------------------------------------------------------------------------------------------"
-
-# The message counts and warmup counts are set to very low values for quick testing of the script.
-# For a real performance run I recommend setting warmup count to 10k and message count in excess of 100k
-# However for transactions, sync_publish and especially small durable transactions (which is quite slow) I recommend
-# setting very low values to start with and experiment while increasing them slowly.
-
-# Test 1 Trans Queue
-run_testcase "Trans_Queue" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 2 Dura Queue
-run_testcase "Dura_Queue" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 3 Dura Queue Sync
-run_testcase "Dura_Queue_Sync" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent"
-
-# Test 4 Dura Queue Sync Publish and Ack
-run_testcase "Dura_SyncPubAck" "-Daddress=$DURA_QUEUE -Ddurable=true -Dsync_ack=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent"
-
-# Test 5 Topic
-run_testcase "Topic" "-Daddress=$TOPIC" "-Daddress=$TOPIC -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 6 Durable Topic
-run_testcase "Dura_Topic" "-Daddress=$DURA_TOPIC -Ddurable=true" "-Daddress=$DURA_TOPIC -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 7 Fanout
-run_testcase "Fanout" "-Daddress=amq.fanout" "-Daddress=amq.fanout -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 8 Small TX
-run_testcase "Small_Txs_2" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=1" \
- "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=1"
-
-# Test 9 Large TX
-run_testcase "Large_Txs_1000" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=10" \
- "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=10"
-
-# Test 10 256 MSG
-run_testcase "Msg_256b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=256 -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 11 512 MSG
-run_testcase "Msg_512b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=512 -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 12 2048 MSG
-run_testcase "Msg_2048b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=2048 -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 13 Random size MSG
-run_testcase "Random_Msg_Size" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 14 Random size MSG Durable
-run_testcase "Rand_Msg_Dura" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 15 64K MSG
-run_testcase "Msg_64K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 16 Durable 64K MSG
-run_testcase "Msg_Durable_64K" "-Daddress=$DURA_QUEUE -Ddurable=true -Damqj.tcpNoDelay=true" \
- "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 17 500K MSG
-run_testcase "Msg_500K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Dwarmup_count=1 -Dmsg_count=10"
-
-# Test 18 Durable 500K MSG
-run_testcase "Msg_Dura_500K" "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Ddurable=true" \
- "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
diff --git a/java/tools/bin/perf_report.sh b/java/tools/bin/perf_report.sh
new file mode 100755
index 0000000000..e6b4c987e5
--- /dev/null
+++ b/java/tools/bin/perf_report.sh
@@ -0,0 +1,140 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# This will run the 8 use cases defined below and produce
+# a report in tabular format. Refer to the documentation
+# for more details.
+
+SUB_MEM=-Xmx1024M
+PUB_MEM=-Xmx1024M
+LOG_CONFIG="-Damqj.logging.level=WARN"
+QUEUE="queue;{create:always,node:{x-declare:{auto-delete:true}}}"
+DURA_QUEUE="dqueue;{create:always,node:{durable:true,x-declare:{auto-delete:true}}}"
+TOPIC="amq.topic/test"
+DURA_TOPIC="amq.topic/test;{create:always,link:{durable:true}}"
+
+. setenv.sh
+
+waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; }
+cleanup()
+{
+ pids=`ps aux | grep java | grep Perf | awk '{print $2}'`
+ if [ "$pids" != "" ]; then
+ kill -3 $pids
+ kill -9 $pids >/dev/null 2>&1
+ fi
+}
+
+# $1 test name
+# $2 consumer options
+# $3 producer options
+run_testcase()
+{
+ sh run_sub.sh $LOG_CONFIG $SUB_MEM $2 > sub.out &
+ waitfor sub.out "Warming up"
+ sh run_pub.sh $LOG_CONFIG $PUB_MEM $3 > pub.out &
+ waitfor sub.out "Completed the test"
+ waitfor pub.out "Consumer has completed the test"
+ sleep 2 #give a grace period to shutdown
+ print_result $1
+}
+
+print_result()
+{
+ prod_rate=`cat pub.out | grep "Producer rate" | awk '{print $3}'`
+ sys_rate=`cat sub.out | grep "System Throughput" | awk '{print $4}'`
+ cons_rate=`cat sub.out | grep "Consumer rate" | awk '{print $4}'`
+ avg_latency=`cat sub.out | grep "Avg Latency" | awk '{print $4}'`
+ min_latency=`cat sub.out | grep "Min Latency" | awk '{print $4}'`
+ max_latency=`cat sub.out | grep "Max Latency" | awk '{print $4}'`
+
+ printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11d|%11d|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency
+ echo "------------------------------------------------------------------------------------------------"
+}
+
+trap cleanup EXIT
+
+echo "Test report on " `date +%F`
+echo "================================================================================================"
+echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|"
+echo "------------------------------------------------------------------------------------------------"
+
+# The message counts and warmup counts are set to very low values for quick testing of the script.
+# For a real performance run I recommend setting warmup count to 10k and message count in excess of 100k
+# However for transactions, sync_publish and especially small durable transactions (which is quite slow) I recommend
+# setting very low values to start with and experiment while increasing them slowly.
+
+# Test 1 Trans Queue
+#run_testcase "Trans_Queue" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 2 Dura Queue
+run_testcase "Dura_Queue" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 3 Dura Queue Sync
+run_testcase "Dura_Queue_Sync" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent"
+
+# Test 4 Dura Queue Sync Publish and Ack
+run_testcase "Dura_SyncPubAck" "-Daddress=$DURA_QUEUE -Ddurable=true -Dsync_ack=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_publish=persistent"
+
+# Test 5 Topic
+run_testcase "Topic" "-Daddress=$TOPIC" "-Daddress=$TOPIC -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 6 Durable Topic
+run_testcase "Dura_Topic" "-Daddress=$DURA_TOPIC -Ddurable=true" "-Daddress=$DURA_TOPIC -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 7 Fanout
+run_testcase "Fanout" "-Daddress=amq.fanout" "-Daddress=amq.fanout -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 8 Small TX
+run_testcase "Small_Txs_2" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=1" \
+ "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=1"
+
+# Test 9 Large TX
+run_testcase "Large_Txs_1000" "-Daddress=$DURA_QUEUE -Ddurable=true -Dtransacted=true -Dtrans_size=10" \
+ "-Daddress=$DURA_QUEUE -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=10"
+
+# Test 10 256 MSG
+run_testcase "Msg_256b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=256 -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 11 512 MSG
+run_testcase "Msg_512b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=512 -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 12 2048 MSG
+run_testcase "Msg_2048b" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Dmsg_size=2048 -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 13 Random size MSG
+run_testcase "Random_Msg_Size" "-Daddress=$QUEUE" "-Daddress=$QUEUE -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 14 Random size MSG Durable
+run_testcase "Rand_Msg_Dura" "-Daddress=$DURA_QUEUE -Ddurable=true" "-Daddress=$DURA_QUEUE -Ddurable=true -Drandom_msg_size=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 15 64K MSG
+run_testcase "Msg_64K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 16 Durable 64K MSG
+run_testcase "Msg_Durable_64K" "-Daddress=$DURA_QUEUE -Ddurable=true -Damqj.tcpNoDelay=true" \
+ "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=64000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 17 500K MSG
+run_testcase "Msg_500K" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true" "-Daddress=$QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 18 Durable 500K MSG
+run_testcase "Msg_Dura_500K" "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Ddurable=true" \
+ "-Daddress=$DURA_QUEUE -Damqj.tcpNoDelay=true -Dmsg_size=500000 -Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
diff --git a/java/tools/bin/qpid-bench b/java/tools/bin/qpid-bench
index cd894b607f..c982e64efd 100755..100644
--- a/java/tools/bin/qpid-bench
+++ b/java/tools/bin/qpid-bench
@@ -18,6 +18,18 @@
# under the License.
#
-. check-qpid-java-env
+if [ -z "$QPID_HOME" ]; then
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
+fi
-$JAVA -cp $CLASSPATH -server $JAVA_MEM $LOG_CONFIG org.apache.qpid.tools.QpidBench "$@"
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-all.jar
+
+# Set other variables used by the qpid-run script before calling
+export JAVA=java \
+ JAVA_VM=-server \
+ JAVA_MEM=-Xmx1024m \
+ QPID_CLASSPATH=$QPID_LIBS
+
+. qpid-run org.apache.qpid.tools.QpidBench "$@"
diff --git a/java/tools/bin/qpid-python-testkit b/java/tools/bin/qpid-python-testkit
index 7233d0d075..cbe7972421 100755
--- a/java/tools/bin/qpid-python-testkit
+++ b/java/tools/bin/qpid-python-testkit
@@ -22,12 +22,9 @@
# via the python test runner. The defaults are set for a running
# from an svn checkout
-. check-qpid-java-env
+. ./set-testkit-env.sh
export PYTHONPATH=./:$PYTHONPATH
-echo $PYTHONPATH
-if [ "$OUTDIR" = "" ] ; then
- OUTDIR=$PWD
-fi
-testdir=$OUTDIR/testkit-out-`date +%F-%H-%M-%S`
-qpid-python-test -m testkit -DOUTDIR=$testdir"$@"
+rm -rf $OUTDIR
+qpid-python-test -DOUTDIR=$OUTDIR -m testkit "$@"
+
diff --git a/java/tools/bin/run-pub b/java/tools/bin/run-pub
deleted file mode 100755
index 9efe58c4b8..0000000000
--- a/java/tools/bin/run-pub
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-. check-qpid-java-env
-
-JVM_ARGS="$1"
-PROGRAM_ARGS="$2"
-
-echo "JVM ARGS : $JAVA_MEM $JVM_ARGS"
-echo "PROGRAM ARGS : $PROGRAM_ARGS"
-$JAVA -cp $CLASSPATH $LOG_CONFIG $JAVA_MEM $JVM_ARGS org.apache.qpid.tools.PerfProducer $PROGRAM_ARGS
diff --git a/java/tools/bin/run-sub b/java/tools/bin/run-sub
deleted file mode 100755
index 8449563f7f..0000000000
--- a/java/tools/bin/run-sub
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-. check-qpid-java-env
-
-echo "All args $@"
-
-JVM_ARGS="$1"
-PROGRAM_ARGS="$2"
-
-echo "JVM ARGS : $JAVA_MEM $JVM_ARGS"
-echo "PROGRAM ARGS : $PROGRAM_ARGS"
-
-$JAVA -cp $CLASSPATH $LOG_CONFIG $JAVA_MEM $JVM_ARGS org.apache.qpid.tools.PerfConsumer $PROGRAM_ARGS
-
diff --git a/java/tools/bin/run_pub.sh b/java/tools/bin/run_pub.sh
new file mode 100644
index 0000000000..91b9287dea
--- /dev/null
+++ b/java/tools/bin/run_pub.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+. $QPID_TEST_HOME/bin/setenv.sh
+
+echo "$@"
+$JAVA_HOME/bin/java -cp $CLASSPATH $@ org.apache.qpid.tools.PerfProducer
diff --git a/java/tools/bin/run_sub.sh b/java/tools/bin/run_sub.sh
new file mode 100644
index 0000000000..c9ad2fed74
--- /dev/null
+++ b/java/tools/bin/run_sub.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+. $QPID_TEST_HOME/bin/setenv.sh
+
+echo "$@"
+$JAVA_HOME/bin/java -cp $CLASSPATH $@ org.apache.qpid.tools.PerfConsumer
+
diff --git a/java/tools/bin/set-testkit-env.sh b/java/tools/bin/set-testkit-env.sh
new file mode 100644
index 0000000000..051dad8179
--- /dev/null
+++ b/java/tools/bin/set-testkit-env.sh
@@ -0,0 +1,88 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# If QPIDD_EXEC ..etc is not set, it will first check to see
+# if this is run from a qpid svn check out, if not it will look
+# for installed rpms.
+
+abs_path()
+{
+ D=`dirname "$1"`
+ B=`basename "$1"`
+ echo "`cd \"$D\" 2>/dev/null && pwd || echo \"$D\"`/$B"
+}
+
+# Environment for python tests
+
+if [ -d ../../../python ] ; then
+ PYTHON_DIR=../../../python
+ PYTHONPATH=$PYTHON_DIR:$PYTHON_DIR/qpid
+elif [ -z `echo $PYTHONPATH | awk '$0 ~ /qpid/'` ]; then
+ echo "WARNING: skipping test, no qpid python scripts found ."; exit 0;
+fi
+
+
+if [ "$QPIDD_EXEC" = "" ] ; then
+ if [ -x ../../../cpp/src/qpidd ]; then
+ QPIDD_EXEC=`abs_path "../../../cpp/src/qpidd"`
+ elif [ -n "$(which qpidd)" ] ; then
+ QPIDD_EXEC=$(which qpidd)
+ else
+ echo "WARNING: skipping test, QPIDD_EXEC not set and qpidd not found."; exit 0;
+ fi
+fi
+
+if [ "$CLUSTER_LIB" = "" ] ; then
+ if [ -x ../../../cpp/src/.libs/cluster.so ]; then
+ CLUSTER_LIB=`abs_path "../../../cpp/src/.libs/cluster.so"`
+ elif [ -e /usr/lib64/qpid/daemon/cluster.so ] ; then
+ CLUSTER_LIB="/usr/lib64/qpid/daemon/cluster.so"
+ elif [ -e /usr/lib/qpid/daemon/cluster.so ] ; then
+ CLUSTER_LIB="/usr/lib/qpid/daemon/cluster.so"
+ else
+ echo "WARNING: skipping test, CLUSTER_LIB not set and cluster.so not found."; exit 0;
+ fi
+fi
+
+if [ "$STORE_LIB" = "" ] ; then
+ if [ -e /usr/lib64/qpid/daemon/msgstore.so ] ; then
+ STORE_LIB="/usr/lib64/qpid/daemon/msgstore.so"
+ elif [ -e /usr/lib/qpid/daemon/msgstore.so ] ; then
+ STORE_LIB="/usr/lib/qpid/daemon/msgstore.so"
+ #else
+ # echo "WARNING: skipping test, STORE_LIB not set and msgstore.so not found."; exit 0;
+ fi
+fi
+
+if [ "$QP_CP" = "" ] ; then
+ if [ -d ../../build/lib/ ]; then
+ QP_JAR_PATH=`abs_path "../../build/lib/"`
+ elif [ -d /usr/share/java/qpid-deps ]; then
+ QP_JAR_PATH=`abs_path "/usr/share/java"`
+ else
+ "WARNING: skipping test, QP_CP not set and the Qpid jars are not present."; exit 0;
+ fi
+ QP_CP=`find $QP_JAR_PATH -name '*.jar' | tr '\n' ':'`
+fi
+
+if [ "$OUTDIR" = "" ] ; then
+ OUTDIR=`abs_path "./output"`
+fi
+
+export PYTHONPATH PYTHON_DIR QPIDD_EXEC CLUSTER_LIB QP_CP OUTDIR
diff --git a/java/tools/bin/setenv.sh b/java/tools/bin/setenv.sh
new file mode 100644
index 0000000000..24135e711b
--- /dev/null
+++ b/java/tools/bin/setenv.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Compiles the test classes and sets the CLASSPATH
+
+# check for QPID_TEST_HOME
+if [ "$QPID_TEST_HOME" = "" ] ; then
+ echo "ERROR: Please set QPID_TEST_HOME ...."
+ exit 1
+fi
+
+# check for JAVA_HOME
+if [ "$JAVA_HOME" = "" ] ; then
+ echo "ERROR: Please set JAVA_HOME ...."
+ exit 1
+fi
+
+# VENDOR_LIB path needs to be set
+# for Qpid set this to {qpid_checkout}/java/build/lib
+if [ "$VENDOR_LIB" = "" ] ; then
+ echo "ERROR: Please set VENDOR_LIB path in the script ...."
+ exit 1
+fi
+
+
+[ -d $QPID_TEST_HOME/classes ] || mkdir $QPID_TEST_HOME/classes
+
+CLASSPATH=`find $VENDOR_LIB -name *.jar* | tr '\n' ":"`
+$JAVA_HOME/bin/javac -cp $CLASSPATH -d $QPID_TEST_HOME/classes -sourcepath $QPID_TEST_HOME/src `find $QPID_TEST_HOME/src -name '*.java'`
+
+export CLASSPATH=$QPID_TEST_HOME/classes:$CLASSPATH
+
diff --git a/java/tools/bin/start-consumers b/java/tools/bin/start-consumers
deleted file mode 100644
index c71fc0c21f..0000000000
--- a/java/tools/bin/start-consumers
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# This starts the controller for coordinating perf tests/
-
-. check-qpid-java-env
-
-PROGRAM_NAME="start-consumers"
-PROCESS_COUNT=1
-CON_COUNT=1
-MSG_COUNT=10000
-ADDRESS="queue;{create:always}"
-UNIQUE_DEST="false"
-
-EXTRA_JVM_ARGS=" -Dmax_prefetch=500 "
-
-TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'`
-
-TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\
- --long connection-count:,process-count:,create-unique-queues-topics,\
-jvm-args:,queue:,topic:,address:,\
-msg-count:,help -- "$@")
-
-usage()
-{
- printf "\n%s\n" "Usage: start-producers [option].."
-
- printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test"
-
- printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test"
-
- printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic"
-
- printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue"
-
- printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic"
-
- printf "\n%13s\n%44s\n" "--address" "The address you want to publish to"
-
- printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)"
-
- printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify"
-}
-
-eval set -- "$TEMP"
-while true; do
- case $1 in
- -C|--connection-count)
- CON_COUNT="$2"; shift; shift; continue
- ;;
- -P|--process-count)
- PROCESS_COUNT="$2"; shift; shift; continue
- ;;
- -u|--create-unique-queues-topics)
- UNIQUE_DEST="true"; shift; continue
- ;;
- --queue)
- ADDRESS="$2;{create: always}"; shift; shift; continue
- ;;
- --topic)
- ADDRESS="amq.topic/$2"; shift; shift; continue
- ;;
- --address)
- ADDRESS="$2"; shift; shift; continue
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -a|--jvm-args)
- EXTRA_JVM_ARGS="$2"; shift; shift; continue
- ;;
- -c|--msg-count)
- MSG_COUNT="$2"; shift; shift; continue
- ;;
- --)
- # no more arguments to parse
- break
- ;;
- *)
- # no more arguments to parse
- break
- ;;
- esac
-done
-
-CONSUMER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dprecision=mili -Dcon_count=$CON_COUNT -Dprint_std_dev=true"
-
-start_consumers()
-{
- for ((i=0; i<$PROCESS_COUNT; i++))
- do
- if [ "$UNIQUE_DEST" = "true" ]; then
- sh run-sub "$CONSUMER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.sub.out 2>&1 &
- else
- sh run-sub "$CONSUMER_ARGS $@" > ${TEST_ID}_$i.sub.out 2>&1 &
- fi
- done
-}
-
-start_consumers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS"
-
diff --git a/java/tools/bin/start-producers b/java/tools/bin/start-producers
deleted file mode 100644
index 7ba0286f7c..0000000000
--- a/java/tools/bin/start-producers
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# This starts the controller for coordinating perf tests/
-
-. check-qpid-java-env
-
-PROGRAM_NAME="start-producers"
-PROCESS_COUNT=1
-CON_COUNT=1
-MSG_TYPE="bytes"
-WARMUP_MSG_COUNT=1000
-MSG_COUNT=10000
-MSG_SIZE=1024
-ADDRESS="queue;{create:always}"
-UNIQUE_DEST="false"
-
-EXTRA_JVM_ARGS=""
-TEST_ID=`echo ${HOSTNAME} | awk -F . '{print $1}'`
-
-TEMP=$(getopt -n $PROGRAM_NAME -o C:P:uc:p:a:s:t:w:h\
- --long connection-count:,process-count:,create-unique-queues-topics,\
-jvm-args:,queue:,topic:,address:,\
-msg-count:,msg-size:msg-type:,warmup-msg-count,help -- "$@")
-
-usage()
-{
- printf "\n%s\n" "Usage: start-producers [option].."
-
- printf "\n%32s\n%51s\n" "-C, --connection-count=count" "No of consumers participating in the test"
-
- printf "\n%29s\n%51s\n" "-P, --process-count=count" "No of producers participating in the test"
-
- printf "\n%37s\n%105s\n" "-u, --create-unique-queues-topics" "This will create unique queue names and topics based on what you specify for --queue or --topic"
-
- printf "\n%11s\n%55s\n" "--queue" "The Queue you want to publish to. Ex my-queue"
-
- printf "\n%11s\n%84s\n" "--topic" "The Topic you want to publish to in amq.topic exchange. Ex amq.topic/topic"
-
- printf "\n%13s\n%44s\n" "--address" "The address you want to publish to"
-
- printf "\n%23s\n%37s\n" "-s, --msg-size=size" "message size (default 1024)"
-
- printf "\n%25s\n%50s\n" "-c, --msg-count=count" "message count per test (default 500,000)"
-
- printf "\n%18s\n%38s\n" "-t, --msg-type" "{bytes|text} (default bytes)"
-
- printf "\n%26s\n%49s\n" "-w, --warmup-msg-count" "warm up message count (default 100,000)"
-
- printf "\n%18s\n%49s\n" "-a, --jvm-args" "Extra jvm arguments you want to specify"
-}
-
-eval set -- "$TEMP"
-while true; do
- case $1 in
- -C|--connection-count)
- CON_COUNT="$2"; shift; shift; continue
- ;;
- -P|--process-count)
- PROCESS_COUNT="$2"; shift; shift; continue
- ;;
- -u|--create-unique-queues-topics)
- UNIQUE_DEST="true"; shift; continue
- ;;
- --queue)
- ADDRESS="$2;{create: always}"; shift; shift; continue
- ;;
- --topic)
- ADDRESS="amq.topic/$2"; shift; shift; continue
- ;;
- --address)
- ADDRESS="$2"; shift; shift; continue
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -a|--jvm-args)
- EXTRA_JVM_ARGS="$2"; shift; shift; continue
- ;;
- -s|--msg-size)
- MSG_SIZE="$2"; shift; shift; continue
- ;;
- -c|--msg-count)
- MSG_COUNT="$2"; shift; shift; continue
- ;;
- -t|--msg_type)
- MSG_TYPE="$2"; shift; shift; continue
- ;;
- -w|--warmup-msg-count)
- WARMUP_MSG_COUNT="$2"; shift; shift; continue
- ;;
- --)
- # no more arguments to parse
- break
- ;;
- *)
- # no more arguments to parse
- break
- ;;
- esac
-done
-
-PRODUCER_ARGS="-server -Durl=amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672' -Dext_controller=true -Dprecision=mili -Dcon_count=$CON_COUNT"
-
-start_producers()
-{
- for ((i=0; i<$PROCESS_COUNT; i++))
- do
- if [ "$UNIQUE_DEST" = "true" ]; then
- sh run-pub "$PRODUCER_ARGS $@" "${TEST_ID}_$i" > ${TEST_ID}_$i.pub.out 2>&1 &
- else
- sh run-pub "$PRODUCER_ARGS $@" > ${TEST_ID}_$i.pub.out 2>&1 &
- fi
- done
-}
-
-start_producers "-Daddress=$ADDRESS -Duse_unique_dest=$UNIQUE_DEST -Dmsg_count=$MSG_COUNT -Dmsg_size=$MSG_SIZE -Dwarmup_count=$WARMUP_MSG_COUNT -Dmsg_type=$MSG_TYPE -Dcon_count=$CON_COUNT $EXTRA_JVM_ARGS"
-
diff --git a/java/tools/etc/perf-report.gnu b/java/tools/etc/perf-report.gnu
deleted file mode 100644
index 6d5020efb5..0000000000
--- a/java/tools/etc/perf-report.gnu
+++ /dev/null
@@ -1,42 +0,0 @@
-set terminal png
-set datafile separator ","
-
-set title "Variation of avg latency between iterations"
-set yrange [10:20]
-set xlabel "Iterations"
-set ylabel "Latency (ms)"
-set output "avg_latency.png"
-plot "stats-csv.log" using 9 title "avg latency" with lines, 14 title "target latency" with lines
-
-
-set title "Variation of max latency between iterations"
-set yrange [0:1000]
-set xlabel "Iterations"
-set ylabel "Latency (ms)"
-set output "max_latency.png"
-plot "stats-csv.log" using 11 title "max latency" with lines,14 title "target latency" with lines,100 title "100 ms" with lines
-
-
-set title "Variation of standard deviation of latency between iterations"
-set yrange [0:20]
-set xlabel "Iterations"
-set ylabel "Standard Deviation"
-set output "std_dev_latency.png"
-plot "stats-csv.log" using 12 title "standard deviation" with lines
-
-
-set title "Variation of system throughput between iterations"
-set yrange [400000:450000]
-set xlabel "Iterations"
-set ylabel "System Throuhgput (msg/sec)"
-set output "system_rate.png"
-plot "stats-csv.log" using 2 title "system throughput" with lines
-
-
-set title "Variation of avg producer & consumer rates between iterations"
-set yrange [6500:7500]
-set xlabel "Iterations"
-set ylabel "Avg Rates (msg/sec)"
-set output "prod_cons_rate.png"
-plot "stats-csv.log" using 6 title "producer rate" with lines,"stats-csv.log" using 3 title "consumer rate" with lines
-
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/Clock.java b/java/tools/src/main/java/org/apache/qpid/tools/Clock.java
deleted file mode 100644
index 37369959a8..0000000000
--- a/java/tools/src/main/java/org/apache/qpid/tools/Clock.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.apache.qpid.tools;
-
-/**
- * In the future this will be replaced by a Clock abstraction
- * that can utilize a realtime clock when running in RT Java.
- */
-
-public class Clock
-{
- private static Precision precision;
- private static long offset = -1; // in nano secs
-
- public enum Precision
- {
- NANO_SECS, MILI_SECS;
-
- static Precision getPrecision(String str)
- {
- if ("mili".equalsIgnoreCase(str))
- {
- return MILI_SECS;
- }
- else
- {
- return NANO_SECS;
- }
- }
- };
-
- static
- {
- precision = Precision.getPrecision(System.getProperty("precision","mili"));
- //offset = Long.getLong("offset",-1);
-
- System.out.println("Using precision : " + precision + " and offset " + offset);
- }
-
- public static Precision getPrecision()
- {
- return precision;
- }
-
- public static long getTime()
- {
- if (precision == Precision.NANO_SECS)
- {
- if (offset == -1)
- {
- return System.nanoTime();
- }
- else
- {
- return System.nanoTime() + offset;
- }
- }
- else
- {
- if (offset == -1)
- {
- return System.currentTimeMillis();
- }
- else
- {
- return System.currentTimeMillis() + offset/convertToMiliSecs();
- }
- }
- }
-
- public static long convertToSecs()
- {
- if (precision == Precision.NANO_SECS)
- {
- return 1000000000;
- }
- else
- {
- return 1000;
- }
- }
-
- public static long convertToMiliSecs()
- {
- if (precision == Precision.NANO_SECS)
- {
- return 1000000;
- }
- else
- {
- return 1;
- }
- }
-}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java b/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java
index 90ee7e28ae..b88b242e6d 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/LatencyTest.java
@@ -77,7 +77,7 @@ public class LatencyTest extends PerfBase implements MessageListener
public LatencyTest()
{
- super("");
+ super();
warmedUp = lock.newCondition();
testCompleted = lock.newCondition();
// Storing the following two for efficiency
@@ -314,7 +314,7 @@ public class LatencyTest extends PerfBase implements MessageListener
public static void main(String[] args)
{
- final LatencyTest latencyTest = new LatencyTest();
+ final LatencyTest latencyTest = new LatencyTest();
Runnable r = new Runnable()
{
public void run()
@@ -334,16 +334,16 @@ public class LatencyTest extends PerfBase implements MessageListener
}
}
};
-
+
Thread t;
try
{
- t = Threading.getThreadFactory().createThread(r);
+ t = Threading.getThreadFactory().createThread(r);
}
catch(Exception e)
{
throw new Error("Error creating latency test thread",e);
}
- t.start();
+ t.start();
}
-}
+} \ No newline at end of file
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java
index 121e94cea1..ac597d17de 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/PerfBase.java
@@ -20,113 +20,36 @@
*/
package org.apache.qpid.tools;
-import java.net.InetAddress;
import java.text.DecimalFormat;
-import java.util.UUID;
+import java.util.Hashtable;
import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
import javax.jms.Destination;
-import javax.jms.MapMessage;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
import javax.jms.Session;
+import javax.naming.Context;
+import javax.naming.InitialContext;
import org.apache.qpid.client.AMQAnyDestination;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession_0_10;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.messaging.Address;
public class PerfBase
{
- public final static String CODE = "CODE";
- public final static String ID = "ID";
- public final static String REPLY_ADDR = "REPLY_ADDR";
- public final static String MAX_LATENCY = "MAX_LATENCY";
- public final static String MIN_LATENCY = "MIN_LATENCY";
- public final static String AVG_LATENCY = "AVG_LATENCY";
- public final static String STD_DEV = "STD_DEV";
- public final static String CONS_RATE = "CONS_RATE";
- public final static String PROD_RATE = "PROD_RATE";
- public final static String MSG_COUNT = "MSG_COUNT";
- public final static String TIMESTAMP = "Timestamp";
-
- String CONTROLLER_ADDR = System.getProperty("CONT_ADDR","CONTROLLER;{create: always, node:{x-declare:{auto-delete:true}}}");
-
TestParams params;
Connection con;
Session session;
- Session controllerSession;
Destination dest;
- Destination myControlQueue;
- Destination controllerQueue;
+ Destination feedbackDest;
DecimalFormat df = new DecimalFormat("###.##");
- String id;
- String myControlQueueAddr;
-
- MessageProducer sendToController;
- MessageConsumer receiveFromController;
- String prefix = "";
- enum OPCode {
- REGISTER_CONSUMER, REGISTER_PRODUCER,
- PRODUCER_STARTWARMUP, CONSUMER_STARTWARMUP,
- CONSUMER_READY, PRODUCER_READY,
- PRODUCER_START,
- RECEIVED_END_MSG, CONSUMER_STOP,
- RECEIVED_PRODUCER_STATS, RECEIVED_CONSUMER_STATS,
- CONTINUE_TEST, STOP_TEST
- };
-
- enum MessageType {
- BYTES, TEXT, MAP, OBJECT;
-
- public static MessageType getType(String s) throws Exception
- {
- if ("text".equalsIgnoreCase(s))
- {
- return TEXT;
- }
- else if ("bytes".equalsIgnoreCase(s))
- {
- return BYTES;
- }
- /*else if ("map".equalsIgnoreCase(s))
- {
- return MAP;
- }
- else if ("object".equalsIgnoreCase(s))
- {
- return OBJECT;
- }*/
- else
- {
- throw new Exception("Unsupported message type");
- }
- }
- };
-
- MessageType msgType = MessageType.BYTES;
-
- public PerfBase(String prefix)
+ public PerfBase()
{
params = new TestParams();
- String host = "";
- try
- {
- host = InetAddress.getLocalHost().getHostName();
- }
- catch (Exception e)
- {
- }
- id = host + "-" + UUID.randomUUID().toString();
- this.prefix = prefix;
- this.myControlQueueAddr = id + ";{create: always}";
}
public void setUp() throws Exception
- {
+ {
+
if (params.getHost().equals("") || params.getPort() == -1)
{
con = new AMQConnection(params.getUrl());
@@ -139,78 +62,7 @@ public class PerfBase
session = con.createSession(params.isTransacted(),
params.isTransacted()? Session.SESSION_TRANSACTED:params.getAckMode());
- controllerSession = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- dest = createDestination();
- controllerQueue = new AMQAnyDestination(CONTROLLER_ADDR);
- myControlQueue = session.createQueue(myControlQueueAddr);
- msgType = MessageType.getType(params.getMessageType());
- System.out.println("Using " + msgType + " messages");
-
- sendToController = controllerSession.createProducer(controllerQueue);
- receiveFromController = controllerSession.createConsumer(myControlQueue);
- }
-
- private Destination createDestination() throws Exception
- {
- if (params.isUseUniqueDests())
- {
- System.out.println("Prefix : " + prefix);
- Address addr = Address.parse(params.getAddress());
- AMQAnyDestination temp = new AMQAnyDestination(params.getAddress());
- int type = ((AMQSession_0_10)session).resolveAddressType(temp);
-
- if ( type == AMQDestination.TOPIC_TYPE)
- {
- addr = new Address(addr.getName(),addr.getSubject() + "." + prefix,addr.getOptions());
- System.out.println("Setting subject : " + addr);
- }
- else
- {
- addr = new Address(addr.getName() + "_" + prefix,addr.getSubject(),addr.getOptions());
- System.out.println("Setting name : " + addr);
- }
-
- return new AMQAnyDestination(addr);
- }
- else
- {
- return new AMQAnyDestination(params.getAddress());
- }
- }
-
- public synchronized void sendMessageToController(MapMessage m) throws Exception
- {
- m.setString(ID, id);
- m.setString(REPLY_ADDR,myControlQueueAddr);
- sendToController.send(m);
- }
-
- public void receiveFromController(OPCode expected) throws Exception
- {
- MapMessage m = (MapMessage)receiveFromController.receive();
- OPCode code = OPCode.values()[m.getInt(CODE)];
- System.out.println("Received Code : " + code);
- if (expected != code)
- {
- throw new Exception("Expected OPCode : " + expected + " but received : " + code);
- }
-
- }
-
- public boolean continueTest() throws Exception
- {
- MapMessage m = (MapMessage)receiveFromController.receive();
- OPCode code = OPCode.values()[m.getInt(CODE)];
- System.out.println("Received Code : " + code);
- return (code == OPCode.CONTINUE_TEST);
- }
-
- public void tearDown() throws Exception
- {
- session.close();
- controllerSession.close();
- con.close();
+ dest = new AMQAnyDestination(params.getAddress());
}
public void handleError(Exception e,String msg)
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java
index b63892bb51..0ef0455a64 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/PerfConsumer.java
@@ -20,17 +20,13 @@
*/
package org.apache.qpid.tools;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-import javax.jms.MapMessage;
+import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
import javax.jms.TextMessage;
-import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.thread.Threading;
/**
@@ -51,7 +47,7 @@ import org.apache.qpid.thread.Threading;
* b) They are on separate machines that have their time synced via a Time Server
*
* In order to calculate latency the producer inserts a timestamp
- * when the message is sent. The consumer will note the current time the message is
+ * hen the message is sent. The consumer will note the current time the message is
* received and will calculate the latency as follows
* latency = rcvdTime - msg.getJMSTimestamp()
*
@@ -59,9 +55,13 @@ import org.apache.qpid.thread.Threading;
* variance in latencies.
*
* Avg latency is measured by adding all latencies and dividing by the total msgs.
+ * You can also compute this by (rcvdTime - testStartTime)/rcvdMsgCount
*
* Throughput
* ===========
+ * System throughput is calculated as follows
+ * rcvdMsgCount/(rcvdTime - testStartTime)
+ *
* Consumer rate is calculated as
* rcvdMsgCount/(rcvdTime - startTime)
*
@@ -81,160 +81,130 @@ public class PerfConsumer extends PerfBase implements MessageListener
long minLatency = Long.MAX_VALUE;
long totalLatency = 0; // to calculate avg latency.
int rcvdMsgCount = 0;
+ long testStartTime = 0; // to measure system throughput
long startTime = 0; // to measure consumer throughput
long rcvdTime = 0;
boolean transacted = false;
int transSize = 0;
- boolean printStdDev = false;
- List<Long> sample;
-
final Object lock = new Object();
- public PerfConsumer(String prefix)
+ public PerfConsumer()
{
- super(prefix);
- System.out.println("Consumer ID : " + id);
+ super();
}
public void setUp() throws Exception
{
super.setUp();
consumer = session.createConsumer(dest);
- System.out.println("Consumer: " + id + " Receiving messages from : " + ((AMQDestination)dest).getQueueName() + "\n");
// Storing the following two for efficiency
transacted = params.isTransacted();
transSize = params.getTransactionSize();
- printStdDev = params.isPrintStdDev();
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.REGISTER_CONSUMER.ordinal());
- sendMessageToController(m);
}
public void warmup()throws Exception
{
- receiveFromController(OPCode.CONSUMER_STARTWARMUP);
- Message msg = consumer.receive();
- // This is to ensure we drain the queue before we start the actual test.
- while ( msg != null)
+ System.out.println("Warming up......");
+
+ boolean start = false;
+ while (!start)
{
- if (msg.getBooleanProperty("End") == true)
+ Message msg = consumer.receive();
+ if (msg instanceof TextMessage)
{
- // It's more realistic for the consumer to signal this.
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.PRODUCER_READY.ordinal());
- sendMessageToController(m);
+ if (((TextMessage)msg).getText().equals("End"))
+ {
+ start = true;
+ MessageProducer temp = session.createProducer(msg.getJMSReplyTo());
+ temp.send(session.createMessage());
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+ temp.close();
+ }
}
- msg = consumer.receive(1000);
- }
-
- if (params.isTransacted())
- {
- session.commit();
}
-
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.CONSUMER_READY.ordinal());
- sendMessageToController(m);
- consumer.setMessageListener(this);
}
public void startTest() throws Exception
{
- System.out.println("Consumer: " + id + " Starting test......" + "\n");
- resetCounters();
+ System.out.println("Starting test......");
+ consumer.setMessageListener(this);
}
- public void resetCounters()
+ public void printResults() throws Exception
{
- rcvdMsgCount = 0;
- maxLatency = 0;
- minLatency = Long.MAX_VALUE;
- totalLatency = 0;
- if (printStdDev)
+ synchronized (lock)
{
- sample = null;
- sample = new ArrayList<Long>(params.getMsgCount());
+ lock.wait();
}
- }
-
- public void sendResults() throws Exception
- {
- receiveFromController(OPCode.CONSUMER_STOP);
double avgLatency = (double)totalLatency/(double)rcvdMsgCount;
- double consRate = (double)rcvdMsgCount*Clock.convertToSecs()/(double)(rcvdTime - startTime);
- double stdDev = 0.0;
- if (printStdDev)
- {
- stdDev = calculateStdDev(avgLatency);
- }
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.RECEIVED_CONSUMER_STATS.ordinal());
- m.setDouble(AVG_LATENCY, avgLatency/Clock.convertToMiliSecs());
- m.setDouble(MIN_LATENCY,minLatency/Clock.convertToMiliSecs());
- m.setDouble(MAX_LATENCY,maxLatency/Clock.convertToMiliSecs());
- m.setDouble(STD_DEV, stdDev/Clock.convertToMiliSecs());
- m.setDouble(CONS_RATE, consRate);
- m.setLong(MSG_COUNT, rcvdMsgCount);
- sendMessageToController(m);
-
+ double throughput = ((double)rcvdMsgCount/(double)(rcvdTime - testStartTime))*1000;
+ double consRate = ((double)rcvdMsgCount/(double)(rcvdTime - startTime))*1000;
System.out.println(new StringBuilder("Total Msgs Received : ").append(rcvdMsgCount).toString());
System.out.println(new StringBuilder("Consumer rate : ").
append(df.format(consRate)).
append(" msg/sec").toString());
+ System.out.println(new StringBuilder("System Throughput : ").
+ append(df.format(throughput)).
+ append(" msg/sec").toString());
System.out.println(new StringBuilder("Avg Latency : ").
- append(df.format(avgLatency/Clock.convertToMiliSecs())).
+ append(df.format(avgLatency)).
append(" ms").toString());
System.out.println(new StringBuilder("Min Latency : ").
- append(df.format(minLatency/Clock.convertToMiliSecs())).
+ append(minLatency).
append(" ms").toString());
System.out.println(new StringBuilder("Max Latency : ").
- append(df.format(maxLatency/Clock.convertToMiliSecs())).
+ append(maxLatency).
append(" ms").toString());
- if (printStdDev)
- {
- System.out.println(new StringBuilder("Std Dev : ").
- append(stdDev/Clock.convertToMiliSecs()).toString());
- }
+ System.out.println("Completed the test......\n");
}
- public double calculateStdDev(double mean)
+ public void notifyCompletion(Destination replyTo) throws Exception
{
- double v = 0;
- for (double latency: sample)
+ MessageProducer tmp = session.createProducer(replyTo);
+ Message endMsg = session.createMessage();
+ tmp.send(endMsg);
+ if (params.isTransacted())
{
- v = v + Math.pow((latency-mean), 2);
+ session.commit();
}
- v = v/sample.size();
- return Math.round(Math.sqrt(v));
+ tmp.close();
+ }
+
+ public void tearDown() throws Exception
+ {
+ consumer.close();
+ session.close();
+ con.close();
}
public void onMessage(Message msg)
{
try
{
- // To figure out the decoding overhead of text
- if (msgType == MessageType.TEXT)
+ if (msg instanceof TextMessage && ((TextMessage)msg).getText().equals("End"))
{
- ((TextMessage)msg).getText();
- }
+ notifyCompletion(msg.getJMSReplyTo());
- if (msg.getBooleanProperty("End"))
- {
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.RECEIVED_END_MSG.ordinal());
- sendMessageToController(m);
+ synchronized (lock)
+ {
+ lock.notifyAll();
+ }
}
else
{
- rcvdTime = Clock.getTime();
+ rcvdTime = System.currentTimeMillis();
rcvdMsgCount ++;
if (rcvdMsgCount == 1)
{
startTime = rcvdTime;
+ testStartTime = msg.getJMSTimestamp();
}
if (transacted && (rcvdMsgCount % transSize == 0))
@@ -242,14 +212,10 @@ public class PerfConsumer extends PerfBase implements MessageListener
session.commit();
}
- long latency = rcvdTime - msg.getLongProperty(TIMESTAMP);
+ long latency = rcvdTime - msg.getJMSTimestamp();
maxLatency = Math.max(maxLatency, latency);
minLatency = Math.min(minLatency, latency);
totalLatency = totalLatency + latency;
- if (printStdDev)
- {
- sample.add(latency);
- }
}
}
@@ -260,21 +226,14 @@ public class PerfConsumer extends PerfBase implements MessageListener
}
- public void run()
+ public void test()
{
try
{
setUp();
warmup();
- boolean nextIteration = true;
- while (nextIteration)
- {
- System.out.println("=========================================================\n");
- System.out.println("Consumer: " + id + " starting a new iteration ......\n");
- startTest();
- sendResults();
- nextIteration = continueTest();
- }
+ startTest();
+ printResults();
tearDown();
}
catch(Exception e)
@@ -283,43 +242,26 @@ public class PerfConsumer extends PerfBase implements MessageListener
}
}
- @Override
- public void tearDown() throws Exception
- {
- super.tearDown();
- }
-
- public static void main(String[] args) throws InterruptedException
+ public static void main(String[] args)
{
- String scriptId = (args.length == 1) ? args[0] : "";
- int conCount = Integer.getInteger("con_count",1);
- final CountDownLatch testCompleted = new CountDownLatch(conCount);
- for (int i=0; i < conCount; i++)
+ final PerfConsumer cons = new PerfConsumer();
+ Runnable r = new Runnable()
{
-
- final PerfConsumer cons = new PerfConsumer(scriptId + i);
- Runnable r = new Runnable()
- {
- public void run()
- {
- cons.run();
- testCompleted.countDown();
- }
- };
-
- Thread t;
- try
- {
- t = Threading.getThreadFactory().createThread(r);
- }
- catch(Exception e)
+ public void run()
{
- throw new Error("Error creating consumer thread",e);
+ cons.test();
}
- t.start();
-
+ };
+
+ Thread t;
+ try
+ {
+ t = Threading.getThreadFactory().createThread(r);
+ }
+ catch(Exception e)
+ {
+ throw new Error("Error creating consumer thread",e);
}
- testCompleted.await();
- System.out.println("Consumers have completed the test......\n");
+ t.start();
}
} \ No newline at end of file
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java
index ac6129ab68..015d1e6205 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/PerfProducer.java
@@ -23,15 +23,13 @@ package org.apache.qpid.tools;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
-import java.util.concurrent.CountDownLatch;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
-import javax.jms.MapMessage;
import javax.jms.Message;
+import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
-import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.thread.Threading;
/**
@@ -53,52 +51,38 @@ import org.apache.qpid.thread.Threading;
* System throughput and latencies calculated by the PerfConsumer are more realistic
* numbers.
*
- * Answer by rajith : I agree about in memory buffering affecting rates. But Based on test runs
- * I have done so far, it seems quite useful to compute the producer rate as it gives an
- * indication of how the system behaves. For ex if there is a gap between producer and consumer rates
- * you could clearly see the higher latencies and when producer and consumer rates are very close,
- * latency is good.
- *
*/
public class PerfProducer extends PerfBase
{
- private static long SEC = 60000;
-
MessageProducer producer;
Message msg;
- Object payload;
- List<Object> payloads;
+ byte[] payload;
+ List<byte[]> payloads;
boolean cacheMsg = false;
boolean randomMsgSize = false;
boolean durable = false;
Random random;
int msgSizeRange = 1024;
- boolean rateLimitProducer = false;
- double rateFactor = 0.4;
- double rate = 0.0;
-
- public PerfProducer(String prefix)
+
+ public PerfProducer()
{
- super(prefix);
- System.out.println("Producer ID : " + id);
+ super();
}
public void setUp() throws Exception
{
super.setUp();
- durable = params.isDurable();
- rateLimitProducer = params.getRate() > 0 ? true : false;
- if (rateLimitProducer)
- {
- System.out.println("The test will attempt to limit the producer to " + params.getRate() + " msg/sec");
- }
+ feedbackDest = session.createTemporaryQueue();
+ durable = params.isDurable();
+
// if message caching is enabled we pre create the message
// else we pre create the payload
if (params.isCacheMessage())
{
cacheMsg = true;
- msg = createMessage(createPayload(params.getMsgSize()));
+
+ msg = MessageFactory.createBytesMessage(session, params.getMsgSize());
msg.setJMSDeliveryMode(durable?
DeliveryMode.PERSISTENT :
DeliveryMode.NON_PERSISTENT
@@ -109,52 +93,21 @@ public class PerfProducer extends PerfBase
random = new Random(20080921);
randomMsgSize = true;
msgSizeRange = params.getMsgSize();
- payloads = new ArrayList<Object>(msgSizeRange);
-
+ payloads = new ArrayList<byte[]>(msgSizeRange);
+
for (int i=0; i < msgSizeRange; i++)
{
- payloads.add(createPayload(i));
+ payloads.add(MessageFactory.createMessagePayload(i).getBytes());
}
- }
+ }
else
{
- payload = createPayload(params.getMsgSize());
+ payload = MessageFactory.createMessagePayload(params.getMsgSize()).getBytes();
}
producer = session.createProducer(dest);
- System.out.println("Producer: " + id + " Sending messages to: " + ((AMQDestination)dest).getQueueName());
producer.setDisableMessageID(params.isDisableMessageID());
producer.setDisableMessageTimestamp(params.isDisableTimestamp());
-
- MapMessage m = controllerSession.createMapMessage();
- m.setInt(CODE, OPCode.REGISTER_PRODUCER.ordinal());
- sendMessageToController(m);
- }
-
- Object createPayload(int size)
- {
- if (msgType == MessageType.TEXT)
- {
- return MessageFactory.createMessagePayload(size);
- }
- else
- {
- return MessageFactory.createMessagePayload(size).getBytes();
- }
- }
-
- Message createMessage(Object payload) throws Exception
- {
- if (msgType == MessageType.TEXT)
- {
- return session.createTextMessage((String)payload);
- }
- else
- {
- BytesMessage m = session.createBytesMessage();
- m.writeBytes((byte[])payload);
- return m;
- }
}
protected Message getNextMessage() throws Exception
@@ -164,130 +117,117 @@ public class PerfProducer extends PerfBase
return msg;
}
else
- {
- Message m;
-
+ {
+ msg = session.createBytesMessage();
+
if (!randomMsgSize)
{
- m = createMessage(payload);
+ ((BytesMessage)msg).writeBytes(payload);
}
else
{
- m = createMessage(payloads.get(random.nextInt(msgSizeRange)));
+ ((BytesMessage)msg).writeBytes(payloads.get(random.nextInt(msgSizeRange)));
}
- m.setJMSDeliveryMode(durable?
+ msg.setJMSDeliveryMode(durable?
DeliveryMode.PERSISTENT :
DeliveryMode.NON_PERSISTENT
);
- return m;
+ return msg;
}
}
public void warmup()throws Exception
{
- receiveFromController(OPCode.PRODUCER_STARTWARMUP);
- System.out.println("Producer: " + id + " Warming up......");
+ System.out.println("Warming up......");
+ MessageConsumer tmp = session.createConsumer(feedbackDest);
for (int i=0; i < params.getWarmupCount() -1; i++)
{
producer.send(getNextMessage());
}
- sendEndMessage();
+ Message msg = session.createTextMessage("End");
+ msg.setJMSReplyTo(feedbackDest);
+ producer.send(msg);
+
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.receive();
if (params.isTransacted())
{
session.commit();
}
+
+ tmp.close();
}
public void startTest() throws Exception
{
- resetCounters();
- receiveFromController(OPCode.PRODUCER_START);
+ System.out.println("Starting test......");
int count = params.getMsgCount();
boolean transacted = params.isTransacted();
int tranSize = params.getTransactionSize();
- long limit = (long)(params.getRate() * rateFactor); // in msecs
- long timeLimit = (long)(SEC * rateFactor); // in msecs
-
- long start = Clock.getTime(); // defaults to nano secs
- long interval = start;
+ long start = System.currentTimeMillis();
for(int i=0; i < count; i++ )
{
Message msg = getNextMessage();
- msg.setLongProperty(TIMESTAMP, Clock.getTime());
+ msg.setJMSTimestamp(System.currentTimeMillis());
producer.send(msg);
if ( transacted && ((i+1) % tranSize == 0))
{
session.commit();
}
-
- if (rateLimitProducer && i%limit == 0)
- {
- long elapsed = (Clock.getTime() - interval)*Clock.convertToMiliSecs(); // in msecs
- if (elapsed < timeLimit)
- {
- Thread.sleep(elapsed);
- }
- interval = Clock.getTime();
-
- }
- }
- sendEndMessage();
- if ( transacted)
- {
- session.commit();
}
- long time = Clock.getTime() - start;
- rate = (double)count*Clock.convertToSecs()/(double)time;
+ long time = System.currentTimeMillis() - start;
+ double rate = ((double)count/(double)time)*1000;
System.out.println(new StringBuilder("Producer rate: ").
append(df.format(rate)).
append(" msg/sec").
toString());
}
- public void resetCounters()
+ public void waitForCompletion() throws Exception
{
+ MessageConsumer tmp = session.createConsumer(feedbackDest);
+ Message msg = session.createTextMessage("End");
+ msg.setJMSReplyTo(feedbackDest);
+ producer.send(msg);
- }
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
- public void sendEndMessage() throws Exception
- {
- Message msg = session.createMessage();
- msg.setBooleanProperty("End", true);
- producer.send(msg);
- }
+ tmp.receive();
- public void sendResults() throws Exception
- {
- MapMessage msg = controllerSession.createMapMessage();
- msg.setInt(CODE, OPCode.RECEIVED_PRODUCER_STATS.ordinal());
- msg.setDouble(PROD_RATE, rate);
- sendMessageToController(msg);
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.close();
+ System.out.println("Consumer has completed the test......");
}
- @Override
public void tearDown() throws Exception
{
- super.tearDown();
+ producer.close();
+ session.close();
+ con.close();
}
- public void run()
+ public void test()
{
try
{
setUp();
warmup();
- boolean nextIteration = true;
- while (nextIteration)
- {
- System.out.println("=========================================================\n");
- System.out.println("Producer: " + id + " starting a new iteration ......\n");
- startTest();
- sendResults();
- nextIteration = continueTest();
- }
+ startTest();
+ waitForCompletion();
tearDown();
}
catch(Exception e)
@@ -296,63 +236,27 @@ public class PerfProducer extends PerfBase
}
}
- public void startControllerIfNeeded()
+
+ public static void main(String[] args)
{
- if (!params.isExternalController())
+ final PerfProducer prod = new PerfProducer();
+ Runnable r = new Runnable()
{
- final PerfTestController controller = new PerfTestController();
- Runnable r = new Runnable()
- {
- public void run()
- {
- controller.run();
- }
- };
-
- Thread t;
- try
+ public void run()
{
- t = Threading.getThreadFactory().createThread(r);
+ prod.test();
}
- catch(Exception e)
- {
- throw new Error("Error creating controller thread",e);
- }
- t.start();
+ };
+
+ Thread t;
+ try
+ {
+ t = Threading.getThreadFactory().createThread(r);
}
- }
-
-
- public static void main(String[] args) throws InterruptedException
- {
- String scriptId = (args.length == 1) ? args[0] : "";
- int conCount = Integer.getInteger("con_count",1);
- final CountDownLatch testCompleted = new CountDownLatch(conCount);
- for (int i=0; i < conCount; i++)
+ catch(Exception e)
{
- final PerfProducer prod = new PerfProducer(scriptId + i);
- prod.startControllerIfNeeded();
- Runnable r = new Runnable()
- {
- public void run()
- {
- prod.run();
- testCompleted.countDown();
- }
- };
-
- Thread t;
- try
- {
- t = Threading.getThreadFactory().createThread(r);
- }
- catch(Exception e)
- {
- throw new Error("Error creating producer thread",e);
- }
- t.start();
+ throw new Error("Error creating producer thread",e);
}
- testCompleted.await();
- System.out.println("Producers have completed the test......");
+ t.start();
}
} \ No newline at end of file
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java b/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java
deleted file mode 100644
index 5c98c645f4..0000000000
--- a/java/tools/src/main/java/org/apache/qpid/tools/PerfTestController.java
+++ /dev/null
@@ -1,422 +0,0 @@
-package org.apache.qpid.tools;
-
-import java.io.FileWriter;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-
-import org.apache.qpid.client.message.AMQPEncodedMapMessage;
-
-/**
- * The Controller coordinates a test run between a number
- * of producers and consumers, configured via -Dprod_count and -Dcons_count.
- *
- * It waits till all the producers and consumers have registered and then
- * conducts a warmup run. Once all consumers and producers have completed
- * the warmup run and is ready, it will conduct the actual test run and
- * collect all stats from the participants and calculates the system
- * throughput, the avg/min/max for producer rates, consumer rates and latency.
- *
- * These stats are then printed to std out.
- * The Controller also prints events to std out to give a running account
- * of the test run in progress. Ex registering of participants, starting warmup ..etc.
- * This allows a scripting tool to monitor the progress.
- *
- * The Controller can be run in two modes.
- * 1. A single test run (default) where it just runs until the message count specified
- * for the producers via -Dmsg_count is sent and received.
- *
- * 2. Time based, configured via -Dduration=x, where x is in mins.
- * In this mode, the Controller repeatedly cycles through the tests (after an initial
- * warmup run) until the desired time is reached. If a test run is in progress
- * and the time is up, it will allow the run the complete.
- *
- * After each iteration, the stats will be printed out in csv format to a separate log file.
- * System throughput is calculated as follows
- * totalMsgCount/(totalTestTime)
- */
-public class PerfTestController extends PerfBase implements MessageListener
-{
- enum TestMode { SINGLE_RUN, TIME_BASED };
-
- TestMode testMode = TestMode.SINGLE_RUN;
-
- long totalTestTime;
-
- private double avgSystemLatency = 0.0;
- private double minSystemLatency = Double.MAX_VALUE;
- private double maxSystemLatency = 0;
- private double avgSystemLatencyStdDev = 0.0;
-
- private double avgSystemConsRate = 0.0;
- private double maxSystemConsRate = 0.0;
- private double minSystemConsRate = Double.MAX_VALUE;
-
- private double avgSystemProdRate = 0.0;
- private double maxSystemProdRate = 0.0;
- private double minSystemProdRate = Double.MAX_VALUE;
-
- private long totalMsgCount = 0;
- private double totalSystemThroughput = 0.0;
-
- private int consumerCount = Integer.getInteger("cons_count", 1);
- private int producerCount = Integer.getInteger("prod_count", 1);
- private int duration = Integer.getInteger("duration", -1); // in mins
- private Map<String,MapMessage> consumers;
- private Map<String,MapMessage> producers;
-
- private CountDownLatch consRegistered;
- private CountDownLatch prodRegistered;
- private CountDownLatch consReady;
- private CountDownLatch prodReady;
- private CountDownLatch receivedEndMsg;
- private CountDownLatch receivedConsStats;
- private CountDownLatch receivedProdStats;
-
- private MessageConsumer consumer;
- private boolean printStdDev = false;
- FileWriter writer;
-
- public PerfTestController()
- {
- super("");
- consumers = new ConcurrentHashMap<String,MapMessage>(consumerCount);
- producers = new ConcurrentHashMap<String,MapMessage>(producerCount);
-
- consRegistered = new CountDownLatch(consumerCount);
- prodRegistered = new CountDownLatch(producerCount);
- consReady = new CountDownLatch(consumerCount);
- prodReady = new CountDownLatch(producerCount);
- printStdDev = params.isPrintStdDev();
- testMode = (duration == -1) ? TestMode.SINGLE_RUN : TestMode.TIME_BASED;
- }
-
- public void setUp() throws Exception
- {
- super.setUp();
- if (testMode == TestMode.TIME_BASED)
- {
- writer = new FileWriter("stats-csv.log");
- }
- consumer = controllerSession.createConsumer(controllerQueue);
- System.out.println("\nController: " + producerCount + " producers are expected");
- System.out.println("Controller: " + consumerCount + " consumers are expected \n");
- consumer.setMessageListener(this);
- consRegistered.await();
- prodRegistered.await();
- System.out.println("\nController: All producers and consumers have registered......\n");
- }
-
- public void warmup() throws Exception
- {
- System.out.println("Controller initiating warm up sequence......");
- sendMessageToNodes(OPCode.CONSUMER_STARTWARMUP,consumers.values());
- sendMessageToNodes(OPCode.PRODUCER_STARTWARMUP,producers.values());
- prodReady.await();
- consReady.await();
- System.out.println("\nController : All producers and consumers are ready to start the test......\n");
- }
-
- public void startTest() throws Exception
- {
- resetCounters();
- System.out.println("\nController Starting test......");
- long start = Clock.getTime();
- sendMessageToNodes(OPCode.PRODUCER_START,producers.values());
- receivedEndMsg.await();
- totalTestTime = Clock.getTime() - start;
- sendMessageToNodes(OPCode.CONSUMER_STOP,consumers.values());
- receivedProdStats.await();
- receivedConsStats.await();
- }
-
- public void resetCounters()
- {
- minSystemLatency = Double.MAX_VALUE;
- maxSystemLatency = 0;
- maxSystemConsRate = 0.0;
- minSystemConsRate = Double.MAX_VALUE;
- maxSystemProdRate = 0.0;
- minSystemProdRate = Double.MAX_VALUE;
-
- totalMsgCount = 0;
-
- receivedConsStats = new CountDownLatch(consumerCount);
- receivedProdStats = new CountDownLatch(producerCount);
- receivedEndMsg = new CountDownLatch(producerCount);
- }
-
- public void calcStats() throws Exception
- {
- double totLatency = 0.0;
- double totStdDev = 0.0;
- double totalConsRate = 0.0;
- double totalProdRate = 0.0;
-
- MapMessage conStat = null; // for error handling
- try
- {
- for (MapMessage m: consumers.values())
- {
- conStat = m;
- minSystemLatency = Math.min(minSystemLatency,m.getDouble(MIN_LATENCY));
- maxSystemLatency = Math.max(maxSystemLatency,m.getDouble(MAX_LATENCY));
- totLatency = totLatency + m.getDouble(AVG_LATENCY);
- totStdDev = totStdDev + m.getDouble(STD_DEV);
-
- minSystemConsRate = Math.min(minSystemConsRate,m.getDouble(CONS_RATE));
- maxSystemConsRate = Math.max(maxSystemConsRate,m.getDouble(CONS_RATE));
- totalConsRate = totalConsRate + m.getDouble(CONS_RATE);
-
- totalMsgCount = totalMsgCount + m.getLong(MSG_COUNT);
- }
- }
- catch(Exception e)
- {
- System.out.println("Error calculating stats from Consumer : " + conStat);
- }
-
-
- MapMessage prodStat = null; // for error handling
- try
- {
- for (MapMessage m: producers.values())
- {
- prodStat = m;
- minSystemProdRate = Math.min(minSystemProdRate,m.getDouble(PROD_RATE));
- maxSystemProdRate = Math.max(maxSystemProdRate,m.getDouble(PROD_RATE));
- totalProdRate = totalProdRate + m.getDouble(PROD_RATE);
- }
- }
- catch(Exception e)
- {
- System.out.println("Error calculating stats from Producer : " + conStat);
- }
-
- avgSystemLatency = totLatency/consumers.size();
- avgSystemLatencyStdDev = totStdDev/consumers.size();
- avgSystemConsRate = totalConsRate/consumers.size();
- avgSystemProdRate = totalProdRate/producers.size();
-
- System.out.println("Total test time : " + totalTestTime + " in " + Clock.getPrecision());
-
- totalSystemThroughput = (totalMsgCount*Clock.convertToSecs()/totalTestTime);
- }
-
- public void printResults() throws Exception
- {
- System.out.println(new StringBuilder("Total Msgs Received : ").append(totalMsgCount).toString());
- System.out.println(new StringBuilder("System Throughput : ").
- append(df.format(totalSystemThroughput)).
- append(" msg/sec").toString());
- System.out.println(new StringBuilder("Avg Consumer rate : ").
- append(df.format(avgSystemConsRate)).
- append(" msg/sec").toString());
- System.out.println(new StringBuilder("Min Consumer rate : ").
- append(df.format(minSystemConsRate)).
- append(" msg/sec").toString());
- System.out.println(new StringBuilder("Max Consumer rate : ").
- append(df.format(maxSystemConsRate)).
- append(" msg/sec").toString());
-
- System.out.println(new StringBuilder("Avg Producer rate : ").
- append(df.format(avgSystemProdRate)).
- append(" msg/sec").toString());
- System.out.println(new StringBuilder("Min Producer rate : ").
- append(df.format(minSystemProdRate)).
- append(" msg/sec").toString());
- System.out.println(new StringBuilder("Max Producer rate : ").
- append(df.format(maxSystemProdRate)).
- append(" msg/sec").toString());
-
- System.out.println(new StringBuilder("Avg System Latency : ").
- append(df.format(avgSystemLatency)).
- append(" ms").toString());
- System.out.println(new StringBuilder("Min System Latency : ").
- append(df.format(minSystemLatency)).
- append(" ms").toString());
- System.out.println(new StringBuilder("Max System Latency : ").
- append(df.format(maxSystemLatency)).
- append(" ms").toString());
- if (printStdDev)
- {
- System.out.println(new StringBuilder("Avg System Std Dev : ").
- append(avgSystemLatencyStdDev));
- }
- }
-
- private synchronized void sendMessageToNodes(OPCode code,Collection<MapMessage> nodes) throws Exception
- {
- System.out.println("\nController: Sending code " + code);
- MessageProducer tmpProd = controllerSession.createProducer(null);
- MapMessage msg = controllerSession.createMapMessage();
- msg.setInt(CODE, code.ordinal());
- for (MapMessage node : nodes)
- {
- if (node.getString(REPLY_ADDR) == null)
- {
- System.out.println("REPLY_ADDR is null " + node);
- }
- else
- {
- System.out.println("Controller: Sending " + code + " to " + node.getString(REPLY_ADDR));
- }
- tmpProd.send(controllerSession.createQueue(node.getString(REPLY_ADDR)), msg);
- }
- }
-
- public void onMessage(Message msg)
- {
- try
- {
- MapMessage m = (MapMessage)msg;
- OPCode code = OPCode.values()[m.getInt(CODE)];
-
- System.out.println("\n---------Controller Received Code : " + code);
- System.out.println("---------Data : " + ((AMQPEncodedMapMessage)m).getMap());
-
- switch (code)
- {
- case REGISTER_CONSUMER :
- if (consRegistered.getCount() == 0)
- {
- System.out.println("Warning : Expected number of consumers have already registered," +
- "ignoring extra consumer");
- break;
- }
- consumers.put(m.getString(ID),m);
- consRegistered.countDown();
- break;
-
- case REGISTER_PRODUCER :
- if (prodRegistered.getCount() == 0)
- {
- System.out.println("Warning : Expected number of producers have already registered," +
- "ignoring extra producer");
- break;
- }
- producers.put(m.getString(ID),m);
- prodRegistered.countDown();
- break;
-
- case CONSUMER_READY :
- consReady.countDown();
- break;
-
- case PRODUCER_READY :
- prodReady.countDown();
- break;
-
- case RECEIVED_END_MSG :
- receivedEndMsg.countDown();
- break;
-
- case RECEIVED_CONSUMER_STATS :
- consumers.put(m.getString(ID),m);
- receivedConsStats.countDown();
- break;
-
- case RECEIVED_PRODUCER_STATS :
- producers.put(m.getString(ID),m);
- receivedProdStats.countDown();
- break;
-
- default:
- throw new Exception("Invalid OPCode " + code);
- }
- }
- catch (Exception e)
- {
- handleError(e,"Error when receiving messages " + msg);
- }
- }
-
- public void run()
- {
- try
- {
- setUp();
- warmup();
- if (testMode == TestMode.SINGLE_RUN)
- {
- startTest();
- calcStats();
- printResults();
- }
- else
- {
- long startTime = Clock.getTime();
- long timeLimit = duration * 60 * 1000; // duration is in mins.
- boolean nextIteration = true;
- while (nextIteration)
- {
- startTest();
- calcStats();
- writeStatsToFile();
- if (Clock.getTime() - startTime < timeLimit)
- {
- sendMessageToNodes(OPCode.CONTINUE_TEST,consumers.values());
- sendMessageToNodes(OPCode.CONTINUE_TEST,producers.values());
- nextIteration = true;
- }
- else
- {
- nextIteration = false;
- }
- }
- }
- tearDown();
-
- }
- catch(Exception e)
- {
- handleError(e,"Error when running test");
- }
- }
-
- @Override
- public void tearDown() throws Exception {
- System.out.println("Controller: Completed the test......\n");
- if (testMode == TestMode.TIME_BASED)
- {
- writer.close();
- }
- sendMessageToNodes(OPCode.STOP_TEST,consumers.values());
- sendMessageToNodes(OPCode.STOP_TEST,producers.values());
- super.tearDown();
- }
-
- public void writeStatsToFile() throws Exception
- {
- writer.append(String.valueOf(totalMsgCount)).append(",");
- writer.append(df.format(totalSystemThroughput)).append(",");
- writer.append(df.format(avgSystemConsRate)).append(",");
- writer.append(df.format(minSystemConsRate)).append(",");
- writer.append(df.format(maxSystemConsRate)).append(",");
- writer.append(df.format(avgSystemProdRate)).append(",");
- writer.append(df.format(minSystemProdRate)).append(",");
- writer.append(df.format(maxSystemProdRate)).append(",");
- writer.append(df.format(avgSystemLatency)).append(",");
- writer.append(df.format(minSystemLatency)).append(",");
- writer.append(df.format(maxSystemLatency));
- if (printStdDev)
- {
- writer.append(",").append(String.valueOf(avgSystemLatencyStdDev));
- }
- writer.append("\n");
- writer.flush();
- }
-
- public static void main(String[] args)
- {
- PerfTestController controller = new PerfTestController();
- controller.run();
- }
-}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java b/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java
index d73be0181b..89d6462a39 100644
--- a/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java
+++ b/java/tools/src/main/java/org/apache/qpid/tools/TestParams.java
@@ -25,25 +25,25 @@ import javax.jms.Session;
public class TestParams
{
/*
- * By default the connection URL is used.
+ * By default the connection URL is used.
* This allows a user to easily specify a fully fledged URL any given property.
* Ex. SSL parameters
- *
+ *
* By providing a host & port allows a user to simply override the URL.
* This allows to create multiple clients in test scripts easily,
- * without having to deal with the long URL format.
+ * without having to deal with the long URL format.
*/
private String url = "amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'";
-
+
private String host = "";
-
+
private int port = -1;
private String address = "queue; {create : always}";
private int msg_size = 1024;
- private int random_msg_size_start_from = 1;
+ private int msg_type = 1; // not used yet
private boolean cacheMessage = false;
@@ -62,28 +62,19 @@ public class TestParams
private int msg_count = 10;
private int warmup_count = 1;
-
+
private boolean random_msg_size = false;
- private String msgType = "bytes";
-
- private boolean printStdDev = false;
-
- private long rate = -1;
-
- private boolean externalController = false;
-
- private boolean useUniqueDest = false; // useful when using multiple connections.
-
public TestParams()
{
-
+
url = System.getProperty("url",url);
host = System.getProperty("host","");
port = Integer.getInteger("port", -1);
- address = System.getProperty("address",address);
+ address = System.getProperty("address","queue");
msg_size = Integer.getInteger("msg_size", 1024);
+ msg_type = Integer.getInteger("msg_type",1);
cacheMessage = Boolean.getBoolean("cache_msg");
disableMessageID = Boolean.getBoolean("disableMessageID");
disableTimestamp = Boolean.getBoolean("disableTimestamp");
@@ -94,12 +85,6 @@ public class TestParams
msg_count = Integer.getInteger("msg_count",msg_count);
warmup_count = Integer.getInteger("warmup_count",warmup_count);
random_msg_size = Boolean.getBoolean("random_msg_size");
- msgType = System.getProperty("msg_type","bytes");
- printStdDev = Boolean.getBoolean("print_std_dev");
- rate = Long.getLong("rate",-1);
- externalController = Boolean.getBoolean("ext_controller");
- useUniqueDest = Boolean.getBoolean("use_unique_dest");
- random_msg_size_start_from = Integer.getInteger("random_msg_size_start_from", 1);
}
public String getUrl()
@@ -137,9 +122,9 @@ public class TestParams
return msg_size;
}
- public int getRandomMsgSizeStartFrom()
+ public int getMsgType()
{
- return random_msg_size_start_from;
+ return msg_type;
}
public boolean isDurable()
@@ -176,39 +161,10 @@ public class TestParams
{
return disableTimestamp;
}
-
+
public boolean isRandomMsgSize()
{
return random_msg_size;
}
- public String getMessageType()
- {
- return msgType;
- }
-
- public boolean isPrintStdDev()
- {
- return printStdDev;
- }
-
- public long getRate()
- {
- return rate;
- }
-
- public boolean isExternalController()
- {
- return externalController;
- }
-
- public void setAddress(String addr)
- {
- address = addr;
- }
-
- public boolean isUseUniqueDests()
- {
- return useUniqueDest;
- }
}
diff --git a/java/upload.xml b/java/upload.xml
deleted file mode 100644
index 9f2fd6819b..0000000000
--- a/java/upload.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.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.
--->
-<project name="upload" default="upload" xmlns:ivy="antlib:org.apache.ivy.ant">
- <description>Targets for uploading releases to ASF's Nexus instance</description>
-
- <property name="nexus.organisation" value="org.apache"/>
- <property name="nexus.host" value="repository.apache.org"/>
- <property name="nexus.upload.url" value="https://repository.apache.org/service/local/staging/deploy/maven2"/>
-
- <!-- properties for downloading ivy if required -->
- <property name="ivy.jar.dir" value="lib/ivy" />
- <property name="ivy.install.version" value="2.2.0" />
- <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy-${ivy.install.version}.jar" />
- <property name="ivy.repo.url" value="http://repo1.maven.org/maven2/org/apache/ivy/ivy"/>
-
- <target name="download-ivy">
- <mkdir dir="${ivy.jar.dir}"/>
- <!-- download Ivy from web site so that it can be used without any special installation -->
- <echo message="Downloading ivy..."/>
- <get src="${ivy.repo.url}/${ivy.install.version}/ivy-${ivy.install.version}.jar"
- dest="${ivy.jar.file}" usetimestamp="true"/>
- </target>
-
- <target name="load-ivy">
- <!-- Try to load Ivy from local ivy dir, in case the user has not already dropped it into
- Ant's lib dir (note that the latter copy will always take precedence). Won't
- fail so long as Ivy is in at least one of the locations. -->
- <mkdir dir="${ivy.jar.dir}"/>
- <path id="ivy.lib.path">
- <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
- </path>
- <taskdef resource="org/apache/ivy/ant/antlib.xml"
- uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
- </target>
-
- <!-- check the following properties which must be specified by the user-->
- <target name="check-props-exist" description="check that the required properties have been set">
- <fail unless="nexus.user" message="You must supply the 'nexus.user' property"/>
- <fail unless="nexus.password" message="You must supply the 'nexus.password' property"/>
- <fail unless="maven.artifact.dir" message="You must supply the 'maven.artifact.dir' property"/>
- </target>
-
- <target name="perform-nexus-upload" description="really requires the prepare-upload target to be run first">
- <ivy:configure file="ivysettings-nexus.xml"/>
- <ivy:resolve file="ivy.xml"/>
- <ivy:retrieve/>
- <ivy:deliver/>
- <ivy:publish publishivy="false" resolver="nexus"
- artifactspattern="${maven.artifact.dir}/[organisation]/[module]/[artifact]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
- </target>
-
- <target name="upload" depends="load-ivy, check-props-exist, perform-nexus-upload"/>
-
- <target name="help" description="display detailed build documentation">
- <echo>
-Ivy can be leveraged either by installing it in the Ant lib dir yourself,
-or by running the following command in qpid/java to place it in the
-qpid/java/lib/ivy lib folder:
-
- ant -buildfile upload.xml download-ivy
-
-The publishing task should be run once the release process has otherwise
-been completed and the artifacts signed. It can be performed from the
-qpid/java directory with a command as follows:
-
- ant -buildfile upload.xml -Dnexus.user=&lt;apache_username&gt; -Dnexus.password=&lt;password&gt;
- -Dmaven.artifact.dir=&lt;path to maven repo structure from release process&gt;
-
-Note: if you are behind a proxy server it is necessary to give Ant the
-proxy settings by doing something like:
-
-export ANT_OPTS=&quot;-Dhttp.proxyHost=&lt;host&gt; -Dhttp.proxyPort=&lt;port&gt; -Dhttps.proxyHost=&lt;host&gt; -Dhttps.proxyPort=&lt;port&gt;&quot;
- </echo>
- </target>
-</project>
diff --git a/packaging/windows/INSTALL_NOTES.html b/packaging/windows/INSTALL_NOTES.html
index f8e109cb36..4aecce697a 100644
--- a/packaging/windows/INSTALL_NOTES.html
+++ b/packaging/windows/INSTALL_NOTES.html
@@ -1,11 +1,11 @@
<html>
<head>
-<title>Apache Qpid C++ 0.10 Installation Notes</title>
+<title>Apache Qpid C++ 0.9 Installation Notes</title>
</head>
<body>
-<H1>Apache Qpid C++ 0.10 Installation Notes</H1>
+<H1>Apache Qpid C++ 0.9 Installation Notes</H1>
-<p>Thank you for installing Apache Qpid version 0.10 for Windows.
+<p>Thank you for installing Apache Qpid version 0.9 for Windows.
If the requisite features were installed, you can now run a broker,
use the example programs, and design your own messaging programs while
reading the Qpid C++ API reference documentation.</p>
diff --git a/packaging/windows/installer.proj b/packaging/windows/installer.proj
index 5dc16b0bfa..7be5fda472 100644
--- a/packaging/windows/installer.proj
+++ b/packaging/windows/installer.proj
@@ -20,7 +20,7 @@
<!--
Packaging script for Apache Qpid on Windows
- Builds the C++, .NET, and WCF components, and packages those along with user
+ Builds the C++ and WCF components, and packages those along with user
documentation and the python pieces needed to generate QMF stuff.
-->
@@ -87,8 +87,7 @@
<ItemGroup>
<WcfProjects Include="$(source_root)\wcf\src\Apache\Qpid\**\*.csproj"/>
- <WcfArtifacts Include="$(source_root)\wcf\src\Apache\Qpid\Channel\bin\Release\Apache.Qpid.Channel.dll"/>
- <WcfArtifacts Include="$(source_root)\wcf\src\Apache\Qpid\Channel\bin\Release\Apache.Qpid.Interop.dll"/>
+ <WcfArtifacts Include="$(source_root)\wcf\src\Apache\Qpid\Channel\bin\Release\*.dll"/>
<WcfExamples Include="$(source_root)\wcf\samples\**\*"
Exclude="$(source_root)\wcf\samples\**\.svn\**"/>
</ItemGroup>
@@ -218,9 +217,9 @@
OutputFile="boost_dlls.wxs" />
<Candle
ToolPath="$(WixToolPath)"
- DefineConstants="qpidc_version=0.13"
+ DefineConstants="qpidc_version=0.9"
InstallerPlatform="x64"
- OutputFile="qpidc-0.13-x64.msi" />
+ OutputFile="qpidc-0.9-x64.msi" />
-->
<Exec
Command="heat dir $(staging_dir)\include\qpid -var var.qpid_headers_dir -dr QpidInclude -gg -cg group_QpidHeaders -out qpid_headers.wxs" />
@@ -230,19 +229,13 @@
<Exec
Command="heat dir $(staging_dir)\bin\boost -var var.boost_dll_dir -dr QpidBin -srd -gg -cg group_BoostDlls -sw5150 -out boost_dlls.wxs" />
<Exec
- Command="heat file $(staging_dir)\examples\README.txt -var var.examples_dir -dr INSTALLLOCATION -gg -cg group_Examples -out examples_README.wxs" />
- <Exec
- Command="heat file $(staging_dir)\examples\examples.sln -var var.examples_dir -dr INSTALLLOCATION -gg -cg group_Examples -out examples_examples.wxs" />
- <Exec
- Command="heat dir $(staging_dir)\examples\messaging -var var.examples_dir -dr INSTALLLOCATION -gg -cg group_Examples -out examples_messaging.wxs" />
- <Exec
- Command="heat dir $(staging_dir)\examples\qmf-console -var var.examples_dir -dr INSTALLLOCATION -gg -cg group_Examples -out examples_qmf-console.wxs" />
+ Command="heat dir $(staging_dir)\examples -var var.examples_dir -dr INSTALLLOCATION -gg -cg group_Examples -out examples.wxs" />
<Exec
Command="heat dir $(staging_dir)\docs\api -var var.api_docs_dir -dr QpidDoc -gg -cg group_APIDocs -out api_docs.wxs" />
<Exec
- Command="candle -dqpidc_version=0.13 -dProgramFiles=$(ProgramFiles) -dstaging_dir=$(staging_dir) -dqpid_headers_dir=$(staging_dir)\include\qpid -dboost_headers_dir=$(staging_dir)\include\boost -dboost_dll_dir=$(staging_dir)\bin\boost -dexamples_dir=$(staging_dir)\examples -dapi_docs_dir=$(staging_dir)\docs\api -ext WiXNetFxExtension qpidc.wxs qpid_headers.wxs boost_headers.wxs boost_dlls.wxs examples.wxs api_docs.wxs -arch $(Architecture)" />
+ Command="candle -dqpidc_version=0.9 -dProgramFiles=$(ProgramFiles) -dstaging_dir=$(staging_dir) -dqpid_headers_dir=$(staging_dir)\include\qpid -dboost_headers_dir=$(staging_dir)\include\boost -dboost_dll_dir=$(staging_dir)\bin\boost -dexamples_dir=$(staging_dir)\examples -dapi_docs_dir=$(staging_dir)\docs\api -ext WiXNetFxExtension qpidc.wxs qpid_headers.wxs boost_headers.wxs boost_dlls.wxs examples.wxs api_docs.wxs -arch $(Architecture)" />
<Exec
- Command="light -ext WiXNetFxExtension -ext WixUtilExtension -ext WixUIExtension -cultures:en-us -out qpidc-0.13-$(Architecture).msi qpidc.wixobj qpid_headers.wixobj boost_headers.wixobj boost_dlls.wixobj examples_README.wixobj examples_examples.wixobj examples_messaging.wixobj examples_qmf-console.wixobj api_docs.wixobj" />
+ Command="light -ext WiXNetFxExtension -ext WixUtilExtension -ext WixUIExtension -cultures:en-us -out qpidc-0.9-$(Architecture).msi qpidc.wixobj qpid_headers.wixobj boost_headers.wixobj boost_dlls.wixobj examples.wixobj api_docs.wixobj" />
</Target>
</Project>
diff --git a/python/qpid/client.py b/python/qpid/client.py
index 5a877bb8d6..45ce8498e8 100644
--- a/python/qpid/client.py
+++ b/python/qpid/client.py
@@ -106,7 +106,7 @@ class Client:
try:
id = None
for i in xrange(1, 64*1024):
- if not self.sessions.has_key(i):
+ if not self.sessions.has_key(id):
id = i
break
finally:
diff --git a/python/qpid/codec010.py b/python/qpid/codec010.py
index 94a1cd4263..0846db6bf7 100644
--- a/python/qpid/codec010.py
+++ b/python/qpid/codec010.py
@@ -17,7 +17,7 @@
# under the License.
#
-import datetime, string
+import datetime
from packer import Packer
from datatypes import serial, timestamp, RangedSet, Struct, UUID
from ops import Compound, PRIMITIVE, COMPOUND
@@ -241,20 +241,15 @@ class Codec(Packer):
v = sc.read_primitive(type)
result[k] = v
return result
-
- def _write_map_elem(self, k, v):
- type = self.encoding(v)
- sc = StringCodec()
- sc.write_str8(k)
- sc.write_uint8(type.CODE)
- sc.write_primitive(type, v)
- return sc.encoded
-
def write_map(self, m):
sc = StringCodec()
if m is not None:
sc.write_uint32(len(m))
- sc.write(string.joinfields(map(self._write_map_elem, m.keys(), m.values()), ""))
+ for k, v in m.items():
+ type = self.encoding(v)
+ sc.write_str8(k)
+ sc.write_uint8(type.CODE)
+ sc.write_primitive(type, v)
self.write_vbin32(sc.encoded)
def read_array(self):
diff --git a/python/qpid/messaging/driver.py b/python/qpid/messaging/driver.py
index 7c21388213..2eb2c1863e 100644
--- a/python/qpid/messaging/driver.py
+++ b/python/qpid/messaging/driver.py
@@ -66,7 +66,7 @@ class Attachment:
# XXX
-DURABLE_DEFAULT=False
+DURABLE_DEFAULT=True
# XXX
@@ -526,7 +526,7 @@ class Driver:
rawlog.debug("OPEN[%s]: %s:%s", self.log_id, host, port)
trans = transports.TRANSPORTS.get(self.connection.transport)
if trans:
- self._transport = trans(self.connection, host, port)
+ self._transport = trans(host, port)
else:
raise ConnectError("no such transport: %s" % self.connection.transport)
if self._retrying and self._reconnect_log:
@@ -828,9 +828,8 @@ class Engine:
self._closing = True
def attach(self, ssn):
- if ssn.closed: return
sst = self._attachments.get(ssn)
- if sst is None:
+ if sst is None and not ssn.closed:
for i in xrange(0, self.channel_max):
if not self._sessions.has_key(i):
ch = i
@@ -931,7 +930,6 @@ class Engine:
def resolve_declare(self, sst, lnk, dir, action):
declare = lnk.options.get("create") in ("always", dir)
- assrt = lnk.options.get("assert") in ("always", dir)
def do_resolved(type, subtype):
err = None
if type is None:
@@ -940,12 +938,7 @@ class Engine:
else:
err = NotFound(text="no such queue: %s" % lnk.name)
else:
- if assrt:
- expected = lnk.options.get("node", {}).get("type")
- if expected and type != expected:
- err = AssertionFailed(text="expected %s, got %s" % (expected, type))
- if err is None:
- action(type, subtype)
+ action(type, subtype)
if err:
tgt = lnk.target
diff --git a/python/qpid/messaging/endpoints.py b/python/qpid/messaging/endpoints.py
index 338ac70ecf..b8101b76e6 100644
--- a/python/qpid/messaging/endpoints.py
+++ b/python/qpid/messaging/endpoints.py
@@ -158,7 +158,6 @@ class Connection(Endpoint):
self.reconnect_log = options.get("reconnect_log", True)
self.address_ttl = options.get("address_ttl", 60)
- self.tcp_nodelay = options.get("tcp_nodelay", False)
self.options = options
@@ -198,7 +197,7 @@ class Connection(Endpoint):
return result
def check_closed(self):
- if not self._connected:
+ if self.closed:
self._condition.gc()
raise ConnectionClosed()
@@ -1007,9 +1006,9 @@ class Receiver(Endpoint, object):
self.draining = True
self._wakeup()
self._ecwait(lambda: not self.draining)
- msg = self.session._get(self, timeout=0)
self._grant()
self._wakeup()
+ msg = self.session._get(self, timeout=0)
if msg is None:
raise Empty()
elif self._capacity not in (0, UNLIMITED.value):
diff --git a/python/qpid/messaging/transports.py b/python/qpid/messaging/transports.py
index 7abaae12e8..8133a45604 100644
--- a/python/qpid/messaging/transports.py
+++ b/python/qpid/messaging/transports.py
@@ -17,23 +17,18 @@
# under the License.
#
-import socket
from qpid.util import connect
TRANSPORTS = {}
-class SocketTransport:
+class tcp:
- def __init__(self, conn, host, port):
+ def __init__(self, host, port):
self.socket = connect(host, port)
- if conn.tcp_nodelay:
- self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
def fileno(self):
return self.socket.fileno()
-class tcp(SocketTransport):
-
def reading(self, reading):
return reading
@@ -57,14 +52,17 @@ try:
except ImportError:
pass
else:
- class tls(SocketTransport):
+ class tls:
- def __init__(self, conn, host, port):
- SocketTransport.__init__(self, conn, host, port)
+ def __init__(self, host, port):
+ self.socket = connect(host, port)
self.tls = wrap_socket(self.socket)
self.socket.setblocking(0)
self.state = None
+ def fileno(self):
+ return self.socket.fileno()
+
def reading(self, reading):
if self.state is None:
return reading
diff --git a/python/qpid/tests/messaging/endpoints.py b/python/qpid/tests/messaging/endpoints.py
index db5ec03df2..c303ca652a 100644
--- a/python/qpid/tests/messaging/endpoints.py
+++ b/python/qpid/tests/messaging/endpoints.py
@@ -46,10 +46,6 @@ class SetupTests(Base):
self.conn.open()
self.ping(self.conn.session())
- def testTcpNodelay(self):
- self.conn = Connection.establish(self.broker, tcp_nodelay=True)
- assert self.conn._driver._transport.socket.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
-
def testConnectError(self):
try:
# Specifying port 0 yields a bad address on Windows; port 4 is unassigned
@@ -115,8 +111,8 @@ class SetupTests(Base):
class flaky:
- def __init__(self, conn, host, port):
- self.real = real(conn, host, port)
+ def __init__(self, host, port):
+ self.real = real(host, port)
self.sent_count = 0
self.recv_count = 0
@@ -190,9 +186,6 @@ class ConnectionTests(Base):
def setup_connection(self):
return Connection.establish(self.broker, **self.connection_options())
- def testCheckClosed(self):
- assert not self.conn.check_closed()
-
def testSessionAnon(self):
ssn1 = self.conn.session()
ssn2 = self.conn.session()
@@ -255,8 +248,8 @@ class ConnectionTests(Base):
class hangable:
- def __init__(self, conn, host, port):
- self.tcp = TRANSPORTS["tcp"](conn, host, port)
+ def __init__(self, host, port):
+ self.tcp = TRANSPORTS["tcp"](host, port)
self.hung = False
def hang(self):
@@ -1186,16 +1179,6 @@ test-link-bindings-queue; {
snd.send(m)
self.drain(qrcv, expected=msgs)
- def testAssert1(self):
- try:
- snd = self.ssn.sender("amq.topic; {assert: always, node: {type: queue}}")
- assert 0, "assertion failed to trigger"
- except AssertionFailed, e:
- pass
-
- def testAssert2(self):
- snd = self.ssn.sender("amq.topic; {assert: always}")
-
NOSUCH_Q = "this-queue-should-not-exist"
UNPARSEABLE_ADDR = "name/subject; {bad options"
UNLEXABLE_ADDR = "\0x0\0x1\0x2\0x3"
diff --git a/python/qpid/util.py b/python/qpid/util.py
index 89677289e2..e62bebdf24 100644
--- a/python/qpid/util.py
+++ b/python/qpid/util.py
@@ -39,17 +39,12 @@ except ImportError:
self.sock.close()
def connect(host, port):
- for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
- af, socktype, proto, canonname, sa = res
- sock = socket.socket(af, socktype, proto)
- try:
- sock.connect(sa)
- break
- except socket.error, msg:
- sock.close
- else:
- # If we got here then we couldn't connect (yet)
- raise
+ sock = socket.socket()
+ sock.connect((host, port))
+ sock.setblocking(1)
+ # XXX: we could use this on read, but we'd have to put write in a
+ # loop as well
+ # sock.settimeout(1)
return sock
def listen(host, port, predicate = lambda: True, bound = lambda: None):
@@ -106,23 +101,15 @@ def fill(text, indent, heading = None):
class URL:
RE = re.compile(r"""
- # [ <scheme>:// ] [ <user> [ / <password> ] @] ( <host4> | \[ <host6> \] ) [ :<port> ]
- ^ (?: ([^:/@]+)://)? (?: ([^:/@]+) (?: / ([^:/@]+) )? @)? (?: ([^@:/\[]+) | \[ ([a-f0-9:.]+) \] ) (?: :([0-9]+))?$
-""", re.X | re.I)
+ # [ <scheme>:// ] [ <user> [ / <password> ] @] <host> [ :<port> ]
+ ^ (?: ([^:/@]+)://)? (?: ([^:/@]+) (?: / ([^:/@]+) )? @)? ([^@:/]+) (?: :([0-9]+))?$
+""", re.X)
AMQPS = "amqps"
AMQP = "amqp"
- def __init__(self, s=None, **kwargs):
- if s is None:
- self.scheme = kwargs.get('scheme', None)
- self.user = kwargs.get('user', None)
- self.password = kwargs.get('password', None)
- self.host = kwargs.get('host', None)
- self.port = kwargs.get('port', None)
- if self.host is None:
- raise ValueError('Host required for url')
- elif isinstance(s, URL):
+ def __init__(self, s):
+ if isinstance(s, URL):
self.scheme = s.scheme
self.user = s.user
self.password = s.password
@@ -132,8 +119,7 @@ class URL:
match = URL.RE.match(s)
if match is None:
raise ValueError(s)
- self.scheme, self.user, self.password, host4, host6, port = match.groups()
- self.host = host4 or host6
+ self.scheme, self.user, self.password, self.host, port = match.groups()
if port is None:
self.port = None
else:
@@ -151,25 +137,11 @@ class URL:
if self.password:
s += "/%s" % self.password
s += "@"
- if ':' not in self.host:
- s += self.host
- else:
- s += "[%s]" % self.host
+ s += self.host
if self.port:
s += ":%s" % self.port
return s
- def __eq__(self, url):
- if isinstance(url, basestring):
- url = URL(url)
- return \
- self.scheme==url.scheme and \
- self.user==url.user and self.password==url.password and \
- self.host==url.host and self.port==url.port
-
- def __ne__(self, url):
- return not self.__eq__(url)
-
def default(value, default):
if value is None:
return default
diff --git a/python/setup.py b/python/setup.py
index 65cb72854f..9c04421c51 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -298,7 +298,7 @@ class install_lib(_install_lib):
return outfiles + extra
setup(name="qpid-python",
- version="0.13",
+ version="0.9",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
packages=["mllib", "qpid", "qpid.messaging", "qpid.tests",
diff --git a/ruby/LICENSE.txt b/ruby/LICENSE.txt
new file mode 100755
index 0000000000..6b0b1270ff
--- /dev/null
+++ b/ruby/LICENSE.txt
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/ruby/Makefile b/ruby/Makefile
new file mode 100644
index 0000000000..9cac3207c0
--- /dev/null
+++ b/ruby/Makefile
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+SASL_DIR = ext/sasl
+SASL_MODULE = $(SASL_DIR)/sasl.so
+RUBY_LIB = lib
+SPEC_CACHE_SCRIPT = sc.rb
+
+.PHONY: spec_cache all clean distclean
+
+all : build
+
+$(SASL_MODULE) : $(SASL_DIR)/sasl.c
+ cd $(SASL_DIR); ruby extconf.rb
+ $(MAKE) -C $(SASL_DIR)
+
+spec_cache :
+ echo "require 'qpid'" > $(SPEC_CACHE_SCRIPT)
+ echo "Qpid::Spec010::load()" >> $(SPEC_CACHE_SCRIPT)
+ ruby -I $(RUBY_LIB) -I $(SASL_DIR) $(SPEC_CACHE_SCRIPT)
+ rm $(SPEC_CACHE_SCRIPT)
+
+build: $(SASL_MODULE) spec_cache
+
+clean:
+ cd $(SASL_DIR); make clean
+
+distclean:
+ cd $(SASL_DIR); make distclean
+ rm -rf $(RUBY_LIB)/qpid/spec_cache
+
diff --git a/ruby/NOTICE.txt b/ruby/NOTICE.txt
new file mode 100644
index 0000000000..fff2bca45c
--- /dev/null
+++ b/ruby/NOTICE.txt
@@ -0,0 +1,19 @@
+=========================================================================
+== NOTICE file corresponding to the section 4 d of ==
+== the Apache License, Version 2.0, ==
+== in this case for the Apache Qpid distribution. ==
+=========================================================================
+
+This product includes software developed by the Apache Software Foundation
+(http://www.apache.org/).
+
+Please read the LICENSE.txt file present in the root directory of this
+distribution.
+
+
+Aside from contributions to the Apache Qpid project, this software also
+includes (binary only):
+
+ - None at this time.
+
+
diff --git a/ruby/README.txt b/ruby/README.txt
new file mode 100644
index 0000000000..330f9c6f61
--- /dev/null
+++ b/ruby/README.txt
@@ -0,0 +1,26 @@
+= Running hello-world.rb =
+
+The ruby client includes a simple hello-world example that publishes
+and consumes a message. You can find this in the examples
+directory. This example requires a running broker.
+
+You can set RUBYLIB to the directories containing the Qpid ruby
+library and the SASL extension, then run the example from the command
+line. These are found in the ./lib and ./ext/sasl subdirectories.
+
+$ export RUBYLIB=/home/me/qpid/ruby/lib:/home/me/qpid/ruby/ext/sasl
+$ ./hello-world.rb
+#<Qpid::Message:0xb761c378 @headers=[#<struct Struct::Qpid_Message_properties content_length=nil, message_id=nil, correlation_id=nil, reply_to=nil, content_type="text/plain", content_encoding=nil, user_id=nil, app_id=nil, application_headers=nil, st_type=message_properties, id=nil>, #<struct Struct::Qpid_Delivery_properties discard_unroutable=nil, immediate=nil, redelivered=nil, priority=nil, delivery_mode=nil, ttl=nil, timestamp=nil, expiration=nil, exchange="", routing_key="test-queue", resume_id=nil, resume_ttl=nil, st_type=delivery_properties, id=nil>], @body="Hello World!", @id=#<Qpid::Serial:0xb76450fc @value=0>>
+
+Alternatively, you can specify the library paths using $ ruby -I:
+
+$ ruby -I /home/me/qpid/ruby/lib:/home/me/qpid/ruby/ext/sasl hello-world.rb
+#<Qpid::Message:0xb7504a44 @headers=[#<struct Struct::Qpid_Message_properties content_length=nil, message_id=nil, correlation_id=nil, reply_to=nil, content_type="text/plain", content_encoding=nil, user_id=nil, app_id=nil, application_headers=nil, st_type=message_properties, id=nil>, #<struct Struct::Qpid_Delivery_properties discard_unroutable=nil, immediate=nil, redelivered=nil, priority=nil, delivery_mode=nil, ttl=nil, timestamp=nil, expiration=nil, exchange="", routing_key="test-queue", resume_id=nil, resume_ttl=nil, st_type=delivery_properties, id=nil>], @body="Hello World!", @id=#<Qpid::Serial:0xb752d548 @value=0>>
+
+= Running the Tests =
+
+The "tests" directory contains a collection of unit tests for the ruby
+client. These can be run from the 'ruby' directory with the Rakefile
+provided:
+
+$ rake test
diff --git a/ruby/RELEASE_NOTES b/ruby/RELEASE_NOTES
new file mode 100644
index 0000000000..90e7297e47
--- /dev/null
+++ b/ruby/RELEASE_NOTES
@@ -0,0 +1,10 @@
+Apache Qpid Ruby 0.8 Release Notes
+---------------------------------
+
+The Qpid 0.8 release of the ruby client contains support the for AMQP
+0-10 & 0-8 specifications. See:
+
+http://www.amqp.org/confluence/display/AMQP/AMQP+Specification
+
+The README file provided contains some details on installing and using
+the ruby client that is included with this distribution.
diff --git a/ruby/Rakefile b/ruby/Rakefile
new file mode 100644
index 0000000000..9b0878813d
--- /dev/null
+++ b/ruby/Rakefile
@@ -0,0 +1,116 @@
+#
+# 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.
+#
+
+# Rakefile for ruby-rpm -*- ruby -*-
+require 'rake/clean'
+require 'rake/testtask'
+require 'rake/gempackagetask'
+require 'pathname'
+
+PKG_NAME='ruby-qpid'
+PKG_VERSION='0.10.2'
+GEM_NAME='qpid'
+
+EXT_CONF="ext/sasl/extconf.rb"
+MAKEFILE="ext/sasl/Makefile"
+SASL_MODULE="ext/sasl/sasl.so"
+SASL_SRC=SASL_MODULE.gsub(/.so$/, ".c")
+
+#
+# Additional files for clean/clobber
+#
+
+CLEAN.include [ "**/*~", "lib/*/spec_cache", SASL_MODULE, "ext/**/*.o" ]
+
+CLOBBER.include [ "config.save", "ext/**/mkmf.log",
+ MAKEFILE ]
+
+file MAKEFILE => EXT_CONF do |t|
+ Dir::chdir(File::dirname(EXT_CONF)) do
+ unless sh "ruby #{File::basename(EXT_CONF)}"
+ $stderr.puts "Failed to run extconf"
+ break
+ end
+ end
+end
+
+file SASL_MODULE => [ MAKEFILE, SASL_SRC ] do |t|
+ Dir::chdir(File::dirname(EXT_CONF)) do
+ unless sh "make"
+ $stderr.puts "make failed"
+ break
+ end
+ end
+end
+desc "Build the native library and AMQP spec cache"
+task :build => :spec_cache
+
+Rake::TestTask.new(:test) do |t|
+ t.test_files = FileList['tests/*.rb'].exclude("tests/util.rb")
+ t.libs = [ 'lib', 'ext/sasl' ]
+end
+
+Rake::TestTask.new(:"test_0-8") do |t|
+ t.test_files = FileList["tests_0-8/*.rb"]
+ t.libs = [ 'lib', 'ext/sasl' ]
+end
+
+desc "Create cached versions of the AMQP specs"
+task :spec_cache => SASL_MODULE do |t|
+ pid = fork do
+ $:.insert(0, "lib", "ext/sasl")
+ require 'qpid'
+ Qpid::Spec010::load()
+ end
+ Process.wait(pid)
+end
+
+#
+# Packaging
+#
+
+PKG_FILES = FileList[
+ "LICENSE.txt", "NOTICE.txt",
+ "Rakefile", "RELEASE_NOTES",
+ "lib/**/*.rb", "lib/**/*.xml", "lib/**/*.dtd", "lib/*/spec_cache/*.rb*",
+ "tests/**/*", "examples/**", "ext/**/*.[ch]", "ext/**/MANIFEST",
+ "ext/**/extconf.rb"
+]
+
+DIST_FILES = FileList[
+ "pkg/*.tgz", "pkg/*.gem"
+]
+
+SPEC = Gem::Specification.new do |s|
+ s.name = GEM_NAME
+ s.version = PKG_VERSION
+ s.email = "dev@qpid.apache.org"
+ s.homepage = "http://cwiki.apache.org/qpid/"
+ s.summary = "Ruby client for Qpid"
+ s.files = PKG_FILES
+ s.required_ruby_version = '>= 1.8.1'
+ s.description = "Ruby client for Qpid"
+ s.extensions << 'ext/sasl/extconf.rb'
+end
+
+Rake::GemPackageTask.new(SPEC) do |pkg|
+ task pkg.package_dir => [ :spec_cache ]
+ pkg.need_tar = true
+ pkg.need_zip = true
+end
diff --git a/ruby/examples/hello-world.rb b/ruby/examples/hello-world.rb
new file mode 100755
index 0000000000..e8ef673316
--- /dev/null
+++ b/ruby/examples/hello-world.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/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.
+#
+
+require "qpid"
+require "socket"
+
+broker = if ARGV.length > 0 then ARGV[0] else "localhost" end
+port = if ARGV.length > 1 then ARGV[1].to_i else 5672 end
+if ARGV.length > 2 then
+ puts "usage: hello-world.rb [ <broker> [ <port> ] ]"
+ exit 1
+end
+
+conn = Qpid::Connection.new(TCPSocket.new(broker, port))
+conn.start(10)
+
+ssn = conn.session("test")
+
+# create a queue
+ssn.queue_declare("test-queue")
+
+ssn.exchange_declare("test-exchange", :type => "direct")
+
+# Publish a message
+dp = ssn.delivery_properties(:routing_key => "test-queue")
+mp = ssn.message_properties(:content_type => "text/plain")
+msg = Qpid::Message.new(dp, mp, "Hello World!")
+ssn.message_transfer(:message => msg)
+
+# subscribe to a queue
+ssn.message_subscribe(:destination => "messages", :queue => "test-queue",
+ :accept_mode => ssn.message_accept_mode.none)
+incoming = ssn.incoming("messages")
+
+# start incoming message flow
+incoming.start()
+
+# grab a message from the queue
+p incoming.get(10)
+
+# cancel the subscription and close the session and connection
+ssn.message_cancel(:destination => "messages")
+ssn.close()
+conn.close()
diff --git a/ruby/examples/qmf-libvirt.rb b/ruby/examples/qmf-libvirt.rb
new file mode 100644
index 0000000000..492f4fe8d6
--- /dev/null
+++ b/ruby/examples/qmf-libvirt.rb
@@ -0,0 +1,80 @@
+#!/usr/bin/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.
+#
+
+require "qpid"
+
+s = Qpid::Qmf::Session.new()
+b = s.add_broker("amqp://localhost:5672")
+
+while true:
+ nodes = s.objects(:class => "node")
+ nodes.each do |node|
+ puts "node: #{node.hostname}"
+ for (key, val) in node.properties
+ puts " property: #{key}, #{val}"
+ end
+
+ # Find any domains that on the current node.
+ domains = s.objects(:class => "domain", 'node' => node.object_id)
+ domains.each do |domain|
+ r = domain.getXMLDesc()
+ puts "status: #{r.status}"
+ if r.status == 0
+ puts "xml description: #{r.description}"
+ puts "length: #{r.description.length}"
+ end
+
+ puts " domain: #{domain.name}, state: #{domain.state}, id: #{domain.id}"
+ for (key, val) in domain.properties
+ puts " property: #{key}, #{val}"
+ end
+ end
+
+ pools = s.objects(:class => "pool", 'node' => node.object_id)
+ pools.each do |pool|
+ puts " pool: #{pool.name}"
+ for (key, val) in pool.properties
+ puts " property: #{key}, #{val}"
+ end
+
+ r = pool.getXMLDesc()
+ puts "status: #{r.status}"
+ puts "text: #{r.text}"
+ if r.status == 0
+ puts "xml description: #{r.description}"
+ puts "length: #{r.description.length}"
+ end
+
+ # Find volumes that are part of the pool.
+ volumes = s.objects(:class => "volume", 'pool' => pool.object_id)
+ volumes.each do |volume|
+ puts " volume: #{volume.name}"
+ for (key, val) in volume.properties
+ puts " property: #{key}, #{val}"
+ end
+ end
+ end
+
+ end
+
+ puts '----------------------------'
+ sleep(5)
+
+end
diff --git a/ruby/ext/sasl/extconf.rb b/ruby/ext/sasl/extconf.rb
new file mode 100644
index 0000000000..56841f34e3
--- /dev/null
+++ b/ruby/ext/sasl/extconf.rb
@@ -0,0 +1,28 @@
+#
+# 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 'mkmf'
+
+extension_name = 'sasl'
+have_library("c", "main")
+
+unless have_library("sasl2")
+ raise "Package cyrus-sasl-devel not found"
+end
+
+create_makefile(extension_name)
diff --git a/ruby/ext/sasl/sasl.c b/ruby/ext/sasl/sasl.c
new file mode 100644
index 0000000000..2d4e40d30e
--- /dev/null
+++ b/ruby/ext/sasl/sasl.c
@@ -0,0 +1,472 @@
+/*
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <string.h>
+#include <sasl/sasl.h>
+#include <ruby.h>
+
+static VALUE mSasl;
+
+#define INPUT_SIZE 512
+#define MECH_SIZE 32
+
+typedef void* sasl_context_t;
+
+#define QSASL_OK 0
+#define QSASL_CONTINUE 1
+#define QSASL_FAILED 2
+
+typedef struct {
+ char magic[8];
+ sasl_conn_t* conn;
+ sasl_callback_t callbacks[8];
+ char* userName;
+ char* password;
+ char* operUserName;
+ unsigned int minSsf;
+ unsigned int maxSsf;
+ char mechanism[MECH_SIZE];
+ char input[INPUT_SIZE];
+} context_t;
+
+//
+// Resolve forward references
+//
+static VALUE qsasl_free(int, VALUE*, VALUE);
+
+//
+// Validate an input string to ensure that it is either NULL or of reasonable size.
+//
+static int qsasl_valid(char* str)
+{
+ int idx;
+
+ if (str == 0)
+ return 1;
+
+ for (idx = 0; idx < INPUT_SIZE; idx++) {
+ if (str[idx] == '\0')
+ return 1;
+ }
+
+ return 0;
+}
+
+//
+// SASL callback for identity and authentication identity.
+//
+static int qsasl_cb_user(void* _context, int id, const char **result, unsigned *len)
+{
+ context_t* context = (context_t*) _context;
+
+ if (context->userName)
+ *result = context->userName;
+
+ return SASL_OK;
+}
+
+//
+// SASL callback for passwords.
+//
+static int qsasl_cb_password(sasl_conn_t* conn, void* _context, int id, sasl_secret_t **psecret)
+{
+ context_t* context = (context_t*) _context;
+ sasl_secret_t* secret;
+ size_t length;
+
+ if (context->password)
+ length = strlen(context->password);
+ else
+ length = 0;
+
+ secret = (sasl_secret_t*) malloc(sizeof(sasl_secret_t) + length);
+ secret->len = length;
+ if (length)
+ memcpy(secret->data, context->password, length);
+ *psecret = secret;
+
+ return SASL_OK;
+}
+
+//
+// Interactively prompt the user for authentication data.
+//
+static void qsasl_prompt(sasl_context_t _context, sasl_interact_t* interact)
+{
+ context_t* context = (context_t*) _context;
+ char *pass;
+ char *input;
+ char passwdPrompt[100];
+
+ if (interact->id == SASL_CB_PASS) {
+ strncpy(passwdPrompt, interact->prompt, 95);
+ strcat(passwdPrompt, ": ");
+ pass = getpass(passwdPrompt);
+ strncpy(context->input, pass, INPUT_SIZE - 1);
+ context->input[INPUT_SIZE - 1] = '\0';
+ } else {
+ printf(interact->prompt);
+ if (interact->defresult) {
+ printf(" (%s)", interact->defresult);
+ }
+ printf(": ");
+ input = fgets(context->input, INPUT_SIZE, stdin);
+ if (input != context->input) {
+ rb_raise(rb_eRuntimeError, "Unexpected EOF on interactive prompt");
+ }
+ }
+
+ interact->result = context->input;
+ interact->len = strlen(context->input);
+}
+
+//
+// Initialize the SASL client library.
+//
+static VALUE qsasl_client_init()
+{
+ int result;
+
+ result = sasl_client_init(0);
+ if (result != SASL_OK)
+ rb_raise(rb_eRuntimeError,
+ "sasl_client_init failed: %d - %s",
+ result, sasl_errstring(result, -0, 0));
+ return Qnil;
+}
+
+//
+// Allocate a new SASL client context.
+//
+static VALUE qsasl_client_new(int argc, VALUE *argv, VALUE obj)
+{
+ char* mechanism = 0;
+ char* serviceName = 0;
+ char* hostName = 0;
+ char* userName = 0;
+ char* password = 0;
+ unsigned int minSsf = 0;
+ unsigned int maxSsf = 65535;
+
+ int result;
+ int i = 0;
+ context_t *context;
+ sasl_security_properties_t secprops;
+
+ if (argc != 7)
+ rb_raise(rb_eRuntimeError, "Wrong number of arguments");
+
+ if (!NIL_P(argv[0]))
+ mechanism = StringValuePtr(argv[0]);
+ if (!NIL_P(argv[1]))
+ serviceName = StringValuePtr(argv[1]);
+ if (!NIL_P(argv[2]))
+ hostName = StringValuePtr(argv[2]);
+ if (!NIL_P(argv[3]))
+ userName = StringValuePtr(argv[3]);
+ if (!NIL_P(argv[4]))
+ password = StringValuePtr(argv[4]);
+ minSsf = FIX2INT(argv[5]);
+ maxSsf = FIX2INT(argv[6]);
+
+ if (!qsasl_valid(mechanism) || !qsasl_valid(serviceName) ||
+ !qsasl_valid(hostName) || !qsasl_valid(userName) ||
+ !qsasl_valid(password)) {
+ rb_raise(rb_eRuntimeError, "Invalid string argument");
+ }
+
+ context = (context_t*) malloc(sizeof(context_t));
+ memset(context, 0, sizeof(context_t));
+ strcpy(context->magic, "QSASL01");
+
+ context->minSsf = minSsf;
+ context->maxSsf = maxSsf;
+ if (mechanism != 0) {
+ strncpy(context->mechanism, mechanism, MECH_SIZE - 1);
+ context->mechanism[MECH_SIZE - 1] = '\0';
+ }
+
+ context->callbacks[i].id = SASL_CB_GETREALM;
+ context->callbacks[i].proc = 0;
+ context->callbacks[i++].context = 0;
+
+ if (userName != 0 && userName[0] != '\0') {
+ context->userName = (char*) malloc(strlen(userName) + 1);
+ strcpy(context->userName, userName);
+
+ context->callbacks[i].id = SASL_CB_USER;
+ context->callbacks[i].proc = qsasl_cb_user;
+ context->callbacks[i++].context = context;
+
+ context->callbacks[i].id = SASL_CB_AUTHNAME;
+ context->callbacks[i].proc = qsasl_cb_user;
+ context->callbacks[i++].context = context;
+ }
+
+ context->callbacks[i].id = SASL_CB_PASS;
+ if (password != 0 && password[0] != '\0') {
+ context->password = (char*) malloc(strlen(password) + 1);
+ strcpy(context->password, password);
+
+ context->callbacks[i].proc = qsasl_cb_password;
+ } else
+ context->callbacks[i].proc = 0;
+ context->callbacks[i++].context = context;
+
+ context->callbacks[i].id = SASL_CB_LIST_END;
+ context->callbacks[i].proc = 0;
+ context->callbacks[i++].context = 0;
+
+ result = sasl_client_new(serviceName, hostName, 0, 0,
+ context->callbacks, 0, &context->conn);
+
+ if (result != SASL_OK) {
+ context->conn = 0;
+ qsasl_free(1, (VALUE*) &context, Qnil);
+ rb_raise(rb_eRuntimeError, "sasl_client_new failed: %d - %s",
+ result, sasl_errstring(result, 0, 0));
+ }
+
+ secprops.min_ssf = minSsf;
+ secprops.max_ssf = maxSsf;
+ secprops.maxbufsize = 65535;
+ secprops.property_names = 0;
+ secprops.property_values = 0;
+ secprops.security_flags = 0;//TODO: provide means for application to configure these
+
+ result = sasl_setprop(context->conn, SASL_SEC_PROPS, &secprops);
+ if (result != SASL_OK) {
+ qsasl_free(1, (VALUE*) &context, Qnil);
+ rb_raise(rb_eRuntimeError, "sasl_setprop failed: %d - %s",
+ result, sasl_errdetail(context->conn));
+ }
+
+ return (VALUE) context;
+}
+
+//
+// Free a SASL client context.
+//
+static VALUE qsasl_free(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+
+ if (argc == 1)
+ context = (context_t*) argv[0];
+ else
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+
+ if (context->conn)
+ sasl_dispose(&context->conn);
+ if (context->userName)
+ free(context->userName);
+ if (context->password)
+ free(context->password);
+ if (context->operUserName)
+ free(context->operUserName);
+ free(context);
+
+ return Qnil;
+}
+
+//
+// Start the SASL exchange from the client's point of view.
+//
+static VALUE qsasl_client_start(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+ char* mechList;
+ char* mechToUse;
+ int result;
+ int propResult;
+ const char* response;
+ unsigned int len;
+ sasl_interact_t* interact = 0;
+ const char* chosen;
+ const char* operName;
+
+ if (argc == 2) {
+ context = (context_t*) argv[0];
+ mechList = StringValuePtr(argv[1]);
+ } else
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+
+ if (strlen(context->mechanism) == 0)
+ mechToUse = mechList;
+ else
+ mechToUse = context->mechanism;
+
+ do {
+ result = sasl_client_start(context->conn, mechToUse, &interact,
+ &response, &len, &chosen);
+ if (result == SASL_INTERACT) {
+ qsasl_prompt(context, interact);
+ }
+ } while (result == SASL_INTERACT);
+
+ if (result != SASL_OK && result != SASL_CONTINUE)
+ rb_raise(rb_eRuntimeError, "sasl_client_start failed: %d - %s",
+ result, sasl_errdetail(context->conn));
+
+ if (result == SASL_OK) {
+ propResult = sasl_getprop(context->conn, SASL_USERNAME, (const void**) &operName);
+ if (propResult == SASL_OK) {
+ context->operUserName = (char*) malloc(strlen(operName) + 1);
+ strcpy(context->operUserName, operName);
+ }
+ }
+
+ return rb_ary_new3(3, INT2NUM(result), rb_str_new(response, len), rb_str_new2(chosen));
+}
+
+//
+// Take a step in the SASL exchange (only needed for multi-challenge mechanisms).
+//
+static VALUE qsasl_client_step(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+ VALUE challenge;
+ int result;
+ int propResult;
+ const char* response;
+ const char* operName;
+ unsigned int len;
+ sasl_interact_t* interact = 0;
+
+ if (argc == 2) {
+ context = (context_t*) argv[0];
+ challenge = argv[1];
+ }
+ else
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+
+ do {
+ result = sasl_client_step(context->conn,
+ RSTRING(challenge)->ptr, RSTRING(challenge)->len,
+ &interact, &response, &len);
+ if (result == SASL_INTERACT) {
+ qsasl_prompt(context, interact);
+ }
+ } while (result == SASL_INTERACT);
+
+ if (result != SASL_OK && result != SASL_CONTINUE)
+ return QSASL_FAILED;
+
+ if (result == SASL_OK) {
+ propResult = sasl_getprop(context->conn, SASL_USERNAME, (const void**) &operName);
+ if (propResult == SASL_OK) {
+ context->operUserName = (char*) malloc(strlen(operName) + 1);
+ strcpy(context->operUserName, operName);
+ }
+ }
+
+ return rb_ary_new3(2, INT2NUM(result), rb_str_new(response, len));
+}
+
+static VALUE qsasl_user_id(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+
+ if (argc == 1) {
+ context = (context_t*) argv[0];
+ } else {
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+ }
+
+ if (context->operUserName)
+ return rb_str_new2(context->operUserName);
+
+ return Qnil;
+}
+
+//
+// Encode transport data for the security layer.
+//
+static VALUE qsasl_encode(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+ VALUE clearText;
+ const char* outBuffer;
+ unsigned int outSize;
+ int result;
+
+ if (argc == 2) {
+ context = (context_t*) argv[0];
+ clearText = argv[1];
+ }
+ else
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+
+ result = sasl_encode(context->conn,
+ RSTRING(clearText)->ptr, RSTRING(clearText)->len,
+ &outBuffer, &outSize);
+ if (result != SASL_OK)
+ rb_raise(rb_eRuntimeError, "sasl_encode failed: %d - %s",
+ result, sasl_errdetail(context->conn));
+
+ return rb_str_new(outBuffer, outSize);
+}
+
+//
+// Decode transport data for the security layer.
+//
+static VALUE qsasl_decode(int argc, VALUE *argv, VALUE obj)
+{
+ context_t* context;
+ VALUE cipherText;
+ const char* outBuffer;
+ unsigned int outSize;
+ int result;
+
+ if (argc == 2) {
+ context = (context_t*) argv[0];
+ cipherText = argv[1];
+ }
+ else
+ rb_raise(rb_eRuntimeError, "Wrong Number of Arguments");
+
+ result = sasl_decode(context->conn,
+ RSTRING(cipherText)->ptr, RSTRING(cipherText)->len,
+ &outBuffer, &outSize);
+ if (result != SASL_OK)
+ rb_raise(rb_eRuntimeError, "sasl_decode failed: %d - %s",
+ result, sasl_errdetail(context->conn));
+
+ return rb_str_new(outBuffer, outSize);
+}
+
+//
+// Initialize the Sasl module.
+//
+void Init_sasl()
+{
+ mSasl = rb_define_module("Sasl");
+
+ rb_define_module_function(mSasl, "client_init", qsasl_client_init, -1);
+ rb_define_module_function(mSasl, "client_new", qsasl_client_new, -1);
+ rb_define_module_function(mSasl, "free", qsasl_free, -1);
+ rb_define_module_function(mSasl, "client_start", qsasl_client_start, -1);
+ rb_define_module_function(mSasl, "client_step", qsasl_client_step, -1);
+ rb_define_module_function(mSasl, "user_id", qsasl_user_id, -1);
+ rb_define_module_function(mSasl, "encode", qsasl_encode, -1);
+ rb_define_module_function(mSasl, "decode", qsasl_decode, -1);
+}
diff --git a/ruby/lib/qpid.rb b/ruby/lib/qpid.rb
new file mode 100644
index 0000000000..1c719e9b1d
--- /dev/null
+++ b/ruby/lib/qpid.rb
@@ -0,0 +1,41 @@
+#
+# 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
+ def self.logger
+ @logger ||= {}
+ @logger
+ end
+end
+
+require "qpid/util"
+require "qpid/queue"
+require "qpid/packer"
+require "qpid/framer"
+require "qpid/codec"
+require 'qpid/datatypes'
+require 'qpid/spec010'
+require 'qpid/delegates'
+require 'qpid/invoker'
+require "qpid/assembler"
+require 'qpid/session'
+require "qpid/connection"
+require "qpid/spec"
+require 'qpid/queue'
+require 'qpid/qmf'
diff --git a/ruby/lib/qpid/assembler.rb b/ruby/lib/qpid/assembler.rb
new file mode 100644
index 0000000000..b768c3f195
--- /dev/null
+++ b/ruby/lib/qpid/assembler.rb
@@ -0,0 +1,148 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Qpid
+
+ class << self
+ attr_accessor :asm_logger
+ end
+
+ class Segment
+
+ attr_reader :type, :payload, :track, :channel
+ attr_accessor :id, :offset
+
+ def initialize(first, last, type, track, channel, payload)
+ @id = nil
+ @offset = nil
+ @first = first
+ @last = last
+ @type = type
+ @track = track
+ @channel = channel
+ @payload = payload
+ end
+
+ def first_segment? ; @first ; end
+
+ def last_segment? ; @last ; end
+
+ def decode(spec)
+ segs = spec[:segment_type]
+ choice = segs.enum.choices[type]
+ return method("decode_#{choice.name}").call(spec)
+ end
+
+ def decode_control(spec)
+ sc = StringCodec.new(spec, payload)
+ return sc.read_control()
+ end
+
+ def decode_command(spec)
+ sc = StringCodec.new(spec, payload)
+ hdr, cmd = sc.read_command()
+ cmd.id = id
+ return hdr, cmd
+ end
+
+ def decode_header(spec)
+ sc = StringCodec.new(spec, payload)
+ values = []
+ until sc.encoded.empty?
+ values << sc.read_struct32()
+ end
+ return values
+ end
+
+ def decode_body(spec)
+ payload
+ end
+
+ def append(frame)
+ @payload += frame.payload
+ end
+
+ def to_s
+ f = first_segment? ? 'F' : '.'
+ l = last_segment? ? 'L' : '.'
+ return "%s%s %s %s %s %s" % [f, l, @type,
+ @track, @channel, @payload.inspect]
+ end
+
+ end
+
+ class Assembler < Framer
+
+ def logger; Qpid::asm_logger; end
+
+ def initialize(sock, max_payload = Frame::MAX_PAYLOAD)
+ super(sock)
+ @max_payload = max_payload
+ @fragments = {}
+ end
+
+ def read_segment
+ loop do
+ frame = read_frame
+ key = [frame.channel, frame.track]
+ seg = @fragments[key]
+ unless seg
+ seg = Segment.new(frame.first_segment?,
+ frame.last_segment?,
+ frame.type, frame.track,
+ frame.channel, "")
+ @fragments[key] = seg
+ end
+
+ seg.append(frame)
+
+ if frame.last_frame?
+ @fragments.delete(key)
+ logger.debug("RECV #{seg}") if logger
+ return seg
+ end
+ end
+ end
+
+ def write_segment(segment)
+ remaining = segment.payload
+
+ first = true
+ while first or remaining
+ payload = remaining[0, @max_payload]
+ remaining = remaining[@max_payload, remaining.size]
+
+ flags = 0
+
+ flags |= FIRST_FRM if first
+ flags |= LAST_FRM unless remaining
+ flags |= FIRST_SEG if segment.first_segment?
+ flags |= LAST_SEG if segment.last_segment?
+
+ frame = Frame.new(flags, segment.type, segment.track,
+ segment.channel, payload)
+ write_frame(frame)
+
+ first = false
+ end
+
+ logger.debug("SENT #{segment}") if logger
+ end
+ end
+end
diff --git a/ruby/lib/qpid/client.rb b/ruby/lib/qpid/client.rb
new file mode 100644
index 0000000000..ec3d100a9c
--- /dev/null
+++ b/ruby/lib/qpid/client.rb
@@ -0,0 +1,136 @@
+#
+# 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 "thread"
+require "qpid/peer"
+require "qpid/queue"
+
+module Qpid08
+
+ class Client
+ def initialize(host, port, spec, vhost = "/")
+ @host = host
+ @port = port
+ @spec = spec
+ @vhost = vhost
+
+ @mechanism = nil
+ @response = nil
+ @locale = nil
+
+ @queues = {}
+ @mutex = Mutex.new()
+
+ @closed = false
+ @code = nil
+ @started = ConditionVariable.new()
+
+ @conn = Connection.new(@host, @port, @spec)
+ @peer = Peer.new(@conn, ClientDelegate.new(self))
+ end
+
+ attr_reader :mechanism, :response, :locale
+
+ def closed?; @closed end
+ def closed=(value); @closed = value end
+ def code; @code end
+
+ def wait()
+ @mutex.synchronize do
+ @started.wait(@mutex)
+ end
+ raise EOFError.new() if closed?
+ end
+
+ def signal_start()
+ @started.broadcast()
+ end
+
+ def queue(key)
+ @mutex.synchronize do
+ q = @queues[key]
+ if q.nil?
+ q = Queue.new()
+ @queues[key] = q
+ end
+ return q
+ end
+ end
+
+ def start(response, mechanism="AMQPLAIN", locale="en_US")
+ @response = response
+ @mechanism = mechanism
+ @locale = locale
+
+ @conn.connect()
+ @conn.init()
+ @peer.start()
+ wait()
+ channel(0).connection_open(@vhost)
+ end
+
+ def channel(id)
+ return @peer.channel(id)
+ end
+
+ def close(msg = nil)
+ @closed = true
+ @code = msg
+ @peer.close()
+ end
+ end
+
+ class ClientDelegate
+
+ include Delegate
+
+ def initialize(client)
+ @client = client
+ end
+
+ def connection_start(ch, msg)
+ ch.connection_start_ok(:mechanism => @client.mechanism,
+ :response => @client.response,
+ :locale => @client.locale)
+ end
+
+ def connection_tune(ch, msg)
+ ch.connection_tune_ok(*msg.fields)
+ @client.signal_start()
+ end
+
+ def connection_close(ch, msg)
+ puts "CONNECTION CLOSED: #{msg.args.join(", ")}"
+ @client.close(msg)
+ end
+
+ def channel_close(ch, msg)
+ puts "CHANNEL[#{ch.id}] CLOSED: #{msg.args.join(", ")}"
+ ch.channel_close_ok()
+ ch.close()
+ end
+
+ def basic_deliver(ch, msg)
+ queue = @client.queue(msg.consumer_tag)
+ queue << msg
+ end
+
+ end
+
+end
diff --git a/ruby/lib/qpid/codec.rb b/ruby/lib/qpid/codec.rb
new file mode 100644
index 0000000000..a3b5d101c4
--- /dev/null
+++ b/ruby/lib/qpid/codec.rb
@@ -0,0 +1,457 @@
+#
+# 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/packer.rb'
+require 'iconv'
+
+module Qpid
+
+ class Codec
+
+ include Qpid::Packer
+
+ attr_reader :spec
+
+ def initialize(spec = "")
+ @spec = spec
+ end
+
+ def write_void(v)
+ unless v.nil?
+ raise Exception.new("void not nil: #{v}")
+ end
+ end
+
+ def read_void
+ return nil
+ end
+
+ def write_bit(b)
+ unless b
+ raise Exception.new("bit is nil: #{b}")
+ end
+ end
+
+ def read_bit
+ return true
+ end
+
+ def read_uint8
+ return unpack("C", 1)
+ end
+
+ def write_uint8(n)
+ return pack("C", n)
+ end
+
+ def read_int8
+ return unpack("c", 1)
+ end
+
+ def write_int8(n)
+ pack("c", n)
+ end
+
+ def read_char
+ return unpack("c", 1)
+ end
+
+ def write_char(c)
+ pack("c")
+ end
+
+ def read_boolean
+ return read_uint8 != 0
+ end
+
+ def write_boolean(b)
+ n = 0
+ n = 1 if b != 0
+ write_uint8(n)
+ end
+
+ def read_uint16
+ return unpack("n", 2)
+ end
+
+ def write_uint16(n)
+ pack("n", n)
+ end
+
+ def read_int16
+ # XXX: holy moly.. pack/unpack doesn't have signed network byte order. Crazy hackery.
+ val = unpack("n", 2)
+ val -= 2 ** 16 if val >= 2 ** 15
+ return val
+ end
+
+ def write_int16(n)
+ # XXX: Magically this one works even though it's not signed.
+ pack("n", n)
+ end
+
+ def read_uint32
+ return unpack("N", 4)
+ end
+
+ def write_uint32(n)
+ pack("N", n)
+ end
+
+ def read_int32
+ # Again no pack/unpack for signed int
+ return unpack("N", 4)
+ end
+
+ def write_int32(n)
+ # FIXME
+ pack("N", n)
+ end
+
+ def read_float
+ return unpack("g", 4)
+ end
+
+ def write_float(n)
+ pack("g", n)
+ end
+
+ def read_sequence_no
+ return read_uint32.to_serial
+ end
+
+ def write_sequence_no(n)
+ write_uint32(n.value)
+ end
+
+ def encode_64bit(num, signed = false)
+ b = []
+
+ if num < 0 && signed
+ num += 2 ** 64
+ end
+
+ (0..7).each do |c|
+ d = 7 - c
+ b[c] = (num & (0xff << d * 8)) >> d * 8
+ end
+ pack('C8', *b)
+ end
+
+
+ def decode_64bit(signed = false)
+ # Silly ruby pack/unpack does not implement 64 bit network byte order
+ # encode/decode.
+ a = unpack('C8', 8)
+ num = 0
+ (0..7).each do |c|
+ d = 7 - c
+ num |= a[c] << 8 * d
+ end
+
+ if signed && num >= 2 ** 63
+ num -= 2 ** 64
+ end
+ return num
+ end
+
+ def read_uint64
+ return decode_64bit
+ end
+
+ def write_uint64(n)
+ encode_64bit(n)
+ end
+
+ def read_int64
+ return decode_64bit(signed = true)
+ end
+
+ def write_int64(n)
+ encode_64bit(n, signed = true)
+ end
+
+ def read_datetime
+ return read_uint64
+ end
+
+ def write_datetime(n)
+ write_uint64(n)
+ end
+
+ def read_double
+ return unpack("G", 8)
+ end
+
+ def write_double(n)
+ pack("G", n)
+ end
+
+ def read_vbin8
+ # XXX
+ return read(read_uint8)
+ end
+
+ def write_vbin8(b)
+ # XXX
+ write_uint8(b.length)
+ write(b)
+ end
+
+ def read_str8
+ # FIXME: Check iconv.. I think this will throw if there are odd characters.
+ return Iconv.conv("ASCII", "UTF-8", read_vbin8)
+ end
+
+ def write_str8(s)
+ write_vbin8(Iconv.conv("UTF-8", "ASCII", s))
+ end
+
+ def read_str16
+ return Iconv.conv("ASCII", "UTF-8", read_vbin16)
+ end
+
+ def write_str16(s)
+ write_vbin16(Iconv.conv("UTF-8", "ASCII", s))
+ end
+
+ def read_vbin16
+ # XXX: Using read method?
+ return read(read_uint16)
+ end
+
+ def write_vbin16(b)
+ write_uint16(b.length)
+ write(b)
+ end
+
+ def read_sequence_set
+ # FIXME: Need datatypes
+ result = RangedSet.new
+ size = read_uint16
+ nranges = size / 8
+ nranges.times do |i|
+ lower = read_sequence_no
+ upper = read_sequence_no
+ result.add(lower, upper)
+ end
+ return result
+ end
+
+ def write_sequence_set(ss)
+ size = 8 * ss.ranges.length
+ write_uint16(size)
+ ss.ranges.each do |range|
+ write_sequence_no(range.lower)
+ write_sequence_no(range.upper)
+ end
+ end
+
+ def read_vbin32
+ return read(read_uint32)
+ end
+
+ def write_vbin32(b)
+ write_uint32(b.length)
+ write(b)
+ end
+
+ def write_map(m)
+ sc = StringCodec.new(@spec)
+ unless m.nil?
+ sc.write_uint32(m.size)
+ m.each do |k, v|
+ unless type = @spec.encoding(v.class)
+ raise Exception.new("no encoding for: #{v.class}")
+ end
+ sc.write_str8(k)
+ sc.write_uint8(type.code)
+ type.encode(sc, v)
+ end
+ end
+ write_vbin32(sc.encoded)
+ end
+
+ def read_map
+ sc = StringCodec.new(@spec, read_vbin32)
+ return nil unless sc.encoded
+ count = sc.read_uint32
+ result = nil
+ if count
+ result = {}
+ until sc.encoded.empty?
+ k = sc.read_str8
+ code = sc.read_uint8
+ type = @spec.types[code]
+ v = type.decode(sc)
+ result[k] = v
+ end
+ end
+ return result
+ end
+
+ def write_array(a)
+ sc = StringCodec.new(@spec)
+ unless a.nil?
+ if a.length > 0
+ type = @spec.encoding(a[0].class)
+ else
+ type = @spec.encoding(nil.class)
+ end
+ sc.write_uint8(type.code)
+ sc.write_uint32(a.size)
+ a.each { |o| type.encode(sc, o) }
+ end
+ write_vbin32(sc.encoded)
+ end
+
+ def read_array
+ sc = StringCodec.new(@spec, read_vbin32)
+ return nil if not sc.encoded
+ type = @spec.types[sc.read_uint8]
+ count = sc.read_uint32
+ result = nil
+ if count
+ result = []
+ count.times { |i| result << (type.decode(sc)) }
+ end
+ return result
+ end
+
+ def write_list(l)
+ sc = StringCodec.new(@spec)
+ unless l.nil?
+ sc.write_uint32(l.length)
+ l.each do |o|
+ type = @spec.encoding(o.class)
+ sc.write_uint8(type.code)
+ type.encode(sc, o)
+ end
+ end
+ write_vbin32(sc.encoded)
+ end
+
+ def read_list
+ sc = StringCodec.new(@spec, read_vbin32)
+ return nil if not sc.encoded
+ count = sc.read_uint32
+ result = nil
+ if count
+ result = []
+ count.times do |i|
+ type = @spec.types[sc.read_uint8]
+ result << type.decode(sc)
+ end
+ end
+ return result
+ end
+
+ def read_struct32
+ size = read_uint32
+ code = read_uint16
+ type = @spec.structs[code]
+ # XXX: BLEH!
+ fields = type.decode_fields(self)
+ return Qpid::struct(type, fields)
+ end
+
+ def write_struct32(value)
+ type = value.st_type
+ sc = StringCodec.new(@spec)
+ sc.write_uint16(type.code)
+ type.encode_fields(sc, value)
+ write_vbin32(sc.encoded)
+ end
+
+ def read_control
+ cntrl = @spec.controls[read_uint16]
+ return Qpid::struct(cntrl, cntrl.decode_fields(self))
+ end
+
+ def write_control(ctrl)
+ type = ctrl.st_type
+ write_uint16(type.code)
+ type.encode_fields(self, ctrl)
+ end
+
+ def read_command
+ type = @spec.commands[read_uint16]
+ hdr = @spec[:header].decode(self)
+ cmd = Qpid::struct(type, type.decode_fields(self))
+ return hdr, cmd
+ end
+
+ def write_command(hdr, cmd)
+ type = cmd.st_type
+ write_uint16(type.code)
+ hdr.st_type.encode(self, hdr)
+ type.encode_fields(self, cmd)
+ end
+
+ def read_size(width)
+ if width > 0
+ return send(:"read_uint#{width * 8}")
+ end
+ end
+
+ def write_size(width, n)
+ if width > 0
+ send(:"write_uint#{width * 8}", n)
+ end
+ end
+
+ def read_uuid
+ return unpack("a16", 16)
+ end
+
+ def write_uuid(s)
+ pack("a16", s)
+ end
+
+ def read_bin128
+ return unpack("a16", 16)
+ end
+
+ def write_bin128(b)
+ pack("a16", b)
+ end
+
+ end
+
+ class StringCodec < Codec
+
+ def initialize(spec, encoded = "")
+ @spec = spec
+ @encoded = encoded
+ end
+
+ attr_reader :encoded
+
+ def write(s)
+ @encoded += s
+ end
+
+ def read(n)
+ return "" if n.nil?
+ result = @encoded[0...n]
+ @encoded = @encoded[n...@encoded.size] || ""
+ return result
+ end
+ end
+end
diff --git a/ruby/lib/qpid/codec08.rb b/ruby/lib/qpid/codec08.rb
new file mode 100644
index 0000000000..148dee07bb
--- /dev/null
+++ b/ruby/lib/qpid/codec08.rb
@@ -0,0 +1,265 @@
+#
+# 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 Qpid08
+ # is there a better way to do this?
+ class StringWriter
+
+ def initialize(str = "")
+ @str = str
+ end
+
+ def write(value)
+ @str << value
+ end
+
+ def to_s()
+ return @str
+ end
+
+ end
+
+ class EOF < Exception; end
+
+ class Encoder
+
+ def initialize(out)
+ @out = out
+ @bits = []
+ end
+
+ attr_reader(:out)
+
+ def encode(type, value)
+ send(type, value)
+ end
+
+ def bit(b)
+ @bits << b
+ end
+
+ def octet(o)
+ pack("C", o)
+ end
+
+ def short(s)
+ pack("n", s)
+ end
+
+ def long(l)
+ pack("N", l)
+ end
+
+ def longlong(l)
+ lower = l & 0xffffffff
+ upper = (l & ~0xffffffff) >> 32
+ long(upper)
+ long(lower)
+ end
+
+ def timestamp(l)
+ longlong(l)
+ end
+
+ def shortstr(s)
+ # shortstr is actually octetstr
+ octet(s.length)
+ write(s)
+ end
+
+ def longstr(s)
+ case s
+ when Hash
+ table(s)
+ else
+ long(s.length)
+ write(s)
+ end
+ end
+
+ def table(t)
+ t = {} if t.nil?
+ enc = Encoder.new(StringWriter.new())
+ t.each {|key, value|
+ enc.shortstr(key)
+ # I offer this chicken to the gods of polymorphism. May they
+ # choke on it.
+ case value
+ when String
+ type = :longstr
+ desc = "S"
+ when Numeric
+ type = :long
+ desc = "I"
+ else
+ raise Exception.new("unknown table value: #{value.class}")
+ end
+ enc.write(desc)
+ enc.encode(type, value)
+ }
+ longstr(enc.out.to_s())
+ end
+
+ def write(str)
+ flushbits()
+ @out.write(str)
+ # puts "OUT #{str.inspect()}"
+ end
+
+ def pack(fmt, *args)
+ write(args.pack(fmt))
+ end
+
+ def flush()
+ flushbits()
+ end
+
+ private
+
+ def flushbits()
+ if @bits.empty? then return end
+
+ bytes = []
+ index = 0
+ @bits.each {|b|
+ bytes << 0 if index == 0
+ if b then bytes[-1] |= 1 << index end
+ index = (index + 1) % 8
+ }
+ @bits.clear()
+ bytes.each {|b|
+ octet(b)
+ }
+ end
+
+ end
+
+ class StringReader
+
+ def initialize(str)
+ @str = str
+ @index = 0
+ end
+
+ def read(n)
+ result = @str[@index, n]
+ @index += result.length
+ return result
+ end
+
+ end
+
+ class Decoder
+
+ def initialize(_in)
+ @in = _in
+ @bits = []
+ end
+
+ def decode(type)
+ return send(type)
+ end
+
+ def bit()
+ if @bits.empty?
+ byte = octet()
+ 7.downto(0) {|i|
+ @bits << (byte[i] == 1)
+ }
+ end
+ return @bits.pop()
+ end
+
+ def octet()
+ return unpack("C", 1)
+ end
+
+ def short()
+ return unpack("n", 2)
+ end
+
+ def long()
+ return unpack("N", 4)
+ end
+
+ def longlong()
+ upper = long()
+ lower = long()
+ return upper << 32 | lower
+ end
+
+ def timestamp()
+ return longlong()
+ end
+
+ def shortstr()
+ # shortstr is actually octetstr
+ return read(octet())
+ end
+
+ def longstr()
+ return read(long())
+ end
+
+ def table()
+ dec = Decoder.new(StringReader.new(longstr()))
+ result = {}
+ while true
+ begin
+ key = dec.shortstr()
+ rescue EOF
+ break
+ end
+ desc = dec.read(1)
+ case desc
+ when "S"
+ value = dec.longstr()
+ when "I"
+ value = dec.long()
+ else
+ raise Exception.new("unrecognized descriminator: #{desc.inspect()}")
+ end
+ result[key] = value
+ end
+ return result
+ end
+
+ def read(n)
+ return "" if n == 0
+ result = @in.read(n)
+ if result.nil? or result.empty?
+ raise EOF.new()
+ else
+ # puts " IN #{result.inspect()}"
+ return result
+ end
+ end
+
+ def unpack(fmt, size)
+ result = read(size).unpack(fmt)
+ if result.length == 1
+ return result[0]
+ else
+ return result
+ end
+ end
+
+ end
+
+end
diff --git a/ruby/lib/qpid/config.rb b/ruby/lib/qpid/config.rb
new file mode 100644
index 0000000000..b5b79cd309
--- /dev/null
+++ b/ruby/lib/qpid/config.rb
@@ -0,0 +1,32 @@
+#
+# 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 Config
+
+ def self.amqp_spec
+ dirs = [File::expand_path(File::join(File::dirname(__FILE__), "specs"))]
+ dirs.each do |d|
+ spec = File::join(d, "amqp.0-10-qpid-errata.xml")
+ return spec if File::exists? spec
+ end
+ end
+
+ end
+end
diff --git a/ruby/lib/qpid/connection.rb b/ruby/lib/qpid/connection.rb
new file mode 100644
index 0000000000..d2efbfb263
--- /dev/null
+++ b/ruby/lib/qpid/connection.rb
@@ -0,0 +1,222 @@
+#
+# 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 'monitor'
+
+module Qpid
+
+ class ChannelBusy< Exception ; end
+
+ class ChannelsBusy < Exception ; end
+
+ class SessionBusy < Exception ; end
+
+ class ConnectionFailed < Exception ; end
+
+ class Timeout < Exception ; end
+
+ class Connection < Assembler
+
+ include MonitorMixin
+
+ attr_reader :spec, :attached, :sessions, :thread
+ attr_accessor :opened, :failed, :close_code, :user_id
+
+ def initialize(sock, args={})
+ super(sock)
+
+ delegate = args[:delegate] || Qpid::Delegate::Client.method(:new)
+ spec = args[:spec] || nil
+
+ @spec = Qpid::Spec010::load(spec)
+ @track = @spec["track"]
+
+ @attached = {}
+ @sessions = {}
+
+ @condition = new_cond
+ @opened = false
+ @failed = false
+ @close_code = [nil, "connection aborted"]
+
+ @thread = nil
+
+ @channel_max = 65535
+ @user_id = nil
+
+ @delegate = delegate.call(self, args)
+ end
+
+ def attach(name, ch, delegate, force=false)
+ synchronize do
+ ssn = @attached[ch.id]
+ if ssn
+ raise ChannelBusy.new(ch, ssn) unless ssn.name == name
+ else
+ ssn = @sessions[name]
+ if ssn.nil?
+ ssn = Session.new(name, @spec, :delegate => delegate)
+ @sessions[name] = ssn
+ elsif ssn.channel
+ if force
+ @attached.delete(ssn.channel.id)
+ ssn.channel = nil
+ else
+ raise SessionBusy.new(ssn)
+ end
+ end
+ @attached[ch.id] = ssn
+ ssn.channel = ch
+ end
+ ch.session = ssn
+ return ssn
+ end
+ end
+
+ def detach(name, ch)
+ synchronize do
+ @attached.delete(ch.id)
+ ssn = @sessions.delete(name)
+ if ssn
+ ssn.channel = nil
+ ssn.closed
+ return ssn
+ end
+ end
+ end
+
+ def session(name, kwargs = {})
+ timeout = kwargs[:timeout]
+ delegate = kwargs[:delegate] || Qpid::Session::Client.method(:new)
+
+ # FIXME: Python has cryptic comment about 'ch 0 ?'
+ channel = (0..@channel_max).detect { |i| ! @attached.key?(i) }
+ raise ChannelsBusy unless channel
+
+ synchronize do
+ ch = Channel.new(self, channel)
+ ssn = attach(name, ch, delegate)
+ ssn.channel.session_attach(name)
+ if ssn.wait_for(timeout) { ssn.channel }
+ return ssn
+ else
+ detach(name, ch)
+ raise Timeout
+ end
+ end
+ end
+
+ def detach_all
+ synchronize do
+ attached.values.each do |ssn|
+ ssn.exceptions << @close_code unless @close_code[0] == 200
+ detach(ssn.name, ssn.channel)
+ end
+ end
+ end
+
+ def start(timeout=nil)
+ @delegate.start
+ @thread = Thread.new { run }
+ @thread[:name] = 'conn'
+ synchronize do
+ unless @condition.wait_for(timeout) { @opened || @failed }
+ raise Timeout
+ end
+ end
+ if @failed
+ raise ConnectionFailed.new(@close_code)
+ end
+ end
+
+ def run
+ # XXX: we don't really have a good way to exit this loop without
+ # getting the other end to kill the socket
+ loop do
+ begin
+ seg = read_segment
+ rescue Qpid::Closed => e
+ detach_all
+ break
+ end
+ @delegate.received(seg)
+ end
+ end
+
+ def close(timeout=nil)
+ return unless @opened
+ Channel.new(self, 0).connection_close(200)
+ synchronize do
+ unless @condition.wait_for(timeout) { ! @opened }
+ raise Timeout
+ end
+ end
+ @thread.join(timeout)
+ @thread = nil
+ end
+
+ def signal
+ synchronize { @condition.signal }
+ end
+
+ def to_s
+ # FIXME: We'd like to report something like HOST:PORT
+ return @sock.to_s
+ end
+
+ class Channel < Invoker
+
+ attr_reader :id, :connection
+ attr_accessor :session
+
+ def initialize(connection, id)
+ @connection = connection
+ @id = id
+ @session = nil
+ end
+
+ def resolve_method(name)
+ inst = @connection.spec[name]
+ if inst.is_a?(Qpid::Spec010::Control)
+ return invocation(:method, inst)
+ else
+ return invocation(:error, nil)
+ end
+ end
+
+ def invoke(type, args)
+ ctl = type.create(*args)
+ sc = StringCodec.new(@connection.spec)
+ sc.write_control(ctl)
+ @connection.write_segment(Segment.new(true, true, type.segment_type,
+ type.track, self.id, sc.encoded))
+
+ log = Qpid::logger["qpid.io.ctl"]
+ log.debug("SENT %s", ctl) if log
+ end
+
+ def to_s
+ return "#{@connection}[#{@id}]"
+ end
+
+ end
+
+ end
+
+end
diff --git a/ruby/lib/qpid/connection08.rb b/ruby/lib/qpid/connection08.rb
new file mode 100644
index 0000000000..09a4888cc4
--- /dev/null
+++ b/ruby/lib/qpid/connection08.rb
@@ -0,0 +1,252 @@
+#
+# 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 "socket"
+require "qpid/codec08"
+
+module Qpid08
+
+ class Connection
+
+ def initialize(host, port, spec)
+ @host = host
+ @port = port
+ @spec = spec
+ end
+
+ attr_reader(:host, :port, :spec)
+
+ def connect()
+ @sock = TCPSocket.open(@host, @port)
+ @out = Encoder.new(@sock)
+ @in = Decoder.new(@sock)
+ end
+
+ def init()
+ @out.write("AMQP")
+ [1, 1, @spec.major, @spec.minor].each {|o|
+ @out.octet(o)
+ }
+ end
+
+ def write(frame)
+ # puts "OUT #{frame.inspect()}"
+ @out.octet(@spec.constants[frame.payload.type].id)
+ @out.short(frame.channel)
+ frame.payload.encode(@out)
+ @out.octet(frame_end)
+ end
+
+ def read()
+ type = @spec.constants[@in.octet()].name
+ channel = @in.short()
+ payload = Payload.decode(type, @spec, @in)
+ oct = @in.octet()
+ if oct != frame_end
+ raise Exception.new("framing error: expected #{frame_end}, got #{oct}")
+ end
+ frame = Frame.new(channel, payload)
+ # puts " IN #{frame.inspect}"
+ return frame
+ end
+
+ private
+
+ def frame_end
+ @spec.constants[:"frame_end"].id
+ end
+
+ end
+
+ class Frame
+
+ def initialize(channel, payload)
+ @channel = channel
+ @payload = payload
+ end
+
+ attr_reader(:channel, :payload)
+
+ end
+
+ class Payload
+
+ TYPES = {}
+
+ def Payload.singleton_method_added(name)
+ if name == :type
+ TYPES[type] = self
+ end
+ end
+
+ def Payload.decode(type, spec, dec)
+ klass = TYPES[type]
+ klass.decode(spec, dec)
+ end
+
+ end
+
+ class Method < Payload
+
+ def initialize(method, args)
+ if args.size != method.fields.size
+ raise ArgumentError.new("argument mismatch #{method} #{args}")
+ end
+ @method = method
+ @args = args
+ end
+
+ attr_reader(:method, :args)
+
+ def Method.type; :frame_method end
+
+ def type; Method.type end
+
+ def encode(encoder)
+ buf = StringWriter.new()
+ enc = Encoder.new(buf)
+ enc.short(@method.parent.id)
+ enc.short(@method.id)
+ @method.fields.zip(self.args).each {|f, a|
+ if a.nil?; a = f.default end
+ enc.encode(f.type, a)
+ }
+ enc.flush()
+ encoder.longstr(buf.to_s)
+ end
+
+ def Method.decode(spec, decoder)
+ buf = decoder.longstr()
+ dec = Decoder.new(StringReader.new(buf))
+ klass = spec.classes[dec.short()]
+ meth = klass.methods[dec.short()]
+ args = meth.fields.map {|f| dec.decode(f.type)}
+ return Method.new(meth, args)
+ end
+
+ def inspect(); "#{method.qname}(#{args.join(", ")})" end
+
+ end
+
+ class Header < Payload
+
+ def Header.type; :frame_header end
+
+ def initialize(klass, weight, size, properties)
+ @klass = klass
+ @weight = weight
+ @size = size
+ @properties = properties
+ end
+
+ attr_reader :weight, :size, :properties
+
+ def type; Header.type end
+
+ def encode(encoder)
+ buf = StringWriter.new()
+ enc = Encoder.new(buf)
+ enc.short(@klass.id)
+ enc.short(@weight)
+ enc.longlong(@size)
+
+ # property flags
+ nprops = @klass.fields.size
+ flags = 0
+ 0.upto(nprops - 1) do |i|
+ f = @klass.fields[i]
+ flags <<= 1
+ flags |= 1 unless @properties[f.name].nil?
+ # the last bit indicates more flags
+ if i > 0 and (i % 15) == 0
+ flags <<= 1
+ if nprops > (i + 1)
+ flags |= 1
+ enc.short(flags)
+ flags = 0
+ end
+ end
+ end
+ flags <<= ((16 - (nprops % 15)) % 16)
+ enc.short(flags)
+
+ # properties
+ @klass.fields.each do |f|
+ v = @properties[f.name]
+ enc.encode(f.type, v) unless v.nil?
+ end
+ enc.flush()
+ encoder.longstr(buf.to_s)
+ end
+
+ def Header.decode(spec, decoder)
+ dec = Decoder.new(StringReader.new(decoder.longstr()))
+ klass = spec.classes[dec.short()]
+ weight = dec.short()
+ size = dec.longlong()
+
+ # property flags
+ bits = []
+ while true
+ flags = dec.short()
+ 15.downto(1) do |i|
+ if flags >> i & 0x1 != 0
+ bits << true
+ else
+ bits << false
+ end
+ end
+ break if flags & 0x1 == 0
+ end
+
+ # properties
+ properties = {}
+ bits.zip(klass.fields).each do |b, f|
+ properties[f.name] = dec.decode(f.type) if b
+ end
+ return Header.new(klass, weight, size, properties)
+ end
+
+ def inspect(); "#{@klass.name}(#{@properties.inspect()})" end
+
+ end
+
+ class Body < Payload
+
+ def Body.type; :frame_body end
+
+ def type; Body.type end
+
+ def initialize(content)
+ @content = content
+ end
+
+ attr_reader :content
+
+ def encode(enc)
+ enc.longstr(@content)
+ end
+
+ def Body.decode(spec, dec)
+ return Body.new(dec.longstr())
+ end
+
+ end
+
+end
diff --git a/ruby/lib/qpid/datatypes.rb b/ruby/lib/qpid/datatypes.rb
new file mode 100644
index 0000000000..418388c73a
--- /dev/null
+++ b/ruby/lib/qpid/datatypes.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
+
+ def self.struct(type, *args)
+ # FIXME: This is fragile; the last arg could be a hash,
+ # without being hte keywords
+ kwargs = {}
+ kwargs = args.pop if args.any? && args[-1].is_a?(Hash)
+
+ if args.size > type.fields.size
+ raise TypeError,
+ "%s() takes at most %d arguments (%d given)" %
+ [type.name, type.fields.size, args.size]
+ end
+
+ attrs = type.fields.inject({}) do |attrs, field|
+ if args.any?
+ attrs[field.name] = args.shift
+ if kwargs.key?(field.name)
+ raise TypeError,
+ "%s() got multiple values for keyword argument '%s'" %
+ [type.name, field.name]
+ end
+ elsif kwargs.key?(field.name)
+ attrs[field.name] = kwargs.delete(field.name)
+ else
+ attrs[field.name] = field.default
+ end
+ attrs
+ end
+
+ unless kwargs.empty?
+ unexpected = kwargs.keys[0]
+ raise TypeError,
+ "%s() got an unexpected keyword argument '%s'" %
+ [type.name, unexpected]
+ end
+
+ attrs[:st_type] = type
+ attrs[:id] = nil
+
+ name = "Qpid_" + type.name.to_s.capitalize
+ unless ::Struct.const_defined?(name)
+ vars = type.fields.collect { |f| f.name } << :st_type << :id
+ ::Struct.new(name, *vars)
+ end
+ st = ::Struct.const_get(name)
+
+ result = st.new
+ attrs.each { |k, v| result[k] = v }
+ return result
+ end
+
+ class Message
+
+ attr_accessor :headers, :body, :id
+
+ def initialize(*args)
+ @body = nil
+ @headers = nil
+
+ @body = args.pop unless args.empty?
+ @headers = args unless args.empty?
+
+ @id = nil
+ end
+
+ def has(name)
+ return ! get(name).nil?
+ end
+
+ def get(name)
+ if @headers
+ name = name.to_sym
+ @headers.find { |h| h.st_type.name == name }
+ end
+ end
+
+ def set(header)
+ @headers ||= []
+ if h = @headers.find { |h| h.st_type == header.st_type }
+ ind = @headers.index(h)
+ @headers[ind] = header
+ else
+ @headers << header
+ end
+ end
+
+ def clear(name)
+ if @headers
+ name = name.to_sym
+ @headers.delete_if { |h| h.st_type.name == name }
+ end
+ end
+
+ # FIXME: Not sure what to do here
+ # Ruby doesn't have a notion of a evaluable string representation
+ # def __repr__(self):
+ # args = []
+ # if self.headers:
+ # args.extend(map(repr, self.headers))
+ # if self.body:
+ # args.append(repr(self.body))
+ # if self.id is not None:
+ # args.append("id=%s" % self.id)
+ # return "Message(%s)" % ", ".join(args)
+ # end
+ end
+
+ class ::Object
+
+ def to_serial
+ Qpid::Serial.new(self)
+ end
+ end
+
+ class Serial
+
+ include Comparable
+
+ attr_accessor :value
+
+ def initialize(value)
+ @value = value & 0xFFFFFFFF
+ end
+
+ def hash
+ @value.hash
+ end
+
+ def to_serial
+ self
+ end
+
+ def eql?(other)
+ other = other.to_serial
+ value.eql?(other.value)
+ end
+
+ def <=>(other)
+ return 1 if other.nil?
+
+ other = other.to_serial
+
+ delta = (value - other.value) & 0xFFFFFFFF
+ neg = delta & 0x80000000
+ mag = delta & 0x7FFFFFFF
+
+ return (neg>0) ? -mag : mag
+ end
+
+ def +(other)
+ result = other.to_serial
+ result.value += value
+ return result
+ end
+
+ def -(other)
+ result = other.to_serial
+ result.value = value - result.value
+ return result
+ end
+
+ def succ
+ Serial.new(value + 1)
+ end
+
+ # FIXME: Not sure what to do here
+ # Ruby doesn't have a notion of a evaluable string representation
+ # def __repr__(self):
+ # return "serial(%s)" % self.value
+ # end
+
+ def to_s
+ value.to_s
+ end
+
+ end
+
+ # The Python class datatypes.Range is emulated by the standard
+ # Range class with a few additions
+ class ::Range
+
+ alias :lower :begin
+ alias :upper :end
+
+ def touches(r)
+ # XXX: are we doing more checks than we need?
+ return (r.include?(lower - 1) ||
+ r.include?(upper + 1) ||
+ include?(r.lower - 1) ||
+ include?(r.upper + 1) ||
+ r.include?(lower) ||
+ r.include?(upper) ||
+ include?(r.lower) ||
+ include?(r.upper))
+ end
+
+ def span(r)
+ Range.new([lower, r.lower].min, [upper, r.upper].max)
+ end
+
+ def intersect(r)
+ l = [lower, r.lower].max
+ u = [upper, r.upper].min
+ return l > u ? nil : Range.new(l, u)
+ end
+
+ end
+
+ class RangedSet
+
+ include Enumerable
+
+ attr_accessor :ranges
+
+ def initialize(*args)
+ @ranges = []
+ args.each { |n| add(n) }
+ end
+
+ def each(&block)
+ ranges.each { |r| yield(r) }
+ end
+
+ def include?(n)
+ if (n.is_a?(Range))
+ super(n)
+ else
+ ranges.find { |r| r.include?(n) }
+ end
+ end
+
+ def add_range(range)
+ ranges.delete_if do |r|
+ if range.touches(r)
+ range = range.span(r)
+ true
+ else
+ false
+ end
+ end
+ ranges << range
+ end
+
+ def add(lower, upper = nil)
+ upper = lower if upper.nil?
+ add_range(Range.new(lower, upper))
+ end
+
+ def to_s
+ repr = ranges.sort { |a,b| b.lower <=> a.lower }.
+ map { |r| r.to_s }.join(",")
+ "<RangedSet: {#{repr}}"
+ end
+ end
+
+ class Future
+ def initialize(initial=nil, exception=Exception)
+ @value = initial
+ @error = nil
+ @set = Util::Event.new
+ @exception = exception
+ end
+
+ def error(error)
+ @error = error
+ @set.set
+ end
+
+ def set(value)
+ @value = value
+ @set.set
+ end
+
+ def get(timeout=nil)
+ @set.wait(timeout)
+ unless @error.nil?
+ raise @exception.new(@error)
+ end
+ @value
+ end
+ end
+
+ class UUID
+ include Comparable
+
+ attr_accessor :bytes
+
+ def initialize(bytes)
+ @bytes = bytes
+ end
+
+ def <=>(other)
+ if other.respond_to?(:bytes)
+ return bytes <=> other.bytes
+ else
+ raise NotImplementedError
+ end
+ end
+
+ def to_s
+ UUID::format(bytes)
+ end
+
+ # FIXME: Not sure what to do here
+ # Ruby doesn't have a notion of a evaluable string representation
+ # def __repr__(self):
+ # return "UUID(%r)" % str(self)
+ # end
+
+ def self.random_uuid
+ bytes = (1..16).collect { |i| rand(256) }
+
+ # From RFC4122, the version bits are set to 0100
+ bytes[7] &= 0x0F
+ bytes[7] |= 0x40
+
+ # From RFC4122, the top two bits of byte 8 get set to 01
+ bytes[8] &= 0x3F
+ bytes[8] |= 0x80
+ return bytes.pack("C16")
+ end
+
+ def self.uuid4
+ UUID.new(random_uuid)
+ end
+
+ def self.format(s)
+ # Python format !LHHHHL
+ # big-endian, ulong, ushort x 4, ulong
+ "%08x-%04x-%04x-%04x-%04x%08x" % s.unpack("NnnnnN")
+ end
+ end
+end
diff --git a/ruby/lib/qpid/delegates.rb b/ruby/lib/qpid/delegates.rb
new file mode 100644
index 0000000000..f779047e05
--- /dev/null
+++ b/ruby/lib/qpid/delegates.rb
@@ -0,0 +1,237 @@
+#
+# 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 'rbconfig'
+require 'sasl'
+
+module Qpid
+
+ class Delegate
+
+ def initialize(connection, args={})
+ @connection = connection
+ @spec = connection.spec
+ @delegate = args[:delegate] || Qpid::Delegate::Client.method(:new)
+ @control = @spec[:track].enum[:control].value
+ end
+
+ def log ; Qpid::logger["qpid.io.ctl"]; end
+
+ def received(seg)
+ ssn = @connection.attached[seg.channel]
+ unless ssn
+ ch = Qpid::Connection::Channel.new(@connection, seg.channel)
+ else
+ ch = ssn.channel
+ end
+
+ if seg.track == @control
+ ctl = seg.decode(@spec)
+ log.debug("RECV %s", ctl) if log
+ attr = ctl.st_type.name
+ method(attr).call(ch, ctl)
+ elsif ssn.nil?
+ ch.session_detached
+ else
+ ssn.received(seg)
+ end
+ end
+
+ def connection_close(ch, close)
+ @connection.close_code = [close.reply_code, close.reply_text]
+ ch.connection_close_ok
+ @connection.sock.close_write()
+ unless @connection.opened
+ @connection.failed = true
+ @connection.signal
+ end
+ end
+
+ def connection_close_ok(ch, close_ok)
+ @connection.opened = false
+ @connection.signal
+ end
+
+ def session_attach(ch, a)
+ begin
+ @connection.attach(a.name, ch, @delegate, a.force)
+ ch.session_attached(a.name)
+ rescue Qpid::ChannelBusy
+ ch.session_detached(a.name)
+ rescue Qpid::SessionBusy
+ ch.session_detached(a.name)
+ end
+ end
+
+ def session_attached(ch, a)
+ ch.session.signal
+ end
+
+ def session_detach(ch, d)
+ #send back the confirmation of detachment before removing the
+ #channel from the attached set; this avoids needing to hold the
+ #connection lock during the sending of this control and ensures
+ #that if the channel is immediately reused for a new session the
+ #attach request will follow the detached notification.
+ ch.session_detached(d.name)
+ ssn = @connection.detach(d.name, ch)
+ end
+
+ def session_detached(ch, d)
+ @connection.detach(d.name, ch)
+ end
+
+ def session_request_timeout(ch, rt)
+ ch.session_timeout(rt.timeout)
+ end
+
+ def session_command_point(ch, cp)
+ ssn = ch.session
+ ssn.receiver.next_id = cp.command_id
+ ssn.receiver.next_offset = cp.command_offset
+ end
+
+ def session_completed(ch, cmp)
+ ch.session.sender.has_completed(cmp.commands)
+ if cmp.timely_reply
+ ch.session_known_completed(cmp.commands)
+ end
+ ch.session.signal
+ end
+
+ def session_known_completed(ch, kn_cmp)
+ ch.session.receiver.known_completed(kn_cmp.commands)
+ end
+
+ def session_flush(ch, f)
+ rcv = ch.session.receiver
+ if f.expected
+ if rcv.next_id
+ exp = Qpid::RangedSet.new(rcv.next_id)
+ else
+ exp = nil
+ end
+ ch.session_expected(exp)
+ end
+ if f.confirmed
+ ch.session_confirmed(rcv.completed)
+ end
+ if f.completed
+ ch.session_completed(rcv.completed)
+ end
+ end
+
+ class Server < Delegate
+
+ def start
+ @connection.read_header()
+ @connection.write_header(@spec.major, @spec.minor)
+ ch = Qpid::Connection::Channel.new(@connection, 0)
+ ch.connection_start(:mechanisms => ["ANONYMOUS"])
+ ch
+ end
+
+ def connection_start_ok(ch, start_ok)
+ ch.connection_tune(:channel_max => 65535)
+ end
+
+ def connection_tune_ok(ch, tune_ok)
+ nil
+ end
+
+ def connection_open(ch, open)
+ @connection.opened = true
+ ch.connection_open_ok()
+ @connection.signal
+ end
+ end
+
+ class Client < Delegate
+
+ # FIXME: Python uses os.name for platform - we don't have an exact
+ # analog in Ruby
+ PROPERTIES = {"product" => "qpid python client",
+ "version" => "development",
+ "platform" => Config::CONFIG["build_os"],
+ "qpid.client_process" => File.basename($0),
+ "qpid.client_pid" => Process.pid,
+ "qpid.client_ppid" => Process.ppid}
+
+
+ def initialize(connection, args)
+ super(connection)
+
+ result = Sasl::client_init
+
+ @mechanism= args[:mechanism]
+ @username = args[:username]
+ @password = args[:password]
+ @service = args[:service] || "qpidd"
+ @min_ssf = args[:min_ssf] || 0
+ @max_ssf = args[:max_ssf] || 65535
+
+ @saslConn = Sasl.client_new(@mechanism, @service, args[:host],
+ @username, @password, @min_ssf, @max_ssf)
+ end
+
+ def start
+ @connection.write_header(@spec.major, @spec.minor)
+ @connection.read_header
+ end
+
+ def connection_start(ch, start)
+ mech_list = ""
+ start.mechanisms.each do |m|
+ mech_list += m + " "
+ end
+ begin
+ resp = Sasl.client_start(@saslConn, mech_list)
+ @connection.user_id = Sasl.user_id(@saslConn)
+ ch.connection_start_ok(:client_properties => PROPERTIES,
+ :mechanism => resp[2],
+ :response => resp[1])
+ rescue exception
+ ch.connection_close(:message => $!.message)
+ @connection.failed = true
+ @connection.signal
+ end
+ end
+
+ def connection_secure(ch, secure)
+ resp = Sasl.client_step(@saslConn, secure.challenge)
+ @connection.user_id = Sasl.user_id(@saslConn)
+ ch.connection_secure_ok(:response => resp[1])
+ end
+
+ def connection_tune(ch, tune)
+ ch.connection_tune_ok(:channel_max => tune.channel_max,
+ :max_frame_size => tune.max_frame_size,
+ :heartbeat => 0)
+ ch.connection_open()
+ @connection.security_layer_tx = @saslConn
+ end
+
+ def connection_open_ok(ch, open_ok)
+ @connection.security_layer_rx = @saslConn
+ @connection.opened = true
+ @connection.signal
+ end
+ end
+ end
+end
diff --git a/ruby/lib/qpid/fields.rb b/ruby/lib/qpid/fields.rb
new file mode 100644
index 0000000000..cc87d07529
--- /dev/null
+++ b/ruby/lib/qpid/fields.rb
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+class Class
+ def fields(*fields)
+ module_eval {
+ def initialize(*args, &block)
+ args = init_fields(*args)
+
+ if respond_to? :init
+ init(*args) {|*a| yield(*a)}
+ elsif args.any?
+ raise ArgumentError, "extra arguments: #{args.inspect}"
+ end
+ end
+ }
+
+ vars = fields.map {|f| :"@#{f.to_s().chomp("?")}"}
+
+ define_method(:init_fields) {|*args|
+ vars.each {|v|
+ instance_variable_set(v, args.shift())
+ }
+ args
+ }
+
+ vars.each_index {|i|
+ define_method(fields[i]) {
+ instance_variable_get(vars[i])
+ }
+ }
+ end
+end
diff --git a/ruby/lib/qpid/framer.rb b/ruby/lib/qpid/framer.rb
new file mode 100644
index 0000000000..d057605383
--- /dev/null
+++ b/ruby/lib/qpid/framer.rb
@@ -0,0 +1,212 @@
+#
+# 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 'monitor'
+require 'logger'
+require 'sasl'
+
+module Qpid
+
+ FIRST_SEG = 0x08
+ LAST_SEG = 0x04
+ FIRST_FRM = 0x02
+ LAST_FRM = 0x01
+
+ class << self
+ attr_accessor :raw_logger, :frm_logger
+ end
+
+ def self.packed_size(format)
+ # FIXME: This is a total copout to simulate Python's
+ # struct.calcsize
+ ([0]*256).pack(format).size
+ end
+
+ class Frame
+ attr_reader :payload, :track, :flags, :type, :channel
+
+ # HEADER = "!2BHxBH4x"
+ # Python Meaning Ruby
+ # ! big endian (implied by format char)
+ # 2B 2 uchar C2
+ # H unsigned short n
+ # x pad byte x
+ # B uchar C
+ # H unsigned short n
+ # 4x pad byte x4
+ HEADER = "C2nxCnx4"
+ HEADER_SIZE = Qpid::packed_size(HEADER)
+ MAX_PAYLOAD = 65535 - HEADER_SIZE
+
+ def initialize(flags, type, track, channel, payload)
+ if payload.size > MAX_PAYLOAD
+ raise ArgumentError, "max payload size exceeded: #{payload.size}"
+ end
+
+ @flags = flags
+ @type = type
+ @track = track
+ @channel = channel
+ @payload = payload
+ end
+
+ def first_segment? ; FIRST_SEG & @flags > 0 ; end
+
+ def last_segment? ; LAST_SEG & @flags > 0 ; end
+
+ def first_frame? ; FIRST_FRM & @flags > 0 ; end
+
+ def last_frame? ; LAST_FRM & @flags > 0 ; end
+
+ def to_s
+ fs = first_segment? ? 'S' : '.'
+ ls = last_segment? ? 's' : '.'
+ ff = first_frame? ? 'F' : '.'
+ lf = last_frame? ? 'f' : '.'
+
+ return "%s%s%s%s %s %s %s %s" % [fs, ls, ff, lf,
+ @type,
+ @track,
+ @channel,
+ @payload.inspect]
+ end
+ end
+
+ class FramingError < Exception ; end
+
+ class Closed < Exception ; end
+
+ class Framer
+ include Packer
+
+ # Python: "!4s4B"
+ HEADER = "a4C4"
+ HEADER_SIZE = 8
+
+ def raw
+ Qpid::raw_logger
+ end
+
+ def frm
+ Qpid::frm_logger
+ end
+
+ def initialize(sock)
+ @sock = sock
+ @sock.extend(MonitorMixin)
+ @tx_buf = ""
+ @rx_buf = ""
+ @security_layer_tx = nil
+ @security_layer_rx = nil
+ @maxbufsize = 65535
+ end
+
+ attr_reader :sock
+ attr_accessor :security_layer_tx, :security_layer_rx
+
+ def aborted? ; false ; end
+
+ def write(buf)
+ @tx_buf += buf
+ end
+
+ def flush
+ @sock.synchronize do
+ if @security_layer_tx
+ cipher_buf = Sasl.encode(@security_layer_tx, @tx_buf)
+ _write(cipher_buf)
+ else
+ _write(@tx_buf)
+ end
+ @tx_buf = ""
+ frm.debug("FLUSHED") if frm
+ end
+ rescue
+ @sock.close unless @sock.closed?
+ end
+
+ def _write(buf)
+ while buf && buf.size > 0
+ # FIXME: Catch errors
+ n = @sock.write(buf)
+ raw.debug("SENT #{buf[0, n].inspect}") if raw
+ buf[0,n] = ""
+ @sock.flush
+ end
+ end
+
+ def read(n)
+ while @rx_buf.size < n
+ begin
+ s = @sock.recv(@maxbufsize)
+ if @security_layer_rx
+ s = Sasl.decode(@security_layer_rx, s)
+ end
+ rescue IOError => e
+ raise e if @rx_buf != ""
+ @sock.close unless @sock.closed?
+ raise Closed
+ end
+ # FIXME: Catch errors
+ if s.nil? or s.size == 0
+ @sock.close unless @sock.closed?
+ raise Closed
+ end
+ @rx_buf += s
+ raw.debug("RECV #{n}/#{@rx_buf.size} #{s.inspect}") if raw
+ end
+ data = @rx_buf[0, n]
+ @rx_buf = @rx_buf[n, @rx_buf.size - n]
+ return data
+ end
+
+ def read_header
+ unpack(Framer::HEADER, Framer::HEADER_SIZE)
+ end
+
+ def write_header(major, minor)
+ @sock.synchronize do
+ pack(Framer::HEADER, "AMQP", 1, 1, major, minor)
+ flush()
+ end
+ end
+
+ def write_frame(frame)
+ @sock.synchronize do
+ size = frame.payload.size + Frame::HEADER_SIZE
+ track = frame.track & 0x0F
+ pack(Frame::HEADER, frame.flags, frame.type, size, track, frame.channel)
+ write(frame.payload)
+ if frame.last_segment? and frame.last_frame?
+ flush()
+ frm.debug("SENT #{frame}") if frm
+ end
+ end
+ end
+
+ def read_frame
+ flags, type, size, track, channel = unpack(Frame::HEADER, Frame::HEADER_SIZE)
+ raise FramingError if (flags & 0xF0 > 0)
+ payload = read(size - Frame::HEADER_SIZE)
+ frame = Frame.new(flags, type, track, channel, payload)
+ frm.debug("RECV #{frame}") if frm
+ return frame
+ end
+ end
+end
diff --git a/ruby/lib/qpid/invoker.rb b/ruby/lib/qpid/invoker.rb
new file mode 100644
index 0000000000..39716ac6c2
--- /dev/null
+++ b/ruby/lib/qpid/invoker.rb
@@ -0,0 +1,65 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+class Qpid::Invoker
+
+ # Requires that client defines a invoke method and overrides
+ # resolve_method
+
+ # FIXME: Is it really worth defining methods in method_missing ? We
+ # could just dispatch there directly
+
+ def invc_method(name, resolved)
+ define_singleton_method(name) { |*args| invoke(resolved, args) }
+ # FIXME: the Python code also attaches docs from resolved.pydoc
+ end
+
+ def invc_value(name, resolved)
+ define_singleton_method(name) { | | resolved }
+ end
+
+ def invc_error(name, resolved)
+ msg = "%s instance has no attribute '%s'" % [self.class.name, name]
+ if resolved
+ msg += "\n%s" % resolved
+ end
+ raise NameError, msg
+ end
+
+ def resolve_method(name)
+ invocation(:error, nil)
+ end
+
+ def method_missing(name, *args)
+ disp, resolved = resolve_method(name)
+ disp.call(name, resolved)
+ send(name, *args)
+ end
+
+ def invocation(kind, name = nil)
+ [ method("invc_#{kind}"), name ]
+ end
+
+ private
+ def define_singleton_method(name, &body)
+ singleton_class = class << self; self; end
+ singleton_class.send(:define_method, name, &body)
+ end
+
+end
diff --git a/ruby/lib/qpid/packer.rb b/ruby/lib/qpid/packer.rb
new file mode 100644
index 0000000000..ae1be37faf
--- /dev/null
+++ b/ruby/lib/qpid/packer.rb
@@ -0,0 +1,33 @@
+#
+# 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 Packer
+ def unpack(fmt, len)
+ raw = read(len)
+ values = raw.unpack(fmt)
+ values = values[0] if values.size == 1
+ return values
+ end
+
+ def pack(fmt, *args)
+ write(args.pack(fmt))
+ end
+ end
+end
diff --git a/ruby/lib/qpid/peer.rb b/ruby/lib/qpid/peer.rb
new file mode 100644
index 0000000000..cdb962169b
--- /dev/null
+++ b/ruby/lib/qpid/peer.rb
@@ -0,0 +1,289 @@
+#
+# 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 "thread"
+require "qpid/queue"
+require "qpid/connection08"
+require "qpid/fields"
+
+module Qpid08
+
+ Queue = Qpid::Queue
+
+ class Peer
+
+ def initialize(conn, delegate)
+ @conn = conn
+ @delegate = delegate
+ @outgoing = Queue.new()
+ @work = Queue.new()
+ @channels = {}
+ @mutex = Mutex.new()
+ end
+
+ def channel(id)
+ @mutex.synchronize do
+ ch = @channels[id]
+ if ch.nil?
+ ch = Channel.new(id, self, @outgoing, @conn.spec)
+ @channels[id] = ch
+ end
+ return ch
+ end
+ end
+
+ def channel_delete(id)
+ @channels.delete(id)
+ end
+
+ def start()
+ spawn(:writer)
+ spawn(:reader)
+ spawn(:worker)
+ end
+
+ def close()
+ @mutex.synchronize do
+ @channels.each_value do |ch|
+ ch.close()
+ end
+ @outgoing.close()
+ @work.close()
+ end
+ end
+
+ private
+
+ def spawn(method, *args)
+ Thread.new do
+ begin
+ send(method, *args)
+ # is this the standard way to catch any exception?
+ rescue Closed => e
+ puts "#{method} #{e}"
+ rescue Object => e
+ print e
+ e.backtrace.each do |line|
+ print "\n ", line
+ end
+ print "\n"
+ end
+ end
+ end
+
+ def reader()
+ while true
+ frame = @conn.read()
+ ch = channel(frame.channel)
+ ch.dispatch(frame, @work)
+ end
+ end
+
+ def writer()
+ while true
+ @conn.write(@outgoing.get())
+ end
+ end
+
+ def worker()
+ while true
+ dispatch(@work.get())
+ end
+ end
+
+ def dispatch(queue)
+ frame = queue.get()
+ ch = channel(frame.channel)
+ payload = frame.payload
+ if payload.method.content?
+ content = Qpid08::read_content(queue)
+ else
+ content = nil
+ end
+
+ message = Message.new(payload.method, payload.args, content)
+ @delegate.dispatch(ch, message)
+ end
+
+ end
+
+ class Channel
+ def initialize(id, peer, outgoing, spec)
+ @id = id
+ @peer = peer
+ @outgoing = outgoing
+ @spec = spec
+ @incoming = Queue.new()
+ @responses = Queue.new()
+ @queue = nil
+ @closed = false
+ end
+
+ attr_reader :id
+
+ def closed?; @closed end
+
+ def close()
+ return if closed?
+ @peer.channel_delete(@id)
+ @closed = true
+ @incoming.close()
+ @responses.close()
+ end
+
+ def dispatch(frame, work)
+ payload = frame.payload
+ case payload
+ when Method
+ if payload.method.response?
+ @queue = @responses
+ else
+ @queue = @incoming
+ work << @incoming
+ end
+ end
+ @queue << frame
+ end
+
+ def method_missing(name, *args)
+ method = @spec.find_method(name)
+ if method.nil?
+ raise NoMethodError.new("undefined method '#{name}' for #{self}:#{self.class}")
+ end
+
+ if args.size == 1 and args[0].instance_of? Hash
+ kwargs = args[0]
+ invoke_args = method.fields.map do |f|
+ kwargs[f.name]
+ end
+ content = kwargs[:content]
+ else
+ invoke_args = []
+ method.fields.each do |f|
+ if args.any?
+ invoke_args << args.shift()
+ else
+ invoke_args << f.default
+ end
+ end
+ if method.content? and args.any?
+ content = args.shift()
+ else
+ content = nil
+ end
+ if args.any? then raise ArgumentError.new("#{args.size} extr arguments") end
+ end
+ return invoke(method, invoke_args, content)
+ end
+
+ def invoke(method, args, content = nil)
+ raise Closed() if closed?
+ frame = Frame.new(@id, Method.new(method, args))
+ @outgoing << frame
+
+ if method.content?
+ content = Content.new() if content.nil?
+ write_content(method.parent, content, @outgoing)
+ end
+
+ nowait = false
+ f = method.fields[:"nowait"]
+ nowait = args[method.fields.index(f)] unless f.nil?
+
+ unless nowait or method.responses.empty?
+ resp = @responses.get().payload
+ if resp.method.content?
+ content = read_content(@responses)
+ else
+ content = nil
+ end
+ if method.responses.include? resp.method
+ return Message.new(resp.method, resp.args, content)
+ else
+ # XXX: ValueError doesn't actually exist
+ raise ValueError.new(resp)
+ end
+ end
+ end
+
+ def write_content(klass, content, queue)
+ size = content.size
+ header = Frame.new(@id, Header.new(klass, content.weight, size, content.headers))
+ queue << header
+ content.children.each {|child| write_content(klass, child, queue)}
+ queue << Frame.new(@id, Body.new(content.body)) if size > 0
+ end
+
+ end
+
+ def Qpid08.read_content(queue)
+ frame = queue.get()
+ header = frame.payload
+ children = []
+ 1.upto(header.weight) { children << read_content(queue) }
+ size = header.size
+ read = 0
+ buf = ""
+ while read < size
+ body = queue.get()
+ content = body.payload.content
+ buf << content
+ read += content.size
+ end
+ buf.freeze()
+ return Content.new(header.properties.clone(), buf, children)
+ end
+
+ class Content
+ def initialize(headers = {}, body = "", children = [])
+ @headers = headers
+ @body = body
+ @children = children
+ end
+
+ attr_reader :headers, :body, :children
+
+ def size; body.size end
+ def weight; children.size end
+
+ def [](key); @headers[key] end
+ def []=(key, value); @headers[key] = value end
+ end
+
+ class Message
+ fields(:method, :args, :content)
+
+ alias fields args
+
+ def method_missing(name)
+ return args[@method.fields[name].id]
+ end
+
+ def inspect()
+ "#{method.qname}(#{args.join(", ")})"
+ end
+ end
+
+ module Delegate
+ def dispatch(ch, msg)
+ send(msg.method.qname, ch, msg)
+ end
+ end
+
+end
diff --git a/ruby/lib/qpid/qmf.rb b/ruby/lib/qpid/qmf.rb
new file mode 100644
index 0000000000..4711d355cd
--- /dev/null
+++ b/ruby/lib/qpid/qmf.rb
@@ -0,0 +1,1957 @@
+# 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.
+#
+
+# Console API for Qpid Management Framework
+
+require 'socket'
+require 'monitor'
+require 'thread'
+require 'uri'
+require 'time'
+
+module Qpid::Qmf
+
+ # To access the asynchronous operations, a class must be derived from
+ # Console with overrides of any combination of the available methods.
+ class Console
+
+ # Invoked when a connection is established to a broker
+ def broker_connected(broker); end
+
+ # Invoked when the connection to a broker is lost
+ def broker_disconnected(broker); end
+
+ # Invoked when a QMF package is discovered
+ def new_package(name); end
+
+ # Invoked when a new class is discovered. Session.getSchema can be
+ # used to obtain details about the class
+ def new_class(kind, klass_key); end
+
+ # Invoked when a QMF agent is discovered
+ def new_agent(agent); end
+
+ # Invoked when a QMF agent disconects
+ def del_agent(agent); end
+
+ # Invoked when an object is updated
+ def object_props(broker, record); end
+
+ # Invoked when an object is updated
+ def object_stats(broker, record); end
+
+ # Invoked when an event is raised
+ def event(broker, event); end
+
+ # Invoked when an agent heartbeat is received.
+ def heartbeat(agent, timestamp); end
+
+ # Invoked when the connection sequence reaches the point where broker information is available.
+ def broker_info(broker); end
+
+ # Invoked when a method response from an asynchronous method call is received.
+ def method_response(broker, seq, response); end
+ end
+
+ class BrokerURL
+
+ attr_reader :host, :port, :auth_name, :auth_pass
+
+ def initialize(text)
+ uri = URI.parse(text)
+
+ @host = uri.host
+ @port = uri.port ? uri.port : 5672
+ @auth_name = uri.user
+ @auth_pass = uri.password
+
+ return uri
+ end
+
+ def name
+ "#{@host}:#{@port}"
+ end
+
+ def match(host, port)
+ # FIXME: Unlcear what the Python code is actually checking for
+ # here, especially since HOST can resolve to multiple IP's
+ @port == port &&
+ (host == @host || ipaddr(host, port) == ipaddr(@host, @port))
+ end
+
+ private
+ def ipaddr(host, port)
+ s = Socket::getaddrinfo(host, port,
+ Socket::AF_INET, Socket::SOCK_STREAM)
+ s[0][2]
+ end
+ end
+
+ # An instance of the Session class represents a console session running
+ # against one or more QMF brokers. A single instance of Session is
+ # needed to interact with the management framework as a console.
+ class Session
+ CONTEXT_SYNC = 1
+ CONTEXT_STARTUP = 2
+ CONTEXT_MULTIGET = 3
+
+ DEFAULT_GET_WAIT_TIME = 60
+
+ include MonitorMixin
+
+ attr_reader :binding_key_list, :select, :seq_mgr, :console, :packages
+
+ # Initialize a session. If the console argument is provided, the
+ # more advanced asynchronous features are available. If console is
+ # defaulted, the session will operate in a simpler, synchronous
+ # manner. The rcvObjects, rcvEvents, and rcvHeartbeats arguments
+ # are meaningful only if 'console' is provided. They control
+ # whether object updates, events, and agent-heartbeats are
+ # subscribed to. If the console is not interested in receiving one
+ # or more of the above, setting the argument to False will reduce
+ # tha bandwidth used by the API. If manageConnections is set to
+ # True, the Session object will manage connections to the brokers.
+ # This means that if a broker is unreachable, it will retry until a
+ # connection can be established. If a connection is lost, the
+ # Session will attempt to reconnect.
+ #
+ # If manageConnections is set to False, the user is responsible for
+ # handing failures. In this case, an unreachable broker will cause
+ # addBroker to raise an exception. If userBindings is set to False
+ # (the default) and rcvObjects is True, the console will receive
+ # data for all object classes. If userBindings is set to True, the
+ # user must select which classes the console shall receive by
+ # invoking the bindPackage or bindClass methods. This allows the
+ # console to be configured to receive only information that is
+ # relavant to a particular application. If rcvObjects id False,
+ # userBindings has no meaning.
+ #
+ # Accept a hash of parameters, where keys can be :console,
+ # :rcv_objects, :rcv_events, :rcv_heartbeats, :manage_connections,
+ # and :user_bindings
+ def initialize(kwargs = {})
+ super()
+ @console = kwargs[:console] || nil
+ @brokers = []
+ @packages = {}
+ @seq_mgr = SequenceManager.new
+ @cv = new_cond
+ @sync_sequence_list = []
+ @result = []
+ @select = []
+ @error = nil
+ @rcv_objects = kwargs[:rcv_objects] == nil ? true : kwargs[:rcv_objects]
+ @rcv_events = kwargs[:rcv_events] == nil ? true : kwargs[:rcv_events]
+ @rcv_heartbeats = kwargs[:rcv_heartbeats] == nil ? true : kwargs[:rcv_heartbeats]
+ @user_bindings = kwargs[:user_bindings] == nil ? false : kwargs[:user_bindings]
+ unless @console
+ @rcv_objects = false
+ @rcv_events = false
+ @rcv_heartbeats = false
+ end
+ @binding_key_list = binding_keys
+ @manage_connections = kwargs[:manage_connections] || false
+
+ if @user_bindings && ! @rcv_objects
+ raise ArgumentError, "user_bindings can't be set unless rcv_objects is set and a console is provided"
+ end
+
+ end
+
+ def to_s
+ "QMF Console Session Manager (brokers: #{@brokers.size})"
+ end
+
+ def managedConnections?
+ return @manage_connections
+ end
+
+ # Connect to a Qpid broker. Returns an object of type Broker
+ #
+ # To supply a username for authentication, use the URL syntax:
+ #
+ # amqp://username@hostname:port
+ #
+ # If the broker needs a password for the client, an interactive prompt will be
+ # provided to the user.
+ #
+ # To supply a username and a password, use
+ #
+ # amqp://username:password@hostname:port
+ #
+ # The following keyword arguments may be used to control authentication:
+ #
+ # :mechanism - SASL mechanism (i.e. "PLAIN", "GSSAPI", "ANONYMOUS", etc.
+ # - defaults to unspecified (the system chooses for you)
+ # :service - SASL service name (i.e. the kerberos principal of the broker)
+ # - defaults to "qpidd"
+ # :min_ssf - Minimum Security Strength Factor for SASL security layers
+ # - defaults to 0
+ # :max_ssf - Maximum Security Strength Factor for SASL security layers
+ # - defaults to 65535
+ #
+ def add_broker(target = "amqp://localhost", kwargs = {})
+ url = BrokerURL.new(target)
+ broker = Broker.new(self, url.host, url.port, url.auth_name, url.auth_pass, kwargs)
+ unless broker.connected? || @manage_connections
+ raise broker.error
+ end
+
+ @brokers << broker
+ objects(:broker => broker, :class => "agent") unless @manage_connections
+ return broker
+ end
+
+ # Disconnect from a broker. The 'broker' argument is the object
+ # returned from the addBroker call
+ def del_broker(broker)
+ broker.shutdown
+ @brokers.delete(broker)
+ end
+
+ # Get the list of known classes within a QMF package
+ def classes(package_name)
+ list = []
+ @brokers.each { |broker| broker.wait_for_stable }
+ if @packages.include?(package_name)
+ # FIXME What's the actual structure of @packages[package_name]
+ @packages[package_name].each do |key, schema_class|
+ list << schema_class.klass_key
+ end
+ end
+ return list
+ end
+
+ # Get the schema for a QMF class
+ def schema(klass_key)
+ @brokers.each { |broker| broker.wait_for_stable }
+ if @packages.include?(klass_key.package)
+ @packages[klass_key.package][ [klass_key.klass_name, klass_key.hash] ]
+ end
+ end
+
+ def bind_package(package_name)
+ unless @user_bindings && @rcv_objects
+ raise "userBindings option not set for Session"
+ end
+ @brokers.each do |broker|
+ args = { :exchange => "qpid.management",
+ :queue => broker.topic_name,
+ :binding_key => "console.obj.*.*.#{package_name}.#" }
+ broker.amqp_session.exchange_bind(args)
+ end
+ end
+
+ def bind_class(package_name, class_name)
+ unless @user_bindings && @rcv_objects
+ raise "userBindings option not set for Session"
+ end
+ @brokers.each do |broker|
+ args = { :exchange => "qpid.management",
+ :queue => broker.topic_name,
+ :binding_key=> "console.obj.*.*.#{package_name}.#{class_name}.#" }
+ broker.amqp_session.exchange_bind(args)
+ end
+ end
+
+ def bind_class_key(klass_key)
+ unless @user_bindings && @rcv_objects
+ raise "userBindings option not set for Session"
+ end
+ pname, cname, hash = klass_key.to_a()
+ @brokers.each do |broker|
+ args = { :exchange => "qpid.management",
+ :queue => broker.topic_name,
+ :binding_key => "console.obj.*.*.#{pname}.#{cname}.#" }
+ broker.amqp_session.exchange_bind(args)
+ end
+ end
+
+ # Get a list of currently known agents
+ def agents(broker=nil)
+ broker_list = []
+ if broker.nil?
+ broker_list = @brokers.dup
+ else
+ broker_list << broker
+ end
+ broker_list.each { |b| b.wait_for_stable }
+ agent_list = []
+ broker_list.each { |b| agent_list += b.agents }
+ return agent_list
+ end
+
+ # Get a list of objects from QMF agents.
+ # All arguments are passed by name(keyword).
+ #
+ # The class for queried objects may be specified in one of the
+ # following ways:
+ # :schema => <schema> - supply a schema object returned from getSchema.
+ # :key => <key> - supply a klass_key from the list returned by getClasses.
+ # :class => <name> - supply a class name as a string. If the class name exists
+ # in multiple packages, a _package argument may also be supplied.
+ # :object_id = <id> - get the object referenced by the object-id
+ #
+ # If objects should be obtained from only one agent, use the following argument.
+ # Otherwise, the query will go to all agents.
+ #
+ # :agent = <agent> - supply an agent from the list returned by getAgents.
+ #
+ # If the get query is to be restricted to one broker (as opposed to
+ # all connected brokers), add the following argument:
+ #
+ # :broker = <broker> - supply a broker as returned by addBroker.
+ #
+ # The default timeout for this synchronous operation is 60 seconds. To change the timeout,
+ # use the following argument:
+ #
+ # :timeout = <time in seconds>
+ #
+ # If additional arguments are supplied, they are used as property
+ # selectors, as long as their keys are strings. For example, if
+ # the argument "name" => "test" is supplied, only objects whose
+ # "name" property is "test" will be returned in the result.
+ def objects(kwargs)
+ if kwargs.include?(:broker)
+ broker_list = []
+ broker_list << kwargs[:broker]
+ else
+ broker_list = @brokers
+ end
+ broker_list.each { |broker|
+ broker.wait_for_stable
+ if kwargs[:package] != "org.apache.qpid.broker" or kwargs[:class] != "agent"
+ objects(:agent => broker.agent(1,0), :package => "org.apache.qpid.broker", :class => "agent") if broker.connected?
+ end
+ }
+
+ agent_list = []
+ if kwargs.include?(:agent)
+ agent = kwargs[:agent]
+ unless broker_list.include?(agent.broker)
+ raise ArgumentError, "Supplied agent is not accessible through the supplied broker"
+ end
+ agent_list << agent if agent.broker.connected?
+ else
+ if kwargs.include?(:object_id)
+ oid = kwargs[:object_id]
+ broker_list.each { |broker|
+ broker.agents.each { |agent|
+ if oid.broker_bank == agent.broker_bank && oid.agent_bank == agent.agent_bank
+ agent_list << agent if agent.broker.connected?
+ end
+ }
+ }
+ else
+ broker_list.each { |broker|
+ agent_list += broker.agents if broker.connected?
+ }
+ end
+ end
+
+ cname = nil
+ if kwargs.include?(:schema)
+ # FIXME: What kind of object is kwargs[:schema]
+ pname, cname, hash = kwargs[:schema].getKey().to_a
+ elsif kwargs.include?(:key)
+ pname, cname, hash = kwargs[:key].to_a
+ elsif kwargs.include?(:class)
+ pname, cname, hash = [kwargs[:package], kwargs[:class], nil]
+ end
+ if cname.nil? && ! kwargs.include?(:object_id)
+ raise ArgumentError,
+ "No class supplied, use :schema, :key, :class, or :object_id' argument"
+ end
+
+ map = {}
+ @select = []
+ if kwargs.include?(:object_id)
+ map["_objectid"] = kwargs[:object_id].to_s
+ else
+ map["_class"] = cname
+ map["_package"] = pname if pname
+ map["_hash"] = hash if hash
+ kwargs.each do |k,v|
+ @select << [k, v] if k.is_a?(String)
+ end
+ end
+
+ @result = []
+ agent_list.each do |agent|
+ broker = agent.broker
+ send_codec = Qpid::StringCodec.new(broker.conn.spec)
+ seq = nil
+ synchronize do
+ seq = @seq_mgr.reserve(CONTEXT_MULTIGET)
+ @sync_sequence_list << seq
+ end
+ broker.set_header(send_codec, ?G, seq)
+ send_codec.write_map(map)
+ bank_key = "%d.%d" % [broker.broker_bank, agent.agent_bank]
+ smsg = broker.message(send_codec.encoded, "agent.#{bank_key}")
+ broker.emit(smsg)
+ end
+
+ timeout = false
+ if kwargs.include?(:timeout)
+ wait_time = kwargs[:timeout]
+ else
+ wait_time = DEFAULT_GET_WAIT_TIME
+ end
+ synchronize do
+ unless @cv.wait_for(wait_time) { @sync_sequence_list.empty? || @error }
+ @sync_sequence_list.each do |pending_seq|
+ @seq_mgr.release(pending_seq)
+ end
+ @sync_sequence_list = []
+ timeout = true
+ end
+ end
+
+ if @error
+ errorText = @error
+ @error = nil
+ raise errorText
+ end
+
+ if @result.empty? && timeout
+ raise "No agent responded within timeout period"
+ end
+ @result
+ end
+
+ # Return one and only one object or nil.
+ def object(kwargs)
+ objs = objects(kwargs)
+ return objs.length == 1 ? objs[0] : nil
+ end
+
+ # Return the first of potentially many objects.
+ def first_object(kwargs)
+ objs = objects(kwargs)
+ return objs.length > 0 ? objs[0] : nil
+ end
+
+ def set_event_filter(kwargs); end
+
+ def handle_broker_connect(broker); end
+
+ def handle_broker_resp(broker, codec, seq)
+ broker.broker_id = codec.read_uuid
+ @console.broker_info(broker) if @console
+
+ # Send a package request
+ # (effectively inc and dec outstanding by not doing anything)
+ send_codec = Qpid::StringCodec.new(broker.conn.spec)
+ seq = @seq_mgr.reserve(CONTEXT_STARTUP)
+ broker.set_header(send_codec, ?P, seq)
+ smsg = broker.message(send_codec.encoded)
+ broker.emit(smsg)
+ end
+
+ def handle_package_ind(broker, codec, seq)
+ pname = codec.read_str8
+ new_package = false
+ synchronize do
+ new_package = ! @packages.include?(pname)
+ @packages[pname] = {} if new_package
+ end
+ @console.new_package(pname) if @console
+
+ # Send a class request
+ broker.inc_outstanding
+ send_codec = Qpid::StringCodec.new(broker.conn.spec)
+ seq = @seq_mgr.reserve(CONTEXT_STARTUP)
+ broker.set_header(send_codec, ?Q, seq)
+ send_codec.write_str8(pname)
+ smsg = broker.message(send_codec.encoded)
+ broker.emit(smsg)
+ end
+
+ def handle_command_complete(broker, codec, seq)
+ code = codec.read_uint32
+ text = codec.read_str8
+ context = @seq_mgr.release(seq)
+ if context == CONTEXT_STARTUP
+ broker.dec_outstanding
+ elsif context == CONTEXT_SYNC && seq == broker.sync_sequence
+ broker.sync_done
+ elsif context == CONTEXT_MULTIGET && @sync_sequence_list.include?(seq)
+ synchronize do
+ @sync_sequence_list.delete(seq)
+ @cv.signal if @sync_sequence_list.empty?
+ end
+ end
+ end
+
+ def handle_class_ind(broker, codec, seq)
+ kind = codec.read_uint8
+ classKey = ClassKey.new(codec)
+ unknown = false
+
+ synchronize do
+ return unless @packages.include?(classKey.package)
+ unknown = true unless @packages[classKey.package].include?([classKey.klass_name, classKey.hash])
+ end
+
+
+ if unknown
+ # Send a schema request for the unknown class
+ broker.inc_outstanding
+ send_codec = Qpid::StringCodec.new(broker.conn.spec)
+ seq = @seq_mgr.reserve(CONTEXT_STARTUP)
+ broker.set_header(send_codec, ?S, seq)
+ classKey.encode(send_codec)
+ smsg = broker.message(send_codec.encoded)
+ broker.emit(smsg)
+ end
+ end
+
+ def handle_method_resp(broker, codec, seq)
+ code = codec.read_uint32
+ text = codec.read_str16
+ out_args = {}
+ pair = @seq_mgr.release(seq)
+ return unless pair
+ method, synchronous = pair
+ if code == 0
+ method.arguments.each do |arg|
+ if arg.dir.index(?O)
+ out_args[arg.name] = decode_value(codec, arg.type)
+ end
+ end
+ end
+ result = MethodResult.new(code, text, out_args)
+ if synchronous:
+ broker.synchronize do
+ broker.sync_result = MethodResult.new(code, text, out_args)
+ broker.sync_done
+ end
+ else
+ @console.method_response(broker, seq, result) if @console
+ end
+ end
+
+ def handle_heartbeat_ind(broker, codec, seq, msg)
+ if @console
+ broker_bank = 1
+ agent_bank = 0
+ dp = msg.get("delivery_properties")
+ if dp
+ key = dp["routing_key"]
+ key_elements = key.split(".")
+ if key_elements.length == 4
+ broker_bank = key_elements[2].to_i
+ agent_bank = key_elements[3].to_i
+ end
+ end
+ agent = broker.agent(broker_bank, agent_bank)
+ timestamp = codec.read_uint64
+ @console.heartbeat(agent, timestamp) if agent
+ end
+ end
+
+ def handle_event_ind(broker, codec, seq)
+ if @console
+ event = Event.new(self, broker, codec)
+ @console.event(broker, event)
+ end
+ end
+
+ def handle_schema_resp(broker, codec, seq)
+ kind = codec.read_uint8
+ classKey = ClassKey.new(codec)
+ klass = SchemaClass.new(self, kind, classKey, codec)
+ synchronize { @packages[classKey.package][ [classKey.klass_name, classKey.hash] ] = klass }
+
+ @seq_mgr.release(seq)
+ broker.dec_outstanding
+ @console.new_class(kind, classKey) if @console
+ end
+
+ def handle_content_ind(broker, codec, seq, prop=false, stat=false)
+ klass_key = ClassKey.new(codec)
+ pname, cname, hash = klass_key.to_a() ;
+
+ schema = nil
+ synchronize do
+ return unless @packages.include?(klass_key.package)
+ return unless @packages[klass_key.package].include?([klass_key.klass_name, klass_key.hash])
+ schema = @packages[klass_key.package][ [klass_key.klass_name, klass_key.hash] ]
+ end
+
+
+ object = Qpid::Qmf::Object.new(self, broker, schema, codec, prop, stat)
+ if pname == "org.apache.qpid.broker" && cname == "agent" && prop
+ broker.update_agent(object)
+ end
+
+ synchronize do
+ if @sync_sequence_list.include?(seq)
+ if object.timestamps()[2] == 0 && select_match(object)
+ @result << object
+ end
+ return
+ end
+ end
+
+ @console.object_props(broker, object) if @console && @rcv_objects && prop
+ @console.object_stats(broker, object) if @console && @rcv_objects && stat
+ end
+
+ def handle_broker_disconnect(broker); end
+
+ def handle_error(error)
+ synchronize do
+ @error = error if @sync_sequence_list.length > 0
+ @sync_sequence_list = []
+ @cv.signal
+ end
+ end
+
+ # Decode, from the codec, a value based on its typecode
+ def decode_value(codec, typecode)
+ case typecode
+ when 1: data = codec.read_uint8 # U8
+ when 2: data = codec.read_uint16 # U16
+ when 3: data = codec.read_uint32 # U32
+ when 4: data = codec.read_uint64 # U64
+ when 6: data = codec.read_str8 # SSTR
+ when 7: data = codec.read_str16 # LSTR
+ when 8: data = codec.read_int64 # ABSTIME
+ when 9: data = codec.read_uint64 # DELTATIME
+ when 10: data = ObjectId.new(codec) # REF
+ when 11: data = codec.read_uint8 != 0 # BOOL
+ when 12: data = codec.read_float # FLOAT
+ when 13: data = codec.read_double # DOUBLE
+ when 14: data = codec.read_uuid # UUID
+ when 15: data = codec.read_map # FTABLE
+ when 16: data = codec.read_int8 # S8
+ when 17: data = codec.read_int16 # S16
+ when 18: data = codec.read_int32 # S32
+ when 19: data = codec.read_int64 # S64
+ when 20: # Object
+ inner_type_code = codec.read_uint8()
+ if (inner_type_code == 20)
+ classKey = ClassKey.new(codec)
+ innerSchema = schema(classKey)
+ data = Object.new(self, @broker, innerSchema, codec, true, true, false) if innerSchema
+ else
+ data = decode_value(codec, inner_type_code)
+ end
+ when 21:
+ data = []
+ rec_codec = Qpid::StringCodec.new(codec.spec, codec.read_vbin32())
+ count = rec_codec.read_uint32()
+ while count > 0 do
+ type = rec_codec.read_uint8()
+ data << (decode_value(rec_codec,type))
+ count -= 1
+ end
+ when 22:
+ data = []
+ rec_codec = Qpid::StringCodec.new(codec.spec, codec.read_vbin32())
+ count = rec_codec.read_uint32()
+ type = rec_codec.read_uint8()
+ while count > 0 do
+ data << (decode_value(rec_codec,type))
+ count -= 1
+ end
+ else
+ raise ArgumentError, "Invalid type code: #{typecode} - #{typecode.inspect}"
+ end
+ return data
+ end
+
+ ENCODINGS = {
+ String => 6,
+ Fixnum => 18,
+ Bignum => 19,
+ Float => 12,
+ Array => 21,
+ Hash => 15
+ }
+
+ def encoding(object)
+ klass = object.class
+ if ENCODINGS.has_key?(klass)
+ return ENCODINGS[klass]
+ end
+ for base in klass.__bases__
+ result = encoding(base)
+ return result unless result.nil?
+ end
+ end
+
+ # Encode, into the codec, a value based on its typecode
+ def encode_value(codec, value, typecode)
+ # FIXME: Python does a lot of magic type conversions
+ # We just assume that value has the right type; this is safer
+ # than coercing explicitly, since Array::pack will complain
+ # loudly about various type errors
+ case typecode
+ when 1: codec.write_uint8(value) # U8
+ when 2: codec.write_uint16(value) # U16
+ when 3: codec.write_uint32(value) # U32
+ when 4: codec.write_uint64(value) # U64
+ when 6: codec.write_str8(value) # SSTR
+ when 7: codec.write_str16(value) # LSTR
+ when 8: codec.write_int64(value) # ABSTIME
+ when 9: codec.write_uint64(value) # DELTATIME
+ when 10: value.encode(codec) # REF
+ when 11: codec.write_uint8(value ? 1 : 0) # BOOL
+ when 12: codec.write_float(value) # FLOAT
+ when 13: codec.write_double(value) # DOUBLE
+ when 14: codec.write_uuid(value) # UUID
+ when 15: codec.write_map(value) # FTABLE
+ when 16: codec.write_int8(value) # S8
+ when 17: codec.write_int16(value) # S16
+ when 18: codec.write_int32(value) # S32
+ when 19: codec.write_int64(value) # S64
+ when 20: value.encode(codec)
+ when 21: # List
+ send_codec = Qpid::StringCodec.new(codec.spec)
+ encode_value(send_codec, value.size, 3)
+ value.each do v
+ ltype = encoding(v)
+ encode_value(send_codec,ltype,1)
+ encode_value(send_codec,v,ltype)
+ end
+ codec.write_vbin32(send_codec.encoded)
+ when 22: # Array
+ send_codec = Qpid::StringCodec.new(codec.spec)
+ encode_value(send_codec, value.size, 3)
+ if value.size > 0
+ ltype = encoding(value[0])
+ encode_value(send_codec,ltype,1)
+ value.each do v
+ encode_value(send_codec,v,ltype)
+ end
+ end
+ codec.write_vbin32(send_codec.encoded)
+ else
+ raise ValueError, "Invalid type code: %d" % typecode
+ end
+ end
+
+ def display_value(value, typecode)
+ case typecode
+ when 1: return value.to_s
+ when 2: return value.to_s
+ when 3: return value.to_s
+ when 4: return value.to_s
+ when 6: return value.to_s
+ when 7: return value.to_s
+ when 8: return strftime("%c", gmtime(value / 1000000000))
+ when 9: return value.to_s
+ when 10: return value.to_s
+ when 11: return value ? 'T' : 'F'
+ when 12: return value.to_s
+ when 13: return value.to_s
+ when 14: return Qpid::UUID::format(value)
+ when 15: return value.to_s
+ when 16: return value.to_s
+ when 17: return value.to_s
+ when 18: return value.to_s
+ when 19: return value.to_s
+ when 20: return value.to_s
+ when 21: return value.to_s
+ when 22: return value.to_s
+ else
+ raise ValueError, "Invalid type code: %d" % typecode
+ end
+ end
+
+ private
+
+ def binding_keys
+ key_list = []
+ key_list << "schema.#"
+ if @rcv_objects && @rcv_events && @rcv_heartbeats &&
+ ! @user_bindings
+ key_list << "console.#"
+ else
+ if @rcv_objects && ! @user_bindings
+ key_list << "console.obj.#"
+ else
+ key_list << "console.obj.*.*.org.apache.qpid.broker.agent"
+ end
+ key_list << "console.event.#" if @rcv_events
+ key_list << "console.heartbeat.#" if @rcv_heartbeats
+ end
+ return key_list
+ end
+
+ # Check the object against select to check for a match
+ def select_match(object)
+ select.each do |key, value|
+ object.properties.each do |prop, propval|
+ return false if key == prop.name && value != propval
+ end
+ end
+ return true
+ end
+
+ end
+
+ class Package
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+ end
+
+ # A ClassKey uniquely identifies a class from the schema.
+ class ClassKey
+ attr_reader :package, :klass_name, :hash
+
+ def initialize(package="", klass_name="", hash=0)
+ if (package.kind_of?(Qpid::Codec))
+ @package = package.read_str8()
+ @klass_name = package.read_str8()
+ @hash = package.read_bin128()
+ else
+ @package = package
+ @klass_name = klass_name
+ @hash = hash
+ end
+ end
+
+ def encode(codec)
+ codec.write_str8(@package)
+ codec.write_str8(@klass_name)
+ codec.write_bin128(@hash)
+ end
+
+ def to_a()
+ return [@package, @klass_name, @hash]
+ end
+
+ def hash_string()
+ "%08x-%08x-%08x-%08x" % hash.unpack("NNNN")
+ end
+
+ def to_s()
+ return "#{@package}:#{@klass_name}(#{hash_string()})"
+ end
+ end
+
+ class SchemaClass
+
+ CLASS_KIND_TABLE = 1
+ CLASS_KIND_EVENT = 2
+
+ attr_reader :klass_key, :arguments, :super_klass_key
+
+ def initialize(session, kind, key, codec)
+ @session = session
+ @kind = kind
+ @klass_key = key
+ @super_klass_key = nil
+ @properties = []
+ @statistics = []
+ @methods = []
+ @arguments = []
+
+ has_supertype = 0 #codec.read_uint8
+ if @kind == CLASS_KIND_TABLE
+ prop_count = codec.read_uint16
+ stat_count = codec.read_uint16
+ method_count = codec.read_uint16
+ if has_supertype == 1
+ @super_klass_key = ClassKey.new(codec)
+ end
+ prop_count.times { |idx|
+ @properties << SchemaProperty.new(codec) }
+ stat_count.times { |idx|
+ @statistics << SchemaStatistic.new(codec) }
+ method_count.times { |idx|
+ @methods<< SchemaMethod.new(codec) }
+ elsif @kind == CLASS_KIND_EVENT
+ arg_count = codec.read_uint16
+ arg_count.times { |idx|
+ sa = SchemaArgument.new(codec, false)
+ @arguments << sa
+ }
+ end
+ end
+
+ def is_table?
+ @kind == CLASS_KIND_TABLE
+ end
+
+ def is_event?
+ @kind == CLASS_KIND_EVENT
+ end
+
+ def properties(include_inherited = true)
+ returnValue = @properties
+ if !@super_klass_key.nil? && include_inherited
+ returnValue = @properties + @session.schema(@super_klass_key).properties
+ end
+ return returnValue
+ end
+
+ def statistics(include_inherited = true)
+ returnValue = @statistics
+ if !@super_klass_key.nil? && include_inherited
+ returnValue = @statistics + @session.schema(@super_klass_key).statistics
+ end
+ return returnValue
+ end
+
+ def methods(include_inherited = true)
+ returnValue = @methods
+ if !@super_klass_key.nil? && include_inherited
+ returnValue = @methods + @session.schema(@super_klass_key).methods
+ end
+ return returnValue
+ end
+
+ def to_s
+ if @kind == CLASS_KIND_TABLE
+ kind_str = "Table"
+ elsif @kind == CLASS_KIND_EVENT
+ kind_str = "Event"
+ else
+ kind_str = "Unsupported"
+ end
+ "#{kind_str} Class: #{klass_key.to_s}"
+ end
+ end
+
+ class SchemaProperty
+
+ attr_reader :name, :type, :access, :index, :optional,
+ :unit, :min, :max, :maxlen, :desc, :refClass, :refPackage
+
+ def initialize(codec)
+ map = codec.read_map
+ @name = map["name"]
+ @type = map["type"]
+ @access = map["access"]
+ @index = map["index"] != 0
+ @optional = map["optional"] != 0
+ @unit = map["unit"]
+ @min = map["min"]
+ @max = map["max"]
+ @maxlen = map["maxlen"]
+ @desc = map["desc"]
+ @refClass = map["refClass"]
+ @refPackage = map["refPackage"]
+ end
+
+ def to_s
+ @name
+ end
+ end
+
+ class SchemaStatistic
+
+ attr_reader :name, :type, :unit, :desc, :refClass, :refPackage
+
+ def initialize(codec)
+ map = codec.read_map
+ @name = map["name"]
+ @type = map["type"]
+ @unit = map["unit"]
+ @desc = map["desc"]
+ @refClass = map["refClass"]
+ @refPackage = map["refPackage"]
+ end
+
+ def to_s
+ @name
+ end
+ end
+
+ class SchemaMethod
+
+ attr_reader :name, :desc, :arguments
+
+ def initialize(codec)
+ map = codec.read_map
+ @name = map["name"]
+ arg_count = map["argCount"]
+ @desc = map["desc"]
+ @arguments = []
+ arg_count.times { |idx|
+ @arguments << SchemaArgument.new(codec, true)
+ }
+ end
+
+ def to_s
+ result = @name + "("
+ first = true
+ result += @arguments.select { |arg| arg.dir.index(?I) }.join(", ")
+ result += ")"
+ return result
+ end
+ end
+
+ class SchemaArgument
+
+ attr_reader :name, :type, :dir, :unit, :min, :max, :maxlen
+ attr_reader :desc, :default, :refClass, :refPackage
+
+ def initialize(codec, method_arg)
+ map = codec.read_map
+ @name = map["name"]
+ @type = map["type"]
+ @dir = map["dir"].upcase if method_arg
+ @unit = map["unit"]
+ @min = map["min"]
+ @max = map["max"]
+ @maxlen = map["maxlen"]
+ @desc = map["desc"]
+ @default = map["default"]
+ @refClass = map["refClass"]
+ @refPackage = map["refPackage"]
+ end
+ end
+
+ # Object that represents QMF object identifiers
+ class ObjectId
+
+ include Comparable
+
+ attr_reader :first, :second
+
+ def initialize(codec, first=0, second=0)
+ if codec
+ @first = codec.read_uint64
+ @second = codec.read_uint64
+ else
+ @first = first
+ @second = second
+ end
+ end
+
+ def <=>(other)
+ return 1 unless other.is_a?(ObjectId)
+ return -1 if first < other.first
+ return 1 if first > other.first
+ return second <=> other.second
+ end
+
+ def to_s
+ "%d-%d-%d-%d-%d" % [flags, sequence, broker_bank, agent_bank, object]
+ end
+
+ def index
+ [first, second]
+ end
+
+ def flags
+ (first & 0xF000000000000000) >> 60
+ end
+
+ def sequence
+ (first & 0x0FFF000000000000) >> 48
+ end
+
+ def broker_bank
+ (first & 0x0000FFFFF0000000) >> 28
+ end
+
+ def agent_bank
+ first & 0x000000000FFFFFFF
+ end
+
+ def object
+ second
+ end
+
+ def durable?
+ sequence == 0
+ end
+
+ def encode(codec)
+ codec.write_uint64(first)
+ codec.write_uint64(second)
+ end
+ end
+
+ class Object
+
+ DEFAULT_METHOD_WAIT_TIME = 60
+
+ attr_reader :object_id, :schema, :properties, :statistics,
+ :current_time, :create_time, :delete_time, :broker
+
+ def initialize(session, broker, schema, codec, prop, stat, managed=true)
+ @session = session
+ @broker = broker
+ @schema = schema
+ if managed
+ @current_time = codec.read_uint64
+ @create_time = codec.read_uint64
+ @delete_time = codec.read_uint64
+ @object_id = ObjectId.new(codec)
+ end
+ @properties = []
+ @statistics = []
+ if prop
+ missing = parse_presence_masks(codec, schema)
+ schema.properties.each do |property|
+ v = nil
+ unless missing.include?(property.name)
+ v = @session.decode_value(codec, property.type)
+ end
+ @properties << [property, v]
+ end
+ end
+
+ if stat
+ schema.statistics.each do |statistic|
+ s = @session.decode_value(codec, statistic.type)
+ @statistics << [statistic, s]
+ end
+ end
+ end
+
+ def klass_key
+ @schema.klass_key
+ end
+
+
+ def methods
+ @schema.methods
+ end
+
+ # Return the current, creation, and deletion times for this object
+ def timestamps
+ return [@current_time, @create_time, @delete_time]
+ end
+
+ # Return a string describing this object's primary key
+ def index
+ @properties.select { |property, value|
+ property.index
+ }.collect { |property,value|
+ @session.display_value(value, property.type) }.join(":")
+ end
+
+ # Replace properties and/or statistics with a newly received update
+ def merge_update(newer)
+ unless object_id == newer.object_id
+ raise "Objects with different object-ids"
+ end
+ @properties = newer.properties unless newer.properties.empty?
+ @statistics = newer.statistics unless newer.statistics.empty?
+ end
+
+ def update
+ obj = @session.object(:object_id => @object_id, :broker => @broker)
+ if obj
+ merge_update(obj)
+ else
+ raise "Underlying object no longer exists."
+ end
+ end
+
+ def to_s
+ @schema.klass_key.to_s
+ end
+
+ # This must be defined because ruby has this (deprecated) method built in.
+ def id
+ method_missing(:id)
+ end
+
+ # Same here..
+ def type
+ method_missing(:type)
+ end
+
+ def name
+ method_missing(:name)
+ end
+
+ def method_missing(name, *args)
+ name = name.to_s
+
+ if method = @schema.methods.find { |method| name == method.name }
+ return invoke(method, name, args)
+ end
+
+ @properties.each do |property, value|
+ return value if name == property.name
+ if name == "_#{property.name}_" && property.type == 10
+ # Dereference references
+ deref = @session.objects(:object_id => value, :broker => @broker)
+ return nil unless deref.size == 1
+ return deref[0]
+ end
+ end
+ @statistics.each do |statistic, value|
+ if name == statistic.name
+ return value
+ end
+ end
+ raise "Type Object has no attribute '#{name}'"
+ end
+
+ def encode(codec)
+ codec.write_uint8(20)
+ @schema.klass_key.encode(codec)
+
+ # emit presence masks for optional properties
+ mask = 0
+ bit = 0
+ schema.properties.each do |property|
+ if prop.optional
+ bit = 1 if bit == 0
+ mask |= bit if value
+ bit = bit << 1
+ if bit == 256
+ bit = 0
+ codec.write_uint8(mask)
+ mask = 0
+ end
+ codec.write_uint8(mask) if bit != 0
+ end
+ end
+
+ # encode properties
+ @properties.each do |property, value|
+ @session.encode_value(codec, value, prop.type) if value
+ end
+
+ # encode statistics
+ @statistics.each do |statistic, value|
+ @session.encode_value(codec, value, stat.type)
+ end
+ end
+
+ private
+
+ def send_method_request(method, name, args, synchronous = false, time_wait = nil)
+ @schema.methods.each do |schema_method|
+ if name == schema_method.name
+ send_codec = Qpid::StringCodec.new(@broker.conn.spec)
+ seq = @session.seq_mgr.reserve([schema_method, synchronous])
+ @broker.set_header(send_codec, ?M, seq)
+ @object_id.encode(send_codec)
+ @schema.klass_key.encode(send_codec)
+ send_codec.write_str8(name)
+
+ formals = method.arguments.select { |arg| arg.dir.index(?I) }
+ count = method.arguments.select { |arg| arg.dir.index(?I) }.size
+ unless formals.size == args.size
+ raise "Incorrect number of arguments: expected #{formals.size}, got #{args.size}"
+ end
+
+ formals.zip(args).each do |formal, actual|
+ @session.encode_value(send_codec, actual, formal.type)
+ end
+
+ ttl = time_wait ? time_wait * 1000 : nil
+ smsg = @broker.message(send_codec.encoded,
+ "agent.#{object_id.broker_bank}.#{object_id.agent_bank}", ttl=ttl)
+ @broker.sync_start if synchronous
+ @broker.emit(smsg)
+
+ return seq
+ end
+ end
+ end
+
+ def invoke(method, name, args)
+ kwargs = args[args.size - 1]
+ sync = true
+ timeout = DEFAULT_METHOD_WAIT_TIME
+
+ if kwargs.class == Hash
+ if kwargs.include?(:timeout)
+ timeout = kwargs[:timeout]
+ end
+
+ if kwargs.include?(:async)
+ sync = !kwargs[:async]
+ end
+ args.pop
+ end
+
+ seq = send_method_request(method, name, args, synchronous = sync)
+ if seq
+ return seq unless sync
+ unless @broker.wait_for_sync_done(timeout)
+ @session.seq_mgr.release(seq)
+ raise "Timed out waiting for method to respond"
+ end
+
+ if @broker.error
+ error_text = @broker.error
+ @broker.error = nil
+ raise error_text
+ end
+
+ return @broker.sync_result
+ end
+ raise "Invalid Method (software defect) [#{name}]"
+ end
+
+ def parse_presence_masks(codec, schema)
+ exclude_list = []
+ bit = 0
+ schema.properties.each do |property|
+ if property.optional
+ if bit == 0
+ mask = codec.read_uint8
+ bit = 1
+ end
+ if (mask & bit) == 0
+ exclude_list << property.name
+ end
+ bit *= 2
+ bit = 0 if bit == 256
+ end
+ end
+ return exclude_list
+ end
+ end
+
+ class MethodResult
+
+ attr_reader :status, :text, :out_args
+
+ def initialize(status, text, out_args)
+ @status = status
+ @text = text
+ @out_args = out_args
+ end
+
+ def method_missing(name)
+ name = name.to_s()
+ if @out_args.include?(name)
+ return @out_args[name]
+ else
+ raise "Unknown method result arg #{name}"
+ end
+ end
+
+ def to_s
+ argsString = ""
+ padding = ""
+ out_args.each do |key,value|
+ argsString += padding
+ padding = " " if padding == ""
+ argsString += key.to_s
+ argsString += " => "
+ argsString += value.to_s()
+ end
+ "MethodResult(Msg: '#{text}' Status: #{status} Return: [#{argsString}])"
+ end
+ end
+
+ class ManagedConnection
+
+ DELAY_MIN = 1
+ DELAY_MAX = 128
+ DELAY_FACTOR = 2
+ include MonitorMixin
+
+ def initialize(broker)
+ super()
+ @broker = broker
+ @cv = new_cond
+ @is_cancelled = false
+ end
+
+ # Main body of the running thread.
+ def start
+ @thread = Thread.new {
+ delay = DELAY_MIN
+ while true
+ begin
+ @broker.try_to_connect
+ synchronize do
+ while !@is_cancelled and @broker.connected?
+ @cv.wait
+ Thread.exit if @is_cancelled
+ delay = DELAY_MIN
+ end
+ end
+
+ rescue
+ delay *= DELAY_FACTOR if delay < DELAY_MAX
+ end
+
+ synchronize do
+ @cv.wait(delay)
+ Thread.exit if @is_cancelled
+ end
+ end
+ }
+ end
+
+ # Tell this thread to stop running and return.
+ def stop
+ synchronize do
+ @is_cancelled = true
+ @cv.signal
+ end
+ end
+
+ # Notify the thread that the connection was lost.
+ def disconnected
+ synchronize do
+ @cv.signal
+ end
+ end
+
+ def join
+ @thread.join
+ end
+ end
+
+ class Broker
+
+ SYNC_TIME = 60
+ @@next_seq = 1
+
+ include MonitorMixin
+
+ attr_accessor :error
+
+ attr_reader :amqp_session_id, :amqp_session, :conn, :broker_bank, :topic_name
+
+ attr_accessor :broker_id, :sync_result
+
+ def initialize(session, host, port, auth_name, auth_pass, kwargs)
+ super()
+
+ # For debugging..
+ Thread.abort_on_exception = true
+
+ @session = session
+ @host = host
+ @port = port
+ @auth_name = auth_name
+ @auth_pass = auth_pass
+ @user_id = nil
+ @auth_mechanism = kwargs[:mechanism]
+ @auth_service = kwargs[:service]
+ @broker_bank = 1
+ @topic_bound = false
+ @cv = new_cond
+ @error = nil
+ @broker_id = nil
+ @is_connected = false
+ @amqp_session_id = "%s.%d.%d" % [Socket.gethostname, Process::pid, @@next_seq]
+ @@next_seq += 1
+ @conn = nil
+ if @session.managedConnections?
+ @thread = ManagedConnection.new(self)
+ @thread.start
+ else
+ @thread = nil
+ try_to_connect
+ end
+ end
+
+ def connected?
+ @is_connected
+ end
+
+ def agent(broker_bank, agent_bank)
+ bank_key = "%d.%d" % [broker_bank, agent_bank]
+ return @agents[bank_key]
+ end
+
+ # Get the list of agents reachable via this broker
+ def agents
+ @agents.values
+ end
+
+ def url
+ "#{@host}:#{@port}"
+ end
+
+ def to_s
+ if connected?
+ "Broker connected at: #{url}"
+ else
+ "Disconnected Broker"
+ end
+ end
+
+ def wait_for_sync_done(timeout=nil)
+ wait_time = timeout ? timeout : SYNC_TIME
+ synchronize do
+ return @cv.wait_for(wait_time) { ! @sync_in_flight || @error }
+ end
+ end
+
+ def wait_for_stable
+ synchronize do
+ return unless connected?
+ return if @reqs_outstanding == 0
+ @sync_in_flight = true
+ unless @cv.wait_for(SYNC_TIME) { @reqs_outstanding == 0 }
+ raise "Timed out waiting for broker to synchronize"
+ end
+ end
+ end
+
+ # Compose the header of a management message
+ def set_header(codec, opcode, seq=0)
+ codec.write_uint8(?A)
+ codec.write_uint8(?M)
+ codec.write_uint8(?2)
+ codec.write_uint8(opcode)
+ codec.write_uint32(seq)
+ end
+
+ def message(body, routing_key="broker", ttl=nil)
+ dp = @amqp_session.delivery_properties
+ dp.routing_key = routing_key
+ dp.ttl = ttl if ttl
+ mp = @amqp_session.message_properties
+ mp.content_type = "x-application/qmf"
+ mp.reply_to = amqp_session.reply_to("amq.direct", @reply_name)
+ #mp.user_id = @user_id if @user_id
+ return Qpid::Message.new(dp, mp, body)
+ end
+
+ def emit(msg, dest="qpid.management")
+ @amqp_session.message_transfer(:destination => dest,
+ :message => msg)
+ end
+
+ def inc_outstanding
+ synchronize { @reqs_outstanding += 1 }
+ end
+
+ def dec_outstanding
+ synchronize do
+ @reqs_outstanding -= 1
+ if @reqs_outstanding == 0 && ! @topic_bound
+ @topic_bound = true
+ @session.binding_key_list.each do |key|
+ args = {
+ :exchange => "qpid.management",
+ :queue => @topic_name,
+ :binding_key => key }
+ @amqp_session.exchange_bind(args)
+ end
+ end
+ if @reqs_outstanding == 0 && @sync_in_flight
+ sync_done
+ end
+ end
+ end
+
+ def sync_start
+ synchronize { @sync_in_flight = true }
+ end
+
+ def sync_done
+ synchronize do
+ @sync_in_flight = false
+ @cv.signal
+ end
+ end
+
+ def update_agent(obj)
+ bank_key = "%d.%d" % [obj.brokerBank, obj.agentBank]
+ if obj.delete_time == 0
+ unless @agents.include?(bank_key)
+ agent = Agent.new(self, obj.agentBank, obj.label)
+ @agents[bank_key] = agent
+ @session.console.new_agent(agent) if @session.console
+ end
+ else
+ agent = @agents.delete(bank_key)
+ @session.console.del_agent(agent) if agent && @session.console
+ end
+ end
+
+ def shutdown
+ if @thread
+ @thread.stop
+ @thread.join
+ end
+ if connected?
+ @amqp_session.incoming("rdest").stop
+ if @session.console
+ @amqp_session.incoming("tdest").stop
+ end
+ @amqp_session.close
+ @is_connected = false
+ end
+ end
+
+ def try_to_connect
+ @agents = {}
+ @agents["1.0"] = Agent.new(self, 0, "BrokerAgent")
+ @topic_bound = false
+ @sync_in_flight = false
+ @sync_request = 0
+ @sync_result = nil
+ @reqs_outstanding = 1
+
+ # FIXME: Need sth for Qpid::Util::connect
+
+ @conn = Qpid::Connection.new(TCPSocket.new(@host, @port),
+ :mechanism => @auth_mechanism,
+ :username => @auth_name,
+ :password => @auth_pass,
+ :host => @host,
+ :service => @auth_service)
+ @conn.start
+ @user_id = @conn.user_id
+ @reply_name = "reply-%s" % amqp_session_id
+ @amqp_session = @conn.session(@amqp_session_id)
+ @amqp_session.auto_sync = true
+
+ @amqp_session.queue_declare(:queue => @reply_name,
+ :exclusive => true,
+ :auto_delete => true)
+
+ @amqp_session.exchange_bind(:exchange => "amq.direct",
+ :queue => @reply_name,
+ :binding_key => @reply_name)
+ @amqp_session.message_subscribe(:queue => @reply_name,
+ :destination => "rdest",
+ :accept_mode => @amqp_session.message_accept_mode.none,
+ :acquire_mode => @amqp_session.message_acquire_mode.pre_acquired)
+ q = @amqp_session.incoming("rdest")
+ q.exc_listen(& method(:exception_cb))
+ q.listen(& method(:reply_cb))
+ @amqp_session.message_set_flow_mode(:destination => "rdest",
+ :flow_mode => 1)
+ @amqp_session.message_flow(:destination => "rdest",
+ :unit => 0,
+ :value => 0xFFFFFFFF)
+ @amqp_session.message_flow(:destination => "rdest",
+ :unit => 1,
+ :value => 0xFFFFFFFF)
+
+ @topic_name = "topic-#{@amqp_session_id}"
+ @amqp_session.queue_declare(:queue => @topic_name,
+ :exclusive => true,
+ :auto_delete => true)
+ @amqp_session.message_subscribe(:queue => @topic_name,
+ :destination => "tdest",
+ :accept_mode => @amqp_session.message_accept_mode.none,
+ :acquire_mode => @amqp_session.message_acquire_mode.pre_acquired)
+ @amqp_session.incoming("tdest").listen(& method(:reply_cb))
+ @amqp_session.message_set_flow_mode(:destination => "tdest",
+ :flow_mode => 1)
+ @amqp_session.message_flow(:destination => "tdest",
+ :unit => 0,
+ :value => 0xFFFFFFFF)
+ @amqp_session.message_flow(:destination => "tdest",
+ :unit => 1,
+ :value => 0xFFFFFFFF)
+
+ @is_connected = true
+ @session.handle_broker_connect(self)
+
+ codec = Qpid::StringCodec.new(@conn.spec)
+ set_header(codec, ?B)
+ msg = message(codec.encoded)
+ emit(msg)
+ end
+
+ private
+
+ # Check the header of a management message and extract the opcode and
+ # class
+ def check_header(codec)
+ begin
+ return [nil, nil] unless codec.read_uint8 == ?A
+ return [nil, nil] unless codec.read_uint8 == ?M
+ return [nil, nil] unless codec.read_uint8 == ?2
+ opcode = codec.read_uint8
+ seq = codec.read_uint32
+ return [opcode, seq]
+ rescue
+ return [nil, nil]
+ end
+ end
+
+ def reply_cb(msg)
+ codec = Qpid::StringCodec.new(@conn.spec, msg.body)
+ loop do
+ opcode, seq = check_header(codec)
+ return unless opcode
+ case opcode
+ when ?b: @session.handle_broker_resp(self, codec, seq)
+ when ?p: @session.handle_package_ind(self, codec, seq)
+ when ?z: @session.handle_command_complete(self, codec, seq)
+ when ?q: @session.handle_class_ind(self, codec, seq)
+ when ?m: @session.handle_method_resp(self, codec, seq)
+ when ?h: @session.handle_heartbeat_ind(self, codec, seq, msg)
+ when ?e: @session.handle_event_ind(self, codec, seq)
+ when ?s: @session.handle_schema_resp(self, codec, seq)
+ when ?c: @session.handle_content_ind(self, codec, seq, true, false)
+ when ?i: @session.handle_content_ind(self, codec, seq, false, true)
+ when ?g: @session.handle_content_ind(self, codec, seq, true, true)
+ else
+ raise "Unexpected opcode #{opcode.inspect}"
+ end
+ end
+ end
+
+ def exception_cb(data)
+ @is_connected = false
+ @error = data
+ synchronize { @cv.signal if @sync_in_flight }
+ @session.handle_error(@error)
+ @session.handle_broker_disconnect(self)
+ @thread.disconnected if @thread
+ end
+ end
+
+ class Agent
+ attr_reader :broker, :agent_bank, :label
+
+ def initialize(broker, agent_bank, label)
+ @broker = broker
+ @agent_bank = agent_bank
+ @label = label
+ end
+
+ def broker_bank
+ @broker.broker_bank
+ end
+
+ def to_s
+ "Agent at bank %d.%d (%s)" % [@broker.broker_bank, @agent_bank, @label]
+ end
+ end
+
+ class Event
+
+ attr_reader :klass_key, :arguments, :timestamp, :name, :schema
+
+ def initialize(session, broker, codec)
+ @session = session
+ @broker = broker
+ @klass_key = ClassKey.new(codec)
+ @timestamp = codec.read_int64
+ @severity = codec.read_uint8
+ @schema = nil
+
+ pname, cname, hash = @klass_key.to_a()
+ session.packages.keys.each do |pname|
+ k = [cname, hash]
+ if session.packages[pname].include?(k)
+ @schema = session.packages[pname][k]
+ @arguments = {}
+ @schema.arguments.each do |arg|
+ v = session.decode_value(codec, arg.type)
+ @arguments[arg.name] = v
+ end
+ end
+ end
+ end
+
+ def to_s
+ return "<uninterpretable>" unless @schema
+ t = Time.at(self.timestamp / 1000000000)
+ out = t.strftime("%c")
+ out += " " + sev_name + " " + @klass_key.package + ":" + @klass_key.klass_name
+ out += " broker=" + @broker.url
+ @schema.arguments.each do |arg|
+ out += " " + arg.name + "=" + @session.display_value(@arguments[arg.name], arg.type)
+ end
+ return out
+ end
+
+ def sev_name
+ case @severity
+ when 0 : return "EMER "
+ when 1 : return "ALERT"
+ when 2 : return "CRIT "
+ when 3 : return "ERROR"
+ when 4 : return "WARN "
+ when 5 : return "NOTIC"
+ when 6 : return "INFO "
+ when 7 : return "DEBUG"
+ else
+ return "INV-%d" % @severity
+ end
+ end
+
+ end
+
+ # Manage sequence numbers for asynchronous method calls
+ class SequenceManager
+ include MonitorMixin
+
+ def initialize
+ super()
+ @sequence = 0
+ @pending = {}
+ end
+
+ # Reserve a unique sequence number
+ def reserve (data)
+ synchronize do
+ result = @sequence
+ @sequence += 1
+ @pending[result] = data
+ return result
+ end
+ end
+
+ # Release a reserved sequence number
+ def release (seq)
+ synchronize { @pending.delete(seq) }
+ end
+ end
+
+ class DebugConsole < Console
+
+ def broker_connected(broker)
+ puts "brokerConnected #{broker}"
+ end
+
+ def broker_disconnected(broker)
+ puts "brokerDisconnected #{broker}"
+ end
+
+ def new_package(name)
+ puts "newPackage #{name}"
+ end
+
+ def new_class(kind, klass_key)
+ puts "newClass #{kind} #{klass_key}"
+ end
+
+ def new_agent(agent)
+ puts "new_agent #{agent}"
+ end
+
+ def del_agent(agent)
+ puts "delAgent #{agent}"
+ end
+
+ def object_props(broker, record)
+ puts "objectProps #{record}"
+ end
+
+ def object_stats(broker, record)
+ puts "objectStats #{record}"
+ end
+
+ def event(broker, event)
+ puts "event #{event}"
+ end
+
+ def heartbeat(agent, timestamp)
+ puts "heartbeat #{agent}"
+ end
+
+ def broker_info(broker)
+ puts "brokerInfo #{broker}"
+ end
+ end
+
+ module XML
+ TYPES = {
+ 1 => "uint8",
+ 2 => "uint16",
+ 3 => "uint32",
+ 4 => "uint64",
+ 5 => "bool",
+ 6 => "short-stirng",
+ 7 => "long-string",
+ 8 => "abs-time",
+ 9 => "delta-time",
+ 10 => "reference",
+ 11 => "boolean",
+ 12 => "float",
+ 13 => "double",
+ 14 => "uuid",
+ 15 => "field-table",
+ 16 => "int8",
+ 17 => "int16",
+ 18 => "int32",
+ 19 => "int64",
+ 20 => "object",
+ 21 => "list",
+ 22 => "array"
+ }
+
+ ACCESS_MODES = {
+ 1 => "RC",
+ 2 => "RW",
+ 3 => "RO"
+ }
+
+ def common_attributes(item)
+ attr_string = ""
+ attr_string << " desc='#{item.desc}'" if item.desc
+ attr_string << " desc='#{item.desc}'" if item.desc
+ attr_string << " refPackage='#{item.refPackage}'" if item.refPackage
+ attr_string << " refClass='#{item.refClass}'" if item.refClass
+ attr_string << " unit='#{item.unit}'" if item.unit
+ attr_string << " min='#{item.min}'" if item.min
+ attr_string << " max='#{item.max}'" if item.max
+ attr_string << " maxlen='#{item.maxlen}'" if item.maxlen
+ return attr_string
+ end
+
+ module_function :common_attributes
+
+ def schema_xml(session, *packages)
+ schema = "<schemas>\n"
+ packages.each do |package|
+ schema << "\t<schema package='#{package}'>\n"
+ session.classes(package).each do |klass_key|
+ klass = session.schema(klass_key)
+ if klass.is_table?
+ if klass.super_klass_key
+ schema << "\t\t<class name='#{klass.klass_key.klass_name}' hash='#{klass.klass_key.hash_string}' extends='#{klass.super_klass_key.to_s}'>\n"
+ else
+ schema << "\t\t<class name='#{klass.klass_key.klass_name}' hash='#{klass.klass_key.hash_string}'>\n"
+ end
+ klass.properties(false).each do |property|
+ schema << "\t\t\t<property name='#{property.name}' type='#{TYPES[property.type]}' access='#{ACCESS_MODES[property.access]}' optional='#{property.optional ? "True" : "False"}'#{common_attributes(property)}/>\n"
+ end
+ klass.methods(false).each do |method|
+ schema << "\t\t\t<method name='#{method.name}'>\n"
+ method.arguments.each do |arg|
+ schema << "\t\t\t\t<arg name='#{arg.name}' dir='#{arg.dir}' type='#{TYPES[arg.type]}'#{common_attributes(arg)}/>\n"
+ end
+ schema << "\t\t\t</method>\n"
+ end
+ schema << "\t\t</class>\n"
+ else
+ schema << "\t\t<event name='#{klass.klass_key.klass_name}' hash='#{klass.klass_key.hash_string}'>\n"
+ klass.arguments.each do |arg|
+ schema << "\t\t\t<arg name='#{arg.name}'type='#{TYPES[arg.type]}'#{common_attributes(arg)}/>\n"
+ end
+ schema << "\t\t</event>\n"
+ end
+ end
+ schema << "\t</package>\n"
+ end
+ schema << "</schema>"
+ end
+
+ module_function :schema_xml
+ end
+
+end
diff --git a/ruby/lib/qpid/queue.rb b/ruby/lib/qpid/queue.rb
new file mode 100644
index 0000000000..4150173b53
--- /dev/null
+++ b/ruby/lib/qpid/queue.rb
@@ -0,0 +1,101 @@
+#
+# 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.
+#
+
+# Augment the standard python multithreaded Queue implementation to add a
+# close() method so that threads blocking on the content of a queue can be
+# notified if the queue is no longer in use.
+
+require 'thread'
+
+# Python nominally uses a bounded queue, but the code never establishes
+# a maximum size; we therefore use Ruby's unbounded queue
+class Qpid::Queue < ::Queue
+
+ DONE = Object.new
+ STOP = Object.new
+
+ def initialize
+ super
+ @error = nil
+ @listener = nil
+ @exc_listener = nil
+ @exc_listener_lock = Monitor.new
+ @thread = nil
+ end
+
+ def close(error = nil)
+ @error = error
+ put(DONE)
+ unless @thread.nil?
+ @thread.join()
+ @thread = nil
+ end
+ end
+
+ def get(block = true, timeout = nil)
+ unless timeout.nil?
+ raise NotImplementedError
+ end
+ result = pop(! block)
+ if result == DONE
+ # this guarantees that any other waiting threads or any future
+ # calls to get will also result in a Qpid::Closed exception
+ put(DONE)
+ raise Qpid::Closed.new(@error)
+ else
+ return result
+ end
+ end
+
+ alias :put :push
+
+ def exc_listen(&block)
+ @exc_listener_lock.synchronize do
+ @exc_listener = block
+ end
+ end
+
+ def listen(&block)
+ if ! block_given? && @thread
+ put(STOP)
+ @thread.join()
+ @thread = nil
+ end
+
+ # FIXME: There is a potential race since we could be changing one
+ # non-nil listener to another
+ @listener = block
+
+ if block_given? && @thread.nil?
+ @thread = Thread.new do
+ loop do
+ begin
+ o = get()
+ break if o == STOP
+ @listener.call(o)
+ rescue Qpid::Closed => e
+ @exc_listener.call(e) if @exc_listener
+ break
+ end
+ end
+ end
+ end
+ end
+
+end
diff --git a/ruby/lib/qpid/session.rb b/ruby/lib/qpid/session.rb
new file mode 100644
index 0000000000..d693b722c2
--- /dev/null
+++ b/ruby/lib/qpid/session.rb
@@ -0,0 +1,458 @@
+#
+# 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 'monitor'
+
+module Qpid
+
+ class Session < Invoker
+
+ def log; Qpid::logger["qpid.io.cmd"]; end
+ def msg; Qpid::logger["qpid.io.msg"]; end
+
+
+ class Exception < RuntimeError; end
+ class Closed < Qpid::Session::Exception; end
+ class Detached < Qpid::Session::Exception; end
+
+
+ INCOMPLETE = Object.new
+
+ def self.client(*args)
+ return Qpid::Client(*args)
+ end
+
+ def self.server(*args)
+ return Server(*args)
+ end
+
+ attr_reader :name, :spec, :auto_sync, :timeout, :channel
+ attr_reader :results, :exceptions
+ attr_accessor :channel, :auto_sync, :send_id, :receiver, :sender
+
+ # FIXME: Pass delegate through a block ?
+ def initialize(name, spec, kwargs = {})
+ auto_sync = true
+ auto_sync = kwargs[:auto_sync] if kwargs.key?(:auto_sync)
+ timeout = kwargs[:timeout] || 10
+ delegate = kwargs[:delegate]
+
+ @name = name
+ @spec = spec
+ @auto_sync = auto_sync
+ @timeout = timeout
+ @invoke_lock = Monitor.new
+ @closing = false
+ @closed = false
+
+ @cond_lock = Monitor.new
+ @condition = @cond_lock.new_cond
+
+ @send_id = true
+ @receiver = Receiver.new(self)
+ @sender = Sender.new(self)
+
+ @lock = Monitor.new
+ @incoming = {}
+ @results = {}
+ @exceptions = []
+
+ @assembly = nil
+
+ @delegate = delegate.call(self) if delegate
+
+ @ctl_seg = spec[:segment_type].enum[:control].value
+ @cmd_seg = spec[:segment_type].enum[:command].value
+ @hdr_seg = spec[:segment_type].enum[:header].value
+ @body_seg = spec[:segment_type].enum[:body].value
+ end
+
+ def incoming(destination)
+ @lock.synchronize do
+ queue = @incoming[destination]
+ unless queue
+ queue = Incoming.new(self, destination)
+ @incoming[destination] = queue
+ end
+ return queue
+ end
+ end
+
+ def error?
+ @exceptions.size > 0
+ end
+
+ def sync(timeout=nil)
+ if channel && Thread.current == channel.connection.thread
+ raise Qpid::Session::Exception, "deadlock detected"
+ end
+ unless @auto_sync
+ execution_sync(:sync => true)
+ end
+ last = @sender.next_id - 1
+ @cond_lock.synchronize do
+ unless @condition.wait_for(timeout) {
+ @sender.completed.include?(last) || error?
+ }
+ raise Qpid::Timeout
+ end
+ end
+ if error?
+ raise Qpid::Session::Exception, @exceptions
+ end
+ end
+
+ def close(timeout=nil)
+ @invoke_lock.synchronize do
+ @closing = true
+ channel.session_detach(name)
+ end
+ @cond_lock.synchronize do
+ unless @condition.wait_for(timeout) { @closed }
+ raise Qpid::Timeout
+ end
+ end
+ end
+
+ def closed
+ @lock.synchronize do
+ return if @closed
+
+ @results.each { |id, f| f.error(exceptions) }
+ @results.clear
+
+ @incoming.values.each { |q| q.close(exceptions) }
+ @closed = true
+ @cond_lock.synchronize { @condition.signal }
+ end
+ end
+
+ def resolve_method(name)
+ o = @spec.children[name]
+ case o
+ when Qpid::Spec010::Command
+ return invocation(:method, o)
+ when Qpid::Spec010::Struct
+ return invocation(:method, o)
+ when Qpid::Spec010::Domain
+ return invocation(:value, o.enum) unless o.enum.nil?
+ end
+
+ matches = @spec.children.select { |x|
+ x.name.to_s.include?(name.to_s)
+ }.collect { |x| x.name.to_s }.sort
+ if matches.size == 0
+ msg = nil
+ elsif matches.size == 1
+ msg = "Did you mean #{matches[0]} ? "
+ else
+ msg = "Did you mean one of #{matches.join(",")} ? "
+ end
+ return invocation(:error, msg)
+ end
+
+ def invoke(type, args)
+ # XXX
+ unless type.respond_to?(:track)
+ return type.create(*args)
+ end
+ @invoke_lock.synchronize do
+ return do_invoke(type, args)
+ end
+ end
+
+ def do_invoke(type, args)
+ raise Qpid::Session::Closed if @closing
+ raise Qpid::Session::Detached unless channel
+
+ # Clumsy simulation of Python's keyword args
+ kwargs = {}
+ if args.size > 0 && args[-1].is_a?(Hash)
+ if args.size > type.fields.size
+ kwargs = args.pop
+ elsif type.fields[args.size - 1].type != @spec[:map]
+ kwargs = args.pop
+ end
+ end
+
+ if type.payload
+ if args.size == type.fields.size + 1
+ message = args.pop
+ else
+ message = kwargs.delete(:message) # XXX Really ?
+ end
+ else
+ message = nil
+ end
+
+ hdr = Qpid::struct(@spec[:header])
+ hdr.sync = @auto_sync || kwargs.delete(:sync)
+
+ cmd = type.create(*args.push(kwargs))
+ sc = Qpid::StringCodec.new(@spec)
+ sc.write_command(hdr, cmd)
+
+ seg = Segment.new(true, (message.nil? ||
+ (message.headers.nil? && message.body.nil?)),
+ type.segment_type, type.track, @channel.id, sc.encoded)
+
+ unless type.result.nil?
+ result = Future.new(exception=Exception)
+ @results[@sender.next_id] = result
+ end
+ emit(seg)
+
+ log.debug("SENT %s %s %s" % [seg.id, hdr, cmd]) if log
+
+ unless message.nil?
+ unless message.headers.nil?
+ sc = Qpid::StringCodec.new(@spec)
+ message.headers.each { |st| sc.write_struct32(st) }
+
+ seg = Segment.new(false, message.body.nil?, @hdr_seg,
+ type.track, @channel.id, sc.encoded)
+ emit(seg)
+ end
+ unless message.body.nil?
+ seg = Segment.new(false, true, @body_seg, type.track,
+ @channel.id, message.body)
+ emit(seg)
+ end
+ msg.debug("SENT %s" % message) if msg
+ end
+
+ if !type.result.nil?
+ return @auto_sync ? result.get(@timeout) : result
+ elsif @auto_sync
+ sync(@timeout)
+ end
+ end
+
+ def received(seg)
+ @receiver.received(seg)
+ if seg.first_segment?
+ raise Qpid::Session::Exception unless @assembly.nil?
+ @assembly = []
+ end
+ @assembly << seg
+ if seg.last_segment?
+ dispatch(@assembly)
+ @assembly = nil
+ end
+ end
+
+ def dispatch(assembly)
+ hdr = nil
+ cmd = nil
+ header = nil
+ body = nil
+ assembly.each do |seg|
+ d = seg.decode(@spec)
+ case seg.type
+ when @cmd_seg
+ hdr, cmd = d
+ when @hdr_seg
+ header = d
+ when @body_seg
+ body = d
+ else
+ raise Qpid::Session::Exception
+ end
+ end
+ log.debug("RECV %s %s %s" % [cmd.id, hdr, cmd]) if log
+
+ if cmd.st_type.payload
+ result = @delegate.send(cmd.st_type.name, cmd, header, body)
+ else
+ result = @delegate.send(cmd.st_type.name, cmd)
+ end
+
+ unless cmd.st_type.result.nil?
+ execution_result(cmd.id, result)
+ end
+
+ if result != INCOMPLETE
+ assembly.each do |seg|
+ @receiver.has_completed(seg)
+ # XXX: don't forget to obey sync for manual completion as well
+ if hdr.sync
+ @channel.session_completed(@receiver.completed)
+ end
+ end
+ end
+ end
+
+ # Python calls this 'send', but that has a special meaning
+ # in Ruby, so we call it 'emit'
+ def emit(seg)
+ @sender.emit(seg)
+ end
+
+ def signal
+ @cond_lock.synchronize { @condition.signal }
+ end
+
+ def wait_for(timeout = nil, &block)
+ @cond_lock.synchronize { @condition.wait_for(timeout, &block) }
+ end
+
+ def to_s
+ "<Session: #{name}, #{channel}>"
+ end
+
+ class Receiver
+
+ attr_reader :completed
+ attr_accessor :next_id, :next_offset
+
+ def initialize(session)
+ @session = session
+ @next_id = nil
+ @next_offset = nil
+ @completed = Qpid::RangedSet.new()
+ end
+
+ def received(seg)
+ if @next_id.nil? || @next_offset.nil?
+ raise Exception, "todo"
+ end
+ seg.id = @next_id
+ seg.offset = @next_offset
+ if seg.last_segment?
+ @next_id += 1
+ @next_offset = 0
+ else
+ @next_offset += seg.payload.size
+ end
+ end
+
+ def has_completed(seg)
+ if seg.id.nil?
+ raise ArgumentError, "cannot complete unidentified segment"
+ end
+ if seg.last_segment?
+ @completed.add(seg.id)
+ end
+ end
+
+ def known_completed(commands)
+ completed = Qpid::RangedSet.new()
+ @completed.ranges.each do |c|
+ unless commands.ranges.find { |kc|
+ kc.contains(c.lower) && kc.contains(c.upper)
+ }
+ completed.add_range(c)
+ end
+ end
+ @completed = completed
+ end
+ end
+
+ class Sender
+
+ def initialize(session)
+ @session = session
+ @next_id = 0.to_serial
+ @next_offset = 0
+ @segments = []
+ @completed = RangedSet.new()
+ end
+
+ attr_reader :next_id, :completed
+
+ def emit(seg)
+ seg.id = @next_id
+ seg.offset = @next_offset
+ if seg.last_segment?
+ @next_id += 1
+ @next_offset = 0
+ else
+ @next_offset += seg.payload.size
+ end
+ @segments << seg
+ if @session.send_id
+ @session.send_id = false
+ @session.channel.session_command_point(seg.id, seg.offset)
+ end
+ @session.channel.connection.write_segment(seg)
+ end
+
+ def has_completed(commands)
+ @segments = @segments.reject { |seg| commands.include?(seg.id) }
+ commands.ranges.each do |range|
+ @completed.add(range.lower, range.upper)
+ end
+ end
+ end
+
+ class Incoming < Qpid::Queue
+
+ def initialize(session, destination)
+ super()
+ @session = session
+ @destination = destination
+ end
+
+ def start
+ @session.message_credit_unit.choices.each do |unit|
+ @session.message_flow(@destination, unit.value, 0xFFFFFFFF)
+ end
+ end
+
+ def stop
+ @session.message_cancel(@destination)
+ listen # Kill the listener
+ end
+ end
+
+ class Delegate
+
+ def initialize(session)
+ @session = session
+ end
+
+ #XXX: do something with incoming accepts
+ def message_accept(ma) nil; end
+
+ def execution_result(er)
+ future = @session.results.delete(er.command_id)
+ future.set(er.value)
+ end
+
+ def execution_exception(ex)
+ @session.exceptions << ex
+ end
+ end
+
+ class Client < Delegate
+
+ def log ; Qpid::logger["qpid.io.msg"]; end
+
+ def message_transfer(cmd, headers, body)
+ m = Qpid::Message.new(body)
+ m.headers = headers
+ m.id = cmd.id
+ messages = @session.incoming(cmd.destination)
+ messages.put(m)
+ log.debug("RECV %s" % m) if log
+ return INCOMPLETE
+ end
+ end
+ end
+end
diff --git a/ruby/lib/qpid/spec.rb b/ruby/lib/qpid/spec.rb
new file mode 100644
index 0000000000..b3d70d019d
--- /dev/null
+++ b/ruby/lib/qpid/spec.rb
@@ -0,0 +1,183 @@
+#
+# 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 "set"
+require "rexml/document"
+require "qpid/fields"
+require "qpid/traverse"
+
+module Qpid
+ module Spec
+
+ include REXML
+
+ class Container < Array
+
+ def initialize()
+ @cache = {}
+ end
+
+ def [](key)
+ return @cache[key] if @cache.include?(key)
+ value = do_lookup(key)
+ @cache[key] = value
+ return value
+ end
+
+ def do_lookup(key)
+ case key
+ when String
+ return find {|x| x.name == key.intern()}
+ when Symbol
+ return find {|x| x.name == key}
+ else
+ return slice(key)
+ end
+ end
+
+ def +(other)
+ copy = clone()
+ copy.concat(other)
+ return copy
+ end
+
+ end
+
+ class Reference
+
+ fields(:name)
+
+ def init(&block)
+ @resolver = block
+ end
+
+ def resolve(*args)
+ @resolver.call(*args)
+ end
+
+ end
+
+ class Loader
+
+ def initialize()
+ @stack = []
+ end
+
+ def container()
+ return Container.new()
+ end
+
+ def load(obj)
+ case obj
+ when String
+ elem = @stack[-1]
+ result = container()
+ elem.elements.each(obj) {|e|
+ @index = result.size
+ result << load(e)
+ }
+ @index = nil
+ return result
+ else
+ elem = obj
+ @stack << elem
+ begin
+ result = send(:"load_#{elem.name}")
+ ensure
+ @stack.pop()
+ end
+ return result
+ end
+ end
+
+ def element
+ @stack[-1]
+ end
+
+ def text
+ element.text
+ end
+
+ def attr(name, type = :string, default = nil, path = nil)
+ if path.nil?
+ elem = element
+ else
+ elem = nil
+ element.elements.each(path) {|elem|}
+ if elem.nil?
+ return default
+ end
+ end
+
+ value = elem.attributes[name]
+ value = value.strip() unless value.nil?
+ if value.nil?
+ default
+ else
+ send(:"parse_#{type}", value)
+ end
+ end
+
+ def parse_int(value)
+ if value.nil?
+ return nil
+ else
+ value.to_i(0)
+ end
+ end
+
+ TRUE = ["yes", "true", "1"].to_set
+ FALSE = ["no", "false", "0", nil].to_set
+
+ def parse_bool(value)
+ if TRUE.include?(value)
+ true
+ elsif FALSE.include?(value)
+ false
+ else
+ raise Exception.new("parse error, expecting boolean: #{value}")
+ end
+ end
+
+ def parse_string(value)
+ value.to_s
+ end
+
+ def parse_symbol(value)
+ value.intern() unless value.nil?
+ end
+
+ REPLACE = {" " => "_", "-" => "_"}
+ KEYWORDS = {"global" => "global_", "return" => "return_"}
+
+ def parse_name(value)
+ return if value.nil?
+
+ REPLACE.each do |k, v|
+ value = value.gsub(k, v)
+ end
+
+ value = KEYWORDS[value] if KEYWORDS.has_key? value
+ return value.intern()
+ end
+
+ end
+
+ end
+end
diff --git a/ruby/lib/qpid/spec010.rb b/ruby/lib/qpid/spec010.rb
new file mode 100644
index 0000000000..3e54115087
--- /dev/null
+++ b/ruby/lib/qpid/spec010.rb
@@ -0,0 +1,485 @@
+#
+# 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/spec"
+require 'pathname'
+require 'fileutils'
+
+module Qpid::Spec010
+
+ include Qpid::Spec
+
+ # XXX: workaround for ruby bug/missfeature
+ Reference = Reference
+ Loader = Loader
+
+ class Spec
+
+ ENCODINGS = {
+ String => "str16",
+ Fixnum => "int64",
+ Bignum => "int64",
+ Float => "float",
+ NilClass => "void",
+ Array => "list",
+ Hash => "map"
+ }
+
+ fields(:major, :minor, :port, :children)
+
+ def init()
+ @controls = {}
+ @commands = {}
+ @structs = {}
+ @types = {}
+ children.each {|c|
+ case c
+ when Control
+ @controls[c.code] = c
+ when Command
+ @commands[c.code] = c
+ when Struct
+ @structs[c.code] = c
+ when Type
+ @types[c.code] = c unless c.code.nil?
+ end
+ }
+ end
+
+ attr_reader :controls, :commands, :structs, :types
+
+ def [](key)
+ return @children[key]
+ end
+
+ def encoding(klass)
+ if ENCODINGS.has_key?(klass)
+ return self[ENCODINGS[klass]]
+ end
+ for base in klass.__bases__
+ result = encoding(base)
+ return result unless result.nil?
+ end
+ end
+
+ def inspect; "spec"; end
+ end
+
+ class Constant
+
+ fields(:name, :value)
+
+ attr :parent, true
+
+ end
+
+ class Type
+
+ fields(:name, :code, :fixed, :variable)
+
+ attr :parent, true
+
+ def present?(value)
+ if @fixed == 0
+ return value
+ else
+ return !value.nil?
+ end
+ end
+
+ def encode(codec, value)
+ codec.send("write_#{name}", value)
+ end
+
+ def decode(codec)
+ return codec.send("read_#{name}")
+ end
+
+ def inspect; name; end
+
+ end
+
+ class Domain < Type
+
+ fields(:name, :type, :enum)
+
+ attr :parent, true
+
+ def encode(codec, value)
+ @type.encode(codec, value)
+ end
+
+ def decode(codec)
+ return @type.decode(codec)
+ end
+
+ end
+
+ class Enum
+ fields(:choices)
+
+ def [](choice)
+ case choice
+ when String
+ choice = choice.to_sym
+ return choices.find { |c| c.name == choice }
+ when Symbol
+ return choices.find { |c| c.name == choice }
+ else
+ return choices.find { |c| c.value == choice }
+ end
+ end
+
+ def method_missing(name, *args)
+ raise ArgumentError.new("wrong number of arguments") unless args.empty?
+ return self[name].value
+ end
+
+ end
+
+ class Choice
+ fields(:name, :value)
+ end
+
+ class Composite
+
+ fields(:name, :code, :size, :pack, :fields)
+
+ attr :parent, true
+
+ # Python calls this 'new', but that has special meaning in Ruby
+ def create(*args)
+ return Qpid::struct(self, *args)
+ end
+
+ def decode(codec)
+ codec.read_size(@size)
+ codec.read_uint16() unless @code.nil?
+ return Qpid::struct(self, self.decode_fields(codec))
+ end
+
+ def decode_fields(codec)
+ flags = 0
+ pack.times {|i| flags |= (codec.read_uint8() << 8*i)}
+
+ result = {}
+
+ fields.each_index {|i|
+ f = @fields[i]
+ if flags & (0x1 << i) != 0
+ result[f.name] = f.type.decode(codec)
+ else
+ result[f.name] = nil
+ end
+ }
+
+ return result
+ end
+
+ def encode(codec, value)
+ sc = Qpid::StringCodec.new(@spec)
+ sc.write_uint16(@code) unless @code.nil?
+ encode_fields(sc, value)
+ codec.write_size(@size, sc.encoded.size)
+ codec.write(sc.encoded)
+ end
+
+ def encode_fields(codec, values)
+ # FIXME: This could be written cleaner using select
+ # instead of flags
+ flags = 0
+ fields.each_index do |i|
+ f = fields[i]
+ flags |= (0x1 << i) if f.type.present?(values[f.name])
+ end
+
+ pack.times { |i| codec.write_uint8((flags >> 8*i) & 0xFF) }
+
+ fields.each_index do |i|
+ f = fields[i]
+ f.type.encode(codec, values[f.name]) if flags & (0x1 << i) != 0
+ end
+ end
+
+ def inspect; name; end
+
+ end
+
+ class Field
+
+ fields(:name, :type, :exceptions)
+
+ def default()
+ return nil
+ end
+
+ end
+
+ class Struct < Composite
+
+ def present?(value)
+ return !value.nil?
+ end
+
+ end
+
+ class Action < Composite; end
+
+ class Control < Action
+
+ def segment_type
+ @parent[:segment_type].enum[:control].value
+ end
+
+ def track
+ @parent[:track].enum[:control].value
+ end
+
+ end
+
+ class Command < Action
+
+ attr_accessor :payload, :result
+
+ def segment_type
+ @parent["segment_type"].enum["command"].value
+ end
+
+ def track
+ @parent["track"].enum["command"].value
+ end
+
+ end
+
+ class Doc
+ fields(:type, :title, :text)
+ end
+
+ class Loader010 < Loader
+
+ def initialize()
+ super()
+ end
+
+ def klass
+ cls = element
+ until cls.nil?
+ break if cls.name == "class"
+ cls = cls.parent
+ end
+ return cls
+ end
+
+ def scope
+ if element.name == "struct"
+ return nil
+ else
+ return class_name
+ end
+ end
+
+ def class_name
+ cls = klass
+ if cls.nil?
+ return nil
+ else
+ return parse_name(cls.attributes["name"].strip)
+ end
+ end
+
+ def class_code
+ cls = klass
+ if cls.nil?
+ return 0
+ else
+ return parse_int(cls.attributes["code"].strip)
+ end
+ end
+
+ def parse_decl(value)
+ name = parse_name(value)
+
+ s = scope
+ if s.nil?
+ return name
+ else
+ return :"#{s}_#{name}"
+ end
+ end
+
+ def parse_code(value)
+ c = parse_int(value)
+ if c.nil?
+ return nil
+ else
+ return c | (class_code << 8)
+ end
+ end
+
+ def parse_type(value)
+ name = parse_name(value.sub(".", "_"))
+ cls = class_name
+ return Reference.new {|spec|
+ candidates = [name]
+ candidates << :"#{cls}_#{name}" unless cls.nil?
+ for c in candidates
+ child = spec[c]
+ break unless child.nil?
+ end
+ if child.nil?
+ raise Exception.new("unresolved type: #{name}")
+ else
+ child
+ end
+}
+ end
+
+ def load_amqp()
+ children = nil
+
+ for s in ["constant", "type", "domain", "struct", "control",
+ "command"]
+ ch = load(s)
+ if children.nil?
+ children = ch
+ else
+ children += ch
+ end
+ children += load("class/#{s}")
+ end
+ children += load("class/command/result/struct")
+ Spec.new(attr("major", :int), attr("minor", :int), attr("port", :int),
+ children)
+ end
+
+ def load_constant()
+ Constant.new(attr("name", :decl), attr("value", :int))
+ end
+
+ def load_type()
+ Type.new(attr("name", :decl), attr("code", :code),
+ attr("fixed-width", :int), attr("variable-width", :int))
+ end
+
+ def load_domain()
+ Domain.new(attr("name", :decl), attr("type", :type), load("enum").first)
+ end
+
+ def load_enum()
+ Enum.new(load("choice"))
+ end
+
+ def load_choice()
+ Choice.new(attr("name", :name), attr("value", :int))
+ end
+
+ def load_field()
+ Field.new(attr("name", :name), attr("type", :type))
+ end
+
+ def load_struct()
+ Struct.new(attr("name", :decl), attr("code", :code), attr("size", :int),
+ attr("pack", :int), load("field"))
+ end
+
+ def load_action(cls)
+ cls.new(attr("name", :decl), attr("code", :code), 0, 2, load("field"))
+ end
+
+ def load_control()
+ load_action(Control)
+ end
+
+ def load_command()
+ result = attr("type", :type, nil, "result")
+ result = attr("name", :type, nil, "result/struct") if result.nil?
+ segs = load("segments")
+ cmd = load_action(Command)
+ cmd.result = result
+ cmd.payload = !segs.empty?
+ return cmd
+ end
+
+ def load_result()
+ true
+ end
+
+ def load_segments()
+ true
+ end
+
+ end
+
+ def self.spec_cache(specfile)
+ File::join(File::dirname(__FILE__), "spec_cache",
+ File::basename(specfile, ".xml") + ".rb_marshal")
+ end
+
+ # XXX: could be shared
+ def self.load(spec = nil)
+ return spec if spec.is_a?(Qpid::Spec010::Spec)
+ if spec.nil?
+ # FIXME: Need to add a packaging setup in here so we know where
+ # the installed spec is going to be.
+ specfile = nil
+ if ENV['AMQP_SPEC']
+ specfile = ENV['AMQP_SPEC']
+ else
+ require "qpid/config"
+ specfile = Qpid::Config.amqp_spec
+ end
+ else
+ specfile = spec
+ end
+
+ specfile_cache = spec_cache(specfile)
+ # FIXME: Check that cache is newer than specfile
+ if File::exist?(specfile_cache)
+ begin
+ spec = File::open(specfile_cache, "r") do |f|
+ Marshal::load(f)
+ end
+ return spec
+ rescue
+ # Ignore, will load from XML
+ end
+ end
+
+ doc = File::open(specfile, "r") { |f| Document.new(f) }
+ spec = Loader010.new().load(doc.root)
+ spec.traverse! do |o|
+ if o.is_a?(Reference)
+ o.resolve(spec)
+ else
+ o
+ end
+ end
+
+ spec.children.each { |c| c.parent = spec }
+
+ begin
+ FileUtils::mkdir_p(File::dirname(specfile_cache))
+ File::open(specfile_cache, "w") { |f| Marshal::dump(spec, f) }
+ rescue
+ # Ignore, we are fine without the cached spec
+ end
+ return spec
+ end
+
+end
diff --git a/ruby/lib/qpid/spec08.rb b/ruby/lib/qpid/spec08.rb
new file mode 100644
index 0000000000..902c05c297
--- /dev/null
+++ b/ruby/lib/qpid/spec08.rb
@@ -0,0 +1,190 @@
+#
+# 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/spec"
+
+module Qpid08
+
+ module Spec
+
+ include Qpid::Spec
+
+ # XXX: workaround for ruby bug/missfeature
+ Reference = Reference
+
+ class Root
+ fields(:major, :minor, :classes, :constants, :domains)
+
+ def find_method(name)
+ classes.each do |c|
+ c.methods.each do |m|
+ if name == m.qname
+ return m
+ end
+ end
+ end
+
+ return nil
+ end
+ end
+
+ class Constant
+ fields(:name, :id, :type, :docs)
+ end
+
+ class Domain
+ fields(:name, :type)
+ end
+
+ class Class
+ fields(:name, :id, :handler, :fields, :methods, :docs)
+ end
+
+ class Method
+ fields(:name, :id, :content?, :responses, :synchronous?, :fields,
+ :docs)
+
+ def init()
+ @response = false
+ end
+
+ attr :parent, true
+
+ def response?; @response end
+ def response=(b); @response = b end
+
+ def qname
+ :"#{parent.name}_#{name}"
+ end
+ end
+
+ class Field
+ fields(:name, :id, :type, :docs)
+
+ def default
+ case type
+ when :bit then false
+ when :octet, :short, :long, :longlong then 0
+ when :shortstr, :longstr then ""
+ when :table then {}
+ end
+ end
+ end
+
+ class Doc
+ fields(:type, :text)
+ end
+
+ class Container08 < Container
+ def do_lookup(key)
+ case key
+ when Integer
+ return find {|x| x.id == key}
+ else
+ return super(key)
+ end
+ end
+ end
+
+ class Loader08 < Loader
+
+ def container()
+ return Container08.new()
+ end
+
+ def load_amqp()
+ Root.new(attr("major", :int), attr("minor", :int), load("class"),
+ load("constant"), load("domain"))
+ end
+
+ def load_class()
+ Class.new(attr("name", :name), attr("index", :int), attr("handler", :name),
+ load("field"), load("method"), load("doc"))
+ end
+
+ def load_method()
+ Method.new(attr("name", :name), attr("index", :int),
+ attr("content", :bool), load("response"),
+ attr("synchronous", :bool), load("field"), load("docs"))
+ end
+
+ def load_response()
+ name = attr("name", :name)
+ Reference.new {|spec, klass|
+ response = klass.methods[name]
+ if response.nil?
+ raise Exception.new("no such method: #{name}")
+ end
+ response
+ }
+ end
+
+ def load_field()
+ type = attr("type", :name)
+ if type.nil?
+ domain = attr("domain", :name)
+ type = Reference.new {|spec, klass|
+ spec.domains[domain].type
+ }
+ end
+ Field.new(attr("name", :name), @index, type, load("docs"))
+ end
+
+ def load_constant()
+ Constant.new(attr("name", :name), attr("value", :int), attr("class", :name),
+ load("doc"))
+ end
+
+ def load_domain()
+ Domain.new(attr("name", :name), attr("type", :name))
+ end
+
+ def load_doc()
+ Doc.new(attr("type", :symbol), text)
+ end
+
+ end
+
+ def self.load(spec)
+ case spec
+ when String
+ spec = File.new(spec)
+ end
+ doc = Document.new(spec)
+ spec = Loader08.new().load(doc.root)
+ spec.classes.each do |klass|
+ klass.traverse! do |o|
+ case o
+ when Reference
+ o.resolve(spec, klass)
+ else
+ o
+ end
+ end
+ klass.methods.each do |m|
+ m.parent = klass
+ m.responses.each do |r|
+ r.response = true
+ end
+ end
+ end
+ return spec
+ end
+ end
+end
diff --git a/ruby/lib/qpid/specs/amqp.0-10-qpid-errata.xml b/ruby/lib/qpid/specs/amqp.0-10-qpid-errata.xml
new file mode 100644
index 0000000000..365928ea4e
--- /dev/null
+++ b/ruby/lib/qpid/specs/amqp.0-10-qpid-errata.xml
@@ -0,0 +1,6654 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright Notice
+ ================
+ (c) Copyright Cisco Systems, Credit Suisse, Deutsche Borse Systems, Envoy Technologies, Inc.,
+ Goldman Sachs, IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A,
+ Novell, Rabbit Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc.
+ 2006, 2007. All rights reserved.
+
+ License
+ =======
+
+ Cisco Systems, Credit Suisse, Deutsche Borse Systems, Envoy Technologies, Inc.,Goldman Sachs,
+ IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A, Novell, Rabbit
+ Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc. (collectively,
+ the "Authors") each hereby grants to you a worldwide, perpetual, royalty-free, nontransferable,
+ nonexclusive license to (i) copy, display, distribute and implement the Advanced Messaging Queue
+ Protocol ("AMQP") Specification and (ii) the Licensed Claims that are held by the Authors, all for
+ the purpose of implementing the Advanced Messaging Queue Protocol Specification. Your license and
+ any rights under this Agreement will terminate immediately without notice from any Author if you
+ bring any claim, suit, demand, or action related to the Advanced Messaging Queue Protocol
+ Specification against any Author. Upon termination, you shall destroy all copies of the Advanced
+ Messaging Queue Protocol Specification in your possession or control.
+
+ As used hereunder, "Licensed Claims" means those claims of a patent or patent application,
+ throughout the world, excluding design patents and design registrations, owned or controlled, or
+ that can be sublicensed without fee and in compliance with the requirements of this Agreement, by
+ an Author or its affiliates now or at any future time and which would necessarily be infringed by
+ implementation of the Advanced Messaging Queue Protocol Specification. A claim is necessarily
+ infringed hereunder only when it is not possible to avoid infringing it because there is no
+ plausible non-infringing alternative for implementing the required portions of the Advanced
+ Messaging Queue Protocol Specification. Notwithstanding the foregoing, Licensed Claims shall not
+ include any claims other than as set forth above even if contained in the same patent as Licensed
+ Claims; or that read solely on any implementations of any portion of the Advanced Messaging Queue
+ Protocol Specification that are not required by the Advanced Messaging Queue Protocol
+ Specification, or that, if licensed, would require a payment of royalties by the licensor to
+ unaffiliated third parties. Moreover, Licensed Claims shall not include (i) any enabling
+ technologies that may be necessary to make or use any Licensed Product but are not themselves
+ expressly set forth in the Advanced Messaging Queue Protocol Specification (e.g., semiconductor
+ manufacturing technology, compiler technology, object oriented technology, networking technology,
+ operating system technology, and the like); or (ii) the implementation of other published
+ standards developed elsewhere and merely referred to in the body of the Advanced Messaging Queue
+ Protocol Specification, or (iii) any Licensed Product and any combinations thereof the purpose or
+ function of which is not required for compliance with the Advanced Messaging Queue Protocol
+ Specification. For purposes of this definition, the Advanced Messaging Queue Protocol
+ Specification shall be deemed to include both architectural and interconnection requirements
+ essential for interoperability and may also include supporting source code artifacts where such
+ architectural, interconnection requirements and source code artifacts are expressly identified as
+ being required or documentation to achieve compliance with the Advanced Messaging Queue Protocol
+ Specification.
+
+ As used hereunder, "Licensed Products" means only those specific portions of products (hardware,
+ software or combinations thereof) that implement and are compliant with all relevant portions of
+ the Advanced Messaging Queue Protocol Specification.
+
+ The following disclaimers, which you hereby also acknowledge as to any use you may make of the
+ Advanced Messaging Queue Protocol Specification:
+
+ THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
+ REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS
+ OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
+ IMPLEMENTATION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD
+ PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF OR RELATING TO ANY USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED
+ MESSAGING QUEUE PROTOCOL SPECIFICATION.
+
+ The name and trademarks of the Authors may NOT be used in any manner, including advertising or
+ publicity pertaining to the Advanced Messaging Queue Protocol Specification or its contents
+ without specific, written prior permission. Title to copyright in the Advanced Messaging Queue
+ Protocol Specification will at all times remain with the Authors.
+
+ No other rights are granted by implication, estoppel or otherwise.
+
+ Upon termination of your license or rights under this Agreement, you shall destroy all copies of
+ the Advanced Messaging Queue Protocol Specification in your possession or control.
+
+ Trademarks
+ ==========
+ "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the Octagon Symbol are
+ trademarks of JPMorgan Chase & Co.
+
+ IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
+
+ IONA, IONA Technologies, and the IONA logos are trademarks of IONA Technologies PLC and/or its
+ subsidiaries.
+
+ LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered trademarks of Red Hat,
+ Inc. in the US and other countries.
+
+ Java, all Java-based trademarks and OpenOffice.org are trademarks of Sun Microsystems, Inc. in the
+ United States, other countries, or both.
+
+ Other company, product, or service names may be trademarks or service marks of others.
+
+ Links to full AMQP specification:
+ =================================
+ http://www.envoytech.org/spec/amq/
+ http://www.iona.com/opensource/amqp/
+ http://www.redhat.com/solutions/specifications/amqp/
+ http://www.twiststandards.org/tiki-index.php?page=AMQ
+ http://www.imatix.com/amqp
+-->
+
+<!--
+ XML Notes
+ =========
+
+ We use entities to indicate repetition; attributes to indicate properties.
+
+ We use the "name" attribute as an identifier, usually within the context of the surrounding
+ entities.
+
+ We use hyphens (minus char '-') to seperate words in names.
+
+ We do not enforce any particular validation mechanism but we support all mechanisms. The protocol
+ definition conforms to a formal grammar that is published seperately in several technologies.
+
+-->
+
+<!DOCTYPE amqp SYSTEM "amqp.0-10.dtd">
+
+<amqp xmlns="http://www.amqp.org/schema/amqp.xsd"
+ major="0" minor="10" port="5672">
+
+ <!--
+ ====================== == type definitions == ======================
+ -->
+
+ <!--
+ 0x00 - 0x0f: Fixed width, 1 octet
+ -->
+
+ <type name="bin8" code="0x00" fixed-width="1" label="octet of unspecified encoding">
+ <doc>
+ The bin8 type consists of exactly one octet of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET
+ +----------+
+ | bin8 |
+ +----------+
+ </doc>
+
+ <doc type="bnf">
+ bin8 = OCTET
+ </doc>
+ </type>
+
+ <type name="int8" code="0x01" fixed-width="1" label="8-bit signed integral value (-128 - 127)">
+ <doc>
+ The int8 type is a signed integral value encoded using an 8-bit two's complement
+ representation.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET
+ +----------+
+ | int8 |
+ +----------+
+ </doc>
+
+ <doc type="bnf">
+ int8 = OCTET
+ </doc>
+ </type>
+
+ <type name="uint8" code="0x02" fixed-width="1" label="8-bit unsigned integral value (0 - 255)">
+ <doc>
+ The uint8 type is an 8-bit unsigned integral value.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET
+ +---------+
+ | uint8 |
+ +---------+
+ </doc>
+
+ <doc type="bnf">
+ uint8 = OCTET
+ </doc>
+ </type>
+
+ <type name="char" code="0x04" fixed-width="1" label="an iso-8859-15 character">
+ <doc>
+ The char type encodes a single character from the iso-8859-15 character set.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET
+ +----------+
+ | char |
+ +----------+
+ </doc>
+
+ <doc type="bnf">
+ char = OCTET
+ </doc>
+ </type>
+
+ <type name="boolean" code="0x08" fixed-width="1"
+ label="boolean value (zero represents false, nonzero represents true)">
+ <doc>
+ The boolean type is a single octet that encodes a true or false value. If the octet is zero,
+ then the boolean is false. Any other value represents true.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET
+ +---------+
+ | boolean |
+ +---------+
+ </doc>
+
+ <doc type="bnf">
+ boolean = OCTET
+ </doc>
+ </type>
+
+ <!--
+ 0x10 - 0x1f: Fixed width, 2 octets
+ -->
+
+ <type name="bin16" code="0x10" fixed-width="2" label="two octets of unspecified binary encoding">
+ <doc>
+ The bin16 type consists of two consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET
+ +-----------+-----------+
+ | octet-one | octet-two |
+ +-----------+-----------+
+ </doc>
+
+ <doc type="bnf">
+ bin16 = 2 OCTET
+ </doc>
+ </type>
+
+ <type name="int16" code="0x11" fixed-width="2" label="16-bit signed integral value">
+ <doc>
+ The int16 type is a signed integral value encoded using a 16-bit two's complement
+ representation in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET
+ +-----------+----------+
+ | high-byte | low-byte |
+ +-----------+----------+
+ </doc>
+
+ <doc type="bnf">
+ int16 = high-byte low-byte
+ high-byte = OCTET
+ low-byte = OCTET
+ </doc>
+ </type>
+
+ <type name="uint16" code="0x12" fixed-width="2" label="16-bit unsigned integer">
+ <doc>
+ The uint16 type is a 16-bit unsigned integral value encoded in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET
+ +-----------+----------+
+ | high-byte | low-byte |
+ +-----------+----------+
+ </doc>
+
+ <doc type="bnf">
+ uint16 = high-byte low-byte
+ high-byte = OCTET
+ low-byte = OCTET
+ </doc>
+ </type>
+
+ <!--
+ 0x20 - 0x2f: Fixed width, 4 octets
+ -->
+
+ <type name="bin32" code="0x20" fixed-width="4" label="four octets of unspecified binary encoding">
+ <doc>
+ The bin32 type consists of 4 consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-------------+------------+
+ | octet-one | octet-two | octet-three | octet-four |
+ +-----------+-----------+-------------+------------+
+ </doc>
+
+ <doc type="bnf">
+ bin32 = 4 OCTET
+ </doc>
+ </type>
+
+ <type name="int32" code="0x21" fixed-width="4" label="32-bit signed integral value">
+ <doc>
+ The int32 type is a signed integral value encoded using a 32-bit two's complement
+ representation in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+------------+----------+----------+
+ | byte-four | byte-three | byte-two | byte-one |
+ +-----------+------------+----------+----------+
+ MSB LSB
+ </doc>
+
+ <doc type="bnf">
+ int32 = byte-four byte-three byte-two byte-one
+ byte-four = OCTET ; most significant byte (MSB)
+ byte-three = OCTET
+ byte-two = OCTET
+ byte-one = OCTET ; least significant byte (LSB)
+ </doc>
+ </type>
+
+ <type name="uint32" code="0x22" fixed-width="4" label="32-bit unsigned integral value">
+ <doc>
+ The uint32 type is a 32-bit unsigned integral value encoded in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+------------+----------+----------+
+ | byte-four | byte-three | byte-two | byte-one |
+ +-----------+------------+----------+----------+
+ MSB LSB
+ </doc>
+
+ <doc type="bnf">
+ uint32 = byte-four byte-three byte-two byte-one
+ byte-four = OCTET ; most significant byte (MSB)
+ byte-three = OCTET
+ byte-two = OCTET
+ byte-one = OCTET ; least significant byte (LSB)
+ </doc>
+ </type>
+
+ <type name="float" code="0x23" fixed-width="4"
+ label="single precision IEEE 754 32-bit floating point">
+ <doc>
+ The float type encodes a single precision 32-bit floating point number. The format and
+ operations are defined by the IEEE 754 standard for 32-bit floating point numbers.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs
+ +-----------------------+
+ | float |
+ +-----------------------+
+ IEEE 754 32-bit float
+ </doc>
+
+ <doc type="bnf">
+ float = 4 OCTET ; IEEE 754 32-bit floating point number
+ </doc>
+ </type>
+
+ <type name="char-utf32" code="0x27" fixed-width="4"
+ label="single unicode character in UTF-32 encoding">
+ <doc>
+ The char-utf32 type consists of a single unicode character in the UTF-32 encoding.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs
+ +------------------+
+ | char-utf32 |
+ +------------------+
+ UTF-32 character
+ </doc>
+
+ <doc type="bnf">
+ char-utf32 = 4 OCTET ; single UTF-32 character
+ </doc>
+ </type>
+
+ <type name="sequence-no" fixed-width="4" label="serial number defined in RFC-1982">
+ <doc>
+ The sequence-no type encodes, in network byte order, a serial number as defined in RFC-1982.
+ The arithmetic, operators, and ranges for numbers of this type are defined by RFC-1982.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs
+ +------------------------+
+ | sequence-no |
+ +------------------------+
+ RFC-1982 serial number
+ </doc>
+
+ <doc type="bnf">
+ sequence-no = 4 OCTET ; RFC-1982 serial number
+ </doc>
+ </type>
+
+ <!--
+ 0x30 - 0x3f: Fixed width types - 8 octets
+ -->
+
+ <type name="bin64" code="0x30" fixed-width="8"
+ label="eight octets of unspecified binary encoding">
+ <doc>
+ The bin64 type consists of eight consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+-------------+-------------+
+ | octet-one | octet-two | ... | octet-seven | octet-eight |
+ +-----------+-----------+-----+-------------+-------------+
+ </doc>
+
+ <doc type="bnf">
+ bin64 = 8 OCTET
+ </doc>
+ </type>
+
+ <type name="int64" code="0x31" fixed-width="8" label="64-bit signed integral value">
+ <doc>
+ The int64 type is a signed integral value encoded using a 64-bit two's complement
+ representation in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +------------+------------+-----+----------+----------+
+ | byte-eight | byte-seven | ... | byte-two | byte-one |
+ +------------+------------+-----+----------+----------+
+ MSB LSB
+ </doc>
+
+ <doc type="bnf">
+ int64 = byte-eight byte-seven byte-six byte-five
+ byte-four byte-three byte-two byte-one
+ byte-eight = 1 OCTET ; most significant byte (MSB)
+ byte-seven = 1 OCTET
+ byte-six = 1 OCTET
+ byte-five = 1 OCTET
+ byte-four = 1 OCTET
+ byte-three = 1 OCTET
+ byte-two = 1 OCTET
+ byte-one = 1 OCTET ; least significant byte (LSB)
+ </doc>
+ </type>
+
+ <type name="uint64" code="0x32" fixed-width="8" label="64-bit unsigned integral value">
+ <doc>
+ The uint64 type is a 64-bit unsigned integral value encoded in network byte order.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +------------+------------+-----+----------+----------+
+ | byte-eight | byte-seven | ... | byte-two | byte-one |
+ +------------+------------+-----+----------+----------+
+ MSB LSB
+ </doc>
+
+ <doc type="bnf">
+ uint64 = byte-eight byte-seven byte-six byte-five
+ byte-four byte-three byte-two byte-one
+ byte-eight = 1 OCTET ; most significant byte (MSB)
+ byte-seven = 1 OCTET
+ byte-six = 1 OCTET
+ byte-five = 1 OCTET
+ byte-four = 1 OCTET
+ byte-three = 1 OCTET
+ byte-two = 1 OCTET
+ byte-one = 1 OCTET ; least significant byte (LSB)
+ </doc>
+ </type>
+
+ <type name="double" code="0x33" fixed-width="8" label="double precision IEEE 754 floating point">
+ <doc>
+ The double type encodes a double precision 64-bit floating point number. The format and
+ operations are defined by the IEEE 754 standard for 64-bit double precision floating point
+ numbers.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 8 OCTETs
+ +-----------------------+
+ | double |
+ +-----------------------+
+ IEEE 754 64-bit float
+ </doc>
+
+ <doc type="bnf">
+ double = 8 OCTET ; double precision IEEE 754 floating point number
+ </doc>
+ </type>
+
+ <type name="datetime" code="0x38" fixed-width="8" label="datetime in 64 bit POSIX time_t format">
+ <doc>
+ The datetime type encodes a date and time using the 64 bit POSIX time_t format.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 8 OCTETs
+ +---------------------+
+ | datetime |
+ +---------------------+
+ posix time_t format
+ </doc>
+
+ <doc type="bnf">
+ datetime = 8 OCTET ; 64 bit posix time_t format
+ </doc>
+ </type>
+
+ <!--
+ 0x40 - 0x4f: Fixed width types - 16 octets
+ -->
+
+ <type name="bin128" code="0x40" fixed-width="16"
+ label="sixteen octets of unspecified binary encoding">
+ <doc>
+ The bin128 type consists of 16 consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+---------------+---------------+
+ | octet-one | octet-two | ... | octet-fifteen | octet-sixteen |
+ +-----------+-----------+-----+---------------+---------------+
+ </doc>
+
+ <doc type="bnf">
+ bin128 = 16 OCTET
+ </doc>
+ </type>
+
+ <type name="uuid" code="0x48" fixed-width="16" label="UUID (RFC-4122 section 4.1.2) - 16 octets">
+ <doc>
+ The uuid type encodes a universally unique id as defined by RFC-4122. The format and
+ operations for this type can be found in section 4.1.2 of RFC-4122.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 16 OCTETs
+ +---------------+
+ | uuid |
+ +---------------+
+ RFC-4122 UUID
+ </doc>
+
+ <doc type="bnf">
+ uuid = 16 OCTET ; RFC-4122 section 4.1.2
+ </doc>
+ </type>
+
+ <!--
+ 0x50 - 0x5f: Fixed width types - 32 octets
+ -->
+
+ <type name="bin256" code="0x50" fixed-width="32"
+ label="thirty two octets of unspecified binary encoding">
+ <doc>
+ The bin256 type consists of thirty two consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+------------------+------------------+
+ | octet-one | octet-two | ... | octet-thirty-one | octet-thirty-two |
+ +-----------+-----------+-----+------------------+------------------+
+ </doc>
+
+ <doc type="bnf">
+ bin256 = 32 OCTET
+ </doc>
+ </type>
+
+ <!--
+ 0x60 - 0x6f: Fixed width types - 64 octets
+ -->
+
+ <type name="bin512" code="0x60" fixed-width="64"
+ label="sixty four octets of unspecified binary encoding">
+ <doc>
+ The bin512 type consists of sixty four consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+-------------------+------------------+
+ | octet-one | octet-two | ... | octet-sixty-three | octet-sixty-four |
+ +-----------+-----------+-----+-------------------+------------------+
+ </doc>
+
+ <doc type="bnf">
+ bin512 = 64 OCTET
+ </doc>
+ </type>
+
+ <!--
+ 0x70 - 0x7f: Fixed width types - 128 octets
+ -->
+
+ <type name="bin1024" code="0x70" fixed-width="128"
+ label="one hundred and twenty eight octets of unspecified binary encoding">
+ <doc>
+ The bin1024 type consists of one hundred and twenty eight octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+------------------------+------------------------+
+ | octet-one | octet-two | ... | octet-one-twenty-seven | octet-one-twenty-eight |
+ +-----------+-----------+-----+------------------------+------------------------+
+ </doc>
+
+ <doc type="bnf">
+ bin1024 = 128 OCTET
+ </doc>
+ </type>
+
+ <!--
+ 0x80 - 0x8f: Variable length - one byte length field (up to 255 octets)
+ -->
+
+ <type name="vbin8" code="0x80" variable-width="1" label="up to 255 octets of opaque binary data">
+ <doc>
+ The vbin8 type encodes up to 255 octets of opaque binary data. The number of octets is first
+ encoded as an 8-bit unsigned integral value. This is followed by the actual data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET size OCTETs
+ +---------+-------------+
+ | size | octets |
+ +---------+-------------+
+ uint8
+ </doc>
+
+ <doc type="bnf">
+ vbin8 = size octets
+ size = uint8
+ octets = 0*255 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str8-latin" code="0x84" variable-width="1" label="up to 255 iso-8859-15 characters">
+ <doc>
+ The str8-latin type encodes up to 255 octets of iso-8859-15 characters. The number of octets
+ is first encoded as an 8-bit unsigned integral value. This is followed by the actual
+ characters.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET size OCTETs
+ +---------+------------------------+
+ | size | characters |
+ +---------+------------------------+
+ uint16 iso-8859-15 characters
+ </doc>
+
+ <doc type="bnf">
+ str8-latin = size characters
+ size = uint8
+ characters = 0*255 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str8" code="0x85" variable-width="1" label="up to 255 octets worth of UTF-8 unicode">
+ <doc>
+ The str8 type encodes up to 255 octets worth of UTF-8 unicode. The number of octets of unicode
+ is first encoded as an 8-bit unsigned integral value. This is followed by the actual UTF-8
+ unicode. Note that the encoded size refers to the number of octets of unicode, not necessarily
+ the number of characters since the UTF-8 unicode may include multi-byte character sequences.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET size OCTETs
+ +---------+--------------+
+ | size | utf8-unicode |
+ +---------+--------------+
+ uint8
+ </doc>
+
+ <doc type="bnf">
+ str8 = size utf8-unicode
+ size = uint8
+ utf8-unicode = 0*255 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str8-utf16" code="0x86" variable-width="1"
+ label="up to 255 octets worth of UTF-16 unicode">
+ <doc>
+ The str8-utf16 type encodes up to 255 octets worth of UTF-16 unicode. The number of octets of
+ unicode is first encoded as an 8-bit unsigned integral value. This is followed by the actual
+ UTF-16 unicode. Note that the encoded size refers to the number of octets of unicode, not the
+ number of characters since the UTF-16 unicode will include at least two octets per unicode
+ character.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET size OCTETs
+ +---------+---------------+
+ | size | utf16-unicode |
+ +---------+---------------+
+ uint8
+ </doc>
+
+ <doc type="bnf">
+ str8-utf16 = size utf16-unicode
+ size = uint8
+ utf16-unicode = 0*255 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <!--
+ 0x90 - 0x9f: Variable length types - two byte length field (up to 65535 octets)
+ -->
+
+ <type name="vbin16" code="0x90" variable-width="2"
+ label="up to 65535 octets of opaque binary data">
+ <doc>
+ The vbin16 type encodes up to 65535 octets of opaque binary data. The number of octets is
+ first encoded as a 16-bit unsigned integral value in network byte order. This is followed by
+ the actual data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 2 OCTETs size OCTETs
+ +----------+-------------+
+ | size | octets |
+ +----------+-------------+
+ uint16
+ </doc>
+
+ <doc type="bnf">
+ vbin16 = size octets
+ size = uint16
+ octets = 0*65535 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str16-latin" code="0x94" variable-width="2"
+ label="up to 65535 iso-8859-15 characters">
+ <doc>
+ The str16-latin type encodes up to 65535 octets of is-8859-15 characters. The number of octets
+ is first encoded as a 16-bit unsigned integral value in network byte order. This is followed
+ by the actual characters.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 2 OCTETs size OCTETs
+ +----------+------------------------+
+ | size | characters |
+ +----------+------------------------+
+ uint16 iso-8859-15 characters
+ </doc>
+
+ <doc type="bnf">
+ str16-latin = size characters
+ size = uint16
+ characters = 0*65535 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str16" code="0x95" variable-width="2"
+ label="up to 65535 octets worth of UTF-8 unicode">
+ <doc>
+ The str16 type encodes up to 65535 octets worth of UTF-8 unicode. The number of octets is
+ first encoded as a 16-bit unsigned integral value in network byte order. This is followed by
+ the actual UTF-8 unicode. Note that the encoded size refers to the number of octets of
+ unicode, not necessarily the number of unicode characters since the UTF-8 unicode may include
+ multi-byte character sequences.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 2 OCTETs size OCTETs
+ +----------+--------------+
+ | size | utf8-unicode |
+ +----------+--------------+
+ uint16
+ </doc>
+
+ <doc type="bnf">
+ str16 = size utf8-unicode
+ size = uint16
+ utf8-unicode = 0*65535 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="str16-utf16" code="0x96" variable-width="2"
+ label="up to 65535 octets worth of UTF-16 unicode">
+ <doc>
+ The str16-utf16 type encodes up to 65535 octets worth of UTF-16 unicode. The number of octets
+ is first encoded as a 16-bit unsigned integral value in network byte order. This is followed
+ by the actual UTF-16 unicode. Note that the encoded size refers to the number of octets of
+ unicode, not the number of unicode characters since the UTF-16 unicode will include at least
+ two octets per unicode character.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 2 OCTETs size OCTETs
+ +----------+---------------+
+ | size | utf16-unicode |
+ +----------+---------------+
+ uint16
+ </doc>
+
+ <doc type="bnf">
+ str16-utf16 = size utf16-unicode
+ size = uint16
+ utf16-unicode = 0*65535 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="byte-ranges" variable-width="2" label="byte ranges within a 64-bit payload">
+ <doc>
+ The byte-ranges type encodes up to 65535 octets worth of non-overlapping, non-touching,
+ ascending byte ranges within a 64-bit sequence of bytes. Each range is represented as an
+ inclusive lower and upper bound that identifies all the byte offsets included within a given
+ range.
+ </doc>
+
+ <doc>
+ The number of octets of data is first encoded as a 16-bit unsigned integral value in network
+ byte order. This is then followed by the encoded representation of the ranges included in the
+ set. These MUST be encoded in ascending order, and any two ranges included in a given set MUST
+ NOT include overlapping or touching byte offsets.
+ </doc>
+
+ <doc>
+ Each range is encoded as a pair of 64-bit unsigned integral values in network byte order
+ respectively representing the lower and upper bounds for that range. Note that because each
+ range is exactly 16 octets, the size in octets of the encoded ranges will always be 16 times
+ the number of ranges in the set.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ +----= size OCTETs =----+
+ | |
+ 2 OCTETs | 16 OCTETs |
+ +----------+-----+-----------+-----+
+ | size | .../| range |\... |
+ +----------+---/ +-----------+ \---+
+ uint16 / / \ \
+ / / \ \
+ / 8 OCTETs 8 OCTETs \
+ +-----------+-----------+
+ | lower | upper |
+ +-----------+-----------+
+ uint64 uint64
+ </doc>
+
+ <doc type="bnf">
+ byte-ranges = size *range
+ size = uint16
+ range = lower upper
+ lower = uint64
+ upper = uint64
+ </doc>
+ </type>
+
+ <type name="sequence-set" variable-width="2" label="ranged set representation">
+ <doc>
+ The sequence-set type is a set of pairs of RFC-1982 numbers representing a discontinuous range
+ within an RFC-1982 sequence. Each pair represents a closed interval within the list.
+ </doc>
+
+ <doc>
+ Sequence-sets can be represented as lists of pairs of positive 32-bit numbers, each pair
+ representing a closed interval that does not overlap or touch with any other interval in the
+ list. For example, a set containing words 0, 1, 2, 5, 6, and 15 can be represented:
+ </doc>
+
+ <doc type="picture">
+ [(0, 2), (5, 6), (15, 15)]
+ </doc>
+
+ <doc>
+ 1) The list-of-pairs representation is sorted ascending (as defined by RFC 1982
+ (http://www.ietf.org/rfc/rfc1982.txt) ) by the first elements of each pair.
+ </doc>
+
+ <doc>
+ 2) The list-of-pairs is flattened into a list-of-words.
+ </doc>
+
+ <doc>
+ 3) Each word in the list is packed into ascending locations in memory with network byte
+ ordering.
+ </doc>
+
+ <doc>
+ 4) The size in bytes, represented as a 16-bit network-byte-order unsigned value, is prepended.
+ </doc>
+
+ <doc>
+ For instance, the example from above would be encoded:
+ </doc>
+
+ <doc type="picture">
+ [(0, 2), (5, 6), (15, 15)] -- already sorted.
+ [0, 2, 5, 6, 15, 15] -- flattened.
+ 000000000000000200000005000000060000000F0000000F -- bytes in hex
+ 0018000000000000000200000005000000060000000F0000000F -- bytes in hex,
+ length (24) prepended
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ +----= size OCTETs =----+
+ | |
+ 2 OCTETs | 8 OCTETs |
+ +----------+-----+-----------+-----+
+ | size | .../| range |\... |
+ +----------+---/ +-----------+ \---+
+ uint16 / / \ \
+ / / \ \
+ / / \ \
+ / / \ \
+ / 4 OCTETs 4 OCTETs \
+ +-------------+-------------+
+ | lower | upper |
+ +-------------+-------------+
+ sequence-no sequence-no
+ </doc>
+
+ <doc type="bnf">
+ sequence-set = size *range
+ size = uint16 ; length of variable portion in bytes
+
+ range = lower upper ; inclusive
+ lower = sequence-no
+ upper = sequence-no
+ </doc>
+ </type>
+
+ <!--
+ 0xa0 - 0xaf: Variable length types - four byte length field (up to 4294967295 octets)
+ -->
+
+ <type name="vbin32" code="0xa0" variable-width="4"
+ label="up to 4294967295 octets of opaque binary data">
+ <doc>
+ The vbin32 type encodes up to 4294967295 octets of opaque binary data. The number of octets is
+ first encoded as a 32-bit unsigned integral value in network byte order. This is followed by
+ the actual data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs size OCTETs
+ +----------+-------------+
+ | size | octets |
+ +----------+-------------+
+ uint32
+ </doc>
+
+ <doc type="bnf">
+ vbin32 = size octets
+ size = uint32
+ octets = 0*4294967295 OCTET ; size OCTETs
+ </doc>
+ </type>
+
+ <type name="map" code="0xa8" variable-width="4" label="a mapping of keys to typed values">
+ <doc>
+ A map is a set of distinct keys where each key has an associated (type,value) pair. The triple
+ of the key, type, and value, form an entry within a map. Each entry within a given map MUST
+ have a distinct key. A map is encoded as a size in octets, a count of the number of entries,
+ followed by the encoded entries themselves.
+ </doc>
+
+ <doc>
+ An encoded map may contain up to (4294967295 - 4) octets worth of encoded entries. The size is
+ encoded as a 32-bit unsigned integral value in network byte order equal to the number of
+ octets worth of encoded entries plus 4. (The extra 4 octets is added for the entry count.) The
+ size is then followed by the number of entries encoded as a 32-bit unsigned integral value in
+ network byte order. Finally the entries are encoded sequentially.
+ </doc>
+
+ <doc>
+ An entry is encoded as the key, followed by the type, and then the value. The key is always a
+ string encoded as a str8. The type is a single octet that may contain any valid AMQP type
+ code. The value is encoded according to the rules defined by the type code for that entry.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ +------------= size OCTETs =-----------+
+ | |
+ 4 OCTETs | 4 OCTETs |
+ +----------+----------+-----+---------------+-----+
+ | size | count | .../| entry |\... |
+ +----------+----------+---/ +---------------+ \---+
+ uint32 uint32 / / \ \
+ / / \ \
+ / / \ \
+ / / \ \
+ / / \ \
+ / k OCTETs 1 OCTET n OCTETs \
+ +-----------+---------+-----------+
+ | key | type | value |
+ +-----------+---------+-----------+
+ str8 *type*
+ </doc>
+
+ <doc type="bnf">
+ map = size count *entry
+
+ size = uint32 ; size of count and entries in octets
+ count = uint32 ; number of entries in the map
+
+ entry = key type value
+ key = str8
+ type = OCTET ; type code of the value
+ value = *OCTET ; the encoded value
+ </doc>
+ </type>
+
+ <type name="list" code="0xa9" variable-width="4" label="a series of consecutive type-value pairs">
+ <doc>
+ A list is an ordered sequence of (type, value) pairs. The (type, value) pair forms an item
+ within the list. The list may contain items of many distinct types. A list is encoded as a
+ size in octets, followed by a count of the number of items, followed by the items themselves
+ encoded in their defined order.
+ </doc>
+
+ <doc>
+ An encoded list may contain up to (4294967295 - 4) octets worth of encoded items. The size is
+ encoded as a 32-bit unsigned integral value in network byte order equal to the number of
+ octets worth of encoded items plus 4. (The extra 4 octets is added for the item count.) The
+ size is then followed by the number of items encoded as a 32-bit unsigned integral value in
+ network byte order. Finally the items are encoded sequentially in their defined order.
+ </doc>
+
+ <doc>
+ An item is encoded as the type followed by the value. The type is a single octet that may
+ contain any valid AMQP type code. The value is encoded according to the rules defined by the
+ type code for that item.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ +---------= size OCTETs =---------+
+ | |
+ 4 OCTETs | 4 OCTETs |
+ +----------+----------+-----+----------+-----+
+ | size | count | .../| item |\... |
+ +----------+----------+---/ +----------+ \---+
+ uint32 uint32 / / \ \
+ / / \ \
+ / 1 OCTET n OCTETs \
+ +----------+-----------+
+ | type | value |
+ +----------+-----------+
+ *type*
+ </doc>
+
+ <doc type="bnf">
+ list = size count *item
+
+ size = uint32 ; size of count and items in octets
+ count = uint32 ; number of items in the list
+
+ item = type value
+ type = OCTET ; type code of the value
+ value = *OCTET ; the encoded value
+ </doc>
+ </type>
+
+ <type name="array" code="0xaa" variable-width="4"
+ label="a defined length collection of values of a single type">
+ <doc>
+ An array is an ordered sequence of values of the same type. The array is encoded in as a size
+ in octets, followed by a type code, then a count of the number values in the array, and
+ finally the values encoded in their defined order.
+ </doc>
+
+ <doc>
+ An encoded array may contain up to (4294967295 - 5) octets worth of encoded values. The size
+ is encoded as a 32-bit unsigned integral value in network byte order equal to the number of
+ octets worth of encoded values plus 5. (The extra 5 octets consist of 4 octets for the count
+ of the number of values, and one octet to hold the type code for the items in the array.) The
+ size is then followed by a single octet that may contain any valid AMQP type code. The type
+ code is then followed by the number of values encoded as a 32-bit unsigned integral value in
+ network byte order. Finally the values are encoded sequentially in their defined order
+ according to the rules defined by the type code for the array.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs 1 OCTET 4 OCTETs (size - 5) OCTETs
+ +----------+---------+----------+-------------------------+
+ | size | type | count | values |
+ +----------+---------+----------+-------------------------+
+ uint32 uint32 *count* encoded *types*
+ </doc>
+
+ <doc type="bnf">
+ array = size type count values
+
+ size = uint32 ; size of type, count, and values in octets
+ type = OCTET ; the type of the encoded values
+ count = uint32 ; number of items in the array
+
+ values = 0*4294967290 OCTET ; (size - 5) OCTETs
+ </doc>
+ </type>
+
+ <type name="struct32" code="0xab" variable-width="4" label="a coded struct with a 32-bit size">
+ <doc>
+ The struct32 type describes any coded struct with a 32-bit (4 octet) size. The type is
+ restricted to be only coded structs with a 32-bit size, consequently the first six octets of
+ any encoded value for this type MUST always contain the size, class-code, and struct-code in
+ that order.
+ </doc>
+
+ <doc>
+ The size is encoded as a 32-bit unsigned integral value in network byte order that is equal to
+ the size of the encoded field-data, packing-flags, class-code, and struct-code. The class-code
+ is a single octet that may be set to any valid class code. The struct-code is a single octet
+ that may be set to any valid struct code within the given class-code.
+ </doc>
+
+ <doc>
+ The first six octets are then followed by the packing flags and encoded field data. The
+ presence and quantity of packing-flags, as well as the specific fields are determined by the
+ struct definition identified with the encoded class-code and struct-code.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 4 OCTETs 1 OCTET 1 OCTET pack-width OCTETs n OCTETs
+ +----------+------------+-------------+-------------------+------------+
+ | size | class-code | struct-code | packing-flags | field-data |
+ +----------+------------+-------------+-------------------+------------+
+ uint32
+
+ n = (size - 2 - pack-width)
+ </doc>
+
+ <doc type="bnf">
+ struct32 = size class-code struct-code packing-flags field-data
+
+ size = uint32
+
+ class-code = OCTET ; zero for top-level structs
+ struct-code = OCTET ; together with class-code identifies the struct
+ ; definition which determines the pack-width and
+ ; fields
+
+ packing-flags = 0*4 OCTET ; pack-width OCTETs
+
+ field-data = *OCTET ; (size - 2 - pack-width) OCTETs
+ </doc>
+ </type>
+
+ <!--
+ 0xb0 - 0xbf: Reserved
+ -->
+
+ <!--
+ 0xc0 - 0xcf:Fixed width types - 5 octets
+ -->
+
+ <type name="bin40" code="0xc0" fixed-width="5" label="five octets of unspecified binary encoding">
+ <doc>
+ The bin40 type consists of five consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-------------+------------+------------+
+ | octet-one | octet-two | octet-three | octet-four | octet-five |
+ +-----------+-----------+-------------+------------+------------+
+ </doc>
+
+ <doc type="bnf">
+ bin40 = 5 OCTET
+ </doc>
+ </type>
+
+ <type name="dec32" code="0xc8" fixed-width="5"
+ label="32-bit decimal value (e.g. for use in financial values)">
+ <doc>
+ The dec32 type is decimal value with a variable number of digits following the decimal point.
+ It is encoded as an 8-bit unsigned integral value representing the number of decimal places.
+ This is followed by the signed integral value encoded using a 32-bit two's complement
+ representation in network byte order.
+ </doc>
+
+ <doc>
+ The former value is referred to as the exponent of the divisor. The latter value is the
+ mantissa. The decimal value is given by: mantissa / 10^exponent.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 4 OCTETs
+ +----------+----------+
+ | exponent | mantissa |
+ +----------+----------+
+ uint8 int32
+ </doc>
+
+ <doc type="bnf">
+ dec32 = exponent mantissa
+ exponent = uint8
+ mantissa = int32
+ </doc>
+ </type>
+
+ <!--
+ 0xd0 - 0xdf: Fixed width types - 9 octets
+ -->
+
+ <type name="bin72" code="0xd0" fixed-width="9"
+ label="nine octets of unspecified binary encoding">
+ <doc>
+ The bin72 type consists of nine consecutive octets of opaque binary data.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+ +-----------+-----------+-----+-------------+------------+
+ | octet-one | octet-two | ... | octet-eight | octet-nine |
+ +-----------+-----------+-----+-------------+------------+
+ </doc>
+
+ <doc type="bnf">
+ bin64 = 9 OCTET
+ </doc>
+ </type>
+
+ <type name="dec64" code="0xd8" fixed-width="9"
+ label="64-bit decimal value (e.g. for use in financial values)">
+ <doc>
+ The dec64 type is decimal value with a variable number of digits following the decimal point.
+ It is encoded as an 8-bit unsigned integral value representing the number of decimal places.
+ This is followed by the signed integral value encoded using a 64-bit two's complement
+ representation in network byte order.
+ </doc>
+
+ <doc>
+ The former value is referred to as the exponent of the divisor. The latter value is the
+ mantissa. The decimal value is given by: mantissa / 10^exponent.
+ </doc>
+
+ <doc type="picture" title="Wire Format">
+ 1 OCTET 8 OCTETs
+ +----------+----------+
+ | exponent | mantissa |
+ +----------+----------+
+ uint8 int64
+ </doc>
+
+ <doc type="bnf">
+ dec64 = exponent mantissa
+ exponent = uint8
+ mantissa = int64
+ </doc>
+ </type>
+
+ <!--
+ 0xe0 - 0xef: Reserved
+ -->
+
+ <!--
+ 0xf0 - 0xff: Zero-length types
+ -->
+
+ <type name="void" code="0xf0" fixed-width="0" label="the void type">
+ <doc>
+ The void type is used within tagged data structures such as maps and lists to indicate an
+ empty value. The void type has no value and is encoded as an empty sequence of octets.
+ </doc>
+ </type>
+
+ <type name="bit" code="0xf1" fixed-width="0" label="presence indicator">
+ <doc>
+ The bit type is used to indicate that a packing flag within a packed struct is being used to
+ represent a boolean value based on the presence of an empty value. The bit type has no value
+ and is encoded as an empty sequence of octets.
+ </doc>
+ </type>
+
+ <!--
+ ======================================================
+ == CONSTANTS
+ ======================================================
+ -->
+
+ <!-- Protocol constants -->
+
+ <constant name="MIN-MAX-FRAME-SIZE" value="4096" label="The minimum size (in bytes) which can be
+ agreed upon as the maximum frame size.">
+ <doc>
+ During the initial connection negotiation, the two peers must agree upon a maximum frame size.
+ This constant defines the minimum value to which the maximum frame size can be set. By
+ defining this value, the peers can guarantee that they can send frames of up to this size
+ until they have agreed a definitive maximum frame size for that connection.
+ </doc>
+ </constant>
+
+ <!--
+ ======================================================
+ == DOMAIN TYPES
+ ======================================================
+ -->
+
+ <!-- Segment types -->
+
+ <domain name="segment-type" type="uint8" label="valid values for the frame type indicator.">
+ <doc>
+ Segments are defined in <xref ref="specification.transport.assemblies_segments_and_frames"/>.
+ The segment domain defines the valid values that may be used for the segment indicator within
+ the frame header.
+ </doc>
+
+ <enum>
+ <choice name="control" value="0">
+ <doc>
+ The frame type indicator for Control segments (see <xref
+ ref="specification.formal_notation.controls"/>).
+ </doc>
+ </choice>
+ <choice name="command" value="1">
+ <doc>
+ The frame type indicator for Command segments (see <xref
+ ref="specification.formal_notation.commands"/>).
+ </doc>
+ </choice>
+ <choice name="header" value="2" >
+ <doc>
+ The frame type indicator for Header segments (see <xref
+ ref="specification.formal_notation.segments.header"/>).
+ </doc>
+ </choice>
+ <choice name="body" value="3" >
+ <doc>
+ The frame type indicator for Body segments (see <xref
+ ref="specification.formal_notation.segments.body"/>).
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <!-- Tracks -->
+
+ <domain name="track" type="uint8" label="Valid values for transport level tracks">
+ <doc> Tracks are defined in <xref ref="specification.transport.channels_and_tracks"/>. The
+ track domain defines the valid values that may used for the track indicator within the frame
+ header</doc>
+ <enum>
+ <choice name="control" value="0">
+ <doc>
+ The track used for all controls. All controls defined in this specification MUST be sent
+ on track 0.
+ </doc>
+ </choice>
+ <choice name="command" value="1">
+ <doc>
+ The track used for all commands. All commands defined in this specification MUST be sent
+ on track 1.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+
+ <domain name="str16-array" type="array" label="An array of values of type str16.">
+ <doc>
+ An array of values of type str16.
+ </doc>
+ </domain>
+
+
+
+ <!-- == Class: connection ==================================================================== -->
+
+ <class name="connection" code="0x1" label="work with connections">
+ <doc>
+ The connection class provides controls for a client to establish a network connection to a
+ server, and for both peers to operate the connection thereafter.
+ </doc>
+
+ <doc type="grammar">
+ connection = open-connection
+ *use-connection
+ close-connection
+ open-connection = C:protocol-header
+ S:START C:START-OK
+ *challenge
+ S:TUNE C:TUNE-OK
+ C:OPEN S:OPEN-OK | S:REDIRECT
+ challenge = S:SECURE C:SECURE-OK
+ use-connection = *channel
+ close-connection = C:CLOSE S:CLOSE-OK
+ / S:CLOSE C:CLOSE-OK
+ </doc>
+
+ <role name="server" implement="MUST" />
+ <role name="client" implement="MUST" />
+
+ <domain name="close-code" type="uint16" label="code used in the connection.close control to
+ indicate reason for closure">
+ <enum>
+ <choice name="normal" value="200">
+ <doc>
+ The connection closed normally.
+ </doc>
+ </choice>
+
+ <choice name="connection-forced" value="320">
+ <doc>
+ An operator intervened to close the connection for some reason. The client may retry at
+ some later date.
+ </doc>
+ </choice>
+
+ <choice name="invalid-path" value="402">
+ <doc>
+ The client tried to work with an unknown virtual host.
+ </doc>
+ </choice>
+
+ <choice name="framing-error" value="501">
+ <doc>
+ A valid frame header cannot be formed from the incoming byte stream.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="amqp-host-url" type="str16" label="URL for identifying an AMQP Server">
+ <doc>
+ The amqp-url domain defines a format for identifying an AMQP Server. It is used to provide
+ alternate hosts in the case where a client has to reconnect because of failure, or because
+ the server requests the client to do so upon initial connection.
+ </doc>
+ <doc type="bnf"><![CDATA[
+ amqp_url = "amqp:" prot_addr_list
+ prot_addr_list = [prot_addr ","]* prot_addr
+ prot_addr = tcp_prot_addr | tls_prot_addr
+
+ tcp_prot_addr = tcp_id tcp_addr
+ tcp_id = "tcp:" | ""
+ tcp_addr = [host [":" port] ]
+ host = <as per http://www.ietf.org/rfc/rfc3986.txt>
+ port = number]]>
+ </doc>
+ </domain>
+
+ <domain name="amqp-host-array" type="array" label="An array of values of type amqp-host-url">
+ <doc>
+ Used to provide a list of alternate hosts.
+ </doc>
+ </domain>
+
+ <!-- - Control: connection.start - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="start" code="0x1" label="start connection negotiation">
+ <doc>
+ This control starts the connection negotiation process by telling the client the supported
+ security mechanisms and locales from which the client can choose.
+ </doc>
+
+ <rule name="protocol-name">
+ <doc>
+ If the server cannot support the protocol specified in the protocol header, it MUST close
+ the socket connection without sending any response control.
+ </doc>
+ <doc type="scenario">
+ The client sends a protocol header containing an invalid protocol name. The server must
+ respond by closing the connection.
+ </doc>
+ </rule>
+
+ <rule name="client-support">
+ <doc>
+ If the client cannot handle the protocol version suggested by the server it MUST close the
+ socket connection.
+ </doc>
+ <doc type="scenario">
+ The server sends a protocol version that is lower than any valid implementation, e.g. 0.1.
+ The client must respond by closing the connection.
+ </doc>
+ </rule>
+
+ <implement role="client" handle="MUST" />
+
+ <response name="start-ok" />
+
+ <field name="server-properties" type="map" label="server properties">
+ <rule name="required-fields">
+ <doc>
+ The properties SHOULD contain at least these fields: "host", specifying the server host
+ name or address, "product", giving the name of the server product, "version", giving the
+ name of the server version, "platform", giving the name of the operating system,
+ "copyright", if appropriate, and "information", giving other general information.
+ </doc>
+ <doc type="scenario">
+ Client connects to server and inspects the server properties. It checks for the presence
+ of the required fields.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="mechanisms" type="str16-array" label="available security mechanisms"
+ required="true">
+ <doc>
+ A list of the security mechanisms that the server supports.
+ </doc>
+ </field>
+
+ <field name="locales" type="str16-array" label="available message locales" required="true">
+ <doc>
+ A list of the message locales that the server supports. The locale defines the language in
+ which the server will send reply texts.
+ </doc>
+
+ <rule name="required-support">
+ <doc>
+ The server MUST support at least the en_US locale.
+ </doc>
+ <doc type="scenario">
+ Client connects to server and inspects the locales field. It checks for the presence of
+ the required locale(s).
+ </doc>
+ </rule>
+ </field>
+ </control>
+
+ <!-- - Control: connection.start-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="start-ok" code="0x2" label="select security mechanism and locale">
+ <doc>
+ This control selects a SASL security mechanism.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="client-properties" type="map" label="client properties">
+ <rule name="required-fields">
+ <!-- This rule is not testable from the client side -->
+ <doc>
+ The properties SHOULD contain at least these fields: "product", giving the name of the
+ client product, "version", giving the name of the client version, "platform", giving the
+ name of the operating system, "copyright", if appropriate, and "information", giving
+ other general information.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="mechanism" type="str8" label="selected security mechanism" required="true">
+ <doc>
+ A single security mechanisms selected by the client, which must be one of those specified
+ by the server.
+ </doc>
+
+ <rule name="security">
+ <doc>
+ The client SHOULD authenticate using the highest-level security profile it can handle
+ from the list provided by the server.
+ </doc>
+ </rule>
+
+ <rule name="validity">
+ <doc>
+ If the mechanism field does not contain one of the security mechanisms proposed by the
+ server in the Start control, the server MUST close the connection without sending any
+ further data.
+ </doc>
+ <doc type="scenario">
+ Client connects to server and sends an invalid security mechanism. The server must
+ respond by closing the connection (a socket close, with no connection close
+ negotiation).
+ </doc>
+ </rule>
+ </field>
+
+ <field name="response" type="vbin32" label="security response data" required="true">
+ <doc>
+ A block of opaque data passed to the security mechanism. The contents of this data are
+ defined by the SASL security mechanism.
+ </doc>
+ </field>
+
+ <field name="locale" type="str8" label="selected message locale" required="true">
+ <doc>
+ A single message locale selected by the client, which must be one of those specified by
+ the server.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.secure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="secure" code="0x3" label="security mechanism challenge">
+ <doc>
+ The SASL protocol works by exchanging challenges and responses until both peers have
+ received sufficient information to authenticate each other. This control challenges the
+ client to provide more information.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <response name="secure-ok" />
+
+ <field name="challenge" type="vbin32" label="security challenge data" required="true">
+ <doc>
+ Challenge information, a block of opaque binary data passed to the security mechanism.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.secure-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="secure-ok" code="0x4" label="security mechanism response">
+ <doc>
+ This control attempts to authenticate, passing a block of SASL data for the security
+ mechanism at the server side.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="response" type="vbin32" label="security response data" required="true">
+ <doc>
+ A block of opaque data passed to the security mechanism. The contents of this data are
+ defined by the SASL security mechanism.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.tune - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="tune" code="0x5" label="propose connection tuning parameters">
+ <doc>
+ This control proposes a set of connection configuration values to the client. The client can
+ accept and/or adjust these.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <response name="tune-ok" />
+
+ <field name="channel-max" type="uint16" label="proposed maximum channels">
+ <doc>
+ The maximum total number of channels that the server allows per connection. If this is not
+ set it means that the server does not impose a fixed limit, but the number of allowed
+ channels may be limited by available server resources.
+ </doc>
+ </field>
+
+ <field name="max-frame-size" type="uint16" label="proposed maximum frame size">
+ <doc>
+ The largest frame size that the server proposes for the connection. The client can
+ negotiate a lower value. If this is not set means that the server does not impose any
+ specific limit but may reject very large frames if it cannot allocate resources for them.
+ </doc>
+
+ <rule name="minimum">
+ <doc>
+ Until the max-frame-size has been negotiated, both peers MUST accept frames of up to
+ MIN-MAX-FRAME-SIZE octets large, and the minimum negotiated value for max-frame-size is
+ also MIN-MAX-FRAME-SIZE.
+ </doc>
+ <doc type="scenario">
+ Client connects to server and sends a large properties field, creating a frame of
+ MIN-MAX-FRAME-SIZE octets. The server must accept this frame.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="heartbeat-min" type="uint16" label="the minimum supported heartbeat delay">
+ <doc>
+ The minimum delay, in seconds, of the connection heartbeat supported by the server. If
+ this is not set it means the server does not support sending heartbeats.
+ </doc>
+ </field>
+
+ <field name="heartbeat-max" type="uint16" label="the maximum supported heartbeat delay">
+ <doc>
+ The maximum delay, in seconds, of the connection heartbeat supported by the server. If
+ this is not set it means the server has no maximum.
+ </doc>
+
+ <rule name="permitted-range">
+ <doc>
+ The heartbeat-max value must be greater than or equal to the value supplied in the
+ heartbeat-min field.
+ </doc>
+ </rule>
+
+ <rule name="no-heartbeat-min">
+ <doc>
+ If no heartbeat-min is supplied, then the heartbeat-max field MUST remain empty.
+ </doc>
+ </rule>
+ </field>
+ </control>
+
+ <!-- - Control: connection.tune-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="tune-ok" code="0x6" label="negotiate connection tuning parameters">
+ <doc>
+ This control sends the client's connection tuning parameters to the server. Certain fields
+ are negotiated, others provide capability information.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="channel-max" type="uint16" label="negotiated maximum channels" required="true">
+ <doc>
+ The maximum total number of channels that the client will use per connection.
+ </doc>
+
+ <rule name="upper-limit">
+ <doc>
+ If the client specifies a channel max that is higher than the value provided by the
+ server, the server MUST close the connection without attempting a negotiated close. The
+ server may report the error in some fashion to assist implementers.
+ </doc>
+
+ </rule>
+
+ <rule name="available-channels">
+ <doc>
+ If the client agrees to a channel-max of N channels, then the channels available for
+ communication between client and server are precisely the channels numbered 0 to (N-1).
+ </doc>
+ </rule>
+ </field>
+
+ <field name="max-frame-size" type="uint16" label="negotiated maximum frame size">
+ <doc>
+ The largest frame size that the client and server will use for the connection. If it is
+ not set means that the client does not impose any specific limit but may reject very large
+ frames if it cannot allocate resources for them. Note that the max-frame-size limit
+ applies principally to content frames, where large contents can be broken into frames of
+ arbitrary size.
+ </doc>
+
+ <rule name="minimum">
+ <doc>
+ Until the max-frame-size has been negotiated, both peers MUST accept frames of up to
+ MIN-MAX-FRAME-SIZE octets large, and the minimum negotiated value for max-frame-size is
+ also MIN-MAX-FRAME-SIZE.
+ </doc>
+ </rule>
+
+ <rule name="upper-limit">
+ <doc>
+ If the client specifies a max-frame-size that is higher than the value provided by the
+ server, the server MUST close the connection without attempting a negotiated close. The
+ server may report the error in some fashion to assist implementers.
+ </doc>
+ </rule>
+
+ <rule name="max-frame-size">
+ <doc>
+ A peer MUST NOT send frames larger than the agreed-upon size. A peer that receives an
+ oversized frame MUST close the connection with the framing-error close-code.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="heartbeat" type="uint16" label="negotiated heartbeat delay">
+ <doc>
+ The delay, in seconds, of the connection heartbeat chosen by the client. If it is not set
+ it means the client does not want a heartbeat.
+ </doc>
+
+ <rule name="permitted-range">
+ <doc>
+ The chosen heartbeat MUST be in the range supplied by the heartbeat-min and
+ heartbeat-max fields of connection.tune.
+ </doc>
+ </rule>
+
+ <rule name="no-heartbeat-min">
+ <doc>
+ The heartbeat field MUST NOT be set if the heartbeat-min field of connection.tune was
+ not set by the server.
+ </doc>
+ </rule>
+ </field>
+ </control>
+
+ <!-- - Control: connection.open - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="open" code="0x7" label="open connection to virtual host">
+ <doc>
+ This control opens a connection to a virtual host, which is a collection of resources, and
+ acts to separate multiple application domains within a server. The server may apply
+ arbitrary limits per virtual host, such as the number of each type of entity that may be
+ used, per connection and/or in total.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <response name="open-ok" />
+ <response name="redirect" />
+
+ <field name="virtual-host" type="str8" label="virtual host name" required="true">
+ <doc>
+ The name of the virtual host to work with.
+ </doc>
+
+ <rule name="separation">
+ <doc>
+ If the server supports multiple virtual hosts, it MUST enforce a full separation of
+ exchanges, queues, and all associated entities per virtual host. An application,
+ connected to a specific virtual host, MUST NOT be able to access resources of another
+ virtual host.
+ </doc>
+ </rule>
+
+ <rule name="security">
+ <doc>
+ The server SHOULD verify that the client has permission to access the specified virtual
+ host.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="capabilities" type="str16-array" label="required capabilities">
+ <doc>
+ The client can specify zero or more capability names. The server can use this to determine
+ how to process the client's connection request.
+ </doc>
+ </field>
+
+ <field name="insist" type="bit" label="insist on connecting to server">
+ <doc>
+ In a configuration with multiple collaborating servers, the server may respond to a
+ connection.open control with a Connection.Redirect. The insist option tells the server
+ that the client is insisting on a connection to the specified server.
+ </doc>
+ <rule name="behavior">
+ <doc>
+ When the client uses the insist option, the server MUST NOT respond with a
+ Connection.Redirect control. If it cannot accept the client's connection request it
+ should respond by closing the connection with a suitable reply code.
+ </doc>
+ </rule>
+ </field>
+ </control>
+
+ <!-- - Control: connection.open-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="open-ok" code="0x8" label="signal that connection is ready">
+ <doc>
+ This control signals to the client that the connection is ready for use.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="known-hosts" type="amqp-host-array" label="alternate hosts which may be used in
+ the case of failure">
+ <doc>
+ Specifies an array of equivalent or alternative hosts that the server knows about, which
+ will normally include the current server itself. Each entry in the array will be in the
+ form of an IP address or DNS name, optionally followed by a colon and a port number.
+ Clients can cache this information and use it when reconnecting to a server after a
+ failure. This field may be empty.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.redirect - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="redirect" code="0x9" label="redirects client to other server">
+ <doc>
+ This control redirects the client to another server, based on the requested virtual host
+ and/or capabilities.
+ </doc>
+
+ <rule name="usage">
+ <doc>
+ When getting the connection.redirect control, the client SHOULD reconnect to the host
+ specified, and if that host is not present, to any of the hosts specified in the
+ known-hosts list.
+ </doc>
+ </rule>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="host" type="amqp-host-url" label="server to connect to" required="true">
+ <doc>
+ Specifies the server to connect to.
+ </doc>
+ </field>
+
+ <field name="known-hosts" type="amqp-host-array" label="alternate hosts to try in case of
+ failure">
+ <doc>
+ An array of equivalent or alternative hosts that the server knows about.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.heartbeat - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="heartbeat" code="0xa" label="indicates connection is still alive">
+ <doc>
+ The heartbeat control may be used to generate artificial network traffic when a connection
+ is idle. If a connection is idle for more than twice the negotiated heartbeat delay, the
+ peers MAY be considered disconnected.
+ </doc>
+ <implement role="client" handle="MAY" />
+ <implement role="server" handle="MAY" />
+ </control>
+
+ <!-- - Control: connection.close - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="close" code="0xb" label="request a connection close">
+ <doc>
+ This control indicates that the sender wants to close the connection. The reason for close
+ is indicated with the reply-code and reply-text. The channel this control is sent on MAY be
+ used to indicate which channel caused the connection to close.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+ <implement role="server" handle="MUST" />
+
+ <response name="close-ok" />
+
+ <field name="reply-code" type="close-code" label="the numeric reply code"
+ required="true">
+ <doc>
+ Indicates the reason for connection closure.
+ </doc>
+ </field>
+ <field name="reply-text" type="str8" label="the localized reply text">
+ <doc>
+ This text can be logged as an aid to resolving issues.
+ </doc>
+ </field>
+ </control>
+
+ <!-- - Control: connection.close-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <control name="close-ok" code="0xc" label="confirm a connection close">
+ <doc>
+ This control confirms a connection.close control and tells the recipient that it is safe to
+ release resources for the connection and close the socket.
+ </doc>
+
+ <rule name="reporting">
+ <doc>
+ A peer that detects a socket closure without having received a Close-Ok handshake control
+ SHOULD log the error.
+ </doc>
+ </rule>
+
+ <implement role="client" handle="MUST" />
+ <implement role="server" handle="MUST" />
+ </control>
+
+ </class>
+
+ <!-- == Class: session ======================================================================= -->
+
+ <class name="session" code="0x2" label="session controls">
+ <doc>
+ A session is a named interaction between two peers. Session names are chosen by the upper
+ layers and may be used indefinitely. The model layer may associate long-lived or durable state
+ with a given session name. The session layer provides transport of commands associated with
+ this interaction.
+ </doc>
+
+ <doc>
+ The controls defined within this class are specified in terms of the "sender" of commands and
+ the "receiver" of commands. Since both client and server send and receive commands, the
+ overall session dialog is symmetric, however the semantics of the session controls are defined
+ in terms of a single sender/receiver pair, and it is assumed that the client and server will
+ each contain both a sender and receiver implementation.
+ </doc>
+
+ <rule name="attachment">
+ <doc>
+ The transport MUST be attached in order to use any control other than "attach", "attached",
+ "detach", or "detached". A peer receiving any other control on a detached transport MUST
+ discard it and send a session.detached with the "not-attached" reason code.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MUST" />
+ <role name="client" implement="MUST" />
+
+ <role name="sender" implement="MUST">
+ <doc>
+ The sender of commands.
+ </doc>
+ </role>
+ <role name="receiver" implement="MUST">
+ <doc>
+ The receiver of commands.
+ </doc>
+ </role>
+
+ <domain name="name" type="vbin16" label="opaque session name">
+ <doc>
+ The session name uniquely identifies an interaction between two peers. It is scoped to a
+ given authentication principal.
+ </doc>
+ </domain>
+
+ <domain name="detach-code" type="uint8" label="reason for detach">
+ <enum>
+ <choice name="normal" value="0">
+ <doc>
+ The session was detached by request.
+ </doc>
+ </choice>
+ <choice name="session-busy" value="1">
+ <doc>
+ The session is currently attached to another transport.
+ </doc>
+ </choice>
+ <choice name="transport-busy" value="2">
+ <doc>
+ The transport is currently attached to another session.
+ </doc>
+ </choice>
+ <choice name="not-attached" value="3">
+ <doc>
+ The transport is not currently attached to any session.
+ </doc>
+ </choice>
+ <choice name="unknown-ids" value="4">
+ <doc>
+ Command data was received prior to any use of the command-point control.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="commands" type="sequence-set" label="identifies a set of commands">
+ </domain>
+
+ <struct name="header" size="1" pack="1">
+ <doc>
+ The session header appears on commands after the class and command id, but prior to command
+ arguments.
+ </doc>
+
+ <field name="sync" type="bit" label="request notification of completion">
+ <doc>
+ Request notification of completion for this command.
+ </doc>
+ </field>
+ </struct>
+
+ <struct name="command-fragment" size="0" pack="0" label="byte-ranges within a set of commands">
+
+ <field name="command-id" type="sequence-no" required="true">
+
+ </field>
+ <field name="byte-ranges" type="byte-ranges" required="true">
+
+ </field>
+ </struct>
+
+ <domain name="command-fragments" type="array" label="an array of values of type
+ command-fragment"/>
+
+ <control name="attach" code="0x1" label="attach to the named session">
+ <doc>
+ Requests that the current transport be attached to the named session. Success or failure
+ will be indicated with an attached or detached response. This control is idempotent.
+ </doc>
+
+ <rule name="one-transport-per-session">
+ <doc>
+ A session MUST NOT be attached to more than one transport at a time.
+ </doc>
+ </rule>
+
+ <rule name="one-session-per-transport">
+ <doc>
+ A transport MUST NOT be attached to more than one session at a time.
+ </doc>
+ </rule>
+
+ <rule name="idempotence">
+ <doc>
+ Attaching a session to its current transport MUST succeed and result in an attached
+ response.
+ </doc>
+ </rule>
+
+ <rule name="scoping">
+ <doc>
+ Attachment to the same session name from distinct authentication principals MUST succeed.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MAY" />
+
+ <response name="attached"/>
+ <response name="detached"/>
+
+ <field name="name" type="name" label="the session name" required="true">
+ <doc>
+ Identifies the session to be attached to the current transport.
+ </doc>
+ </field>
+
+ <field name="force" type="bit" label="force attachment to a busy session">
+ <doc>
+ If set then a busy session will be forcibly detached from its other transport and
+ reattached to the current transport.
+ </doc>
+ </field>
+ </control>
+
+ <control name="attached" code="0x2" label="confirm attachment to the named session">
+ <doc>
+ Confirms successful attachment of the transport to the named session.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="name" type="name" label="the session name" required="true">
+ <doc>
+ Identifies the session now attached to the current transport.
+ </doc>
+ </field>
+ </control>
+
+ <control name="detach" code="0x3" label="detach from the named session">
+ <doc>
+ Detaches the current transport from the named session.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <response name="detached"/>
+
+ <field name="name" type="name" label="the session name" required="true">
+ <doc>
+ Identifies the session to detach.
+ </doc>
+ </field>
+ </control>
+
+ <control name="detached" code="0x4" label="confirm detachment from the named session">
+ <doc>
+ Confirms detachment of the current transport from the named session.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="name" type="name" label="the session name" required="true">
+ <doc>
+ Identifies the detached session.
+ </doc>
+ </field>
+ <field name="code" type="detach-code" label="the reason for detach" required="true">
+ <doc>
+ Identifies the reason for detaching from the named session.
+ </doc>
+ </field>
+ </control>
+
+ <!--
+ Execution state is the set of confirmed, and completed incoming commands, as well as the set
+ of outgoing in-doubt commands held for replay.
+ -->
+
+ <control name="request-timeout" code="0x5" label="requests the execution timeout be changed">
+ <doc>
+ This control may be sent by either the sender or receiver of commands. It requests that the
+ execution timeout be changed. This is the minimum amount of time that a peer must preserve
+ execution state for a detached session.
+ </doc>
+
+ <rule name="maximum-granted-timeout">
+ <doc>
+ The handler of this request MUST set his timeout to the maximum allowed value less than or
+ equal to the requested timeout, and MUST convey the chosen timeout in the response.
+ </doc>
+ </rule>
+
+ <implement role="sender" handle="MUST" />
+ <implement role="receiver" handle="MUST" />
+
+ <response name="timeout"/>
+
+ <field name="timeout" type="uint32" label="the requested timeout">
+ <doc>
+ The requested timeout for execution state in seconds. If not set, this control requests
+ that execution state is preserved indefinitely.
+ </doc>
+ </field>
+ </control>
+
+ <control name="timeout" code="0x6" label="the granted timeout">
+ <doc>
+ This control may be sent by the either the sender or receiver of commands. It is a
+ one-to-one reply to the request-timeout control that indicates the granted timeout for
+ execution state.
+ </doc>
+
+ <implement role="sender" handle="MUST" />
+ <implement role="receiver" handle="MUST" />
+
+ <field name="timeout" type="uint32" label="the execution timeout">
+ <doc>
+ The timeout for execution state. If not set, then execution state is preserved
+ indefinitely.
+ </doc>
+ </field>
+ </control>
+
+ <control name="command-point" code="0x7"
+ label="the command id and byte offset of subsequent data">
+ <doc>
+ This control is sent by the sender of commands and handled by the receiver of commands. This
+ establishes the sequence numbers associated with all subsequent command data sent from the
+ sender to the receiver. The subsequent command data will be numbered starting with the
+ values supplied in this control and proceeding sequentially. This must be used at least once
+ prior to sending any command data on newly attached transports.
+ </doc>
+
+ <rule name="newly-attached-transports">
+ <doc>
+ If command data is sent on a newly attached transport the session MUST be detached with an
+ "unknown-id" reason-code.
+ </doc>
+ </rule>
+
+ <rule name="zero-offset">
+ <doc>
+ If the offset is zero, the next data frame MUST have the first-frame and first-segment
+ flags set. Violation of this is a framing error.
+ </doc>
+ </rule>
+
+ <rule name="nonzero-offset">
+ <doc>
+ If the offset is nonzero, the next data frame MUST NOT have both the first-frame and
+ first-segment flag set. Violation of this is a framing error.
+ </doc>
+ </rule>
+
+ <implement role="receiver" handle="MUST" />
+
+ <field name="command-id" type="sequence-no" label="the command-id of the next command"
+ required="true"/>
+ <field name="command-offset" type="uint64" label="the byte offset within the command"
+ required="true"/>
+ </control>
+
+ <control name="expected" code="0x8" label="informs the peer of expected commands">
+ <doc>
+ This control is sent by the receiver of commands and handled by the sender of commands. It
+ informs the sender of what commands and command fragments are expected at the receiver.
+ This control is only sent in response to a flush control with the expected flag set. The
+ expected control is never sent spontaneously.
+ </doc>
+
+ <rule name="include-next-command">
+ <doc>
+ The set of expected commands MUST include the next command after the highest seen command.
+ </doc>
+ </rule>
+
+ <rule name="commands-empty-means-new-session">
+ <doc>
+ The set of expected commands MUST have zero elements if and only if the sender holds no
+ execution state for the session (i.e. it is a new session).
+ </doc>
+ </rule>
+
+ <rule name="no-overlaps">
+ <doc>
+ If a command-id appears in the commands field, it MUST NOT appear in the fragments field.
+ </doc>
+ </rule>
+
+ <rule name="minimal-fragments">
+ <doc>
+ When choice is permitted, a command MUST appear in the commands field rather than the
+ fragments field.
+ </doc>
+ </rule>
+
+ <implement role="sender" handle="MUST" />
+
+ <field name="commands" type="commands" label="expected commands" required="true"/>
+ <field name="fragments" type="command-fragments" label="expected fragments" />
+ </control>
+
+ <control name="confirmed" code="0x9" label="notifies of confirmed commands">
+ <doc>
+ This control is sent by the receiver of commands and handled by the sender of commands. This
+ sends the set of commands that will definitely be completed by this peer to the sender. This
+ excludes commands known by the receiver to be considered confirmed or complete at the
+ sender.
+ </doc>
+ <doc>
+ This control must be sent if the partner requests the set of confirmed commands using the
+ session.flush control with the confirmed flag set.
+ </doc>
+ <doc>
+ This control may be sent spontaneously. One reason for separating confirmation from
+ completion is for large persistent messages, where the receipt (and storage to a durable
+ store) of part of the message will result in less data needing to be replayed in the case of
+ transport failure during transmission.
+ </doc>
+ <doc>
+ A simple implementation of an AMQP client or server may be implemented to take no action on
+ receipt of session.confirmed controls, and take action only when receiving
+ session.completed controls.
+ </doc>
+ <doc>
+ A simple implementation of an AMQP client or server may be implemented such that it never
+ spontaneously sends session.confirmed and that when requested for the set of confirmed
+ commands (via the session.flush control) it responds with the same set of commands as it
+ would to when the set of completed commands was requested (trivially all completed commands
+ are confirmed).
+ </doc>
+
+ <rule name="durability">
+ <doc>
+ If a command has durable implications, it MUST NOT be confirmed until the fact of the
+ command has been recorded on durable media.
+ </doc>
+ </rule>
+
+ <rule name="no-overlaps">
+ <doc>
+ If a command-id appears in the commands field, it MUST NOT appear in the fragments field.
+ </doc>
+ </rule>
+
+ <rule name="minimal-fragments">
+ <doc>
+ When choice is permitted, a command MUST appear in the commands field rather than the
+ fragments field.
+ </doc>
+ </rule>
+
+ <implement role="sender" handle="MUST" />
+
+ <field name="commands" type="commands" label="entirely confirmed commands">
+ <rule name="exclude-known-complete">
+ <doc>
+ Command-ids included in prior known-complete replies MUST be excluded from the set of
+ all confirmed commands.
+ </doc>
+ </rule>
+ </field>
+ <field name="fragments" type="command-fragments" label="partially confirmed commands"/>
+ </control>
+
+ <control name="completed" code="0xa" label="notifies of command completion">
+ <doc>
+ This control is sent by the receiver of commands, and handled by the sender of commands. It
+ informs the sender of all commands completed by the receiver. This excludes commands known
+ by the receiver to be considered complete at the sender.
+ </doc>
+
+ <rule name="known-completed-reply">
+ <doc>
+ The sender MUST eventually reply with a known-completed set that covers the completed ids.
+ </doc>
+ </rule>
+
+ <rule name="delayed-reply">
+ <doc>
+ The known-complete reply MAY be delayed at the senders discretion if the timely-reply
+ field is not set.
+ </doc>
+ </rule>
+
+ <rule name="merged-reply">
+ <doc>
+ Multiple replies may be merged by sending a single known-completed that includes the union
+ of the merged command-id sets.
+ </doc>
+ </rule>
+
+ <implement role="sender" handle="MUST" />
+
+ <field name="commands" type="commands" label="completed commands">
+ <doc>
+ The ids of all completed commands. This excludes commands known by the receiver to be
+ considered complete at the sender.
+ </doc>
+
+ <rule name="completed-implies-confirmed">
+ <doc>
+ The sender MUST consider any completed commands to also be confirmed.
+ </doc>
+ </rule>
+
+ <rule name="exclude-known-complete">
+ <doc>
+ Command-ids included in prior known-complete replies MUST be excluded from the set of
+ all completed commands.
+ </doc>
+ </rule>
+ </field>
+ <field name="timely-reply" type="bit">
+ <doc>
+ If set, the sender is no longer free to delay the known-completed reply.
+ </doc>
+ </field>
+ </control>
+
+ <control name="known-completed" code="0xb" label="Inform peer of which commands are known to be
+ completed">
+ <doc>
+ This control is sent by the sender of commands, and handled by the receiver of commands. It
+ is sent in reply to one or more completed controls from the receiver. It informs the
+ receiver that commands are known to be completed by the sender.
+ </doc>
+
+ <rule name="stateless">
+ <doc>
+ The sender need not keep state to generate this reply. It is sufficient to reply to any
+ completed control with an exact echo of the completed ids.
+ </doc>
+ </rule>
+
+ <implement role="receiver" handle="MUST" />
+
+ <field name="commands" type="commands" label="commands known to be complete">
+ <doc>
+ The set of completed commands for one or more session.completed controls.
+ </doc>
+
+ <rule name="known-completed-implies-known-confirmed">
+ <doc>
+ The receiver MUST treat any of the specified commands to be considered by the sender as
+ confirmed as well as completed.
+ </doc>
+ </rule>
+ </field>
+ </control>
+
+ <control name="flush" code="0xc" label="requests a session.completed">
+ <doc>
+ This control is sent by the sender of commands and handled by the receiver of commands. It
+ requests that the receiver produce the indicated command sets. The receiver should issue the
+ indicated sets at the earliest possible opportunity.
+ </doc>
+
+ <implement role="receiver" handle="MUST" />
+
+ <field name="expected" type="bit" label="request notification of expected commands"/>
+ <field name="confirmed" type="bit" label="request notification of confirmed commands"/>
+ <field name="completed" type="bit" label="request notification of completed commands"/>
+ </control>
+
+ <control name="gap" code="0xd" label="indicates missing segments in the stream">
+ <doc>
+ This control is sent by the sender of commands and handled by the receiver of commands. It
+ sends command ranges for which there will be no further data forthcoming. The receiver
+ should proceed with the next available commands that arrive after the gap.
+ </doc>
+
+ <rule name="gap-confirmation-and-completion">
+ <doc>
+ The command-ids covered by a session.gap MUST be added to the completed and confirmed sets
+ by the receiver.
+ </doc>
+ </rule>
+
+ <rule name="aborted-commands">
+ <doc>
+ If a session.gap covers a partially received command, the receiving peer MUST treat the
+ command as aborted.
+ </doc>
+ </rule>
+
+ <rule name="completed-or-confirmed-commands">
+ <doc>
+ If a session.gap covers a completed or confirmed command, the receiving peer MUST continue
+ to treat the command as completed or confirmed.
+ </doc>
+ </rule>
+
+ <implement role="receiver" handle="MUST" />
+
+ <field name="commands" type="commands">
+ <doc>
+ The set of command-ids that are contained in this gap.
+ </doc>
+ </field>
+ </control>
+
+ </class>
+
+ <!-- == Class: execution ===================================================================== -->
+
+ <class name="execution" code="0x3" label="execution commands">
+ <doc>
+ The execution class provides commands that carry execution information about other model level
+ commands.
+ </doc>
+
+ <role name="server" implement="MUST"/>
+ <role name="client" implement="MUST"/>
+
+ <domain name="error-code" type="uint16">
+ <enum>
+ <choice name="unauthorized-access" value="403">
+ <doc>
+ The client attempted to work with a server entity to which it has no access due to
+ security settings.
+ </doc>
+ </choice>
+
+ <choice name="not-found" value="404">
+ <doc>
+ The client attempted to work with a server entity that does not exist.
+ </doc>
+ </choice>
+
+ <choice name="resource-locked" value="405">
+ <doc>
+ The client attempted to work with a server entity to which it has no access because
+ another client is working with it.
+ </doc>
+ </choice>
+
+ <choice name="precondition-failed" value="406">
+ <doc>
+ The client requested a command that was not allowed because some precondition failed.
+ </doc>
+ </choice>
+
+ <choice name="resource-deleted" value="408">
+ <doc>
+ A server entity the client is working with has been deleted.
+ </doc>
+ </choice>
+
+ <choice name="illegal-state" value="409">
+ <doc>
+ The peer sent a command that is not permitted in the current state of the session.
+ </doc>
+ </choice>
+
+ <choice name="command-invalid" value="503">
+ <doc>
+ The command segments could not be decoded.
+ </doc>
+ </choice>
+
+ <choice name="resource-limit-exceeded" value="506">
+ <doc>
+ The client exceeded its resource allocation.
+ </doc>
+ </choice>
+
+ <choice name="not-allowed" value="530">
+ <doc>
+ The peer tried to use a command a manner that is inconsistent with the rules described
+ in the specification.
+ </doc>
+ </choice>
+
+ <choice name="illegal-argument" value="531">
+ <doc>
+ The command argument is malformed, i.e. it does not fall within the specified domain.
+ The illegal-argument exception can be raised on execution of any command which has
+ domain valued fields.
+ </doc>
+ </choice>
+
+ <choice name="not-implemented" value="540">
+ <doc>
+ The peer tried to use functionality that is not implemented in its partner.
+ </doc>
+ </choice>
+
+ <choice name="internal-error" value="541">
+ <doc>
+ The peer could not complete the command because of an internal error. The peer may
+ require intervention by an operator in order to resume normal operations.
+ </doc>
+ </choice>
+
+ <choice name="invalid-argument" value="542">
+ <doc>
+ An invalid argument was passed to a command, and the operation could not
+ proceed. An invalid argument is not illegal (see illegal-argument), i.e. it matches
+ the domain definition; however the particular value is invalid in this context.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <!-- - Command: execution.sync - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="sync" code="0x1" label="request notification of completion for issued commands">
+ <doc>
+ This command is complete when all prior commands are completed.
+ </doc>
+
+ <implement role="server" handle="MUST"/>
+ <implement role="client" handle="MUST"/>
+ </command>
+
+ <!-- - Command: execution.result - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="result" code="0x2" label="carries execution results">
+ <doc>
+ This command carries data resulting from the execution of a command.
+ </doc>
+
+ <implement role="server" handle="MUST"/>
+ <implement role="client" handle="MUST"/>
+
+ <field name="command-id" type="sequence-no" required="true"/>
+ <field name="value" type="struct32"/>
+ </command>
+
+ <!-- - Command: execution.exception - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="exception" code="0x3" label="notifies a peer of an execution error">
+ <doc>
+ This command informs a peer of an execution exception. The command-id, when given,
+ correlates the error to a specific command.
+ </doc>
+
+ <implement role="client" handle="MUST"/>
+ <implement role="server" handle="MUST"/>
+
+ <field name="error-code" type="error-code" required="true" label="error code indicating the
+ type of error"/>
+ <field name="command-id" type="sequence-no" label="exceptional command">
+ <doc>
+ The command-id of the command which caused the exception. If the exception was not caused
+ by a specific command, this value is not set.
+ </doc>
+ </field>
+ <field name="class-code" type="uint8" label="the class code of the command whose execution
+ gave rise to the error (if appropriate)"/>
+ <field name="command-code" type="uint8" label="the class code of the command whose execution
+ gave rise to the error (if appropriate)"/>
+ <field name="field-index" type="uint8" label="index of the exceptional field">
+ <doc>
+ The zero based index of the exceptional field within the arguments to the exceptional
+ command. If the exception was not caused by a specific field, this value is not set.
+ </doc>
+ </field>
+ <field name="description" type="str16" label="descriptive text on the exception">
+ <doc>
+ The description provided is implementation defined, but MUST be in the language
+ appropriate for the selected locale. The intention is that this description is suitable
+ for logging or alerting output.
+ </doc>
+ </field>
+ <field name="error-info" type="map" label="map to carry additional information about the
+ error"/>
+
+ </command>
+
+ </class>
+
+ <!-- == Class: message ======================================================================= -->
+
+ <class name="message" code="0x4" label="message transfer">
+ <doc>
+ The message class provides commands that support an industry-standard messaging model.
+ </doc>
+
+ <doc type="picture" title="Transfer States">
+ START:
+
+ The message has yet to be sent to the recipient.
+
+ NOT-ACQUIRED:
+
+ The message has been sent to the recipient, but is not
+ acquired by the recipient.
+
+ ACQUIRED:
+
+ The message has been sent to and acquired by the recipient.
+
+ END:
+
+ The transfer is complete.
+ </doc>
+
+ <doc type="picture" title="State Transitions"><![CDATA[
+ *:TRANSFER (accept-mode=none) *:TRANSFER (acquire-mode=pre-acquired)
+ +---------------------------------START------------------------------------------+
+ | | |
+ | | *:TRANSFER (acquire-mode=not-acquired) |
+ | | |
+ | R:RELEASE \|/ |
+ | +-------------NOT-ACQUIRED<--+ |
+ | | | | | R:ACQUIRE (if unavailable) |
+ | | | +-----+ |
+ | | | |
+ | | | R:ACQUIRE (if available) |
+ | | | |
+ | | \|/ |
+ | | ACQUIRED<-------------------------------------------+
+ | | |
+ | | | R:ACCEPT / R:REJECT / R:RELEASE
+ | | |
+ | | \|/
+ | +------------->END]]>
+ | /|\
+ | |
+ +-------------------------------+
+ </doc>
+
+ <doc type="grammar">
+ message = *:TRANSFER [ R:ACQUIRE ] [ R:ACCEPT / R:REJECT / R:RELEASE ]
+ / *:RESUME
+ / *:SET-FLOW-MODE
+ / *:FLOW
+ / *:STOP
+ / C:SUBSCRIBE
+ / C:CANCEL
+ / C:FLUSH
+ </doc>
+
+ <rule name="persistent-message">
+ <doc>
+ The server SHOULD respect the delivery-mode property of messages and SHOULD make a
+ best-effort to hold persistent messages on a reliable storage mechanism.
+ </doc>
+ <doc type="scenario">
+ Send a persistent message to queue, stop server, restart server and then verify whether
+ message is still present. Assumes that queues are durable. Persistence without durable
+ queues makes no sense.
+ </doc>
+ </rule>
+
+ <rule name="no-persistent-message-discard">
+ <doc>
+ The server MUST NOT discard a persistent message in case of a queue overflow.
+ </doc>
+ <doc type="scenario">
+ Create a queue overflow situation with persistent messages and verify that messages do not
+ get lost (presumably the server will write them to disk).
+ </doc>
+ </rule>
+
+ <rule name="throttling">
+ <doc>
+ The server MAY use the message.flow command to slow or stop a message publisher when
+ necessary.
+ </doc>
+ </rule>
+
+ <rule name="non-persistent-message-overflow">
+ <doc>
+ The server MAY overflow non-persistent messages to persistent storage.
+ </doc>
+ </rule>
+
+ <rule name="non-persistent-message-discard">
+ <doc>
+ The server MAY discard or dead-letter non-persistent messages on a priority basis if the
+ queue size exceeds some configured limit.
+ </doc>
+ </rule>
+
+ <rule name="min-priority-levels">
+ <doc>
+ The server MUST implement at least 2 priority levels for messages, where priorities 0 and
+ 9 are treated as two distinct levels.
+ </doc>
+ </rule>
+
+ <rule name="priority-level-implementation">
+ <doc>
+ The server SHOULD implement distinct priority levels in the following manner:
+ </doc>
+ <doc>
+ If the server implements n distinct priorities then priorities 0 to 5 - ceiling(n/2) should
+ be treated equivalently and should be the lowest effective priority. The priorities 4 +
+ floor(n/2) should be treated equivalently and should be the highest effective priority. The
+ priorities (5 - ceiling(n/2)) to (4 + floor(n/2)) inclusive must be treated as distinct
+ priorities.
+ </doc>
+ <doc>
+ Thus, for example, if 2 distinct priorities are implemented, then levels 0 to 4 are
+ equivalent, and levels 5 to 9 are equivalent and levels 4 and 5 are distinct. If 3 distinct
+ priorities are implements the 0 to 3 are equivalent, 5 to 9 are equivalent and 3, 4 and 5
+ are distinct.
+ </doc>
+ <doc>
+ This scheme ensures that if two priorities are distinct for a server which implements m
+ separate priority levels they are also distinct for a server which implements n different
+ priority levels where n > m.
+ </doc>
+ </rule>
+
+ <rule name="priority-delivery">
+ <doc>
+ The server MUST deliver messages of the same priority in order irrespective of their
+ individual persistence.
+ </doc>
+ <doc type="scenario">
+ Send a set of messages with the same priority but different persistence settings to a queue.
+ Subscribe and verify that messages arrive in same order as originally published.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MUST" />
+ <role name="client" implement="MUST" />
+
+ <domain name="destination" type="str8" label="destination for a message">
+ <doc>
+ Specifies the destination to which the message is to be transferred.
+ </doc>
+ </domain>
+
+ <domain name="accept-mode" type="uint8" label="indicates a confirmation mode">
+ <doc>
+ Controls how the sender of messages is notified of successful transfer.
+ </doc>
+
+ <enum>
+ <choice name="explicit" value="0">
+ <doc>
+ Successful transfer is signaled by message.accept. An acquired message (whether
+ acquisition was implicit as in pre-acquired mode or explicit as in not-acquired mode) is
+ not considered transferred until a message.accept that includes the transfer command is
+ received.
+ </doc>
+ </choice>
+
+ <choice name="none" value="1">
+ <doc>
+ Successful transfer is assumed when accept-mode is "pre-acquired". Messages transferred
+ with an accept-mode of "not-acquired" cannot be acquired when accept-mode is "none".
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="acquire-mode" type="uint8" label="indicates the transfer mode">
+ <doc>
+ Indicates whether a transferred message can be considered as automatically acquired or
+ whether an explicit request is necessary in order to acquire it.
+ </doc>
+
+ <enum>
+ <choice name="pre-acquired" value="0">
+ <doc>
+ the message is acquired when the transfer starts
+ </doc>
+ </choice>
+
+ <choice name="not-acquired" value="1">
+ <doc>
+ the message is not acquired when it arrives, and must be explicitly acquired by the
+ recipient
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="reject-code" type="uint16" label="reject code for transfer">
+ <doc>
+ Code specifying the reason for a message reject.
+ </doc>
+ <enum>
+ <choice name="unspecified" value="0">
+ <doc>
+ Rejected for an unspecified reason.
+ </doc>
+ </choice>
+ <choice name="unroutable" value="1">
+ <doc>
+ Delivery was attempted but there were no queues which the message could be routed to.
+ </doc>
+ </choice>
+ <choice name="immediate" value="2">
+ <doc>
+ The rejected message had the immediate flag set to true, but at the time of the transfer
+ at least one of the queues to which it was to be routed did not have any subscriber able
+ to take the message.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="resume-id" type="str16">
+ <doc>
+ A resume-id serves to identify partially transferred message content. The id is chosen by
+ the sender, and must be unique to a given user. A resume-id is not expected to be unique
+ across users.
+ </doc>
+ </domain>
+
+ <domain name="delivery-mode" type="uint8"
+ label="indicates whether a message should be treated as transient or durable">
+ <doc>
+
+ Used to set the reliability requirements for a message which is transferred to the server.
+ </doc>
+ <enum>
+ <choice name="non-persistent" value="1">
+ <doc>
+ A non-persistent message may be lost in event of a failure, but the nature of the
+ communication is such that an occasional message loss is tolerable. This is the lowest
+ overhead mode. Non-persistent messages are delivered at most once only.
+ </doc>
+ </choice>
+
+ <choice name="persistent" value="2">
+ <doc>
+ A persistent message is one which must be stored on a persistent medium (usually hard
+ drive) at every stage of delivery so that it will not be lost in event of failure (other
+ than of the medium itself). This is normally accomplished with some additional overhead.
+ A persistent message may be delivered more than once if there is uncertainty about the
+ state of its delivery after a failure and recovery.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="delivery-priority" type="uint8"
+ label="indicates the desired priority to assign to a message transfer">
+ <doc>
+ Used to assign a priority to a message transfer. Priorities range from 0 (lowest) to 9
+ (highest).
+ </doc>
+ <enum>
+ <choice name="lowest" value="0">
+ <doc>
+ Lowest possible priority message.
+ </doc>
+ </choice>
+
+ <choice name="lower" value="1">
+ <doc>
+ Very low priority message
+ </doc>
+ </choice>
+
+ <choice name="low" value="2">
+ <doc>
+ Low priority message.
+ </doc>
+ </choice>
+
+ <choice name="below-average" value="3">
+ <doc>
+ Below average priority message.
+ </doc>
+ </choice>
+
+ <choice name="medium" value="4">
+ <doc>
+ Medium priority message.
+ </doc>
+ </choice>
+
+
+ <choice name="above-average" value="5">
+ <doc>
+ Above average priority message
+ </doc>
+ </choice>
+
+
+ <choice name="high" value="6">
+ <doc>
+ High priority message
+ </doc>
+ </choice>
+
+ <choice name="higher" value="7">
+ <doc>
+ Higher priority message
+ </doc>
+ </choice>
+
+ <choice name="very-high" value="8">
+ <doc>
+ Very high priority message.
+ </doc>
+ </choice>
+
+ <choice name="highest" value="9">
+ <doc>
+ Highest possible priority message.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <struct name="delivery-properties" size="4" code="0x1" pack="2">
+ <field name="discard-unroutable" type="bit" label="controls discard of unroutable messages">
+ <doc>
+ If set on a message that is not routable the broker can discard it. If not set, an
+ unroutable message should be handled by reject when accept-mode is explicit; or by routing
+ to the alternate-exchange if defined when accept-mode is none.
+ </doc>
+ </field>
+
+ <field name="immediate" type="bit" label="Consider message unroutable if it cannot be
+ processed immediately">
+ <doc>
+ If the immediate flag is set to true on a message transferred to a Server, then the
+ message should be considered unroutable (and not delivered to any queues) if, for any
+ queue that it is to be routed to according to the standard routing behavior, there is not
+ a subscription on that queue able to receive the message. The treatment of unroutable
+ messages is dependent on the value of the discard-unroutable flag.
+ </doc>
+ <doc>
+ The immediate flag is ignored on transferred to a Client.
+ </doc>
+ </field>
+
+ <field name="redelivered" type="bit" label="redelivery flag">
+ <doc>
+ This boolean flag indicates that the message may have been previously delivered to this
+ or another client.
+ </doc>
+ <doc>
+ If the redelivered flag is set on transfer to a Server, then any delivery of the message
+ from that Server to a Client must also have the redelivered flag set to true.
+ </doc>
+ <rule name="implementation">
+ <doc>
+ The server MUST try to signal redelivered messages when it can. When redelivering a
+ message that was not successfully accepted, the server SHOULD deliver it to the original
+ client if possible.
+ </doc>
+ <doc type="scenario">
+ Create a shared queue and publish a message to the queue. Subscribe using explicit
+ accept-mode, but do not accept the message. Close the session, reconnect, and subscribe
+ to the queue again. The message MUST arrive with the redelivered flag set.
+ </doc>
+ </rule>
+ <rule name="hinting">
+ <doc>
+ The client should not rely on the redelivered field to detect duplicate messages where
+ publishers may themselves produce duplicates. A fully robust client should be able to
+ track duplicate received messages on non-transacted, and locally-transacted sessions.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="priority" type="delivery-priority" label="message priority, 0 to 9"
+ required="true">
+ <doc> Message priority, which can be between 0 and 9. Messages with higher priorities may be
+ delivered before those with lower priorities. </doc>
+ </field>
+
+ <field name="delivery-mode" type="delivery-mode" label="message persistence requirement"
+ required="true">
+ <doc> The delivery mode may be non-persistent or persistent. </doc>
+ </field>
+
+ <field name="ttl" type="uint64" label="time to live in ms">
+ <doc> Duration in milliseconds for which the message should be considered "live". If this is
+ set then a message expiration time will be computed based on the current time plus this
+ value. Messages that live longer than their expiration time will be discarded (or dead
+ lettered).</doc>
+ <rule name="ttl-decrement">
+ <doc>
+ If a message is transferred between brokers before delivery to a final subscriber the
+ ttl should be decremented before peer to peer transfer and both timestamp and expiration
+ should be cleared.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="timestamp" type="datetime" label="message timestamp">
+ <doc>
+ The timestamp is set by the broker on arrival of the message.
+ </doc>
+ </field>
+
+ <field name="expiration" type="datetime" label="message expiration time">
+ <doc>
+ The expiration header assigned by the broker. After receiving the message the broker sets
+ expiration to the sum of the ttl specified in the publish command and the current time.
+ (ttl=expiration - timestamp)
+ </doc>
+ </field>
+
+ <field name="exchange" type="exchange.name" label="originating exchange">
+ <doc>
+ Identifies the exchange specified in the destination field of the message.transfer used to
+ publish the message. This MUST be set by the broker upon receipt of a message.
+ </doc>
+ </field>
+
+ <field name="routing-key" type="str8" label="message routing key">
+ <doc>
+ The value of the key determines to which queue the exchange will send the message. The way
+ in which keys are used to make this routing decision depends on the type of exchange to
+ which the message is sent. For example, a direct exchange will route a message to a queue
+ if that queue is bound to the exchange with a binding-key identical to the routing-key of
+ the message.
+ </doc>
+ </field>
+
+ <field name="resume-id" type="resume-id" label="global id for message transfer">
+ <doc>
+ When a resume-id is provided the recipient MAY use it to retain message data should the
+ session expire while the message transfer is still incomplete.
+ </doc>
+ </field>
+
+ <field name="resume-ttl" type="uint64" label="ttl in ms for interrupted message data">
+ <doc>
+ When a resume-ttl is provided the recipient MAY use it has a guideline for how long to
+ retain the partially complete data when a resume-id is specified. If no resume-id is
+ specified then this value should be ignored.
+ </doc>
+ </field>
+ </struct>
+
+ <struct name="fragment-properties" size="4" code="0x2" pack="2">
+ <doc>
+ These properties permit the transfer of message fragments. These may be used in conjunction
+ with byte level flow control to limit the rate at which large messages are received. Only
+ the first fragment carries the delivery-properties and message-properties.
+
+ Syntactically each fragment appears as a complete message to the lower layers of the
+ protocol, however the model layer is required to treat all the fragments as a single
+ message. For example all fragments must be delivered to the same client. In pre-acquired
+ mode, no message fragments can be delivered by the broker until the entire message has been
+ received.
+ </doc>
+
+ <field name="first" type="bit" default="1">
+ <doc>True if this fragment contains the start of the message, false otherwise.</doc>
+ </field>
+
+ <field name="last" type="bit" default="1">
+ <doc>True if this fragment contains the end of the message, false otherwise.</doc>
+ </field>
+
+ <field name="fragment-size" type="uint64">
+ <doc>This field may optionally contain the size of the fragment.</doc>
+ </field>
+ </struct>
+
+ <struct name="reply-to" size="2" pack="2">
+ <doc>The reply-to domain provides a simple address structure for replying to to a message to a
+ destination within the same virtual-host.</doc>
+ <field name="exchange" type="exchange.name" label="the name of the exchange to reply to"/>
+ <field name="routing-key" type="str8" label="the routing-key to use when replying"/>
+ </struct>
+
+ <struct name="message-properties" size="4" code="0x3" pack="2">
+ <field name="content-length" type="uint64" label="length of the body segment in bytes">
+ <doc>
+ The length of the body segment in bytes.
+ </doc>
+ </field>
+
+ <field name="message-id" type="uuid" label="application message identifier">
+ <doc>
+ Message-id is an optional property of UUID type which uniquely identifies a message within
+ the message system. The message producer is usually responsible for setting the
+ message-id. The server MAY discard a message as a duplicate if the value of the message-id
+ matches that of a previously received message. Duplicate messages MUST still be accepted
+ if transferred with an accept-mode of "explicit".
+ </doc>
+
+ <rule name="unique">
+ <doc>
+ A message-id MUST be unique within a given server instance. A message-id SHOULD be
+ globally unique (i.e. across different systems).
+ </doc>
+ </rule>
+
+ <rule name="immutable">
+ <doc>
+ A message ID is immutable. Once set, a message-id MUST NOT be changed or reassigned,
+ even if the message is replicated, resent or sent to multiple queues.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="correlation-id" type="vbin16" label="application correlation identifier">
+ <doc>
+ This is a client-specific id that may be used to mark or identify messages between
+ clients. The server ignores this field.
+ </doc>
+ </field>
+
+ <field name="reply-to" type="reply-to" label="destination to reply to">
+ <doc>
+ The destination of any message that is sent in reply to this message.
+ </doc>
+ </field>
+
+ <field name="content-type" type="str8" label="MIME content type">
+ <doc>
+ The RFC-2046 MIME type for the message content (such as "text/plain"). This is set by the
+ originating client.
+ </doc>
+ </field>
+
+ <field name="content-encoding" type="str8" label="MIME content encoding">
+ <doc>
+ The encoding for character-based message content. This is set by the originating client.
+ Examples include UTF-8 and ISO-8859-15.
+ </doc>
+ </field>
+
+ <field name="user-id" type="vbin16" label="creating user id">
+ <doc>
+ The identity of the user responsible for producing the message. The client sets this
+ value, and it is authenticated by the broker.
+ </doc>
+
+ <rule name="authentication">
+ <doc>
+ The server MUST produce an unauthorized-access exception if the user-id field is set to
+ a principle for which the client is not authenticated.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="app-id" type="vbin16" label="creating application id">
+ <doc>
+ The identity of the client application responsible for producing the message.
+ </doc>
+ </field>
+
+ <field name="application-headers" type="map" label="application specific headers table">
+ <doc>
+ This is a collection of user-defined headers or properties which may be set by the
+ producing client and retrieved by the consuming client.
+ </doc>
+ </field>
+ </struct>
+
+ <domain name="flow-mode" type="uint8" label="the flow-mode for allocating flow credit">
+ <enum>
+ <choice name="credit" value="0">
+ <doc>
+ Credit based flow control.
+ </doc>
+ </choice>
+
+ <choice name="window" value="1">
+ <doc>
+ Window based flow control.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <domain name="credit-unit" type="uint8" label="specifies the unit of credit balance">
+ <enum>
+ <choice name="message" value="0">
+ <doc>Indicates a value specified in messages.</doc>
+ </choice>
+ <choice name="byte" value="1">
+ <doc>Indicates a value specified in bytes.</doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <!-- - Command: message.transfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="transfer" code="0x1" label="transfer a message">
+ <doc>
+ This command transfers a message between two peers. When a client uses this command to
+ publish a message to a broker, the destination identifies a specific exchange. The message
+ will then be routed to queues as defined by the exchange configuration.
+
+ The client may request a broker to transfer messages to it, from a particular queue, by
+ issuing a subscribe command. The subscribe command specifies the destination that the broker
+ should use for any resulting transfers.
+ </doc>
+
+ <rule name="transactional-publish">
+ <doc>
+ If a transfer to an exchange occurs within a transaction, then it is not available from
+ the queue until the transaction commits. It is not specified whether routing takes place
+ when the transfer is received or when the transaction commits.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+
+ <field name="destination" type="destination" label="message destination">
+ <doc>
+ Specifies the destination to which the message is to be transferred.
+ </doc>
+
+ <rule name="blank-destination">
+ <doc>
+ The server MUST accept a blank destination to mean the default exchange.
+ </doc>
+ </rule>
+
+ <exception name="nonexistent-exchange" error-code="not-found">
+ <doc>
+ If the destination refers to an exchange that does not exist, the peer MUST raise a
+ session exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="accept-mode" type="accept-mode" required="true">
+ <doc>
+ Indicates whether message.accept, session.complete, or nothing at all is required to
+ indicate successful transfer of the message.
+ </doc>
+ </field>
+
+ <field name="acquire-mode" type="acquire-mode" required="true">
+ <doc>
+ Indicates whether or not the transferred message has been acquired.
+ </doc>
+ </field>
+
+ <segments>
+ <header>
+ <entry type="delivery-properties"/>
+ <entry type="fragment-properties"/>
+ <entry type="message-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ <!-- - Command: message.accept - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="accept" code="0x2" label="reject a message">
+ <doc>
+ Accepts the message. Once a transfer is accepted, the command-id may no longer be referenced
+ from other commands.
+ </doc>
+
+ <rule name="acquisition">
+ <doc>
+ The recipient MUST have acquired a message in order to accept it.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="transfers" type="session.commands" required="true">
+ <doc>
+ Identifies the messages previously transferred that should be accepted.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.reject - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="reject" code="0x3" label="reject a message">
+ <doc>
+ Indicates that the message transfers are unprocessable in some way. A server may reject a
+ message if it is unroutable. A client may reject a message if it is invalid. A message may
+ be rejected for other reasons as well. Once a transfer is rejected, the command-id may no
+ longer be referenced from other commands.
+ </doc>
+
+ <rule name="alternate-exchange">
+ <doc>
+ When a client rejects a message, the server MUST deliver that message to the
+ alternate-exchange on the queue from which it was delivered. If no alternate-exchange is
+ defined for that queue the broker MAY discard the message.
+ </doc>
+ </rule>
+
+ <rule name="acquisition">
+ <doc>
+ The recipient MUST have acquired a message in order to reject it. If the message is not
+ acquired any reject MUST be ignored.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="transfers" type="session.commands" required="true">
+ <doc>
+ Identifies the messages previously transferred that should be rejected.
+ </doc>
+ </field>
+ <field name="code" type="reject-code" required="true">
+ <doc>
+ Code describing the reason for rejection.
+ </doc>
+ </field>
+ <field name="text" type="str8" label="informational text for message reject">
+ <doc>
+ Text describing the reason for rejection.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.release - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="release" code="0x4" label="release a message">
+ <doc>
+ Release previously transferred messages. When acquired messages are released, they become
+ available for acquisition by any subscriber. Once a transfer is released, the command-id may
+ no longer be referenced from other commands.
+ </doc>
+
+ <rule name="ordering">
+ <doc>
+ Acquired messages that have been released MAY subsequently be delivered out of order.
+ Implementations SHOULD ensure that released messages keep their position with respect to
+ undelivered messages of the same priority.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MAY" />
+
+ <field name="transfers" type="session.commands" required="true">
+ <doc>
+ Indicates the messages to be released.
+ </doc>
+ </field>
+ <field name="set-redelivered" type="bit" label="mark the released messages as redelivered">
+ <doc>
+ By setting set-redelivered to true, any acquired messages released to a queue with this
+ command will be marked as redelivered on their next transfer from that queue. If this flag
+ is not set, then an acquired message will retain its original redelivered status on the
+ queue. Messages that are not acquired are unaffected by the value of this flag.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.acquire - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="acquire" code="0x5" label="acquire messages for consumption">
+ <doc>
+ Acquires previously transferred messages for consumption. The acquired ids (if any) are
+ sent via message.acquired.
+ </doc>
+
+ <rule name="one-to-one">
+ <doc>
+ Each acquire MUST produce exactly one message.acquired even if it is empty.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="transfers" type="session.commands" required="true">
+ <doc>
+ Indicates the messages to be acquired.
+ </doc>
+ </field>
+
+ <result>
+ <struct name="acquired" size="4" code="0x4" pack="2" label="indicates acquired messages">
+ <doc>
+ Identifies a set of previously transferred messages that have now been acquired.
+ </doc>
+
+ <field name="transfers" type="session.commands" required="true">
+ <doc>
+ Indicates the acquired messages.
+ </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ <!-- - Command: message.resume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="resume" code="0x6" label="resume an interrupted message transfer">
+ <doc>
+ This command resumes an interrupted transfer. The recipient should return the amount of
+ partially transferred data associated with the given resume-id, or zero if there is no data
+ at all. If a non-zero result is returned, the recipient should expect to receive message
+ fragment(s) containing the remainder of the interrupted message.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="destination" type="destination">
+ <doc>
+ The destination to which the remaining message fragments are transferred.
+ </doc>
+
+ <exception name="destination-not-found" error-code="not-found">
+ <doc>If the destination does not exist, the recipient MUST close the session.</doc>
+ </exception>
+ </field>
+
+ <field name="resume-id" type="resume-id" required="true">
+ <doc>
+ The name of the transfer being resumed.
+ </doc>
+
+ <rule name="unknown-resume-id">
+ <doc>If the resume-id is not known, the recipient MUST return an offset of zero.</doc>
+ </rule>
+ </field>
+
+ <result>
+ <struct name="message-resume-result" size="4" code="0x5" pack="2">
+ <field name="offset" type="uint64">
+ <doc>
+ Indicates the amount of data already transferred.
+ </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ <!-- - Command: message.subscribe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="subscribe" code="0x7" label="start a queue subscription">
+ <doc> This command asks the server to start a "subscription", which is a request for messages
+ from a specific queue. Subscriptions last as long as the session they were created on, or
+ until the client cancels them. </doc>
+
+ <rule name="simultaneous-subscriptions">
+ <doc> The server SHOULD support at least 16 subscriptions per queue, and ideally, impose no
+ limit except as defined by available resources. </doc>
+ <doc type="scenario"> Create a queue and create subscriptions on that queue until the server
+ closes the connection. Verify that the number of subscriptions created was at least
+ sixteen and report the total number. </doc>
+ </rule>
+
+ <rule name="default-flow-mode">
+ <doc> The default flow mode for new subscriptions is window-mode. </doc>
+ </rule>
+
+ <exception name="queue-deletion" error-code="resource-deleted">
+ <doc>
+ If the queue for this subscription is deleted, any subscribing sessions MUST be closed.
+ This exception may occur at any time after the subscription has been completed.
+ </doc>
+ </exception>
+
+ <exception name="queue-not-found" error-code="not-found">
+ <doc> If the queue for this subscription does not exist, then the subscribing session MUST
+ be closed. </doc>
+ </exception>
+
+ <rule name="initial-credit">
+ <doc>
+ Immediately after a subscription is created, the initial byte and message credit for that
+ destination is zero.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST"/>
+
+ <field name="queue" type="queue.name" required="true">
+ <doc> Specifies the name of the subscribed queue. </doc>
+ </field>
+
+ <field name="destination" type="destination" label="incoming message destination">
+ <doc> The client specified name for the subscription. This is used as the destination for
+ all messages transferred from this subscription. The destination is scoped to the session.
+ </doc>
+
+ <exception name="unique-subscriber-destination" error-code="not-allowed">
+ <doc> The client MUST NOT specify a destination that refers to an existing subscription on
+ the same session. </doc>
+ <doc type="scenario"> Attempt to create two subscriptions on the same session with the
+ same non-empty destination. </doc>
+ </exception>
+ </field>
+
+ <field name="accept-mode" type="accept-mode" required="true">
+ <doc> The accept-mode to use for messages transferred from this subscription. </doc>
+ </field>
+
+ <field name="acquire-mode" type="acquire-mode" required="true">
+ <doc> The acquire-mode to use for messages transferred from this subscription. </doc>
+ </field>
+
+ <field name="exclusive" type="bit" label="request exclusive access">
+ <doc> Request an exclusive subscription. This prevents other subscribers from subscribing to
+ the queue. </doc>
+
+ <exception name="in-use" error-code="resource-locked">
+ <doc> The server MUST NOT grant an exclusive subscription to a queue that already has
+ subscribers. </doc>
+ <doc type="scenario"> Open two connections to a server, and in one connection create a
+ shared (non-exclusive) queue and then subscribe to the queue. In the second connection
+ attempt to subscribe to the same queue using the exclusive option. </doc>
+ </exception>
+ </field>
+
+ <field name="resume-id" type="resume-id">
+ <doc> Requests that the broker use the supplied resume-id when transferring messages for
+ this subscription. </doc>
+ </field>
+
+ <field name="resume-ttl" type="uint64">
+ <doc> Requested duration in milliseconds for the broker use as resume-ttl when transferring
+ messages for this subscription. </doc>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for vendor extensions">
+ <doc> The syntax and semantics of these arguments depends on the providers implementation.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="cancel" code="0x8" label="end a queue subscription">
+ <doc>
+ This command cancels a subscription. This does not affect already delivered messages, but it
+ does mean the server will not send any more messages for that subscription. The client may
+ receive an arbitrary number of messages in between sending the cancel command and receiving
+ notification that the cancel command is complete.
+ </doc>
+
+ <rule name="post-cancel-transfer-resolution">
+ <doc>
+ Canceling a subscription MUST NOT affect pending transfers. A transfer made prior to
+ canceling transfers to the destination MUST be able to be accepted, released, acquired, or
+ rejected after the subscription is canceled.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="destination" type="destination" required="true">
+ <exception name="subscription-not-found" error-code="not-found">
+ <doc>
+ If the subscription specified by the destination is not found, the server MUST close the
+ session.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: message.set-flow-mode - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="set-flow-mode" code="0x9" label="set the flow control mode">
+ <doc>
+ Sets the mode of flow control used for a given destination to either window or credit based
+ flow control.
+
+ With credit based flow control, the sender of messages continually maintains its current
+ credit balance with the recipient. The credit balance consists of two values, a message
+ count, and a byte count. Whenever message data is sent, both counts must be decremented.
+ If either value reaches zero, the flow of message data must stop. Additional credit is
+ received via the message.flow command.
+
+ The sender MUST NOT send partial assemblies. This means that if there is not enough byte
+ credit available to send a complete message, the sender must either wait or use message
+ fragmentation (see the fragment-properties header struct) to send the first part of the
+ message data in a complete assembly.
+
+ Window based flow control is identical to credit based flow control, however message
+ transfer completion implicitly grants a single unit of message credit, and the size of the
+ message in byte credits for each completed message transfer. Completion of the transfer
+ command with session.completed is the only way credit is implicitly updated; message.accept,
+ message.release, message.reject, tx.commit and tx.rollback have no effect on the outstanding
+ credit balances.
+ </doc>
+
+ <rule name="byte-accounting">
+ <doc>
+ The byte count is decremented by the payload size of each transmitted frame with segment
+ type header or body appearing within a message.transfer command. Note that the payload
+ size is the frame size less the frame header size.
+ </doc>
+ </rule>
+
+ <rule name="mode-switching">
+ <doc>
+ Mode switching may only occur if both the byte and message credit balance are zero. There
+ are three ways for a recipient of messages to be sure that the sender's credit balances
+ are zero:
+
+ 1) The recipient may send a message.stop command to the sender. When the recipient
+ receives notification of completion for the message.stop command, it knows that the
+ sender's credit is zero.
+
+ 2) The recipient may perform the same steps described in (1) with the message.flush
+ command substituted for the message.stop command.
+
+ 3) Immediately after a subscription is created with message.subscribe, the credit for
+ that destination is zero.
+ </doc>
+ </rule>
+
+ <rule name="default-flow-mode">
+ <doc>
+ Prior to receiving an explicit set-flow-mode command, a peer MUST consider the flow-mode
+ to be window.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="destination" type="destination"/>
+ <field name="flow-mode" type="flow-mode" required="true">
+ <doc>
+ The new flow control mode.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.flow - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="flow" code="0xa" label="control message flow">
+ <doc>
+ This command controls the flow of message data to a given destination. It is used by the
+ recipient of messages to dynamically match the incoming rate of message flow to its
+ processing or forwarding capacity. Upon receipt of this command, the sender must add "value"
+ number of the specified unit to the available credit balance for the specified destination.
+ A value of (0xFFFFFFFF) indicates an infinite amount of credit. This disables any limit for
+ the given unit until the credit balance is zeroed with message.stop or message.flush.
+ </doc>
+
+ <!-- throws no-such-destination -->
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="destination" type="destination"/>
+ <field name="unit" type="credit-unit" required="true">
+ <doc>
+ The unit of value.
+ </doc>
+ </field>
+ <field name="value" type="uint32">
+ <doc>
+ If the value is not set then this indicates an infinite amount of credit.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: message.flush - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="flush" code="0xb" label="force the sending of available messages">
+ <doc>
+ Forces the sender to exhaust his credit supply. The sender's credit will always be zero when
+ this command completes. The command completes when immediately available message data has
+ been transferred, or when the credit supply is exhausted.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="destination" type="destination"/>
+ </command>
+
+ <!-- - Command: message.stop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="stop" code="0xc" label="stop the sending of messages">
+ <doc>
+ On receipt of this command, a producer of messages MUST set his credit to zero for the given
+ destination. When notifying of completion, credit MUST be zero and no further messages will
+ be sent until such a time as further credit is received.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <field name="destination" type="destination"/>
+ </command>
+
+ </class>
+
+ <!-- == Class: tx ============================================================================ -->
+
+ <class name="tx" code="0x5" label="work with standard transactions">
+ <doc>
+ Standard transactions provide so-called "1.5 phase commit". We can ensure that work is never
+ lost, but there is a chance of confirmations being lost, so that messages may be resent.
+ Applications that use standard transactions must be able to detect and ignore duplicate
+ messages.
+ </doc>
+
+ <doc type="grammar">
+ tx = C:SELECT
+ / C:COMMIT
+ / C:ROLLBACK
+ </doc>
+
+ <!-- XXX: this isn't really a rule, as stated there is no way for
+ a client library to implement this -->
+ <rule name="duplicate-tracking">
+ <doc>
+ An client using standard transactions SHOULD be able to track all messages received within a
+ reasonable period, and thus detect and reject duplicates of the same message. It SHOULD NOT
+ pass these to the application layer.
+ </doc>
+ </rule>
+
+ <role name="server" implement="SHOULD" />
+
+ <!-- - Command: tx.select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="select" code="0x1" label="select standard transaction mode">
+ <doc>
+ This command sets the session to use standard transactions. The client must use this command
+ exactly once on a session before using the Commit or Rollback commands.
+ </doc>
+
+ <exception name="exactly-once" error-code="illegal-state">
+ <doc>
+ A client MUST NOT select standard transactions on a session that is already transactional.
+ </doc>
+ </exception>
+
+ <exception name="no-dtx" error-code="illegal-state">
+ <doc>
+ A client MUST NOT select standard transactions on a session that is already enlisted in a
+ distributed transaction.
+ </doc>
+ </exception>
+
+ <exception name="explicit-accepts" error-code="not-allowed">
+ <doc>
+ On a session on which tx.select has been issued, a client MUST NOT issue a
+ message.subscribe command with the accept-mode property set to any value other than
+ explicit. Similarly a tx.select MUST NOT be issued on a session on which a there is a non
+ cancelled subscriber with accept-mode of none.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MUST" />
+ </command>
+
+ <!-- - Command: tx.commit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="commit" code="0x2" label="commit the current transaction">
+ <doc>
+ This command commits all messages published and accepted in the current transaction. A
+ new transaction starts immediately after a commit.
+ </doc>
+ <doc>
+ In more detail, the commit acts on all messages which have been transferred from the Client
+ to the Server, and on all acceptances of messages sent from Server to Client. Since the
+ commit acts on commands sent in the same direction as the commit command itself, there is no
+ ambiguity on the scope of the commands being committed. Further, the commit will not be
+ completed until all preceding commands which it affects have been completed.
+ </doc>
+ <doc>
+ Since transactions act on explicit accept commands, the only valid accept-mode for message
+ subscribers is explicit. For transferring messages from Client to Server (publishing) all
+ accept-modes are permitted.
+ </doc>
+
+ <exception name="select-required" error-code="illegal-state">
+ <doc>
+ A client MUST NOT issue tx.commit on a session that has not been selected for standard
+ transactions with tx.select.
+ </doc>
+ </exception>
+
+
+
+ <implement role="server" handle="MUST" />
+ </command>
+
+ <!-- - Command: tx.rollback - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="rollback" code="0x3" label="abandon the current transaction">
+ <doc>
+ This command abandons the current transaction. In particular the transfers from Client to
+ Server (publishes) and accepts of transfers from Server to Client which occurred in the
+ current transaction are discarded. A new transaction starts immediately after a rollback.
+ </doc>
+ <doc>
+ In more detail, when a rollback is issued, any the effects of transfers which occurred from
+ Client to Server are discarded. The Server will issue completion notification for all such
+ transfers prior to the completion of the rollback. Similarly the effects of any
+ message.accept issued from Client to Server prior to the issuance of the tx.rollback will be
+ discarded; and notification of completion for all such commands will be issued before the
+ issuance of the completion for the rollback.
+ </doc>
+ <doc>
+ After the completion of the rollback, the client will still hold the messages which it has
+ not yet accepted (including those for which accepts were previously issued within the
+ transaction); i.e. the messages remain "acquired". If the Client wishes to release those
+ messages back to the Server, then appropriate message.release commands must be issued.
+ </doc>
+
+ <exception name="select-required" error-code="illegal-state">
+ <doc>
+ A client MUST NOT issue tx.rollback on a session that has not been selected for standard
+ transactions with tx.select.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MUST" />
+ </command>
+
+ </class>
+
+ <!-- == Class: dtx =========================================================================== -->
+
+ <class name="dtx" code="0x6" label="Demarcates dtx branches">
+ <doc>
+ This provides the X-Open XA distributed transaction protocol support. It allows a session
+ to be selected for use with distributed transactions, the transactional boundaries for work on
+ that session to be demarcated and allows the transaction manager to coordinate transaction
+ outcomes.
+ </doc>
+
+ <doc type="grammar">
+ dtx-demarcation = C:SELECT *demarcation
+ demarcation = C:START C:END
+ </doc>
+
+ <doc type="grammar">
+ dtx-coordination = *coordination
+ coordination = command
+ / outcome
+ / recovery
+ command = C:SET-TIMEOUT
+ / C:GET-TIMEOUT
+ outcome = one-phase-commit
+ / one-phase-rollback
+ / two-phase-commit
+ / two-phase-rollback
+ one-phase-commit = C:COMMIT
+ one-phase-rollback = C:ROLLBACK
+ two-phase-commit = C:PREPARE C:COMMIT
+ two-phase-rollback = C:PREPARE C:ROLLBACK
+ recovery = C:RECOVER *recovery-outcome
+ recovery-outcome = one-phase-commit
+ / one-phase-rollback
+ / C:FORGET
+
+ </doc>
+
+ <rule name="transactionality">
+ <doc>
+ Enabling XA transaction support on a session requires that the server MUST manage
+ transactions demarcated by start-end blocks. That is to say that on this XA-enabled session,
+ work undergone within transactional blocks is performed on behalf a transaction branch
+ whereas work performed outside of transactional blocks is NOT transactional.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MAY" />
+ <role name="client" implement="MAY" />
+
+ <!-- XA domains -->
+
+ <domain name="xa-status" type="uint16" label="XA return codes">
+ <enum>
+ <choice name="xa-ok" value="0">
+ <doc>
+ Normal execution completion (no error).
+ </doc>
+ </choice>
+
+ <choice name="xa-rbrollback" value="1">
+ <doc>
+ The rollback was caused for an unspecified reason.
+ </doc>
+ </choice>
+
+ <choice name="xa-rbtimeout" value="2">
+ <doc>
+ A transaction branch took too long.
+ </doc>
+ </choice>
+
+ <choice name="xa-heurhaz" value="3">
+ <doc>
+ The transaction branch may have been heuristically completed.
+ </doc>
+ </choice>
+
+ <choice name="xa-heurcom" value="4">
+ <doc>
+ The transaction branch has been heuristically committed.
+ </doc>
+ </choice>
+
+ <choice name="xa-heurrb" value="5">
+ <doc>
+ The transaction branch has been heuristically rolled back.
+ </doc>
+ </choice>
+
+ <choice name="xa-heurmix" value="6">
+ <doc>
+ The transaction branch has been heuristically committed and rolled back.
+ </doc>
+ </choice>
+
+ <choice name="xa-rdonly" value="7">
+ <doc>
+ The transaction branch was read-only and has been committed.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <struct name="xa-result" size="4" code="0x1" pack="2">
+ <field name="status" type="xa-status" required="true"/>
+ </struct>
+
+ <!-- Struct for xid -->
+
+ <struct name="xid" size="4" code="0x4" pack="2" label="dtx branch identifier">
+ <doc>
+ An xid uniquely identifies a transaction branch.
+ </doc>
+
+ <field name="format" type="uint32" label="implementation specific format code"
+ required="true"/>
+ <field name="global-id" type="vbin8" label="global transaction id" required="true"/>
+ <field name="branch-id" type="vbin8" label="branch qualifier" required="true"/>
+ </struct>
+
+ <!-- - Command: dtx.select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="select" code="0x1" label="Select dtx mode">
+ <doc>
+ This command sets the session to use distributed transactions. The client must use this
+ command at least once on a session before using XA demarcation operations.
+ </doc>
+
+ <implement role="server" handle="MAY" />
+ </command>
+
+ <!-- - Command: dtx.start - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="start" code="0x2" label="Start a dtx branch">
+ <doc>
+ This command is called when messages should be produced and consumed on behalf a transaction
+ branch identified by xid.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ send a session exception.
+ </doc>
+ </exception>
+
+ <exception name="already-known" error-code="not-allowed">
+ <doc>
+ If neither join nor resume is specified is specified and the transaction branch specified
+ by xid has previously been seen then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="join-and-resume" error-code="not-allowed">
+ <doc>
+ If join and resume are specified then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch to be started.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-allowed">
+ <doc>
+ If xid is already known by the broker then the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="join" type="bit" label="Join with existing xid flag">
+ <doc>
+ Indicate whether this is joining an already associated xid. Indicate that the start
+ applies to joining a transaction previously seen.
+ </doc>
+
+ <exception name="unsupported" error-code="not-implemented">
+ <doc>
+ If the broker does not support join the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="resume" type="bit" label="Resume flag">
+ <doc>
+ Indicate that the start applies to resuming a suspended transaction branch specified.
+ </doc>
+ </field>
+
+ <result type="xa-result">
+ <doc>
+ This confirms to the client that the transaction branch is started or specify the error
+ condition.
+
+ The value of this field may be one of the following constants:
+
+ xa-ok: Normal execution.
+
+ xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
+ reason.
+
+ xa-rbtimeout: The work represented by this transaction branch took too long.
+ </doc>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="end" code="0x3" label="End a dtx branch">
+ <doc>
+ This command is called when the work done on behalf a transaction branch finishes or needs
+ to be suspended.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="suspend-and-fail" error-code="not-allowed">
+ <doc>
+ If suspend and fail are specified then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <rule name="success">
+ <doc>
+ If neither fail nor suspend are specified then the portion of work has completed
+ successfully.
+ </doc>
+ </rule>
+
+ <rule name="session-closed">
+ <doc>
+ When a session is closed then the currently associated transaction branches MUST be marked
+ rollback-only.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch to be ended.
+ </doc>
+
+ <exception name="not-associated" error-code="illegal-state">
+ <doc>
+ The session MUST be currently associated with the given xid (through an earlier start
+ call with the same xid).
+ </doc>
+ </exception>
+ </field>
+
+ <field name="fail" type="bit" label="Failure flag">
+ <doc>
+ If set, indicates that this portion of work has failed; otherwise this portion of work has
+ completed successfully.
+ </doc>
+
+ <rule name="failure">
+ <doc>
+ An implementation MAY elect to roll a transaction back if this failure notification is
+ received. Should an implementation elect to implement this behavior, and this bit is
+ set, then then the transaction branch SHOULD be marked as rollback-only and the end
+ result SHOULD have the xa-rbrollback status set.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="suspend" type="bit" label="Temporary suspension flag">
+ <doc>
+ Indicates that the transaction branch is temporarily suspended in an incomplete state.
+ </doc>
+
+ <rule name="resume">
+ <doc>
+ The transaction context is in a suspended state and must be resumed via the start
+ command with resume specified.
+ </doc>
+ </rule>
+
+ </field>
+
+ <result type="xa-result">
+ <doc>
+ This command confirms to the client that the transaction branch is ended or specify the
+ error condition.
+
+ The value of this field may be one of the following constants:
+
+ xa-ok: Normal execution.
+
+ xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
+ reason. If an implementation chooses to implement rollback-on-failure behavior, then
+ this value should be selected if the dtx.end.fail bit was set.
+
+ xa-rbtimeout: The work represented by this transaction branch took too long.
+ </doc>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.commit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="commit" code="0x4" label="Commit work on dtx branch">
+ <doc>
+ Commit the work done on behalf a transaction branch. This command commits the work
+ associated with xid. Any produced messages are made available and any consumed messages are
+ discarded.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ raise an exception.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch to be committed.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-disassociated" error-code="illegal-state">
+ <doc>
+ If this command is called when xid is still associated with a session then the server
+ MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="one-phase" type="bit" label="One-phase optimization flag">
+ <doc>
+ Used to indicate whether one-phase or two-phase commit is used.
+ </doc>
+
+ <exception name="one-phase" error-code="illegal-state">
+ <doc>
+ The one-phase bit MUST be set if a commit is sent without a preceding prepare.
+ </doc>
+ </exception>
+
+ <exception name="two-phase" error-code="illegal-state">
+ <doc>
+ The one-phase bit MUST NOT be set if the commit has been preceded by prepare.
+ </doc>
+ </exception>
+ </field>
+
+ <result type="xa-result">
+ <doc>
+ This confirms to the client that the transaction branch is committed or specify the
+ error condition.
+
+ The value of this field may be one of the following constants:
+
+ xa-ok: Normal execution
+
+ xa-heurhaz: Due to some failure, the work done on behalf of the specified transaction
+ branch may have been heuristically completed.
+
+ xa-heurcom: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was committed.
+
+ xa-heurrb: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was rolled back.
+
+ xa-heurmix: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was partially committed and partially rolled back.
+
+ xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
+ reason.
+
+ xa-rbtimeout: The work represented by this transaction branch took too long.
+ </doc>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.forget - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="forget" code="0x5" label="Discard dtx branch">
+ <doc>
+ This command is called to forget about a heuristically completed transaction branch.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ raise an exception.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch to be forgotten.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-disassociated" error-code="illegal-state">
+ <doc>
+ If this command is called when xid is still associated with a session then the server
+ MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: dtx.get-timeout - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="get-timeout" code="0x6" label="Obtain dtx timeout in seconds">
+ <doc>
+ This command obtains the current transaction timeout value in seconds. If set-timeout was
+ not used prior to invoking this command, the return value is the default timeout; otherwise,
+ the value used in the previous set-timeout call is returned.
+ </doc>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch for getting the timeout.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <result>
+ <struct name="get-timeout-result" size="4" code="0x2" pack="2">
+ <doc> Returns the value of the timeout last specified through set-timeout. </doc>
+
+ <field name="timeout" type="uint32" label="The current transaction timeout value"
+ required="true">
+ <doc> The current transaction timeout value in seconds. </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.prepare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="prepare" code="0x7" label="Prepare a dtx branch">
+ <doc>
+ This command prepares for commitment any message produced or consumed on behalf of xid.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ raise an exception.
+ </doc>
+ </exception>
+
+ <rule name="obligation-1">
+ <doc>
+ Once this command successfully returns it is guaranteed that the transaction branch may be
+ either committed or rolled back regardless of failures.
+ </doc>
+ </rule>
+
+ <rule name="obligation-2">
+ <doc>
+ The knowledge of xid cannot be erased before commit or rollback complete the branch.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch that can be prepared.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-disassociated" error-code="illegal-state">
+ <doc>
+ If this command is called when xid is still associated with a session then the server
+ MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <result type="xa-result">
+ <doc>
+ This command confirms to the client that the transaction branch is prepared or specify the
+ error condition.
+
+ The value of this field may be one of the following constants:
+
+ xa-ok: Normal execution.
+
+ xa-rdonly: The transaction branch was read-only and has been committed.
+
+ xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
+ reason.
+
+ xa-rbtimeout: The work represented by this transaction branch took too long.
+ </doc>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.recover - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="recover" code="0x8" label="Get prepared or completed xids">
+ <doc>
+ This command is called to obtain a list of transaction branches that are in a prepared or
+ heuristically completed state.
+ </doc>
+
+ <implement role="server" handle="MAY" />
+
+ <result>
+ <struct name="recover-result" size="4" code="0x3" pack="2">
+ <doc>
+ Returns to the client a table with single item that is a sequence of transaction xids
+ that are in a prepared or heuristically completed state.
+ </doc>
+
+ <field name="in-doubt" type="array" label="array of xids to be recovered" required="true">
+ <doc> Array containing the xids to be recovered (xids that are in a prepared or
+ heuristically completed state). </doc>
+
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.rollback - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="rollback" code="0x9" label="Rollback a dtx branch">
+ <doc>
+ This command rolls back the work associated with xid. Any produced messages are discarded
+ and any consumed messages are re-enqueued.
+ </doc>
+
+ <exception name="illegal-state" error-code="illegal-state">
+ <doc>
+ If the command is invoked in an improper context (see class grammar) then the server MUST
+ raise an exception.
+ </doc>
+ </exception>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch that can be rolled back.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-disassociated" error-code="illegal-state">
+ <doc>
+ If this command is called when xid is still associated with a session then the server
+ MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <result type="xa-result">
+ <doc>
+ This command confirms to the client that the transaction branch is rolled back or specify
+ the error condition.
+
+ The value of this field may be one of the following constants:
+
+ xa-ok: Normal execution
+
+ xa-heurhaz: Due to some failure, the work done on behalf of the specified transaction
+ branch may have been heuristically completed.
+
+ xa-heurcom: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was committed.
+
+ xa-heurrb: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was rolled back.
+
+ xa-heurmix: Due to a heuristic decision, the work done on behalf of the specified
+ transaction branch was partially committed and partially rolled back.
+
+ xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
+ reason.
+
+ xa-rbtimeout: The work represented by this transaction branch took too long.
+ </doc>
+ </result>
+ </command>
+
+ <!-- - Command: dtx.set-timeout - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="set-timeout" code="0xa" label="Set dtx timeout value">
+ <doc>
+ Sets the specified transaction branch timeout value in seconds.
+ </doc>
+
+ <rule name="effective">
+ <doc>
+ Once set, this timeout value is effective until this command is reinvoked with a different
+ value.
+ </doc>
+ </rule>
+
+ <rule name="reset">
+ <doc>
+ A value of zero resets the timeout value to the default value.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MAY" />
+
+ <field name="xid" type="xid" label="Transaction xid" required="true">
+ <doc>
+ Specifies the xid of the transaction branch for setting the timeout.
+ </doc>
+
+ <exception name="unknown-xid" error-code="not-found">
+ <doc>
+ If xid is unknown (the transaction branch has not been started or has already been
+ ended) then the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ </field>
+
+ <field name="timeout" type="uint32" label="Dtx timeout in seconds" required="true">
+ <doc>
+ The transaction timeout value in seconds.
+ </doc>
+ </field>
+ </command>
+
+ </class>
+
+ <!-- == Class: exchange ====================================================================== -->
+
+ <class name="exchange" code="0x7" label="work with exchanges">
+ <doc>
+ Exchanges match and distribute messages across queues. Exchanges can be configured in the
+ server or created at runtime.
+ </doc>
+
+ <doc type="grammar">
+ exchange = C:DECLARE
+ / C:DELETE
+ / C:QUERY
+ </doc>
+
+ <rule name="required-types">
+ <doc>
+ The server MUST implement these standard exchange types: fanout, direct.
+ </doc>
+ <doc type="scenario">
+ Client attempts to declare an exchange with each of these standard types.
+ </doc>
+ </rule>
+
+ <rule name="recommended-types">
+ <doc>
+ The server SHOULD implement these standard exchange types: topic, headers.
+ </doc>
+ <doc type="scenario">
+ Client attempts to declare an exchange with each of these standard types.
+ </doc>
+ </rule>
+
+ <rule name="required-instances">
+ <doc>
+ The server MUST, in each virtual host, pre-declare an exchange instance for each standard
+ exchange type that it implements, where the name of the exchange instance, if defined, is
+ "amq." followed by the exchange type name.
+
+ The server MUST, in each virtual host, pre-declare at least two direct exchange instances:
+ one named "amq.direct", the other with no public name that serves as a default exchange for
+ publish commands (such as message.transfer).
+ </doc>
+ <doc type="scenario">
+ Client creates a temporary queue and attempts to bind to each required exchange instance
+ ("amq.fanout", "amq.direct", "amq.topic", and "amq.headers" if those types are defined).
+ </doc>
+ </rule>
+
+ <rule name="default-exchange">
+ <doc>
+ The server MUST pre-declare a direct exchange with no public name to act as the default
+ exchange for content publish commands (such as message.transfer) and for default queue
+ bindings.
+ </doc>
+ <doc type="scenario">
+ Client checks that the default exchange is active by publishing a message with a suitable
+ routing key but without specifying the exchange name, then ensuring that the message arrives
+ in the queue correctly.
+ </doc>
+ </rule>
+
+ <rule name="default-access">
+ <doc>
+ The default exchange MUST NOT be accessible to the client except by specifying an empty
+ exchange name in a content publish command (such as message.transfer). That is, the server
+ must not let clients explicitly bind, unbind, delete, or make any other reference to this
+ exchange.
+ </doc>
+ </rule>
+
+ <rule name="extensions">
+ <doc>
+ The server MAY implement other exchange types as wanted.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MUST" />
+ <role name="client" implement="MUST" />
+
+ <domain name="name" type="str8" label="exchange name">
+ <doc>
+ The exchange name is a client-selected string that identifies the exchange for publish
+ commands. Exchange names may consist of any mixture of digits, letters, and underscores.
+ Exchange names are scoped by the virtual host.
+ </doc>
+ </domain>
+
+ <!-- - Command: exchange.declare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="declare" code="0x1" label="verify exchange exists, create if needed">
+ <doc>
+ This command creates an exchange if it does not already exist, and if the exchange exists,
+ verifies that it is of the correct and expected class.
+ </doc>
+
+ <rule name="minimum">
+ <doc>
+ The server SHOULD support a minimum of 16 exchanges per virtual host and ideally, impose
+ no limit except as defined by available resources.
+ </doc>
+ <doc type="scenario">
+ The client creates as many exchanges as it can until the server reports an error; the
+ number of exchanges successfully created must be at least sixteen.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="exchange" type="name" required="true">
+ <exception name="reserved-names" error-code="not-allowed">
+ <doc>
+ Exchange names starting with "amq." are reserved for pre-declared and standardized
+ exchanges. The client MUST NOT attempt to create an exchange starting with "amq.".
+ </doc>
+ </exception>
+
+ <exception name="exchange-name-required" error-code="invalid-argument">
+ <doc>
+ The name of the exchange MUST NOT be a blank or empty string.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="type" type="str8" label="exchange type" required="true">
+ <doc>
+ Each exchange belongs to one of a set of exchange types implemented by the server. The
+ exchange types define the functionality of the exchange - i.e. how messages are routed
+ through it. It is not valid or meaningful to attempt to change the type of an existing
+ exchange.
+ </doc>
+
+ <exception name="typed" error-code="not-allowed">
+ <doc>
+ Exchanges cannot be redeclared with different types. The client MUST NOT attempt to
+ redeclare an existing exchange with a different type than used in the original
+ exchange.declare command.
+ </doc>
+ </exception>
+
+ <exception name="exchange-type-not-found" error-code="not-found">
+ <doc>
+ If the client attempts to create an exchange which the server does not recognize, an
+ exception MUST be sent.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="alternate-exchange" type="name" label= "exchange name for unroutable messages">
+ <doc>
+ In the event that a message cannot be routed, this is the name of the exchange to which
+ the message will be sent. Messages transferred using message.transfer will be routed to
+ the alternate-exchange only if they are sent with the "none" accept-mode, and the
+ discard-unroutable delivery property is set to false, and there is no queue to route to
+ for the given message according to the bindings on this exchange.
+ </doc>
+
+ <rule name="empty-name">
+ <doc>
+ If alternate-exchange is not set (its name is an empty string), unroutable messages
+ that would be sent to the alternate-exchange MUST be dropped silently.
+ </doc>
+ </rule>
+
+ <exception name="pre-existing-exchange" error-code="not-allowed">
+ <doc>
+ If the alternate-exchange is not empty and if the exchange already exists with a
+ different alternate-exchange, then the declaration MUST result in an exception.
+ </doc>
+ </exception>
+
+ <rule name="double-failure">
+ <doc>
+ A message which is being routed to a alternate exchange, MUST NOT be re-routed to a
+ secondary alternate exchange if it fails to route in the primary alternate exchange.
+ After such a failure, the message MUST be dropped. This prevents looping.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="passive" type="bit" label="do not create exchange">
+ <doc>
+ If set, the server will not create the exchange. The client can use this to check whether
+ an exchange exists without modifying the server state.
+ </doc>
+ <exception name="not-found" error-code="not-found">
+ <doc>
+ If set, and the exchange does not already exist, the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="durable" type="bit" label="request a durable exchange">
+ <doc>
+ If set when creating a new exchange, the exchange will be marked as durable. Durable
+ exchanges remain active when a server restarts. Non-durable exchanges (transient
+ exchanges) are purged if/when a server restarts.
+ </doc>
+
+ <rule name="support">
+ <doc>
+ The server MUST support both durable and transient exchanges.
+ </doc>
+ </rule>
+
+ <rule name="sticky">
+ <doc>
+ The server MUST ignore the durable field if the exchange already exists.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="auto-delete" type="bit" label="auto-delete when unused">
+ <doc>
+ If set, the exchange is deleted automatically when there remain no bindings between the
+ exchange and any queue. Such an exchange will not be automatically deleted until at least
+ one binding has been made to prevent the immediate deletion of the exchange upon creation.
+ </doc>
+ <rule name="sticky">
+ <doc>
+ The server MUST ignore the auto-delete field if the exchange already exists.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for declaration">
+ <doc>
+ A set of arguments for the declaration. The syntax and semantics of these arguments
+ depends on the server implementation. This field is ignored if passive is 1.
+ </doc>
+
+ <exception name="unknown-argument" error-code="not-implemented">
+ <doc>
+ If the arguments field contains arguments which are not understood by the server,
+ it MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: exchange.delete - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="delete" code="0x2" label="delete an exchange">
+ <doc>
+ This command deletes an exchange. When an exchange is deleted all queue bindings on the
+ exchange are cancelled.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="exchange" type="name" required="true">
+ <exception name="exists" error-code="not-found">
+ <doc>
+ The client MUST NOT attempt to delete an exchange that does not exist.
+ </doc>
+ </exception>
+
+ <exception name="exchange-name-required" error-code="invalid-argument">
+ <doc>
+ The name of the exchange MUST NOT be a missing or empty string.
+ </doc>
+ </exception>
+
+ <exception name="used-as-alternate" error-code="not-allowed">
+ <doc>
+ An exchange MUST NOT be deleted if it is in use as an alternate-exchange by a queue or
+ by another exchange.
+ </doc>
+ </exception>
+
+ </field>
+
+ <field name="if-unused" type="bit" label="delete only if unused">
+ <doc>
+ If set, the server will only delete the exchange if it has no queue bindings. If the
+ exchange has queue bindings the server does not delete it but raises an exception
+ instead.
+ </doc>
+ <exception name="exchange-in-use" error-code="precondition-failed">
+ <doc>
+ If the exchange has queue bindings, and the if-unused flag is set, the server MUST NOT
+ delete the exchange, but MUST raise and exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: exchange.query - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="query" code="0x3" label="request information about an exchange">
+ <doc>
+ This command is used to request information on a particular exchange.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="name" type="str8" label="the exchange name">
+ <doc>
+ The name of the exchange for which information is requested. If not specified explicitly
+ the default exchange is implied.
+ </doc>
+ </field>
+
+ <result>
+ <struct name="exchange-query-result" size="4" code="0x1" pack="2">
+ <doc>
+ This is sent in response to a query request and conveys information on a particular
+ exchange.
+ </doc>
+
+ <field name="type" type="str8" label="indicate the exchange type">
+ <doc>
+ The type of the exchange. Will be empty if the exchange is not found.
+ </doc>
+ </field>
+
+ <field name="durable" type="bit" label="indicate the durability">
+ <doc>
+ The durability of the exchange, i.e. if set the exchange is durable. Will not be set
+ if the exchange is not found.
+ </doc>
+ </field>
+
+ <field name="not-found" type="bit" label="indicate an unknown exchange">
+ <doc>
+ If set, the exchange for which information was requested is not known.
+ </doc>
+ </field>
+
+ <field name="arguments" type="map" label="other unspecified exchange properties">
+ <doc>
+ A set of properties of the exchange whose syntax and semantics depends on the server
+ implementation. Will be empty if the exchange is not found.
+ </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ <!-- - Command: exchange.bind - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="bind" code="0x4" label="bind queue to an exchange">
+ <doc> This command binds a queue to an exchange. Until a queue is bound it will not receive
+ any messages. In a classic messaging model, store-and-forward queues are bound to a direct
+ exchange and subscription queues are bound to a topic exchange. </doc>
+
+ <rule name="duplicates">
+ <doc>
+ A server MUST ignore duplicate bindings - that is, two or more bind commands with the
+ same exchange, queue, and binding-key - without treating these as an error. The value of
+ the arguments used for the binding MUST NOT be altered by subsequent binding requests.
+ </doc>
+ <doc type="scenario">
+ A client binds a named queue to an exchange. The client then repeats the bind (with
+ identical exchange, queue, and binding-key). The second binding should use a different
+ value for the arguments field.
+ </doc>
+ </rule>
+
+ <rule name="durable-exchange">
+ <doc> Bindings between durable queues and durable exchanges are automatically durable and
+ the server MUST restore such bindings after a server restart. </doc>
+ <doc type="scenario"> A server creates a named durable queue and binds it to a durable
+ exchange. The server is restarted. The client then attempts to use the queue/exchange
+ combination. </doc>
+ </rule>
+
+ <rule name="binding-count">
+ <doc> The server SHOULD support at least 4 bindings per queue, and ideally, impose no limit
+ except as defined by available resources. </doc>
+ <doc type="scenario"> A client creates a named queue and attempts to bind it to 4 different
+ exchanges. </doc>
+ </rule>
+
+ <rule name="multiple-bindings">
+ <doc> Where more than one binding exists between a particular exchange instance and a
+ particular queue instance any given message published to that exchange should be delivered
+ to that queue at most once, regardless of how many distinct bindings match. </doc>
+ <doc type="scenario"> A client creates a named queue and binds it to the same topic exchange
+ at least three times using intersecting binding-keys (for example, "animals.*",
+ "animals.dogs.*", "animal.dogs.chihuahua"). Verify that a message matching all the
+ bindings (using previous example, routing key = "animal.dogs.chihuahua") is delivered once
+ only. </doc>
+ </rule>
+
+ <implement role="server" handle="MUST"/>
+
+ <field name="queue" type="queue.name" required="true">
+ <doc> Specifies the name of the queue to bind. </doc>
+
+ <exception name="empty-queue" error-code="invalid-argument">
+ <doc> A client MUST NOT be allowed to bind a non-existent and unnamed queue (i.e. empty
+ queue name) to an exchange. </doc>
+ <doc type="scenario"> A client attempts to bind with an unnamed (empty) queue name to an
+ exchange. </doc>
+ </exception>
+
+ <exception name="queue-existence" error-code="not-found">
+ <doc> A client MUST NOT be allowed to bind a non-existent queue (i.e. not previously
+ declared) to an exchange. </doc>
+ <doc type="scenario"> A client attempts to bind an undeclared queue name to an exchange.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="exchange" type="name" label="name of the exchange to bind to" required="true">
+ <exception name="exchange-existence" error-code="not-found">
+ <doc> A client MUST NOT be allowed to bind a queue to a non-existent exchange. </doc>
+ <doc type="scenario"> A client attempts to bind a named queue to a undeclared exchange.
+ </doc>
+ </exception>
+
+ <exception name="exchange-name-required" error-code="invalid-argument">
+ <doc> The name of the exchange MUST NOT be a blank or empty string. </doc>
+ </exception>
+ </field>
+
+ <field name="binding-key" type="str8"
+ label="identifies a binding between a given exchange and queue" required="true">
+ <doc> The binding-key uniquely identifies a binding between a given (exchange, queue) pair.
+ Depending on the exchange configuration, the binding key may be matched against the
+ message routing key in order to make routing decisions. The match algorithm depends on the
+ exchange type. Some exchange types may ignore the binding key when making routing
+ decisions. Refer to the specific exchange type documentation. The meaning of an empty
+ binding key depends on the exchange implementation. </doc>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for binding">
+ <doc> A set of arguments for the binding. The syntax and semantics of these arguments
+ depends on the exchange class. </doc>
+
+ <exception name="unknown-argument" error-code="not-implemented">
+ <doc> If the arguments field contains arguments which are not understood by the server, it
+ MUST raise an exception. </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: exchange.unbind - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="unbind" code="0x5" label="unbind a queue from an exchange">
+ <doc>
+ This command unbinds a queue from an exchange.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="queue" type="queue.name" required="true">
+ <doc>
+ Specifies the name of the queue to unbind.
+ </doc>
+ <exception name="non-existent-queue" error-code="not-found">
+ <doc>
+ If the queue does not exist the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="exchange" type="name" required="true">
+ <doc>
+ The name of the exchange to unbind from.
+ </doc>
+
+ <exception name="non-existent-exchange" error-code="not-found">
+ <doc>
+ If the exchange does not exist the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="exchange-name-required" error-code="invalid-argument">
+ <doc>
+ The name of the exchange MUST NOT be a blank or empty string.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="binding-key" type="str8" label="the key of the binding" required="true">
+ <doc>
+ Specifies the binding-key of the binding to unbind.
+ </doc>
+
+ <exception name="non-existent-binding-key" error-code="not-found">
+ <doc>
+ If there is no matching binding-key the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: exchange.bound - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="bound" code="0x6" label="request information about bindings to an exchange">
+ <doc>
+ This command is used to request information on the bindings to a particular exchange.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="exchange" type="str8" label="the exchange name">
+ <doc>
+ The name of the exchange for which binding information is being requested. If not
+ specified explicitly the default exchange is implied.
+ </doc>
+ </field>
+
+ <field name="queue" type="str8" label="a queue name" required="true">
+ <doc>
+ If populated then determine whether the given queue is bound to the exchange.
+ </doc>
+ </field>
+
+ <field name="binding-key" type="str8" label="a binding-key">
+ <doc>
+ If populated defines the binding-key of the binding of interest, if not populated the
+ request will ignore the binding-key on bindings when searching for a match.
+ </doc>
+ </field>
+
+ <field name="arguments" type="map" label="a set of binding arguments">
+ <doc>
+ If populated defines the arguments of the binding of interest if not populated the request
+ will ignore the arguments on bindings when searching for a match
+ </doc>
+ </field>
+
+ <result>
+ <struct name="exchange-bound-result" size="4" code="0x2" pack="2">
+ <field name="exchange-not-found" type="bit" label="indicate an unknown exchange">
+ <doc>
+ If set, the exchange for which information was requested is not known.
+ </doc>
+ </field>
+
+ <field name="queue-not-found" type="bit" label="indicate an unknown queue">
+ <doc>
+ If set, the queue specified is not known.
+ </doc>
+ </field>
+
+ <field name="queue-not-matched" type="bit" label="indicate no matching queue">
+ <doc>
+ A bit which if set indicates that no binding was found from the specified exchange to
+ the specified queue.
+ </doc>
+ </field>
+
+ <field name="key-not-matched" type="bit" label="indicate no matching binding-key">
+ <doc>
+ A bit which if set indicates that no binding was found from the specified exchange
+ with the specified binding-key.
+ </doc>
+ </field>
+
+ <field name="args-not-matched" type="bit" label="indicate no matching arguments">
+ <doc>
+ A bit which if set indicates that no binding was found from the specified exchange
+ with the specified arguments.
+ </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ </class>
+
+ <!-- == Class: queue ========================================================================= -->
+
+ <class name="queue" code="0x8" label="work with queues">
+ <doc>
+ Queues store and forward messages. Queues can be configured in the server or created at
+ runtime. Queues must be attached to at least one exchange in order to receive messages from
+ publishers.
+ </doc>
+
+ <doc type="grammar">
+ queue = C:DECLARE
+ / C:BIND
+ / C:PURGE
+ / C:DELETE
+ / C:QUERY
+ / C:UNBIND
+ </doc>
+
+ <rule name="any-content">
+ <doc>
+ A server MUST allow any content class to be sent to any queue, in any mix, and queue and
+ deliver these content classes independently. Note that all commands that fetch content off
+ queues are specific to a given content class.
+ </doc>
+ <doc type="scenario">
+ Client creates an exchange of each standard type and several queues that it binds to each
+ exchange. It must then successfully send each of the standard content types to each of the
+ available queues.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MUST" />
+ <role name="client" implement="MUST" />
+
+ <domain name="name" type="str8" label="queue name">
+ <doc>
+ The queue name identifies the queue within the virtual host. Queue names must have a length
+ of between 1 and 255 characters inclusive, must start with a digit, letter or underscores
+ ('_') character, and must be otherwise encoded in UTF-8.
+ </doc>
+ </domain>
+
+ <!-- - Command: queue.declare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="declare" code="0x1" label="declare queue">
+ <doc>
+ This command creates or checks a queue. When creating a new queue the client can specify
+ various properties that control the durability of the queue and its contents, and the level
+ of sharing for the queue.
+ </doc>
+
+ <rule name="default-binding">
+ <doc>
+ The server MUST create a default binding for a newly-created queue to the default
+ exchange, which is an exchange of type 'direct' and use the queue name as the binding-key.
+ </doc>
+ <doc type="scenario">
+ Client creates a new queue, and then without explicitly binding it to an exchange,
+ attempts to send a message through the default exchange binding, i.e. publish a message to
+ the empty exchange, with the queue name as binding-key.
+ </doc>
+ </rule>
+
+ <rule name="minimum-queues">
+ <doc>
+ The server SHOULD support a minimum of 256 queues per virtual host and ideally, impose no
+ limit except as defined by available resources.
+ </doc>
+ <doc type="scenario">
+ Client attempts to create as many queues as it can until the server reports an error. The
+ resulting count must at least be 256.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="queue" type="name" required="true">
+ <exception name="reserved-prefix" error-code="not-allowed">
+ <doc>
+ Queue names starting with "amq." are reserved for pre-declared and standardized server
+ queues. A client MUST NOT attempt to declare a queue with a name that starts with "amq."
+ and the passive option set to zero.
+ </doc>
+ <doc type="scenario">
+ A client attempts to create a queue with a name starting with "amq." and with the
+ passive option set to zero.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="alternate-exchange" type="exchange.name"
+ label= "exchange name for messages with exceptions">
+ <doc>
+ The alternate-exchange field specifies how messages on this queue should be treated when
+ they are rejected by a subscriber, or when they are orphaned by queue deletion. When
+ present, rejected or orphaned messages MUST be routed to the alternate-exchange. In all
+ cases the messages MUST be removed from the queue.
+ </doc>
+
+ <exception name="pre-existing-exchange" error-code="not-allowed">
+ <doc>
+ If the alternate-exchange is not empty and if the queue already exists with a different
+ alternate-exchange, then the declaration MUST result in an exception.
+ </doc>
+ </exception>
+
+ <exception name="unknown-exchange" error-code="not-found">
+ <doc>
+ if the alternate-exchange does not match the name of any existing exchange on the
+ server, then an exception must be raised.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="passive" type="bit" label="do not create queue">
+ <doc>
+ If set, the server will not create the queue. This field allows the client to assert the
+ presence of a queue without modifying the server state.
+ </doc>
+
+ <exception name="passive" error-code="not-found">
+ <doc>
+ The client MAY ask the server to assert that a queue exists without creating the queue
+ if not. If the queue does not exist, the server treats this as a failure.
+ </doc>
+ <doc type="scenario">
+ Client declares an existing queue with the passive option and expects the command to
+ succeed. Client then attempts to declare a non-existent queue with the passive option,
+ and the server must close the session with the correct exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="durable" type="bit" label="request a durable queue">
+ <doc>
+ If set when creating a new queue, the queue will be marked as durable. Durable queues
+ remain active when a server restarts. Non-durable queues (transient queues) are purged
+ if/when a server restarts. Note that durable queues do not necessarily hold persistent
+ messages, although it does not make sense to send persistent messages to a transient
+ queue.
+ </doc>
+
+ <rule name="persistence">
+ <doc>
+ The queue definition MUST survive the server losing all transient memory, e.g. a
+ machine restart.
+ </doc>
+ <doc type="scenario">
+ Client creates a durable queue; server is then restarted. Client then attempts to send
+ message to the queue. The message should be successfully delivered.
+ </doc>
+ </rule>
+
+ <rule name="types">
+ <doc>
+ The server MUST support both durable and transient queues.
+ </doc>
+ <doc type="scenario">
+ A client creates two named queues, one durable and one transient.
+ </doc>
+ </rule>
+
+ <rule name="pre-existence">
+ <doc>
+ The server MUST ignore the durable field if the queue already exists.
+ </doc>
+ <doc type="scenario">
+ A client creates two named queues, one durable and one transient. The client then
+ attempts to declare the two queues using the same names again, but reversing the value
+ of the durable flag in each case. Verify that the queues still exist with the original
+ durable flag values.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="exclusive" type="bit" label="request an exclusive queue">
+ <doc>
+ Exclusive queues can only be used from one session at a time. Once a session
+ declares an exclusive queue, that queue cannot be used by any other session until the
+ declaring session closes.
+ </doc>
+
+ <rule name="types">
+ <doc>
+ The server MUST support both exclusive (private) and non-exclusive (shared) queues.
+ </doc>
+ <doc type="scenario">
+ A client creates two named queues, one exclusive and one non-exclusive.
+ </doc>
+ </rule>
+
+ <exception name="in-use" error-code="resource-locked">
+ <doc>
+ If the server receives a declare, bind, consume or get request for a queue that has been
+ declared as exclusive by an existing client session, it MUST raise an exception.
+ </doc>
+ <doc type="scenario">
+ A client declares an exclusive named queue. A second client on a different session
+ attempts to declare a queue of the same name.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="auto-delete" type="bit" label="auto-delete queue when unused">
+ <doc>
+ If this field is set and the exclusive field is also set, then the queue MUST be deleted
+ when the session closes.
+
+ If this field is set and the exclusive field is not set the queue is deleted when all
+ the consumers have finished using it. Last consumer can be cancelled either explicitly
+ or because its session is closed. If there was no consumer ever on the queue, it won't
+ be deleted.
+ </doc>
+
+ <rule name="pre-existence">
+ <doc>
+ The server MUST ignore the auto-delete field if the queue already exists.
+ </doc>
+ <doc type="scenario">
+ A client creates two named queues, one as auto-delete and one explicit-delete. The
+ client then attempts to declare the two queues using the same names again, but reversing
+ the value of the auto-delete field in each case. Verify that the queues still exist with
+ the original auto-delete flag values.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for declaration">
+ <doc>
+ A set of arguments for the declaration. The syntax and semantics of these arguments
+ depends on the server implementation. This field is ignored if passive is 1.
+ </doc>
+
+ <exception name="unknown-argument" error-code="not-implemented">
+ <doc>
+ If the arguments field contains arguments which are not understood by the server,
+ it MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: queue.delete - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="delete" code="0x2" label="delete a queue">
+ <doc>
+ This command deletes a queue. When a queue is deleted any pending messages are sent to the
+ alternate-exchange if defined, or discarded if it is not.
+ </doc>
+
+
+ <implement role="server" handle="MUST" />
+
+ <field name="queue" type="name" required="true">
+ <doc>
+ Specifies the name of the queue to delete.
+ </doc>
+
+ <exception name="empty-name" error-code="invalid-argument">
+ <doc>
+ If the queue name in this command is empty, the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="queue-exists" error-code="not-found">
+ <doc>
+ The queue must exist. If the client attempts to delete a non-existing queue the server
+ MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="if-unused" type="bit" label="delete only if unused">
+ <doc>
+ If set, the server will only delete the queue if it has no consumers. If the queue has
+ consumers the server does does not delete it but raises an exception instead.
+ </doc>
+
+ <exception name="if-unused-flag" error-code="precondition-failed">
+ <doc>
+ The server MUST respect the if-unused flag when deleting a queue.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="if-empty" type="bit" label="delete only if empty">
+ <doc>
+ If set, the server will only delete the queue if it has no messages.
+ </doc>
+ <exception name="not-empty" error-code="precondition-failed">
+ <doc>
+ If the queue is not empty the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: queue.purge - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="purge" code="0x3" label="purge a queue">
+ <doc>
+ This command removes all messages from a queue. It does not cancel subscribers. Purged
+ messages are deleted without any formal "undo" mechanism.
+ </doc>
+
+ <rule name="empty">
+ <doc>
+ A call to purge MUST result in an empty queue.
+ </doc>
+ </rule>
+
+ <rule name="pending-messages">
+ <doc>
+ The server MUST NOT purge messages that have already been sent to a client but not yet
+ accepted.
+ </doc>
+ </rule>
+
+ <rule name="purge-recovery">
+ <doc>
+ The server MAY implement a purge queue or log that allows system administrators to recover
+ accidentally-purged messages. The server SHOULD NOT keep purged messages in the same
+ storage spaces as the live messages since the volumes of purged messages may get very
+ large.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="queue" type="name" required="true">
+ <doc>
+ Specifies the name of the queue to purge.
+ </doc>
+
+ <exception name="empty-name" error-code="invalid-argument">
+ <doc>
+ If the the queue name in this command is empty, the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="queue-exists" error-code="not-found">
+ <doc>
+ The queue MUST exist. Attempting to purge a non-existing queue MUST cause an exception.
+ </doc>
+ </exception>
+ </field>
+ </command>
+
+ <!-- - Command: queue.query - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="query" code="0x4" label="request information about a queue">
+ <doc>
+ This command requests information about a queue.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="queue" type="name" label="the queried queue" required="true"/>
+
+ <result>
+ <struct name="queue-query-result" size="4" code="0x1" pack="2">
+ <doc>
+ This is sent in response to queue.query, and conveys the requested information about a
+ queue. If no queue with the specified name exists then none of the fields within the
+ returned result struct will be populated.
+ </doc>
+
+ <field name="queue" type="name" required="true">
+ <doc>
+ Reports the name of the queue.
+ </doc>
+ </field>
+
+ <field name="alternate-exchange" type="exchange.name" />
+
+ <field name="durable" type="bit" />
+
+ <field name="exclusive" type="bit" />
+
+ <field name="auto-delete" type="bit" />
+
+ <field name="arguments" type="map" />
+
+ <field name="message-count" type="uint32" label="number of messages in queue"
+ required="true">
+ <doc> Reports the number of messages in the queue. </doc>
+ </field>
+
+ <field name="subscriber-count" type="uint32" label="number of subscribers"
+ required="true">
+ <doc>
+ Reports the number of subscribers for the queue.
+ </doc>
+ </field>
+ </struct>
+ </result>
+ </command>
+
+ </class>
+
+ <!-- == Class: file ========================================================================== -->
+
+ <class name="file" code="0x9" label="work with file content">
+ <doc>
+ The file class provides commands that support reliable file transfer. File messages have a
+ specific set of properties that are required for interoperability with file transfer
+ applications. File messages and acknowledgements are subject to session transactions. Note
+ that the file class does not provide message browsing commands; these are not compatible with
+ the staging model. Applications that need browsable file transfer should use Message content
+ and the Message class.
+ </doc>
+
+ <doc type="grammar">
+ file = C:QOS S:QOS-OK
+ / C:CONSUME S:CONSUME-OK
+ / C:CANCEL
+ / C:OPEN S:OPEN-OK C:STAGE content
+ / S:OPEN C:OPEN-OK S:STAGE content
+ / C:PUBLISH
+ / S:DELIVER
+ / S:RETURN
+ / C:ACK
+ / C:REJECT
+ </doc>
+
+ <rule name="reliable-storage">
+ <doc>
+ The server MUST make a best-effort to hold file messages on a reliable storage mechanism.
+ </doc>
+ </rule>
+
+ <rule name="no-discard">
+ <doc>
+ The server MUST NOT discard a file message in case of a queue overflow. The server MUST use
+ the Session.Flow command to slow or stop a file message publisher when necessary.
+ </doc>
+ </rule>
+
+ <rule name="priority-levels">
+ <doc>
+ The server MUST implement at least 2 priority levels for file messages, where priorities 0-4
+ and 5-9 are treated as two distinct levels. The server MAY implement up to 10 priority
+ levels.
+ </doc>
+ </rule>
+
+ <rule name="acknowledgement-support">
+ <doc>
+ The server MUST support both automatic and explicit acknowledgements on file content.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MAY" />
+ <role name="client" implement="MAY" />
+
+ <!-- These are the properties for a File content -->
+ <struct name="file-properties" size="4" code="0x1" pack="2">
+ <field name="content-type" type="str8" label="MIME content type" />
+ <field name="content-encoding" type="str8" label="MIME content encoding" />
+ <field name="headers" type="map" label="message header field table" />
+ <field name="priority" type="uint8" label="message priority, 0 to 9" />
+ <field name="reply-to" type="str8" label="destination to reply to" />
+ <field name="message-id" type="str8" label="application message identifier" />
+ <field name="filename" type="str8" label="message filename" />
+ <field name="timestamp" type="datetime" label="message timestamp" />
+ <!-- This field is deprecated pending review -->
+ <field name="cluster-id" type="str8" label="intra-cluster routing identifier" />
+ </struct>
+
+ <domain name="return-code" type="uint16" label="return code from server">
+ <doc>
+ The return code. The AMQP return codes are defined by this enum.
+ </doc>
+ <enum>
+ <choice name="content-too-large" value="311">
+ <doc>
+ The client attempted to transfer content larger than the server could accept.
+ </doc>
+ </choice>
+
+ <choice name="no-route" value="312">
+ <doc>
+ The exchange cannot route a message, most likely due to an invalid routing key. Only
+ when the mandatory flag is set.
+ </doc>
+ </choice>
+
+ <choice name="no-consumers" value="313">
+ <doc>
+ The exchange cannot deliver to a consumer when the immediate flag is set. As a result of
+ pending data on the queue or the absence of any consumers of the queue.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <!-- - Command: file.qos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="qos" code="0x1" label="specify quality of service">
+ <doc>
+ This command requests a specific quality of service. The QoS can be specified for the
+ current session or for all sessions on the connection. The particular properties and
+ semantics of a qos command always depend on the content class semantics. Though the qos
+ command could in principle apply to both peers, it is currently meaningful only for the
+ server.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <response name="qos-ok" />
+
+ <field name="prefetch-size" type="uint32" label="pre-fetch window in octets">
+ <doc>
+ The client can request that messages be sent in advance so that when the client finishes
+ processing a message, the following message is already held locally, rather than needing
+ to be sent within the session. Pre-fetching gives a performance improvement. This field
+ specifies the pre-fetch window size in octets. May be set to zero, meaning "no specific
+ limit". Note that other pre-fetch limits may still apply. The prefetch-size is ignored if
+ the no-ack option is set.
+ </doc>
+ </field>
+
+ <field name="prefetch-count" type="uint16" label="pre-fetch window in messages">
+ <doc>
+ Specifies a pre-fetch window in terms of whole messages. This is compatible with some file
+ API implementations. This field may be used in combination with the prefetch-size field; a
+ message will only be sent in advance if both pre-fetch windows (and those at the session
+ and connection level) allow it. The prefetch-count is ignored if the no-ack option is set.
+ </doc>
+
+ <rule name="prefetch-discretion">
+ <doc>
+ The server MAY send less data in advance than allowed by the client's specified
+ pre-fetch windows but it MUST NOT send more.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="global" type="bit" label="apply to entire connection">
+ <doc>
+ By default the QoS settings apply to the current session only. If this field is set, they
+ are applied to the entire connection.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: file.qos-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="qos-ok" code="0x2" label="confirm the requested qos">
+ <doc>
+ This command tells the client that the requested QoS levels could be handled by the server.
+ The requested QoS applies to all active consumers until a new QoS is defined.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+ </command>
+
+ <!-- - Command: file.consume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="consume" code="0x3" label="start a queue consumer">
+ <doc>
+ This command asks the server to start a "consumer", which is a transient request for
+ messages from a specific queue. Consumers last as long as the session they were created on,
+ or until the client cancels them.
+ </doc>
+
+ <rule name="min-consumers">
+ <doc>
+ The server SHOULD support at least 16 consumers per queue, unless the queue was declared
+ as private, and ideally, impose no limit except as defined by available resources.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <response name="consume-ok" />
+
+ <field name="queue" type="queue.name">
+ <doc>
+ Specifies the name of the queue to consume from.
+ </doc>
+
+ <exception name="queue-exists-if-empty" error-code="not-allowed">
+ <doc>
+ If the queue name in this command is empty, the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="consumer-tag" type="str8">
+ <doc>
+ Specifies the identifier for the consumer. The consumer tag is local to a connection, so
+ two clients can use the same consumer tags.
+ </doc>
+
+ <exception name="not-existing-consumer" error-code="not-allowed">
+ <doc>
+ The tag MUST NOT refer to an existing consumer. If the client attempts to create two
+ consumers with the same non-empty tag the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-empty-consumer-tag" error-code="not-allowed">
+ <doc>
+ The client MUST NOT specify a tag that is empty or blank.
+ </doc>
+ <doc type="scenario">
+ Attempt to create a consumers with an empty tag.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="no-local" type="bit">
+ <doc>If the no-local field is set the server will not send messages to the connection that
+ published them.</doc>
+ </field>
+
+ <field name="no-ack" type="bit" label="no acknowledgement needed">
+ <doc>
+ If this field is set the server does not expect acknowledgements for messages. That is,
+ when a message is delivered to the client the server automatically and silently
+ acknowledges it on behalf of the client. This functionality increases performance but at
+ the cost of reliability. Messages can get lost if a client dies before it can deliver them
+ to the application.
+ </doc>
+ </field>
+
+ <field name="exclusive" type="bit" label="request exclusive access">
+ <doc>
+ Request exclusive consumer access, meaning only this consumer can access the queue.
+ </doc>
+
+ <exception name="in-use" error-code="resource-locked">
+ <doc>
+ If the server cannot grant exclusive access to the queue when asked, - because there are
+ other consumers active - it MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="nowait" type="bit" label="do not send a reply command">
+ <doc>
+ If set, the server will not respond to the command. The client should not wait for a reply
+ command. If the server could not complete the command it will raise an exception.
+ </doc>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for consuming">
+ <doc>
+ A set of arguments for the consume. The syntax and semantics of these arguments depends on
+ the providers implementation.
+ </doc>
+ </field>
+ </command>
+
+ <command name="consume-ok" code="0x4" label="confirm a new consumer">
+ <doc>
+ This command provides the client with a consumer tag which it MUST use in commands that work
+ with the consumer.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="consumer-tag" type="str8">
+ <doc>
+ Holds the consumer tag specified by the client or provided by the server.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: file.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="cancel" code="0x5" label="end a queue consumer">
+ <doc>
+ This command cancels a consumer. This does not affect already delivered messages, but it
+ does mean the server will not send any more messages for that consumer.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="consumer-tag" type="str8">
+ <doc>
+ the identifier of the consumer to be cancelled.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: file.open - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="open" code="0x6" label="request to start staging">
+ <doc>
+ This command requests permission to start staging a message. Staging means sending the
+ message into a temporary area at the recipient end and then delivering the message by
+ referring to this temporary area. Staging is how the protocol handles partial file transfers
+ - if a message is partially staged and the connection breaks, the next time the sender
+ starts to stage it, it can restart from where it left off.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <response name="open-ok" />
+
+ <field name="identifier" type="str8" label="staging identifier">
+ <doc>
+ This is the staging identifier. This is an arbitrary string chosen by the sender. For
+ staging to work correctly the sender must use the same staging identifier when staging the
+ same message a second time after recovery from a failure. A good choice for the staging
+ identifier would be the SHA1 hash of the message properties data (including the original
+ filename, revised time, etc.).
+ </doc>
+ </field>
+
+ <field name="content-size" type="uint64" label="message content size">
+ <doc>
+ The size of the content in octets. The recipient may use this information to allocate or
+ check available space in advance, to avoid "disk full" errors during staging of very large
+ messages.
+ </doc>
+
+ <rule name="content-size">
+ <doc>
+ The sender MUST accurately fill the content-size field. Zero-length content is
+ permitted.
+ </doc>
+ </rule>
+ </field>
+ </command>
+
+ <!-- - Command: file.open-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="open-ok" code="0x7" label="confirm staging ready">
+ <doc>
+ This command confirms that the recipient is ready to accept staged data. If the message was
+ already partially-staged at a previous time the recipient will report the number of octets
+ already staged.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <response name="stage" />
+
+ <field name="staged-size" type="uint64" label="already staged amount">
+ <doc>
+ The amount of previously-staged content in octets. For a new message this will be zero.
+ </doc>
+
+ <rule name="behavior">
+ <doc>
+ The sender MUST start sending data from this octet offset in the message, counting from
+ zero.
+ </doc>
+ </rule>
+
+ <rule name="staging">
+ <doc>
+ The recipient MAY decide how long to hold partially-staged content and MAY implement
+ staging by always discarding partially-staged content. However if it uses the file
+ content type it MUST support the staging commands.
+ </doc>
+ </rule>
+ </field>
+ </command>
+
+ <!-- - Command: file.stage - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="stage" code="0x8" label="stage message content">
+ <doc>
+ This command stages the message, sending the message content to the recipient from the octet
+ offset specified in the Open-Ok command.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+ <implement role="client" handle="MUST" />
+
+ <segments>
+ <header required="true">
+ <entry type="file-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ <!-- - Command: file.publish - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="publish" code="0x9" label="publish a message">
+ <doc>
+ This command publishes a staged file message to a specific exchange. The file message will
+ be routed to queues as defined by the exchange configuration and distributed to any active
+ consumers when the transaction, if any, is committed.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange to publish to. The exchange name can be empty, meaning
+ the default exchange. If the exchange name is specified, and that exchange does not exist,
+ the server will raise an exception.
+ </doc>
+
+ <rule name="default">
+ <doc>
+ The server MUST accept a blank exchange name to mean the default exchange.
+ </doc>
+ </rule>
+
+ <exception name="refusal" error-code="not-implemented">
+ <doc>
+ The exchange MAY refuse file content in which case it MUST send an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="routing-key" type="str8" label="Message routing key">
+ <doc>
+ Specifies the routing key for the message. The routing key is used for routing messages
+ depending on the exchange configuration.
+ </doc>
+ </field>
+
+ <field name="mandatory" type="bit" label="indicate mandatory routing">
+ <doc>
+ This flag tells the server how to react if the message cannot be routed to a queue. If
+ this flag is set, the server will return an unroutable message with a Return command. If
+ this flag is zero, the server silently drops the message.
+ </doc>
+
+ <rule name="implementation">
+ <doc>
+ The server SHOULD implement the mandatory flag.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="immediate" type="bit" label="request immediate delivery">
+ <doc>
+ This flag tells the server how to react if the message cannot be routed to a queue
+ consumer immediately. If this flag is set, the server will return an undeliverable message
+ with a Return command. If this flag is zero, the server will queue the message, but with
+ no guarantee that it will ever be consumed.
+ </doc>
+
+ <rule name="implementation">
+ <doc>
+ The server SHOULD implement the immediate flag.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="identifier" type="str8" label="staging identifier">
+ <doc>
+ This is the staging identifier of the message to publish. The message must have been
+ staged. Note that a client can send the Publish command asynchronously without waiting for
+ staging to finish.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: file.return - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="return" code="0xa" label="return a failed message">
+ <doc>
+ This command returns an undeliverable message that was published with the "immediate" flag
+ set, or an unroutable message published with the "mandatory" flag set. The reply code and
+ text provide information about the reason that the message was undeliverable.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="reply-code" type="return-code" />
+
+ <field name="reply-text" type="str8" label="The localized reply text.">
+ <doc>
+ This text can be logged as an aid to resolving issues.
+ </doc>
+ </field>
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange that the message was originally published to.
+ </doc>
+ </field>
+
+ <field name="routing-key" type="str8" label="Message routing key">
+ <doc>
+ Specifies the routing key name specified when the message was published.
+ </doc>
+ </field>
+
+ <segments>
+ <header required="true">
+ <entry type="file-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ <!-- - Command: file.deliver - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="deliver" code="0xb" label="notify the client of a consumer message">
+ <doc>
+ This command delivers a staged file message to the client, via a consumer. In the
+ asynchronous message delivery model, the client starts a consumer using the consume command,
+ then the server responds with Deliver commands as and when messages arrive for that
+ consumer.
+ </doc>
+
+ <rule name="redelivery-tracking">
+ <doc>
+ The server SHOULD track the number of times a message has been delivered to clients and
+ when a message is redelivered a certain number of times - e.g. 5 times - without being
+ acknowledged, the server SHOULD consider the message to be non-processable (possibly
+ causing client applications to abort), and move the message to a dead letter queue.
+ </doc>
+ </rule>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="consumer-tag" type="str8" />
+
+ <field name="delivery-tag" type="uint64" >
+ <doc>
+ The server-assigned and session-specific delivery tag
+ </doc>
+
+ <rule name="non-zero">
+ <doc>
+ The server MUST NOT use a zero value for delivery tags. Zero is reserved for client use,
+ meaning "all messages so far received".
+ </doc>
+ </rule>
+ </field>
+
+ <field name="redelivered" type="bit" label="Indicate possible duplicate delivery">
+ <doc>
+ This boolean flag indicates that the message may have been previously delivered to this
+ or another client.
+ </doc>
+ </field>
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange that the message was originally published to.
+ </doc>
+ </field>
+
+ <field name="routing-key" type="str8" label="Message routing key">
+ <doc>
+ Specifies the routing key name specified when the message was published.
+ </doc>
+ </field>
+
+ <field name="identifier" type="str8" label="staging identifier">
+ <doc>
+ This is the staging identifier of the message to deliver. The message must have been
+ staged. Note that a server can send the Deliver command asynchronously without waiting for
+ staging to finish.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: file.ack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="ack" code="0xc" label="acknowledge one or more messages">
+ <doc>
+ This command acknowledges one or more messages delivered via the Deliver command. The client
+ can ask to confirm a single message or a set of messages up to and including a specific
+ message.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="delivery-tag" type="uint64" >
+ <doc>
+ The identifier of the message being acknowledged
+ </doc>
+ <rule name="session-local">
+ <doc>
+ The delivery tag is valid only within the session from which the message was received.
+ i.e. A client MUST NOT receive a message on one session and then acknowledge it on
+ another.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="multiple" type="bit" label="acknowledge multiple messages">
+ <doc>
+ If set to 1, the delivery tag is treated as "up to and including", so that the client can
+ acknowledge multiple messages with a single command. If set to zero, the delivery tag
+ refers to a single message. If the multiple field is 1, and the delivery tag is zero,
+ tells the server to acknowledge all outstanding messages.
+ </doc>
+
+ <rule name="validation">
+ <doc>
+ The server MUST validate that a non-zero delivery-tag refers to an delivered message,
+ and raise an exception if this is not the case.
+ </doc>
+ </rule>
+ </field>
+ </command>
+
+ <!-- - Command: file.reject - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="reject" code="0xd" label="reject an incoming message">
+ <doc>
+ This command allows a client to reject a message. It can be used to return untreatable
+ messages to their original queue. Note that file content is staged before delivery, so the
+ client will not use this command to interrupt delivery of a large message.
+ </doc>
+
+ <rule name="server-interpretation">
+ <doc>
+ The server SHOULD interpret this command as meaning that the client is unable to process
+ the message at this time.
+ </doc>
+ </rule>
+
+ <rule name="not-selection">
+ <doc>
+ A client MUST NOT use this command as a means of selecting messages to process. A rejected
+ message MAY be discarded or dead-lettered, not necessarily passed to another client.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="delivery-tag" type="uint64">
+ <doc>
+ the identifier of the message to be rejected
+ </doc>
+ <rule name="session-local">
+ <doc>
+ The delivery tag is valid only within the session from which the message was received.
+ i.e. A client MUST NOT receive a message on one session and then reject it on another.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="requeue" type="bit" label="requeue the message">
+ <doc>
+ If this field is zero, the message will be discarded. If this bit is 1, the server will
+ attempt to requeue the message.
+ </doc>
+
+ <rule name="requeue-strategy">
+ <doc>
+ The server MUST NOT deliver the message to the same client within the context of the
+ current session. The recommended strategy is to attempt to deliver the message to an
+ alternative consumer, and if that is not possible, to move the message to a dead-letter
+ queue. The server MAY use more sophisticated tracking to hold the message on the queue
+ and redeliver it to the same client at a later stage.
+ </doc>
+ </rule>
+ </field>
+ </command>
+
+ </class>
+
+ <!-- == Class: stream ======================================================================== -->
+
+ <class name="stream" code="0xa" label="work with streaming content">
+ <doc>
+ The stream class provides commands that support multimedia streaming. The stream class uses
+ the following semantics: one message is one packet of data; delivery is unacknowledged and
+ unreliable; the consumer can specify quality of service parameters that the server can try to
+ adhere to; lower-priority messages may be discarded in favor of high priority messages.
+ </doc>
+
+ <doc type="grammar">
+ stream = C:QOS S:QOS-OK
+ / C:CONSUME S:CONSUME-OK
+ / C:CANCEL
+ / C:PUBLISH content
+ / S:RETURN
+ / S:DELIVER content
+ </doc>
+
+ <rule name="overflow-discard">
+ <doc>
+ The server SHOULD discard stream messages on a priority basis if the queue size exceeds some
+ configured limit.
+ </doc>
+ </rule>
+
+ <rule name="priority-levels">
+ <doc>
+ The server MUST implement at least 2 priority levels for stream messages, where priorities
+ 0-4 and 5-9 are treated as two distinct levels. The server MAY implement up to 10 priority
+ levels.
+ </doc>
+ </rule>
+
+ <rule name="acknowledgement-support">
+ <doc>
+ The server MUST implement automatic acknowledgements on stream content. That is, as soon as
+ a message is delivered to a client via a Deliver command, the server must remove it from the
+ queue.
+ </doc>
+ </rule>
+
+ <role name="server" implement="MAY" />
+ <role name="client" implement="MAY" />
+
+ <!-- These are the properties for a Stream content -->
+ <struct name="stream-properties" size="4" code="0x1" pack="2">
+ <field name="content-type" type="str8" label="MIME content type" />
+ <field name="content-encoding" type="str8" label="MIME content encoding" />
+ <field name="headers" type="map" label="message header field table" />
+ <field name="priority" type="uint8" label="message priority, 0 to 9" />
+ <field name="timestamp" type="datetime" label="message timestamp" />
+ </struct>
+
+ <domain name="return-code" type="uint16" label="return code from server">
+ <doc>
+ The return code. The AMQP return codes are defined by this enum.
+ </doc>
+ <enum>
+ <choice name="content-too-large" value="311">
+ <doc>
+ The client attempted to transfer content larger than the server could accept.
+ </doc>
+ </choice>
+
+ <choice name="no-route" value="312">
+ <doc>
+ The exchange cannot route a message, most likely due to an invalid routing key. Only
+ when the mandatory flag is set.
+ </doc>
+ </choice>
+
+ <choice name="no-consumers" value="313">
+ <doc>
+ The exchange cannot deliver to a consumer when the immediate flag is set. As a result of
+ pending data on the queue or the absence of any consumers of the queue.
+ </doc>
+ </choice>
+ </enum>
+ </domain>
+
+ <!-- - Command: stream.qos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="qos" code="0x1" label="specify quality of service">
+ <doc>
+ This command requests a specific quality of service. The QoS can be specified for the
+ current session or for all sessions on the connection. The particular properties and
+ semantics of a qos command always depend on the content class semantics. Though the qos
+ command could in principle apply to both peers, it is currently meaningful only for the
+ server.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <response name="qos-ok" />
+
+ <field name="prefetch-size" type="uint32" label="pre-fetch window in octets">
+ <doc>
+ The client can request that messages be sent in advance so that when the client finishes
+ processing a message, the following message is already held locally, rather than needing
+ to be sent within the session. Pre-fetching gives a performance improvement. This field
+ specifies the pre-fetch window size in octets. May be set to zero, meaning "no specific
+ limit". Note that other pre-fetch limits may still apply.
+ </doc>
+ </field>
+
+ <field name="prefetch-count" type="uint16" label="pre-fetch window in messages">
+ <doc>
+ Specifies a pre-fetch window in terms of whole messages. This field may be used in
+ combination with the prefetch-size field; a message will only be sent in advance if both
+ pre-fetch windows (and those at the session and connection level) allow it.
+ </doc>
+ </field>
+
+ <field name="consume-rate" type="uint32" label="transfer rate in octets/second">
+ <doc>
+ Specifies a desired transfer rate in octets per second. This is usually determined by the
+ application that uses the streaming data. A value of zero means "no limit", i.e. as
+ rapidly as possible.
+ </doc>
+
+ <rule name="ignore-prefetch">
+ <doc>
+ The server MAY ignore the pre-fetch values and consume rates, depending on the type of
+ stream and the ability of the server to queue and/or reply it.
+ </doc>
+ </rule>
+
+ <rule name="drop-by-priority">
+ <doc>
+ The server MAY drop low-priority messages in favor of high-priority messages.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="global" type="bit" label="apply to entire connection">
+ <doc>
+ By default the QoS settings apply to the current session only. If this field is set, they
+ are applied to the entire connection.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: stream.qos-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="qos-ok" code="0x2" label="confirm the requested qos">
+ <doc>
+ This command tells the client that the requested QoS levels could be handled by the server.
+ The requested QoS applies to all active consumers until a new QoS is defined.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+ </command>
+
+ <!-- - Command: stream.consume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="consume" code="0x3" label="start a queue consumer">
+ <doc>
+ This command asks the server to start a "consumer", which is a transient request for
+ messages from a specific queue. Consumers last as long as the session they were created on,
+ or until the client cancels them.
+ </doc>
+
+ <rule name="min-consumers">
+ <doc>
+ The server SHOULD support at least 16 consumers per queue, unless the queue was declared
+ as private, and ideally, impose no limit except as defined by available resources.
+ </doc>
+ </rule>
+
+ <rule name="priority-based-delivery">
+ <doc>
+ Streaming applications SHOULD use different sessions to select different streaming
+ resolutions. AMQP makes no provision for filtering and/or transforming streams except on
+ the basis of priority-based selective delivery of individual messages.
+ </doc>
+ </rule>
+
+ <implement role="server" handle="MUST" />
+
+ <response name="consume-ok" />
+
+ <field name="queue" type="queue.name">
+ <doc>
+ Specifies the name of the queue to consume from.
+ </doc>
+
+ <exception name="queue-exists-if-empty" error-code="not-allowed">
+ <doc>
+ If the queue name in this command is empty, the server MUST raise an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="consumer-tag" type="str8">
+ <doc>
+ Specifies the identifier for the consumer. The consumer tag is local to a connection, so
+ two clients can use the same consumer tags.
+ </doc>
+
+ <exception name="not-existing-consumer" error-code="not-allowed">
+ <doc>
+ The tag MUST NOT refer to an existing consumer. If the client attempts to create two
+ consumers with the same non-empty tag the server MUST raise an exception.
+ </doc>
+ </exception>
+
+ <exception name="not-empty-consumer-tag" error-code="not-allowed">
+ <doc>
+ The client MUST NOT specify a tag that is empty or blank.
+ </doc>
+ <doc type="scenario">
+ Attempt to create a consumers with an empty tag.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="no-local" type="bit">
+ <doc>If the no-local field is set the server will not send messages to the connection that
+ published them.</doc>
+ </field>
+
+ <field name="exclusive" type="bit" label="request exclusive access">
+ <doc>
+ Request exclusive consumer access, meaning only this consumer can access the queue.
+ </doc>
+
+ <exception name="in-use" error-code="resource-locked">
+ <doc>
+ If the server cannot grant exclusive access to the queue when asked, - because there are
+ other consumers active - it MUST raise an exception with return code 405
+ (resource locked).
+ </doc>
+ </exception>
+ </field>
+
+ <field name="nowait" type="bit" label="do not send a reply command">
+ <doc>
+ If set, the server will not respond to the command. The client should not wait for a reply
+ command. If the server could not complete the command it will raise an exception.
+ </doc>
+ </field>
+
+ <field name="arguments" type="map" label="arguments for consuming">
+ <doc>
+ A set of arguments for the consume. The syntax and semantics of these arguments depends on
+ the providers implementation.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: stream.consume-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="consume-ok" code="0x4" label="confirm a new consumer">
+ <doc>
+ This command provides the client with a consumer tag which it may use in commands that work
+ with the consumer.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="consumer-tag" type="str8">
+ <doc>
+ Holds the consumer tag specified by the client or provided by the server.
+ </doc>
+ </field>
+ </command>
+
+ <!-- - Command: stream.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="cancel" code="0x5" label="end a queue consumer">
+ <doc>
+ This command cancels a consumer. Since message delivery is asynchronous the client may
+ continue to receive messages for a short while after cancelling a consumer. It may process
+ or discard these as appropriate.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="consumer-tag" type="str8" />
+ </command>
+
+ <!-- - Command: stream.publish - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="publish" code="0x6" label="publish a message">
+ <doc>
+ This command publishes a message to a specific exchange. The message will be routed to
+ queues as defined by the exchange configuration and distributed to any active consumers as
+ appropriate.
+ </doc>
+
+ <implement role="server" handle="MUST" />
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange to publish to. The exchange name can be empty, meaning
+ the default exchange. If the exchange name is specified, and that exchange does not exist,
+ the server will raise an exception.
+ </doc>
+
+ <rule name="default">
+ <doc>
+ The server MUST accept a blank exchange name to mean the default exchange.
+ </doc>
+ </rule>
+
+ <exception name="refusal" error-code="not-implemented">
+ <doc>
+ The exchange MAY refuse stream content in which case it MUST respond with an exception.
+ </doc>
+ </exception>
+ </field>
+
+ <field name="routing-key" type="str8" label="Message routing key">
+ <doc>
+ Specifies the routing key for the message. The routing key is used for routing messages
+ depending on the exchange configuration.
+ </doc>
+ </field>
+
+ <field name="mandatory" type="bit" label="indicate mandatory routing">
+ <doc>
+ This flag tells the server how to react if the message cannot be routed to a queue. If
+ this flag is set, the server will return an unroutable message with a Return command. If
+ this flag is zero, the server silently drops the message.
+ </doc>
+
+ <rule name="implementation">
+ <doc>
+ The server SHOULD implement the mandatory flag.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="immediate" type="bit" label="request immediate delivery">
+ <doc>
+ This flag tells the server how to react if the message cannot be routed to a queue
+ consumer immediately. If this flag is set, the server will return an undeliverable message
+ with a Return command. If this flag is zero, the server will queue the message, but with
+ no guarantee that it will ever be consumed.
+ </doc>
+
+ <rule name="implementation">
+ <doc>
+ The server SHOULD implement the immediate flag.
+ </doc>
+ </rule>
+ </field>
+
+ <segments>
+ <header required="true">
+ <entry type="stream-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ <!-- - Command: stream.return - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="return" code="0x7" label="return a failed message">
+ <doc>
+ This command returns an undeliverable message that was published with the "immediate" flag
+ set, or an unroutable message published with the "mandatory" flag set. The reply code and
+ text provide information about the reason that the message was undeliverable.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="reply-code" type="return-code" />
+
+ <field name="reply-text" type="str8" label="The localized reply text.">
+ <doc>
+ The localized reply text. This text can be logged as an aid to resolving issues.
+ </doc>
+ </field>
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange that the message was originally published to.
+ </doc>
+ </field>
+
+ <field name="routing-key" type="str8" label="Message routing key">
+ <doc>
+ Specifies the routing key name specified when the message was published.
+ </doc>
+ </field>
+
+ <segments>
+ <header required="true">
+ <entry type="stream-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ <!-- - Command: stream.deliver - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <command name="deliver" code="0x8" label="notify the client of a consumer message">
+ <doc>
+ This command delivers a message to the client, via a consumer. In the asynchronous message
+ delivery model, the client starts a consumer using the Consume command, then the server
+ responds with Deliver commands as and when messages arrive for that consumer.
+ </doc>
+
+ <implement role="client" handle="MUST" />
+
+ <field name="consumer-tag" type="str8" />
+
+ <field name="delivery-tag" type="uint64">
+ <doc>
+ The server-assigned and session-specific delivery tag
+ </doc>
+ <rule name="session-local">
+ <doc>
+ The delivery tag is valid only within the session from which the message was received.
+ i.e. A client MUST NOT receive a message on one session and then acknowledge it on
+ another.
+ </doc>
+ </rule>
+ </field>
+
+ <field name="exchange" type="exchange.name">
+ <doc>
+ Specifies the name of the exchange that the message was originally published to.
+ </doc>
+ </field>
+
+ <field name="queue" type="queue.name" required="true">
+ <doc>
+ Specifies the name of the queue that the message came from. Note that a single session can
+ start many consumers on different queues.
+ </doc>
+ </field>
+
+ <segments>
+ <header required="true">
+ <entry type="stream-properties"/>
+ </header>
+ <body/>
+ </segments>
+ </command>
+
+ </class>
+
+</amqp>
diff --git a/ruby/lib/qpid/specs/amqp.0-10.dtd b/ruby/lib/qpid/specs/amqp.0-10.dtd
new file mode 100644
index 0000000000..2be198525a
--- /dev/null
+++ b/ruby/lib/qpid/specs/amqp.0-10.dtd
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright Notice
+ ================
+ (c) Copyright Cisco Systems, Credit Suisse, Deutsche Börse Systems, Envoy Technologies, Inc.,
+ Goldman Sachs, IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A,
+ Novell, Rabbit Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc
+ 2006, 2007. All rights reserved.
+
+ License
+ =======
+ JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix Corporation, IONA
+ Technologies, Red Hat, Inc., TWIST Process Innovations, and 29West Inc. (collectively, the
+ "Authors") each hereby grants to you a worldwide, perpetual, royalty-free, nontransferable,
+ nonexclusive license to (i) copy, display, distribute and implement the Advanced Messaging Queue
+ Protocol ("AMQP") Specification and (ii) the Licensed Claims that are held by the Authors, all for
+ the purpose of implementing the Advanced Messaging Queue Protocol Specification. Your license and
+ any rights under this Agreement will terminate immediately without notice from any Author if you
+ bring any claim, suit, demand, or action related to the Advanced Messaging Queue Protocol
+ Specification against any Author. Upon termination, you shall destroy all copies of the Advanced
+ Messaging Queue Protocol Specification in your possession or control.
+
+ As used hereunder, "Licensed Claims" means those claims of a patent or patent application,
+ throughout the world, excluding design patents and design registrations, owned or controlled, or
+ that can be sublicensed without fee and in compliance with the requirements of this Agreement, by
+ an Author or its affiliates now or at any future time and which would necessarily be infringed by
+ implementation of the Advanced Messaging Queue Protocol Specification. A claim is necessarily
+ infringed hereunder only when it is not possible to avoid infringing it because there is no
+ plausible non-infringing alternative for implementing the required portions of the Advanced
+ Messaging Queue Protocol Specification. Notwithstanding the foregoing, Licensed Claims shall not
+ include any claims other than as set forth above even if contained in the same patent as Licensed
+ Claims; or that read solely on any implementations of any portion of the Advanced Messaging Queue
+ Protocol Specification that are not required by the Advanced Messaging Queue Protocol
+ Specification, or that, if licensed, would require a payment of royalties by the licensor to
+ unaffiliated third parties. Moreover, Licensed Claims shall not include (i) any enabling
+ technologies that may be necessary to make or use any Licensed Product but are not themselves
+ expressly set forth in the Advanced Messaging Queue Protocol Specification (e.g., semiconductor
+ manufacturing technology, compiler technology, object oriented technology, networking technology,
+ operating system technology, and the like); or (ii) the implementation of other published
+ standards developed elsewhere and merely referred to in the body of the Advanced Messaging Queue
+ Protocol Specification, or (iii) any Licensed Product and any combinations thereof the purpose or
+ function of which is not required for compliance with the Advanced Messaging Queue Protocol
+ Specification. For purposes of this definition, the Advanced Messaging Queue Protocol
+ Specification shall be deemed to include both architectural and interconnection requirements
+ essential for interoperability and may also include supporting source code artifacts where such
+ architectural, interconnection requirements and source code artifacts are expressly identified as
+ being required or documentation to achieve compliance with the Advanced Messaging Queue Protocol
+ Specification.
+
+ As used hereunder, "Licensed Products" means only those specific portions of products (hardware,
+ software or combinations thereof) that implement and are compliant with all relevant portions of
+ the Advanced Messaging Queue Protocol Specification.
+
+ The following disclaimers, which you hereby also acknowledge as to any use you may make of the
+ Advanced Messaging Queue Protocol Specification:
+
+ THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
+ REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS
+ OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
+ IMPLEMENTATION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD
+ PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF OR RELATING TO ANY USE, IMPLEMENTATION OR OF THE ADVANCED
+ MESSAGING QUEUE PROTOCOL SPECIFICATION.
+
+ The name and trademarks of the Authors may NOT be used in any manner, including advertising or
+ publicity pertaining to the Advanced Messaging Queue Protocol Specification or its contents
+ without specific, written prior permission. Title to copyright in the Advanced Messaging Queue
+ Protocol Specification will at all times remain with the Authors.
+
+ No other rights are granted by implication, estoppel or otherwise.
+
+ Upon termination of your license or rights under this Agreement, you shall destroy all copies of
+ the Advanced Messaging Queue Protocol Specification in your possession or control.
+
+ Trademarks
+ ==========
+ "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the Octagon Symbol are
+ trademarks of JPMorgan Chase & Co.
+
+ IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
+
+ IONA, IONA Technologies, and the IONA logos are trademarks of IONA Technologies PLC and/or its
+ subsidiaries.
+
+ LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered trademarks of Red Hat,
+ Inc. in the US and other countries.
+
+ Java, all Java-based trademarks and OpenOffice.org are trademarks of Sun Microsystems, Inc. in the
+ United States, other countries, or both.
+
+ Other company, product, or service names may be trademarks or service marks of others.
+
+ Links to full AMQP specification:
+ =================================
+ http://www.envoytech.org/spec/amq/
+ http://www.iona.com/opensource/amqp/
+ http://www.redhat.com/solutions/specifications/amqp/
+ http://www.twiststandards.org/tiki-index.php?page=AMQ
+ http://www.imatix.com/amqp
+-->
+
+<!ELEMENT amqp (doc|type|struct|domain|constant|class)*>
+<!ATTLIST amqp
+ xmlns CDATA #IMPLIED
+ major CDATA #REQUIRED
+ minor CDATA #REQUIRED
+ port CDATA #REQUIRED
+ comment CDATA #IMPLIED
+>
+
+<!ELEMENT constant (doc|rule)*>
+<!ATTLIST constant
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT type (doc|rule)*>
+<!ATTLIST type
+ name CDATA #REQUIRED
+ label CDATA #IMPLIED
+ code CDATA #IMPLIED
+ fixed-width CDATA #IMPLIED
+ variable-width CDATA #IMPLIED
+>
+
+<!ELEMENT domain (doc|rule|enum)*>
+<!ATTLIST domain
+ name CDATA #REQUIRED
+ type CDATA #IMPLIED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT struct (field|doc|rule)*>
+<!ATTLIST struct
+ name CDATA #REQUIRED
+ label CDATA #IMPLIED
+ size (0|1|2|4) #IMPLIED
+ pack (0|1|2|4) #IMPLIED
+ code CDATA #IMPLIED>
+
+<!ELEMENT enum (choice)*>
+
+<!ELEMENT choice (doc|rule)*>
+<!ATTLIST choice
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED
+>
+
+<!ELEMENT class (doc|role|rule|struct|domain|control|command)*>
+<!ATTLIST class
+ name CDATA #REQUIRED
+ code CDATA #REQUIRED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT role (doc|rule)*>
+<!ATTLIST role
+ name CDATA #REQUIRED
+ implement (MAY|SHOULD|MUST) #REQUIRED
+>
+
+<!ELEMENT control (doc|implement|rule|field|response)*>
+<!ATTLIST control
+ name CDATA #REQUIRED
+ code CDATA #REQUIRED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT command ((doc|implement|rule|exception|field|response)*, result?, segments?)>
+<!ATTLIST command
+ name CDATA #REQUIRED
+ code CDATA #REQUIRED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT implement (doc|rule)*>
+<!ATTLIST implement
+ role CDATA #REQUIRED
+ handle (MAY|SHOULD|MUST) #REQUIRED
+ send (MAY|SHOULD|MUST) #IMPLIED
+>
+
+<!ELEMENT field (doc|rule|exception)*>
+<!ATTLIST field
+ name CDATA #REQUIRED
+ type CDATA #IMPLIED
+ default CDATA #IMPLIED
+ code CDATA #IMPLIED
+ label CDATA #IMPLIED
+ required CDATA #IMPLIED
+>
+
+<!ELEMENT rule (doc*)>
+<!ATTLIST rule
+ name CDATA #REQUIRED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT exception (doc*)>
+<!ATTLIST exception
+ name CDATA #REQUIRED
+ error-code CDATA #IMPLIED
+ label CDATA #IMPLIED
+>
+
+<!ELEMENT response (doc|rule)*>
+<!ATTLIST response
+ name CDATA #IMPLIED
+>
+
+<!ELEMENT result (doc|rule|struct)*>
+<!ATTLIST result
+ type CDATA #IMPLIED
+>
+
+<!ELEMENT segments (doc|rule|header|body)*>
+
+<!ELEMENT header (doc|rule|entry)*>
+<!ATTLIST header
+ required (true|false) #IMPLIED
+>
+
+<!ELEMENT entry (doc|rule)*>
+<!ATTLIST entry
+ type CDATA #REQUIRED
+>
+
+<!ELEMENT body (doc|rule)*>
+<!ATTLIST body
+ required (true|false) #IMPLIED
+>
+
+<!ELEMENT doc (#PCDATA|xref)*>
+<!ATTLIST doc
+ type (grammar|scenario|picture|bnf|todo) #IMPLIED
+ title CDATA #IMPLIED
+>
+
+<!ELEMENT xref (#PCDATA)>
+<!ATTLIST xref
+ ref CDATA #REQUIRED>
diff --git a/ruby/lib/qpid/test.rb b/ruby/lib/qpid/test.rb
new file mode 100644
index 0000000000..2e643f4348
--- /dev/null
+++ b/ruby/lib/qpid/test.rb
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require "qpid/spec08"
+require "qpid/client"
+
+module Qpid08
+
+ module Test
+
+ def connect()
+ spec = Spec.load("../specs/amqp.0-8.xml")
+ c = Client.new("0.0.0.0", 5672, spec)
+ c.start({"LOGIN" => "guest", "PASSWORD" => "guest"})
+ return c
+ end
+
+ end
+
+end
diff --git a/ruby/lib/qpid/traverse.rb b/ruby/lib/qpid/traverse.rb
new file mode 100644
index 0000000000..67358a7eb1
--- /dev/null
+++ b/ruby/lib/qpid/traverse.rb
@@ -0,0 +1,64 @@
+#
+# 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.
+#
+
+class Object
+
+ public
+
+ def traverse()
+ traverse! {|o| yield(o); o}
+ end
+
+ def traverse_children!()
+ instance_variables.each {|v|
+ value = instance_variable_get(v)
+ replacement = yield(value)
+ instance_variable_set(v, replacement) unless replacement.equal? value
+ }
+ end
+
+ def traverse!(replacements = {})
+ return replacements[__id__] if replacements.has_key? __id__
+ replacement = yield(self)
+ replacements[__id__] = replacement
+ traverse_children! {|o| o.traverse!(replacements) {|c| yield(c)}}
+ return replacement
+ end
+
+end
+
+class Array
+ def traverse_children!()
+ map! {|o| yield(o)}
+ end
+end
+
+class Hash
+ def traverse_children!()
+ mods = {}
+ each_pair {|k, v|
+ key = yield(k)
+ value = yield(v)
+ mods[key] = value unless key.equal? k and value.equal? v
+ delete(k) unless key.equal? k
+ }
+
+ merge!(mods)
+ end
+end
diff --git a/ruby/lib/qpid/util.rb b/ruby/lib/qpid/util.rb
new file mode 100644
index 0000000000..2dbc37da09
--- /dev/null
+++ b/ruby/lib/qpid/util.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.
+#
+
+require 'thread'
+require 'monitor'
+
+# Monkeypatch
+class MonitorMixin::ConditionVariable
+
+ # Wait until BLOCK returns TRUE or TIMEOUT seconds have passed
+ # Return TRUE if BLOCK returned TRUE within the TIMEOUT, FALSE
+ # otherswise
+ def wait_for(timeout=nil, &block)
+ start = Time.now
+ passed = 0
+ until yield
+ if timeout.nil?
+ wait
+ elsif passed < timeout
+ wait(timeout)
+ else
+ return false
+ end
+ passed = Time.now - start
+ end
+ return true
+ end
+end
+
+module Qpid::Util
+
+ # Similar to Python's threading.Event
+ class Event
+ def initialize
+ @monitor = Monitor.new
+ @cond = @monitor.new_cond
+ @set = false
+ end
+
+ def set
+ @monitor.synchronize do
+ @set = true
+ @cond.signal
+ end
+ end
+
+ def clear
+ @monitor.synchronize { @set = false }
+ end
+
+ def wait(timeout = nil)
+ @monitor.synchronize do
+ unless @set
+ @cond.wait_for(timeout) { @set }
+ end
+ end
+ end
+ end
+end
diff --git a/ruby/tests/assembler.rb b/ruby/tests/assembler.rb
new file mode 100644
index 0000000000..1181ece547
--- /dev/null
+++ b/ruby/tests/assembler.rb
@@ -0,0 +1,78 @@
+#
+# 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 "test/unit"
+require "qpid"
+require 'tests/util'
+
+require 'logger'
+
+class TestAssembler< Test::Unit::TestCase
+
+ Segment = Qpid::Segment
+ Assembler = Qpid::Assembler
+
+ def setup
+ # Qpid::asm_logger = Logger.new(STDOUT)
+
+ @server = Util::ServerThread.new do |socket|
+ asm = Assembler.new(socket)
+ begin
+ header = asm.read_header
+ asm.write_header(header[-2], header[-1])
+ loop do
+ seg = asm.read_segment
+ asm.write_segment(seg)
+ end
+ rescue Qpid::Closed
+ nil # Ignore
+ end
+ end
+ end
+
+ def teardown
+ @server.finish
+ @server.join
+ end
+
+ def test_assembler
+ asm = Assembler.new(@server.client, max_payload = 1)
+ asm.write_header(0, 10)
+ asm.write_segment(Segment.new(true, false, 1, 2, 3, "TEST"))
+ asm.write_segment(Segment.new(false, true, 1, 2, 3, "ING"))
+
+ assert_equal( ["AMQP", 1, 1, 0, 10], asm.read_header)
+
+ seg = asm.read_segment
+ assert_equal(true, seg.first_segment?)
+ assert_equal(false, seg.last_segment?)
+ assert_equal(1, seg.type)
+ assert_equal(2, seg.track)
+ assert_equal(3, seg.channel)
+ assert_equal("TEST", seg.payload)
+
+ seg = asm.read_segment
+ assert_equal(false, seg.first_segment?)
+ assert_equal(true, seg.last_segment?)
+ assert_equal(1, seg.type)
+ assert_equal(2, seg.track)
+ assert_equal(3, seg.channel)
+ assert_equal("ING", seg.payload)
+ end
+end
diff --git a/ruby/tests/codec010.rb b/ruby/tests/codec010.rb
new file mode 100644
index 0000000000..a9a5ca81e0
--- /dev/null
+++ b/ruby/tests/codec010.rb
@@ -0,0 +1,122 @@
+#
+# 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 "test/unit"
+require "qpid"
+require "tests/util"
+require "socket"
+
+class CodecTest < Test::Unit::TestCase
+
+ def setup
+ @spec = Qpid::Spec010::load
+ end
+
+ def check(type, value)
+ t = @spec[type]
+ sc = Qpid::StringCodec.new(@spec)
+ t.encode(sc, value)
+ decoded = t.decode(sc)
+ assert_equal(value, decoded)
+ end
+
+
+ def testMapString
+ check("map", {"string" => "this is a test"})
+ end
+
+ def testMapInt
+ check("map", {"int" => 3})
+ end
+
+ def testMapLong
+ check("map", {"long" => 2**32})
+ end
+
+ def testMapNone
+ check("map", {"none" => None})
+ end
+
+ def testMapNested
+ check("map", {"map" => {"string" => "nested test"}})
+ end
+
+ def testMapList
+ check("map", {"list" => [1, "two", 3.0, -4]})
+ end
+
+ def testMapAll
+ check("map", {"string" => "this is a test",
+ "int" => 3,
+ "long" => 2**32,
+ "nil" => nil,
+ "map" => {"string" => "nested map"},
+ "list" => [1, "two", 3.0, -4]})
+ end
+
+ def testMapEmpty
+ check("map", {})
+ end
+
+ def testMapNone
+ check("map", nil)
+ end
+
+ def testList
+ check("list", [1, "two", 3.0, -4])
+ end
+
+ def testListEmpty
+ check("list", [])
+ end
+
+ def testListNone
+ check("list", nil)
+ end
+
+ def testArrayInt
+ check("array", [1, 2, 3, 4])
+ end
+
+ def testArrayString
+ check("array", ["one", "two", "three", "four"])
+ end
+
+ def testArrayEmpty
+ check("array", [])
+ end
+
+ def testArrayNone
+ check("array", nil)
+ end
+
+ def testInt64
+ check("int64", 2 ** 40 * -1 + 43)
+ end
+
+ def testUint64
+ check("int64", 2 ** 42)
+ end
+
+ def testReadNone
+ sc = Qpid::StringCodec.new(@spec)
+ # Python behaves this way
+ assert_equal("", sc.read(nil))
+ end
+end
diff --git a/ruby/tests/connection.rb b/ruby/tests/connection.rb
new file mode 100644
index 0000000000..c2a851ec0a
--- /dev/null
+++ b/ruby/tests/connection.rb
@@ -0,0 +1,246 @@
+#
+# 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 'test/unit'
+require 'qpid'
+require 'tests/util'
+
+class MockServer
+
+ def initialize(queue)
+ @queue = queue
+ end
+
+ def connection(conn, args={})
+ return Qpid::Delegate::Server.new(conn, :delegate => method(:session))
+ end
+
+ def session(ssn, args={})
+ ssn.auto_sync = false
+ return MockSession.new(ssn, @queue)
+ end
+end
+
+class MockSession < Qpid::Session::Delegate
+
+ def initialize(session, queue)
+ @session = session
+ @queue = queue
+ end
+
+ def execution_sync(es)
+ nil
+ end
+
+ def queue_query(qq)
+ return qq.st_type.result.create(qq.queue)
+ end
+
+ def message_transfer(cmd, headers, body)
+ if cmd.destination == "echo"
+ m = Qpid::Message.new(body)
+ m.headers = headers
+ @session.message_transfer(cmd.destination, cmd.accept_mode,
+ cmd.acquire_mode, m)
+ elsif cmd.destination == "abort"
+ @session.channel.connection.sock.close()
+ else
+ @queue.put([cmd, headers, body])
+ end
+ end
+
+ def exchange_declare(ed)
+ # do nothing
+ end
+end
+
+class TestConnectionTest < Test::Unit::TestCase
+
+ def setup
+ # Make sure errors in threads lead to a noisy death of the test
+ Thread.abort_on_exception = true
+
+ @queue = Qpid::Queue.new
+ @running = true
+ ts = MockServer.new(@queue)
+ @server = Util::ServerThread.new do |socket|
+ conn = Qpid::Connection.new(socket, :delegate => ts.method(:connection))
+ begin
+ conn.start(5)
+ rescue Qpid::Closed
+ # Ignore
+ end
+ end
+
+ class << @server
+ def finish
+ @running.lock
+ client.close
+ @sockets.each { |sock| sock.close unless sock.closed? }
+ end
+ end
+
+ @server[:name] = 'server'
+ Thread.current[:name] = 'test'
+ end
+
+ def teardown
+ @server.finish
+ @server.join
+ end
+
+ def connect
+ sock = @server.client
+ return Qpid::Connection.new(sock)
+ end
+
+ def test_basic
+ c = connect
+ c.start(10)
+
+ ssn1 = c.session("test1", :timeout => 10)
+ ssn2 = c.session("test2", :timeout => 10)
+
+ assert_equal(c.sessions["test1"], ssn1)
+ assert_equal(c.sessions["test2"], ssn2)
+ assert_not_nil ssn1.channel
+ assert_not_nil ssn2.channel
+ assert(c.attached.values.include?(ssn1))
+ assert(c.attached.values.include?(ssn2))
+
+ ssn1.close(5)
+
+ assert_nil(ssn1.channel)
+ assert(! c.attached.values.include?(ssn1))
+ assert(c.sessions.values.include?(ssn2))
+
+ ssn2.close(5)
+
+ assert_nil(ssn2.channel)
+ assert(! c.attached.values.include?(ssn2))
+ assert(! c.sessions.values.include?(ssn2))
+
+ ssn = c.session("session", :timeout => 10)
+
+ assert_not_nil(ssn.channel)
+ assert(c.sessions.values.include?(ssn))
+
+ destinations = ["one", "two", "three"]
+
+ destinations.each { |d| ssn.message_transfer(d) }
+
+ destinations.each do |d|
+ cmd, header, body = @queue.get(10)
+ assert_equal(d, cmd.destination)
+ assert_nil(header)
+ assert_nil(body)
+ end
+
+ msg = Qpid::Message.new("this is a test")
+ ssn.message_transfer("four", :message => msg)
+ cmd, header, body = @queue.get(10)
+ assert_equal("four", cmd.destination)
+ assert_nil(header)
+ assert_equal(msg.body, body)
+
+ qq = ssn.queue_query("asdf")
+ assert_equal("asdf", qq.queue)
+ c.close(5)
+ end
+
+ def test_close_get
+ c = connect
+ c.start(10)
+ ssn = c.session("test", :timeout => 10)
+ echos = ssn.incoming("echo")
+
+ 10.times do |i|
+ ssn.message_transfer("echo",
+ :message => Qpid::Message.new("test#{i}"))
+ end
+
+ ssn.auto_sync=false
+ ssn.message_transfer("abort")
+
+ 10.times do |i|
+ m = echos.get(timeout=10)
+ assert_equal("test#{i}", m.body)
+ end
+
+ begin
+ m = echos.get(timeout=10)
+ flunk("Expected Closed")
+ rescue Qpid::Closed
+ # Ignore
+ end
+ end
+
+ def test_close_listen
+ c = connect
+ c.start(10)
+ ssn = c.session("test", :timeout => 10)
+ echos = ssn.incoming("echo")
+
+ messages = []
+ exceptions = []
+ lock = Monitor.new
+ condition = lock.new_cond
+
+ echos.exc_listen do |e|
+ exceptions << e
+ lock.synchronize { condition.signal }
+ end
+ echos.listen do |m|
+ messages << m
+ end
+
+ 10.times do |i|
+ ssn.message_transfer("echo",
+ :message => Qpid::Message.new("test#{i}"))
+ end
+ ssn.auto_sync=false
+ ssn.message_transfer("abort")
+
+ lock.synchronize { condition.wait(10) }
+
+ 10.times do |i|
+ m = messages.shift
+ assert_equal("test#{i}", m.body)
+ end
+
+ assert_equal(1, exceptions.size)
+ end
+
+ def test_sync
+ c = connect
+ c.start(10)
+ s = c.session("test")
+ s.auto_sync = false
+ s.message_transfer("echo",
+ :message => Qpid::Message.new("test"))
+ s.sync(10)
+ end
+
+ def test_exchange_declare
+ c = connect
+ c.start(10)
+ s = c.session("test")
+ s.exchange_declare("test-exchange")
+ end
+end
diff --git a/ruby/tests/datatypes.rb b/ruby/tests/datatypes.rb
new file mode 100644
index 0000000000..65b1f9e3f5
--- /dev/null
+++ b/ruby/tests/datatypes.rb
@@ -0,0 +1,224 @@
+#
+# 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 'test/unit'
+require 'qpid'
+require 'tests/util'
+
+class TestSerial < Test::Unit::TestCase
+
+ def test_cmp
+ [0, 0x8FFFFFFF, 0xFFFFFFFF].each do |s|
+ s = s.to_serial
+ assert(s + 1 > s)
+ assert(s - 1 < s)
+ assert(s < s + 1)
+ assert(s > s - 1)
+ end
+ last = 0xFFFFFFFF.to_serial
+ zero = 0.to_serial
+ assert_equal(zero, last + 1)
+
+ assert_equal(last, [last, zero].min)
+ assert_equal(zero, [last, zero].max)
+ end
+
+ def test_incr
+ s = 0.to_serial
+ s += 1
+ assert_equal(1.to_serial, s)
+ end
+
+ def test_in
+ l = [1, 2, 3, 4].collect { |i| i.to_serial }
+ assert(l.include?(1.to_serial))
+ assert(l.include?((0xFFFFFFFF + 2).to_serial))
+ assert(l.include?(4))
+ end
+
+ def test_none
+ assert_not_equal(nil, 0.to_serial)
+ end
+
+ def test_hash
+ zero = 0.to_serial
+ d = { zero => :zero }
+ # FIXME: this does not work, since Ruby looks up the key and does
+ # a 0.eql?(zero), which bypasses the Qpid::Serial::eql?
+ # assert_equal(:zero, d[0])
+ end
+end
+
+class TestRangedSet < Test::Unit::TestCase
+
+ def assert_contains(rset, elts, nonelts = [])
+ assert_equal(elts, elts.select { |e| rset.include?(e) })
+ assert_equal(nonelts, nonelts.select { |e| ! rset.include?(e) })
+ end
+
+ def assert_ranges(rs, *ranges)
+ assert_equal(ranges.size, rs.ranges.size)
+ assert( ranges.all? { |rng| rs.include?(rng) } )
+ end
+
+ def test_simple
+ rs = Qpid::RangedSet.new
+
+ assert(rs.ranges.empty?)
+
+ rs.add(1)
+ assert_contains(rs, [1], [0,2])
+ assert_ranges(rs, 1..1)
+
+ rs.add(2)
+ assert_contains(rs, [1,2], [0,3])
+ assert_ranges(rs, 1..2)
+
+ rs.add(0)
+ assert_contains(rs, [0,1,2], [-1, 3])
+ assert_ranges(rs, 0..2)
+
+ rs.add(37)
+ assert_contains(rs, [0,1,2,37], [-1, 3, 36, 38])
+ assert_ranges(rs, 0..2, 37..37)
+
+ rs.add(-1)
+ assert_ranges(rs, -1..2, 37..37)
+
+ rs.add(-3)
+ assert_ranges(rs, -1..2, 37..37, -3..-3)
+
+ rs.add(1, 20)
+ assert_contains(rs, [20], [21])
+ assert_ranges(rs, -1..20, 37..37, -3..-3)
+
+ rs.add(21,36)
+ assert_ranges(rs, -1..37, -3..-3)
+
+ rs.add(-3, 5)
+ assert_ranges(rs, -3..37)
+ end
+
+ def test_add_self
+ a = Qpid::RangedSet.new
+ a.add(0, 8)
+ assert_ranges(a, 0..8)
+
+ a.add(0, 8)
+ assert_ranges(a, 0..8)
+ end
+end
+
+class TestRange < Test::Unit::TestCase
+
+ def test_intersect1
+ a = Range.new(0, 10)
+ b = Range.new(9, 20)
+ i1 = a.intersect(b)
+ i2 = b.intersect(a)
+ assert_equal(9..10, i1)
+ assert_equal(9..10, i2)
+ end
+
+ def test_intersect2
+ a = Range.new(0, 10)
+ b = Range.new(11, 20)
+ assert_equal(nil, a.intersect(b))
+ assert_equal(nil, b.intersect(a))
+ end
+
+ def test_intersect3
+ a = Range.new(0, 10)
+ b = Range.new(3, 5)
+ i1 = a.intersect(b)
+ i2 = b.intersect(a)
+ assert_equal(3..5, i1)
+ assert_equal(3..5, i2)
+ end
+end
+
+class TestUUIDTest < Test::Unit::TestCase
+
+ def test_simple
+ # this test is kind of lame, but it does excercise the basic
+ # functionality of the class
+ u = Qpid::UUID::uuid4
+ 1024.times { |i| assert_not_equal(u, Qpid::UUID::uuid4) }
+ assert_raise NotImplementedError do
+ u == 0
+ end
+ end
+end
+
+class TestMessage < Test::Unit::TestCase
+
+ def setup
+ @@spec ||= Qpid::Spec010::load()
+ @mp = Qpid::struct(@@spec["message_properties"])
+ @dp = Qpid::struct(@@spec["delivery_properties"])
+ @fp = Qpid::struct(@@spec["fragment_properties"])
+ end
+
+ def test_has
+ m = Qpid::Message.new(@mp, @dp, @fp, "body")
+ assert m.has("message_properties")
+ assert m.has("delivery_properties")
+ assert m.has("fragment_properties")
+ end
+
+ def test_get
+ m = Qpid::Message.new(@mp, @dp, @fp, "body")
+ assert_same(@mp, m.get("message_properties"))
+ assert_same(@dp, m.get("delivery_properties"))
+ assert_same(@fp, m.get("fragment_properties"))
+ end
+
+ def test_set
+ m = Qpid::Message.new(@mp, @dp, "body")
+ assert_nil m.get("fragment_properties")
+ m.set(@fp)
+ assert_same(@fp, m.get("fragment_properties"), "4")
+ end
+
+ def test_set_on_empty
+ m = Qpid::Message.new("body")
+ assert_nil m.get("delivery_properties")
+ m.set(@dp)
+ assert_same(@dp, m.get("delivery_properties"), "5")
+ end
+
+ def test_set_replace
+ m = Qpid::Message.new(@mp, @dp, @fp, "body")
+ dp = Qpid::struct(@@spec["delivery_properties"])
+ assert_same(@dp, m.get("delivery_properties"), "6")
+ m.set(dp)
+ assert_same(dp, m.get("delivery_properties"), "7")
+ end
+
+ def test_clear
+ m = Qpid::Message.new(@mp, @dp, @fp, "body")
+ assert_same(@mp, m.get("message_properties"), "8")
+ assert_same(@dp, m.get("delivery_properties"), "9")
+ assert_same(@fp, m.get("fragment_properties"), "10")
+ m.clear("fragment_properties")
+ assert_nil m.get("fragment_properties")
+ assert_same(@mp, m.get("message_properties"), "11")
+ assert_same(@dp, m.get("delivery_properties"), "12")
+ end
+end
diff --git a/ruby/tests/framer.rb b/ruby/tests/framer.rb
new file mode 100644
index 0000000000..1d56f2faf1
--- /dev/null
+++ b/ruby/tests/framer.rb
@@ -0,0 +1,99 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require "test/unit"
+require "qpid"
+require 'tests/util'
+
+require 'logger'
+
+class TestFramer < Test::Unit::TestCase
+
+ include Test
+
+ def setup
+ #Qpid::raw_logger = Logger.new(STDOUT)
+ #Qpid::frm_logger = Logger.new(STDOUT)
+
+ @server = Util::ServerThread.new do |socket|
+ conn = Qpid::Framer.new(socket)
+ begin
+ h = conn.read_header
+ conn.write_header(h[-2], h[-1])
+ loop do
+ frame = conn.read_frame
+ conn.write_frame(frame)
+ conn.flush
+ end
+ rescue Qpid::Closed
+ nil # Ignore
+ end
+ end
+ end
+
+ def teardown
+ @server.finish
+ @server.join
+ end
+
+ Frame = Qpid::Frame
+
+ def test_framer
+ c = Qpid::Framer.new(@server.client)
+
+ c.write_header(0, 10)
+ assert_equal( ["AMQP", 1, 1, 0, 10], c.read_header())
+
+ c.write_frame(Frame.new(Qpid::FIRST_FRM, 1, 2, 3, "THIS"))
+ c.write_frame(Frame.new(0, 1, 2, 3, "IS"))
+ c.write_frame(Frame.new(0, 1, 2, 3, "A"))
+ c.write_frame(Frame.new(Qpid::LAST_FRM, 1, 2, 3, "TEST"))
+ c.flush()
+
+ f = c.read_frame
+ assert(f.first_frame?)
+ assert(! f.last_frame?)
+ assert_equal(1, f.type)
+ assert_equal(2, f.track)
+ assert_equal(3, f.channel)
+ assert_equal("THIS", f.payload)
+
+ f = c.read_frame
+ assert_equal(0, f.flags)
+ assert_equal(1, f.type)
+ assert_equal(2, f.track)
+ assert_equal(3, f.channel)
+ assert_equal("IS", f.payload)
+
+ f = c.read_frame
+ assert_equal(0, f.flags)
+ assert_equal(1, f.type)
+ assert_equal(2, f.track)
+ assert_equal(3, f.channel)
+ assert_equal("A", f.payload)
+
+ f = c.read_frame
+ assert(f.last_frame?)
+ assert(! f.first_frame?)
+ assert_equal(1, f.type)
+ assert_equal(2, f.track)
+ assert_equal(3, f.channel)
+ assert_equal("TEST", f.payload)
+ end
+end
diff --git a/ruby/tests/qmf.rb b/ruby/tests/qmf.rb
new file mode 100644
index 0000000000..274e38416e
--- /dev/null
+++ b/ruby/tests/qmf.rb
@@ -0,0 +1,248 @@
+#
+# 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 "test/unit"
+require "qpid"
+require "tests/util"
+require "socket"
+require "monitor.rb"
+
+class QmfTest < Test::Unit::TestCase
+
+ class Handler < Qpid::Qmf::Console
+ include MonitorMixin
+
+ def initialize
+ super()
+ @xmt_list = {}
+ @rcv_list = {}
+ end
+
+ def method_response(broker, seq, response)
+ synchronize do
+ @rcv_list[seq] = response
+ end
+ end
+
+ def request(broker, count)
+ @count = count
+ for idx in 0...count
+ synchronize do
+ seq = broker.echo(idx, "Echo Message", :async => true)
+ @xmt_list[seq] = idx
+ end
+ end
+ end
+
+ def check
+ return "fail (attempted send=%d, actual sent=%d)" % [@count, @xmt_list.size] unless @count == @xmt_list.size
+ lost = 0
+ mismatched = 0
+ @xmt_list.each do |seq, value|
+ if @rcv_list.include?(seq)
+ result = @rcv_list.delete(seq)
+ mismatch += 1 unless result.sequence == value
+ else
+ lost += 1
+ end
+ end
+ spurious = @rcv_list.size
+ if lost == 0 and mismatched == 0 and spurious == 0
+ return "pass"
+ else
+ return "fail (lost=%d, mismatch=%d, spurious=%d)" % [lost, mismatched, spurious]
+ end
+ end
+ end
+
+ def setup()
+ # Make sure errors in threads lead to a noisy death of the test
+ Thread.abort_on_exception = true
+
+ @host = ENV.fetch("QMF_TEST_HOST", 'localhost')
+ @port = ENV.fetch("QMF_TEST_PORT", 5672)
+
+ sock = TCPSocket.new(@host, @port)
+
+ @conn = Qpid::Connection.new(sock)
+ @conn.start()
+
+ @session = @conn.session("test-session")
+ end
+
+ def teardown
+ unless @session.error?
+ @session.close(10)
+ end
+ @conn.close(10)
+ if @qmf
+ @qmf.del_broker(@qmf_broker)
+ end
+ end
+
+ def start_qmf(kwargs = {})
+ @qmf = Qpid::Qmf::Session.new(kwargs)
+ @qmf_broker = @qmf.add_broker("amqp://%s:%d" % [@host, @port])
+
+ brokers = @qmf.objects(:class => "broker")
+ assert_equal(1, brokers.length)
+ @broker = brokers[0]
+ end
+
+ def test_methods_sync()
+ start_qmf
+ body = "Echo Message Body"
+ for seq in 1..10
+ res = @broker.echo(seq, body, :timeout => 10)
+ assert_equal(0, res.status)
+ assert_equal("OK", res.text)
+ assert_equal(seq, res.sequence)
+ assert_equal(body, res.body)
+ end
+ end
+
+ def test_methods_async()
+ handler = Handler.new
+ start_qmf(:console => handler)
+ handler.request(@broker, 20)
+ sleep(1)
+ assert_equal("pass", handler.check)
+ end
+
+ def test_move_queued_messages()
+ """
+ Test ability to move messages from the head of one queue to another.
+ Need to test moveing all and N messages.
+ """
+
+ "Set up source queue"
+ start_qmf
+ @session.queue_declare(:queue => "src-queue", :exclusive => true, :auto_delete => true)
+ @session.exchange_bind(:queue => "src-queue", :exchange => "amq.direct", :binding_key => "routing_key")
+
+ props = @session.delivery_properties(:routing_key => "routing_key")
+ for count in 1..20
+ body = "Move Message %d" % count
+ src_msg = Qpid::Message.new(props, body)
+ @session.message_transfer(:destination => "amq.direct", :message => src_msg)
+ end
+
+ "Set up destination queue"
+ @session.queue_declare(:queue => "dest-queue", :exclusive => true, :auto_delete => true)
+ @session.exchange_bind(:queue => "dest-queue", :exchange => "amq.direct")
+
+ queues = @qmf.objects(:class => "queue")
+
+ "Move 10 messages from src-queue to dest-queue"
+ result = @qmf.objects(:class => "broker")[0].queueMoveMessages("src-queue", "dest-queue", 10)
+ assert_equal(0, result.status)
+
+ sq = @qmf.objects(:class => "queue", "name" => "src-queue")[0]
+ dq = @qmf.objects(:class => "queue", "name" => "dest-queue")[0]
+
+ assert_equal(10, sq.msgDepth)
+ assert_equal(10, dq.msgDepth)
+
+ "Move all remaining messages to destination"
+ result = @qmf.objects(:class => "broker")[0].queueMoveMessages("src-queue", "dest-queue", 0)
+ assert_equal(0, result.status)
+
+ sq = @qmf.objects(:class => "queue", 'name' => "src-queue")[0]
+ dq = @qmf.objects(:class => "queue", 'name' => "dest-queue")[0]
+
+ assert_equal(0, sq.msgDepth)
+ assert_equal(20, dq.msgDepth)
+
+ "Use a bad source queue name"
+ result = @qmf.objects(:class => "broker")[0].queueMoveMessages("bad-src-queue", "dest-queue", 0)
+ assert_equal(4, result.status)
+
+ "Use a bad destination queue name"
+ result = @qmf.objects(:class => "broker")[0].queueMoveMessages("src-queue", "bad-dest-queue", 0)
+ assert_equal(4, result.status)
+
+ " Use a large qty (40) to move from dest-queue back to "
+ " src-queue- should move all "
+ result = @qmf.objects(:class => "broker")[0].queueMoveMessages("dest-queue", "src-queue", 40)
+ assert_equal(0, result.status)
+
+ sq = @qmf.objects(:class => "queue", 'name' => "src-queue")[0]
+ dq = @qmf.objects(:class => "queue", 'name' => "dest-queue")[0]
+
+ assert_equal(20, sq.msgDepth)
+ assert_equal(0, dq.msgDepth)
+
+ "Consume the messages of the queue and check they are all there in order"
+ @session.message_subscribe(:queue => "src-queue",
+ :destination => "tag")
+ @session.message_flow(:destination => "tag",
+ :unit => @session.message_credit_unit.message,
+ :value => 0xFFFFFFFF)
+ @session.message_flow(:destination => "tag",
+ :unit => @session.message_credit_unit.byte,
+ :value => 0xFFFFFFFF)
+ queue = @session.incoming("tag")
+ for count in 1..20
+ consumed_msg = queue.get(timeout=1)
+ body = "Move Message %d" % count
+ assert_equal(body, consumed_msg.body)
+ end
+ end
+
+ # Test ability to purge messages from the head of a queue. Need to test
+ # moveing all, 1 (top message) and N messages.
+ def test_purge_queue
+ start_qmf
+ # Set up purge queue"
+ @session.queue_declare(:queue => "purge-queue",
+ :exclusive => true,
+ :auto_delete => true)
+ @session.exchange_bind(:queue => "purge-queue",
+ :exchange => "amq.direct",
+ :binding_key => "routing_key")
+
+ props = @session.delivery_properties(:routing_key => "routing_key")
+ 20.times do |count|
+ body = "Purge Message %d" % count
+ msg = Qpid::Message.new(props, body)
+ @session.message_transfer(:destination => "amq.direct",
+ :message => msg)
+ end
+
+ pq = @qmf.objects(:class => "queue", 'name' => "purge-queue")[0]
+
+ "Purge top message from purge-queue"
+ result = pq.purge(1)
+ assert_equal(0, result.status)
+ pq = @qmf.objects(:class => "queue", 'name' => "purge-queue")[0]
+ assert_equal(19, pq.msgDepth)
+
+ "Purge top 9 messages from purge-queue"
+ result = pq.purge(9)
+ assert_equal(0, result.status)
+ pq = @qmf.objects(:class => "queue", 'name' => "purge-queue")[0]
+ assert_equal(10, pq.msgDepth)
+
+ "Purge all messages from purge-queue"
+ result = pq.purge(0)
+ assert_equal(0, result.status)
+ pq = @qmf.objects(:class => "queue", 'name' => "purge-queue")[0]
+ assert_equal(0, pq.msgDepth)
+ end
+end
diff --git a/ruby/tests/queue.rb b/ruby/tests/queue.rb
new file mode 100644
index 0000000000..4ec0e07ffb
--- /dev/null
+++ b/ruby/tests/queue.rb
@@ -0,0 +1,80 @@
+#
+# 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 'test/unit'
+require 'qpid'
+
+class TestQueue < Test::Unit::TestCase
+
+ # The qpid queue class just provides sime simple extensions to
+ # python's standard queue data structure, so we don't need to test
+ # all the queue functionality.
+
+ def setup
+ # Make sure errors in threads lead to a noisy death of the test
+ Thread.abort_on_exception = true
+ end
+
+ def test_listen
+ values = []
+ heard = Qpid::Util::Event.new
+
+ listener = Proc.new do |x|
+ values << x
+ heard.set
+ end
+
+ q = Qpid::Queue.new
+ q.listen(&listener)
+
+ heard.clear
+ q.put(1)
+ heard.wait
+ assert_equal([1], values)
+ heard.clear
+ q.put(2)
+ heard.wait
+ assert_equal([1, 2], values)
+
+ q.listen
+ q.put(3)
+ assert_equal(3, q.get)
+
+ q.listen(&listener)
+ heard.clear
+ q.put(4)
+ heard.wait
+ assert_equal([1,2,4], values)
+ end
+
+ def test_close
+ q = Qpid::Queue.new
+ (1..3).each { |i| q.put(i) }
+ q.close
+ assert_equal(1, q.get)
+ assert_equal(2, q.get)
+ assert_equal(3, q.get)
+ 10.times do |i|
+ assert_raises(Qpid::Closed) do
+ q.get
+ end
+ end
+ end
+
+end
diff --git a/ruby/tests/spec010.rb b/ruby/tests/spec010.rb
new file mode 100644
index 0000000000..6db1523455
--- /dev/null
+++ b/ruby/tests/spec010.rb
@@ -0,0 +1,80 @@
+#
+# 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 "test/unit"
+require "qpid/test"
+require "qpid/spec010"
+
+class SpecTest < Test::Unit::TestCase
+
+ def setup()
+ @spec = Qpid::Spec010.load()
+ end
+
+ def testSessionHeader()
+ hdr = @spec[:header]
+ sc = Qpid::StringCodec.new(@spec)
+ hdr.encode(sc, Qpid::struct(hdr, :sync=>true))
+ assert sc.encoded == "\x01\x01"
+
+ sc = Qpid::StringCodec.new(@spec)
+ hdr.encode(sc, Qpid::struct(hdr, :sync=>false))
+ assert sc.encoded == "\x01\x00"
+ end
+
+ def encdec(type, value)
+ sc = Qpid::StringCodec.new(@spec)
+ type.encode(sc, value)
+ decoded = type.decode(sc)
+ return decoded
+ end
+
+ def testMessageProperties()
+ mp = @spec[:message_properties]
+ rt = @spec[:reply_to]
+
+ props = Qpid::struct(mp,
+ :content_length=>3735928559,
+ :reply_to=>Qpid::struct(rt,
+ :exchange=>"the exchange name",
+ :routing_key=>"the routing key"))
+ dec = encdec(mp, props)
+ assert props.content_length == dec.content_length
+ assert props.reply_to.exchange == dec.reply_to.exchange
+ assert props.reply_to.routing_key == dec.reply_to.routing_key
+ end
+
+ def testMessageSubscribe()
+ ms = @spec[:message_subscribe]
+ cmd = Qpid::struct(ms, :exclusive=>true, :destination=>"this is a test")
+ dec = encdec(@spec[:message_subscribe], cmd)
+ assert cmd.exclusive == dec.exclusive
+ assert cmd.destination == dec.destination
+ end
+
+ def testXid()
+ xid = @spec[:xid]
+ sc = Qpid::StringCodec.new(@spec)
+ st = Qpid::struct(xid, :format=>0, :global_id=>"gid", :branch_id=>"bid")
+ xid.encode(sc, st)
+ assert sc.encoded == "\x00\x00\x00\x10\x06\x04\x07\x00\x00\x00\x00\x00\x03gid\x03bid"
+ assert xid.decode(sc) == st
+ end
+
+end
diff --git a/ruby/tests/util.rb b/ruby/tests/util.rb
new file mode 100644
index 0000000000..b22a6bab2f
--- /dev/null
+++ b/ruby/tests/util.rb
@@ -0,0 +1,72 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'thread'
+require 'socket'
+
+module Util
+
+ TOPDIR = File::dirname(File::dirname(File::expand_path(__FILE__)))
+ SPEC = File::join(TOPDIR, "specs", "amqp.0-10-qpid-errata.xml")
+
+ PORT = 1234
+ HOST = "0.0.0.0"
+
+ def self.connect(host = HOST, port = PORT)
+ TCPSocket.new(host, port)
+ end
+
+ class ServerThread < Thread
+ def initialize(&block)
+ @sockets = []
+ @running = Mutex.new
+ started = Qpid::Util::Event.new
+ super(started, @running) do |started, running|
+ tcp_srv = TCPServer.new(HOST, PORT)
+ begin
+ started.set
+ while ! running.locked? and (session = tcp_srv.accept)
+ yield(session)
+ end
+ rescue Exception => e
+ # Exceptions in the server thread are hard to see
+ # Make sure they apear loudly on the console
+ $stderr.puts "#{ "*" * 20} Server exception #{ "*" * 20}"
+ $stderr.puts e.message
+ $stderr.puts e.backtrace
+ raise
+ ensure
+ tcp_srv.close
+ end
+ end
+ started.wait
+ end
+
+ def finish
+ @running.lock
+ @sockets.each { |sock| sock.close unless sock.closed? }
+ end
+
+ def client(host = HOST, port = PORT)
+ sock = Util::connect(host, port)
+ @sockets << sock
+ sock
+ end
+ end
+end
diff --git a/ruby/tests_0-8/basic.rb b/ruby/tests_0-8/basic.rb
new file mode 100644
index 0000000000..10a43b1aab
--- /dev/null
+++ b/ruby/tests_0-8/basic.rb
@@ -0,0 +1,69 @@
+#
+# 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 "test/unit"
+require "qpid/test"
+require "qpid"
+
+class Basic < Test::Unit::TestCase
+
+ include Qpid08::Test
+
+ def publish(body, headers = {})
+ cli = connect()
+ ch = cli.channel(1)
+ ch.channel_open()
+ content = Qpid08::Content.new(headers, body)
+ ch.basic_publish(:content => content)
+ msg = ch.channel_close()
+ assert msg.method.qname == :channel_close_ok
+ end
+
+ def consume(body, headers = {})
+ cli = connect()
+ ch = cli.channel(1)
+ ch.channel_open()
+ ch.queue_declare(:queue => "test-queue")
+ ch.queue_bind(:queue_name => "test-queue")
+ ch.basic_consume(:queue => "test-queue", :consumer_tag => "ctag")
+ content = Qpid08::Content.new(headers, body)
+ ch.basic_publish(:routing_key => "test-queue", :content => content)
+ queue = cli.queue("ctag")
+ msg = queue.pop()
+ assert content.headers == msg.content.headers
+ assert content.body == msg.content.body
+ assert content.children == msg.content.children
+ ch.basic_ack(msg.delivery_tag)
+ msg = ch.channel_close()
+ assert msg.method.qname == :channel_close_ok
+ end
+
+ def test_publish(); publish("hello world") end
+
+ def test_publish_empty(); publish("") end
+
+ def test_publish_headers(); publish("hello world", :content_type => "text/plain") end
+
+ def test_consume(); consume("hello world") end
+
+ def test_consume_empty(); consume("") end
+
+ def test_consume_headers(); consume("hello_world", :content_type => "text/plain") end
+
+end
diff --git a/ruby/tests_0-8/channel.rb b/ruby/tests_0-8/channel.rb
new file mode 100644
index 0000000000..1eea8f18d9
--- /dev/null
+++ b/ruby/tests_0-8/channel.rb
@@ -0,0 +1,48 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require "test/unit"
+require "qpid/test"
+require "qpid"
+
+class Channel < Test::Unit::TestCase
+
+ include Qpid08::Test
+
+ def test_channel_open_close()
+ c = connect()
+ ch = c.channel(1)
+ msg = ch.channel_open()
+ assert msg.method.qname == :channel_open_ok
+ msg = ch.channel_close()
+ assert msg.method.qname == :channel_close_ok
+ end
+
+ def test_channel_close()
+ c = connect()
+ ch = c.channel(1)
+ begin
+ ch.channel_close()
+ rescue Qpid::Closed => e
+ assert c.code.method.qname == :connection_close
+ assert c.code.reply_code == 504
+ end
+ end
+
+end
diff --git a/specs/management-schema.xml b/specs/management-schema.xml
index 9e2a644c2a..65d8d4f11d 100644
--- a/specs/management-schema.xml
+++ b/specs/management-schema.xml
@@ -92,7 +92,6 @@
<arg name="srcQueue" dir="I" type="sstr" desc="Source queue"/>
<arg name="destQueue" dir="I" type="sstr" desc="Destination queue"/>
<arg name="qty" dir="I" type="uint32" desc="# of messages to move. 0 means all messages"/>
- <arg name="filter" dir="I" type="map" default="{}" desc="if specified, move only those messages matching this filter"/>
</method>
<method name="setLogLevel" desc="Set the log level">
@@ -103,34 +102,6 @@
<arg name="level" dir="O" type="sstr"/>
</method>
- <method name="getTimestampConfig" desc="Get the message timestamping configuration">
- <arg name="receive" dir="O" type="bool" desc="True if received messages are timestamped."/>
- </method>
-
- <method name="setTimestampConfig" desc="Set the message timestamping configuration">
- <arg name="receive" dir="I" type="bool" desc="Set true to enable timestamping received messages."/>
- </method>
-
- <method name="create" desc="Create an object of the specified type">
- <arg name="type" dir="I" type="sstr" desc="The type of object to create"/>
- <arg name="name" dir="I" type="sstr" desc="The name of the object to create"/>
- <arg name="properties" dir="I" type="map" desc="Type specific object properties"/>
- <arg name="strict" dir="I" type="bool" desc="If specified, treat unrecognised object properties as an error"/>
- </method>
-
- <method name="delete" desc="Delete an object of the specified type">
- <arg name="type" dir="I" type="sstr" desc="The type of object to delete"/>
- <arg name="name" dir="I" type="sstr" desc="The name of the object to delete"/>
- <arg name="options" dir="I" type="map" desc="Type specific object options for deletion"/>
- </method>
-
- <method name="query" desc="Query the current state of an object.">
- <arg name="type" dir="I" type="sstr" desc="The type of object to query."/>
- <arg name="name" dir="I" type="sstr" desc="The name of the object to query"/>
- <arg name="results" dir="O" type="map" desc="A snapshot of the object's state."/>
- </method>
-
-
</class>
<!--
@@ -179,8 +150,8 @@
<statistic name="msgTxnDequeues" type="count64" unit="message" desc="Transactional messages dequeued"/>
<statistic name="msgPersistEnqueues" type="count64" unit="message" desc="Persistent messages enqueued"/>
<statistic name="msgPersistDequeues" type="count64" unit="message" desc="Persistent messages dequeued"/>
- <statistic name="msgDepth" type="count64" unit="message" desc="Current size of queue in messages" assign="msgTotalEnqueues - msgTotalDequeues"/>
- <statistic name="byteDepth" type="count64" unit="octet" desc="Current size of queue in bytes" assign="byteTotalEnqueues - byteTotalDequeues"/>
+ <statistic name="msgDepth" type="count32" unit="message" desc="Current size of queue in messages" assign="msgTotalEnqueues - msgTotalDequeues"/>
+ <statistic name="byteDepth" type="count32" unit="octet" desc="Current size of queue in bytes" assign="byteTotalEnqueues - byteTotalDequeues"/>
<statistic name="byteTotalEnqueues" type="count64" unit="octet" desc="Total messages enqueued"/>
<statistic name="byteTotalDequeues" type="count64" unit="octet" desc="Total messages dequeued"/>
<statistic name="byteTxnEnqueues" type="count64" unit="octet" desc="Transactional messages enqueued"/>
@@ -191,19 +162,15 @@
<statistic name="bindingCount" type="hilo32" unit="binding" desc="Current bindings"/>
<statistic name="unackedMessages" type="hilo32" unit="message" desc="Messages consumed but not yet acked"/>
<statistic name="messageLatency" type="mmaTime" unit="nanosecond" desc="Broker latency through this queue"/>
- <statistic name="flowStopped" type="bool" desc="Flow control active."/>
- <statistic name="flowStoppedCount" type="count32" desc="Number of times flow control was activated for this queue"/>
<method name="purge" desc="Discard all or some messages on a queue">
<arg name="request" dir="I" type="uint32" desc="0 for all messages or n>0 for n messages"/>
- <arg name="filter" dir="I" type="map" default="{}" desc="if specified, purge only those messages matching this filter"/>
</method>
<method name="reroute" desc="Remove all or some messages on this queue and route them to an exchange">
<arg name="request" dir="I" type="uint32" desc="0 for all messages or n>0 for n messages"/>
<arg name="useAltExchange" dir="I" type="bool" desc="Iff true, use the queue's configured alternate exchange; iff false, use exchange named in the 'exchange' argument"/>
<arg name="exchange" dir="I" type="sstr" desc="Name of the exchange to route the messages through"/>
- <arg name="filter" dir="I" type="map" default="{}" desc="if specified, reroute only those messages matching this filter"/>
</method>
</class>
@@ -272,16 +239,13 @@
<property name="vhostRef" type="objId" references="Vhost" access="RC" index="y" parentRef="y"/>
<property name="address" type="sstr" access="RC" index="y"/>
<property name="incoming" type="bool" access="RC"/>
- <property name="SystemConnection" type="bool" access="RC" desc="Infrastructure/ Inter-system connection (Cluster, Federation, ...)"/>
- <property name="userProxyAuth" type="bool" access="RO" desc="Authorization to proxy for users not on broker"/>
+ <property name="SystemConnection" type="bool" access="RC" desc="Infrastucture/ Inter-system connection (Cluster, Federation, ...)"/>
<property name="federationLink" type="bool" access="RO" desc="Is this a federation link"/>
<property name="authIdentity" type="sstr" access="RO" desc="authId of connection if authentication enabled"/>
<property name="remoteProcessName" type="lstr" access="RO" optional="y" desc="Name of executable running as remote client"/>
<property name="remotePid" type="uint32" access="RO" optional="y" desc="Process ID of remote client"/>
<property name="remoteParentPid" type="uint32" access="RO" optional="y" desc="Parent Process ID of remote client"/>
<property name="shadow" type="bool" access="RO" desc="True for shadow connections"/>
- <property name="saslMechanism" type="sstr" access="RO" desc="SASL mechanism"/>
- <property name="saslSsf" type="uint16" access="RO" desc="SASL security strength factor"/>
<statistic name="closing" type="bool" desc="This client is closing by management request"/>
<statistic name="framesFromClient" type="count64"/>
<statistic name="framesToClient" type="count64"/>
@@ -416,8 +380,8 @@
<arg name="reason" type="lstr" desc="Reason for a failure"/>
<arg name="rhost" type="sstr" desc="Address (i.e. DNS name, IP address, etc.) of a remotely connected host"/>
<arg name="user" type="sstr" desc="Authentication identity"/>
- <arg name="msgDepth" type="count64" desc="Current size of queue in messages"/>
- <arg name="byteDepth" type="count64" desc="Current size of queue in bytes"/>
+ <arg name="msgDepth" type="count32" desc="Current size of queue in messages"/>
+ <arg name="byteDepth" type="count32" desc="Current size of queue in bytes"/>
</eventArguments>
<event name="clientConnect" sev="inform" args="rhost, user"/>
diff --git a/tests/setup.py b/tests/setup.py
index 2ea7d347e7..5438275b22 100755
--- a/tests/setup.py
+++ b/tests/setup.py
@@ -20,7 +20,7 @@
from distutils.core import setup
setup(name="qpid-tests",
- version="0.13",
+ version="0.9",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
packages=["qpid_tests", "qpid_tests.broker_0_10", "qpid_tests.broker_0_9",
diff --git a/tests/src/py/qpid_tests/broker_0_10/__init__.py b/tests/src/py/qpid_tests/broker_0_10/__init__.py
index 7b779df5f4..921786af22 100644
--- a/tests/src/py/qpid_tests/broker_0_10/__init__.py
+++ b/tests/src/py/qpid_tests/broker_0_10/__init__.py
@@ -33,4 +33,3 @@ from lvq import *
from priority import *
from threshold import *
from extensions import *
-from msg_groups import *
diff --git a/tests/src/py/qpid_tests/broker_0_10/alternate_exchange.py b/tests/src/py/qpid_tests/broker_0_10/alternate_exchange.py
index 8cbb5793d9..0ffeb57172 100644
--- a/tests/src/py/qpid_tests/broker_0_10/alternate_exchange.py
+++ b/tests/src/py/qpid_tests/broker_0_10/alternate_exchange.py
@@ -18,7 +18,7 @@
#
import traceback
from qpid.queue import Empty
-from qpid.datatypes import Message, RangedSet
+from qpid.datatypes import Message
from qpid.testlib import TestBase010
from qpid.session import SessionException
@@ -77,7 +77,13 @@ class AlternateExchangeTests(TestBase010):
"""
session = self.session
#set up a 'dead letter queue':
- dlq = self.setup_dlq()
+ session.exchange_declare(exchange="dlq", type="fanout")
+ session.queue_declare(queue="deleted", exclusive=True, auto_delete=True)
+ session.exchange_bind(exchange="dlq", queue="deleted")
+ session.message_subscribe(destination="dlq", queue="deleted")
+ session.message_flow(destination="dlq", unit=session.credit_unit.message, value=0xFFFFFFFFL)
+ session.message_flow(destination="dlq", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
+ dlq = session.incoming("dlq")
#create a queue using the dlq as its alternate exchange:
session.queue_declare(queue="delete-me", alternate_exchange="dlq")
@@ -230,121 +236,6 @@ class AlternateExchangeTests(TestBase010):
self.assertEqual("Three", dlq.get(timeout=1).body)
self.assertEmpty(dlq)
- def test_queue_delete_loop(self):
- """
- Test that if a queue is bound to its own alternate exchange,
- then on deletion there is no infinite looping
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #create a queue using the dlq as its alternate exchange:
- session.queue_declare(queue="delete-me", alternate_exchange="dlq")
- #bind that queue to the dlq as well:
- session.exchange_bind(exchange="dlq", queue="delete-me")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delete-me")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
- #delete it:
- session.queue_delete(queue="delete-me")
- #cleanup:
- session.exchange_delete(exchange="dlq")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_queue_delete_no_match(self):
- """
- Test that on queue deletion, if the queues own alternate
- exchange cannot find a match for the message, the
- alternate-exchange of that exchange will be tried. Note:
- though the spec rules out going to the alternate-exchanges
- alternate exchange when sending to an exchange, it does not
- cover this case.
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #setu up an 'intermediary' exchange
- session.exchange_declare(exchange="my-exchange", type="direct", alternate_exchange="dlq")
-
- #create a queue using the intermediary as its alternate exchange:
- session.queue_declare(queue="delete-me", alternate_exchange="my-exchange")
- #bind that queue to the dlq as well:
- session.exchange_bind(exchange="dlq", queue="delete-me")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delete-me")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
-
- #delete it:
- session.queue_delete(queue="delete-me")
- #cleanup:
- session.exchange_delete(exchange="my-exchange")
- session.exchange_delete(exchange="dlq")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_reject_no_match(self):
- """
- Test that on rejecting a message, if the queues own alternate
- exchange cannot find a match for the message, the
- alternate-exchange of that exchange will be tried. Note:
- though the spec rules out going to the alternate-exchanges
- alternate exchange when sending to an exchange, it does not
- cover this case.
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #setu up an 'intermediary' exchange
- session.exchange_declare(exchange="my-exchange", type="direct", alternate_exchange="dlq")
-
- #create a queue using the intermediary as its alternate exchange:
- session.queue_declare(queue="delivery-queue", alternate_exchange="my-exchange", auto_delete=True)
- #bind that queue to the dlq as well:
- session.exchange_bind(exchange="dlq", queue="delivery-queue")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delivery-queue")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
-
- #get and reject those messages:
- session.message_subscribe(destination="a", queue="delivery-queue")
- session.message_flow(destination="a", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="a", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- incoming = session.incoming("a")
- for m in ["One", "Two", "Three"]:
- msg = incoming.get(timeout=1)
- self.assertEqual(m, msg.body)
- session.message_reject(RangedSet(msg.id))
- session.message_cancel(destination="a")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
- #cleanup:
- session.exchange_delete(exchange="my-exchange")
- session.exchange_delete(exchange="dlq")
-
- def setup_dlq(self):
- session = self.session
- #set up 'dead-letter' handling:
- session.exchange_declare(exchange="dlq", type="fanout")
- session.queue_declare(queue="deleted", exclusive=True, auto_delete=True)
- session.exchange_bind(exchange="dlq", queue="deleted")
- session.message_subscribe(destination="dlq", queue="deleted")
- session.message_flow(destination="dlq", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="dlq", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- dlq = session.incoming("dlq")
- return dlq
def assertEmpty(self, queue):
try:
diff --git a/tests/src/py/qpid_tests/broker_0_10/dtx.py b/tests/src/py/qpid_tests/broker_0_10/dtx.py
index 19a5c6a8d9..2823385a3b 100644
--- a/tests/src/py/qpid_tests/broker_0_10/dtx.py
+++ b/tests/src/py/qpid_tests/broker_0_10/dtx.py
@@ -6,9 +6,9 @@
# 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
@@ -36,7 +36,7 @@ class DtxTests(TestBase010):
and the appropriate result verified.
The other tests enforce more specific rules and behaviour on a
- per-method or per-field basis.
+ per-method or per-field basis.
"""
XA_RBROLLBACK = 1
@@ -49,8 +49,8 @@ class DtxTests(TestBase010):
self.session = self.conn.session("dtx-session", 1)
def test_simple_commit(self):
- """
- Test basic one-phase commit behaviour.
+ """
+ Test basic one-phase commit behaviour.
"""
guard = self.keepQueuesAlive(["queue-a", "queue-b"])
session = self.session
@@ -73,8 +73,8 @@ class DtxTests(TestBase010):
self.assertMessageId("commit", "queue-b")
def test_simple_prepare_commit(self):
- """
- Test basic two-phase commit behaviour.
+ """
+ Test basic two-phase commit behaviour.
"""
guard = self.keepQueuesAlive(["queue-a", "queue-b"])
session = self.session
@@ -100,8 +100,8 @@ class DtxTests(TestBase010):
def test_simple_rollback(self):
- """
- Test basic rollback behaviour.
+ """
+ Test basic rollback behaviour.
"""
guard = self.keepQueuesAlive(["queue-a", "queue-b"])
session = self.session
@@ -123,8 +123,8 @@ class DtxTests(TestBase010):
self.assertMessageId("rollback", "queue-a")
def test_simple_prepare_rollback(self):
- """
- Test basic rollback behaviour after the transaction has been prepared.
+ """
+ Test basic rollback behaviour after the transaction has been prepared.
"""
guard = self.keepQueuesAlive(["queue-a", "queue-b"])
session = self.session
@@ -146,18 +146,18 @@ class DtxTests(TestBase010):
#check result
self.assertMessageCount(1, "queue-a")
self.assertMessageCount(0, "queue-b")
- self.assertMessageId("prepare-rollback", "queue-a")
+ self.assertMessageId("prepare-rollback", "queue-a")
def test_select_required(self):
"""
check that an error is flagged if select is not issued before
- start or end
+ start or end
"""
session = self.session
tx = self.xid("dummy")
try:
session.dtx_start(xid=tx)
-
+
#if we get here we have failed, but need to do some cleanup:
session.dtx_end(xid=tx)
session.dtx_rollback(xid=tx)
@@ -197,10 +197,10 @@ class DtxTests(TestBase010):
other.close()
session1.dtx_end(xid=tx)
session1.dtx_rollback(xid=tx)
-
+
#verification:
if failed: self.assertEquals(530, error.args[0].error_code)
- else: self.fail("Xid already known, expected exception!")
+ else: self.fail("Xid already known, expected exception!")
def test_forget_xid_on_completion(self):
"""
@@ -210,8 +210,8 @@ class DtxTests(TestBase010):
#do some transactional work & complete the transaction
self.test_simple_commit()
# session has been reset, so reselect for use with dtx
- self.session.dtx_select()
-
+ self.session.dtx_select()
+
#start association for the same xid as the previously completed txn
tx = self.xid("my-xid")
self.session.dtx_start(xid=tx)
@@ -237,9 +237,9 @@ class DtxTests(TestBase010):
self.assertEquals(503, e.args[0].error_code)
def test_start_join(self):
- """
+ """
Verify 'join' behaviour, where a session is associated with a
- transaction that is already associated with another session.
+ transaction that is already associated with another session.
"""
guard = self.keepQueuesAlive(["one", "two"])
#create two sessions & select them for use with dtx:
@@ -269,14 +269,14 @@ class DtxTests(TestBase010):
#mark end on both sessions
session1.dtx_end(xid=tx)
session2.dtx_end(xid=tx)
-
+
#commit and check
session1.dtx_commit(xid=tx, one_phase=True)
self.assertMessageCount(1, "one")
self.assertMessageCount(1, "two")
self.assertMessageId("a", "two")
self.assertMessageId("b", "one")
-
+
def test_suspend_resume(self):
"""
@@ -300,7 +300,7 @@ class DtxTests(TestBase010):
session.dtx_start(xid=tx, resume=True)
self.swap(session, "two", "one")#swap 'b' from 'two' to 'one'
session.dtx_end(xid=tx)
-
+
#commit and check
session.dtx_commit(xid=tx, one_phase=True)
self.assertMessageCount(1, "one")
@@ -308,7 +308,7 @@ class DtxTests(TestBase010):
self.assertMessageId("a", "two")
self.assertMessageId("b", "one")
- def test_suspend_start_end_resume(self):
+ def test_suspend_start_end_resume(self):
"""
Test suspension and resumption of an association with work
done on another transaction when the first transaction is
@@ -332,7 +332,7 @@ class DtxTests(TestBase010):
session.dtx_start(xid=tx, resume=True)
self.swap(session, "two", "one")#swap 'b' from 'two' to 'one'
session.dtx_end(xid=tx)
-
+
#commit and check
session.dtx_commit(xid=tx, one_phase=True)
self.assertMessageCount(1, "one")
@@ -341,10 +341,10 @@ class DtxTests(TestBase010):
self.assertMessageId("b", "one")
def test_end_suspend_and_fail(self):
- """
+ """
Verify that the correct error is signalled if the suspend and
fail flag are both set when disassociating a transaction from
- the session
+ the session
"""
session = self.session
session.dtx_select()
@@ -356,16 +356,16 @@ class DtxTests(TestBase010):
except SessionException, e:
self.assertEquals(503, e.args[0].error_code)
- #cleanup
+ #cleanup
other = self.connect()
session = other.session("cleanup", 1)
session.dtx_rollback(xid=tx)
session.close()
other.close()
-
+
def test_end_unknown_xid(self):
- """
+ """
Verifies that the correct exception is thrown when an attempt
is made to end the association for a xid not previously
associated with the session
@@ -382,7 +382,7 @@ class DtxTests(TestBase010):
def test_end(self):
"""
Verify that the association is terminated by end and subsequent
- operations are non-transactional
+ operations are non-transactional
"""
guard = self.keepQueuesAlive(["tx-queue"])
session = self.conn.session("alternate", 1)
@@ -408,7 +408,7 @@ class DtxTests(TestBase010):
session.message_accept(RangedSet(msg.id))
session.close()
- session = self.session
+ session = self.session
#commit the transaction and check that the first message (and
#only the first message) is then delivered
session.dtx_commit(xid=tx, one_phase=True)
@@ -418,7 +418,7 @@ class DtxTests(TestBase010):
def test_invalid_commit_one_phase_true(self):
"""
Test that a commit with one_phase = True is rejected if the
- transaction in question has already been prepared.
+ transaction in question has already been prepared.
"""
other = self.connect()
tester = other.session("tester", 1)
@@ -447,7 +447,7 @@ class DtxTests(TestBase010):
def test_invalid_commit_one_phase_false(self):
"""
Test that a commit with one_phase = False is rejected if the
- transaction in question has not yet been prepared.
+ transaction in question has not yet been prepared.
"""
other = self.connect()
tester = other.session("tester", 1)
@@ -474,7 +474,7 @@ class DtxTests(TestBase010):
def test_invalid_commit_not_ended(self):
"""
- Test that a commit fails if the xid is still associated with a session.
+ Test that a commit fails if the xid is still associated with a session.
"""
other = self.connect()
tester = other.session("tester", 1)
@@ -502,7 +502,7 @@ class DtxTests(TestBase010):
def test_invalid_rollback_not_ended(self):
"""
- Test that a rollback fails if the xid is still associated with a session.
+ Test that a rollback fails if the xid is still associated with a session.
"""
other = self.connect()
tester = other.session("tester", 1)
@@ -531,7 +531,7 @@ class DtxTests(TestBase010):
def test_invalid_prepare_not_ended(self):
"""
- Test that a prepare fails if the xid is still associated with a session.
+ Test that a prepare fails if the xid is still associated with a session.
"""
other = self.connect()
tester = other.session("tester", 1)
@@ -586,9 +586,9 @@ class DtxTests(TestBase010):
session1.dtx_rollback(xid=tx)
def test_get_timeout(self):
- """
+ """
Check that get-timeout returns the correct value, (and that a
- transaction with a timeout can complete normally)
+ transaction with a timeout can complete normally)
"""
session = self.session
tx = self.xid("dummy")
@@ -599,12 +599,12 @@ class DtxTests(TestBase010):
session.dtx_set_timeout(xid=tx, timeout=60)
self.assertEqual(60, session.dtx_get_timeout(xid=tx).timeout)
self.assertEqual(self.XA_OK, session.dtx_end(xid=tx).status)
- self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
-
+ self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
+
def test_set_timeout(self):
- """
+ """
Test the timeout of a transaction results in the expected
- behaviour
+ behaviour
"""
guard = self.keepQueuesAlive(["queue-a", "queue-b"])
@@ -627,7 +627,7 @@ class DtxTests(TestBase010):
self.assertMessageId("timeout", "queue-a")
#check the correct codes are returned when we try to complete the txn
self.assertEqual(self.XA_RBTIMEOUT, session.dtx_end(xid=tx).status)
- self.assertEqual(self.XA_RBTIMEOUT, session.dtx_rollback(xid=tx).status)
+ self.assertEqual(self.XA_RBTIMEOUT, session.dtx_rollback(xid=tx).status)
@@ -649,20 +649,20 @@ class DtxTests(TestBase010):
if i in [2, 5, 6, 8]:
session.dtx_prepare(xid=tx)
prepared.append(tx)
- else:
+ else:
session.dtx_rollback(xid=tx)
xids = session.dtx_recover().in_doubt
-
+
#rollback the prepared transactions returned by recover
for x in xids:
- session.dtx_rollback(xid=x)
+ session.dtx_rollback(xid=x)
#validate against the expected list of prepared transactions
actual = set([x.global_id for x in xids]) #TODO: come up with nicer way to test these
expected = set([x.global_id for x in prepared])
intersection = actual.intersection(expected)
-
+
if intersection != expected:
missing = expected.difference(actual)
extra = actual.difference(expected)
@@ -723,7 +723,7 @@ class DtxTests(TestBase010):
session.message_transfer(message=Message(dp, mp, "DtxMessage"))
#start the transaction:
- session.dtx_select()
+ session.dtx_select()
self.assertEqual(self.XA_OK, self.session.dtx_start(xid=tx).status)
#'swap' the message from one queue to the other, under that transaction:
@@ -760,7 +760,7 @@ class DtxTests(TestBase010):
def getMessageProperty(self, msg, prop):
for h in msg.headers:
if hasattr(h, prop): return getattr(h, prop)
- return None
+ return None
def keepQueuesAlive(self, names):
session = self.conn.session("nasty", 99)
@@ -768,7 +768,7 @@ class DtxTests(TestBase010):
session.queue_declare(queue=n, auto_delete=True)
session.message_subscribe(destination=n, queue=n)
return session
-
+
def createMessage(self, session, key, id, body):
dp=session.delivery_properties(routing_key=key)
mp=session.message_properties(correlation_id=id)
diff --git a/tests/src/py/qpid_tests/broker_0_10/exchange.py b/tests/src/py/qpid_tests/broker_0_10/exchange.py
index db52b36754..9a4cfd37d6 100644
--- a/tests/src/py/qpid_tests/broker_0_10/exchange.py
+++ b/tests/src/py/qpid_tests/broker_0_10/exchange.py
@@ -226,6 +226,8 @@ class DefaultExchangeRuleTests(TestHelper, StandardExchangeVerifier):
# Test automatic binding by queue name.
self.queue_declare(queue="d")
self.assertPublishConsume(queue="d", routing_key="d")
+ # Test explicit bind to default queue
+ self.verifyDirectExchange("")
# TODO aconway 2006-09-27: Fill in empty tests:
@@ -446,9 +448,9 @@ class MiscellaneousErrorsTests(TestHelper):
def testTypeNotKnown(self):
try:
self.session.exchange_declare(exchange="test_type_not_known_exchange", type="invalid_type")
- self.fail("Expected 404 for declaration of unknown exchange type.")
+ self.fail("Expected 503 for declaration of unknown exchange type.")
except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
+ self.assertEquals(503, e.args[0].error_code)
def testDifferentDeclaredType(self):
self.exchange_declare(exchange="test_different_declared_type_exchange", type="direct")
@@ -458,30 +460,7 @@ class MiscellaneousErrorsTests(TestHelper):
self.fail("Expected 530 for redeclaration of exchange with different type.")
except SessionException, e:
self.assertEquals(530, e.args[0].error_code)
-
- def testDefaultAccessBind(self):
- try:
- self.session.queue_declare(queue="my-queue", auto_delete=True, exclusive=True)
- self.session.exchange_bind(exchange="", queue="my-queue", binding_key="another-key")
- self.fail("Expected 542 (invalid-argument) code for bind to default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
- def testDefaultAccessUnbind(self):
- try:
- self.session.queue_declare(queue="my-queue", auto_delete=True, exclusive=True)
- self.session.exchange_unbind(exchange="", queue="my-queue", binding_key="my-queue")
- self.fail("Expected 542 (invalid-argument) code for unbind from default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
- def testDefaultAccessDelete(self):
- try:
- self.session.exchange_delete(exchange="")
- self.fail("Expected 542 (invalid-argument) code for delete of default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
+
class ExchangeTests(TestHelper):
def testHeadersBindNoMatchArg(self):
self.session.queue_declare(queue="q", exclusive=True, auto_delete=True)
diff --git a/tests/src/py/qpid_tests/broker_0_10/extensions.py b/tests/src/py/qpid_tests/broker_0_10/extensions.py
index 50c0aa3dd1..26ea3cb0e9 100644
--- a/tests/src/py/qpid_tests/broker_0_10/extensions.py
+++ b/tests/src/py/qpid_tests/broker_0_10/extensions.py
@@ -20,8 +20,6 @@ from qpid.client import Client, Closed
from qpid.queue import Empty
from qpid.content import Content
from qpid.testlib import TestBase010
-from qpid.session import SessionException
-from qpid.datatypes import uuid4
from time import sleep
class ExtensionTests(TestBase010):
@@ -30,58 +28,10 @@ class ExtensionTests(TestBase010):
def test_timed_autodelete(self):
session = self.session
session2 = self.conn.session("another-session")
- name=str(uuid4())
- session2.queue_declare(queue=name, exclusive=True, auto_delete=True, arguments={"qpid.auto_delete_timeout":3})
+ session2.queue_declare(queue="my-queue", exclusive=True, auto_delete=True, arguments={"qpid.auto_delete_timeout":5})
session2.close()
- result = session.queue_query(queue=name)
- self.assertEqual(name, result.queue)
+ result = session.queue_query(queue="my-queue")
+ self.assertEqual("my-queue", result.queue)
sleep(5)
- result = session.queue_query(queue=name)
+ result = session.queue_query(queue="my-queue")
self.assert_(not result.queue)
-
- def valid_policy_args(self, args, name="test-queue"):
- try:
- self.session.queue_declare(queue=name, arguments=args)
- self.session.queue_delete(queue=name) # cleanup
- except SessionException, e:
- self.fail("declare with valid policy args failed: %s" % (args))
- self.session = self.conn.session("replacement", 2)
-
- def invalid_policy_args(self, args, name="test-queue"):
- # go through invalid declare attempts twice to make sure that
- # the queue doesn't actually get created first time around
- # even if exception is thrown
- for i in range(1, 3):
- try:
- self.session.queue_declare(queue=name, arguments=args)
- self.session.queue_delete(queue=name) # cleanup
- self.fail("declare with invalid policy args suceeded: %s (iteration %d)" % (args, i))
- except SessionException, e:
- self.session = self.conn.session(str(uuid4()))
-
- def test_policy_max_size_as_valid_string(self):
- self.valid_policy_args({"qpid.max_size":"3"})
-
- def test_policy_max_count_as_valid_string(self):
- self.valid_policy_args({"qpid.max_count":"3"})
-
- def test_policy_max_count_and_size_as_valid_strings(self):
- self.valid_policy_args({"qpid.max_count":"3","qpid.max_size":"0"})
-
- def test_policy_negative_count(self):
- self.invalid_policy_args({"qpid.max_count":-1})
-
- def test_policy_negative_size(self):
- self.invalid_policy_args({"qpid.max_size":-1})
-
- def test_policy_size_as_invalid_string(self):
- self.invalid_policy_args({"qpid.max_size":"foo"})
-
- def test_policy_count_as_invalid_string(self):
- self.invalid_policy_args({"qpid.max_count":"foo"})
-
- def test_policy_size_as_float(self):
- self.invalid_policy_args({"qpid.max_size":3.14159})
-
- def test_policy_count_as_float(self):
- self.invalid_policy_args({"qpid.max_count":"2222222.22222"})
diff --git a/tests/src/py/qpid_tests/broker_0_10/management.py b/tests/src/py/qpid_tests/broker_0_10/management.py
index ac6d7578da..06f3212a6f 100644
--- a/tests/src/py/qpid_tests/broker_0_10/management.py
+++ b/tests/src/py/qpid_tests/broker_0_10/management.py
@@ -156,7 +156,7 @@ class ManagementTest (TestBase010):
queues = self.qmf.getObjects(_class="queue")
"Move 10 messages from src-queue to dest-queue"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 10, {})
+ result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 10)
self.assertEqual (result.status, 0)
sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
@@ -166,7 +166,7 @@ class ManagementTest (TestBase010):
self.assertEqual (dq.msgDepth,10)
"Move all remaining messages to destination"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 0, {})
+ result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 0)
self.assertEqual (result.status,0)
sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
@@ -176,16 +176,16 @@ class ManagementTest (TestBase010):
self.assertEqual (dq.msgDepth,20)
"Use a bad source queue name"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("bad-src-queue", "dest-queue", 0, {})
+ result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("bad-src-queue", "dest-queue", 0)
self.assertEqual (result.status,4)
"Use a bad destination queue name"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "bad-dest-queue", 0, {})
+ result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "bad-dest-queue", 0)
self.assertEqual (result.status,4)
" Use a large qty (40) to move from dest-queue back to "
" src-queue- should move all "
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("dest-queue", "src-queue", 40, {})
+ result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("dest-queue", "src-queue", 40)
self.assertEqual (result.status,0)
sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
@@ -225,55 +225,23 @@ class ManagementTest (TestBase010):
pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
"Purge top message from purge-queue"
- result = pq.purge(1, {})
+ result = pq.purge(1)
self.assertEqual (result.status, 0)
pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
self.assertEqual (pq.msgDepth,19)
"Purge top 9 messages from purge-queue"
- result = pq.purge(9, {})
+ result = pq.purge(9)
self.assertEqual (result.status, 0)
pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
self.assertEqual (pq.msgDepth,10)
"Purge all messages from purge-queue"
- result = pq.purge(0, {})
+ result = pq.purge(0)
self.assertEqual (result.status, 0)
pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
self.assertEqual (pq.msgDepth,0)
- def test_reroute_priority_queue(self):
- self.startQmf()
- session = self.session
-
- #setup test queue supporting multiple priority levels
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True, arguments={'x-qpid-priorities':10})
-
- #send some messages of varying priority to that queue:
- for i in range(0, 5):
- deliveryProps = session.delivery_properties(routing_key="test-queue", priority=i+5)
- session.message_transfer(message=Message(deliveryProps, "Message %d" % (i+1)))
-
-
- #declare and bind a queue to amq.fanout through which rerouted
- #messages can be verified:
- session.queue_declare(queue="rerouted", exclusive=True, auto_delete=True, arguments={'x-qpid-priorities':10})
- session.exchange_bind(queue="rerouted", exchange="amq.fanout")
-
- #reroute messages from test queue to amq.fanout (and hence to
- #rerouted queue):
- pq = self.qmf.getObjects(_class="queue", name="test-queue")[0]
- result = pq.reroute(0, False, "amq.fanout", {})
- self.assertEqual(result.status, 0)
-
- #verify messages are all rerouted:
- self.subscribe(destination="incoming", queue="rerouted")
- incoming = session.incoming("incoming")
- for i in range(0, 5):
- msg = incoming.get(timeout=1)
- self.assertEqual("Message %d" % (5-i), msg.body)
-
-
def test_reroute_queue(self):
"""
Test ability to reroute messages from the head of a queue.
@@ -301,7 +269,7 @@ class ManagementTest (TestBase010):
pq = self.qmf.getObjects(_class="queue", name="reroute-queue")[0]
"Reroute top message from reroute-queue to alternate exchange"
- result = pq.reroute(1, True, "", {})
+ result = pq.reroute(1, True, "")
self.assertEqual(result.status, 0)
pq.update()
aq = self.qmf.getObjects(_class="queue", name="alt-queue1")[0]
@@ -309,7 +277,7 @@ class ManagementTest (TestBase010):
self.assertEqual(aq.msgDepth,1)
"Reroute top 9 messages from reroute-queue to alt.direct2"
- result = pq.reroute(9, False, "alt.direct2", {})
+ result = pq.reroute(9, False, "alt.direct2")
self.assertEqual(result.status, 0)
pq.update()
aq = self.qmf.getObjects(_class="queue", name="alt-queue2")[0]
@@ -317,11 +285,11 @@ class ManagementTest (TestBase010):
self.assertEqual(aq.msgDepth,9)
"Reroute using a non-existent exchange"
- result = pq.reroute(0, False, "amq.nosuchexchange", {})
+ result = pq.reroute(0, False, "amq.nosuchexchange")
self.assertEqual(result.status, 4)
"Reroute all messages from reroute-queue"
- result = pq.reroute(0, False, "alt.direct2", {})
+ result = pq.reroute(0, False, "alt.direct2")
self.assertEqual(result.status, 0)
pq.update()
aq = self.qmf.getObjects(_class="queue", name="alt-queue2")[0]
@@ -337,44 +305,11 @@ class ManagementTest (TestBase010):
session.message_transfer(destination="amq.direct", message=msg)
"Reroute onto the same queue"
- result = pq.reroute(0, False, "amq.direct", {})
+ result = pq.reroute(0, False, "amq.direct")
self.assertEqual(result.status, 0)
pq.update()
self.assertEqual(pq.msgDepth,20)
-
- def test_reroute_alternate_exchange(self):
- """
- Test that when rerouting, the alternate-exchange is considered if relevant
- """
- self.startQmf()
- session = self.session
- # 1. Create 2 exchanges A and B (fanout) where B is the
- # alternate exchange for A
- session.exchange_declare(exchange="B", type="fanout")
- session.exchange_declare(exchange="A", type="fanout", alternate_exchange="B")
-
- # 2. Bind queue X to B
- session.queue_declare(queue="X", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="X", exchange="B")
-
- # 3. Send 1 message to queue Y
- session.queue_declare(queue="Y", exclusive=True, auto_delete=True)
- props = session.delivery_properties(routing_key="Y")
- session.message_transfer(message=Message(props, "reroute me!"))
-
- # 4. Call reroute on queue Y and specify that messages should
- # be sent to exchange A
- y = self.qmf.getObjects(_class="queue", name="Y")[0]
- result = y.reroute(1, False, "A", {})
- self.assertEqual(result.status, 0)
-
- # 5. verify that the message is rerouted through B (as A has
- # no matching bindings) to X
- self.subscribe(destination="x", queue="X")
- self.assertEqual("reroute me!", session.incoming("x").get(timeout=1).body)
-
- # Cleanup
- for e in ["A", "B"]: session.exchange_delete(exchange=e)
+
def test_methods_async (self):
"""
@@ -584,63 +519,4 @@ class ManagementTest (TestBase010):
conn_qmf.update()
self.assertEqual(conn_qmf.msgsToClient, 1)
- def test_timestamp_config(self):
- """
- Test message timestamping control.
- """
- self.startQmf()
- conn = self.connect()
- session = conn.session("timestamp-session")
-
- #verify that receive message timestamping is OFF by default
- broker = self.qmf.getObjects(_class="broker")[0]
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
- #self.assertEqual(rc.receive, False)
-
- #try to enable it
- rc = broker.setTimestampConfig(True)
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
-
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
- self.assertEqual(rc.receive, True)
-
- #send a message to a queue
- session.queue_declare(queue="ts-q", exclusive=True, auto_delete=True)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="ts-q"), "abc"))
-
- #receive message from queue, and verify timestamp is present
- session.message_subscribe(destination="d", queue="ts-q")
- session.message_flow(destination="d", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="d", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- incoming = session.incoming("d")
- msg = incoming.get(timeout=1)
- self.assertEqual("abc", msg.body)
- self.assertEqual(msg.has("delivery_properties"), True)
- dp = msg.get("delivery_properties")
- assert(dp.timestamp)
-
- #try to disable it
- rc = broker.setTimestampConfig(False)
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
-
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
- self.assertEqual(rc.receive, False)
-
- #send another message to the queue
- session.message_transfer(message=Message(session.delivery_properties(routing_key="ts-q"), "def"))
-
- #receive message from queue, and verify timestamp is NOT PRESENT
- msg = incoming.get(timeout=1)
- self.assertEqual("def", msg.body)
- self.assertEqual(msg.has("delivery_properties"), True)
- dp = msg.get("delivery_properties")
- self.assertEqual(dp.timestamp, None)
-
+
diff --git a/tests/src/py/qpid_tests/broker_0_10/message.py b/tests/src/py/qpid_tests/broker_0_10/message.py
index 6c864bcd13..e80333a1e6 100644
--- a/tests/src/py/qpid_tests/broker_0_10/message.py
+++ b/tests/src/py/qpid_tests/broker_0_10/message.py
@@ -245,46 +245,26 @@ class MessageTests(TestBase010):
self.fail("Got message after cancellation: " + msg)
except Empty: None
- #cancellation of non-existant consumers should be result in 404s
- try:
- session.message_cancel(destination="my-consumer")
- self.fail("Expected 404 for recancellation of subscription.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- session = self.conn.session("alternate-session", timeout=10)
- try:
- session.message_cancel(destination="this-never-existed")
- self.fail("Expected 404 for cancellation of unknown subscription.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
+ #cancellation of non-existant consumers should be handled without error
+ session.message_cancel(destination="my-consumer")
+ session.message_cancel(destination="this-never-existed")
def test_ack(self):
"""
- Test basic ack/recover behaviour using a combination of implicit and
- explicit accept subscriptions.
+ Test basic ack/recover behaviour
"""
- self.startQmf()
- session1 = self.conn.session("alternate-session", timeout=10)
- session1.queue_declare(queue="test-ack-queue", auto_delete=True)
-
- delivery_properties = session1.delivery_properties(routing_key="test-ack-queue")
- for i in ["One", "Two", "Three", "Four", "Five"]:
- session1.message_transfer(message=Message(delivery_properties, i))
+ session = self.conn.session("alternate-session", timeout=10)
+ session.queue_declare(queue="test-ack-queue", auto_delete=True)
- # verify enqueued message count, use both QMF and session query to verify consistency
- self.assertEqual(5, session1.queue_query(queue="test-ack-queue").message_count)
- queueObj = self.qmf.getObjects(_class="queue", name="test-ack-queue")[0]
- self.assertEquals(queueObj.msgDepth, 5)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 0)
+ session.message_subscribe(queue = "test-ack-queue", destination = "consumer")
+ session.message_flow(destination="consumer", unit=session.credit_unit.message, value=0xFFFFFFFFL)
+ session.message_flow(destination="consumer", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
+ queue = session.incoming("consumer")
- # subscribe with implied acquire, explicit accept:
- session1.message_subscribe(queue = "test-ack-queue", destination = "consumer")
- session1.message_flow(destination="consumer", unit=session1.credit_unit.message, value=0xFFFFFFFFL)
- session1.message_flow(destination="consumer", unit=session1.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session1.incoming("consumer")
+ delivery_properties = session.delivery_properties(routing_key="test-ack-queue")
+ for i in ["One", "Two", "Three", "Four", "Five"]:
+ session.message_transfer(message=Message(delivery_properties, i))
msg1 = queue.get(timeout=1)
msg2 = queue.get(timeout=1)
@@ -298,46 +278,20 @@ class MessageTests(TestBase010):
self.assertEqual("Four", msg4.body)
self.assertEqual("Five", msg5.body)
- # messages should not be on the queue:
- self.assertEqual(0, session1.queue_query(queue="test-ack-queue").message_count)
- # QMF shows the dequeues as not having happened yet, since they are have
- # not been accepted
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 5)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 0)
-
- session1.message_accept(RangedSet(msg1.id, msg2.id, msg4.id))#One, Two and Four
-
- # QMF should now reflect the accepted messages as being dequeued
- self.assertEqual(0, session1.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 2)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 3)
-
- #subscribe from second session here to ensure queue is not auto-deleted
- #when alternate session closes. Use implicit accept mode to test that
- #we don't need to explicitly accept
- session2 = self.conn.session("alternate-session-2", timeout=10)
- session2.message_subscribe(queue = "test-ack-queue", destination = "checker", accept_mode=1)
-
- #now close the first session, and see that the unaccepted messages are
- #then redelivered to another subscriber:
- session1.close(timeout=10)
+ session.message_accept(RangedSet(msg1.id, msg2.id, msg4.id))#One, Two and Four
- # check the statistics - the queue_query will show the non-accepted
- # messages have been released. QMF never considered them dequeued, so
- # those counts won't change
- self.assertEqual(2, session2.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 2)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 3)
+ #subscribe from second session here to ensure queue is not
+ #auto-deleted when alternate session closes (no need to ack on these):
+ self.session.message_subscribe(queue = "test-ack-queue", destination = "checker", accept_mode=1)
- session2.message_flow(destination="checker", unit=session2.credit_unit.message, value=0xFFFFFFFFL)
- session2.message_flow(destination="checker", unit=session2.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session2.incoming("checker")
+ #now close the session, and see that the unacked messages are
+ #then redelivered to another subscriber:
+ session.close(timeout=10)
+
+ session = self.session
+ session.message_flow(destination="checker", unit=session.credit_unit.message, value=0xFFFFFFFFL)
+ session.message_flow(destination="checker", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
+ queue = session.incoming("checker")
msg3b = queue.get(timeout=1)
msg5b = queue.get(timeout=1)
@@ -350,33 +304,6 @@ class MessageTests(TestBase010):
self.fail("Got unexpected message: " + extra.body)
except Empty: None
- self.assertEqual(0, session2.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 0)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 5)
-
- # Subscribe one last time to keep the queue available, and to verify
- # that the implied accept worked by verifying no messages have been
- # returned when session2 is closed.
- self.session.message_subscribe(queue = "test-ack-queue", destination = "final-checker")
-
- session2.close(timeout=10)
-
- # check the statistics - they should not have changed
- self.assertEqual(0, self.session.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 0)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 5)
-
- self.session.message_flow(destination="final-checker", unit=self.session.credit_unit.message, value=0xFFFFFFFFL)
- self.session.message_flow(destination="final-checker", unit=self.session.credit_unit.byte, value=0xFFFFFFFFL)
- try:
- extra = self.session.incoming("final-checker").get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
def test_reject(self):
session = self.session
session.queue_declare(queue = "q", exclusive=True, auto_delete=True, alternate_exchange="amq.fanout")
@@ -571,47 +498,6 @@ class MessageTests(TestBase010):
msgB = q.get(timeout=10)
- def test_window_stop(self):
- """
- Ensure window based flow control reacts to stop correctly
- """
- session = self.session
- #setup subscriber on a test queue
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 1, destination = "c")
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
-
-
- #send batch of messages to queue
- for i in range(0, 10):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %d" % (i+1)))
-
- #retrieve all delivered messages
- q = session.incoming("c")
- for i in range(0, 5):
- msg = q.get(timeout = 1)
- session.receiver._completed.add(msg.id)#TODO: this may be done automatically
- self.assertDataEquals(session, msg, "Message %d" % (i+1))
-
- session.message_stop(destination = "c")
-
- #now send completions, normally used to move window forward,
- #but after a stop should not do so
- session.channel.session_completed(session.receiver._completed)
-
- #check no more messages are sent
- self.assertEmpty(q)
-
- #re-establish window and check remaining messages
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
- for i in range(0, 5):
- msg = q.get(timeout = 1)
- self.assertDataEquals(session, msg, "Message %d" % (i+6))
-
-
def test_subscribe_not_acquired(self):
"""
Test the not-acquired modes works as expected for a simple case
@@ -1016,6 +902,7 @@ class MessageTests(TestBase010):
assert messages.get(timeout=1).body == "second"
self.assertEmpty(messages)
+
def assertDataEquals(self, session, msg, expected):
self.assertEquals(expected, msg.body)
diff --git a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py b/tests/src/py/qpid_tests/broker_0_10/msg_groups.py
deleted file mode 100644
index 99d11151e8..0000000000
--- a/tests/src/py/qpid_tests/broker_0_10/msg_groups.py
+++ /dev/null
@@ -1,1077 +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.
-#
-
-from qpid.messaging import *
-from qpid.tests.messaging import Base
-import qmf.console
-
-from time import sleep
-#
-# Tests the Broker's support for message groups
-#
-
-class MultiConsumerMsgGroupTests(Base):
- """
- Tests for the behavior of multi-consumer message groups. These tests allow
- a messages from the same group be consumed by multiple different clients as
- long as each message is processed "in sequence". See QPID-3346 for
- details.
- """
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def test_simple(self):
- """ Verify simple acquire/accept actions on a set of grouped
- messages shared between two receivers.
- """
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","A","B","B","B","C","C","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = a-0, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ---, ---, ---, ---, ---, ---, ---, ---,
-
- # create consumers on separate sessions: C1,C2
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 should acquire A-0, then C2 should acquire B-3
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0);
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # C1 Acknowledge A-0
- c1.session.acknowledge(m1);
-
- # C2 should next acquire A-1
- m3 = c2.fetch(0);
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 1
-
- # C1 should next acquire C-6, since groups A&B are held by c2
- m4 = c1.fetch(0);
- assert m4.properties['THE-GROUP'] == 'C'
- assert m4.content['index'] == 6
-
- ## Queue = XXX, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ^C2, +C2, +C2, ^C1, +C1, +C1,
-
- # C2 Acknowledge B-3, freeing up the rest of B group
- c2.session.acknowledge(m2);
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ---, ---, ^C1, +C1, +C1,
-
- # C1 should now acquire B-4, since it is next "free"
- m5 = c1.fetch(0);
- assert m5.properties['THE-GROUP'] == 'B'
- assert m5.content['index'] == 4
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ^C1, +C1, ^C1, +C1, +C1,
-
- # C1 acknowledges C-6, freeing the C group
- c1.session.acknowledge(m4)
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, XXX, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ^C1, +C1, ---, ---, ---
-
- # C2 should next fetch A-2, followed by C-7
- m7 = c2.fetch(0);
- assert m7.properties['THE-GROUP'] == 'A'
- assert m7.content['index'] == 2
-
- m8 = c2.fetch(0);
- assert m8.properties['THE-GROUP'] == 'C'
- assert m8.content['index'] == 7
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, XXX, c-7, c-8...
- ## Owners= ---, ^C2, ^C2, ---, ^C1, +C1, ---, ^C2, +C2
-
- # have C2 ack all fetched messages, freeing C-8
- c2.session.acknowledge()
-
- ## Queue = XXX, XXX, XXX, XXX, b-4, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ^C1, +C1, ---, ---, ---
-
- # the next fetch of C2 would get C-8, since B-5 is "owned"
- m9 = c2.fetch(0);
- assert m9.properties['THE-GROUP'] == 'C'
- assert m9.content['index'] == 8
-
- ## Queue = XXX, XXX, XXX, XXX, b-4, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ^C1, +C1, ---, ---, ^C2
-
- # C1 acks B-4, freeing B-5 for consumption
- c1.session.acknowledge(m5)
-
- ## Queue = XXX, XXX, XXX, XXX, XXX, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ---, ^C2, ---, ---, ^C2
-
- # the next fetch of C2 would get B-5
- m10 = c2.fetch(0);
- assert m10.properties['THE-GROUP'] == 'B'
- assert m10.content['index'] == 5
-
- # there should be no more left for C1:
- try:
- mx = c1.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- c1.session.acknowledge()
- c2.session.acknowledge()
- c1.close()
- c2.close()
- snd.close()
-
- def test_simple_browse(self):
- """ Test the behavior of a browsing subscription on a message grouping
- queue.
- """
-
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ---, ---, ---, ---, ---
-
- # create consumer and browser
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
-
- # C1 should acquire A-0
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ^C1, ---, +C1, ---, ---
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # verify that the browser may see A-2, even though its group is owned
- # by C1
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # verify the consumer can own groups currently seen by the browser
- m3 = c1.fetch(0);
- assert m3.properties['THE-GROUP'] == 'B'
- assert m3.content['index'] == 1
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'C'
- assert m2.content['index'] == 4
-
- def test_release(self):
- """ Verify releasing a message can free its assocated group
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 release m1, and the first group
-
- s1.acknowledge(m1, Disposition(RELEASED, set_redelivered=True))
-
- # C2 should be able to get group 'A', msg 'A-0' now
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
- def test_reject(self):
- """ Verify rejecting a message can free its associated group
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 rejects m1, and the first group is released
- s1.acknowledge(m1, Disposition(REJECTED))
-
- # C2 should be able to get group 'A', msg 'A-1' now
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 1
-
- def test_close(self):
- """ Verify behavior when a consumer that 'owns' a group closes.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 will own group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 will own group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 shuffles off the mortal coil...
- c1.close();
-
- # but the session (s1) remains active, so "A" remains blocked
- # from c2, c2 should fetch the next B-3
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # and there should be no more messages available for C2
- try:
- m2 = c2.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- # close session s1, releasing the A group
- s1.close()
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 1
-
- # and there should be no more messages now
- try:
- m2 = c2.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- def test_transaction(self):
- """ Verify behavior when using transactions.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B","A","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.conn.session(transactional=True)
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.conn.session(transactional=True)
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 gets group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 gets group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- s1.acknowledge(m1) # A-0 consumed, A group freed
- s2.acknowledge(m2) # B-2 consumed, B group freed
-
- s1.commit() # A-0 consumption done, A group now free
- s2.rollback() # releases B-2, and group B
-
- ## Q: ["A1","B2","B3","A4","B5"]
-
- # C2 should be able to get the next A
- m3 = c2.fetch(0)
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 1
-
- # C1 should be able to get B-2
- m4 = c1.fetch(0)
- assert m4.properties['THE-GROUP'] == 'B'
- assert m4.content['index'] == 2
-
- s2.acknowledge(m3) # C2 consumes A-1
- s1.acknowledge(m4) # C1 consumes B-2
- s1.commit() # C1 consume B-2 occurs, free group B
-
- ## Q: [["A1",]"B3","A4","B5"]
-
- # A-1 is still considered owned by C2, since the commit has yet to
- # occur, so the next available to C1 would be B-3
- m5 = c1.fetch(0) # B-3
- assert m5.properties['THE-GROUP'] == 'B'
- assert m5.content['index'] == 3
-
- # and C2 should find A-4 available, since it owns the A group
- m6 = c2.fetch(0) # A-4
- assert m6.properties['THE-GROUP'] == 'A'
- assert m6.content['index'] == 4
-
- s2.acknowledge(m6) # C2 consumes A-4
-
- # uh-oh, A-1 and A-4 released, along with A group
- s2.rollback()
-
- ## Q: ["A1",["B3"],"A4","B5"]
- m7 = c1.fetch(0) # A-1 is found
- assert m7.properties['THE-GROUP'] == 'A'
- assert m7.content['index'] == 1
-
- ## Q: [["A1"],["B3"],"A4","B5"]
- # since C1 "owns" both A and B group, C2 should find nothing available
- try:
- m8 = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # C1 next gets A4
- m9 = c1.fetch(0)
- assert m9.properties['THE-GROUP'] == 'A'
- assert m9.content['index'] == 4
-
- s1.acknowledge()
-
- ## Q: [["A1"],["B3"],["A4"],"B5"]
- # even though C1 acknowledges A1,B3, and A4, B5 is still considered
- # owned as the commit has yet to take place
- try:
- m10 = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # now A1,B3,A4 dequeued, B5 should be free
- s1.commit()
-
- ## Q: ["B5"]
- m11 = c2.fetch(0)
- assert m11.properties['THE-GROUP'] == 'B'
- assert m11.content['index'] == 5
-
- s2.acknowledge()
- s2.commit()
-
- def test_send_transaction(self):
- """ Verify behavior when sender is using transactions.
- """
- ssn = self.conn.session(transactional=True)
- snd = ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- msg = Message(content={'index':0}, properties={"THE-GROUP": "A"})
- snd.send(msg)
- msg = Message(content={'index':1}, properties={"THE-GROUP": "B"})
- snd.send(msg)
- snd.session.commit()
- msg = Message(content={'index':2}, properties={"THE-GROUP": "A"})
- snd.send(msg)
-
- # Queue: [A0,B1, (uncommitted: A2) ]
-
- s1 = self.conn.session(transactional=True)
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.conn.session(transactional=True)
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 gets A0, group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 gets B2, group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # Since A2 uncommitted, there should be nothing left to fetch
- try:
- mX = c1.fetch(0)
- assert False # should not get here
- except Empty:
- pass
- try:
- mX = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- snd.session.commit()
- msg = Message(content={'index':3}, properties={"THE-GROUP": "B"})
- snd.send(msg)
-
- # Queue: [A2, (uncommitted: B3) ]
-
- # B3 has yet to be committed, so C2 should see nothing available:
- try:
- mX = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # but A2 should be available to C1
- m3 = c1.fetch(0)
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 2
-
- # now make B3 available
- snd.session.commit()
-
- # C1 should still be done:
- try:
- mX = c1.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # but C2 should find the new B
- m4 = c2.fetch(0)
- assert m4.properties['THE-GROUP'] == 'B'
- assert m4.content['index'] == 3
-
- # extra: have C1 rollback, verify C2 finds the released 'A' messages
- c1.session.rollback()
-
- ## Q: ["A0","A2"]
-
- # C2 should be able to get the next A
- m5 = c2.fetch(0)
- assert m5.properties['THE-GROUP'] == 'A'
- assert m5.content['index'] == 0
-
- m6 = c2.fetch(0)
- assert m6.properties['THE-GROUP'] == 'A'
- assert m6.content['index'] == 2
-
- c2.session.acknowledge()
- c2.session.commit()
-
- def test_query(self):
- """ Verify the queue query method against message groups
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","C","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- m2 = c2.fetch(0)
-
- # at this point, group A should be owned by C1, group B by C2, and
- # group C should be available
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
-
- # verify the query method call's group information
- rc = broker.query("queue", "msg-group-q")
- assert rc.status == 0
- assert rc.text == "OK"
- results = rc.outArgs['results']
- assert 'qpid.message_group_queue' in results
- q_info = results['qpid.message_group_queue']
- assert 'group_header_key' in q_info and q_info['group_header_key'] == "THE-GROUP"
- assert 'group_state' in q_info and len(q_info['group_state']) == 3
- for g_info in q_info['group_state']:
- assert 'group_id' in g_info
- if g_info['group_id'] == "A":
- assert g_info['msg_count'] == 3
- assert g_info['consumer'] != ""
- elif g_info['group_id'] == "B":
- assert g_info['msg_count'] == 2
- assert g_info['consumer'] != ""
- elif g_info['group_id'] == "C":
- assert g_info['msg_count'] == 2
- assert g_info['consumer'] == ""
- else:
- assert(False) # should never get here
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_free(self):
- """ Verify we can purge a queue of all messages of a given "unowned"
- group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "B" }}
- assert queue.msgDepth == 6
- rc = queue.purge(0, msg_filter)
- assert rc.status == 0
- queue.update()
- assert queue.msgDepth == 4
-
- # verify all B's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'B'
- count += 1
- except Empty:
- pass
- assert count == 4
-
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_acquired(self):
- """ Verify we can purge messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can purge group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.purge(0, msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 4 # the pending acquired A still counts!
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_count(self):
- """ Verify we can purge a fixed number of messages from an acquired
- group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can purge group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.purge(1, msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 5 # the pending acquired A still counts!
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- a_count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- if m2.properties['THE-GROUP'] != 'A':
- count += 1
- else:
- a_count += 1
- except Empty:
- pass
- assert count == 3 # non-A's
- assert a_count == 1 # and one is an A
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_move_all(self):
- """ Verify we can move messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # set up destination queue
- rcvr = self.ssn.receiver("dest-q; {create:always, delete:receiver," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can move what's left of group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- rc = broker.queueMoveMessages("msg-group-q", "dest-q", 0, msg_filter)
- assert rc.status == 0
-
- # verify all other A's removed from msg-group-q
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
-
- # verify the moved A's are at the dest-q
- s2 = self.setup_session()
- b1 = s2.receiver("dest-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2 or m2.content['index'] == 5
- count += 1
- except Empty:
- pass
- assert count == 2 # two A's moved
-
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_move_count(self):
- """ Verify we can move a fixed number of messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # set up destination queue
- rcvr = self.ssn.receiver("dest-q; {create:always, delete:receiver," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- # now setup a QMF session, so we can move group B
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "B" }}
- rc = broker.queueMoveMessages("msg-group-q", "dest-q", 3, msg_filter)
- assert rc.status == 0
-
- # verify all B's removed from msg-group-q
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'B'
- count += 1
- except Empty:
- pass
- assert count == 4
-
- # verify the moved B's are at the dest-q
- s2 = self.setup_session()
- b1 = s2.receiver("dest-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1 or m2.content['index'] == 3
- count += 1
- except Empty:
- pass
- assert count == 2
-
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_reroute(self):
- """ Verify we can reroute messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # create a topic exchange for the reroute
- rcvr = self.ssn.receiver("reroute-q; {create: always, delete:receiver," +
- " node: {type: topic}}")
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can reroute group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.reroute(0, False, "reroute-q", msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 4 # the pending acquired A still counts!
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
-
- # and what of reroute-q?
- count = 0
- try:
- while True:
- m2 = rcvr.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2 or m2.content['index'] == 5
- count += 1
- except Empty:
- pass
- assert count == 2
-
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_queue_delete(self):
- """ Test deleting a queue while consumers are active.
- """
-
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ---, ---, ---, ---, ---
-
- # create consumers
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 should acquire A-0
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # c2 acquires B-1
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # with group A and B owned, and C free, delete the
- # queue
- snd.close()
- self.ssn.close()
-
- def test_default_group_id(self):
- """ Verify the queue assigns the default group id should a message
- arrive without a group identifier.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- m = Message(content={}, properties={"NO-GROUP-HEADER":"HA-HA"})
- snd.send(m)
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
-
- # grab the group state off the queue, and verify the default group is
- # present ("qpid.no-group" is the broker default)
- rc = broker.query("queue", "msg-group-q")
- assert rc.status == 0
- assert rc.text == "OK"
- results = rc.outArgs['results']
- assert 'qpid.message_group_queue' in results
- q_info = results['qpid.message_group_queue']
- assert 'group_header_key' in q_info and q_info['group_header_key'] == "THE-GROUP"
- assert 'group_state' in q_info and len(q_info['group_state']) == 1
- g_info = q_info['group_state'][0]
- assert 'group_id' in g_info
- assert g_info['group_id'] == 'qpid.no-group'
-
- self.qmf_session.delBroker(self.qmf_broker)
-
-
-class StickyConsumerMsgGroupTests(Base):
- """
- Tests for the behavior of sticky-consumer message groups. These tests
- expect all messages from the same group be consumed by the same clients.
- See QPID-3347 for details.
- """
- pass # TBD
diff --git a/tests/src/py/qpid_tests/broker_0_10/priority.py b/tests/src/py/qpid_tests/broker_0_10/priority.py
index 6a60add97e..3651a1218b 100644
--- a/tests/src/py/qpid_tests/broker_0_10/priority.py
+++ b/tests/src/py/qpid_tests/broker_0_10/priority.py
@@ -33,13 +33,13 @@ class PriorityTests (Base):
def setup_session(self):
return self.conn.session()
- def prioritised_delivery(self, priorities, levels=10, key="x-qpid-priorities"):
+ def prioritised_delivery(self, priorities, levels=10):
"""
Test that message on a queue are delivered in priority order.
"""
msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
- snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{'%s':%s}}}}" % (key, levels),
+ snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{x-qpid-priorities:%s}}}}" % levels,
durable=self.durable())
for m in msgs: snd.send(m)
@@ -50,16 +50,16 @@ class PriorityTests (Base):
assert msg.content == expected.content
self.ssn.acknowledge(msg)
- def fairshare_delivery(self, priorities, default_limit=5, limits=None, levels=10, level_key="x-qpid-priorities", fairshare_key="x-qpid-fairshare"):
+ def fairshare_delivery(self, priorities, default_limit=5, limits=None, levels=10):
msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
- limit_policy = "'%s':%s" % (fairshare_key, default_limit)
+ limit_policy = "x-qpid-fairshare:%s" % default_limit
if limits:
for k, v in limits.items():
- limit_policy += ", '%s-%s':%s" % (fairshare_key, k, v)
+ limit_policy += ", x-qpid-fairshare-%s:%s" % (k, v)
- snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{'%s':%s, %s}}}}"
- % (level_key, levels, limit_policy),
+ snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{x-qpid-priorities:%s, %s}}}}"
+ % (levels, limit_policy),
durable=self.durable())
for m in msgs: snd.send(m)
@@ -79,18 +79,12 @@ class PriorityTests (Base):
def test_prioritised_delivery_1(self):
self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,15,7,8,10,10,2], levels = 10)
- def test_prioritised_delivery_with_alias(self):
- self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,15,7,8,10,10,2], levels = 10, key="qpid.priorities")
-
def test_prioritised_delivery_2(self):
self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,15,7,8,10,10,2], levels = 5)
def test_fairshare_1(self):
self.fairshare_delivery(priorities = [4,5,3,6,10,10,2,10,2,10,10,1,10,10,10,3,3,3,10,10,3,10,3,10,10,10,10,10,10,2,3])
- def test_fairshare_with_alias(self):
- self.fairshare_delivery(priorities = [4,5,3,6,10,10,2,10,2,10,10,1,10,10,10,3,3,3,10,10,2,3], level_key="qpid.priorities", fairshare_key="qpid.fairshare")
-
def test_fairshare_2(self):
self.fairshare_delivery(priorities = [10 for i in range(30)])
diff --git a/tests/src/py/qpid_tests/broker_0_10/threshold.py b/tests/src/py/qpid_tests/broker_0_10/threshold.py
index 6628ae8424..bcd3c507e2 100644
--- a/tests/src/py/qpid_tests/broker_0_10/threshold.py
+++ b/tests/src/py/qpid_tests/broker_0_10/threshold.py
@@ -60,18 +60,3 @@ class ThresholdTests (Base):
def test_alert_size_alias(self):
self.do_threshold_test("x-qpid-maximum-message-size", 15, [Message("msg-%s" % i) for i in range(3)])
-
- def test_alert_on_alert_queue(self):
- rcv = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdExceeded.#; {link:{x-declare:{arguments:{'qpid.alert_count':1}}}}")
- rcvQMFv1 = self.ssn.receiver("qpid.management/console.event.#; {link:{x-declare:{arguments:{'qpid.alert_count':1}}}}")
- snd = self.ssn.sender("ttq; {create:always, node: {x-declare:{auto_delete:True,exclusive:True,arguments:{'qpid.alert_count':1}}}}")
- snd.send(Message("my-message"))
- queues = []
- for i in range(2):
- event = rcv.fetch()
- schema = event.content[0]["_schema_id"]
- assert schema["_class_name"] == "queueThresholdExceeded"
- values = event.content[0]["_values"]
- queues.append(values["qName"])
- assert "ttq" in queues, "expected event for ttq (%s)" % (queues)
-
diff --git a/tools/setup.py b/tools/setup.py
index 4231476c90..8811e49682 100755
--- a/tools/setup.py
+++ b/tools/setup.py
@@ -20,7 +20,7 @@
from distutils.core import setup
setup(name="qpid-tools",
- version="0.13",
+ version="0.9",
author="Apache Qpid",
author_email="dev@qpid.apache.org",
scripts=["src/py/qpid-cluster",
@@ -30,8 +30,7 @@ setup(name="qpid-tools",
"src/py/qpid-queue-stats",
"src/py/qpid-route",
"src/py/qpid-stat",
- "src/py/qpid-tool",
- "src/py/qmf-tool"],
+ "src/py/qpid-tool"],
url="http://qpid.apache.org/",
license="Apache Software License",
description="Diagnostic and management tools for Apache Qpid brokers.")
diff --git a/tools/src/py/qmf-tool b/tools/src/py/qmf-tool
index 894dc9cc7d..e366d04709 100755
--- a/tools/src/py/qmf-tool
+++ b/tools/src/py/qmf-tool
@@ -31,100 +31,6 @@ from qpid.disp import Display
import cqpid
import qmf2
-class OptsAndArgs(object):
-
- def __init__(self, argv):
- self.argv = argv
- self.usage = """qmf-tool [OPTIONS] [<broker-host>[:<port>]]"""
- self.option_parser = optparse.OptionParser(usage=self.usage)
- self.conn_group = optparse.OptionGroup(self.option_parser, "Connection Options")
- self.conn_group.add_option("-u", "--user", action="store", type="string", help="User name for authentication")
- self.conn_group.add_option("-p", "--password", action="store", type="string", help="Password for authentication")
- self.conn_group.add_option("-t", "--transport", action="store", type="string", help="Transport type (tcp, ssl, rdma)")
- self.conn_group.add_option("-m", "--mechanism", action="store", type="string", help="SASL Mechanism for security")
- self.conn_group.add_option("-s", "--service", action="store", type="string", default="qpidd", help="SASL Service name")
- self.conn_group.add_option("--min-ssf", action="store", type="int", metavar="<n>", help="Minimum acceptable security strength factor")
- self.conn_group.add_option("--max-ssf", action="store", type="int", metavar="<n>", help="Maximum acceptable security strength factor")
- self.conn_group.add_option("--conn-option", action="append", default=[], metavar="<NAME=VALUE>", help="Additional connection option(s)")
- self.option_parser.add_option_group(self.conn_group)
-
- self.qmf_group = optparse.OptionGroup(self.option_parser, "QMF Session Options")
- self.qmf_group.add_option("--domain", action="store", type="string", help="QMF Domain")
- self.qmf_group.add_option("--agent-age", action="store", type="int", metavar="<n>", help="Time, in minutes, to age out non-communicating agents")
- self.qmf_group.add_option("--qmf-option", action="append", default=[], metavar="<NAME=VALUE>", help="Additional QMF session option(s)")
- self.option_parser.add_option_group(self.qmf_group)
-
- def parse(self):
- host = "localhost"
- conn_options = []
- qmf_options = []
-
- options, encArgs = self.option_parser.parse_args(args=self.argv)
- try:
- encoding = locale.getpreferredencoding()
- args = [a.decode(encoding) for a in encArgs]
- except:
- args = encArgs
-
- if len(args) > 1:
- host = args[1]
-
- if options.user:
- conn_options.append("username:'%s'" % options.user)
- if options.password:
- conn_options.append("password:'%s'" % options.password)
- if options.transport:
- conn_options.append("transport:'%s'" % options.transport)
- if options.mechanism:
- conn_options.append("sasl_mechanisms:'%s'" % options.mechanism)
- if options.service:
- conn_options.append("sasl_service:'%s'" % options.service)
- if options.min_ssf:
- conn_options.append("sasl_min_ssf:%d" % options.min_ssf)
- if options.max_ssf:
- conn_options.append("sasl_max_ssf:%d" % options.max_ssf)
- for x in options.conn_option:
- try:
- key, val = x.split('=')
- conn_options.append("%s:%s" % (key, val))
- except:
- raise Exception("Improperly formatted text for --conn-option: '%s'" % x)
-
- if options.domain:
- qmf_options.append("domain:'%s'" % options.domain)
- if options.agent_age:
- qmf_options.append("max-agent-age:%d" % options.agent_age)
- for x in options.qmf_option:
- try:
- key, val = x.split('=')
- qmf_options.append("%s:%s" % (key, val))
- except:
- raise Exception("Improperly formatted text for --qmf-option: '%s'" % x)
-
- conn_string = '{'
- first = True
- for x in conn_options:
- if first:
- first = None
- else:
- conn_string += ','
- conn_string += x
- conn_string += '}'
-
- qmf_string = '{'
- first = True
- for x in qmf_options:
- if first:
- first = None
- else:
- qmf_string += ','
- qmf_string += x
- qmf_string += '}'
-
- return host, conn_string, qmf_string
-
-
-
class Mcli(Cmd):
""" Management Command Interpreter """
@@ -149,11 +55,10 @@ class Mcli(Cmd):
print
print "Agent Commands:"
print " set filter <filter-string> - Filter the list of agents"
- print " list agents - Print a list of the known Agents"
- print " set default <item-number> - Set the default agent for operations"
print " show filter - Show the agent filter currently in effect"
+ print " list agents - Print a list of the known Agents"
print " show agent <item-number> - Print detailed information about an Agent"
- print " show options - Show option strings used in the QMF session"
+ print " set default <item-number> - Set the default agent for operations"
print
print "Schema Commands:"
print " list packages - Print a list of packages supported by the default agent"
@@ -207,7 +112,7 @@ class Mcli(Cmd):
def complete_show(self, text, line, begidx, endidx):
tokens = split(line[:begidx])
if len(tokens) == 1:
- return [i for i in ('options', 'filter', 'agent ', 'class ') if i.startswith(text)]
+ return [i for i in ('filter', 'agent ', 'class ') if i.startswith(text)]
return []
def do_show(self, data):
@@ -270,15 +175,13 @@ class Mcli(Cmd):
class QmfData:
"""
"""
- def __init__(self, disp, url, conn_options, qmf_options):
+ def __init__(self, disp, url):
self.disp = disp
self.url = url
- self.conn_options = conn_options
- self.qmf_options = qmf_options
self.agent_filter = '[]'
- self.connection = cqpid.Connection(self.url, self.conn_options)
+ self.connection = cqpid.Connection(self.url)
self.connection.open()
- self.session = qmf2.ConsoleSession(self.connection, self.qmf_options)
+ self.session = qmf2.ConsoleSession(self.connection)
self.session.setAgentFilter(self.agent_filter)
self.session.open()
self.lock = Lock()
@@ -336,12 +239,6 @@ class QmfData:
print "What do you want to show? Type 'help' for more information."
return
- if tokens[0] == 'options':
- print "Options used in this session:"
- print " Connection Options : %s" % self.scrubConnOptions()
- print " QMF Session Options: %s" % self.qmf_options
- return
-
if tokens[0] == 'agent':
self.showAgent(tokens[1:])
return
@@ -739,33 +636,32 @@ class QmfData:
first = None
return result
- def scrubConnOptions(self):
- pw = self.conn_options.find('password:')
- if pw < 0:
- return self.conn_options
- scrubbed = self.conn_options[:pw + 9] + "***"
- delim = self.conn_options[pw:].find(',')
- if delim < 0:
- delim = self.conn_options[pw:].find('}')
- scrubbed += self.conn_options[pw + delim:]
- return scrubbed
-
+def Usage():
+ print "Usage: qpid-tool [[<username>/<password>@]<target-host>[:<tcp-port>]]"
+ print
#=========================================================
# Main Program
#=========================================================
-try:
- oa = OptsAndArgs(sys.argv)
- host, conn_options, qmf_options = oa.parse()
-except Exception, e:
- print "Parse Error: %s" % e
+
+# Get host name and port if specified on the command line
+cargs = sys.argv[1:]
+_host = "localhost"
+
+if len(cargs) > 0:
+ _host = cargs[0]
+
+if _host[0] == '-':
+ Usage()
+ if _host != '-h' and _host != "--help":
+ print "qpid-tool: error: no such option:", _host
sys.exit(1)
disp = Display()
# Attempt to make a connection to the target broker
try:
- data = QmfData(disp, host, conn_options, qmf_options)
+ data = QmfData(disp, _host)
except Exception, e:
if str(e).find("Exchange not found") != -1:
print "Management not enabled on broker: Use '-m yes' option on broker startup."
diff --git a/tools/src/py/qpid-cluster b/tools/src/py/qpid-cluster
index d4f9391dcf..312d59f670 100755
--- a/tools/src/py/qpid-cluster
+++ b/tools/src/py/qpid-cluster
@@ -247,7 +247,7 @@ def main(argv=None):
parser.add_option("-k", "--all-stop", action="store_true", default=False, help="Shut down the whole cluster")
parser.add_option("-f", "--force", action="store_true", default=False, help="Suppress the 'are you sure' prompt")
parser.add_option("-n", "--numeric", action="store_true", default=False, help="Don't resolve names")
-
+
opts, args = parser.parse_args(args=argv)
if args:
@@ -268,12 +268,12 @@ def main(argv=None):
if opts.del_connection:
config._delConn = opts.del_connection
- if len(config._delConn.split(":")) != 2:
+ if len(config._delConn.split(":")) != 2:
parser.error("Member ID must be of form: <host or ip>:<number>")
if opts.stop:
- config._stopId = opts.stop
- if len(config._stopId.split(":")) != 2:
+ config._stopID = opts.stop
+ if len(config._stopId.split(":")) != 2:
parser.error("Member ID must be of form: <host or ip>:<number>")
config._stopAll = opts.all_stop
@@ -303,7 +303,6 @@ def main(argv=None):
bm.Disconnect()
except Exception, e:
- raise
print str(e)
return 1
diff --git a/tools/src/py/qpid-config b/tools/src/py/qpid-config
index bb49b9d7c9..04b31e98ed 100755
--- a/tools/src/py/qpid-config
+++ b/tools/src/py/qpid-config
@@ -39,12 +39,17 @@ Usage: qpid-config [OPTIONS]
qpid-config [OPTIONS] unbind <exchange-name> <queue-name> [binding-key]"""
description = """
+ADDRESS syntax:
+
+ [username/password@] hostname
+ ip-address [:<port>]
+
Examples:
$ qpid-config add queue q
-$ qpid-config add exchange direct d -a localhost:5672
-$ qpid-config exchanges -a 10.1.1.7:10000
-$ qpid-config queues -a guest/guest@broker-host:10000
+$ qpid-config add exchange direct d localhost:5672
+$ qpid-config exchanges 10.1.1.7:10000
+$ qpid-config queues guest/guest@broker-host:10000
Add Exchange <type> values:
@@ -75,7 +80,6 @@ class Config:
self._recursive = False
self._host = "localhost"
self._connTimeout = 10
- self._ignoreDefault = False
self._altern_ex = None
self._passive = False
self._durable = False
@@ -93,14 +97,6 @@ class Config:
self._eventGeneration = None
self._file = None
self._sasl_mechanism = None
- self._flowStopCount = None
- self._flowResumeCount = None
- self._flowStopSize = None
- self._flowResumeSize = None
- self._msgGroupHeader = None
- self._sharedMsgGroup = False
- self._extra_arguments = []
- self._returnCode = 0
config = Config()
@@ -115,20 +111,6 @@ LVQNB = "qpid.last_value_queue_no_browse"
MSG_SEQUENCE = "qpid.msg_sequence"
IVE = "qpid.ive"
QUEUE_EVENT_GENERATION = "qpid.queue_event_generation"
-FLOW_STOP_COUNT = "qpid.flow_stop_count"
-FLOW_RESUME_COUNT = "qpid.flow_resume_count"
-FLOW_STOP_SIZE = "qpid.flow_stop_size"
-FLOW_RESUME_SIZE = "qpid.flow_resume_size"
-MSG_GROUP_HDR_KEY = "qpid.group_header_key"
-SHARED_MSG_GROUP = "qpid.shared_msg_group"
-#There are various arguments to declare that have specific program
-#options in this utility. However there is now a generic mechanism for
-#passing arguments as well. The SPECIAL_ARGS list contains the
-#arguments for which there are specific program options defined
-#i.e. the arguments for which there is special processing on add and
-#list
-SPECIAL_ARGS=[FILECOUNT,FILESIZE,MAX_QUEUE_SIZE,MAX_QUEUE_COUNT,POLICY_TYPE,CLUSTER_DURABLE,LVQ,LVQNB,MSG_SEQUENCE,IVE,QUEUE_EVENT_GENERATION,FLOW_STOP_COUNT,FLOW_STOP_SIZE,FLOW_RESUME_SIZE,
- MSG_GROUP_HDR_KEY,SHARED_MSG_GROUP]
class JHelpFormatter(IndentedHelpFormatter):
"""Format usage and description without stripping newlines from usage strings
@@ -161,14 +143,10 @@ def OptionsAndArguments(argv):
group1 = OptionGroup(parser, "General Options")
group1.add_option("-t", "--timeout", action="store", type="int", default=10, metavar="<secs>", help="Maximum time to wait for broker connection (in seconds)")
group1.add_option("-b", "--bindings", action="store_true", help="Show bindings in queue or exchange list")
- group1.add_option("-a", "--broker-addr", action="store", type="string", default="localhost:5672", metavar="<address>", help="Address of qpidd broker with syntax: [username/password@] hostname | ip-address [:<port>]")
+ group1.add_option("-a", "--broker-addr", action="store", type="string", default="localhost:5672", metavar="<address>", help="Maximum time to wait for broker connection (in seconds)")
group1.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). SASL automatically picks the most secure available mechanism - use this option to override.")
parser.add_option_group(group1)
- group_ls = OptionGroup(parser, "Options for Listing Exchanges and Queues")
- group_ls.add_option("--ignore-default", action="store_true", help="Ignore the default exchange in exchange or queue list")
- parser.add_option_group(group_ls)
-
group2 = OptionGroup(parser, "Options for Adding Exchanges and Queues")
group2.add_option("--alternate-exchange", action="store", type="string", metavar="<aexname>", help="Name of the alternate-exchange for the new queue or exchange. Exchanges route messages to the alternate exchange if they are unable to route them elsewhere. Queues route messages to the alternate exchange if they are rejected by a subscriber or orphaned by queue deletion.")
group2.add_option("--passive", "--dry-run", action="store_true", help="Do not actually add the exchange or queue, ensure that all parameters and permissions are correct and would allow it to be created.")
@@ -178,26 +156,12 @@ def OptionsAndArguments(argv):
group3 = OptionGroup(parser, "Options for Adding Queues")
group3.add_option("--cluster-durable", action="store_true", help="The new queue becomes durable if there is only one functioning cluster node")
group3.add_option("--file-count", action="store", type="int", default=8, metavar="<n>", help="Number of files in queue's persistence journal")
- group3.add_option("--file-size", action="store", type="int", default=24, metavar="<n>", help="File size in pages (64KiB/page)")
- group3.add_option("--max-queue-size", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as bytes")
- group3.add_option("--max-queue-count", action="store", type="int", metavar="<n>", help="Maximum in-memory queue size as a number of messages")
+ group3.add_option("--file-size", action="store", type="int", default=24, metavar="<n>", help="File size in pages (64Kib/page)")
+ group3.add_option("--max-queue-size", action="store", type="int", metavar="<n>", help="Number of files in queue's persistence journal")
+ group3.add_option("--max-queue-count", action="store", type="int", metavar="<n>", help="Number of files in queue's persistence journal")
group3.add_option("--limit-policy", action="store", choices=["none", "reject", "flow-to-disk", "ring", "ring-strict"], metavar="<policy>", help="Action to take when queue limit is reached")
group3.add_option("--order", action="store", choices=["fifo", "lvq", "lvq-no-browse"], metavar="<ordering>", help="Queue ordering policy")
group3.add_option("--generate-queue-events", action="store", type="int", metavar="<n>", help="If set to 1, every enqueue will generate an event that can be processed by registered listeners (e.g. for replication). If set to 2, events will be generated for enqueues and dequeues.")
- group3.add_option("--flow-stop-size", action="store", type="int", metavar="<n>",
- help="Turn on sender flow control when the number of queued bytes exceeds this value.")
- group3.add_option("--flow-resume-size", action="store", type="int", metavar="<n>",
- help="Turn off sender flow control when the number of queued bytes drops below this value.")
- group3.add_option("--flow-stop-count", action="store", type="int", metavar="<n>",
- help="Turn on sender flow control when the number of queued messages exceeds this value.")
- group3.add_option("--flow-resume-count", action="store", type="int", metavar="<n>",
- help="Turn off sender flow control when the number of queued messages drops below this value.")
- group3.add_option("--group-header", action="store", type="string", metavar="<header-name>",
- help="Enable message groups. Specify name of header that holds group identifier.")
- group3.add_option("--shared-groups", action="store_true",
- help="Allow message group consumption across multiple consumers.")
- group3.add_option("--argument", dest="extra_arguments", action="append", default=[],
- metavar="<NAME=VALUE>", help="Specify a key-value pair to add to queue arguments")
# no option for declaring an exclusive queue - which can only be used by the session that creates it.
parser.add_option_group(group3)
@@ -209,7 +173,7 @@ def OptionsAndArguments(argv):
group5 = OptionGroup(parser, "Options for Deleting Queues")
group5.add_option("--force", action="store_true", help="Force delete of queue even if it's currently used or it's not empty")
group5.add_option("--force-if-not-empty", action="store_true", help="Force delete of queue even if it's not empty")
- group5.add_option("--force-if-used", action="store_true", help="Force delete of queue even if it's currently used")
+ group5.add_option("--force-if-not-used", action="store_true", help="Force delete of queue even if it's currently used")
parser.add_option_group(group5)
group6 = OptionGroup(parser, "Options for Declaring Bindings")
@@ -232,8 +196,6 @@ def OptionsAndArguments(argv):
config._connTimeout = opts.timeout
if config._connTimeout == 0:
config._connTimeout = None
- if opts.ignore_default:
- config._ignoreDefault = True
if opts.alternate_exchange:
config._altern_ex = opts.alternate_exchange
if opts.passive:
@@ -248,7 +210,7 @@ def OptionsAndArguments(argv):
config._fileCount = opts.file_count
if opts.file_size:
config._fileSize = opts.file_size
- if opts.max_queue_size != None:
+ if opts.max_queue_size:
config._maxQueueSize = opts.max_queue_size
if opts.max_queue_count:
config._maxQueueCount = opts.max_queue_count
@@ -267,24 +229,10 @@ def OptionsAndArguments(argv):
config._if_unused = False
if opts.force_if_not_empty:
config._if_empty = False
- if opts.force_if_used:
+ if opts.force_if_not_used:
config._if_unused = False
if opts.sasl_mechanism:
config._sasl_mechanism = opts.sasl_mechanism
- if opts.flow_stop_size:
- config._flowStopSize = opts.flow_stop_size
- if opts.flow_resume_size:
- config._flowResumeSize = opts.flow_resume_size
- if opts.flow_stop_count:
- config._flowStopCount = opts.flow_stop_count
- if opts.flow_resume_count:
- config._flowResumeCount = opts.flow_resume_count
- if opts.group_header:
- config._msgGroupHeader = opts.group_header
- if opts.shared_groups:
- config._sharedMsgGroup = True
- if opts.extra_arguments:
- config._extra_arguments = opts.extra_arguments
return args
@@ -375,16 +323,9 @@ class BrokerManager:
caption1 = "Type "
caption2 = "Exchange Name"
maxNameLen = len(caption2)
- found = False
for ex in exchanges:
if self.match(ex.name, filter):
if len(ex.name) > maxNameLen: maxNameLen = len(ex.name)
- found = True
- if not found:
- global config
- config._returnCode = 1
- return
-
print "%s%-*s Attributes" % (caption1, maxNameLen, caption2)
line = ""
for i in range(((maxNameLen + len(caption1)) / 5) + 5):
@@ -392,11 +333,9 @@ class BrokerManager:
print line
for ex in exchanges:
- if config._ignoreDefault and not ex.name: continue
if self.match(ex.name, filter):
print "%-10s%-*s " % (ex.type, maxNameLen, ex.name),
args = ex.arguments
- if not args: args = {}
if ex.durable: print "--durable",
if MSG_SEQUENCE in args and args[MSG_SEQUENCE] == 1: print "--sequence",
if IVE in args and args[IVE] == 1: print "--ive",
@@ -409,7 +348,6 @@ class BrokerManager:
bindings = self.qmf.getObjects(_class="binding", _agent=self.brokerAgent)
queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
for ex in exchanges:
- if config._ignoreDefault and not ex.name: continue
if self.match(ex.name, filter):
print "Exchange '%s' (%s)" % (ex.name, ex.type)
for bind in bindings:
@@ -423,18 +361,12 @@ class BrokerManager:
def QueueList(self, filter):
queues = self.qmf.getObjects(_class="queue", _agent=self.brokerAgent)
+
caption = "Queue Name"
maxNameLen = len(caption)
- found = False
for q in queues:
if self.match(q.name, filter):
if len(q.name) > maxNameLen: maxNameLen = len(q.name)
- found = True
- if not found:
- global config
- config._returnCode = 1
- return
-
print "%-*s Attributes" % (maxNameLen, caption)
line = ""
for i in range((maxNameLen / 5) + 5):
@@ -445,28 +377,21 @@ class BrokerManager:
if self.match(q.name, filter):
print "%-*s " % (maxNameLen, q.name),
args = q.arguments
- if not args: args = {}
if q.durable: print "--durable",
if CLUSTER_DURABLE in args and args[CLUSTER_DURABLE] == 1: print "--cluster-durable",
if q.autoDelete: print "auto-del",
if q.exclusive: print "excl",
- if FILESIZE in args: print "--file-size=%s" % args[FILESIZE],
- if FILECOUNT in args: print "--file-count=%s" % args[FILECOUNT],
- if MAX_QUEUE_SIZE in args: print "--max-queue-size=%s" % args[MAX_QUEUE_SIZE],
- if MAX_QUEUE_COUNT in args: print "--max-queue-count=%s" % args[MAX_QUEUE_COUNT],
+ if FILESIZE in args: print "--file-size=%d" % args[FILESIZE],
+ if FILECOUNT in args: print "--file-count=%d" % args[FILECOUNT],
+ if MAX_QUEUE_SIZE in args: print "--max-queue-size=%d" % args[MAX_QUEUE_SIZE],
+ if MAX_QUEUE_COUNT in args: print "--max-queue-count=%d" % args[MAX_QUEUE_COUNT],
if POLICY_TYPE in args: print "--limit-policy=%s" % args[POLICY_TYPE].replace("_", "-"),
if LVQ in args and args[LVQ] == 1: print "--order lvq",
if LVQNB in args and args[LVQNB] == 1: print "--order lvq-no-browse",
- if QUEUE_EVENT_GENERATION in args: print "--generate-queue-events=%s" % args[QUEUE_EVENT_GENERATION],
+ if QUEUE_EVENT_GENERATION in args: print "--generate-queue-events=%d" % args[QUEUE_EVENT_GENERATION],
if q.altExchange:
print "--alternate-exchange=%s" % q._altExchange_.name,
- if FLOW_STOP_SIZE in args: print "--flow-stop-size=%s" % args[FLOW_STOP_SIZE],
- if FLOW_RESUME_SIZE in args: print "--flow-resume-size=%s" % args[FLOW_RESUME_SIZE],
- if FLOW_STOP_COUNT in args: print "--flow-stop-count=%s" % args[FLOW_STOP_COUNT],
- if FLOW_RESUME_COUNT in args: print "--flow-resume-count=%s" % args[FLOW_RESUME_COUNT],
- if MSG_GROUP_HDR_KEY in args: print "--group-header=%s" % args[MSG_GROUP_HDR_KEY],
- if SHARED_MSG_GROUP in args and args[SHARED_MSG_GROUP] == 1: print "--shared-groups",
- print " ".join(["--argument %s=%s" % (k, v) for k,v in args.iteritems() if not k in SPECIAL_ARGS])
+ print
def QueueListRecurse(self, filter):
exchanges = self.qmf.getObjects(_class="exchange", _agent=self.brokerAgent)
@@ -482,7 +407,6 @@ class BrokerManager:
if ex != None:
ename = ex.name
if ename == "":
- if config._ignoreDefault: continue
ename = "''"
print " bind [%s] => %s" % (bind.bindingKey, ename)
@@ -512,17 +436,11 @@ class BrokerManager:
Usage()
qname = args[0]
declArgs = {}
- for a in config._extra_arguments:
- r = a.split("=", 1)
- if len(r) == 2: value = r[1]
- else: value = None
- declArgs[r[0]] = value
-
if config._durable:
declArgs[FILECOUNT] = config._fileCount
declArgs[FILESIZE] = config._fileSize
- if config._maxQueueSize != None:
+ if config._maxQueueSize:
declArgs[MAX_QUEUE_SIZE] = config._maxQueueSize
if config._maxQueueCount:
declArgs[MAX_QUEUE_COUNT] = config._maxQueueCount
@@ -550,26 +468,11 @@ class BrokerManager:
if config._eventGeneration:
declArgs[QUEUE_EVENT_GENERATION] = config._eventGeneration
- if config._flowStopSize:
- declArgs[FLOW_STOP_SIZE] = config._flowStopSize
- if config._flowResumeSize:
- declArgs[FLOW_RESUME_SIZE] = config._flowResumeSize
- if config._flowStopCount:
- declArgs[FLOW_STOP_COUNT] = config._flowStopCount
- if config._flowResumeCount:
- declArgs[FLOW_RESUME_COUNT] = config._flowResumeCount
-
- if config._msgGroupHeader:
- declArgs[MSG_GROUP_HDR_KEY] = config._msgGroupHeader
- if config._sharedMsgGroup:
- declArgs[SHARED_MSG_GROUP] = 1
-
if config._altern_ex != None:
self.broker.getAmqpSession().queue_declare(queue=qname, alternate_exchange=config._altern_ex, passive=config._passive, durable=config._durable, arguments=declArgs)
else:
self.broker.getAmqpSession().queue_declare(queue=qname, passive=config._passive, durable=config._durable, arguments=declArgs)
-
def DelQueue(self, args):
if len(args) < 1:
Usage()
@@ -714,7 +617,7 @@ def main(argv=None):
print "Failed: %s: %s" % (e.__class__.__name__, e)
return 1
- return config._returnCode
+ return 0
if __name__ == "__main__":
sys.exit(main())
diff --git a/tools/src/py/qpid-printevents b/tools/src/py/qpid-printevents
index d56d2899b1..2be2f0be8b 100755
--- a/tools/src/py/qpid-printevents
+++ b/tools/src/py/qpid-printevents
@@ -20,7 +20,7 @@
#
import os
-import optparse
+import optparse
from optparse import IndentedHelpFormatter
import sys
import socket
@@ -62,11 +62,11 @@ _usage = "%prog [options] [broker-addr]..."
_description = \
"""
-Collect and print events from one or more Qpid message brokers.
+Collect and print events from one or more Qpid message brokers.
If no broker-addr is supplied, %prog connects to 'localhost:5672'.
-[broker-addr] syntax:
+[broker-addr] syntax:
[username/password@] hostname
ip-address [:<port>]
@@ -91,20 +91,20 @@ def main(argv=None):
session = Session(console, rcvObjects=False, rcvHeartbeats=options.heartbeats, manageConnections=True)
brokers = []
try:
- try:
- for host in arguments:
- brokers.append(session.addBroker(host, None, options.sasl_mechanism))
+ for host in arguments:
+ brokers.append(session.addBroker(host, None, options.sasl_mechanism))
- while (True):
- sleep(10)
+ while (True):
+ sleep(10)
- except KeyboardInterrupt:
- print
- return 0
+ except KeyboardInterrupt:
+ print
+ return 0
+
+ except Exception, e:
+ print "Failed: %s - %s" % (e.__class__.__name__, e)
+ return 1
- except Exception, e:
- print "Failed: %s - %s" % (e.__class__.__name__, e)
- return 1
finally:
while len(brokers):
b = brokers.pop()
diff --git a/tools/src/py/qpid-route b/tools/src/py/qpid-route
index f90416d7b0..3c4de85d1e 100755
--- a/tools/src/py/qpid-route
+++ b/tools/src/py/qpid-route
@@ -27,18 +27,18 @@ import locale
from qmf.console import Session, BrokerURL
usage = """
-Usage: qpid-route [OPTIONS] dynamic add <dest-broker> <src-broker> <exchange> [tag] [exclude-list] [mechanism]
+Usage: qpid-route [OPTIONS] dynamic add <dest-broker> <src-broker> <exchange> [tag] [exclude-list]
qpid-route [OPTIONS] dynamic del <dest-broker> <src-broker> <exchange>
qpid-route [OPTIONS] route add <dest-broker> <src-broker> <exchange> <routing-key> [tag] [exclude-list] [mechanism]
qpid-route [OPTIONS] route del <dest-broker> <src-broker> <exchange> <routing-key>
- qpid-route [OPTIONS] queue add <dest-broker> <src-broker> <exchange> <queue> [mechanism]
+ qpid-route [OPTIONS] queue add <dest-broker> <src-broker> <exchange> <queue>
qpid-route [OPTIONS] queue del <dest-broker> <src-broker> <exchange> <queue>
qpid-route [OPTIONS] route list [<dest-broker>]
qpid-route [OPTIONS] route flush [<dest-broker>]
qpid-route [OPTIONS] route map [<broker>]
- qpid-route [OPTIONS] link add <dest-broker> <src-broker> [mechanism]
+ qpid-route [OPTIONS] link add <dest-broker> <src-broker>
qpid-route [OPTIONS] link del <dest-broker> <src-broker>
qpid-route [OPTIONS] link list [<dest-broker>]"""
@@ -61,7 +61,7 @@ class Config:
self._transport = "tcp"
self._ack = 0
self._connTimeout = 10
- self._client_sasl_mechanism = None
+ self._sasl_mechanism = None
config = Config()
@@ -95,7 +95,7 @@ def OptionsAndArguments(argv):
parser.add_option("--ack", action="store", type="int", metavar="<n>", help="Acknowledge transfers over the bridge in batches of N")
parser.add_option("-t", "--transport", action="store", type="string", default="tcp", metavar="<transport>", help="Transport to use for links, defaults to tcp")
- parser.add_option("--client-sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). Used when the client connects to the destination broker (not for authentication between the source and destination brokers - that is specified using the [mechanisms] argument to 'add route'). SASL automatically picks the most secure available mechanism - use this option to override.")
+ parser.add_option("--sasl-mechanism", action="store", type="string", metavar="<mech>", help="SASL mechanism for authentication (e.g. EXTERNAL, ANONYMOUS, PLAIN, CRAM-MD, DIGEST-MD5, GSSAPI). Used when the client connects to the destination broker (not for authentication between the source and destination brokers - that is specified using the [mechanisms] argument to 'add route'). SASL automatically picks the most secure available mechanism - use this option to override.")
opts, encArgs = parser.parse_args(args=argv)
@@ -131,8 +131,8 @@ def OptionsAndArguments(argv):
if opts.ack:
config._ack = opts.ack
- if opts.client_sasl_mechanism:
- config._client_sasl_mechanism = opts.client_sasl_mechanism
+ if opts.sasl_mechanism:
+ config._sasl_mechanism = opts.sasl_mechanism
return args
@@ -143,7 +143,7 @@ class RouteManager:
self.local = BrokerURL(localBroker)
self.remote = None
self.qmf = Session()
- self.broker = self.qmf.addBroker(localBroker, config._connTimeout, config._client_sasl_mechanism)
+ self.broker = self.qmf.addBroker(localBroker, config._connTimeout, config._sasl_mechanism)
self.broker._waitForStable()
self.agent = self.broker.getBrokerAgent()
@@ -166,7 +166,7 @@ class RouteManager:
return link
return None
- def addLink(self, remoteBroker, interbroker_mechanism=""):
+ def addLink(self, remoteBroker, mech="PLAIN"):
self.remote = BrokerURL(remoteBroker)
if self.local.match(self.remote.host, self.remote.port):
raise Exception("Linking broker to itself is not permitted")
@@ -176,7 +176,7 @@ class RouteManager:
link = self.getLink()
if link == None:
res = broker.connect(self.remote.host, self.remote.port, config._durable,
- interbroker_mechanism, self.remote.authName or "", self.remote.authPass or "",
+ mech, self.remote.authName or "", self.remote.authPass or "",
config._transport)
if config._verbose:
print "Connect method returned:", res.status, res.text
@@ -217,11 +217,11 @@ class RouteManager:
added = False
links = self.qmf.getObjects(_class="link")
for link in links:
- url = BrokerURL(host=link.host, port=link.port)
+ url = BrokerURL("%s:%d" % (link.host, link.port))
if url.name() not in self.brokerList:
print " %s..." % url.name(),
try:
- b = self.qmf.addBroker(url, config._connTimeout)
+ b = self.qmf.addBroker("%s:%d" % (link.host, link.port), config._connTimeout)
self.brokerList[url.name()] = b
added = True
print "Ok"
@@ -245,7 +245,7 @@ class RouteManager:
for bridge in bridges:
if bridge.src == ex:
link = bridge._linkRef_
- fromUrl = BrokerURL(host=link.host, port=link.port)
+ fromUrl = "%s:%s" % (link.host, link.port)
toUrl = bridge.getBroker().getUrl()
found = False
for pair in pairs:
@@ -295,11 +295,11 @@ class RouteManager:
if b[0] != self.local.name():
self.qmf.delBroker(b[1])
- def addRoute(self, remoteBroker, exchange, routingKey, tag, excludes, interbroker_mechanism="", dynamic=False):
+ def addRoute(self, remoteBroker, exchange, routingKey, tag, excludes, mech="PLAIN", dynamic=False):
if dynamic and config._srclocal:
raise Exception("--src-local is not permitted on dynamic routes")
- self.addLink(remoteBroker, interbroker_mechanism)
+ self.addLink(remoteBroker, mech)
link = self.getLink()
if link == None:
raise Exception("Link failed to create")
@@ -320,8 +320,8 @@ class RouteManager:
if config._verbose:
print "Bridge method returned:", res.status, res.text
- def addQueueRoute(self, remoteBroker, interbroker_mechanism, exchange, queue ):
- self.addLink(remoteBroker, interbroker_mechanism)
+ def addQueueRoute(self, remoteBroker, exchange, queue):
+ self.addLink(remoteBroker)
link = self.getLink()
if link == None:
raise Exception("Link failed to create")
@@ -504,12 +504,10 @@ def main(argv=None):
rm = RouteManager(localBroker)
if group == "link":
if cmd == "add":
- if nargs < 3 or nargs > 5:
+ if nargs != 4:
Usage()
return(-1)
- interbroker_mechanism = ""
- if nargs > 4: interbroker_mechanism = args[4]
- rm.addLink(remoteBroker, interbroker_mechanism)
+ rm.addLink(remoteBroker)
elif cmd == "del":
if nargs != 4:
Usage()
@@ -520,17 +518,16 @@ def main(argv=None):
elif group == "dynamic":
if cmd == "add":
- if nargs < 5 or nargs > 8:
+ if nargs < 5 or nargs > 7:
Usage()
return(-1)
tag = ""
excludes = ""
- interbroker_mechanism = ""
+ mech = "PLAIN"
if nargs > 5: tag = args[5]
if nargs > 6: excludes = args[6]
- if nargs > 7: interbroker_mechanism = args[7]
- rm.addRoute(remoteBroker, args[4], "", tag, excludes, interbroker_mechanism, dynamic=True)
+ rm.addRoute(remoteBroker, args[4], "", tag, excludes, mech, dynamic=True)
elif cmd == "del":
if nargs != 5:
Usage()
@@ -546,11 +543,11 @@ def main(argv=None):
tag = ""
excludes = ""
- interbroker_mechanism = ""
+ mech = "PLAIN"
if nargs > 6: tag = args[6]
if nargs > 7: excludes = args[7]
- if nargs > 8: interbroker_mechanism = args[8]
- rm.addRoute(remoteBroker, args[4], args[5], tag, excludes, interbroker_mechanism, dynamic=False)
+ if nargs > 8: mech = args[8]
+ rm.addRoute(remoteBroker, args[4], args[5], tag, excludes, mech, dynamic=False)
elif cmd == "del":
if nargs != 6:
Usage()
@@ -568,21 +565,16 @@ def main(argv=None):
return(-1)
elif group == "queue":
- if nargs < 6 or nargs > 7:
+ if nargs != 6:
Usage()
return(-1)
if cmd == "add":
- interbroker_mechanism = ""
- if nargs > 6: interbroker_mechanism = args[6]
- rm.addQueueRoute(remoteBroker, interbroker_mechanism, exchange=args[4], queue=args[5] )
+ rm.addQueueRoute(remoteBroker, exchange=args[4], queue=args[5])
elif cmd == "del":
rm.delQueueRoute(remoteBroker, exchange=args[4], queue=args[5])
else:
Usage()
return(-1)
- else:
- Usage()
- return(-1)
except Exception,e:
if rm:
diff --git a/tools/src/py/qpid-tool b/tools/src/py/qpid-tool
index df8b7e3f96..d3b0aa4097 100755
--- a/tools/src/py/qpid-tool
+++ b/tools/src/py/qpid-tool
@@ -259,24 +259,7 @@ class QmfData(Console):
return
displayId = long(tokens[0])
methodName = tokens[1]
- args = []
- for arg in tokens[2:]:
- ##
- ## If the argument is a map, list, boolean, integer, or floating (one decimal point),
- ## run it through the Python evaluator so it is converted to the correct type.
- ##
- ## TODO: use a regex for this instead of this convoluted logic,
- ## or even consider passing all args through eval() [which would
- ## be a minor change to the interface as string args would then
- ## always need to be quoted as strings within a map/list would
- ## now]
- if arg[0] == '{' or arg[0] == '[' or arg[0] == '"' or arg[0] == '\'' or arg == "True" or arg == "False" or \
- ((arg.count('.') < 2 and (arg.count('-') == 0 or \
- (arg.count('-') == 1 and arg[0] == '-')) and \
- arg.replace('.','').replace('-','').isdigit())):
- args.append(eval(arg))
- else:
- args.append(arg)
+ args = tokens[2:]
obj = None
try:
@@ -350,7 +333,7 @@ class QmfData(Console):
self.notNone(prop.unit), notes, self.notNone(prop.desc))
rows.append(row)
for stat in schema.getStatistics():
- row = (stat.name, self.typeName(stat.type), "", self.notNone(stat.unit), "", self.notNone(stat.desc))
+ row = (stat.name, self.typeName(stat.type), "", self.notNone(prop.unit), "", self.notNone(prop.desc))
rows.append(row)
self.disp.table(title, heads, rows)